From d03a4342bf9b59c4717f5ef150f184d9dbcd26cb Mon Sep 17 00:00:00 2001 From: ReiHashimoto <42664619+ReiHashimoto@users.noreply.github.com> Date: Mon, 16 Oct 2023 16:51:43 +0900 Subject: [PATCH 1/4] make default sort to desc --- .../src/components/Workspace/Experiment/ExperimentTable.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/components/Workspace/Experiment/ExperimentTable.tsx b/frontend/src/components/Workspace/Experiment/ExperimentTable.tsx index 4090b6667..b34942993 100644 --- a/frontend/src/components/Workspace/Experiment/ExperimentTable.tsx +++ b/frontend/src/components/Workspace/Experiment/ExperimentTable.tsx @@ -104,7 +104,7 @@ const TableImple = React.memo(() => { const onClickReload = () => { dispatch(getExperiments()) } - const [order, setOrder] = React.useState('asc') + const [order, setOrder] = React.useState('desc') const [sortTarget, setSortTarget] = React.useState('timestamp') const sortHandler = From eab55078370254b2579d6bc2ce7fd243e991ee14 Mon Sep 17 00:00:00 2001 From: ReiHashimoto <42664619+ReiHashimoto@users.noreply.github.com> Date: Mon, 16 Oct 2023 18:55:09 +0900 Subject: [PATCH 2/4] show start, finish and elapsed time --- .../Workspace/Experiment/ExperimentTable.tsx | 39 ++++++++++++++----- .../slice/Experiments/Experiments.test.ts | 6 ++- .../slice/Experiments/ExperimentsSelectors.ts | 16 +++++--- .../slice/Experiments/ExperimentsType.ts | 7 ++-- .../slice/Experiments/ExperimentsUtils.ts | 5 ++- 5 files changed, 51 insertions(+), 22 deletions(-) diff --git a/frontend/src/components/Workspace/Experiment/ExperimentTable.tsx b/frontend/src/components/Workspace/Experiment/ExperimentTable.tsx index b34942993..ed5b93330 100644 --- a/frontend/src/components/Workspace/Experiment/ExperimentTable.tsx +++ b/frontend/src/components/Workspace/Experiment/ExperimentTable.tsx @@ -28,7 +28,8 @@ import { CollapsibleTable } from './CollapsibleTable' import { selectExperimentsStatusIsUninitialized, selectExperimentsStatusIsFulfilled, - selectExperimentTimeStamp, + selectExperimentStartedAt, + selectExperimentFinishedAt, selectExperimentName, selectExperimentStatus, selectExperimentsStatusIsError, @@ -41,7 +42,7 @@ import { getExperiments, } from 'store/slice/Experiments/ExperimentsActions' import { ExperimentStatusIcon } from './ExperimentStatusIcon' -import { Experiment } from 'store/slice/Experiments/ExperimentsType' +import { ExperimentSortKeys } from 'store/slice/Experiments/ExperimentsType' import { DeleteButton } from './Button/DeleteButton' import { NWBDownloadButton, @@ -58,7 +59,7 @@ import { selectCurrentWorkspaceId, selectIsWorkspaceOwner, } from 'store/slice/Workspace/WorkspaceSelector' -import { AppDispatch } from "../../../store/store"; +import { AppDispatch } from '../../../store/store' export const ExperimentUidContext = React.createContext('') @@ -106,9 +107,10 @@ const TableImple = React.memo(() => { } const [order, setOrder] = React.useState('desc') const [sortTarget, setSortTarget] = - React.useState('timestamp') + React.useState('startedAt') const sortHandler = - (property: keyof Experiment) => (event: React.MouseEvent) => { + (property: keyof ExperimentSortKeys) => + (event: React.MouseEvent) => { const isAsc = sortTarget === property && order === 'asc' setOrder(isAsc ? 'desc' : 'asc') setSortTarget(property) @@ -346,7 +348,7 @@ const HeadItem = React.memo<{ Timestamp @@ -388,7 +390,8 @@ const RowItem = React.memo<{ }>(({ onCheckBoxClick, checked, isOwner }) => { const workspaceId = useSelector(selectCurrentWorkspaceId) const uid = React.useContext(ExperimentUidContext) - const timestamp = useSelector(selectExperimentTimeStamp(uid)) + const startedAt = useSelector(selectExperimentStartedAt(uid)) + const finishedAt = useSelector(selectExperimentFinishedAt(uid)) const status = useSelector(selectExperimentStatus(uid)) const name = useSelector(selectExperimentName(uid)) const hasNWB = useSelector(selectExperimentHasNWB(uid)) @@ -452,8 +455,26 @@ const RowItem = React.memo<{ {open ? : } - - {timestamp} + + {finishedAt == null ? ( + startedAt + ) : ( + <> + {startedAt} - + {finishedAt} + + (elapsed{' '} + {(new Date(finishedAt).getTime() - + new Date(startedAt).getTime()) / + 1000}{' '} + sec) + + + )} {uid} diff --git a/frontend/src/store/slice/Experiments/Experiments.test.ts b/frontend/src/store/slice/Experiments/Experiments.test.ts index 0d8243e20..69a2df6eb 100644 --- a/frontend/src/store/slice/Experiments/Experiments.test.ts +++ b/frontend/src/store/slice/Experiments/Experiments.test.ts @@ -105,7 +105,8 @@ describe('Experiments', () => { experimentList: { [uid1]: { uid: uid1, - timestamp: '2022-05-07 05:26:54', + startedAt: '2022-05-07 05:26:54', + finishedAt: '2022-05-07 05:26:55', frameRate: 30, name: 'record test', hasNWB: true, @@ -133,7 +134,8 @@ describe('Experiments', () => { }, [uid2]: { uid: uid2, - timestamp: '2022-05-07 05:54:53', + startedAt: '2022-05-07 05:54:53', + finishedAt: '2022-05-07 05:54:54', frameRate: 30, name: 'New flow', hasNWB: true, diff --git a/frontend/src/store/slice/Experiments/ExperimentsSelectors.ts b/frontend/src/store/slice/Experiments/ExperimentsSelectors.ts index 58aa19b2e..9fe083b68 100644 --- a/frontend/src/store/slice/Experiments/ExperimentsSelectors.ts +++ b/frontend/src/store/slice/Experiments/ExperimentsSelectors.ts @@ -39,8 +39,11 @@ export const selectExperimentUidList = (state: RootState) => export const selectExperiment = (uid: string) => (state: RootState) => selectExperimentList(state)[uid] -export const selectExperimentTimeStamp = (uid: string) => (state: RootState) => - selectExperiment(uid)(state).timestamp +export const selectExperimentStartedAt = (uid: string) => (state: RootState) => + selectExperiment(uid)(state).startedAt + +export const selectExperimentFinishedAt = (uid: string) => (state: RootState) => + selectExperiment(uid)(state).finishedAt export const selectExperimentName = (uid: string) => (state: RootState) => selectExperiment(uid)(state).name @@ -91,7 +94,8 @@ export const selectExperimentFunctionHasNWB = (uid: string, nodeId: string) => (state: RootState) => selectExperimentFunction(uid, nodeId)(state).hasNWB -export const selectFrameRate = (currentPipelineUid?: string) => (state: RootState) => { - if(!currentPipelineUid) return 50 - return selectExperiment(currentPipelineUid)(state).frameRate || 50 -} +export const selectFrameRate = + (currentPipelineUid?: string) => (state: RootState) => { + if (!currentPipelineUid) return 50 + return selectExperiment(currentPipelineUid)(state).frameRate || 50 + } diff --git a/frontend/src/store/slice/Experiments/ExperimentsType.ts b/frontend/src/store/slice/Experiments/ExperimentsType.ts index 5ca8babc4..841119b5c 100644 --- a/frontend/src/store/slice/Experiments/ExperimentsType.ts +++ b/frontend/src/store/slice/Experiments/ExperimentsType.ts @@ -27,7 +27,8 @@ export type ExperimentType = { } status?: EXPERIMENTS_STATUS name: string - timestamp: string + startedAt: string + finishedAt?: string hasNWB: boolean frameRate?: number } @@ -42,8 +43,8 @@ export type ExperimentFunction = { export type EXPERIMENTS_STATUS = 'success' | 'error' | 'running' -export interface Experiment { +export interface ExperimentSortKeys { uid: string name: string - timestamp: string + startedAt: string } diff --git a/frontend/src/store/slice/Experiments/ExperimentsUtils.ts b/frontend/src/store/slice/Experiments/ExperimentsUtils.ts index 960e84b84..984c283fa 100644 --- a/frontend/src/store/slice/Experiments/ExperimentsUtils.ts +++ b/frontend/src/store/slice/Experiments/ExperimentsUtils.ts @@ -37,12 +37,13 @@ export function convertToExperimentType(dto: ExperimentDTO): ExperimentType { }) return { uid: dto.unique_id, - timestamp: dto.started_at, + startedAt: dto.started_at, + finishedAt: dto.finished_at, status: dto.success, name: dto.name, hasNWB: dto.hasNWB, functions, - frameRate: dto.nwb?.imaging_plane.imaging_rate + frameRate: dto.nwb?.imaging_plane.imaging_rate, } } From 12ac7eb3f8ff35d5cfd8d6b39aa3fdb442617860 Mon Sep 17 00:00:00 2001 From: ReiHashimoto <42664619+ReiHashimoto@users.noreply.github.com> Date: Mon, 16 Oct 2023 20:50:52 +0900 Subject: [PATCH 3/4] show function error message --- .../Workspace/Experiment/CollapsibleTable.tsx | 4 +- .../Experiment/ExperimentStatusIcon.tsx | 76 ++++++++++++++++--- .../slice/Experiments/ExperimentsSelectors.ts | 4 + 3 files changed, 71 insertions(+), 13 deletions(-) diff --git a/frontend/src/components/Workspace/Experiment/CollapsibleTable.tsx b/frontend/src/components/Workspace/Experiment/CollapsibleTable.tsx index d312da0ce..ae2fa8c96 100644 --- a/frontend/src/components/Workspace/Experiment/CollapsibleTable.tsx +++ b/frontend/src/components/Workspace/Experiment/CollapsibleTable.tsx @@ -12,6 +12,7 @@ import Typography from '@mui/material/Typography' import { ExperimentUidContext } from './ExperimentTable' import { selectExperimentFunctionHasNWB, + selectExperimentFunctionMessage, selectExperimentFunctionName, selectExperimentFunctionNodeIdList, selectExperimentFunctionStatus, @@ -77,6 +78,7 @@ const TableRowOfFunction = React.memo<{ const name = useSelector(selectExperimentFunctionName(uid, nodeId)) const status = useSelector(selectExperimentFunctionStatus(uid, nodeId)) const hasNWB = useSelector(selectExperimentFunctionHasNWB(uid, nodeId)) + const message = useSelector(selectExperimentFunctionMessage(uid, nodeId)) return ( @@ -85,7 +87,7 @@ const TableRowOfFunction = React.memo<{ {nodeId} - + diff --git a/frontend/src/components/Workspace/Experiment/ExperimentStatusIcon.tsx b/frontend/src/components/Workspace/Experiment/ExperimentStatusIcon.tsx index 9f75af593..5f7317f40 100644 --- a/frontend/src/components/Workspace/Experiment/ExperimentStatusIcon.tsx +++ b/frontend/src/components/Workspace/Experiment/ExperimentStatusIcon.tsx @@ -4,16 +4,68 @@ import ErrorOutlineIcon from '@mui/icons-material/ErrorOutline' import HorizontalRuleIcon from '@mui/icons-material/HorizontalRule' import { EXPERIMENTS_STATUS } from 'store/slice/Experiments/ExperimentsType' +import { IconButton, Popover, Typography } from '@mui/material' -export const ExperimentStatusIcon = React.memo<{ status: EXPERIMENTS_STATUS }>( - ({ status }) => { - switch (status) { - case 'error': - return - case 'success': - return - case 'running': - return - } - }, -) +export const ExperimentStatusIcon = React.memo<{ + status: EXPERIMENTS_STATUS + message?: string +}>(({ status, message }) => { + switch (status) { + case 'error': + return + case 'success': + return + case 'running': + return + } +}) + +const ErrorIcon = React.memo<{ message?: string }>(({ message }) => { + const [anchorEl, setAnchorEl] = React.useState(null) + const handleClick = (event: React.MouseEvent) => { + setAnchorEl(event.currentTarget) + } + const handleClose = () => { + setAnchorEl(null) + } + + const open = Boolean(anchorEl) + const id = open ? 'error-message-popover' : undefined + + return message == null ? ( + + ) : ( + <> + + + + + + {message} + + + + ) +}) diff --git a/frontend/src/store/slice/Experiments/ExperimentsSelectors.ts b/frontend/src/store/slice/Experiments/ExperimentsSelectors.ts index 9fe083b68..7da6b5fd2 100644 --- a/frontend/src/store/slice/Experiments/ExperimentsSelectors.ts +++ b/frontend/src/store/slice/Experiments/ExperimentsSelectors.ts @@ -90,6 +90,10 @@ export const selectExperimentFunctionStatus = (uid: string, nodeId: string) => (state: RootState) => selectExperimentFunction(uid, nodeId)(state).status +export const selectExperimentFunctionMessage = + (uid: string, nodeId: string) => (state: RootState) => + selectExperimentFunction(uid, nodeId)(state).message + export const selectExperimentFunctionHasNWB = (uid: string, nodeId: string) => (state: RootState) => selectExperimentFunction(uid, nodeId)(state).hasNWB From eed02ac68f5cd89ff5c5b77ba215aff46c0c855b Mon Sep 17 00:00:00 2001 From: ReiHashimoto <42664619+ReiHashimoto@users.noreply.github.com> Date: Thu, 19 Oct 2023 12:52:02 +0900 Subject: [PATCH 4/4] modify timestamp format --- .../Workspace/Experiment/ExperimentTable.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/frontend/src/components/Workspace/Experiment/ExperimentTable.tsx b/frontend/src/components/Workspace/Experiment/ExperimentTable.tsx index ed5b93330..f38ada29c 100644 --- a/frontend/src/components/Workspace/Experiment/ExperimentTable.tsx +++ b/frontend/src/components/Workspace/Experiment/ExperimentTable.tsx @@ -456,7 +456,7 @@ const RowItem = React.memo<{ @@ -464,13 +464,13 @@ const RowItem = React.memo<{ startedAt ) : ( <> - {startedAt} - - {finishedAt} + {/* date string format is YYYY-MM-DD HH:mm:ss */} + {`${startedAt} - ${finishedAt.split(" ")[1]}`} - (elapsed{' '} + (elapsed{" "} {(new Date(finishedAt).getTime() - new Date(startedAt).getTime()) / - 1000}{' '} + 1000}{" "} sec)