Skip to content

Commit

Permalink
upload goals and lois
Browse files Browse the repository at this point in the history
  • Loading branch information
Hernán Vargas Leighton authored and Hernán Vargas Leighton committed Mar 20, 2024
1 parent b880d26 commit cb6ac2c
Show file tree
Hide file tree
Showing 17 changed files with 133 additions and 38 deletions.
1 change: 0 additions & 1 deletion src/DISK/interfaces.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,6 @@ export interface TriggeredLineOfInquiry extends LOICommon{
queryResults: DataQueryResult;
workflows: WorkflowInstantiation[];
metaWorkflows: WorkflowInstantiation[];
result: GoalResult | null;
}

export type Status = 'QUEUED' | 'RUNNING' | 'FAILED' | 'SUCCESSFUL' | 'PENDING';
Expand Down
17 changes: 15 additions & 2 deletions src/components/Fields.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Box, TextField, IconButton, Skeleton, Tooltip, Checkbox, FormControlLabel, FormGroup } from "@mui/material"
import { Box, TextField, IconButton, Skeleton, Tooltip, Checkbox, FormControlLabel, FormGroup, styled } from "@mui/material"
import { Link } from "react-router-dom"
import CancelIcon from '@mui/icons-material/Cancel';
import { TypographySection } from "./Styles";
Expand Down Expand Up @@ -40,6 +40,7 @@ var TriggerConditionEnum = {
METHOD: 2,
MANUAL: 4,
}

export const TriggerConditionEditor = ({defaultValue, onChange}:TriggerConditionEditorProps) => {
const [disabled, setDisabled] = useState<boolean>(false);
const [data, setData] = useState<boolean>(false);
Expand Down Expand Up @@ -112,4 +113,16 @@ export const TriggerConditionEditor = ({defaultValue, onChange}:TriggerCondition
<FormControlLabel control={<Checkbox size="small" checked={method} disabled={disabled} onChange={(e) => onCheckboxChange('METHOD', e.target.checked)}/>} label="On Workflow Changes" />
</Tooltip>
</FormGroup>
}
}

