Skip to content

Commit

Permalink
add hooks to switch workflow with validation
Browse files Browse the repository at this point in the history
  • Loading branch information
ReiHashimoto committed Aug 1, 2023
1 parent 2684385 commit cbc6705
Show file tree
Hide file tree
Showing 12 changed files with 107 additions and 63 deletions.
16 changes: 8 additions & 8 deletions frontend/src/api/experiments/Experiments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,22 +27,22 @@ export type ExperimentDTO = {
success?: EXPERIMENTS_STATUS
started_at: string
finished_at?: string
workspace_id: string
workspace_id: number
unique_id: string
hasNWB: boolean
edgeDict: EdgeDict
nodeDict: NodeDict
}

export async function getExperimentsApi(
workspaceId: string,
workspaceId: number,
): Promise<ExperimentsDTO> {
const response = await axios.get(`${BASE_URL}/experiments/${workspaceId}`)
return response.data
}

export async function deleteExperimentByUidApi(
workspaceId: string,
workspaceId: number,
uid: string,
): Promise<boolean> {
const response = await axios.delete(
Expand All @@ -52,7 +52,7 @@ export async function deleteExperimentByUidApi(
}

export async function deleteExperimentByListApi(
workspaceId: string,
workspaceId: number,
uidList: Array<string>,
): Promise<boolean> {
const response = await axios.post(
Expand All @@ -65,7 +65,7 @@ export async function deleteExperimentByListApi(
}

export async function importExperimentByUidApi(
workspaceId: string,
workspaceId: number,
uid: string,
): Promise<RunPostData> {
const response = await axios.get(
Expand All @@ -75,7 +75,7 @@ export async function importExperimentByUidApi(
}

export async function downloadExperimentNwbApi(
workspaceId: string,
workspaceId: number,
uid: string,
nodeId?: string,
) {
Expand All @@ -90,7 +90,7 @@ export async function downloadExperimentNwbApi(
}

export async function downloadExperimentConfigApi(
workspaceId: string,
workspaceId: number,
uid: string,
) {
const response = await axios.get(
Expand All @@ -103,7 +103,7 @@ export async function downloadExperimentConfigApi(
}

export async function renameExperiment(
workspaceId: string,
workspaceId: number,
uid: string,
new_name: string,
) {
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/api/run/Run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,15 @@ export interface AlgorithmNodePostData extends AlgorithmNodeData {
}

export async function runApi(
workspaceId: string,
workspaceId: number,
data: RunPostData,
): Promise<string> {
const response = await axios.post(`${BASE_URL}/run/${workspaceId}`, data)
return response.data
}

export async function runByUidApi(
workspaceId: string,
workspaceId: number,
uid: string,
data: Omit<RunPostData, 'name'>,
): Promise<string> {
Expand Down Expand Up @@ -79,7 +79,7 @@ export type OutputPathsDTO = {
}

export async function runResult(data: {
workspaceId: string
workspaceId: number
uid: string
pendingNodeIdList: string[]
}): Promise<RunResultDTO> {
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/Workspace/RunButtons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import { setRunBtnOption } from 'store/slice/Pipeline/PipelineSlice'
export const RunButtons = React.memo<UseRunPipelineReturnType>((props) => {
const {
uid,
isStartedSuccess,
runDisabled,
filePathIsUndefined,
algorithmNodeNotExist,
handleCancelPipeline,
Expand Down Expand Up @@ -103,7 +103,7 @@ export const RunButtons = React.memo<UseRunPipelineReturnType>((props) => {
}}
variant="contained"
ref={anchorRef}
disabled={isStartedSuccess}
disabled={runDisabled}
>
<Button onClick={handleClick}>{RUN_BTN_LABELS[runBtnOption]}</Button>
<Button size="small" onClick={handleToggle}>
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/const/Mode.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export const IS_STANDALONE = !(process.env.REACT_APP_IS_STANDALONE === 'false')
export const STANDALONE_WORKSPACE_ID = 'default'
export const STANDALONE_WORKSPACE_ID = 1
25 changes: 2 additions & 23 deletions frontend/src/pages/Workspace/Workspace.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,15 @@
import React, { useEffect } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { useParams } from 'react-router-dom'
import React from 'react'
import { useSelector } from 'react-redux'
import { Box } from '@mui/material'
import { styled } from '@mui/material/styles'
import { STANDALONE_WORKSPACE_ID, IS_STANDALONE } from 'const/Mode'
import { useRunPipeline } from 'store/slice/Pipeline/PipelineHook'
import Experiment from 'components/Workspace/Experiment/Experiment'
import FlowChart from 'components/Workspace/FlowChart/FlowChart'
import Visualize from 'components/Workspace/Visualize/Visualize'
import {
clearCurrentWorkspace,
setCurrentWorkspace,
} from 'store/slice/Workspace/WorkspaceSlice'
import { selectActiveTab } from 'store/slice/Workspace/WorkspaceSelector'

const Workspace: React.FC = () => {
const dispatch = useDispatch()
const runPipeline = useRunPipeline() // タブ切り替えによって結果取得処理が止まってしまうのを回避するため、タブの親レイヤーで呼び出している

const { workspaceId } = useParams<{ workspaceId: string }>()

useEffect(() => {
if (IS_STANDALONE) {
dispatch(setCurrentWorkspace(STANDALONE_WORKSPACE_ID))
} else {
workspaceId && dispatch(setCurrentWorkspace(workspaceId))
}
return () => {
dispatch(clearCurrentWorkspace())
}
}, [workspaceId, dispatch])

const activeTab = useSelector(selectActiveTab)

return (
Expand Down
39 changes: 21 additions & 18 deletions frontend/src/pages/Workspace/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
GridRowModel,
GridRowModes,
} from '@mui/x-data-grid-pro'
import { Link, useSearchParams } from 'react-router-dom'
import { useNavigate, useSearchParams } from 'react-router-dom'
import { selectCurrentUser } from 'store/slice/User/UserSelector'
import Loading from '../../components/common/Loading'
import {
Expand Down Expand Up @@ -55,6 +55,8 @@ const columns = (
handleOpenPopupShare: () => void,
handleOpenPopupDel: (id: number) => void,
handleDownload: (id: number) => void,
handleNavWorkflow: (id: number) => void,
handleNavResult: (id: number) => void,
user?: { id: number },
onEdit?: (id: number) => void,
) => [
Expand Down Expand Up @@ -136,8 +138,8 @@ const columns = (
minWidth: 160,
filterable: false, // todo enable when api complete
sortable: false, // todo enable when api complete
renderCell: (params: GridRenderCellParams<string>) => (
<LinkCustom to={'#'}>Workflow</LinkCustom>
renderCell: (params: GridRenderCellParams<number>) => (
<ButtonCustom onClick={() => handleNavWorkflow(params.row.id)}>Workflow</ButtonCustom>
),
},
{
Expand All @@ -146,9 +148,11 @@ const columns = (
minWidth: 130,
filterable: false, // todo enable when api complete
sortable: false, // todo enable when api complete
renderCell: (_params: GridRenderCellParams<string>) => (
<LinkCustom to={'#'}>Result</LinkCustom>
),
renderCell: (params: GridRenderCellParams<number>) => {
return (
<ButtonCustom onClick={() => handleNavResult(params.row.id)}>Result</ButtonCustom>
)
}
},
{
field: 'download',
Expand Down Expand Up @@ -351,6 +355,7 @@ const PopupDelete = ({ open, handleClose, handleOkDel }: PopupType) => {

const Workspaces = () => {
const dispatch = useDispatch()
const navigate = useNavigate()
const loading = useSelector(selectIsLoadingWorkspaceList)
const data = useSelector(selectWorkspaceData)
const user = useSelector(selectCurrentUser)
Expand Down Expand Up @@ -410,6 +415,14 @@ const Workspaces = () => {
setError('')
}

const handleNavWorkflow = (id: number) => {
navigate(`/console/workspaces/${id}`)
}

const handleNavResult = (id: number) => {
navigate(`/console/workspaces/${id}`, { state: { tab: 2 } })
}

const onEditName = (id: number) => {
setRowModesModel((pre) => ({ ...pre, [id]: { mode: GridRowModes.Edit } }))
}
Expand Down Expand Up @@ -536,6 +549,8 @@ const Workspaces = () => {
handleOpenPopupShare,
handleOpenPopupDel,
handleDownload,
handleNavWorkflow,
handleNavResult,
user,
onEditName,
) as any
Expand Down Expand Up @@ -593,18 +608,6 @@ const ButtonCustom = styled(Button)(({ theme }) => ({
},
}))

const LinkCustom = styled(Link)(({ theme }) => ({
backgroundColor: '#000000c4',
color: '#FFF',
fontSize: 16,
padding: theme.spacing(0.5, 1.5),
textTransform: 'unset',
textDecoration: 'unset',
borderRadius: 5,
'&:hover': {
backgroundColor: '#000000fc',
},
}))

const DialogCustom = styled(Dialog)(({ theme }) => ({
'& .MuiDialog-container': {
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/store/slice/Experiments/ExperimentsActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export const deleteExperimentByList = createAsyncThunk<

export const importExperimentByUid = createAsyncThunk<
RunPostData,
{ workspaceId: string; uid: string }
{ workspaceId: number; uid: string }
>(
`${EXPERIMENTS_SLICE_NAME}/importExperimentByUid`,
async ({ workspaceId, uid }, thunkAPI) => {
Expand Down
44 changes: 43 additions & 1 deletion frontend/src/store/slice/Pipeline/PipelineHook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,58 @@ import { selectAlgorithmNodeNotExist } from '../AlgorithmNode/AlgorithmNodeSelec
import { getExperiments } from '../Experiments/ExperimentsActions'
import { useSnackbar } from 'notistack'
import { RUN_STATUS } from './PipelineType'
import { useLocation, useNavigate, useParams } from 'react-router-dom'
import {
selectIsCurrentUserOwnerWorkspaceItem,
selectWorkspaceItemExists,
} from '../Workspace/WorkspaceSelector'
import { selectCurrentUserId } from '../User/UserSelector'
import { IS_STANDALONE, STANDALONE_WORKSPACE_ID } from 'const/Mode'
import {
clearCurrentWorkspace,
setActiveTab,
setCurrentWorkspace,
} from '../Workspace/WorkspaceSlice'

const POLLING_INTERVAL = 5000

export type UseRunPipelineReturnType = ReturnType<typeof useRunPipeline>

export function useRunPipeline() {
const dispatch = useDispatch()
const navigate = useNavigate()
const location = useLocation()

const { workspaceId } = useParams<{ workspaceId: string }>()
const _workspaceId = Number(workspaceId)
const workspaceExists = useSelector(selectWorkspaceItemExists(_workspaceId))
const currentUserId = useSelector(selectCurrentUserId)
const isOwner = useSelector(
selectIsCurrentUserOwnerWorkspaceItem(_workspaceId, currentUserId),
)

React.useEffect(() => {
if (IS_STANDALONE) {
dispatch(setCurrentWorkspace(STANDALONE_WORKSPACE_ID))
} else {
if (workspaceExists) {
dispatch(setCurrentWorkspace(_workspaceId))
const selectedTab = location.state?.tab
selectedTab && dispatch(setActiveTab(selectedTab))
} else {
navigate('/console/workspaces')
}
}
return () => {
dispatch(clearCurrentWorkspace())
}
}, [dispatch, navigate, workspaceExists, _workspaceId, location.state])

const uid = useSelector(selectPipelineLatestUid)
const isCanceled = useSelector(selectPipelineIsCanceled)
const isStartedSuccess = useSelector(selectPipelineIsStartedSuccess)
const runDisabled = !isOwner ? true : isStartedSuccess

const filePathIsUndefined = useSelector(selectFilePathIsUndefined)
const algorithmNodeNotExist = useSelector(selectAlgorithmNodeNotExist)
const runPostData = useSelector(selectRunPostData)
Expand Down Expand Up @@ -78,7 +120,7 @@ export function useRunPipeline() {
algorithmNodeNotExist,
uid,
status,
isStartedSuccess,
runDisabled,
handleRunPipeline,
handleRunPipelineByUid,
handleCancelPipeline,
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/store/slice/User/UserSelector.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { RootState } from 'store/store'

export const selectCurrentUser = (state: RootState) => state.user.currentUser
export const selectCurrentUserId = (state: RootState) =>
selectCurrentUser(state)?.id
export const selectCurrentUserUid = (state: RootState) =>
selectCurrentUser(state)?.uid
export const selectCurrentUserEmail = (state: RootState) =>
Expand Down
18 changes: 17 additions & 1 deletion frontend/src/store/slice/Workspace/WorkspaceSelector.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,23 @@
import { IS_STANDALONE } from 'const/Mode'
import { RootState } from 'store/store'

export const selectWorkspace = (state: RootState) => state.workspace
export const selectWorkspaceData = (state: RootState) => state.workspace.workspace
export const selectWorkspaceData = (state: RootState) =>
state.workspace.workspace

export const selectWorkspaceItem =
(workspaceId: number) => (state: RootState) =>
selectWorkspaceData(state).items.find((item) => item.id === workspaceId)

export const selectWorkspaceItemExists =
(workspaceId?: number) => (state: RootState) =>
workspaceId && selectWorkspaceItem(workspaceId)(state) !== void 0

export const selectIsCurrentUserOwnerWorkspaceItem =
(workspaceId: number, userId?: number) => (state: RootState) =>
IS_STANDALONE
? true
: selectWorkspaceItem(workspaceId)(state)?.user.id === userId

export const selectActiveTab = (state: RootState) =>
state.workspace.currentWorkspace.selectedTab
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/store/slice/Workspace/WorkspaceSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export const workspaceSlice = createSlice({
setActiveTab: (state, action: PayloadAction<number>) => {
state.currentWorkspace.selectedTab = action.payload
},
setCurrentWorkspace: (state, action: PayloadAction<string>) => {
setCurrentWorkspace: (state, action: PayloadAction<number>) => {
state.currentWorkspace.workspaceId = action.payload
},
clearCurrentWorkspace: (state) => {
Expand Down
Loading

0 comments on commit cbc6705

Please sign in to comment.