Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 54 additions & 52 deletions client/src/components/modal/EditDetailsModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,13 @@ import { FlatConfigOption } from "../steps/Configs/SlideOut";
import OptionSelect from "../steps/Configs/OptionSelect";
import { useDebouncedCallback } from "use-debounce";
import { removeEmpty } from "../../utils/utils";
import {
SystemTypeInterface,
TemplateInterface
} from "../../data/template";
import { SystemTypeInterface, TemplateInterface } from "../../data/template";

import {
applyValueModifiers,
applyVisibilityModifiers,
ConfigValues,
} from "../../utils/modifier-helpers";
import { ConfigValues } from "../../utils/modifier-helpers";

interface EditDetailsModalProps extends ModalInterface {
afterSubmit?: () => void;
Expand All @@ -41,22 +38,20 @@ const EditDetailsModal = observer(
const projectOptions = templateStore.getOptionsForProject();
const allOptions = templateStore.getAllOptions();
const [formInputs, setFormInputs] = useState({
name: details?.name || '',
address: details?.address || '',
type: details?.type || '',
name: details?.name || "",
address: details?.address || "",
type: details?.type || "",
size: details?.size || 0,
notes: details?.notes || '',
notes: details?.notes || "",
});
const [selectedValues, setSelectedValues] = useState<ConfigValues>(
projectStore.getProjectSelections()
projectStore.getProjectSelections(),
);

const evaluatedValues = getEvaluatedValues(projectOptions);
const displayedOptions = getDisplayOptions(projectOptions, 'root');
const displayedOptions = getDisplayOptions(projectOptions, "root");

function getEvaluatedValues(
options: OptionInterface[],
): ConfigValues {
function getEvaluatedValues(options: OptionInterface[]): ConfigValues {
let evaluatedValues: ConfigValues = {};

options.forEach((option) => {
Expand All @@ -78,9 +73,7 @@ const EditDetailsModal = observer(
if (option.childOptions?.length) {
evaluatedValues = {
...evaluatedValues,
...getEvaluatedValues(
option.childOptions,
),
...getEvaluatedValues(option.childOptions),
};
}
});
Expand All @@ -93,8 +86,8 @@ const EditDetailsModal = observer(
parentModelicaPath: string,
): FlatConfigOption[] {
const removeNotSpecifiedList = [
'Buildings.Templates.Data.AllSystems.ashCliZon',
'Buildings.Templates.Data.AllSystems.tit24CliZon'
"Buildings.Templates.Data.AllSystems.ashCliZon",
"Buildings.Templates.Data.AllSystems.tit24CliZon",
];
let displayOptions: FlatConfigOption[] = [];

Expand All @@ -110,8 +103,10 @@ const EditDetailsModal = observer(
);

if (isVisible && option.childOptions?.length) {
const modifiedChildOptions = removeNotSpecifiedList.includes(option.modelicaPath)
? option.childOptions.filter((opt) => opt.name !== 'Not specified')
const modifiedChildOptions = removeNotSpecifiedList.includes(
option.modelicaPath,
)
? option.childOptions.filter((opt) => opt.name !== "Not specified")
: option.childOptions;

displayOptions = [
Expand All @@ -128,42 +123,35 @@ const EditDetailsModal = observer(
},
];

if (selectedValues[selectionPath]) {
const selectedOption = allOptions[
selectedValues[selectionPath]
] as OptionInterface;
const selectedValue = selectedValues[selectionPath];
const evaluatedValue = evaluatedValues[selectionPath];
// Only string values (Modelica paths) can be used for option lookup
if (typeof selectedValue === "string") {
const selectedOption = allOptions[selectedValue] as OptionInterface;

if (selectedOption) {
displayOptions = [
...displayOptions,
...getDisplayOptions(
[selectedOption],
option.modelicaPath,
),
...getDisplayOptions([selectedOption], option.modelicaPath),
];
}
} else if (evaluatedValues[selectionPath]) {
// Only string values (Modelica paths) can be used for option lookup
} else if (typeof evaluatedValue === "string") {
const evaluatedOption = allOptions[
evaluatedValues[selectionPath]
evaluatedValue
] as OptionInterface;

if (evaluatedOption) {
displayOptions = [
...displayOptions,
...getDisplayOptions(
[evaluatedOption],
option.modelicaPath,
),
...getDisplayOptions([evaluatedOption], option.modelicaPath),
];
}
}
} else if (option.childOptions?.length) {
displayOptions = [
...displayOptions,
...getDisplayOptions(
option.childOptions,
option.modelicaPath,
),
...getDisplayOptions(option.childOptions, option.modelicaPath),
];
}
});
Expand All @@ -172,7 +160,9 @@ const EditDetailsModal = observer(
}

const updateTextInput = useDebouncedCallback(
(event: ChangeEvent<HTMLInputElement> | ChangeEvent<HTMLTextAreaElement>) => {
(
event: ChangeEvent<HTMLInputElement> | ChangeEvent<HTMLTextAreaElement>,
) => {
setFormInputs((prevState: any) => {
return {
...prevState,
Expand All @@ -190,7 +180,7 @@ const EditDetailsModal = observer(
[event.target.name]: event.target.value,
};
});
};
}

function updateSelectedOption(
parentModelicaPath: string,
Expand All @@ -216,20 +206,27 @@ const EditDetailsModal = observer(
// This was done due to time and was a bug found last min.
function adjustProjectSelections() {
const projectSelectedItems = selectedValues;
const energyStandard = projectSelectedItems['Buildings.Templates.Data.AllSystems.stdEne'];
const energyStandard =
projectSelectedItems["Buildings.Templates.Data.AllSystems.stdEne"];

if (
energyStandard === 'Buildings.Controls.OBC.ASHRAE.G36.Types.EnergyStandard.ASHRAE90_1' &&
projectSelectedItems['Buildings.Templates.Data.AllSystems.tit24CliZon']
energyStandard ===
"Buildings.Controls.OBC.ASHRAE.G36.Types.EnergyStandard.ASHRAE90_1" &&
projectSelectedItems["Buildings.Templates.Data.AllSystems.tit24CliZon"]
) {
delete projectSelectedItems['Buildings.Templates.Data.AllSystems.tit24CliZon'];
delete projectSelectedItems[
"Buildings.Templates.Data.AllSystems.tit24CliZon"
];
}

if (
energyStandard === 'Buildings.Controls.OBC.ASHRAE.G36.Types.EnergyStandard.California_Title_24' &&
projectSelectedItems['Buildings.Templates.Data.AllSystems.ashCliZon']
energyStandard ===
"Buildings.Controls.OBC.ASHRAE.G36.Types.EnergyStandard.California_Title_24" &&
projectSelectedItems["Buildings.Templates.Data.AllSystems.ashCliZon"]
) {
delete projectSelectedItems['Buildings.Templates.Data.AllSystems.ashCliZon'];
delete projectSelectedItems[
"Buildings.Templates.Data.AllSystems.ashCliZon"
];
}

return projectSelectedItems;
Expand All @@ -248,10 +245,15 @@ const EditDetailsModal = observer(
// The reason for this is we don't want the user to use saved configs with
// changed project details as it will cause issues with evaluated values.
templateStore.systemTypes.forEach((systemType: SystemTypeInterface) => {
const templates = templateStore.getTemplatesForSystem(systemType.modelicaPath);
const templates = templateStore.getTemplatesForSystem(
systemType.modelicaPath,
);

templates.forEach((option: TemplateInterface) => {
configStore.removeAllForSystemTemplate(systemType.modelicaPath, option.modelicaPath);
configStore.removeAllForSystemTemplate(
systemType.modelicaPath,
option.modelicaPath,
);
});
});
if (afterSubmit) afterSubmit();
Expand All @@ -269,10 +271,10 @@ const EditDetailsModal = observer(
updateSelectedOption={updateSelectedOption}
/>
</label>
)
);
})}
</div>
)
);
}

return (
Expand Down
3 changes: 2 additions & 1 deletion client/src/components/steps/Configs/SlideOut.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import { OptionInterface } from "../../../data/template";
import Modal from "../../modal/Modal";
import OptionSelect from "./OptionSelect";
import { mapToDisplayOptions as mapConfigContextToDisplayOptions } from "../../../interpreter/display-option";
import { ConfigContext, ConfigValues } from "../../../interpreter/interpreter";
import { ConfigContext } from "../../../interpreter/interpreter";
import { ConfigValues } from "../../../utils/modifier-helpers";
import { removeEmpty } from "../../../utils/utils";

import "../../../styles/components/config-slide-out.scss";
Expand Down
30 changes: 20 additions & 10 deletions client/src/interpreter/interpreter.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import { ConfigInterface } from "../../src/data/config";
import { TemplateInterface, OptionInterface } from "../../src/data/template";
import { removeEmpty } from "../../src/utils/utils";
import { ConfigValues } from "../utils/modifier-helpers";

export type Literal = boolean | string | number;

export interface ConfigValues {
[key: string]: string;
}

export type Expression = {
operator: string;
operands: Array<Literal | Expression>;
Expand Down Expand Up @@ -149,7 +146,11 @@ const _instancePathToOption = (
if (context.config?.selections) {
Object.entries(context.selections).map(([key, value]) => {
const [, instancePath] = key.split("-");
if (instancePath === curInstancePathList.join(".")) {
// Only string values (Modelica paths) can be used for option lookup
if (
instancePath === curInstancePathList.join(".") &&
typeof value === "string"
) {
option = context.options[value];
}
});
Expand Down Expand Up @@ -624,7 +625,11 @@ const buildModsHelper = (
option.modelicaPath,
newBase,
);
redeclaredType = selections[selectionPath];
const selectionValue = selections[selectionPath];
// Only string values (Modelica paths) can be used for option lookup
if (typeof selectionValue === "string") {
redeclaredType = selectionValue;
}
}

if (option.choiceModifiers && redeclaredType) {
Expand Down Expand Up @@ -652,7 +657,13 @@ const buildModsHelper = (
} else {
// if this is a replaceable element, get the redeclared type
// (this includes instances of replaceable short classes)
const typeOptionPath = getReplaceableType(newBase, option, mods, selections, options);
const typeOptionPath = getReplaceableType(
newBase,
option,
mods,
selections,
options,
);
const typeOption = options[typeOptionPath as string];

if (typeOption && typeOption.options) {
Expand All @@ -668,8 +679,7 @@ const buildModsHelper = (

// Each parent class must also be visited
// See https://github.com/lbl-srg/ctrl-flow-dev/issues/360
typeOption
.treeList
typeOption.treeList
?.filter((path) => path !== (typeOptionPath as string)) // Exclude current class from being visited again
.map((oPath) => {
const o = options[oPath];
Expand All @@ -681,7 +691,7 @@ const buildModsHelper = (
selections,
selectionModelicaPathsCache,
);
})
});

// Further populate `mods` with all options belonging to this class
typeOption.options.map((path) => {
Expand Down
27 changes: 18 additions & 9 deletions client/src/utils/modifier-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ import {
resolveValue,
} from "./expression-helpers";

export interface ConfigValues {
[key: string]: boolean | string | number | null | undefined;
}

export type Modifiers = {
[key: string]: { expression: Expression; final: boolean; redeclare: boolean };
};

export interface ConfigValues {
[key: string]: string;
}

function addToModObject(
newModifiers: Modifiers,
baseInstancePath: string,
Expand Down Expand Up @@ -122,7 +122,13 @@ export function buildModifiers(
const datAll = options["datAll"]; // project settings
updateModifiers(datAll, "", modifiers, "", options);
}
updateModifiers(startOption, baseInstancePath, modifiers, selectedType, options);
updateModifiers(
startOption,
baseInstancePath,
modifiers,
selectedType,
options,
);

return modifiers;
}
Expand Down Expand Up @@ -275,15 +281,18 @@ export function getUpdatedModifiers(
let updatedModifiers: Modifiers = deepCopy(modifiers);

optionKeys.forEach((key) => {
if (values[key] !== null) {
const selectedType = values[key];
const value = values[key];
// Only string values (Modelica paths) can be used for option lookup
if (typeof value === "string") {
const selectedType = value;
const modelicaPath = key.split("-")[0];
const instancePath = key.split("-")[1]?.split(".").slice(0, -1).join(".") || '';
const instancePath =
key.split("-")[1]?.split(".").slice(0, -1).join(".") || "";
const option = allOptions[modelicaPath] as OptionInterface;
let choiceModifiers = {};

if (option?.choiceModifiers) {
choiceModifiers = option?.choiceModifiers[values[key]];
choiceModifiers = option?.choiceModifiers[value];
// take modifiers and change to instace keys, instancePath above and add to updatedModifiers as the last item.
}

Expand Down
Loading