diff --git a/package-lock.json b/package-lock.json index 7e9c39f0e74b874d1b07e348a42b1e6bf8dcd3b7..ea4015377f6e5406c80892d3990c7404fe5f87ef 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8487,6 +8487,11 @@ "has-symbols": "^1.0.1" } }, + "get-node-dimensions": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/get-node-dimensions/-/get-node-dimensions-1.2.1.tgz", + "integrity": "sha512-2MSPMu7S1iOTL+BOa6K1S62hB2zUAYNF/lV0gSVlOaacd087lc6nR1H1r0e3B1CerTo+RceOmi1iJW+vp21xcQ==" + }, "get-own-enumerable-property-symbols": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", @@ -8770,6 +8775,14 @@ "integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==", "dev": true }, + "history": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/history/-/history-5.3.0.tgz", + "integrity": "sha512-ZqaKwjjrAYUYfLG+htGaIIZ4nioX2L70ZUMIFysS3xvBsSG4x/n1V6TXV3N8ZYNuFGlDirFg32T7B6WOUPDYcQ==", + "requires": { + "@babel/runtime": "^7.7.6" + } + }, "hmac-drbg": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", @@ -11876,6 +11889,11 @@ "lodash._reinterpolate": "^3.0.0" } }, + "lodash.throttle": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", + "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==" + }, "lodash.uniq": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", @@ -15127,6 +15145,28 @@ "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" }, + "react-measure": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/react-measure/-/react-measure-2.5.2.tgz", + "integrity": "sha512-M+rpbTLWJ3FD6FXvYV6YEGvQ5tMayQ3fGrZhRPHrE9bVlBYfDCLuDcgNttYfk8IqfOI03jz6cbpqMRTUclQnaA==", + "requires": { + "@babel/runtime": "^7.2.0", + "get-node-dimensions": "^1.2.1", + "prop-types": "^15.6.2", + "resize-observer-polyfill": "^1.5.0" + } + }, + "react-reflex": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/react-reflex/-/react-reflex-4.0.9.tgz", + "integrity": "sha512-XFTNRekFK4ul8mzVd1lniKT/SI0FvNYhXyLNl5gagS1i3iW9QKlpFYcRfVhZlxxaYHb8UyLOs3+H4Ay5cjtbxQ==", + "requires": { + "@babel/runtime": "^7.0.0", + "lodash.throttle": "^4.1.1", + "prop-types": "^15.5.8", + "react-measure": "^2.0.2" + } + }, "react-refresh": { "version": "0.8.3", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.8.3.tgz", @@ -15159,6 +15199,23 @@ } } }, + "react-router": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.3.0.tgz", + "integrity": "sha512-7Wh1DzVQ+tlFjkeo+ujvjSqSJmkt1+8JO+T5xklPlgrh70y7ogx75ODRW0ThWhY7S+6yEDks8TYrtQe/aoboBQ==", + "requires": { + "history": "^5.2.0" + } + }, + "react-router-dom": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.3.0.tgz", + "integrity": "sha512-uaJj7LKytRxZNQV8+RbzJWnJ8K2nPsOOEuX7aQstlMZKQT0164C+X2w6bnkqU3sjtLvpd5ojrezAyfZ1+0sStw==", + "requires": { + "history": "^5.2.0", + "react-router": "6.3.0" + } + }, "react-scripts": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-4.0.3.tgz", diff --git a/package.json b/package.json index 33d2c8a0c3ebad2cadadebdb2e5d7bf499df5722..4386b61820c08dcc1cd569481adb72f74b0c166a 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,9 @@ "react-error-boundary": "^3.1.4", "react-flow-renderer": "^10.1.0", "react-json-view": "latest", + "react-reflex": "^4.0.9", "react-rnd": "^10.3.4", + "react-router-dom": "^6.3.0", "react-use": "^17.3.1", "socket.io-client": "^4.4.1", "zustand": "^3.5.10" diff --git a/src/App.tsx b/src/App.tsx index 515f5046f15d511b745711bd10c2e93b9bcaaffc..7e95168d2b191244f016026475bd8982e973945b 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,5 +1,6 @@ import { makeStyles, createStyles, Theme } from '@material-ui/core/styles'; import Dashboard from './layout/Dashboard'; +import 'react-reflex/styles.css'; const useStyles = makeStyles((theme: Theme) => createStyles({ diff --git a/src/Components/AddNodes.tsx b/src/Components/AddNodes.tsx index 55f3ad81671856828290a7796107a41633bea69b..e8b1ae28cd792f7c9dc11b08395b49dced482fb7 100644 --- a/src/Components/AddNodes.tsx +++ b/src/Components/AddNodes.tsx @@ -177,11 +177,15 @@ function AddNodes(props) { }; return ( - + } aria-controls="panel1a-content" - id="panel1a-header" > {taskCategories.map((categoryName) => ( - + } aria-controls="panel1a-content" - id="panel1a-header" > {categoryName} diff --git a/src/Components/CellEditInJson.tsx b/src/Components/CellEditInJson.tsx index 7028480e1536a84b379cd1488f04cf20ad0044fb..99c3e4726ae0d9ac82814516e0fcabcc91b7a49f 100644 --- a/src/Components/CellEditInJson.tsx +++ b/src/Components/CellEditInJson.tsx @@ -4,6 +4,12 @@ export default function CellEditInJson(propsIn) { const { props } = propsIn; const { row, name, type } = props; + const onChangeL = (edit, row) => { + /* eslint-disable no-console */ + console.log(edit, row, name); + // onChange(edit, row, 1); + }; + return ( onChange(edit, row, index)} - // onAdd={(add) => onChange(add, row, index)} + onEdit={(edit) => onChangeL(edit, row)} + onAdd={(add) => onChangeL(add, row)} defaultValue="object" - // onDelete={(del) => onChange(del, row, index)} - // onSelect={(sel) => onChange(sel, row, index)} + onDelete={(del) => onChangeL(del, row)} + onSelect={(sel) => onChangeL(sel, row)} quotesOnKeys={false} style={{ backgroundColor: 'rgb(59, 77, 172)' }} displayDataTypes diff --git a/src/Components/Conditions.tsx b/src/Components/Conditions.tsx index da8b45109db20732184c633c884e95cdbce20407..82050a744cc857d3cc9c6439659e7e8106377c66 100644 --- a/src/Components/Conditions.tsx +++ b/src/Components/Conditions.tsx @@ -5,15 +5,14 @@ import { IconButton } from '@material-ui/core'; import AddCircleOutlineIcon from '@material-ui/icons/AddCircleOutline'; import EditableTable from './EditableTable'; import state from '../store/state'; +import SidebarTooltip from './SidebarTooltip'; export default function Conditions(props) { const { element } = props; const [conditions, setConditions] = React.useState([]); const setOpenSnackbar = state((state) => state.setOpenSnackbar); - const graphRF = state((state) => state.graphRF); const setSelectedElement = state((state) => state.setSelectedElement); - const [elementL] = React.useState({} as EwoksRFLink); useEffect(() => { if (element && element.data && element.data.conditions) { @@ -66,7 +65,13 @@ export default function Conditions(props) { return (
- Conditions + + Conditions + + {conditions && conditions.length > 0 && ( { - return nod.id === elementL.source; - }).task_type - ) - ? 'select' - : 'input' - : 'input', + type: 'select', + // elementL.source + // ? ['class'].includes( + // graphRF && + // graphRF.nodes[0] && + // graphRF.nodes.find((nod) => { + // return nod.id === elementL.source; + // }).task_type + // ) + // ? 'select' + // : 'input' + // : 'input', values: props.element.data.links_input_names || [], }, { diff --git a/src/Components/CustomTableCell.tsx b/src/Components/CustomTableCell.tsx index 26cd957c662898a18bfee69c7ce94d420c20f392..d3c936669f0b09fd8ab644c166b730ea79d39b94 100644 --- a/src/Components/CustomTableCell.tsx +++ b/src/Components/CustomTableCell.tsx @@ -3,23 +3,22 @@ import TableCell from '@material-ui/core/TableCell'; import TableCellInEditMode from './TableCellInEditMode'; -const useStyles = makeStyles(() => ({ - tableCell: { - width: 120, - height: 20, - padding: '1px', - }, - input: { - width: 90, - height: 20, - padding: '1px', - }, -})); - function CustomTableCell({ index, row, name, onChange, type, typeOfValues }) { + const useStyles = makeStyles(() => ({ + tableCell: { + width: name === 'value' ? '50%' : '30%', + height: 20, + padding: '1px', + }, + input: { + width: 90, + height: 20, + padding: '1px', + }, + })); const classes = useStyles(); const { isEditMode } = row; - // console.log(index, row, name, onChange, type, typeOfValues); + // console.log(index, row, name, type, typeOfValues); return ( diff --git a/src/Components/DataMapping.tsx b/src/Components/DataMapping.tsx index 2704c7da6d172bc6dda67cb9be57c2d75b7a2285..6ae0aa148a13ba234b54c98909df5afe8e48d82d 100644 --- a/src/Components/DataMapping.tsx +++ b/src/Components/DataMapping.tsx @@ -5,10 +5,11 @@ import { IconButton } from '@material-ui/core'; import AddCircleOutlineIcon from '@material-ui/icons/AddCircleOutline'; import EditableTable from './EditableTable'; import state from '../store/state'; +import SidebarTooltip from './SidebarTooltip'; export default function DataMappingComponent(props) { const { element } = props; - // console.log(props); + const setOpenSnackbar = state((state) => state.setOpenSnackbar); const setSelectedElement = state((state) => state.setSelectedElement); const [dataMapping, setDataMapping] = React.useState([]); @@ -19,6 +20,7 @@ export default function DataMappingComponent(props) { useEffect(() => { setElementL(element); + if (element.data && element.data.data_mapping) { setDataMapping(element.data.data_mapping); } @@ -72,7 +74,13 @@ export default function DataMappingComponent(props) { return (
- Data Mapping + + Data Mapping + + ([]); + const setSelectedElement = state((state) => state.setSelectedElement); + + useEffect(() => { + setDefaultInputs(element.default_inputs ? element.default_inputs : []); + }, [element.id, element]); + + const addDefaultInputs = () => { + const el = element as EwoksRFNode; + const elIn = el.default_inputs; + + if (elIn && elIn[elIn.length - 1] && elIn[elIn.length - 1].id === '') { + // console.log('should not ADD default'); + } else { + setSelectedElement( + { + ...element, + default_inputs: [...elIn, { id: '', name: '', value: '' }], + }, + 'fromSaveElement' + ); + } + }; + + const defaultInputsChanged = (table) => { + setSelectedElement( + { + ...element, + default_inputs: table.map((dval) => { + return { + id: dval.name, + name: dval.name, + value: dval.value, + }; + }), + }, + 'fromSaveElement' + ); + }; + + return ( +
+ +
+ Default Inputs + addDefaultInputs()} + > + + +
+
+ + {defaultInputs.length > 0 && ( + + )} +
+ ); +} diff --git a/src/Components/DraggableDialog.tsx b/src/Components/DraggableDialog.tsx index a4b0fb976a1be9b74d70005bc4a9a0ffb200615a..e370d15c8cb2ea33fdd2eebc994c01d289241527 100644 --- a/src/Components/DraggableDialog.tsx +++ b/src/Components/DraggableDialog.tsx @@ -33,6 +33,7 @@ export default function DraggableDialog(props) { const [name, setName] = React.useState(''); const [callbackProps, setCallbackProps] = React.useState({}); const graphRF = state((state) => state.graphRF); + const setOpenSnackbar = state((state) => state.setOpenSnackbar); const [selection, setSelection] = React.useState('ewoks'); @@ -56,9 +57,17 @@ export default function DraggableDialog(props) { }; const handleSave = () => { - setIsOpen(false); - // console.log(name, graph, callbackProps); - props.setValue(name, graph, callbackProps); + if (name) { + setIsOpen(false); + // console.log(name, graph, callbackProps); + props.setValue(name, graph, callbackProps); + } else { + setOpenSnackbar({ + open: true, + text: 'Please put a Name for the parameter!', + severity: 'warning', + }); + } }; const handleChange = ( @@ -112,7 +121,7 @@ export default function DraggableDialog(props) {
+ } aria-controls="panel1a-content" - id="panel1a-header" > Edit{' '} @@ -37,8 +40,8 @@ function EditElement(props) { : 'Graph'} - -
+ + {'source' in element ? ( ) : 'position' in element ? ( diff --git a/src/Components/EditElementStyle.tsx b/src/Components/EditElementStyle.tsx index f535b5467ab7603bcf6748abda8a4d3925379cad..ae23e52502a780c9e73232d8b40324d64e3d337c 100644 --- a/src/Components/EditElementStyle.tsx +++ b/src/Components/EditElementStyle.tsx @@ -15,31 +15,32 @@ export default function EditElementStyle() { ); return ( - - } - aria-controls="panel1a-content" - id="panel1a-header" - > - - Styling{' '} - {'position' in selectedElement - ? 'Node' - : 'source' in selectedElement - ? 'Link' - : 'Graph'} - - - - - {'position' in selectedElement && ( - - )} - {'source' in selectedElement && ( - - )} - - - + ('position' in selectedElement || 'source' in selectedElement) && ( + + } + aria-controls="panel1a-content" + > + + Styling{' '} + {'position' in selectedElement + ? 'Node' + : 'source' in selectedElement + ? 'Link' + : 'Graph'} + + + +
+ {'position' in selectedElement && ( + + )} + {'source' in selectedElement && ( + + )} + +
+
+ ) ); } diff --git a/src/Components/EditLinkStyle.tsx b/src/Components/EditLinkStyle.tsx index 31757648f76647cd31da89208e7dc7a435b75972..9f0dba167b2a5aed38eabd8eb51270663aa7d47d 100644 --- a/src/Components/EditLinkStyle.tsx +++ b/src/Components/EditLinkStyle.tsx @@ -144,6 +144,7 @@ export default function EditLinkStyle(props) { 'step', 'default', 'bendingText', + 'multilineText', 'getAround', ].map((text) => ( diff --git a/src/Components/EditableTable.tsx b/src/Components/EditableTable.tsx index 2b2333f3aae2b108fbd8e6e123dce150ecf9acc2..5787fbfa75fed4c8b969a444a75d1406b30f21a4 100644 --- a/src/Components/EditableTable.tsx +++ b/src/Components/EditableTable.tsx @@ -1,3 +1,8 @@ +/* eslint-disable sonarjs/cognitive-complexity */ +/* + The table that is used to pass parameters for default-values, conditions and data-mapping. + Its cells can change depending on the kind of input and the parent-component params. +*/ import React, { useEffect } from 'react'; import { makeStyles } from '@material-ui/core/styles'; import Table from '@material-ui/core/Table'; @@ -9,10 +14,11 @@ import Paper from '@material-ui/core/Paper'; import IconButton from '@material-ui/core/IconButton'; import EditIcon from '@material-ui/icons/EditOutlined'; import DoneIcon from '@material-ui/icons/DoneAllTwoTone'; -import RevertIcon from '@material-ui/icons/NotInterestedOutlined'; import { FormControl, MenuItem, Select } from '@material-ui/core'; import CustomTableCell from './CustomTableCell'; import DraggableDialog from './DraggableDialog'; +import DeleteIcon from '@material-ui/icons/Delete'; +import state from '../store/state'; const useStyles = makeStyles(() => ({ root: { @@ -24,7 +30,7 @@ const useStyles = makeStyles(() => ({ table: { padding: '1px', minWidth: 160, - maxWidth: 270, + // maxWidth: 270, wordBreak: 'break-all', }, selectTableCell: { @@ -61,6 +67,7 @@ function EditableTable(props) { const [openDialog, setOpenDialog] = React.useState(false); const [dialogContent, setDialogContent] = React.useState({}); const [disableSelectType, setDisableSelectType] = React.useState(false); + const setOpenSnackbar = state((state) => state.setOpenSnackbar); const { defaultValues } = props; const { headers } = props; @@ -94,7 +101,7 @@ function EditableTable(props) { }) : [] ); - setDisableSelectType(false); + setDisableSelectType(true); }, [defaultValues]); const classes = useStyles(); @@ -110,12 +117,7 @@ function EditableTable(props) { }); }; - const onToggleEditMode = (id, index, command) => { - // console.log(props, id, rows, props.defaultValues, command, typeOfInputs); - if (command === 'edit') { - setDisableSelectType(true); - // console.log('disable'); - } + function onToggleEditMode(id, index, command) { if (command === 'edit' && ['list', 'dict'].includes(typeOfInputs[index])) { let initialValue: string | [] | {} = ''; @@ -143,26 +145,48 @@ function EditableTable(props) { callbackProps: { rows, id }, }); } - setRows(() => { - return rows.map((row) => { - if (row.id === id) { - return { - ...row, - id: row.name.replace(' ', '_'), - // value: row.value, - isEditMode: !row.isEditMode, - }; - } - return row; + + const oldRows = [...rows].filter((row, inde) => index !== inde); + + if ( + rows[index].name !== '' && + oldRows.map((oldro) => oldro.name).includes(rows[index].name) + ) { + setOpenSnackbar({ + open: true, + text: 'Not allowed to assign the same property TWICE!', + severity: 'error', }); - }); + // setRows(oldRows); + } else { + setRows(() => { + return rows.map((row) => { + if (row.id === id) { + return { + ...row, + id: row.name.replace(' ', '_') || '', + // value: row.value, + isEditMode: !row.isEditMode, + }; + } + return row; + }); + }); + if (command === 'done') { + // console.log(rows); + props.valuesChanged(rows); + setRows(rows); + } + } if (command === 'done') { setDisableSelectType(true); - props.valuesChanged(rows); + } else { + setDisableSelectType(false); } - }; + } const onChange = (e, row, index) => { + // console.log(e, e.target.value, e.target.name, row, index); if ( ['string', 'bool', 'number', 'boolean', 'null'].includes(typeOfInputs[0]) ) { @@ -203,7 +227,17 @@ function EditableTable(props) { } }; - const onRevert = (id) => { + // const onRevert = (id) => { + // const newRows = rows.filter((row) => { + // return row.id !== id; + // }); + + // setRows(newRows); + // props.valuesChanged(newRows); + // setDisableSelectType(false); + // }; + + const onDelete = (id) => { const newRows = rows.filter((row) => { return row.id !== id; }); @@ -223,11 +257,19 @@ function EditableTable(props) { return rowe; }); setRows(newRows); - props.valuesChanged(newRows); + // props.valuesChanged(newRows); } const tOfI = [...typeOfInputs]; tOfI[index] = e.target.value; setTypeOfInputs(tOfI); + if (['dict', 'list'].includes(e.target.value)) { + showEditableDialog({ + name: row.id, + title: e.target.value === 'list' ? 'Edit list' : 'Edit dict', + graph: e.target.value === 'list' ? [] : {}, + callbackProps: { rows, id: row.id }, + }); + } }; const setRowValue = (name, val, callbackProps) => { @@ -254,6 +296,11 @@ function EditableTable(props) { + {headers[0] !== 'Source' && ( + + Type + + )} {headers[0]} @@ -265,12 +312,13 @@ function EditableTable(props) { {rows.map((row, index) => ( - {headers[0] !== 'Source' && headers[1] !== 'Node_Id' && ( - - - Type - - + + {headers[0] !== 'Source' && ( +
+
handleClick(event, row[0].job_id)} - role="checkbox" - aria-checked={isItemSelected} - tabIndex={-1} - key={row[0].job_id} - selected={isItemSelected} - style={{ whiteSpace: 'nowrap' }} - > - - - - + - {row[0].workflow_id || row[1].workflow_id} - - {row[0].job_id} - - {formatedTime(row[0] && row[0].time)} - - - {formatedTime(row[1] && row[1].time)} - - {/* + + + handleClick(event, row[0].job_id) + } + /> + + + setOpenRow(row[0].job_id)} + > + {open && expandRow === row[0].job_id ? ( + + ) : ( + + )} + + + + {/* || row[1].workflow_id */} + {row[1].workflow_id} + + {row[0].job_id} + + {formatedTime(row[0] && row[0].time)} + + + {formatedTime(row[1] && row[1].time)} + + {/* {formatedTime( new Date( row[1].time.getTime() - row[0].time.getTime() ) )} */} - {row[0].process_id} - {row[0].user_name} - {row[0].host_name} - {/* {row[0].input_uris} + {row[0].process_id} + {row[0].user_name} + {row[0].host_name} + {/* {row[0].input_uris} {row[0].output_uris} */} - + + + + + + + Execution Events + +
+ + + Time + progress + outputs + inputs + type + error + error_traceback + error_message + node_id + task_id + task_uri + {/* id */} + + + + {eventsForWorflow.map((ev) => ( + + + {ev.time} + + {ev.progress} + + {ev.output_uris} + + + {ev.input_uris} + + + {ev.type} + + + {ev.error && ev.error.toString()} + + + {ev.error_traceback} + + + {ev.error_message} + + + {ev.node_id} + + + {ev.task_id} + + + {ev.task_uri} + + {/* + {ev.id} + */} + + ))} + +
+ + +
+ + ); })} {emptyRows > 0 && ( @@ -467,6 +637,26 @@ export default function EnhancedTable() { control={} label="Dense padding" /> + + + Edit Workflows + + + + + + ); } diff --git a/src/Components/GetFromServer.tsx b/src/Components/GetFromServer.tsx index 5c9744fc81b7b449b76726557ab239f8f07bb26a..cb211afe9c3367d54e1be8999deb2b6aa748c723 100644 --- a/src/Components/GetFromServer.tsx +++ b/src/Components/GetFromServer.tsx @@ -7,14 +7,16 @@ import GetFromServerButtons from './GetFromServerButtons'; const useStyles = DashboardStyle; -export default function GetFromServer() { +export default function GetFromServer(props) { const classes = useStyles(); + const { workflowIdInAutocomplete } = props; const [workflowId, setWorkflowId] = React.useState(''); const setInputValue = (workflowDetails) => { if (workflowDetails && workflowDetails.id) { setWorkflowId(workflowDetails.id || ''); + workflowIdInAutocomplete(workflowDetails.id || ''); } }; @@ -37,7 +39,10 @@ export default function GetFromServer() { /> - + ); } diff --git a/src/Components/GetFromServerButtons.tsx b/src/Components/GetFromServerButtons.tsx index abe815ca37694255834cda34dd34a253cc38241c..e794555780cf97ee053b169ab5681cbe8e298ffd 100644 --- a/src/Components/GetFromServerButtons.tsx +++ b/src/Components/GetFromServerButtons.tsx @@ -9,7 +9,7 @@ import { getWorkflow } from '../utils/api'; import ConfirmDialog from './ConfirmDialog'; export default function GetFromServerButtons(props) { - const { workflowId } = props; + const { workflowId, showButtons } = props; const setSubGraph = state((state) => state.setSubGraph); const setWorkingGraph = state((state) => state.setWorkingGraph); @@ -100,29 +100,33 @@ export default function GetFromServerButtons(props) { agreeCallback={getFromServer} disagreeCallback={disAgreeSaveWithout} /> - { - /* eslint-disable no-console */ - console.log('Getting from server'); - }} - > - - - { - /* eslint-disable no-console */ - console.log('Getting subgraph from server'); - }} - > - - + {showButtons[0] && ( + { + /* eslint-disable no-console */ + console.log('Getting from server'); + }} + > + + + )} + {showButtons[1] && ( + { + /* eslint-disable no-console */ + console.log('Getting subgraph from server'); + }} + > + + + )} ); } diff --git a/src/Components/GraphLabelComment.tsx b/src/Components/GraphLabelComment.tsx index e1479e05329cf042462c3b88b60fd042a1443e89..fb49360dc146c86ab8da23933059efd25a92235a 100644 --- a/src/Components/GraphLabelComment.tsx +++ b/src/Components/GraphLabelComment.tsx @@ -1,6 +1,6 @@ import React, { useEffect } from 'react'; -import { TextField } from '@material-ui/core'; +import { FormControl, InputLabel, OutlinedInput } from '@material-ui/core'; import DashboardStyle from '../layout/DashboardStyle'; import state from '../store/state'; import type { GraphDetails } from '../types'; @@ -65,7 +65,46 @@ export default function GraphLabelComment() { {/*
Label: {graphRF.graph.label}
*/} -
+ + Label + + + + Comment + + + + Category + + + {/*
-
-
+
*/} + {/*
-
+
*/} {/* DOC: if the inputs and outputs of the graph are needed
Inputs diff --git a/src/Components/LabelComment.tsx b/src/Components/LabelComment.tsx index d5018b429c018ce834be8671831d3becd5e3260a..8f41dd72633934c2e60a96a6edb7017ce5f15aa2 100644 --- a/src/Components/LabelComment.tsx +++ b/src/Components/LabelComment.tsx @@ -1,10 +1,16 @@ import React, { useEffect } from 'react'; import type { EwoksRFLink } from '../types'; -import { Box, Button, TextField } from '@material-ui/core'; +import { + FormControl, + InputLabel, + OutlinedInput, + TextField, +} from '@material-ui/core'; import DashboardStyle from '../layout/DashboardStyle'; import state from '../store/state'; import SidebarTooltip from './SidebarTooltip'; +import { Autocomplete } from '@material-ui/lab'; const useStyles = DashboardStyle; @@ -16,6 +22,10 @@ export default function LabelComment(props) { const [comment, setComment] = React.useState(''); const [label, setLabel] = React.useState(''); + const [labelChoices, setLabelChoices] = React.useState([ + 'use mappings', + 'use conditions', + ]); const setSelectedElement = state((state) => state.setSelectedElement); useEffect(() => { @@ -23,51 +33,32 @@ export default function LabelComment(props) { setLabel(element.data.label); setComment(element.data.comment); } else if ('source' in element) { - setLabel(element.label); - setComment(element.data && element.data.comment); - } - }, [element]); + const el = element as EwoksRFLink; + setLabel(el.label); + setComment(el.data && el.data.comment); - const useConditions = () => { - const el = element as EwoksRFLink; - const newLabel = - el.data.conditions.length > 0 - ? el.data.conditions - // .map((con) => con.source_output + ': ' + JSON.stringify(con.value)) - .map((con) => `${con.source_output}: ${JSON.stringify(con.value)}`) - .join(', ') - : ''; - setLabel(newLabel); - setSelectedElement( - { - ...element, - label: newLabel, - }, - 'fromSaveElement' - ); - }; + const mappings = + el.data.data_mapping.length > 0 + ? el.data.data_mapping + .map((con) => `${con.source_output}->${con.target_input}`) + .join(', ') + : ''; + const conditions = + el.data.conditions.length > 0 + ? el.data.conditions + .map( + (con) => `${con.source_output}: ${JSON.stringify(con.value)}` + ) + .join(', ') + : ''; - const useMapping = () => { - const el = element as EwoksRFLink; - const newLabel = - el.data.data_mapping.length > 0 - ? el.data.data_mapping - .map((con) => `${con.source_output}->${con.target_input}`) - .join(', ') - : ''; - setLabel(newLabel); - setSelectedElement( - { - ...element, - label: newLabel, - }, - 'fromSaveElement' - ); - }; + setLabelChoices([mappings, conditions, '...']); + } + }, [element]); const labelChanged = (event) => { - // console.log('label changed:', event.target.value); setLabel(event.target.value); + if ('position' in element) { const el = element; setSelectedElement( @@ -105,44 +96,81 @@ export default function LabelComment(props) { return ( <>
- - {Object.keys(element).includes('source') && ( - - - - - - - )} - + + { + setSelectedElement( + { + ...element, + label: newValue, + }, + 'fromSaveElement' + ); + }} + onInputChange={(event, newInputValue) => { + setSelectedElement( + { + ...element, + label: newInputValue, + }, + 'fromSaveElement' + ); + }} + renderInput={(params) => ( + + )} + /> + + + ) : ( + - + className={classes.detailsLabels} + > + + + )}
- - + Comment + + + {/* - + */}
); diff --git a/src/Components/LinkDetails.tsx b/src/Components/LinkDetails.tsx index 2ab47814186ac94330335437bcdec5122ae47134..cfc73be5f9daac78227dfc5b11a304928d169520 100644 --- a/src/Components/LinkDetails.tsx +++ b/src/Components/LinkDetails.tsx @@ -90,14 +90,9 @@ export default function LinkDetails(props) {
{!mapAllData && elementL.source && ( - -
- -
-
+
+ +
)}
{!onError && elementL.source && ( - -
- -
-
+
+ +
)}
diff --git a/src/Components/ManageWorkflows.tsx b/src/Components/ManageWorkflows.tsx index 8c2c89d9a0ba956abef2157464e50f507d85d13a..f3a90c6d11fc65c512b943e0a061d431527c5ae3 100644 --- a/src/Components/ManageWorkflows.tsx +++ b/src/Components/ManageWorkflows.tsx @@ -62,7 +62,10 @@ export default function ManageWorkflows() { - + diff --git a/src/Components/MenuPopover.tsx b/src/Components/MenuPopover.tsx new file mode 100644 index 0000000000000000000000000000000000000000..4cd0fa9d4333179db928169d311209cb3c176ea6 --- /dev/null +++ b/src/Components/MenuPopover.tsx @@ -0,0 +1,37 @@ +import Popover from '@material-ui/core/Popover'; +import SaveGetFromDisk from '../Components/SaveGetFromDisk'; +import GetFromServerButtons from './GetFromServerButtons'; + +export default function MenuPopover({ + anchorEl, + handleClose, + workflowIdInTextbox, +}) { + const open = Boolean(anchorEl); + const id = open ? 'simple-popover' : undefined; + + return ( +
+ + + + +
+ ); +} diff --git a/src/Components/NodeDetails.tsx b/src/Components/NodeDetails.tsx index e2a63f2ca80696cdec13f01084654fe0df6749c6..5c525c5ba83b28a23b35ae683f7b2bd4a93fea71 100644 --- a/src/Components/NodeDetails.tsx +++ b/src/Components/NodeDetails.tsx @@ -1,6 +1,6 @@ import React, { useEffect } from 'react'; -import type { DataMapping, EwoksRFNode, Inputs } from '../types'; +import type { DataMapping, EwoksRFNode } from '../types'; import AddCircleOutlineIcon from '@material-ui/icons/AddCircleOutline'; import EditableTable from './EditableTable'; // import EditIcon from '@material-ui/icons/EditOutlined'; DONT DELETE @@ -20,6 +20,7 @@ import state from '../store/state'; import SidebarTooltip from './SidebarTooltip'; import { OpenInBrowser } from '@material-ui/icons'; import LabelComment from './LabelComment'; +import DefaultInputs from './DefaultInputs'; const useStyles = DashboardStyle; @@ -37,7 +38,6 @@ export default function NodeDetails(props) { const setSelectedElement = state((state) => state.setSelectedElement); // const selectedElement = state((state) => state.selectedElement); // const [editProps, setEditProps] = React.useState(false); - const [defaultInputs, setDefaultInputs] = React.useState([]); const [inputsComplete, setInputsComplete] = React.useState(false); const [advanced, setAdvanced] = React.useState(false); const [defaultErrorNode, setDefaultErrorNode] = React.useState( @@ -92,7 +92,6 @@ export default function NodeDetails(props) { // setDefaultErrorAttributes(element.default_error_attributes); setDataMapping(element.default_error_attributes?.data_mapping); setMapAllData(element.default_error_attributes?.map_all_data || false); - setDefaultInputs(element.default_inputs ? element.default_inputs : []); }, [element.id, element]); const propChanged = (propKeyValue) => { @@ -103,38 +102,6 @@ export default function NodeDetails(props) { }); }; - const addDefaultInputs = () => { - const el = element as EwoksRFNode; - const elIn = el.default_inputs; - if (elIn && elIn[elIn.length - 1] && elIn[elIn.length - 1].id === '') { - // console.log('should not ADD default'); - } else { - setSelectedElement( - { - ...element, - default_inputs: [...elIn, { id: '', name: '', value: '' }], - }, - 'fromSaveElement' - ); - } - }; - - const defaultInputsChanged = (table) => { - setSelectedElement( - { - ...element, - default_inputs: table.map((dval) => { - return { - id: dval.name, - name: dval.name, - value: dval.value, - }; - }), - }, - 'fromSaveElement' - ); - }; - const inputsCompleteChanged = (event) => { setInputsComplete(event.target.checked); setSelectedElement( @@ -228,33 +195,9 @@ export default function NodeDetails(props) { marginBottom: '10px', }} > -
- - -
- Default Inputs - addDefaultInputs()} - > - - -
-
+ + - {defaultInputs.length > 0 && ( - - )} -

Advanced @@ -339,7 +282,10 @@ export default function NodeDetails(props) { specific node is based on. If you need to have them create a new Task with the appropriete properties and use it.`} > - + } aria-controls="panel1a-content" diff --git a/src/Components/TableCellInEditMode.tsx b/src/Components/TableCellInEditMode.tsx index e63af45b8cb54601530491461a0fa649c7b05cfe..64b8450d20621db7a5acbccab73bdd08eeeefcb7 100644 --- a/src/Components/TableCellInEditMode.tsx +++ b/src/Components/TableCellInEditMode.tsx @@ -1,14 +1,20 @@ +/* + The cell within a table when the row is in edit mode. + Provides different input for any selected type (number, string, list etc) +*/ import React, { useEffect } from 'react'; import { makeStyles } from '@material-ui/core/styles'; import Input from '@material-ui/core/Input'; import { + FormControl, FormControlLabel, - MenuItem, Radio, RadioGroup, - Select, + TextField, } from '@material-ui/core'; -import CellEditInJson from './CellEditInJson'; +// Keep the following if edit on the table is needed +// import CellEditInJson from './CellEditInJson'; +import { Autocomplete } from '@material-ui/lab'; const useStyles = makeStyles(() => ({ tableCell: { @@ -33,7 +39,11 @@ function TableCellInEditMode(propsIn) { useEffect(() => { // console.log(row); - setBoolVal(row.value !== null ? row.value.toString() : 'null'); + setBoolVal( + row.value !== null && row.value !== undefined + ? row.value.toString() + : 'null' + ); }, [row.value, row]); const onChangeBool = (e, row, index) => { @@ -49,43 +59,51 @@ function TableCellInEditMode(propsIn) { }; return type === 'dict' || type === 'list' || type === 'object' ? ( - - ) : // onChange(edit, row, index)} - // // onAdd={(add) => onChange(add, row, index)} - // defaultValue="object" - // // onDelete={(del) => onChange(del, row, index)} - // // onSelect={(sel) => onChange(sel, row, index)} - // quotesOnKeys={false} - // style={{ backgroundColor: 'rgb(59, 77, 172)' }} - // displayDataTypes - // // defaultValue={object} - // /> - type === 'select' ? ( - + // + {JSON.stringify(row[name])} + ) : // + typeOfValues.type === 'select' ? ( + <> + + + onChange({ target: { value: val, name } }, row, index) + } + onInputChange={(e, val) => + onChange({ target: { value: val, name } }, row, index) + } + // onInputChange={(event, newInputValue) => {}} + renderInput={(params) => ( + + )} + /> + + {/* */} + ) : type === 'bool' || type === 'boolean' ? ( + + +
+ {label} +
+
+ + ); +} + +export default multilineText; diff --git a/src/CustomNodes/ExecutionStepsNode.tsx b/src/CustomNodes/ExecutionStepsNode.tsx index 41ed0548c6c337ea1fcc3888c1afebe007cf6dae..b106af44be86dbde932bf18b5851832b41a89e6a 100644 --- a/src/CustomNodes/ExecutionStepsNode.tsx +++ b/src/CustomNodes/ExecutionStepsNode.tsx @@ -1,8 +1,13 @@ +/* +A kind of node to appear on the canvas carrying the number of the +step that has been executed. +*/ import { style } from './NodeStyle'; import state from '../store/state'; function ExecutionStepsNode(args) { + // console.log(args); const customTitle = { ...style.title, wordWrap: 'break-word', @@ -10,7 +15,7 @@ function ExecutionStepsNode(args) { backgroundColor: '#ced3ee', textAlign: 'center', padding: '1px', - color: '#4493dd', // TODO: red for failed events-workflows + color: args.data.event.error ? 'red' : '#4493dd', // TODO: red for failed events-workflows fontSize: '1.2em', }; diff --git a/src/index.tsx b/src/index.tsx index 0c99e424171d056bdb4da7419e4f33da0c5f410d..d11ad38f4c072dfb0dd904ccd2938b52cfbb405c 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,14 +1,24 @@ import { StrictMode } from 'react'; import ReactDOM from 'react-dom'; +import { BrowserRouter, Routes, Route } from 'react-router-dom'; import 'normalize.css'; import './styles/index.css'; import App from './App'; +// import SignUp from './layout/SignUp'; +import EwoksUiInfo from './Components/EwoksUiInfo'; +import ExecutionTable from './Components/ExecutionTable'; ReactDOM.render( - + + + } /> + } /> + } /> + + , document.querySelector('#root') ); diff --git a/src/layout/Canvas.tsx b/src/layout/Canvas.tsx index 040c588e9342bb14f7723ac93d8e595e27b41f90..e985e01644cf6b447bdf6eb055ba3c87d680a53f 100644 --- a/src/layout/Canvas.tsx +++ b/src/layout/Canvas.tsx @@ -14,6 +14,7 @@ import ReactFlow, { } from 'react-flow-renderer'; import { makeStyles, createStyles, Theme } from '@material-ui/core/styles'; import bendingText from '../CustomEdges/BendingTextEdge'; +import multilineText from '../CustomEdges/MultilineTextEdge'; import getAround from '../CustomEdges/GetAroundEdge'; import FunctionNode from '../CustomNodes/FunctionNode'; @@ -45,6 +46,7 @@ const useStyles = makeStyles((theme: Theme) => const edgeTypes = { bendingText, + multilineText, getAround, }; @@ -197,7 +199,15 @@ function Canvas() { const onNodeClick = (event, element?: Node) => { const graphElement: EwoksRFNode = nodes.find((el) => el.id === element.id); - setSelectedElement(graphElement); + + if ( + !( + graphElement.task_type === 'executionSteps' && + graphElement.type === 'executionSteps' + ) + ) { + setSelectedElement(graphElement); + } }; const onEdgeClick = (event, element?: Edge) => { diff --git a/src/layout/Dashboard.tsx b/src/layout/Dashboard.tsx index 3073108d81e020d7298fc929ad0f5ad70bd7be91..7b00c6c9769e520f383e2c311d3ea68cc0069996 100644 --- a/src/layout/Dashboard.tsx +++ b/src/layout/Dashboard.tsx @@ -1,22 +1,19 @@ import React, { useState, useEffect } from 'react'; import clsx from 'clsx'; import CssBaseline from '@material-ui/core/CssBaseline'; -import Drawer from '@material-ui/core/Drawer'; import AppBar from '@material-ui/core/AppBar'; import Toolbar from '@material-ui/core/Toolbar'; -import Divider from '@material-ui/core/Divider'; import Paper from '@material-ui/core/Paper'; -import MenuIcon from '@material-ui/icons/Menu'; -import ChevronLeftIcon from '@material-ui/icons/ChevronLeft'; import FiberNew from '@material-ui/icons/FiberNew'; import ImportContactsIcon from '@material-ui/icons/ImportContacts'; import Sidebar from './sidebar'; import { ReactFlowProvider } from 'react-flow-renderer'; +import { Link } from 'react-router-dom'; import Canvas from './Canvas'; import UndoRedo from '../Components/UndoRedo'; import GetFromServer from '../Components/GetFromServer'; -import { Fab, IconButton } from '@material-ui/core'; +import { Fab, IconButton, Typography } from '@material-ui/core'; import SettingsIcon from '@material-ui/icons/Settings'; import SimpleSnackbar from '../Components/Snackbar'; import SettingsInfoDrawer from '../Components/SettingsInfoDrawer'; @@ -25,7 +22,6 @@ import LinearSpinner from '../Components/LinearSpinner'; import ExecuteWorkflow from '../Components/ExecuteWorkflow'; import Tooltip from '@material-ui/core/Tooltip'; import DashboardStyle from './DashboardStyle'; -import SaveGetFromDisk from '../Components/SaveGetFromDisk'; import SaveToServer from '../Components/SaveToServer'; import tooltipText from '../Components/TooltipText'; import state from '../store/state'; @@ -34,6 +30,9 @@ import FormDialog from '../Components/FormDialog'; import ConfirmDialog from '../Components/ConfirmDialog'; import { ErrorBoundary } from 'react-error-boundary'; import ErrorFallback from '../Components/General/ErrorFallback'; +import MenuPopover from '../Components/MenuPopover'; +import MoreVertIcon from '@material-ui/icons/MoreVert'; +import { ReflexContainer, ReflexSplitter, ReflexElement } from 'react-reflex'; const useStyles = DashboardStyle; @@ -44,15 +43,15 @@ export default function Dashboard() { const redoF = React.useRef(null); const saveToServerF = React.useRef(null); - const [open, setOpen] = React.useState(true); - const [openDrawers, setOpenDrawers] = React.useState(true); - const [openSettings, setOpenSettings] = React.useState(false); - const [openInfo, setOpenInfo] = React.useState(false); + const [openDrawers, setOpenDrawers] = useState(true); + const [openSettings, setOpenSettings] = useState(false); + const [openInfo, setOpenInfo] = useState(false); + const [workflowIdInTextbox, setWorkflowIdInTextbox] = useState(''); const setWorkingGraph = state((state) => state.setWorkingGraph); const gettingFromServer = state((state) => state.gettingFromServer); const inExecutionMode = state((state) => state.inExecutionMode); const graphRF = state((state) => state.graphRF); - const [openSaveDialog, setOpenSaveDialog] = React.useState(false); + const [openSaveDialog, setOpenSaveDialog] = useState(false); const initializedGraph = state((state) => state.initializedGraph); const openSettingsDrawer = state((state) => state.openSettingsDrawer); const setOpenSettingsDrawer = state((state) => state.setOpenSettingsDrawer); @@ -60,6 +59,7 @@ export default function Dashboard() { const setCanvasGraphChanged = state((state) => state.setCanvasGraphChanged); const [openAgreeDialog, setOpenAgreeDialog] = useState(false); const undoIndex = state((state) => state.undoIndex); + const [anchorEl, setAnchorEl] = useState(null); useEffect(() => { // console.log(openDrawers); @@ -113,18 +113,11 @@ export default function Dashboard() { }; const handleOpenInfo = () => { - setOpenInfo(true); + // setOpenInfo(true); setOpenSettings(false); - setOpenDrawers(true); + // setOpenDrawers(true); }; - const handleDrawerOpen = () => { - setOpen(true); - // setEditing(!editing); - }; - const handleDrawerClose = () => { - setOpen(false); - }; const fixedHeightPaper = clsx(classes.paper, classes.fixedHeight); const handleKeyDown = (event) => { @@ -154,172 +147,230 @@ export default function Dashboard() { setOpenAgreeDialog(false); }; + const handleClick = (event: React.MouseEvent) => { + setAnchorEl(event.currentTarget); + }; + + const handleClose = () => { + setAnchorEl(null); + }; + + function workflowIdInAutocomplete(id) { + setWorkflowIdInTextbox(id); + } + return ( -
- - - - - +
- - - - - - - - - - - - - - - - - - - -
- -
- -
- - - -
- - - - - - - + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ + + + + + + + +
+
+ + + + + + + - - - - - - - - - - - + {/* onClick={handleOpenInfo} */} + + + + + + + + + + + + + +
+ -
- - - -
- - - - + + + {/* */} + -
-
+ {/* */} + + {/* */} +
+
- - {gettingFromServer && } + +
+
- - ( - - )} - // resetKeys={[]} - // onError={() => console.log()} - > - - - - -
+ + {gettingFromServer && } + + + ( + + )} + // resetKeys={[]} + // onError={() => console.log()} + > + + + + +
+ - -
+ {/* */} + {/*
*/} + + ); } diff --git a/src/layout/DashboardStyle.js b/src/layout/DashboardStyle.js index e5718411e10fb234da58a5708288e138a6b98138..2c95214440e59dd168520624ff5723b455913591 100644 --- a/src/layout/DashboardStyle.js +++ b/src/layout/DashboardStyle.js @@ -57,7 +57,7 @@ const DashboardStyle = makeStyles((theme) => ({ }, appBarShift: { marginLeft: drawerWidth, - width: `calc(100% - ${drawerWidth}px)`, + // width: `calc(100% - ${drawerWidth}px)`, transition: theme.transitions.create(['width', 'margin'], { easing: theme.transitions.easing.sharp, duration: theme.transitions.duration.enteringScreen, @@ -117,7 +117,7 @@ const DashboardStyle = makeStyles((theme) => ({ }, detailsLabels: { - margin: '8px 0px', + padding: '8px 0px', wordBreak: 'break-word', }, @@ -128,6 +128,7 @@ const DashboardStyle = makeStyles((theme) => ({ executionSide: { margin: '8px 5px', wordBreak: 'break-word', + width: '98%', }, })); diff --git a/src/layout/SignUp.tsx b/src/layout/SignUp.tsx index 114b75333dca4822501c39528f1b72b6b1e7fd44..94025ef334ca0380ac679b169aec4109b0879161 100644 --- a/src/layout/SignUp.tsx +++ b/src/layout/SignUp.tsx @@ -4,7 +4,7 @@ import CssBaseline from '@material-ui/core/CssBaseline'; import TextField from '@material-ui/core/TextField'; import FormControlLabel from '@material-ui/core/FormControlLabel'; import Checkbox from '@material-ui/core/Checkbox'; -import Link from '@material-ui/core/Link'; +// import Link from '@material-ui/core/Link'; import Grid from '@material-ui/core/Grid'; import Box from '@material-ui/core/Box'; import LockOutlinedIcon from '@material-ui/icons/LockOutlined'; @@ -13,6 +13,7 @@ import Container from '@material-ui/core/Container'; import { createTheme, ThemeProvider } from '@material-ui/core/styles'; import ArrowForwardIosIcon from '@material-ui/icons/ArrowForwardIos'; import { Fab, IconButton } from '@material-ui/core'; +import { Link } from 'react-router-dom'; const theme = createTheme(); @@ -48,17 +49,64 @@ export default function SignUp(props) { Welcome to the{' '} Ewoks-UI for - managing your Workflows. Get started with a graph where Ewoks-UI - describes itself + managing your Workflows. Select to Edit or Monitor or get + started with a graph where Ewoks-UI describes itself: - + + + + Edit Workflows + + + + + + + + + Monitor Workflows + + + + + + + - tutorial_Graph + Tutorial Workflow - - Already have an account? Sign in - + {/* */} + Already have an account? Sign in + {/* */} diff --git a/src/layout/sidebar.tsx b/src/layout/sidebar.tsx index 8d2232537149eeda64a34c3c816777556526961e..10f45a77e9544e8e4a1e8abd46688a9fc6ba6ad3 100644 --- a/src/layout/sidebar.tsx +++ b/src/layout/sidebar.tsx @@ -61,7 +61,6 @@ export default function Sidebar() { const [openExecutionDetails, setOpenExecutionDetails] = useState( false ); - const graphRF = state((state) => state.graphRF); const setGraphRF = state((state) => state.setGraphRF); const workingGraph = state((state) => state.workingGraph); @@ -326,6 +325,7 @@ export default function Sidebar() { {inExecutionMode ? (
+
) : ( <> @@ -335,11 +335,12 @@ export default function Sidebar() { } aria-controls="panel1a-content" - id="panel1a-header" + id="Accordions-sidebar" > ({ currentExecutionEvent: 0, setCurrentExecutionEvent: (indexOfEvent) => { + // console.log(indexOfEvent); set((state) => ({ ...state, currentExecutionEvent: indexOfEvent, diff --git a/src/store/executedEvents.ts b/src/store/executedEvents.ts index 1f51b562889cf6777c0713a7ee0d603184a84576..6450cd8e359677cef83697eb131d916e439cf70a 100644 --- a/src/store/executedEvents.ts +++ b/src/store/executedEvents.ts @@ -1,5 +1,7 @@ import type { Event } from '../types'; +// DOC: All the events that came in during live executions. These events keep +// pilling-up while the app is up front-back. When should that stop; const executedEvents = (set, get) => ({ executedEvents: [] as Event[], diff --git a/src/store/executingEvents.ts b/src/store/executingEvents.ts index e546e6090d72eb1553dc0e01bf6096c4bb89c7ac..c6320606d0f343203d3f534e07671a5896891767 100644 --- a/src/store/executingEvents.ts +++ b/src/store/executingEvents.ts @@ -119,6 +119,8 @@ const executingEvents = (set, get) => ({ // ExecutionStepNode with the old number before putting the new node // If not in execution dont affect the canvas + // TODO: if not the specific job_id dont afect the canvas in case of viewing + // the same workflow_id but another job while some others are being executed if (prevState.inExecutionMode) { set((state) => ({ ...state, @@ -136,9 +138,7 @@ const executingEvents = (set, get) => ({ { data: { label: `${tempLabel},${(execEvent.id as unknown) as string}`, - node_id: execEvent.node_id, - type: execEvent.type, - values: { a: 1, b: 2 }, + event: execEvent, }, id: execEvent.time, task_type: 'executionSteps', diff --git a/src/store/graphRF.ts b/src/store/graphRF.ts index 352b6a991518f975dbc82baa22970dac83de3867..72d39384a44e75200670f092e7d738315b5e494c 100644 --- a/src/store/graphRF.ts +++ b/src/store/graphRF.ts @@ -16,7 +16,7 @@ const graphRF = (set, get) => ({ graphRF: tutorialGraph, setGraphRF: (graphRF, isChangeToCanvasGraph) => { - if (isChangeToCanvasGraph) { + if (isChangeToCanvasGraph && !get().inExecutionMode) { get().setCanvasGraphChanged(true); } else if (isChangeToCanvasGraph === false) { get().setCanvasGraphChanged(false); diff --git a/src/store/selectedElement.ts b/src/store/selectedElement.ts index 42496b388513f4f6c7eccc7f2f0358d7a91d21b6..1a3dc882005e468444c893af959b98e67606afe7 100644 --- a/src/store/selectedElement.ts +++ b/src/store/selectedElement.ts @@ -48,7 +48,7 @@ const selectedElement = (set, get) => ({ graph: element, nodes: initializeNodes(nodes), links: links.map((link) => { - return { ...link, selected: false }; + return { ...link, selected: false }; // TODO: examine this after update }), }; diff --git a/src/styles/base.css b/src/styles/base.css index 9a1be04f06da4dd864f03c2fad4eb0ec2ef914f8..a26d0ba5e24eff54c4f03e74a38e58cdb47c286f 100644 --- a/src/styles/base.css +++ b/src/styles/base.css @@ -97,3 +97,13 @@ abbr[title] { .MuiAccordionDetails-root { padding: 4px; } + +#Accordions-sidebar { + margin-left: 2px; + border-radius: 10px 0px 0px 10px; +} +#add-nodes-accordion { + width: 100%; + /* margin-left: 2px; */ + border-radius: 10px 0px 0px 10px; +} diff --git a/src/styles/sidebar.css b/src/styles/sidebar.css index 4aae0a00852e1d69709acf0cabedc4809a6e8d0d..d9df4ab2e51ffd50a81c1993335186c933b238d4 100644 --- a/src/styles/sidebar.css +++ b/src/styles/sidebar.css @@ -6,6 +6,7 @@ /* display: flex; */ height: 100%; flex-wrap: wrap; + margin-top: 70px; /* background-color: DodgerBlue; */ } diff --git a/src/utils/calcTasksForLink.ts b/src/utils/calcTasksForLink.ts index 159cc625950455a0438c3670117ae35a528ccd13..23eec4b9a9793976e9973cb428ab321292b0fa6e 100644 --- a/src/utils/calcTasksForLink.ts +++ b/src/utils/calcTasksForLink.ts @@ -19,7 +19,7 @@ export function calcTasksForLink( } if (targetTmp) { - sourceTask = calcTask('target', targetTmp, tasks, newNodeSubgraphs); + targetTask = calcTask('target', targetTmp, tasks, newNodeSubgraphs); } // if not found app does not break, put an empty skeleton @@ -30,6 +30,7 @@ export function calcTasksForLink( optional_input_names: [], required_input_names: [], }; + return [sourceTask, targetTask]; } diff --git a/src/utils/curateGraph.ts b/src/utils/curateGraph.ts index 647c304cf51bcb4925a36b8909bf9e10fb4831ce..e539e9c21c6678075b0e1d130c669ab66077fb5d 100644 --- a/src/utils/curateGraph.ts +++ b/src/utils/curateGraph.ts @@ -7,6 +7,7 @@ function curateGraph(graphRF): GraphRF { for (const nod of graphRFCurrated.nodes) { // INFO: Remove empty lines in table for nodes and links + // TODO: removes only the last not all empty... if ( nod.default_inputs && nod.default_inputs.length > 0 && @@ -41,6 +42,7 @@ function curateGraph(graphRF): GraphRF { lin.data.data_mapping.pop(); } } + return graphRFCurrated; } diff --git a/src/utils/toEwoksNodes.ts b/src/utils/toEwoksNodes.ts index e012f5f2cd827005e5d325600cccd297bb4e354f..062b8f3787204742809bd5902d7942ac005ea5ac 100644 --- a/src/utils/toEwoksNodes.ts +++ b/src/utils/toEwoksNodes.ts @@ -1,10 +1,31 @@ import type { EwoksNode, EwoksRFNode } from '../types'; +function cleanDefaultInputs(default_inputs) { + return ( + (default_inputs && + default_inputs.map((dIn) => { + return { + name: dIn.name, + value: + dIn.value === 'false' + ? false + : dIn.value === 'true' + ? true + : dIn.value === 'null' + ? null + : dIn.value, + }; + })) || + [] + ); +} + // EwoksRFNode --> EwoksNode for saving export function toEwoksNodes(nodes: EwoksRFNode[]): EwoksNode[] { const tempNodes: EwoksRFNode[] = [...nodes].filter( (nod) => !['graphInput', 'graphOutput', 'note'].includes(nod.task_type) ); + return tempNodes.map( ({ id, @@ -41,21 +62,7 @@ export function toEwoksNodes(nodes: EwoksRFNode[]): EwoksNode[] { default_error_attributes: default_error_node ? default_error_attributes : null, - default_inputs: - default_inputs && - default_inputs.map((dIn) => { - return { - name: dIn.name, - value: - dIn.value === 'false' - ? false - : dIn.value === 'true' - ? true - : dIn.value === 'null' - ? null - : dIn.value, - }; - }), + default_inputs: cleanDefaultInputs(default_inputs), uiProps: { nodeWidth, type, @@ -78,7 +85,7 @@ export function toEwoksNodes(nodes: EwoksRFNode[]): EwoksNode[] { // type: task_type, inputs_complete, task_generator: task_generator || null, - default_inputs, + default_inputs: cleanDefaultInputs(default_inputs), default_error_node, ddefault_error_attributes: default_error_node ? default_error_attributes