Skip to content

Commit

Permalink
Components for new executions
Browse files Browse the repository at this point in the history
  • Loading branch information
hvarg committed Mar 13, 2024
1 parent fbbcd89 commit 00d6f90
Show file tree
Hide file tree
Showing 14 changed files with 295 additions and 287 deletions.
22 changes: 14 additions & 8 deletions src/DISK/interfaces.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -119,10 +119,13 @@ export interface VariableOption {
commnet: string | null,
}

export interface LineOfInquiry extends DISKResource {
export interface LOICommon extends DISKResource {
updateCondition: number;
goalQuery: string;
question: Question | ObjectWithId;
}

export interface LineOfInquiry extends LOICommon {
dataQueryTemplate?: DataQueryTemplate;
workflowSeeds: WorkflowSeed[];
metaWorkflowSeeds: WorkflowSeed[];
Expand All @@ -132,7 +135,7 @@ export interface DataQueryTemplate {
endpoint: Endpoint | (Partial<Endpoint> & Pick<Endpoint, 'id'>);
template: string;
description: string;
variablesToShow: string;
variablesToShow: string[];
footnote: string;
}

Expand All @@ -155,7 +158,7 @@ export interface WorkflowSeed {

export type SeedBindings = Pick<WorkflowSeed, 'parameters' | 'inputs' | 'outputs'>;

export interface TriggeredLineOfInquiry extends LineOfInquiry{
export interface TriggeredLineOfInquiry extends LOICommon{
status: Status;
parentLoi: LineOfInquiry;
parentGoal: Goal;
Expand All @@ -180,15 +183,16 @@ export interface WorkflowInstantiation extends WorkflowSeed {
export interface Execution extends ExecutionRecord {
externalId: string ;
result: GoalResult ;
steps: ExecutionRecord ;
inputs: VariableBinding;
outputs: VariableBinding;
steps: ExecutionRecord[];
inputs: VariableBinding[];
outputs: VariableBinding[];

}

export interface GoalResult {
confidenceType: string;
confidenceValue: string;
confidenceValue: number;
extras: VariableBinding[];
}

export interface ExecutionRecord {
Expand Down Expand Up @@ -315,7 +319,9 @@ export type MultiValueAssignation = {
export type QuestionVariableAssignation = {
[questionURI:string] : {
values: string[],
type?: 'http://www.w3.org/2001/XMLSchema#anyURI' | 'http://www.w3.org/2001/XMLSchema#float' | 'http://www.w3.org/2001/XMLSchema#string'
type?: 'http://www.w3.org/2001/XMLSchema#anyURI'
| 'http://www.w3.org/2001/XMLSchema#float'
| 'http://www.w3.org/2001/XMLSchema#string'
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/components/DataQuery/DataQueryTemplateForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export const DataQueryTemplateForm = ({value,onChange, showErrors}:DataQueryTemp
if (value.description !== dataQueryExplanation) setDataQueryExplanation(value.description || "");
if (value.footnote !== tableFootnote) setTableFootnote(value.footnote || "");
if (value.template !== template) setTemplate(value.template || "");
if (value.variablesToShow !== tableVariables) setTableVariables(value.variablesToShow || "");
if (value.variablesToShow && value.variablesToShow.join(", ") !== tableVariables) setTableVariables(value.variablesToShow.join(", ") || "");
if (value.endpoint && value.endpoint.url && value.endpoint.url !== sourceUrl) setSourceUrl(value.endpoint.url);
if (showErrors) {
if (!value.endpoint || !value.endpoint.url) setErrorDataSource(true);
Expand Down Expand Up @@ -74,7 +74,7 @@ export const DataQueryTemplateForm = ({value,onChange, showErrors}:DataQueryTemp
description: dataQueryExplanation,
template: template,
footnote: tableFootnote,
variablesToShow: tableVariables,
variablesToShow: tableVariables.split(/, */g),
endpoint: {id:sourceID},
})
}, [dataQueryExplanation, template, tableFootnote, tableVariables, sourceID]);
Expand Down
89 changes: 39 additions & 50 deletions src/components/FileList.tsx
Original file line number Diff line number Diff line change
@@ -1,87 +1,76 @@
import { Box, Button, Dialog, DialogActions, DialogContent, DialogTitle, IconButton, Table, TableBody, TableCell, TableContainer, TableHead, TableRow} from "@mui/material"
import { Fragment, useEffect, useState } from "react";
import CloseIcon from '@mui/icons-material/Close';
import { LineOfInquiry, RunBinding, TriggeredLineOfInquiry, Workflow, WorkflowRun } from "DISK/interfaces";
import { Endpoint, Execution, LineOfInquiry, RunBinding, TriggeredLineOfInquiry, VariableBinding, Workflow, WorkflowInstantiation, WorkflowRun } from "DISK/interfaces";
import FileCopyIcon from '@mui/icons-material/FileCopy';
import { PrivateLink } from "./PrivateLink";

interface FileListProps {
type: 'input' | 'output',
tloi: TriggeredLineOfInquiry | null,
loi?: LineOfInquiry,
label: string,
renderFiles?: boolean,
}

interface RunStatus extends WorkflowRun {
source: string,
interface RunStatus extends Execution {
source: Endpoint,
}

export const FileList = ({type:displayType, tloi, loi, label: title, renderFiles} : FileListProps) => {
export const FileList = ({type:displayType, tloi, label: title, renderFiles} : FileListProps) => {
const [open, setOpen] = useState(false);
const [total, setTotal] = useState(0);
const [runs, setRuns] = useState<RunStatus[]>([]);

const getFileMap : (run:RunStatus|WorkflowRun) => {[name:string]: RunBinding} = (run) => {
const getFileMap : (run:RunStatus|Execution) => Record<string, VariableBinding> = (run) => {
if (displayType === 'input') {
let newInputs : {[name:string]: RunBinding} = {};
Object.keys(run.inputs || {}).forEach((inName) => {
let data = run.inputs[inName];
if (data.datatype == null || !data.datatype.startsWith("http://www.w3.org/2001/XMLSchema#s")) {
newInputs[inName] = run.inputs[inName];
}
});
return newInputs;
return (run.inputs || []).reduce<Record<string, VariableBinding>>((acc, binding) => {
acc[binding.variable] = binding;
return acc;
}, {});
}

if (!loi)
return (run.outputs ? run.outputs : {})

let doNoStore : string[] = [];
//TODO:
//[...loi.workflows, ...loi.metaWorkflows].forEach((wf) => {
// wf.bindings.forEach((b) => {
// if (b.binding === '_DO_NO_STORE_')
// doNoStore.push(b.variable);
// })
//});
let newOutputs : {[name:string]: RunBinding} = {};
Object.keys(run.outputs || {}).forEach((outName) => {
if (!doNoStore.some(n => outName.startsWith(n))) {
newOutputs[outName] = run.outputs[outName];
}

if (tloi) [...tloi.workflows, ...tloi.metaWorkflows].forEach((wf) => {
wf.outputs.forEach((b) => {
if (b.type === 'DROP')
doNoStore.push(b.variable);
})
});
return newOutputs;
return (run.outputs || []).reduce<Record<string, VariableBinding>>((acc, binding) => {
if (!doNoStore.some(n => n === binding.variable)) {
acc[binding.variable] = binding;
}
return acc;
}, {});
}

// Adds source and all runs
useEffect(() => {
if (tloi) {
let allWfs : Workflow[] = []; // TODO: [ ...(tloi.workflows ? tloi.workflows : []) , ...(tloi.metaWorkflows ? tloi.metaWorkflows : []) ];
let allWfs : WorkflowInstantiation[] = [ ...(tloi.workflows ? tloi.workflows : []) , ...(tloi.metaWorkflows ? tloi.metaWorkflows : []) ];
let allRuns : RunStatus[] = [];
let i = 0;
allWfs.forEach((wf:Workflow) => {
if (wf.runs !== undefined) {
Object.values(wf.runs).forEach((run:WorkflowRun) => {
let list = getFileMap(run);
let length = Object.keys(list).length;
if (length > 0) {
allRuns.push({
...run,
source: wf.source
});
i += length;
}
});
}
allWfs.forEach(wf => {
(wf.executions || []).forEach(run => {
let list = getFileMap(run);
let length = Object.keys(list).length;
if (length > 0) {
allRuns.push({
...run,
source: wf.source
});
i += length;
}
});
});
setTotal(i);
setRuns(allRuns);
}
}, [tloi])

const renderRunTitle = (run:RunStatus) => {
return run.id.replace(/.*#/,'').replace(/--.*/,'');
return run.externalId.replace(/.*#/,'').replace(/--.*/,'');
}

return (
Expand Down Expand Up @@ -113,16 +102,16 @@ export const FileList = ({type:displayType, tloi, loi, label: title, renderFiles
<TableBody>
{Object.keys(getFileMap(run)).map((id:string, i:number) => {
let fileMap = getFileMap(run);
let value: RunBinding = fileMap[id];
if (value.id == null)
let value: VariableBinding = fileMap[id];
if ((value.binding||[]).length === 0)
return null
let filename: string = value.id.replace(/.*#/, '').replace(/SHA[\d\w]{6}_/, '').replace(/-\w{24,25}$/, '');
let filename: string = value.binding[0].replace(/.*#/, '').replace(/SHA[\d\w]{6}_/, '').replace(/-\w{24,25}$/, '');
return <TableRow key={`row_${i}`}>
<TableCell key={`x_${i}`} sx={{padding: "0 10px", textAlign:"end", verticalAlign:"top"}}>
{i+1}
</TableCell>
<TableCell key={`y_${i}`} sx={{padding: "0 10px"}}>
<PrivateLink source={run.source} filename={filename} url={value.id} preview={renderFiles}/>
<PrivateLink source={run.source.url} filename={filename} url={value.binding[0]} preview={renderFiles}/>
{/*renderFile(run, id)*/}
</TableCell>
</TableRow>
Expand Down
2 changes: 1 addition & 1 deletion src/components/goals/GoalsPreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export const HypothesisPreview = ({hypothesis, displayDeleteButton=true, display
[...TLOIs].sort((t1, t2) => {
return new Date(t2.dateCreated!).getTime() - new Date(t1.dateCreated!).getTime();
}).forEach((t) => {
if (t.parentGoal.id === hypothesis.id && t.parentLoi.id && !usedLOIs.has(t.parentLoi.id)) {
if (t.parentLoi && t.parentGoal.id === hypothesis.id && t.parentLoi.id && !usedLOIs.has(t.parentLoi.id)) {
usedLOIs.add(t.parentLoi.id);
latest.push(t);
}
Expand Down
56 changes: 5 additions & 51 deletions src/components/methods/MethodOutputSelector.tsx
Original file line number Diff line number Diff line change
@@ -1,61 +1,15 @@
import { Grid, Select, MenuItem, Typography, Box, Tooltip, TextField } from "@mui/material";
import { Grid, Select, MenuItem, Box, Tooltip } from "@mui/material";
import { MethodVariables, OutputType, VariableBinding } from "DISK/interfaces";
import { useEffect, useState } from "react";
import HelpOutlineIcon from '@mui/icons-material/HelpOutline';
import { SECOND_SELECTORS, OUTPUT_SELECTORS, OutputBindingValue } from "components/outputs";

interface MethodInputSelectorProps {
variable: MethodVariables, // This variable represents a parameter
value?: VariableBinding, // Initial value
onChange?: (newBinding:VariableBinding) => void,
}

interface SelectorField {
label:string,
tooltip:string,
}

interface SelectorExtraValue extends SelectorField {
value: string,
}

const OUTPUT_SELECTORS : Record<OutputType, SelectorField> = {
DROP: {
label: "Ignore output",
tooltip: "Do not store the file on DISK. The file will still be available on WINGS."
},
SAVE: {
label: "Save file",
tooltip: "The file will be stored on the DISK server."
},
PROCESS: {
label: "Process file",
tooltip: "The file will be read by DISK."
}
}

const SECOND_SELECTORS : Record<OutputType, Record<string, SelectorField>> = {
DROP: {},
PROCESS: {
_CONFIDENCE_VALUE_: {
label: "Process as confidence value file",
tooltip: "The first line of the file should be a point floating number.",
}
},
SAVE: {
_DOWNLOAD_ONLY_: {
label: "Provide download link",
tooltip: "The file will be available for download to any DISK user.",
}, _IMAGE_: {
label: "Store as image to be displayed",
tooltip: "The file will be available for visualization and download.",
}, _VISUALIZE_: {
label: "Store as main visualization",
tooltip: "The file will be available for visualization and download." +
"The latest version of this file will be show in the hypothesis page.",
}
}
}

export const MethodOutputSelector = ({variable, value, onChange}:MethodInputSelectorProps) => {
const [paramType, setParamType] = useState<OutputType>('DROP');
const [dataType, setDatatype] = useState<string>('');
Expand Down Expand Up @@ -118,7 +72,7 @@ export const MethodOutputSelector = ({variable, value, onChange}:MethodInputSele
return <Select size="small" sx={{ display: 'inline-block', width: "100%"}} variant="standard" label="Set binding"
value={bindValue} onChange={(e) => onBindValueChange(e.target.value)} required>
{Object.keys(SECOND_SELECTORS[paramType]).map((value: string, i: number) =>
<MenuItem key={`varopt_${i}`} value={value}>{SECOND_SELECTORS[paramType][value].label}</MenuItem>)}
<MenuItem key={`varopt_${i}`} value={value}>{SECOND_SELECTORS[paramType][value as OutputBindingValue]!.label}</MenuItem>)}
</Select>
case 'DROP':
default:
Expand All @@ -145,9 +99,9 @@ export const MethodOutputSelector = ({variable, value, onChange}:MethodInputSele
{renderBindingSelector()}
</Grid>
<Grid item xs={2} md={2} sm={2}>
{SECOND_SELECTORS[paramType] && SECOND_SELECTORS[paramType][bindValue] && (
{SECOND_SELECTORS[paramType] && SECOND_SELECTORS[paramType][bindValue as OutputBindingValue] && (
<Box style={{ zIndex: 10 }}>
<Tooltip arrow title={SECOND_SELECTORS[paramType][bindValue].tooltip}>
<Tooltip arrow title={SECOND_SELECTORS[paramType][bindValue as OutputBindingValue]!.tooltip}>
<HelpOutlineIcon />
</Tooltip>
</Box>
Expand Down
17 changes: 0 additions & 17 deletions src/components/methods/WorkflowList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,23 +68,6 @@ export const WorkflowSeedList = ({editable, workflows: inputWorkflows, metaworkf
}

const onWorkflowSave = (wf:WorkflowSeed) => {
//FIXME: This is a hack, there are no way to send multiple strings as a list
// so we transform demographic_value into a list here.
//wf.bindings = wf.bindings.map((vb:VariableBinding) => {
// let curBinding = vb.binding;
// //TODO:
// //if (vb.variable === 'demographic_value') {
// // if (!curBinding.startsWith("[")) curBinding = '[' + curBinding;
// // if (!curBinding.endsWith("]")) curBinding += "]";
// //}
// return {
// variable: vb.variable,
// binding: curBinding,
// isArray: vb.isArray,
// type: vb.type,
// } as VariableBinding;
//});
//-----
if (notifyChange) {
let curWfs : WorkflowSeed[] = [ ...(editingMeta ? metaWorkflows : workflows) ];
if (selectedWorkflow) curWfs[editingIndex] = wf; //Editing
Expand Down
7 changes: 5 additions & 2 deletions src/components/methods/WorkflowSeedPreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -114,13 +114,16 @@ export const WorkflowSeedPreview = ({workflow:wf, button:externalButton, onDelet
editedValue = "This file will be make available to download"
fontS = "italic"
} else if (value === "_IMAGE_") {
editedValue = "This file will be used on visualizations"
editedValue = "This file will be used to generate visualizations";
fontS = "italic"
} else if (value === "_VISUALIZE_") {
editedValue = "The latest version of this file will be show on TLOI preview"
fontS = "italic"
} else if (value === "_BRAIN_VISUALIZATION_") {
editedValue = "This file is a brain visualization configuration file"
editedValue = "This file will be used to generate a brain visualization"
fontS = "italic"
} else if (value === "_SHINY_LOG_") {
editedValue = "This file will be used to generate Shiny visualizations"
fontS = "italic"
} else if (value === "_CONFIDENCE_VALUE_") {
editedValue = "This file contains the confidence value"
Expand Down
Loading

0 comments on commit 00d6f90

Please sign in to comment.