casebuilder: Validate JSON schema on load/save

feature/gui
Alinson S. Xavier 3 years ago
parent 3d03dfc722
commit 9112d9fde5

@ -5,11 +5,13 @@
"requires": true,
"packages": {
"": {
"name": "relog-web",
"version": "0.1.0",
"dependencies": {
"@testing-library/jest-dom": "^5.16.2",
"@testing-library/react": "^12.1.4",
"@testing-library/user-event": "^13.5.0",
"ajv": "^8.11.0",
"d3": "^7.3.0",
"dagre": "^0.8.5",
"idb": "^6.1.5",
@ -1992,6 +1994,21 @@
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
}
},
"node_modules/@eslint/eslintrc/node_modules/ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"dependencies": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
"json-schema-traverse": "^0.4.1",
"uri-js": "^4.2.2"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/epoberezkin"
}
},
"node_modules/@eslint/eslintrc/node_modules/argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
@ -2022,6 +2039,11 @@
"js-yaml": "bin/js-yaml.js"
}
},
"node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
},
"node_modules/@eslint/eslintrc/node_modules/type-fest": {
"version": "0.20.2",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
@ -4188,13 +4210,13 @@
}
},
"node_modules/ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"version": "8.11.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz",
"integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==",
"dependencies": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
"json-schema-traverse": "^0.4.1",
"json-schema-traverse": "^1.0.0",
"require-from-string": "^2.0.2",
"uri-js": "^4.2.2"
},
"funding": {
@ -4574,6 +4596,11 @@
"webpack": ">=2"
}
},
"node_modules/babel-loader/node_modules/json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
},
"node_modules/babel-loader/node_modules/json5": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
@ -4615,6 +4642,21 @@
"url": "https://opencollective.com/webpack"
}
},
"node_modules/babel-loader/node_modules/schema-utils/node_modules/ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"dependencies": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
"json-schema-traverse": "^0.4.1",
"uri-js": "^4.2.2"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/epoberezkin"
}
},
"node_modules/babel-plugin-dynamic-import-node": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz",
@ -7360,6 +7402,21 @@
"webpack": "^5.0.0"
}
},
"node_modules/eslint/node_modules/ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"dependencies": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
"json-schema-traverse": "^0.4.1",
"uri-js": "^4.2.2"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/epoberezkin"
}
},
"node_modules/eslint/node_modules/ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
@ -7454,6 +7511,11 @@
"js-yaml": "bin/js-yaml.js"
}
},
"node_modules/eslint/node_modules/json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
},
"node_modules/eslint/node_modules/supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
@ -8028,6 +8090,11 @@
"node": ">=8"
}
},
"node_modules/fork-ts-checker-webpack-plugin/node_modules/json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
},
"node_modules/fork-ts-checker-webpack-plugin/node_modules/schema-utils": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz",
@ -8045,6 +8112,21 @@
"url": "https://opencollective.com/webpack"
}
},
"node_modules/fork-ts-checker-webpack-plugin/node_modules/schema-utils/node_modules/ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"dependencies": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
"json-schema-traverse": "^0.4.1",
"uri-js": "^4.2.2"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/epoberezkin"
}
},
"node_modules/fork-ts-checker-webpack-plugin/node_modules/supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
@ -11031,9 +11113,9 @@
"integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA=="
},
"node_modules/json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="
},
"node_modules/json-stable-stringify-without-jsonify": {
"version": "1.0.1",
@ -14290,6 +14372,26 @@
"url": "https://opencollective.com/webpack"
}
},
"node_modules/schema-utils/node_modules/ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"dependencies": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
"json-schema-traverse": "^0.4.1",
"uri-js": "^4.2.2"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/epoberezkin"
}
},
"node_modules/schema-utils/node_modules/json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
},
"node_modules/select-hose": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
@ -15436,19 +15538,6 @@
"is-typedarray": "^1.0.0"
}
},
"node_modules/typescript": {
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.2.tgz",
"integrity": "sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg==",
"peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=4.2.0"
}
},
"node_modules/unbox-primitive": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz",
@ -17882,6 +17971,17 @@
"strip-json-comments": "^3.1.1"
},
"dependencies": {
"ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"requires": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
"json-schema-traverse": "^0.4.1",
"uri-js": "^4.2.2"
}
},
"argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
@ -17903,6 +18003,11 @@
"argparse": "^2.0.1"
}
},
"json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
},
"type-fest": {
"version": "0.20.2",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
@ -19511,13 +19616,13 @@
}
},
"ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"version": "8.11.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz",
"integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==",
"requires": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
"json-schema-traverse": "^0.4.1",
"json-schema-traverse": "^1.0.0",
"require-from-string": "^2.0.2",
"uri-js": "^4.2.2"
}
},
@ -19779,6 +19884,11 @@
"schema-utils": "^2.6.5"
},
"dependencies": {
"json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
},
"json5": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
@ -19805,6 +19915,19 @@
"@types/json-schema": "^7.0.5",
"ajv": "^6.12.4",
"ajv-keywords": "^3.5.2"
},
"dependencies": {
"ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"requires": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
"json-schema-traverse": "^0.4.1",
"uri-js": "^4.2.2"
}
}
}
}
}
@ -21569,6 +21692,17 @@
"v8-compile-cache": "^2.0.3"
},
"dependencies": {
"ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"requires": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
"json-schema-traverse": "^0.4.1",
"uri-js": "^4.2.2"
}
},
"ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
@ -21630,6 +21764,11 @@
"argparse": "^2.0.1"
}
},
"json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
},
"supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
@ -22325,6 +22464,11 @@
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
},
"json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
},
"schema-utils": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz",
@ -22333,6 +22477,19 @@
"@types/json-schema": "^7.0.4",
"ajv": "^6.12.2",
"ajv-keywords": "^3.4.1"
},
"dependencies": {
"ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"requires": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
"json-schema-traverse": "^0.4.1",
"uri-js": "^4.2.2"
}
}
}
},
"supports-color": {
@ -24474,9 +24631,9 @@
"integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA=="
},
"json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="
},
"json-stable-stringify-without-jsonify": {
"version": "1.0.1",
@ -26697,6 +26854,24 @@
"@types/json-schema": "^7.0.8",
"ajv": "^6.12.5",
"ajv-keywords": "^3.5.2"
},
"dependencies": {
"ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"requires": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
"json-schema-traverse": "^0.4.1",
"uri-js": "^4.2.2"
}
},
"json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
}
}
},
"select-hose": {
@ -27578,12 +27753,6 @@
"is-typedarray": "^1.0.0"
}
},
"typescript": {
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.2.tgz",
"integrity": "sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg==",
"peer": true
},
"unbox-primitive": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz",

