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

[No.129]Function with the ability to select cells (Data filter B… #536

Open
wants to merge 48 commits into
base: develop-main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
a01f454
TODO [No.129]Function with the ability to select cells (Data filter B…
sanglevinh Dec 23, 2024
bcc4e50
resolve abnormal workflow: refactor modules
Dec 23, 2024
a3d7492
resolve abnormal workflow: refactor modules
Dec 24, 2024
e3e7c52
fix linter
Dec 24, 2024
25cb106
resolve abnormal workflow: refactor modules
Dec 24, 2024
6e8b59a
resolve abnormal workflow: refactor modules
Dec 25, 2024
0d12c34
fix test
sanglevinh Dec 25, 2024
12442b1
resolve abnormal workflow: refactor modules
Dec 25, 2024
84ec063
fix minor bug in cancel_run
Dec 25, 2024
ebe0eaa
first commit for "resolive abnormal workflow"
Dec 27, 2024
d69bac3
Done Integrate API
sanglevinh Dec 27, 2024
d7d619d
minor fix for WorkflowMonitor
Dec 28, 2024
b186f9d
add check isUpdateDataFilter
sanglevinh Dec 30, 2024
8b22fdd
filter string empty in dim
sanglevinh Jan 3, 2025
816b880
fix dim
sanglevinh Jan 3, 2025
52feca6
fix undefined dataFilterParam
sanglevinh Jan 3, 2025
aba3b9c
clear dataFilterParam when run all
sanglevinh Jan 3, 2025
ac71de4
Fix comment.
sanglevinh Jan 6, 2025
1293d41
Merge remote-tracking branch 'origin/feature/resolve-abnormal-workflo…
sanglevinh Jan 6, 2025
46fbdee
Fix input Dim
sanglevinh Jan 7, 2025
7cfbdf2
reset data filter params when params parent changed
sanglevinh Jan 7, 2025
848176c
Add Slide to Slide BoxFilter
sanglevinh Jan 13, 2025
45e5d35
Add 3 button accept , cancel , reset data filter params
sanglevinh Jan 14, 2025
46d2470
fix check change filter
sanglevinh Jan 14, 2025
931505c
Fix test
sanglevinh Jan 15, 2025
923f2db
fix highlight roi
sanglevinh Jan 15, 2025
7b457a4
add slice range timeseriesplot
sanglevinh Jan 15, 2025
db38497
fĩ dependence
sanglevinh Jan 15, 2025
2a6d8a0
fix validate to > from
sanglevinh Jan 16, 2025
7b05813
fix return 0
sanglevinh Jan 16, 2025
6b18579
fix validate end > start
sanglevinh Jan 16, 2025
cc5e9f5
remove isUpdateFilter
sanglevinh Jan 17, 2025
5132361
Fix highlight roi
sanglevinh Jan 17, 2025
124acaf
fix color line
sanglevinh Jan 17, 2025
afeb0fa
fetch roi and Fluorescence when applied
sanglevinh Jan 20, 2025
cfc60e2
remove console log
sanglevinh Jan 20, 2025
8f2ee83
add dataFilterParam to runpostdata
sanglevinh Jan 21, 2025
5369313
fix test
sanglevinh Jan 21, 2025
6655f53
fix max min roi
sanglevinh Jan 21, 2025
65bfce6
add fitler roi
sanglevinh Jan 21, 2025
971a341
fix min dim and roid
sanglevinh Jan 21, 2025
0253700
remove max min from data input
sanglevinh Jan 21, 2025
d581597
Fix placeholder and min max
sanglevinh Jan 21, 2025
091606e
fix timeDataMaxIndex < 1
sanglevinh Jan 21, 2025
b94fb1a
fix api
sanglevinh Jan 21, 2025
aecc6f0
only show cell roi on popup filter
sanglevinh Jan 22, 2025
81cd712
fix remove drawOrderList when close popup filter
sanglevinh Jan 22, 2025
ec36ba9
fix undefined
sanglevinh Jan 22, 2025
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
3 changes: 3 additions & 0 deletions frontend/src/api/run/Run.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { Edge, Node } from "reactflow"

import { BASE_URL } from "const/API"
import { TDataFilterParam } from "store/slice/AlgorithmNode/AlgorithmNodeType"
import type {
AlgorithmNodeData,
InputNodeData,
Expand Down Expand Up @@ -34,13 +35,15 @@ export interface InputNodePostData extends InputNodeData {
param?: {
[key: string]: unknown
}
dataFilterParam?: TDataFilterParam
hdf5Path?: string
matPath?: string
}

export interface AlgorithmNodePostData extends AlgorithmNodeData {
path: string
param: ParamMap
dataFilterParam?: TDataFilterParam
}

export async function runApi(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
import { memo, SyntheticEvent, useEffect, useState } from "react"
import {
ChangeEvent,
memo,
SyntheticEvent,
useCallback,
useEffect,
useMemo,
useState,
} from "react"
import { useDispatch, useSelector } from "react-redux"

import styled from "@emotion/styled"
import CloseIcon from "@mui/icons-material/Close"
import { Input, InputProps } from "@mui/material"
import Box from "@mui/material/Box"
import Dialog from "@mui/material/Dialog"
import DialogContent from "@mui/material/DialogContent"
Expand All @@ -11,7 +21,12 @@ import Tab from "@mui/material/Tab"
import Tabs, { tabsClasses } from "@mui/material/Tabs"

import { DisplayDataItem } from "components/Workspace/Visualize/DisplayDataItem"
import { selectAlgorithmName } from "store/slice/AlgorithmNode/AlgorithmNodeSelectors"
import {
selectAlgorithmDataFilterParam,
selectAlgorithmName,
} from "store/slice/AlgorithmNode/AlgorithmNodeSelectors"
import { updateFilterParams } from "store/slice/AlgorithmNode/AlgorithmNodeSlice"
import { TDim } from "store/slice/AlgorithmNode/AlgorithmNodeType"
import { NodeIdProps } from "store/slice/FlowElement/FlowElementType"
import {
selectPipelineNodeResultOutputKeyList,
Expand All @@ -29,12 +44,14 @@ interface AlgorithmOutputDialogProps {
open: boolean
onClose: () => void
nodeId: string
allowFilter?: boolean
}

export const AlgorithmOutputDialog = memo(function AlgorithmOutputDialog({
open,
onClose,
nodeId,
allowFilter,
}: AlgorithmOutputDialogProps) {
const dispatch = useDispatch()
const closeFn = () => {
Expand All @@ -43,39 +60,36 @@ export const AlgorithmOutputDialog = memo(function AlgorithmOutputDialog({
}
return (
<Dialog open={open} onClose={closeFn} fullWidth>
<TitleWithCloseButton onClose={closeFn} nodeId={nodeId} />
<DialogContent
dividers
sx={{
pt: 1,
px: 2,
}}
>
<TitleWithCloseButton
title={allowFilter ? "Filter Data" : undefined}
onClose={closeFn}
nodeId={nodeId}
/>
<DialogContent dividers sx={{ pt: 1, px: 2 }}>
{open && <OutputViewer nodeId={nodeId} />}
{open && allowFilter ? <BoxFilter nodeId={nodeId} /> : null}
</DialogContent>
</Dialog>
)
})

interface TitleWithCloseButtonProps extends NodeIdProps {
onClose: () => void
title?: string
}

const TitleWithCloseButton = memo(function TitleWithCloseButtonProps({
nodeId,
onClose,
title,
}: TitleWithCloseButtonProps) {
const nodeName = useSelector(selectAlgorithmName(nodeId))
return (
<DialogTitle sx={{ m: 0, p: 2 }}>
Output of {nodeName}
{title ?? `Output of ${nodeName}`}
<IconButton
onClick={onClose}
sx={{
position: "absolute",
right: 8,
top: 10,
}}
sx={{ position: "absolute", right: 8, top: 10 }}
>
<CloseIcon />
</IconButton>
Expand All @@ -101,6 +115,141 @@ const OutputViewer = memo(function OutputViewer({ nodeId }: NodeIdProps) {
)
})

const InputDim = (
props: { title: string } & InputProps & {
onChangeInput?: (value?: string) => void
},
) => {
const { title, onChangeInput, ...p } = props
const [value, setValue] = useState(p.value)
const [valuePassed, setValuePassed] = useState<string>(p.value as string)

useEffect(() => {
setValue(p.value)
}, [p.value])

const onChange = useCallback((event: ChangeEvent<HTMLInputElement>) => {
const regex = /[^0-9,:]/g
const value = event.target.value.replace(regex, "")
const regexTest = /^(\d+:\d+)(,\d+:\d+)*$/
if (regexTest.test(value) || !value) setValuePassed(value)
setValue(value)
}, [])

const _onBlur = useCallback(() => {
setValue(valuePassed)
onChangeInput?.(valuePassed)
}, [onChangeInput, valuePassed])

return (
<Box>
<Box mb={1}>{title}</Box>
<InputStyled
{...p}
error={value !== valuePassed}
value={value}
onChange={onChange}
onBlur={_onBlur}
/>
</Box>
)
}

const InputStyled = styled(Input, {
shouldForwardProp: (props) => props !== "error",
})<{ error?: boolean }>`
input {
text-align: center;
}
&::after {
border-color: ${({ error }) => (error ? "#ff0000" : "#1976d2")};
}
`

const BoxFilter = ({ nodeId }: { nodeId: string }) => {
const dataFilterParams = useSelector(selectAlgorithmDataFilterParam(nodeId))
const dispatch = useDispatch()

const getData = useCallback(
(value?: TDim[]) =>
value
?.map((r) => {
if (!isNaN(r.start!) && !isNaN(r.end!)) return `${r.start}:${r.end}`
if (!isNaN(r.start!)) return r.start
if (!isNaN(r.end!)) return r.end
return ""
})
.toString(),
[],
)

const { dim1, dim2, dim3, roi } = useMemo(() => {
return {
dim1: getData(dataFilterParams?.dim1),
dim2: getData(dataFilterParams?.dim2),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good if these dimensions, from the real data, are used in the placeholders
placeholder="1:1000" -> placeholder="1:dim3"

dim3: getData(dataFilterParams?.dim3),
roi: getData(dataFilterParams?.roi),
}
}, [dataFilterParams, getData])

const onChange = useCallback(
(name: string, value?: string) => {
const values = value?.split(",").map((v) => {
if (!v) return ""
const array = v.split(":")
const dim: TDim = {}
if (array[0]) dim.start = Number(array[0])
if (array[1]) dim.end = Number(array[1])
return dim
})

dispatch(
updateFilterParams({
nodeId,
dataFilterParam: {
...dataFilterParams,
[name]: values?.filter(Boolean),
},
}),
)
},
[dataFilterParams, dispatch, nodeId],
)

return (
<Box display="flex" gap={2} textAlign="center" pt={2}>
<InputDim
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you place the following buttons

  • APPLY
  • CANCEL
  • RESET

Design documents are being updated

title="Dim 1"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Validate must be applied to input values

  • Numeric values start from 1
  • Compare the value to a larger or smaller value
  • Check the upper limit of the numerical value
    • This requires obtaining the upper limit of the actual data. If this is difficult to handle, please contact us.

name="dim1"
placeholder="1:128"
value={dim1 || ""}
onChangeInput={(v) => onChange("dim1", v)}
/>
<InputDim
title="Dim 2"
name="dim2"
placeholder="1:128"
value={dim2 || ""}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you input "1:0", you cannot delete the 0 using backspace. You need to highlight the whole text and delete, or add some more numbers and then delete those

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This conversation will be unresolved because the reviewer has not yet checked it.
*The reviewer should resolve the conversation.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@milesAraya I have fixed it.

onChangeInput={(v) => onChange("dim2", v)}
/>
<InputDim
title="Dim 3"
name="dim3"
placeholder="1:1000"
value={dim3 || ""}
onChangeInput={(v) => onChange("dim4", v)}
/>
<InputDim
title="ROI"
name="roi"
placeholder="1:23,50:52"
value={roi || ""}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The input does not allow this input style "1:23,50:52"
Comma is not possible

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@milesAraya I have fixed it.

onChangeInput={(v) => onChange("roi", v)}
/>
</Box>
)
}

interface OutputSelectTabsProps {
selectedOutoutKey: string
outputKeyList: string[]
Expand Down Expand Up @@ -165,12 +314,7 @@ const DisplayDataView = memo(function DisplayDataView({
}
}, [dispatch, nodeId, filePath, dataType, itemId])
return (
<Box
sx={{
mx: 1,
my: 2,
}}
>
<Box sx={{ mx: 1, my: 2 }}>
{itemId != null && <DisplayDataItem itemId={itemId} />}
</Box>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,12 @@ export const DialogContext = createContext<{
onOpenInputUrlDialog: (value: FileInputUrl) => void
onOpenClearWorkflowIdDialog: (value: ClearWorkflowIdDialogValue) => void
onMessageError: (value: ErrorDialogValue) => void
onOpenFilterDialog: (nodeId: string) => void
}>({
onOpenOutputDialog: () => null,
onOpenFileSelectDialog: () => null,
onOpenClearWorkflowIdDialog: () => null,
onOpenInputUrlDialog: () => null,
onMessageError: () => null,
onOpenFilterDialog: () => null,
})
10 changes: 10 additions & 0 deletions frontend/src/components/Workspace/FlowChart/FlowChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ const FlowChart = memo(function FlowChart(props: UseRunPipelineReturnType) {
})
const [fileViaUrl, setFileViaUrl] = useState("")
const [errorUrl, setErrorUrl] = useState("")
const [dialogFilterNodeId, setFilterDialogNodeId] = useState("")

const { enqueueSnackbar } = useSnackbar()

Expand Down Expand Up @@ -141,6 +142,7 @@ const FlowChart = memo(function FlowChart(props: UseRunPipelineReturnType) {
onOpenClearWorkflowIdDialog: setDialogClearWorkflowId,
onOpenInputUrlDialog: setDialogViaUrl,
onMessageError: setMessageError,
onOpenFilterDialog: setFilterDialogNodeId,
}}
>
<DndProvider backend={HTML5Backend}>
Expand All @@ -167,6 +169,14 @@ const FlowChart = memo(function FlowChart(props: UseRunPipelineReturnType) {
onClose={() => setDialogNodeId("")}
/>
)}
{dialogFilterNodeId && (
<AlgorithmOutputDialog
nodeId={dialogFilterNodeId}
open
onClose={() => setFilterDialogNodeId("")}
allowFilter
/>
)}
{dialogFile.open && (
<FileSelectDialog
multiSelect={dialogFile.multiSelect}
Expand Down
Loading
Loading