Skip to content

Commit

Permalink
feat(ui-results): add button to display display 'digest' file in resu…
Browse files Browse the repository at this point in the history
…lt list
  • Loading branch information
skamril committed Jul 26, 2024
1 parent e44bb4b commit a6f098d
Show file tree
Hide file tree
Showing 6 changed files with 146 additions and 85 deletions.
1 change: 1 addition & 0 deletions webapp/public/locales/en/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
"global.error.failedtoretrievejobs": "Failed to retrieve job information",
"global.error.failedtoretrievelogs": "Failed to retrieve job logs",
"global.error.failedtoretrievedownloads": "Failed to retrieve downloads list",
"global.error.fileNotFound": "File not found",
"global.error.create": "Creation failed",
"global.error.delete": "Deletion failed",
"global.area.add": "Add an area",
Expand Down
1 change: 1 addition & 0 deletions webapp/public/locales/fr/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
"global.error.failedtoretrievejobs": "Échec de la récupération des tâches",
"global.error.failedtoretrievelogs": "Échec de la récupération des logs",
"global.error.failedtoretrievedownloads": "Échec de la récupération des exports",
"global.error.fileNotFound": "Fichier introuvable",
"global.error.create": "La création a échoué",
"global.error.delete": "La suppression a échoué",
"global.area.add": "Ajouter une zone",
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import {
} from "./style";
import ConfirmationDialog from "../../../../../common/dialogs/ConfirmationDialog";
import LinearProgressWithLabel from "../../../../../common/LinearProgressWithLabel";
import DigestDialog from "./DigestDialog";
import DigestDialog from "../../../../../common/dialogs/DigestDialog";
import type { EmptyObject } from "../../../../../../utils/tsUtils";

