Skip to content

Commit

Permalink
Added calibration feature + some small changes
Browse files Browse the repository at this point in the history
  • Loading branch information
manas-qm committed Aug 8, 2024
1 parent 72806cf commit 0c0b361
Show file tree
Hide file tree
Showing 25 changed files with 907 additions and 106 deletions.
32 changes: 32 additions & 0 deletions frontend/src/modules/CalibrationGraph/CalibrationGraph.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
@import "../../assets/styles/variables";
@import "../../assets/styles/base";

.wrapper {
height: 100%;
display: flex;
color: var(--font) !important;
}

.nodesContainer {
display: flex;
flex-direction: column;
overflow: hidden;
flex-grow: 1;
margin-left: 20px;
margin-right: 20px;
margin-bottom: 10px;
border-radius: var(--border-radius);
}

.titleWrapper {
justify-content: space-between;
}

.listWrapper {
flex-grow: 1;
border: 2px solid var(--border-color);
padding: 2px;;
background-color: var(--popup-background);
max-width: 100%;
overflow: scroll;
}
36 changes: 36 additions & 0 deletions frontend/src/modules/CalibrationGraph/api/CalibrationsAPI.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import Api, { BASIC_HEADERS } from "../../../utils/api";
import { Res } from "../../../common/interfaces/Api";
import { ALL_GRAPHS, GET_WORKFLOW_GRAPH, SUBMIT_WORKFLOW_RUN } from "../../../utils/api/apiRoutes";
import { API_METHODS } from "../../../common/enums/Api";

