From 0bd70b92f4e65c6cdfcc468cd7bac4d709931ab5 Mon Sep 17 00:00:00 2001 From: salam dalloul Date: Wed, 2 Oct 2024 22:28:18 +0200 Subject: [PATCH 1/4] #75 Connect the colour picker to the context neuron data --- .../ViewerContainer/CustomListItem.tsx | 7 ++++++- .../src/components/ViewerContainer/Neurons.tsx | 2 ++ .../frontend/src/models/workspace.ts | 18 ++++++++++++++++++ 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/applications/visualizer/frontend/src/components/ViewerContainer/CustomListItem.tsx b/applications/visualizer/frontend/src/components/ViewerContainer/CustomListItem.tsx index a0893968..12a79d91 100644 --- a/applications/visualizer/frontend/src/components/ViewerContainer/CustomListItem.tsx +++ b/applications/visualizer/frontend/src/components/ViewerContainer/CustomListItem.tsx @@ -1,6 +1,7 @@ import { Add as AddIcon, DeleteOutlined as DeleteOutlinedIcon, HelpOutline as HelpOutlineIcon } from "@mui/icons-material"; import { Box, FormControlLabel, IconButton, Stack, Tooltip, Typography } from "@mui/material"; import { useState } from "react"; +import { ViewerType, type Workspace } from "../../models"; import { vars } from "../../theme/variables.ts"; import CustomSwitch from "./CustomSwitch"; import PickerWrapper from "./PickerWrapper"; @@ -20,6 +21,7 @@ interface CustomListItemProps { onSwitchChange?: (id: string, checked: boolean) => void; onDelete?: (id: string) => void; deleteTooltipTitle?: string; + workspace: Workspace; } const CustomListItem = ({ data, @@ -29,6 +31,7 @@ const CustomListItem = ({ onSwitchChange, onDelete, deleteTooltipTitle, + workspace, }: CustomListItemProps) => { const [anchorEl, setAnchorEl] = useState(null); const [open, setOpen] = useState(false); @@ -55,7 +58,9 @@ const CustomListItem = ({ }; const handleColorChange = (color) => { - setSelectedColor(color.hex); + const hexColor = color.hex; + setSelectedColor(hexColor); + workspace.changeNeuronColorForViewers(data.id, hexColor, [ViewerType.ThreeD, ViewerType.EM]); }; const handleOnMouseEnter = () => { diff --git a/applications/visualizer/frontend/src/components/ViewerContainer/Neurons.tsx b/applications/visualizer/frontend/src/components/ViewerContainer/Neurons.tsx index a7b4b676..c428c0b5 100644 --- a/applications/visualizer/frontend/src/components/ViewerContainer/Neurons.tsx +++ b/applications/visualizer/frontend/src/components/ViewerContainer/Neurons.tsx @@ -123,6 +123,7 @@ const Neurons = ({ children }) => { onSwitchChange={handleSwitchChange} onDelete={handleDeleteNeuron} deleteTooltipTitle="Remove neuron from the workspace" + workspace={currentWorkspace} /> ))} @@ -150,6 +151,7 @@ const Neurons = ({ children }) => { onSwitchChange={handleSwitchChange} onDelete={() => console.log("delete")} deleteTooltipTitle="Remove group from the workspace" + workspace={currentWorkspace} /> ))} diff --git a/applications/visualizer/frontend/src/models/workspace.ts b/applications/visualizer/frontend/src/models/workspace.ts index 8cef28e5..773b7d2a 100644 --- a/applications/visualizer/frontend/src/models/workspace.ts +++ b/applications/visualizer/frontend/src/models/workspace.ts @@ -257,4 +257,22 @@ export class Workspace { getVisibleNeuronsInThreeD(): string[] { return Array.from(this.activeNeurons).filter((neuronId) => this.visibilities[neuronId]?.[ViewerType.ThreeD]?.visibility === Visibility.Visible); } + + changeNeuronColorForViewers(neuronId: string, color: string, viewerTypes: ViewerType[] = [ViewerType.ThreeD, ViewerType.EM]): void { + const unsupportedTypes = viewerTypes.filter((type) => type !== ViewerType.ThreeD && type !== ViewerType.EM); + + if (unsupportedTypes.length > 0) { + throw new Error(`Unsupported viewer types: ${unsupportedTypes.join(", ")}`); + } + + const updated = produce(this, (draft: Workspace) => { + viewerTypes.forEach((viewerType) => { + if (viewerType in draft.visibilities[neuronId]) { + draft.visibilities[neuronId][viewerType].color = color; + } + }); + }); + + this.updateContext(updated); + } } From 834ab60ae936dc819f09e8f0ab7a3e7ae407b9d7 Mon Sep 17 00:00:00 2001 From: salam dalloul Date: Wed, 2 Oct 2024 22:30:43 +0200 Subject: [PATCH 2/4] change changing wireframe icon tooltip text --- .../frontend/src/components/viewers/ThreeD/SceneControls.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/applications/visualizer/frontend/src/components/viewers/ThreeD/SceneControls.tsx b/applications/visualizer/frontend/src/components/viewers/ThreeD/SceneControls.tsx index d1866c96..f6d4804c 100644 --- a/applications/visualizer/frontend/src/components/viewers/ThreeD/SceneControls.tsx +++ b/applications/visualizer/frontend/src/components/viewers/ThreeD/SceneControls.tsx @@ -104,7 +104,7 @@ function SceneControls({ cameraControlRef, isWireframe, setIsWireframe }) { - + setIsWireframe(!isWireframe)}> From f99c449ae85fdcb248c758d01a63b521718d3872 Mon Sep 17 00:00:00 2001 From: salam dalloul Date: Wed, 2 Oct 2024 22:34:11 +0200 Subject: [PATCH 3/4] fix linter issue --- .../frontend/src/components/ViewerContainer/CustomListItem.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/applications/visualizer/frontend/src/components/ViewerContainer/CustomListItem.tsx b/applications/visualizer/frontend/src/components/ViewerContainer/CustomListItem.tsx index 12a79d91..8f470fe9 100644 --- a/applications/visualizer/frontend/src/components/ViewerContainer/CustomListItem.tsx +++ b/applications/visualizer/frontend/src/components/ViewerContainer/CustomListItem.tsx @@ -21,7 +21,7 @@ interface CustomListItemProps { onSwitchChange?: (id: string, checked: boolean) => void; onDelete?: (id: string) => void; deleteTooltipTitle?: string; - workspace: Workspace; + workspace?: Workspace; } const CustomListItem = ({ data, From 7c9ad2df18536209d58e3bc6fc873862db8a007c Mon Sep 17 00:00:00 2001 From: salam dalloul Date: Thu, 3 Oct 2024 13:35:04 +0200 Subject: [PATCH 4/4] Relocate workspace logic to Neurons component and include color in neuron list items to put the correct default value --- .../ViewerContainer/CustomListItem.tsx | 13 ++++++------- .../src/components/ViewerContainer/Neurons.tsx | 17 +++++++++++++---- .../visualizer/frontend/src/models/workspace.ts | 10 +++------- 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/applications/visualizer/frontend/src/components/ViewerContainer/CustomListItem.tsx b/applications/visualizer/frontend/src/components/ViewerContainer/CustomListItem.tsx index 8f470fe9..d1220264 100644 --- a/applications/visualizer/frontend/src/components/ViewerContainer/CustomListItem.tsx +++ b/applications/visualizer/frontend/src/components/ViewerContainer/CustomListItem.tsx @@ -1,7 +1,6 @@ import { Add as AddIcon, DeleteOutlined as DeleteOutlinedIcon, HelpOutline as HelpOutlineIcon } from "@mui/icons-material"; import { Box, FormControlLabel, IconButton, Stack, Tooltip, Typography } from "@mui/material"; import { useState } from "react"; -import { ViewerType, type Workspace } from "../../models"; import { vars } from "../../theme/variables.ts"; import CustomSwitch from "./CustomSwitch"; import PickerWrapper from "./PickerWrapper"; @@ -14,6 +13,7 @@ interface CustomListItemProps { checked: boolean; helpText?: string; description?: string; + color?: string; }; showTooltip?: boolean; listType: string; @@ -21,7 +21,7 @@ interface CustomListItemProps { onSwitchChange?: (id: string, checked: boolean) => void; onDelete?: (id: string) => void; deleteTooltipTitle?: string; - workspace?: Workspace; + onColorChange?: (id: string, color: string) => void; } const CustomListItem = ({ data, @@ -31,11 +31,11 @@ const CustomListItem = ({ onSwitchChange, onDelete, deleteTooltipTitle, - workspace, + onColorChange, }: CustomListItemProps) => { const [anchorEl, setAnchorEl] = useState(null); const [open, setOpen] = useState(false); - const [selectedColor, setSelectedColor] = useState("#9FEE9A"); + const [selectedColor, setSelectedColor] = useState(data.color); const [itemHovered, setItemHovered] = useState(false); const isNeurons = listType === "neurons"; @@ -58,9 +58,8 @@ const CustomListItem = ({ }; const handleColorChange = (color) => { - const hexColor = color.hex; - setSelectedColor(hexColor); - workspace.changeNeuronColorForViewers(data.id, hexColor, [ViewerType.ThreeD, ViewerType.EM]); + setSelectedColor(color.hex); + onColorChange(data.id, color); }; const handleOnMouseEnter = () => { diff --git a/applications/visualizer/frontend/src/components/ViewerContainer/Neurons.tsx b/applications/visualizer/frontend/src/components/ViewerContainer/Neurons.tsx index c428c0b5..a4c5a1ec 100644 --- a/applications/visualizer/frontend/src/components/ViewerContainer/Neurons.tsx +++ b/applications/visualizer/frontend/src/components/ViewerContainer/Neurons.tsx @@ -3,7 +3,7 @@ import { Box, IconButton, Stack, Typography } from "@mui/material"; import Tooltip from "@mui/material/Tooltip"; import { useState } from "react"; import { useGlobalContext } from "../../contexts/GlobalContext.tsx"; -import { type ViewerData, Visibility } from "../../models/models.ts"; +import { type ViewerData, ViewerType, Visibility } from "../../models/models.ts"; import type { Neuron } from "../../rest"; import { vars } from "../../theme/variables.ts"; import CustomEntitiesDropdown from "./CustomEntitiesDropdown.tsx"; @@ -15,6 +15,12 @@ const mapToListItem = (neuron: string, visibility: ViewerData) => ({ label: neuron, checked: Object.values(visibility).every((e) => e === undefined || e.visibility === Visibility.Visible), }); +const mapNeuronsToListItem = (neuron: string, visibility: ViewerData) => ({ + id: neuron, + label: neuron, + checked: Object.values(visibility).every((e) => e === undefined || e.visibility === Visibility.Visible), + color: visibility[ViewerType.ThreeD]?.color || visibility[ViewerType.EM]?.color || "#000000", +}); const neuronToOption = (neuron: Neuron) => ({ id: neuron.name, @@ -59,6 +65,9 @@ const Neurons = ({ children }) => { ); setNeurons(filteredNeurons); }; + const handleColorChange = (neuronId, color) => { + currentWorkspace.changeNeuronColorForViewers(neuronId, color.hex); + }; const autoCompleteOptions = Object.values(neurons) .map((neuron: Neuron) => neuronToOption(neuron)) @@ -116,14 +125,14 @@ const Neurons = ({ children }) => { {Array.from(activeNeurons).map((neuronId) => ( ))} @@ -151,7 +160,7 @@ const Neurons = ({ children }) => { onSwitchChange={handleSwitchChange} onDelete={() => console.log("delete")} deleteTooltipTitle="Remove group from the workspace" - workspace={currentWorkspace} + onColorChange={handleColorChange} /> ))} diff --git a/applications/visualizer/frontend/src/models/workspace.ts b/applications/visualizer/frontend/src/models/workspace.ts index 773b7d2a..c9edbd42 100644 --- a/applications/visualizer/frontend/src/models/workspace.ts +++ b/applications/visualizer/frontend/src/models/workspace.ts @@ -258,15 +258,11 @@ export class Workspace { return Array.from(this.activeNeurons).filter((neuronId) => this.visibilities[neuronId]?.[ViewerType.ThreeD]?.visibility === Visibility.Visible); } - changeNeuronColorForViewers(neuronId: string, color: string, viewerTypes: ViewerType[] = [ViewerType.ThreeD, ViewerType.EM]): void { - const unsupportedTypes = viewerTypes.filter((type) => type !== ViewerType.ThreeD && type !== ViewerType.EM); - - if (unsupportedTypes.length > 0) { - throw new Error(`Unsupported viewer types: ${unsupportedTypes.join(", ")}`); - } + changeNeuronColorForViewers(neuronId: string, color: string): void { + const viewers: ViewerType[] = [ViewerType.ThreeD, ViewerType.EM]; const updated = produce(this, (draft: Workspace) => { - viewerTypes.forEach((viewerType) => { + viewers.forEach((viewerType) => { if (viewerType in draft.visibilities[neuronId]) { draft.visibilities[neuronId][viewerType].color = color; }