export const VisuallyHiddenInput = styled('input')({
clip: 'rect(0 0 0 0)',
clipPath: 'inset(50%)',
height: 1,
overflow: 'hidden',
position: 'absolute',
bottom: 0,
left: 0,
whiteSpace: 'nowrap',
width: 1,
});
3 changes: 2 additions & 1 deletion src/components/RightMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,8 @@ export default function MiniDrawer(props: { children: string | number | boolean
<SubdirectoryArrowRightIcon/>
</ListItemIcon>
<ListItemText disableTypography sx={{ opacity: open ? 1 : 0}} primary={
<Typography sx={{fontWeight: location.pathname != PATH_GOALS && inLocation(PATH_GOALS) ? 700 : 400, textOverflow:'ellipsis', whiteSpace: 'nowrap', overflow: 'hidden'}}>
<Typography sx={{fontWeight: location.pathname != PATH_GOALS && inLocation(PATH_GOALS) || location.pathname != PATH_TLOIS && inLocation(PATH_TLOIS) ? 700 : 400,
textOverflow:'ellipsis', whiteSpace: 'nowrap', overflow: 'hidden'}}>
{selectedGoal.name}
</Typography>
}/>
Expand Down
2 changes: 1 addition & 1 deletion src/components/files/FileList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Fragment, useEffect, useState } from "react";
import CloseIcon from '@mui/icons-material/Close';
import { Endpoint, Execution, TriggeredLineOfInquiry, VariableBinding, WorkflowInstantiation } from "DISK/interfaces";
import FileCopyIcon from '@mui/icons-material/FileCopy';
import { PrivateLink } from "../PrivateLink";
import { PrivateLink } from "./PrivateLink";

interface FileListProps {
type: 'input' | 'output',
Expand Down
File renamed without changes.
9 changes: 9 additions & 0 deletions src/components/files/download.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export const downloadJSON = (str:string, name:string) => {
var dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(str);
var downloadAnchorNode = document.createElement('a');
downloadAnchorNode.setAttribute("href", dataStr);
downloadAnchorNode.setAttribute("download", name + ".json");
document.body.appendChild(downloadAnchorNode);
downloadAnchorNode.click();
downloadAnchorNode.remove();
}
File renamed without changes.
File renamed without changes.
3 changes: 2 additions & 1 deletion src/components/goals/GoalsPreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { useGetTLOIsQuery } from "redux/apis/tlois";
import { useEffect, useState } from "react";
import { TLOIPreview } from "components/tlois/TLOIPreview";
import { getId } from "DISK/util";
import { downloadJSON } from "components/files/download";

const TwoLines = styled(Typography)(({ theme }) => ({
display: "-webkit-box",
Expand Down Expand Up @@ -123,7 +124,7 @@ export const HypothesisPreview = ({hypothesis, displayDeleteButton=true, display
</ConfirmDialog>
</Box>
</Tooltip>)}
<IconButton sx={{ padding: "4px" }} onClick={download}>
<IconButton sx={{ padding: "4px" }} onClick={() => downloadJSON(JSON.stringify(hypothesis), getId(hypothesis))}>
<DownloadIcon />
</IconButton>
</Box>
Expand Down
15 changes: 2 additions & 13 deletions src/components/lois/LOIPreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { closeBackdrop, openBackdrop } from "redux/slices/backdrop";
import { openNotification } from "redux/slices/notifications";
import { useDeleteLOIMutation } from "redux/apis/lois";
import { getId } from "DISK/util";
import { downloadJSON } from "components/files/download";

const TwoLines = styled(Typography)(({ theme }) => ({
display: "-webkit-box",
Expand Down Expand Up @@ -39,18 +40,6 @@ export const LOIPreview = ({loi, displayDeleteButton=true, displayEditButton=tru
{ isLoading: isDeleting }, // This is the destructured mutation result
] = useDeleteLOIMutation();

//DUPLICATED
const download = () => {
let str = JSON.stringify(loi);
var dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(str);
var downloadAnchorNode = document.createElement('a');
downloadAnchorNode.setAttribute("href", dataStr);
downloadAnchorNode.setAttribute("download", getId(loi) + ".json");
document.body.appendChild(downloadAnchorNode); // required for firefox
downloadAnchorNode.click();
downloadAnchorNode.remove();
}

const onDeleteLOI = () => {
console.log("DELETING: ", loi.id);
dispatch(openBackdrop());
Expand Down Expand Up @@ -102,7 +91,7 @@ export const LOIPreview = ({loi, displayDeleteButton=true, displayEditButton=tru
</ConfirmDialog>
</Box>
</Tooltip>)}
<IconButton sx={{ padding: "4px" }} onClick={download}>
<IconButton sx={{ padding: "4px" }} onClick={() => downloadJSON(JSON.stringify(loi), getId(loi))}>
<DownloadIcon />
</IconButton>
</Box>
Expand Down
2 changes: 1 addition & 1 deletion src/components/methods/MethodOutputSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ 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";
import { SECOND_SELECTORS, OUTPUT_SELECTORS, OutputBindingValue } from "components/files/outputs";

interface MethodInputSelectorProps {
variable: MethodVariables, // This variable represents a parameter
Expand Down
2 changes: 1 addition & 1 deletion src/components/methods/WorkflowSeedPreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import OpenInNewIcon from '@mui/icons-material/OpenInNew';
import DeleteIcon from '@mui/icons-material/Delete';
import { Fragment, useEffect, useState } from "react";
import { getBindingAsArray, getFileName } from "DISK/util";
import { PrivateLink } from "components/PrivateLink";
import { PrivateLink } from "components/files/PrivateLink";

const TypographyLabel = styled(Typography)(({ theme }) => ({
color: 'gray',
Expand Down
22 changes: 12 additions & 10 deletions src/components/tlois/TLOIBundle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,18 +53,20 @@ export const TLOIBundle = ({loiId, goal}:TLOIBundleProps) => {
let filtered = (list||[])
.filter(tloi => [...tloi.workflows, ...tloi.metaWorkflows].every(wf => wf.executions.length > 0));

let last = filtered[filtered.length-1];
[...last.workflows, ...last.metaWorkflows]
.filter(wf => wf.executions.length > 0 && wf.executions[0].result)
.forEach((wf) => {
(wf.executions[0].result.extras || []).forEach(binding => {
visualizations.forEach(varName => {
if (binding.variable === varName && binding.binding.length > 0) {
vizMap[varName] = binding.binding[binding.binding.length-1];
}
if (filtered.length > 0) {
let last = filtered[filtered.length-1];
[...last.workflows, ...last.metaWorkflows]
.filter(wf => wf.executions.length > 0 && wf.executions[0].result)
.forEach((wf) => {
(wf.executions[0].result.extras || []).forEach(binding => {
visualizations.forEach(varName => {
if (binding.variable === varName && binding.binding.length > 0) {
vizMap[varName] = binding.binding[binding.binding.length-1];
}
});
});
});
});
}
}
setMainVisualizations(vizMap);
}, [loi, list])
Expand Down
1 change: 0 additions & 1 deletion src/components/tlois/TLOIEdit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ export const TLOIEditButton = ({tloi, label: title} : FileListProps) => {
dateCreated: "",
dateModified: "",
status: "PENDING",
result: null,
workflows: meta ? cleanWorkflows(tloi.workflows) : getEditedWorkflows(),
metaWorkflows: meta ? getEditedWorkflows() : cleanWorkflows(tloi.metaWorkflows),
};
Expand Down
2 changes: 1 addition & 1 deletion src/components/tlois/TLOITable.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { TableContainer, Table, TableHead, TableRow, TableCell, TableBody } from "@mui/material";
import { useState, useEffect } from "react";
import { LineOfInquiry, TriggeredLineOfInquiry } from "DISK/interfaces";
import { ALL_COLUMNS, ColumnName } from "components/outputs/table";
import { ALL_COLUMNS, ColumnName } from "components/files/outputs/table";

interface TLOITableProps {
list: TriggeredLineOfInquiry[]
Expand Down
47 changes: 44 additions & 3 deletions src/pages/Goals/GoalEditor.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { Box, Button, Card, Divider, IconButton, Skeleton, TextField, Tooltip, Typography } from "@mui/material";
import { Box, Button, Card, Divider, IconButton, Input, Skeleton, TextField, Tooltip, Typography, styled } from "@mui/material";
import { Goal, Question, Triple, VariableBinding, toMultiValueAssignation } from "DISK/interfaces";
import { useEffect } from "react";
import { Link, useNavigate, useParams, useSearchParams } from 'react-router-dom'
import CancelIcon from '@mui/icons-material/Cancel';
import SaveIcon from '@mui/icons-material/Save';
import CopyIcon from '@mui/icons-material/ContentCopy';
import CloudUploadIcon from "@mui/icons-material/CloudUpload";
import { PATH_GOALS, UI_PARAMS } from "constants/routes";
import { QuestionSelector } from "components/questions/QuestionSelector";
import { useAppDispatch, useQuestionBindings, useSelectedQuestion } from "redux/hooks";
Expand All @@ -13,7 +14,7 @@ import { closeBackdrop, openBackdrop } from "redux/slices/backdrop";
import { usePostGoalMutation, usePutGoalMutation, useGetGoalByIdQuery } from "redux/apis/goals";
import { openNotification } from "redux/slices/notifications";
import { addBindingsToQuestionGraph } from "components/questions/QuestionHelpers";
import { EditableHeader } from "components/Fields";
import { EditableHeader, VisuallyHiddenInput } from "components/Fields";
import { TextFieldBlock, TypographySubtitle } from "components/Styles";
import { getId } from "DISK/util";

Expand Down Expand Up @@ -171,6 +172,35 @@ export const HypothesisEditor = () => {
setEditedQuestionId(selectedQuestion? selectedQuestion.id : '');
};

const upload : React.ChangeEventHandler<HTMLInputElement> = (ev) => {
if (ev && ev.target && ev.target.files && ev.target.files.length === 1) {
let file = ev.target.files[0];
if (file.type === 'application/json') {
const reader = new FileReader();
reader.onload = (ev2) => {
if (ev2.target && ev2.target.result && typeof ev2.target.result === 'string') {
try {
let newGoal : Goal = {
...JSON.parse(ev2.target.result) as Goal,
id: "",
dateCreated: "",
dateModified: "",
}
loadForm(newGoal);
dispatch(openNotification({ severity: 'success', text: 'Goal successfully loaded'}));
return;
} catch (e) {}
}
dispatch(openNotification({ severity: 'error', text: 'Could not read Goal from file' }));
}

reader.readAsText(file);
}
} else {
dispatch(openNotification({ severity: 'error', text: 'Could not read Goal from file' }));
}
}

return <Card variant="outlined">
<EditableHeader loading={loading} value={name} error={errorName} onChange={onNameChange} redirect={PATH_GOALS + (goal && goal.id ? "/" + getId(goal) : "")}/>
<Divider/>
Expand Down Expand Up @@ -200,7 +230,18 @@ export const HypothesisEditor = () => {
{goal?
<Button color="info" sx={{mr:"10px"}} onClick={onDuplicateClicked}>
<CopyIcon/> Duplicate
</Button> : <Box/>
</Button> : <Box>
<Button
component="label"
role={undefined}
variant="outlined"
tabIndex={-1}
startIcon={<CloudUploadIcon />}
>
Upload
<VisuallyHiddenInput type="file" accept="json" onChange={upload}/>
</Button>
</Box>
}
<Box>
<Button color="error" sx={{mr:"10px"}} component={Link} to={PATH_GOALS + (goal ? "/" + getId(goal) : "")}>
Expand Down
45 changes: 43 additions & 2 deletions src/pages/LOI/LOIEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Box, Button, Card, Divider, Skeleton } from "@mui/material";
import { DataQueryTemplate, LineOfInquiry, Question, QuestionVariable, Workflow, WorkflowSeed } from "DISK/interfaces";
import { useEffect } from "react";
import { Link, useNavigate, useParams, useSearchParams } from 'react-router-dom'
import CloudUploadIcon from "@mui/icons-material/CloudUpload";
import SaveIcon from '@mui/icons-material/Save';
import CopyIcon from '@mui/icons-material/ContentCopy';
import { PATH_LOIS } from "constants/routes";
Expand All @@ -16,7 +17,7 @@ import { openNotification } from "redux/slices/notifications";
import { createQueryForGraph, getAllQuestionVariables, getCompleteQuestionGraph } from "components/questions/QuestionHelpers";
import { TypographySubtitle, TextFieldBlock, FieldBox } from "components/Styles";
import CancelIcon from '@mui/icons-material/Cancel';
import { EditableHeader, TriggerConditionEditor } from "components/Fields";
import { EditableHeader, TriggerConditionEditor, VisuallyHiddenInput } from "components/Fields";
import { DataQueryTemplateForm } from "components/DataQuery/DataQueryTemplateForm";

export const LOIEditor = () => {
Expand Down Expand Up @@ -210,6 +211,35 @@ export const LOIEditor = () => {
}
}

const upload : React.ChangeEventHandler<HTMLInputElement> = (ev) => {
if (ev && ev.target && ev.target.files && ev.target.files.length === 1) {
let file = ev.target.files[0];
if (file.type === 'application/json') {
const reader = new FileReader();
reader.onload = (ev2) => {
if (ev2.target && ev2.target.result && typeof ev2.target.result === 'string') {
try {
let newGoal : LineOfInquiry = {
...JSON.parse(ev2.target.result) as LineOfInquiry,
id: "",
dateCreated: "",
dateModified: "",
}
loadForm(newGoal);
dispatch(openNotification({ severity: 'success', text: 'Line of Inquiry successfully loaded' }));
return;
} catch (e) {}
}
dispatch(openNotification({ severity: 'error', text: 'Could not read Line of Inquiry from file' }));
}

reader.readAsText(file);
}
} else {
dispatch(openNotification({ severity: 'error', text: 'Could not read Goal from file' }));
}
}

return <Card variant="outlined">
<EditableHeader loading={loading} value={name} error={errorName} onChange={onNameChange} redirect={PATH_LOIS + (LOI ? "/" + getId(LOI) : "")}/>
<Divider/>
Expand Down Expand Up @@ -247,7 +277,18 @@ export const LOIEditor = () => {
{LOI?
<Button color="info" sx={{mr:"10px"}} onClick={onDuplicateClicked}>
<CopyIcon/> Duplicate
</Button> : <Box/>
</Button> : <Box>
<Button
component="label"
role={undefined}
variant="outlined"
tabIndex={-1}
startIcon={<CloudUploadIcon />}
>
Upload
<VisuallyHiddenInput type="file" accept="json" onChange={upload}/>
</Button>
</Box>
}
<Box>
<Button color="error" sx={{mr:"10px"}} component={Link} to={PATH_LOIS + (LOI ? "/" + getId(LOI) : "")}>
Expand Down

0 comments on commit cb6ac2c

Please sign in to comment.