@ -12,6 +12,7 @@
"@testing-library/jest-dom": "^5.16.2",
"@testing-library/react": "^12.1.4",
"@testing-library/user-event": "^13.5.0",
"ajv": "^8.11.0",
"d3": "^7.3.0",
"dagre": "^0.8.5",
"idb": "^6.1.5",

@ -13,6 +13,7 @@ import { defaultData, defaultPlant, defaultProduct } from "./defaults";
import { randomPosition } from "./PipelineBlock";
import { exportData, importData } from "./export";
import { generateFile } from "./csv";
import { validate } from "./validate";
const setDefaults = (actualDict, defaultDict) => {
for (const [key, defaultValue] of Object.entries(defaultDict)) {
@ -69,6 +70,7 @@ const openRelogDB = async () => {
const InputPage = () => {
const fileElem = useRef();
let [data, setData] = useState(defaultData);
let [messages, setMessages] = useState([]);
const save = async (data) => {
const db = await openRelogDB();
@ -238,7 +240,18 @@ const InputPage = () => {
};
const onSave = () => {
generateFile("case.json", JSON.stringify(exportData(data), null, 2));
const exported = exportData(data);
const valid = validate(exported);
console.log(exported);
console.log(validate.errors);
if (valid) {
generateFile("case.json", JSON.stringify(exported, null, 2));
} else {
setMessages([
...messages,
"Data has validation errors and could not be saved.",
]);
}
};
const onClear = () => {
@ -248,9 +261,20 @@ const InputPage = () => {
};
const onLoad = (contents) => {
const newData = importData(JSON.parse(contents));
setData(newData);
save(newData);
const parsed = JSON.parse(contents);
const valid = validate(parsed);
if (valid) {
const newData = importData(parsed);
setData(newData);
save(newData);
} else {
console.log(validate.errors);
setMessages([...messages, "File is corrupted and could not be loaded."]);
}
};
const onDismissMessage = (idx) => {
setMessages([...messages.slice(0, idx), ...messages.slice(idx + 1)]);
};
const onChange = (val, field1, field2) => {
@ -289,6 +313,16 @@ const InputPage = () => {
);
}
let messageComps = [];
for (let i = 0; i < messages.length; i++) {
messageComps.push(
<div className="message error" key={i}>
<p>{messages[i]}</p>
<Button label="Dismiss" onClick={() => onDismissMessage(i)} />
</div>
);
}
const onFileSelected = () => {
const file = fileElem.current.files[0];
if (file) {
@ -337,6 +371,7 @@ const InputPage = () => {
{productComps}
{plantComps}
</div>
<div id="messageTray">{messageComps}</div>
<Footer />
</>
);

@ -197,7 +197,7 @@ const PlantBlock = (props) => {
/>
<TextInputRow
label="Variable operating cost"
unit="$"
unit="$/tonne"
tooltip="The cost that the plant incurs to process each tonne of input."
value={props.value["variable operating cost ($/tonne)"]}
onChange={(v) => onChange(v, "variable operating cost ($/tonne)")}

@ -169,7 +169,7 @@ const ProductBlock = (props) => {
/>
<DictInputRow
label="Transportation emissions"
unit="J/km/tonne"
unit="tonne/km/tonne"
tooltip="A dictionary mapping the name of each greenhouse gas, produced to transport one tonne of this product along one kilometer, to the amount of gas produced."
keyPlaceholder="Emission name"
value={props.value["transportation emissions (tonne/km/tonne)"]}

@ -305,6 +305,7 @@ const compressDisposalLimits = (original, result) => {
return;
}
const total = computeTotalInitialAmount(original);
if (!total) return;
const limit = original["disposal limit (tonne)"];
let perc = Math.round((limit[0] / total[0]) * 1e6) / 1e6;
for (let i = 1; i < limit.length; i++) {
@ -369,6 +370,12 @@ export const importPlant = (original) => {
const plant = {};
const parameters = {};
plant["storage"] = {};
plant["storage"]["cost ($/tonne)"] = 0;
plant["storage"]["limit (tonne)"] = 0;
plant["disposal cost ($/tonne)"] = 0;
plant["disposal limit (tonne)"] = 0;
// Initialize null values
["x", "y"].forEach((key) => {
plant[key] = null;
@ -428,9 +435,9 @@ export const importPlant = (original) => {
// Compute area cost factor
let acf = 1;
if (costsInitialized) {
acf = plant["opening cost (min capacity) ($)"];
acf = plant["opening cost (max capacity) ($)"];
if (Array.isArray(acf)) acf = acf[0];
acf = minCapDict["opening cost ($)"][0] / acf;
acf = maxCapDict["opening cost ($)"][0] / acf;
}
resLocDict[locName]["area cost factor"] = acf;

@ -10,6 +10,7 @@ body {
margin: 0;
padding: 0;
border: 0;
font-family: sans-serif;
}
body {
@ -50,3 +51,47 @@ body {
.react-flow__handle-left {
left: -4px !important;
}
#messageTray {
max-width: var(--site-width);
margin: 0 auto;
position: fixed;
bottom: 12px;
left: 0;
right: 0;
z-index: 100;
}
#messageTray .message {
background-color: rgb(221, 69, 69);
color: #eee;
padding: 12px;
border-radius: var(--border-radius);
box-shadow: 4px 4px 8px rgba(0, 0, 0, 0.4);
display: flex;
margin-top: 12px;
}
#messageTray .message p {
flex: 1;
margin: 0;
padding: 12px 0;
}
#messageTray .message button {
margin: 0;
background: transparent;
border: 1px solid #eee;
color: #eee;
float: right;
padding: 0 24px;
line-height: 6px;
}
#messageTray .message button:hover {
background: rgba(255, 255, 255, 0.05);
}
#messageTray .message button:active {
background: rgba(255, 255, 255, 0.1);
}

@ -0,0 +1,182 @@
const Ajv = require("ajv");
const ajv = new Ajv();
const schema = {
$schema: "http://json-schema.org/draft-07/schema#",
$id: "https://anl-ceeesa.github.io/RELOG/input",
title: "Schema for RELOG Input File",
definitions: {
TimeSeries: {
type: "array",
items: {
type: "number",
},
},
Parameters: {
type: "object",
properties: {
"time horizon (years)": {
type: "number",
},
},
required: ["time horizon (years)"],
},
Plant: {
type: "object",
additionalProperties: {
type: "object",
properties: {
input: {
type: "string",
},
"outputs (tonne/tonne)": {
type: "object",
additionalProperties: {
type: "number",
},
},
"energy (GJ/tonne)": {
$ref: "#/definitions/TimeSeries",
},
"emissions (tonne/tonne)": {
type: "object",
additionalProperties: {
$ref: "#/definitions/TimeSeries",
},
},
locations: {
$ref: "#/definitions/PlantLocation",
},
},
required: ["input", "locations"],
},
},
PlantLocation: {
type: "object",
additionalProperties: {
type: "object",
properties: {
location: {
type: "string",
},
"latitude (deg)": {
type: "number",
},
"longitude (deg)": {
type: "number",
},
disposal: {
type: "object",
additionalProperties: {
type: "object",
properties: {
"cost ($/tonne)": {
$ref: "#/definitions/TimeSeries",
},
"limit (tonne)": {
$ref: "#/definitions/TimeSeries",
},
},
required: ["cost ($/tonne)"],
},
},
storage: {
type: "object",
properties: {
"cost ($/tonne)": {
$ref: "#/definitions/TimeSeries",
},
"limit (tonne)": {
type: "number",
},
},
required: ["cost ($/tonne)", "limit (tonne)"],
},
"capacities (tonne)": {
type: "object",
additionalProperties: {
type: "object",
properties: {
"variable operating cost ($/tonne)": {
$ref: "#/definitions/TimeSeries",
},
"fixed operating cost ($)": {
$ref: "#/definitions/TimeSeries",
},
"opening cost ($)": {
$ref: "#/definitions/TimeSeries",
},
},
required: [
"variable operating cost ($/tonne)",
"fixed operating cost ($)",
"opening cost ($)",
],
},
},
},
required: ["capacities (tonne)"],
},
},
InitialAmount: {
type: "object",
additionalProperties: {
type: "object",
properties: {
location: {
type: "string",
},
"latitude (deg)": {
type: "number",
},
"longitude (deg)": {
type: "number",
},
"amount (tonne)": {
$ref: "#/definitions/TimeSeries",
},
},
required: ["amount (tonne)"],
},
},
Product: {
type: "object",
additionalProperties: {
type: "object",
properties: {
"transportation cost ($/km/tonne)": {
$ref: "#/definitions/TimeSeries",
},
"transportation energy (J/km/tonne)": {
$ref: "#/definitions/TimeSeries",
},
"transportation emissions (tonne/km/tonne)": {
type: "object",
additionalProperties: {
$ref: "#/definitions/TimeSeries",
},
},
"initial amounts": {
$ref: "#/definitions/InitialAmount",
},
},
required: ["transportation cost ($/km/tonne)"],
},
},
},
type: "object",
properties: {
parameters: {
$ref: "#/definitions/Parameters",
},
plants: {
$ref: "#/definitions/Plant",
},
products: {
$ref: "#/definitions/Product",
},
},
required: ["parameters", "plants", "products"],
};
export const validate = ajv.compile(schema);
Loading…
Cancel
Save