-
Notifications
You must be signed in to change notification settings - Fork 3
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
base: develop-main
Are you sure you want to change the base?
Changes from 21 commits
a01f454
bcc4e50
a3d7492
e3e7c52
25cb106
6e8b59a
0d12c34
12442b1
84ec063
ebe0eaa
d69bac3
d7d619d
b186f9d
8b22fdd
816b880
52feca6
aba3b9c
ac71de4
1293d41
46fbdee
7cfbdf2
848176c
45e5d35
46d2470
931505c
923f2db
7b457a4
db38497
2a6d8a0
7b05813
6b18579
cc5e9f5
5132361
124acaf
afeb0fa
cfc60e2
8f2ee83
5369313
6655f53
65bfce6
971a341
0253700
d581597
091606e
b94fb1a
aecc6f0
81cd712
ec36ba9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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" | ||
|
@@ -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, | ||
|
@@ -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 = () => { | ||
|
@@ -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> | ||
|
@@ -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), | ||
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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you place the following buttons
Design documents are being updated |
||
title="Dim 1" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Validate must be applied to input values
|
||
name="dim1" | ||
placeholder="1:128" | ||
value={dim1 || ""} | ||
onChangeInput={(v) => onChange("dim1", v)} | ||
/> | ||
<InputDim | ||
title="Dim 2" | ||
name="dim2" | ||
placeholder="1:128" | ||
value={dim2 || ""} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 || ""} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The input does not allow this input style "1:23,50:52" There was a problem hiding this comment. Choose a reason for hiding this commentThe 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[] | ||
|
@@ -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> | ||
) | ||
|
There was a problem hiding this comment.
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"