export class CalibrationsApi extends Api {
constructor() {
super();
}

static api(path: string): string {
return this.address + path;
}

static fetchAllGraphs(rescan: boolean = false): Promise<Res<void>> {
return this._fetch(this.api(ALL_GRAPHS()), API_METHODS.GET, {
headers: BASIC_HEADERS,
queryParams: { rescan },
});
}

static fetchGraph(name: string): Promise<Res<void>> {
return this._fetch(this.api(GET_WORKFLOW_GRAPH()), API_METHODS.GET, {
headers: BASIC_HEADERS,
queryParams: { name },
});
}

static submitWorkflow(name: string, workflow: unknown): Promise<Res<void>> {
return this._fetch(this.api(SUBMIT_WORKFLOW_RUN()), API_METHODS.POST, {
headers: BASIC_HEADERS,
body: JSON.stringify(workflow),
queryParams: { name },
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
.searchContainer {
max-width: 280px;
padding-bottom: 20px;

input {
border-radius: 25px;
font-style: italic;
}
}

.wrapper {
padding-top: 13px;
padding-left: 25px;
padding-bottom: 13px;
width: auto;
min-height: 30px;
border: solid 1px var(--border-color);
border-radius: 7px;
flex-direction: column;
}

.upperContainer {
display: flex;
}

.bottomContainer {
display: flex;
}

.parametersContainer {
max-width: 40%;
}

.graphContainer {
flex: 1;
align-content: center;
//text-align: center;
width: 60%;
}

.leftContainer {
align-content: center;
display: flex;
gap: 10px;
text-wrap: nowrap;
}

.rightContainer {
align-content: center;
text-align: right;
flex-grow: 1;
padding-right: 10px;
}

.iconWrapper {
align-content: center;
max-height: fit-content;
padding-right: 10px;

svg {
display: table-row;

}
}

.titleWrapper {
align-content: center;
color: var(--blue-icon-button-text);
}

.calibrationGraphSelected {
background-color: var(--selected-node);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
import React from "react";
// eslint-disable-next-line css-modules/no-unused-class
import styles from "../CalibrationGraphElement/CalibrationGraphElement.module.scss";
import { PlayIcon } from "../../../../ui-lib/Icons/PlayIcon";
import { classNames } from "../../../../utils/classnames";
import { InputParameter, Parameters, SingleParameter } from "../../../common/Parameters";
import { CalibrationGraphWorkflow } from "../CalibrationGraphList";
import { useSelectionContext } from "../../../common/context/SelectionContext";
import { Checkbox } from "@mui/material";
import InputField from "../../../../DEPRECATED_components/common/Input/InputField";
import { ParameterList } from "../../../common/ParameterList";
import { useCalibrationGraphContext } from "../../context/CalibrationGraphContext";
import CytoscapeGraph from "../CytoscapeGraph/CytoscapeGraph";
import { CalibrationsApi } from "../../api/CalibrationsAPI";
import { NodeDTO } from "../../../Nodes/components/NodeElement/NodeElement";

export interface ICalibrationGraphElementProps {
calibrationGraphKey?: string;
calibrationGraph: CalibrationGraphWorkflow;
}

interface TransformedGraph {
parameters: { [key: string]: string | number };
nodes: { [key: string]: { parameters: InputParameter } };
}

export const CalibrationGraphElement: React.FC<ICalibrationGraphElementProps> = ({ calibrationGraphKey, calibrationGraph }) => {
const { selectedItemName, setSelectedItemName } = useSelectionContext();
const { workflowGraphElements, setSelectedWorkflowName, allCalibrationGraphs, setAllCalibrationGraphs, selectedWorkflowName } =
useCalibrationGraphContext();

const updateParameter = (paramKey: string, newValue: boolean | number | string, workflow?: NodeDTO | CalibrationGraphWorkflow) => {
const updatedParameters = {
...workflow?.parameters,
[paramKey]: {
...(workflow?.parameters as InputParameter)[paramKey],
default: newValue,
},
};

if (selectedWorkflowName && allCalibrationGraphs?.[selectedWorkflowName]) {
const updatedWorkflow = {
...allCalibrationGraphs[selectedWorkflowName],
parameters: updatedParameters,
};

const updatedCalibrationGraphs = {
...allCalibrationGraphs,
[selectedWorkflowName]: updatedWorkflow,
};

setAllCalibrationGraphs(updatedCalibrationGraphs);
}
};
const getInputElement = (key: string, parameter: SingleParameter, node?: NodeDTO | CalibrationGraphWorkflow) => {
switch (parameter.type) {
case "boolean":
return (
<Checkbox
checked={parameter.default as boolean}
// onClick={() => updateParameter(key, !parameter.default, node)}
inputProps={{ "aria-label": "controlled" }}
/>
);
default:
return (
<InputField
placeholder={key}
value={parameter.default ? parameter.default.toString() : ""}
onChange={(val) => {
updateParameter(key, val, node);
}}
/>
);
}
};
const transformDataForSubmit = () => {
const input = allCalibrationGraphs?.[selectedWorkflowName ?? ""];
const workflowParameters = input?.parameters;
const transformParameters = (params?: InputParameter) => {
let transformedParams = {};
for (const key in params) {
transformedParams = { ...transformedParams, [key]: params[key].default };
}
return transformedParams;
};

const transformedGraph: TransformedGraph = {
parameters: transformParameters(workflowParameters),
nodes: {},
};

for (const nodeKey in input?.nodes) {
const node = input?.nodes[nodeKey];
transformedGraph.nodes[nodeKey] = {
parameters: transformParameters(node.parameters),
};
}

return transformedGraph;
};

const handleSubmit = async () => {
if (selectedWorkflowName) {
CalibrationsApi.submitWorkflow(selectedWorkflowName, transformDataForSubmit());
}
};

const show = selectedItemName === calibrationGraphKey;
return (
<div
className={classNames(styles.wrapper, show ? styles.calibrationGraphSelected : "")}
onClick={() => {
setSelectedItemName(calibrationGraphKey);
setSelectedWorkflowName(calibrationGraphKey);
}}
>
<div className={styles.upperContainer}>
<div className={styles.leftContainer}>
<div className={styles.iconWrapper}>
<div onClick={handleSubmit}>
<PlayIcon />
</div>
</div>
<div className={styles.titleWrapper}>{calibrationGraphKey}</div>
</div>
<div className={styles.rightContainer}>
<div>{calibrationGraph?.description}</div>
</div>
</div>
<div className={styles.bottomContainer}>
<div className={styles.parametersContainer}>
<Parameters
key={calibrationGraphKey}
show={show}
showTitle={true}
currentItem={calibrationGraph}
getInputElement={getInputElement}
/>
<ParameterList showParameters={show} mapOfItems={calibrationGraph.nodes} />
</div>
<div className={styles.graphContainer}>{show && workflowGraphElements && <CytoscapeGraph elements={workflowGraphElements} />}</div>
</div>
</div>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React from "react";
// eslint-disable-next-line css-modules/no-unused-class
import styles from "../CalibrationGraphElement/CalibrationGraphElement.module.scss";
import InputField from "../../../../DEPRECATED_components/common/Input/InputField";
import { SearchIcon } from "../../../../ui-lib/Icons/SearchIcon";
import { IconType } from "../../../../common/interfaces/InputProps";

export const CalibrationGraphSearch: React.FC = () => {
return (
<div className={styles.searchContainer}>
<InputField placeholder={"graph name"} iconType={IconType.INNER} icon={<SearchIcon height={18} width={18} />}></InputField>
</div>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React from "react";
// eslint-disable-next-line css-modules/no-unused-class
import styles from "../CalibrationGraph.module.scss";
import { CalibrationGraphElement } from "./CalibrationGraphElement/CalibrationGraphElement";
import { NodeMap } from "../../Nodes/components/NodeElement/NodeElement";
import { useCalibrationGraphContext } from "../context/CalibrationGraphContext";
import { InputParameter } from "../../common/Parameters";

export interface CalibrationGraphWorkflow {
name?: string;
title?: string;
description: string;
parameters?: InputParameter;
nodes?: NodeMap;
connectivity?: string[][];
}

export const CalibrationGraphList: React.FC = () => {
const { allCalibrationGraphs } = useCalibrationGraphContext();
if (!allCalibrationGraphs || Object.entries(allCalibrationGraphs).length === 0) return <div>No calibration graphs</div>;
return (
<div className={styles.listWrapper}>
{Object.entries(allCalibrationGraphs ?? {}).map(([key, graph]) => {
return <CalibrationGraphElement key={key} calibrationGraphKey={key} calibrationGraph={graph} />;
})}
</div>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
@import "../../../../assets/styles/variables";
@import "../../../../assets/styles/base";

.wrapper {
width: auto;
height: 100%;
background: var(--background-color);
border-radius: var(--border-radius);
margin-left: 10px;
margin-right: 10px;
}
Loading

0 comments on commit 0c0b361

Please sign in to comment.