mirror of
https://github.com/ANL-CEEESA/RELOG.git
synced 2025-12-05 23:38:52 -06:00
Implement form validation
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
import { useState } from 'react';
|
||||
import form_styles from './Form.module.css';
|
||||
import Button from './Button';
|
||||
import { validate } from './Form';
|
||||
|
||||
const DictInputRow = (props) => {
|
||||
const dict = { ...props.value };
|
||||
if (!props.disableKeys) {
|
||||
dict[""] = "";
|
||||
dict[""] = "0";
|
||||
}
|
||||
|
||||
let unit = "";
|
||||
@@ -36,6 +36,15 @@ const DictInputRow = (props) => {
|
||||
if (index > 0) {
|
||||
label = "";
|
||||
}
|
||||
|
||||
let isValid = true;
|
||||
if (props.validate !== undefined) {
|
||||
isValid = validate(props.validate, dict[key]);
|
||||
}
|
||||
|
||||
let className = "";
|
||||
if (!isValid) className = form_styles.invalid;
|
||||
|
||||
form.push(
|
||||
<div className={form_styles.FormRow} key={index}>
|
||||
<label>{label}</label>
|
||||
@@ -52,6 +61,7 @@ const DictInputRow = (props) => {
|
||||
data-index={index}
|
||||
value={dict[key]}
|
||||
placeholder={props.valuePlaceholder}
|
||||
className={className}
|
||||
onChange={e => onChangeValue(key, e.target.value)}
|
||||
/>
|
||||
{tooltip}
|
||||
|
||||
@@ -2,7 +2,6 @@ import form_styles from './Form.module.css';
|
||||
import Button from './Button';
|
||||
|
||||
const FileInputRow = (props) => {
|
||||
|
||||
let tooltip = "";
|
||||
if (props.tooltip != undefined) {
|
||||
tooltip = <Button label="?" kind="inline" tooltip={props.tooltip} />;
|
||||
@@ -10,7 +9,7 @@ const FileInputRow = (props) => {
|
||||
|
||||
return <div className={form_styles.FormRow}>
|
||||
<label>{props.label}</label>
|
||||
<input type="text" disabled="disabled" />
|
||||
<input type="text" value={props.value} disabled="disabled" />
|
||||
<Button label="Upload" kind="inline" />
|
||||
<Button label="Clear" kind="inline" />
|
||||
<Button label="Template" kind="inline" />
|
||||
|
||||
@@ -1,3 +1,17 @@
|
||||
const VALIDATION_REGEX = {
|
||||
int: new RegExp('^[0-9]+$'),
|
||||
intList: new RegExp('^\[[0-9]+(,[0-9]+)*\]$'),
|
||||
float: new RegExp('^[0-9]*\\.?[0-9]*$'),
|
||||
};
|
||||
|
||||
export const validate = (kind, value) => {
|
||||
if (value.length == 0) return false;
|
||||
if (!VALIDATION_REGEX[kind].test(value)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
const Form = (props) => {
|
||||
return <>{props.children}</>;
|
||||
};
|
||||
|
||||
@@ -20,4 +20,9 @@
|
||||
|
||||
.FormRow_unit {
|
||||
color: rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
.invalid {
|
||||
border: 2px solid #faa !important;
|
||||
background-color: rgba(255, 0, 0, 0.05);
|
||||
}
|
||||
@@ -12,7 +12,7 @@ const defaultData = {
|
||||
parameters: {
|
||||
"time horizon (years)": "1",
|
||||
"building period (years)": "[1]",
|
||||
"annual inflation rate (%)": "0.0",
|
||||
"annual inflation rate (%)": "0",
|
||||
},
|
||||
products: {
|
||||
},
|
||||
@@ -21,15 +21,13 @@ const defaultData = {
|
||||
};
|
||||
|
||||
const defaultProduct = {
|
||||
"acquisition cost ($/tonne)": "0.00",
|
||||
"disposal cost ($/tonne)": "0.00",
|
||||
"initial amounts": {},
|
||||
"acquisition cost ($/tonne)": "0",
|
||||
"disposal cost ($/tonne)": "0",
|
||||
"disposal limit (tonne)": "0",
|
||||
"transportation cost ($/km/tonne)": "0.00",
|
||||
"transportation cost ($/km/tonne)": "0",
|
||||
"transportation energy (J/km/tonne)": "0",
|
||||
"transportation emissions (J/km/tonne)": {
|
||||
"CO2": 0,
|
||||
"NH2": 0,
|
||||
}
|
||||
"transportation emissions (J/km/tonne)": {}
|
||||
};
|
||||
|
||||
const randomPosition = () => {
|
||||
|
||||
@@ -19,6 +19,7 @@ const ParametersBlock = (props) => {
|
||||
tooltip="Number of years in the simulation."
|
||||
value={props.value["time horizon (years)"]}
|
||||
onChange={v => onChangeField("time horizon (years)", v)}
|
||||
validate="int"
|
||||
/>
|
||||
<TextInputRow
|
||||
label="Building period"
|
||||
@@ -26,6 +27,7 @@ const ParametersBlock = (props) => {
|
||||
tooltip="List of years in which we are allowed to open new plants. For example, if this parameter is set to [1,2,3], we can only open plants during the first three years. By default, this equals [1]; that is, plants can only be opened during the first year."
|
||||
value={props.value["building period (years)"]}
|
||||
onChange={v => onChangeField("building period (years)", v)}
|
||||
validate="intList"
|
||||
/>
|
||||
<TextInputRow
|
||||
label="Annual inflation rate"
|
||||
@@ -33,6 +35,7 @@ const ParametersBlock = (props) => {
|
||||
tooltip="Rate of inflation applied to all costs."
|
||||
value={props.value["annual inflation rate (%)"]}
|
||||
onChange={v => onChangeField("annual inflation rate (%)", v)}
|
||||
validate="float"
|
||||
/>
|
||||
</Form>
|
||||
</Card>
|
||||
|
||||
@@ -13,6 +13,8 @@ const ProductBlock = (props) => {
|
||||
props.onChange(newProduct);
|
||||
};
|
||||
|
||||
const nCenters = Object.keys(props.value["initial amounts"]).length;
|
||||
|
||||
return (
|
||||
<>
|
||||
<Section title={props.name} />
|
||||
@@ -20,6 +22,7 @@ const ProductBlock = (props) => {
|
||||
<Form>
|
||||
<h1>General information</h1>
|
||||
<FileInputRow
|
||||
value={`${nCenters} collection centers`}
|
||||
label="Initial amounts"
|
||||
tooltip="A dictionary mapping the name of each location to its description (see below). If this product is not initially available, this key may be omitted."
|
||||
/>
|
||||
@@ -29,6 +32,7 @@ const ProductBlock = (props) => {
|
||||
tooltip="The cost to acquire one tonne of this product from collection centers. Does not apply to plant outputs."
|
||||
value={props.value["acquisition cost ($/tonne)"]}
|
||||
onChange={v => onChange("acquisition cost ($/tonne)", v)}
|
||||
validate="float"
|
||||
/>
|
||||
|
||||
<h1>Disposal</h1>
|
||||
@@ -38,6 +42,7 @@ const ProductBlock = (props) => {
|
||||
tooltip="The cost to dispose of one tonne of this product at a collection center, without further processing. Does not apply to plant outputs."
|
||||
value={props.value["disposal cost ($/tonne)"]}
|
||||
onChange={v => onChange("disposal cost ($/tonne)", v)}
|
||||
validate="float"
|
||||
/>
|
||||
<TextInputRow
|
||||
label="Disposal limit"
|
||||
@@ -45,6 +50,7 @@ const ProductBlock = (props) => {
|
||||
tooltip="The maximum amount of this product that can be disposed of across all collection centers, without further processing."
|
||||
value={props.value["disposal limit (tonne)"]}
|
||||
onChange={v => onChange("disposal limit (tonne)", v)}
|
||||
validate="float"
|
||||
/>
|
||||
|
||||
<h1>Transportation</h1>
|
||||
@@ -54,6 +60,7 @@ const ProductBlock = (props) => {
|
||||
tooltip="The cost to transport this product."
|
||||
value={props.value["transportation cost ($/km/tonne)"]}
|
||||
onChange={v => onChange("transportation cost ($/km/tonne)", v)}
|
||||
validate="float"
|
||||
/>
|
||||
<TextInputRow
|
||||
label="Transportation energy"
|
||||
@@ -61,15 +68,16 @@ const ProductBlock = (props) => {
|
||||
tooltip="The energy required to transport this product."
|
||||
value={props.value["transportation energy (J/km/tonne)"]}
|
||||
onChange={v => onChange("transportation energy (J/km/tonne)", v)}
|
||||
validate="float"
|
||||
/>
|
||||
<DictInputRow
|
||||
label="Transportation emissions"
|
||||
unit="J/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 (in tonnes)."
|
||||
keyPlaceholder="Emission name"
|
||||
valuePlaceholder="0"
|
||||
value={props.value["transportation emissions (J/km/tonne)"]}
|
||||
onChange={v => onChange("transportation emissions (J/km/tonne)", v)}
|
||||
validate="float"
|
||||
/>
|
||||
</Form>
|
||||
</Card>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import form_styles from './Form.module.css';
|
||||
import Button from './Button';
|
||||
import { validate } from './Form';
|
||||
|
||||
const TextInputRow = (props) => {
|
||||
let unit = "";
|
||||
@@ -12,6 +13,14 @@ const TextInputRow = (props) => {
|
||||
tooltip = <Button label="?" kind="inline" tooltip={props.tooltip} />;
|
||||
}
|
||||
|
||||
let isValid = true;
|
||||
if (props.validate !== undefined) {
|
||||
isValid = validate(props.validate, props.value);
|
||||
}
|
||||
|
||||
let className = "";
|
||||
if (!isValid) className = form_styles.invalid;
|
||||
|
||||
return <div className={form_styles.FormRow}>
|
||||
<label>
|
||||
{props.label} {unit}
|
||||
@@ -21,6 +30,7 @@ const TextInputRow = (props) => {
|
||||
placeholder={props.default}
|
||||
disabled={props.disabled}
|
||||
value={props.value}
|
||||
className={className}
|
||||
onChange={e => props.onChange(e.target.value)}
|
||||
/>
|
||||
{tooltip}
|
||||
|
||||
Reference in New Issue
Block a user