Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switch workflow by project id #84

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 32 additions & 13 deletions frontend/src/api/experiments/Experiments.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,42 @@
import axios from 'axios'

import { BASE_URL } from 'const/API'
import { RunPostData } from 'api/run/Run'
import { EdgeDict, NodeDict, OutputPathsDTO, RunPostData } from 'api/run/Run'
import { EXPERIMENTS_STATUS } from 'store/slice/Experiments/ExperimentsType'

export type ExperimentsDTO = {
[uid: string]: ExperimentDTO
}

export type ExperimentDTO = {
function: {
[uid: string]: {
name: string
success: string
unique_id: string
hasNWB: boolean
}
export type FunctionsDTO = {
[nodeId: string]: {
name: string
success: string
unique_id: string
hasNWB: boolean
message?: string
started_at?: string
finished_at?: string
outputPaths?: OutputPathsDTO
}
}

export type ExperimentDTO = {
function: FunctionsDTO
name: string
success: string
timestamp: string
success?: EXPERIMENTS_STATUS
started_at: string
finished_at?: string
unique_id: string
hasNWB: boolean
edgeDict: EdgeDict
nodeDict: NodeDict
}

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

Expand All @@ -49,6 +61,13 @@ export async function importExperimentByUidApi(
return response.data
}

export async function fetchExperimentApi(
projectId: string,
): Promise<ExperimentDTO> {
const response = await axios.get(`${BASE_URL}/experiments/fetch/${projectId}`)
return response.data
}

export async function downloadExperimentNwbApi(uid: string, nodeId?: string) {
const path =
nodeId != null
Expand Down
22 changes: 15 additions & 7 deletions frontend/src/api/run/Run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,20 @@ export interface AlgorithmNodePostData extends AlgorithmNodeData {
param: ParamMap
}

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

export async function runByUidApi(
projectId: string,
uid: string,
data: Omit<RunPostData, 'name'>,
): Promise<string> {
const response = await axios.post(`${BASE_URL}/run/${uid}`, data)
const response = await axios.post(`${BASE_URL}/run/${projectId}/${uid}`, data)
return response.data
}

Expand All @@ -72,12 +76,16 @@ export type OutputPathsDTO = {
}

export async function runResult(data: {
projectId: string
uid: string
pendingNodeIdList: string[]
}): Promise<RunResultDTO> {
const { uid, pendingNodeIdList } = data
const response = await axios.post(`${BASE_URL}/run/result/${uid}`, {
pendingNodeIdList,
})
const { projectId, uid, pendingNodeIdList } = data
const response = await axios.post(
`${BASE_URL}/run/result/${projectId}/${uid}`,
{
pendingNodeIdList,
},
)
return response.data
}
111 changes: 76 additions & 35 deletions frontend/src/components/FlowChart/FlowChartNode/FileSelect.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
// TODO: Change for this file must be reverted before merge
import React, { useContext } from 'react'
import { Button, Typography } from '@mui/material'
import ButtonGroup from '@mui/material/ButtonGroup'

import { FILE_TREE_TYPE } from 'api/files/Files'
import { FILE_TREE_TYPE, FILE_TREE_TYPE_SET } from 'api/files/Files'
import { LinearProgressWithLabel } from './LinerProgressWithLabel'
import { FILE_TYPE } from 'store/slice/InputNode/InputNodeType'
import { useFileUploader } from 'store/slice/FileUploader/FileUploaderHook'
import { useNavigate, useSearchParams } from 'react-router-dom'
import { DialogContext } from '../DialogContext'
import { getLabelByPath } from 'store/slice/FlowElement/FlowElementUtils'
import { DialogContext } from 'components/FlowChart/DialogContext'

export const FileSelect = React.memo<{
multiSelect?: boolean
Expand Down Expand Up @@ -35,7 +36,6 @@ export const FileSelect = React.memo<{
</div>
)}
<FileSelectImple
nodeId={nodeId}
multiSelect={multiSelect}
filePath={filePath}
onSelectFile={onChangeFilePath}
Expand All @@ -60,52 +60,93 @@ type FileSelectImpleProps = {
fileTreeType?: FILE_TREE_TYPE
selectButtonLabel?: string
uploadButtonLabel?: string
nodeId?: string
}

export const FileSelectImple = React.memo<FileSelectImpleProps>(
({ filePath, nodeId }) => {
const navigate = useNavigate()
const [searchParams] = useSearchParams()
const { onOpenImageAlignment } = useContext(DialogContext)
const id = searchParams.get('id')
const getNameSelectec = () => {
if (Array.isArray(filePath)) {
return `${filePath.length} images selected.`
({
multiSelect = false,
filePath,
onSelectFile,
onUploadFile,
fileTreeType,
selectButtonLabel,
uploadButtonLabel,
}) => {
const { onOpenDialogFile } = useContext(DialogContext)

const onFileInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
event.preventDefault()
if (event.target.files != null && event.target.files[0] != null) {
const file = event.target.files[0]
const formData = new FormData()
formData.append('file', file)
const fileName = file.name
onUploadFile(formData, fileName)
}
return `${filePath ? 1 : 0} images selected.`
}

const inputRef = React.useRef<HTMLInputElement>(null)
const onClick = () => {
if (inputRef.current != null) {
inputRef.current.click()
}
}
const accept = getFileInputAccept(fileTreeType)
const fileName = getLabelByPath(filePath)
return (
<div style={{ padding: 16 }}>
<ButtonGroup size="small" style={{ width: '90%', margin: 'auto' }}>
<div
style={{
padding: 5,
}}
>
<ButtonGroup size="small" style={{ marginRight: 4 }}>
<Button
style={{ width: '80%' }}
variant="outlined"
onClick={() =>
navigate(
`/projects/new-project?id=${id}&back=/projects/workflow?tab=0&id=${id}`,
)
}
onClick={() => {
onOpenDialogFile({
open: true,
multiSelect,
filePath,
fileTreeType,
onSelectFile,
})
}}
>
EDIT IMAGESET
{!!selectButtonLabel ? selectButtonLabel : 'Select File'}
</Button>
<Button onClick={onClick} variant="outlined">
{!!uploadButtonLabel ? uploadButtonLabel : 'Load'}
</Button>
</ButtonGroup>
<div style={{ marginTop: 8 }}>
<div>
<input
ref={inputRef}
type="file"
onChange={onFileInputChange}
accept={accept}
style={{
visibility: 'hidden',
width: 0,
height: 0,
}}
/>
<Typography className="selectFilePath" variant="caption">
{getNameSelectec()}
{!!fileName ? fileName : 'No file is selected.'}
</Typography>
</div>
<ButtonGroup size="small" style={{ width: '90%', margin: '8px 0' }}>
<Button
onClick={() => onOpenImageAlignment(true, { nodeId })}
style={{ width: '80%' }}
variant="outlined"
>
ALIGNMENT
</Button>
</ButtonGroup>
</div>
)
},
)

function getFileInputAccept(fileType: FILE_TREE_TYPE | undefined) {
switch (fileType) {
case FILE_TREE_TYPE_SET.IMAGE:
return '.tif,.tiff'
case FILE_TREE_TYPE_SET.CSV:
return '.csv'
case FILE_TREE_TYPE_SET.HDF5:
return '.hdf5,.nwb'
default:
return undefined
}
}
12 changes: 6 additions & 6 deletions frontend/src/components/Table/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import ReactPaginate from 'react-paginate'
import KeyboardArrowLeftIcon from '@mui/icons-material/KeyboardArrowLeft'
import ChevronRightIcon from '@mui/icons-material/ChevronRight'
import ArrowDownwardIcon from '@mui/icons-material/ArrowDownward'
import { DataProject } from 'pages/Projects'
import { ProjectType } from 'store/slice/Project/ProjectType'

export type Column = {
width?: number | string
Expand All @@ -14,14 +14,14 @@ export type Column = {
align?: string
filter?: boolean
render?: (
item: DataProject,
item: ProjectType,
value?: string | object | number,
index?: number,
) => JSX.Element | null | undefined
}

type TableComponentProps = {
data?: DataProject[]
data?: ProjectType[]
orderBy?: 'ASC' | 'DESC'
orderKey?: string
className?: string
Expand Down Expand Up @@ -51,8 +51,8 @@ const TableComponent: FC<TableComponentProps> = (props) => {
const pageCount = (paginate?.total || 0) / (paginate?.page_size || 1)

const renderCol = useCallback(
(col: Column, item: DataProject, index: number) => {
const value = item[(col.name || col.dataIndex || '') as keyof DataProject]
(col: Column, item: ProjectType, index: number) => {
const value = item[(col.name || col.dataIndex || '') as keyof ProjectType]
if (col.render) return col.render(item, value, index)
return value || null
},
Expand Down Expand Up @@ -191,7 +191,7 @@ const Td = styled('td')(({ theme }) => ({
padding: theme.spacing(2),
borderBottom: '1px solid rgba(224, 224, 224, 1)',
maxWidth: 155,
wordBreak: 'break-word'
wordBreak: 'break-word',
}))

const NoData = styled(Typography)({
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/pages/AccountManager/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import InputError from '../../components/common/InputError'
import SelectError from '../../components/common/SelectError'
import { createUser, deleteUser, editUser, listUser } from 'api/auth'
import { useUser } from 'providers'
import { DataProject } from 'pages/Projects'
import { ProjectType } from 'store/slice/Project/ProjectType'
import { isAdmin, optionsRole } from 'utils/auth'
import Loading from '../../components/common/Loading'

Expand Down Expand Up @@ -304,7 +304,7 @@ const AccountManager = () => {
setOpenDelete(true)
}

const onForgotPassword = (data: DataProject) => {
const onForgotPassword = (data: ProjectType) => {
let newData
if (data.role === 'Admin') newData = { ...data, role: 1 }
else if (data.role === 'Data Manager') newData = { ...data, role: 10 }
Expand Down
38 changes: 7 additions & 31 deletions frontend/src/pages/Projects/index.tsx
Original file line number Diff line number Diff line change
@@ -1,41 +1,17 @@
import { Box, Button, styled } from '@mui/material'
import { useCallback, useMemo, useState } from 'react'
import { useSelector, useDispatch } from 'react-redux'
import TableComponent, { Column } from '../../components/Table'
import { useNavigate } from 'react-router-dom'
import ModalDeleteAccount from 'components/ModalDeleteAccount'

export type DataProject = {
id: number | string
uid?: number | string
name: string
project_type: number
image_count: number
created_time: string
updated_time: string
role?: string | number
}
import { selectProjectList } from 'store/slice/Project/ProjectSelector'
import { deleteProject } from 'store/slice/Project/ProjectSlice'

const Projects = () => {
const navigate = useNavigate()
const dispatch = useDispatch()
const projects = useSelector(selectProjectList)
const [idDelete, setIdDelete] = useState<number | string | undefined>()
const [data, setData] = useState<DataProject[]>([
{
id: '1',
name: 'prj name 1',
created_time: '2023-03-10 09:19',
updated_time: '2023-03-10 09:19',
image_count: 3,
project_type: 0,
},
{
id: '2',
name: 'prj name 2',
created_time: '2023-03-10 09:19',
updated_time: '2023-03-10 09:19',
image_count: 3,
project_type: 1,
},
])

const onEdit = useCallback((id: number | string) => {
navigate(`/projects/new-project?id=${id}`)
Expand Down Expand Up @@ -66,7 +42,7 @@ const Projects = () => {
const onDeleteSubmit = () => {
const id = idDelete
setIdDelete(undefined)
setData(data.filter((e) => e.id !== id))
dispatch(deleteProject(id))
}

const handleCloseDelete = () => {
Expand Down Expand Up @@ -133,7 +109,7 @@ const Projects = () => {
</BoxButton>
<TableComponent
paginate={{ total: 100, page: 1, page_size: 10 }}
data={data}
data={projects}
columns={columns}
/>
</ProjectsWrapper>
Expand Down
Loading