export const ColorStatus = {

Check warning on line 36 in webapp/src/components/App/Singlestudy/HomeView/InformationView/LauncherHistory/JobStepper.tsx

View workflow job for this annotation

GitHub Actions / npm-test (ubuntu-20.04)

Fast refresh only works when a file only exports components. Use a new file to share constants or functions between components
Expand Down
100 changes: 70 additions & 30 deletions webapp/src/components/App/Singlestudy/explore/Results/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import ArchiveIcon from "@mui/icons-material/Archive";
import UnarchiveIcon from "@mui/icons-material/Unarchive";
import DownloadIcon from "@mui/icons-material/Download";
import DeleteForeverIcon from "@mui/icons-material/DeleteForever";
import EqualizerIcon from "@mui/icons-material/Equalizer";
import * as R from "ramda";
import { useNavigate, useOutletContext } from "react-router-dom";
import { grey } from "@mui/material/colors";
Expand All @@ -43,6 +44,8 @@ import { convertUTCToLocalTime } from "../../../../../services/utils";
import LaunchJobLogView from "../../../Tasks/LaunchJobLogView";
import useEnqueueErrorSnackbar from "../../../../../hooks/useEnqueueErrorSnackbar";
import ConfirmationDialog from "../../../../common/dialogs/ConfirmationDialog";
import type { EmptyObject } from "../../../../../utils/tsUtils";
import DigestDialog from "../../../../common/dialogs/DigestDialog";

interface OutputDetail {
name: string;
Expand All @@ -53,6 +56,17 @@ interface OutputDetail {
archived?: boolean;
}

type DialogState =
| {
type: "confirmDelete";
data: string;
}
| {
type: "digest";
data: LaunchJob;
}
| EmptyObject;

const combineJobsAndOutputs = (
jobs: LaunchJob[],
outputs: StudyOutput[],
Expand Down Expand Up @@ -90,12 +104,19 @@ const combineJobsAndOutputs = (
return runningJobs.concat(outputDetails);
};

const iconStyle = {
fontSize: 22,
color: "action.active",
cursor: "pointer",
"&:hover": { color: "action.hover" },
};

function Results() {
const { study } = useOutletContext<{ study: StudyMetadata }>();
const { t } = useTranslation();
const navigate = useNavigate();
const enqueueErrorSnackbar = useEnqueueErrorSnackbar();
const [outputToDelete, setOutputToDelete] = useState<string>();
const [dialogState, setDialogState] = useState<DialogState>({});

const { data: studyJobs, isLoading: studyJobsLoading } =
usePromiseWithSnackbarError(() => getStudyJobs(study.id), {
Expand Down Expand Up @@ -150,12 +171,7 @@ function Results() {
<Box sx={{ height: "24px", margin: 0.5 }}>
<Tooltip title={t(title) as string}>
<Component
sx={{
fontSize: 22,
color: "action.active",
cursor: "pointer",
"&:hover": { color: "action.hover" },
}}
sx={iconStyle}
onClick={async () => {
handler().catch((e) => {
enqueueErrorSnackbar(
Expand All @@ -170,6 +186,12 @@ function Results() {
);
};

////////////////////////////////////////////////////////////////
// Utils
////////////////////////////////////////////////////////////////

const closeDialog = () => setDialogState({});

////////////////////////////////////////////////////////////////
// Event Handlers
////////////////////////////////////////////////////////////////
Expand All @@ -180,12 +202,10 @@ function Results() {
});
};

const handleDeleteOutput = async () => {
if (outputToDelete) {
await deleteOutput(study.id, outputToDelete);
setOutputToDelete(undefined);
reloadOutputs();
}
const handleDeleteOutput = async (outputName: string) => {
closeDialog();
await deleteOutput(study.id, outputName);
reloadOutputs();
};

////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -350,12 +370,7 @@ function Results() {
<Box sx={{ height: "24px", margin: 0.5 }}>
<Tooltip title={t("global.download") as string}>
<DownloadIcon
sx={{
fontSize: 22,
color: "action.active",
cursor: "pointer",
"&:hover": { color: "action.hover" },
}}
sx={iconStyle}
onClick={() => {
if (row.job) {
downloadJobOutput(row.job.id);
Expand All @@ -365,24 +380,39 @@ function Results() {
</Tooltip>
</Box>
)}

{row.job && (
<LaunchJobLogView
job={row.job}
logButton
logErrorButton
/>
)}
{row.job?.status === "success" && (
<Tooltip title="Digest">
<EqualizerIcon
onClick={() => {
setDialogState({
type: "digest",
data: row.job as LaunchJob,
});
}}
sx={iconStyle}
/>
</Tooltip>
)}
<Box sx={{ height: "24px", margin: 0.5 }}>
<Tooltip title={t("global.delete") as string}>
<DeleteForeverIcon
sx={{
fontSize: 22,
color: "action.active",
cursor: "pointer",
...iconStyle,
"&:hover": { color: "error.light" },
}}
onClick={() => {
setOutputToDelete(row.name);
setDialogState({
type: "confirmDelete",
data: row.name,
});
}}
/>
</Tooltip>
Expand Down Expand Up @@ -420,13 +450,23 @@ function Results() {
</TableBody>
</Table>
</TableContainer>
<ConfirmationDialog
open={!!outputToDelete}
onConfirm={handleDeleteOutput}
onCancel={() => setOutputToDelete(undefined)}
>
{t("results.question.deleteOutput", { outputname: outputToDelete })}
</ConfirmationDialog>
{dialogState.type === "confirmDelete" && (
<ConfirmationDialog
open
onConfirm={() => handleDeleteOutput(dialogState.data)}
onCancel={closeDialog}
>
{t("results.question.deleteOutput", { outputname: dialogState.data })}
</ConfirmationDialog>
)}
{dialogState.type === "digest" && (
<DigestDialog
open
studyId={dialogState.data.studyId}
outputId={dialogState.data.outputId}
onOk={closeDialog}
/>
)}
</Box>
);
}
Expand Down
73 changes: 73 additions & 0 deletions webapp/src/components/common/dialogs/DigestDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { Skeleton } from "@mui/material";
import OkDialog, { OkDialogProps } from "./OkDialog";
import EditableMatrix from "../EditableMatrix";
import UsePromiseCond from "../utils/UsePromiseCond";
import type { LaunchJob } from "../../../common/types";
import { getStudyData } from "../../../services/api/study";
import usePromise from "../../../hooks/usePromise";
import { useTranslation } from "react-i18next";
import { AxiosError } from "axios";
import EmptyView from "../page/SimpleContent";
import SearchOffIcon from "@mui/icons-material/SearchOff";

// TODO: redesign DataViewerDialog to use path, then remove this component

export interface DigestDialogProps
extends Pick<OkDialogProps, "open" | "onOk" | "onClose"> {
studyId: LaunchJob["studyId"];
outputId: LaunchJob["outputId"];
}

function DigestDialog({
studyId,
outputId,
...dialogProps
}: DigestDialogProps) {
const { t } = useTranslation();

const synthesisRes = usePromise(
() =>
getStudyData(studyId, `output/${outputId}/economy/mc-all/grid/digest`),
{
deps: [studyId, outputId],
},
);

return (
<OkDialog
{...dialogProps}
title="Digest"
okButtonText={t("global.close")}
fullScreen
sx={{ m: 5 }}
>
<UsePromiseCond
response={synthesisRes}
ifPending={() => <Skeleton sx={{ height: 1, transform: "none" }} />}
ifRejected={(error) => {
if (error instanceof AxiosError && error.response?.status === 404) {
return (
<EmptyView
title={t("global.error.fileNotFound")}
icon={SearchOffIcon}
/>
);
}
return <EmptyView title={error?.toString()} />;
}}
ifResolved={(matrix) =>
matrix && (
<EditableMatrix
matrix={matrix}
columnsNames={matrix.columns}
matrixTime={false}
readOnly
/>
)
}
/>
</OkDialog>
);
}

export default DigestDialog;

0 comments on commit a6f098d

Please sign in to comment.