diff --git a/frontend/src/components/Workspace/Visualize/Plot/ImagePlot.tsx b/frontend/src/components/Workspace/Visualize/Plot/ImagePlot.tsx index cf69ff98d..39f9728d4 100644 --- a/frontend/src/components/Workspace/Visualize/Plot/ImagePlot.tsx +++ b/frontend/src/components/Workspace/Visualize/Plot/ImagePlot.tsx @@ -230,6 +230,9 @@ const ImagePlotChart = memo(function ImagePlotChart({ const [action, setAction] = useState("") const [positionDrag, setChangeSize] = useState() const clickedDataId = useSelector(selectClickedRoi(itemId)) + const clickedRois = useSelector( + (state: RootState) => state.visualaizeItem.clickedRois[itemId] || [], + ) const outputKey: string | null = useSelector(selectRoiItemOutputKeys(itemId)) @@ -344,12 +347,20 @@ const ImagePlotChart = memo(function ImagePlotChart({ const hex = rgba2hex(rgba, roiAlpha) const isClickPoint = pointClick.some((point) => point.z === i) + const isClickedRoi = clickedRois.includes(i.toString()) const isSelected = statusRoi?.temp_selected_roi?.includes(i) || false const isDeleted = statusRoi?.temp_delete_roi?.includes(i) || false const isMerged = statusRoi?.temp_merge_roi?.includes(i) || false const isAdded = statusRoi?.temp_add_roi?.includes(i) || false - if (isClickPoint || isSelected || isDeleted || isMerged || isAdded) { + if ( + isClickPoint || + isClickedRoi || + isSelected || + isDeleted || + isMerged || + isAdded + ) { switch (action) { case DELETE_ROI: if (isClickPoint || isSelected || isDeleted) @@ -360,17 +371,12 @@ const ImagePlotChart = memo(function ImagePlotChart({ return [offset, "#e134eb"] // purple break case ADD_ROI: - if (isAdded) return [offset, "3483eb"] // red + if (isAdded) return [offset, "#3483eb"] // blue break default: - if (isClickPoint || isSelected) return [offset, "#ffffff"] // white + return [offset, "#ffffff"] // white } } - if (clickedDataId !== null && i.toString() === clickedDataId) { - // eslint-disable-next-line no-console - console.log("#############\nImagePlot.tsx Change color") - return [offset, "#FF4500"] // Bright orange-red for clicked ROI - } return [offset, hex] }), diff --git a/frontend/src/store/slice/VisualizeItem/VisualizeItemSlice.ts b/frontend/src/store/slice/VisualizeItem/VisualizeItemSlice.ts index 7f190dfc2..41db946b4 100644 --- a/frontend/src/store/slice/VisualizeItem/VisualizeItemSlice.ts +++ b/frontend/src/store/slice/VisualizeItem/VisualizeItemSlice.ts @@ -867,7 +867,22 @@ export const visualaizeItemSlice = createSlice({ }>, ) => { const { itemId, clickedDataId } = action.payload - state.clickedRois[itemId] = clickedDataId + if (clickedDataId === null) { + state.clickedRois[itemId] = null + } else { + if (!state.clickedRois[itemId]) { + state.clickedRois[itemId] = [] + } + const index = state.clickedRois[itemId]!.indexOf(clickedDataId) + if (index === -1) { + state.clickedRois[itemId]!.push(clickedDataId) + } else { + state.clickedRois[itemId]!.splice(index, 1) + } + if (state.clickedRois[itemId]!.length === 0) { + state.clickedRois[itemId] = null + } + } }, }, extraReducers: (builder) => { @@ -921,11 +936,21 @@ export const visualaizeItemSlice = createSlice({ .addCase(setImageItemClickedDataId.fulfilled, (state, action) => { const { itemId: imageItemId, clickedDataId } = action.meta.arg // Update clickedRois - if (clickedDataId === state.clickedRois[imageItemId]) { - state.clickedRois[imageItemId] = null + if (!state.clickedRois[imageItemId]) { + state.clickedRois[imageItemId] = [] + } + + if (clickedDataId) { + const index = state.clickedRois[imageItemId]!.indexOf(clickedDataId) + if (index === -1) { + state.clickedRois[imageItemId]!.push(clickedDataId) + } else { + state.clickedRois[imageItemId]!.splice(index, 1) + } } else { - state.clickedRois[imageItemId] = clickedDataId + state.clickedRois[imageItemId] = null } + // Update drawOrderList for related time series items Object.values(state.items).forEach((item) => { if (isTimeSeriesItem(item)) { @@ -942,13 +967,8 @@ export const visualaizeItemSlice = createSlice({ item.drawOrderList.splice(index, 1) } } else { - // If clickedDataId is null (deselection), remove the previous selection - const previousSelection = state.clickedRois[imageItemId] - if (previousSelection) { - item.drawOrderList = item.drawOrderList.filter( - (id) => id !== previousSelection, - ) - } + // If clickedDataId is null (deselection), clear the drawOrderList + item.drawOrderList = state.clickedRois[imageItemId] || [] } } } @@ -957,13 +977,29 @@ export const visualaizeItemSlice = createSlice({ .addCase(selectingImageArea.fulfilled, (state, action) => { const { itemId: imageItemId } = action.meta.arg const selectedZList = action.payload + + if (!state.clickedRois[imageItemId]) { + state.clickedRois[imageItemId] = [] + } + selectedZList.forEach((z) => { + const index = state.clickedRois[imageItemId]!.indexOf(z) + if (index === -1) { + state.clickedRois[imageItemId]!.push(z) + } else { + state.clickedRois[imageItemId]!.splice(index, 1) + } + }) + if (state.clickedRois[imageItemId]!.length === 0) { + state.clickedRois[imageItemId] = null + } + Object.values(state.items).forEach((item) => { if (isTimeSeriesItem(item)) { if ( item.refImageItemId != null && imageItemId === item.refImageItemId ) { - item.drawOrderList = selectedZList + item.drawOrderList = state.clickedRois[imageItemId] || [] } } }) diff --git a/frontend/src/store/slice/VisualizeItem/VisualizeItemType.ts b/frontend/src/store/slice/VisualizeItem/VisualizeItemType.ts index 8cb4911a8..083145159 100644 --- a/frontend/src/store/slice/VisualizeItem/VisualizeItemType.ts +++ b/frontend/src/store/slice/VisualizeItem/VisualizeItemType.ts @@ -12,7 +12,7 @@ export type VisualaizeItem = { } layout: ItemLayout clickedRois: { - [itemId: number | string]: string | null + [itemId: number | string]: string[] | null } }