Loading app/src/components/RightPanel/ChromatinViewportConfigurationPanel.tsx +13 −12 Original line number Diff line number Diff line Loading @@ -6,7 +6,7 @@ import './RightPanel.scss'; import { ChromatinRepresentation, SmoothCamera, SmoothCameraConfiguration } from "../../modules/graphics"; import { Text } from '@fluentui/react/lib/Text'; import { ChromatinViewportAggregationFunction, ChromatinViewportColorMappingMode, ChromatinViewportConfiguration, ConfigurationAction, ConfigurationState, LabelingDebugTexture, TooltipNumericAggregation, TooltipTextAggregation, ViewportConfigurationType } from '../../modules/storage/models/viewports'; import { ChromatinViewportAggregationFunction, ChromatinViewportColorMappingMode, ChromatinViewportConfiguration, ConfigurationAction, ConfigurationState, IChromatinDataConfiguration, LabelingDebugTexture, TooltipNumericAggregation, TooltipTextAggregation, ViewportConfigurationType } from '../../modules/storage/models/viewports'; import { BinPositionsData, DataAction, DataID, DataState, isoDataID } from "../../modules/storage/models/data"; import { SelectionAction, SelectionState } from "../../modules/storage/models/selections"; import { useConfiguration, useSelections, useViewportName } from "../hooks"; Loading Loading @@ -209,7 +209,7 @@ export function ChromatinViewportConfigurationPanel(props: { const [isBackgroundColorCalloutVisible, setIsBackgroundColorCalloutVisible] = useState<boolean>(false); const selections = useSelections(0, [configuration, updateConfiguration], props.dataReducer, props.selectionsReducer, 0); const selections = useSelections([configuration, updateConfiguration], props.dataReducer, props.selectionsReducer, configuration.selectedDatum); //#region Viewport Settings const setBackgroundColor = (event: React.SyntheticEvent<HTMLElement>, color: IColor): void => { Loading Loading @@ -243,12 +243,12 @@ export function ChromatinViewportConfigurationPanel(props: { const removeData3D = (index: number) => { if (!configuration) return; const newData = [...configuration.data]; const newData: IChromatinDataConfiguration[] = [...configuration.data]; newData.splice(index, 1); updateConfiguration({ ...configuration, selectedDatum: configuration.selectedDatum == index ? null : configuration.selectedDatum, selectedSelectionID: null, data: newData, }); }; Loading @@ -256,7 +256,7 @@ export function ChromatinViewportConfigurationPanel(props: { const addData = () => { if (!configuration || !selectedPrimaryData) return; const data = [...configuration.data]; const newData = [...configuration.data]; //#region Calculate radius range const positions = (selectedPrimaryData.type == '3d-positions' ? selectedPrimaryData as BinPositionsData : selectedSecondaryData as BinPositionsData).values; Loading @@ -273,7 +273,7 @@ export function ChromatinViewportConfigurationPanel(props: { const radiusRange = { min: 0.0, max: quantiles[0] / 2.0 }; //#region Calculate radius range data.push({ newData.push({ id: selectedPrimaryData.id, secondaryID: selectedSecondaryDataID, Loading @@ -286,6 +286,7 @@ export function ChromatinViewportConfigurationPanel(props: { radius, radiusRange, selectedSelectionID: null, selections: [], mapValues: { Loading Loading @@ -324,19 +325,19 @@ export function ChromatinViewportConfigurationPanel(props: { updateConfiguration({ ...configuration, data, data: newData, }); }; const setDataColor = (ev: React.SyntheticEvent<HTMLElement, Event>, color: IColor): void => { if (configuration.selectedDatum == null) return; const data = [...configuration.data]; data[configuration.selectedDatum] = { ...data[configuration.selectedDatum], color }; const newData = [...configuration.data]; newData[configuration.selectedDatum] = { ...newData[configuration.selectedDatum], color }; updateConfiguration({ ...configuration, data data: newData }); }; Loading Loading @@ -607,7 +608,7 @@ export function ChromatinViewportConfigurationPanel(props: { (<div className={"treeViewListItem " + (configuration.selectedDatum == index ? 'selected' : '')} key={index} onClick={() => setSelectedDatum(index)}> <span style={{ display: 'block', width: '4px' }}></span> <Text className="text" nowrap>{datum.id}</Text> <Delete16Regular primaryFill={'white'} className='icon iconHoverRed' onClick={() => removeData3D(index)}></Delete16Regular> <Delete16Regular primaryFill={'white'} className='icon iconHoverRed' onClick={(e) => { e.stopPropagation(); removeData3D(index); } }></Delete16Regular> </div>) )} Loading Loading @@ -862,7 +863,7 @@ export function ChromatinViewportConfigurationPanel(props: { {/* SELECTIONS */} <div style={{ display: 'block', width: '100%', marginTop: '16px' }}></div> <Separator></Separator> {configuration.selectedDatum && ( {configuration.selectedDatum != null && ( <SelectionsPart selections={selections} configurationReducer={configurationReducer} Loading app/src/components/RightPanel/SelectionsPart.tsx +31 −7 Original line number Diff line number Diff line import { DistanceMapDataConfiguration, ViewportConfiguration, ViewportConfigurationType, ViewportSelectionOptions } from "../../modules/storage/models/viewports"; import { DistanceMapDataConfiguration, ChromatinViewportConfiguration, ViewportConfiguration, ViewportConfigurationType, ViewportSelectionOptions } from "../../modules/storage/models/viewports"; import { DataAction, DataID, DataState } from "../../modules/storage/models/data"; import { isoSelectionID, SelectionAction, SelectionActionKind, SelectionID, Selection, SelectionState } from "../../modules/storage/models/selections"; import { ConfigurationReducer, ConfigurationsWithSelections } from "../hooks"; Loading Loading @@ -49,17 +49,33 @@ export function SelectionsPart<T extends ConfigurationsWithSelections>(props: Pr const dataSize = data.data.find(d => d.id == selectedDataPartID)?.values?.length; if (dataSize) { console.log('adding selection'); globalSelectionsDispatch({ type: SelectionActionKind.ADD, dataID: selectedDataPartID as DataID, dataSize }); } } } const selectSelection = (selectionID: SelectionID) => { if (configuration.type === ViewportConfigurationType.Chromatin && configuration.selectedDatum != null) { const newData = [...configuration.data]; newData[configuration.selectedDatum] = { ...newData[configuration.selectedDatum], selectedSelectionID: selectionID, }; updateConfiguration({ ...configuration, data: newData }); console.log(configuration); } else { updateConfiguration({ ...configuration, selectedSelectionID: selectionID, }); } } const handleRenameStart = (selection: Selection) => setRenaming({ id: selection.id, newName: selection.name }) const handleRenameChange = (newName: string | undefined) => setRenaming({ ...renaming!, newName: newName ?? "" }) Loading @@ -74,7 +90,6 @@ export function SelectionsPart<T extends ConfigurationsWithSelections>(props: Pr name: renaming!.newName.length == 0 ? "unnamed" : renaming!.newName }) setRenaming(null); } const setSelectionVisiblity = (selectionID: SelectionID, visible: boolean, dataIndex = 0) => { Loading Loading @@ -144,7 +159,16 @@ export function SelectionsPart<T extends ConfigurationsWithSelections>(props: Pr a: color.a != undefined ? (color.a / 255) : 1 }, }); } const isSelected = (id: SelectionID) => { if (configuration.type === ViewportConfigurationType.Chromatin && configuration.selectedDatum && configuration.data[configuration.selectedDatum]) { return configuration.data[configuration.selectedDatum].selectedSelectionID == id; } else { return configuration.selectedSelectionID == id; } return false; } return <> Loading @@ -161,7 +185,7 @@ export function SelectionsPart<T extends ConfigurationsWithSelections>(props: Pr <div ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps} className={selection.id == configuration.selectedSelectionID ? "treeViewListItem selected" : "treeViewListItem"} className={isSelected(selection.id) ? "treeViewListItem selected" : "treeViewListItem"} onClick={() => selectSelection(selection.id)}> <DefaultButton id="selectionColorButton" style={{ Loading app/src/components/RightPanel/TADMapViewportConfiguration.tsx +1 −1 Original line number Diff line number Diff line Loading @@ -25,7 +25,7 @@ export function TADMapViewportConfiguration(props: { const [viewportName, setViewportName] = useViewportName(props.node, props.configurationsReducer); const selections = useSelections(0, [configuration, updateConfiguration], props.dataReducer, props.selectionsReducer, 0); const selections = useSelections([configuration, updateConfiguration], props.dataReducer, props.selectionsReducer, 0); const dataList = data.data.filter(d => d.type == 'sparse-distance-matrix' || d.type == '3d-positions').map(d => { return { Loading app/src/components/Tools/ToolOptions.tsx +6 −1 Original line number Diff line number Diff line Loading @@ -16,7 +16,12 @@ export function ToolOptions(props: { const [configuration, updateConfiguration] = configurationReducer; const tool = configuration.tool; const isMac = new UAParser().getOS().name == 'Mac OS'; const hasSelectedSelection = configuration.selectedSelectionID != null; let hasSelectedSelection = configuration.selectedSelectionID != null; if (configuration.type == ViewportConfigurationType.Chromatin && configuration.selectedDatum && configuration.data[configuration.selectedDatum]) { hasSelectedSelection = configuration.data[configuration.selectedDatum].selectedSelectionID != null; } const enforceSelectedSelection = (element: JSX.Element): JSX.Element => { Loading app/src/components/hooks.ts +30 −17 Original line number Diff line number Diff line Loading @@ -2,8 +2,8 @@ import { Actions, Model, TabNode } from "flexlayout-react"; import { Dispatch, useEffect, useState, useCallback } from "react"; import { useFreshTick } from "rooks"; import { ChromatinViewportConfiguration, ConfigurationAction, ConfigurationActionKind, ConfigurationState, dataIndex, DistanceViewportConfiguration, ForceGraphViewportConfiguration, IViewportConfiguration, ViewportConfiguration, ViewportSelectionOptions } from "../modules/storage/models/viewports"; import { DataAction, DataState } from "../modules/storage/models/data"; import { SelectionAction, Selection, SelectionState } from "../modules/storage/models/selections"; import { DataAction, DataID, DataState } from "../modules/storage/models/data"; import { SelectionAction, Selection, SelectionState, SelectionID } from "../modules/storage/models/selections"; // Only configurations that have selections can use this part export type ConfigurationsWithSelections = ChromatinViewportConfiguration | DistanceViewportConfiguration | ForceGraphViewportConfiguration; Loading Loading @@ -67,29 +67,28 @@ export function useConfiguration<T extends ViewportConfiguration>(id: number, co export const useConfigurationTypeless = (id: number, configurationsReducer: [ConfigurationState, Dispatch<ConfigurationAction>]) => useConfiguration<ViewportConfiguration>(id, configurationsReducer); export function useSelections<T extends ConfigurationsWithSelections>( dataPartIndex: dataIndex | null, configurationReducer: ConfigurationReducer<T>, dataReducer: [DataState, Dispatch<DataAction>], selectionsReducer: [SelectionState, Dispatch<SelectionAction>], selectedDataIndex: number): Array<[Selection, ViewportSelectionOptions]> { selectedDataIndex: number | null): Array<[Selection, ViewportSelectionOptions]> { const [configuration, updateConfiguration] = configurationReducer; const [globalSelections, dispatchGlobalSelections] = selectionsReducer; const [result, setResult] = useState<Array<[Selection, ViewportSelectionOptions]>>([]); useEffect(() => { if (!configuration.data || (Array.isArray(configuration.data) && configuration.data.length === 0)) { if (!configuration.data || selectedDataIndex == null || (Array.isArray(configuration.data) && configuration.data.length === 0)) { setResult(() => []); return; } const dataPartID = Array.isArray(configuration.data) ? configuration.data[selectedDataIndex] : configuration.data.id; const dataSelections = Array.isArray(configuration.data) ? configuration.data[selectedDataIndex].selections : configuration.data.selections const dataPartID: DataID | SelectionID | null = Array.isArray(configuration.data) ? configuration.data[selectedDataIndex]?.id || null : configuration.data.id; const dataSelections = Array.isArray(configuration.data) ? configuration.data[selectedDataIndex]?.selections || null : configuration.data.selections; const selections = dataPartID != null ? globalSelections.selections.filter(selection => selection.dataID === dataPartID) : []; const selectionsAssociatedData: Array<ViewportSelectionOptions> = (dataPartID != null && dataPartIndex != null) ? dataSelections.map(s => { return { ...s } }) : []; const selectionsAssociatedData: Array<ViewportSelectionOptions> = dataPartID ? dataSelections.map(s => { return { ...s } }) : []; if (dataPartIndex == null || dataPartID == null) return; if (dataPartID == null) return; const selectionsIDs = selections.map(s => s.id); const selectionsAssociatedDataIds = selectionsAssociatedData.map(s => s.selectionID); Loading @@ -107,10 +106,22 @@ export function useSelections<T extends ConfigurationsWithSelections>( } if (toRemoveAssociatedDataIds.length > 0 || toAddAssociatedDataIds.length > 0) { if (Array.isArray(configuration.data)) { const newData = [...configuration.data]; newData[selectedDataIndex] = { ...configuration.data[selectedDataIndex], selections: newSelectionsAssociatedData }; updateConfiguration({ ...configuration, data: newData }); } else { const newData = { ...configuration.data, selections: newSelectionsAssociatedData } }; updateConfiguration({ ...configuration, Loading @@ -118,6 +129,8 @@ export function useSelections<T extends ConfigurationsWithSelections>( }); } } const newResult: Array<[Selection, ViewportSelectionOptions]> = []; for (const selection of selections) { const associatedSelection: ViewportSelectionOptions | undefined = selectionsAssociatedData.filter(s => s.selectionID == selection.id).at(0); Loading @@ -127,7 +140,7 @@ export function useSelections<T extends ConfigurationsWithSelections>( } } setResult(() => newResult); }, [configuration, configuration.data, globalSelections, dataPartIndex]); }, [configuration, configuration.data, globalSelections, selectedDataIndex]); return result; } Loading Loading
app/src/components/RightPanel/ChromatinViewportConfigurationPanel.tsx +13 −12 Original line number Diff line number Diff line Loading @@ -6,7 +6,7 @@ import './RightPanel.scss'; import { ChromatinRepresentation, SmoothCamera, SmoothCameraConfiguration } from "../../modules/graphics"; import { Text } from '@fluentui/react/lib/Text'; import { ChromatinViewportAggregationFunction, ChromatinViewportColorMappingMode, ChromatinViewportConfiguration, ConfigurationAction, ConfigurationState, LabelingDebugTexture, TooltipNumericAggregation, TooltipTextAggregation, ViewportConfigurationType } from '../../modules/storage/models/viewports'; import { ChromatinViewportAggregationFunction, ChromatinViewportColorMappingMode, ChromatinViewportConfiguration, ConfigurationAction, ConfigurationState, IChromatinDataConfiguration, LabelingDebugTexture, TooltipNumericAggregation, TooltipTextAggregation, ViewportConfigurationType } from '../../modules/storage/models/viewports'; import { BinPositionsData, DataAction, DataID, DataState, isoDataID } from "../../modules/storage/models/data"; import { SelectionAction, SelectionState } from "../../modules/storage/models/selections"; import { useConfiguration, useSelections, useViewportName } from "../hooks"; Loading Loading @@ -209,7 +209,7 @@ export function ChromatinViewportConfigurationPanel(props: { const [isBackgroundColorCalloutVisible, setIsBackgroundColorCalloutVisible] = useState<boolean>(false); const selections = useSelections(0, [configuration, updateConfiguration], props.dataReducer, props.selectionsReducer, 0); const selections = useSelections([configuration, updateConfiguration], props.dataReducer, props.selectionsReducer, configuration.selectedDatum); //#region Viewport Settings const setBackgroundColor = (event: React.SyntheticEvent<HTMLElement>, color: IColor): void => { Loading Loading @@ -243,12 +243,12 @@ export function ChromatinViewportConfigurationPanel(props: { const removeData3D = (index: number) => { if (!configuration) return; const newData = [...configuration.data]; const newData: IChromatinDataConfiguration[] = [...configuration.data]; newData.splice(index, 1); updateConfiguration({ ...configuration, selectedDatum: configuration.selectedDatum == index ? null : configuration.selectedDatum, selectedSelectionID: null, data: newData, }); }; Loading @@ -256,7 +256,7 @@ export function ChromatinViewportConfigurationPanel(props: { const addData = () => { if (!configuration || !selectedPrimaryData) return; const data = [...configuration.data]; const newData = [...configuration.data]; //#region Calculate radius range const positions = (selectedPrimaryData.type == '3d-positions' ? selectedPrimaryData as BinPositionsData : selectedSecondaryData as BinPositionsData).values; Loading @@ -273,7 +273,7 @@ export function ChromatinViewportConfigurationPanel(props: { const radiusRange = { min: 0.0, max: quantiles[0] / 2.0 }; //#region Calculate radius range data.push({ newData.push({ id: selectedPrimaryData.id, secondaryID: selectedSecondaryDataID, Loading @@ -286,6 +286,7 @@ export function ChromatinViewportConfigurationPanel(props: { radius, radiusRange, selectedSelectionID: null, selections: [], mapValues: { Loading Loading @@ -324,19 +325,19 @@ export function ChromatinViewportConfigurationPanel(props: { updateConfiguration({ ...configuration, data, data: newData, }); }; const setDataColor = (ev: React.SyntheticEvent<HTMLElement, Event>, color: IColor): void => { if (configuration.selectedDatum == null) return; const data = [...configuration.data]; data[configuration.selectedDatum] = { ...data[configuration.selectedDatum], color }; const newData = [...configuration.data]; newData[configuration.selectedDatum] = { ...newData[configuration.selectedDatum], color }; updateConfiguration({ ...configuration, data data: newData }); }; Loading Loading @@ -607,7 +608,7 @@ export function ChromatinViewportConfigurationPanel(props: { (<div className={"treeViewListItem " + (configuration.selectedDatum == index ? 'selected' : '')} key={index} onClick={() => setSelectedDatum(index)}> <span style={{ display: 'block', width: '4px' }}></span> <Text className="text" nowrap>{datum.id}</Text> <Delete16Regular primaryFill={'white'} className='icon iconHoverRed' onClick={() => removeData3D(index)}></Delete16Regular> <Delete16Regular primaryFill={'white'} className='icon iconHoverRed' onClick={(e) => { e.stopPropagation(); removeData3D(index); } }></Delete16Regular> </div>) )} Loading Loading @@ -862,7 +863,7 @@ export function ChromatinViewportConfigurationPanel(props: { {/* SELECTIONS */} <div style={{ display: 'block', width: '100%', marginTop: '16px' }}></div> <Separator></Separator> {configuration.selectedDatum && ( {configuration.selectedDatum != null && ( <SelectionsPart selections={selections} configurationReducer={configurationReducer} Loading
app/src/components/RightPanel/SelectionsPart.tsx +31 −7 Original line number Diff line number Diff line import { DistanceMapDataConfiguration, ViewportConfiguration, ViewportConfigurationType, ViewportSelectionOptions } from "../../modules/storage/models/viewports"; import { DistanceMapDataConfiguration, ChromatinViewportConfiguration, ViewportConfiguration, ViewportConfigurationType, ViewportSelectionOptions } from "../../modules/storage/models/viewports"; import { DataAction, DataID, DataState } from "../../modules/storage/models/data"; import { isoSelectionID, SelectionAction, SelectionActionKind, SelectionID, Selection, SelectionState } from "../../modules/storage/models/selections"; import { ConfigurationReducer, ConfigurationsWithSelections } from "../hooks"; Loading Loading @@ -49,17 +49,33 @@ export function SelectionsPart<T extends ConfigurationsWithSelections>(props: Pr const dataSize = data.data.find(d => d.id == selectedDataPartID)?.values?.length; if (dataSize) { console.log('adding selection'); globalSelectionsDispatch({ type: SelectionActionKind.ADD, dataID: selectedDataPartID as DataID, dataSize }); } } } const selectSelection = (selectionID: SelectionID) => { if (configuration.type === ViewportConfigurationType.Chromatin && configuration.selectedDatum != null) { const newData = [...configuration.data]; newData[configuration.selectedDatum] = { ...newData[configuration.selectedDatum], selectedSelectionID: selectionID, }; updateConfiguration({ ...configuration, data: newData }); console.log(configuration); } else { updateConfiguration({ ...configuration, selectedSelectionID: selectionID, }); } } const handleRenameStart = (selection: Selection) => setRenaming({ id: selection.id, newName: selection.name }) const handleRenameChange = (newName: string | undefined) => setRenaming({ ...renaming!, newName: newName ?? "" }) Loading @@ -74,7 +90,6 @@ export function SelectionsPart<T extends ConfigurationsWithSelections>(props: Pr name: renaming!.newName.length == 0 ? "unnamed" : renaming!.newName }) setRenaming(null); } const setSelectionVisiblity = (selectionID: SelectionID, visible: boolean, dataIndex = 0) => { Loading Loading @@ -144,7 +159,16 @@ export function SelectionsPart<T extends ConfigurationsWithSelections>(props: Pr a: color.a != undefined ? (color.a / 255) : 1 }, }); } const isSelected = (id: SelectionID) => { if (configuration.type === ViewportConfigurationType.Chromatin && configuration.selectedDatum && configuration.data[configuration.selectedDatum]) { return configuration.data[configuration.selectedDatum].selectedSelectionID == id; } else { return configuration.selectedSelectionID == id; } return false; } return <> Loading @@ -161,7 +185,7 @@ export function SelectionsPart<T extends ConfigurationsWithSelections>(props: Pr <div ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps} className={selection.id == configuration.selectedSelectionID ? "treeViewListItem selected" : "treeViewListItem"} className={isSelected(selection.id) ? "treeViewListItem selected" : "treeViewListItem"} onClick={() => selectSelection(selection.id)}> <DefaultButton id="selectionColorButton" style={{ Loading
app/src/components/RightPanel/TADMapViewportConfiguration.tsx +1 −1 Original line number Diff line number Diff line Loading @@ -25,7 +25,7 @@ export function TADMapViewportConfiguration(props: { const [viewportName, setViewportName] = useViewportName(props.node, props.configurationsReducer); const selections = useSelections(0, [configuration, updateConfiguration], props.dataReducer, props.selectionsReducer, 0); const selections = useSelections([configuration, updateConfiguration], props.dataReducer, props.selectionsReducer, 0); const dataList = data.data.filter(d => d.type == 'sparse-distance-matrix' || d.type == '3d-positions').map(d => { return { Loading
app/src/components/Tools/ToolOptions.tsx +6 −1 Original line number Diff line number Diff line Loading @@ -16,7 +16,12 @@ export function ToolOptions(props: { const [configuration, updateConfiguration] = configurationReducer; const tool = configuration.tool; const isMac = new UAParser().getOS().name == 'Mac OS'; const hasSelectedSelection = configuration.selectedSelectionID != null; let hasSelectedSelection = configuration.selectedSelectionID != null; if (configuration.type == ViewportConfigurationType.Chromatin && configuration.selectedDatum && configuration.data[configuration.selectedDatum]) { hasSelectedSelection = configuration.data[configuration.selectedDatum].selectedSelectionID != null; } const enforceSelectedSelection = (element: JSX.Element): JSX.Element => { Loading
app/src/components/hooks.ts +30 −17 Original line number Diff line number Diff line Loading @@ -2,8 +2,8 @@ import { Actions, Model, TabNode } from "flexlayout-react"; import { Dispatch, useEffect, useState, useCallback } from "react"; import { useFreshTick } from "rooks"; import { ChromatinViewportConfiguration, ConfigurationAction, ConfigurationActionKind, ConfigurationState, dataIndex, DistanceViewportConfiguration, ForceGraphViewportConfiguration, IViewportConfiguration, ViewportConfiguration, ViewportSelectionOptions } from "../modules/storage/models/viewports"; import { DataAction, DataState } from "../modules/storage/models/data"; import { SelectionAction, Selection, SelectionState } from "../modules/storage/models/selections"; import { DataAction, DataID, DataState } from "../modules/storage/models/data"; import { SelectionAction, Selection, SelectionState, SelectionID } from "../modules/storage/models/selections"; // Only configurations that have selections can use this part export type ConfigurationsWithSelections = ChromatinViewportConfiguration | DistanceViewportConfiguration | ForceGraphViewportConfiguration; Loading Loading @@ -67,29 +67,28 @@ export function useConfiguration<T extends ViewportConfiguration>(id: number, co export const useConfigurationTypeless = (id: number, configurationsReducer: [ConfigurationState, Dispatch<ConfigurationAction>]) => useConfiguration<ViewportConfiguration>(id, configurationsReducer); export function useSelections<T extends ConfigurationsWithSelections>( dataPartIndex: dataIndex | null, configurationReducer: ConfigurationReducer<T>, dataReducer: [DataState, Dispatch<DataAction>], selectionsReducer: [SelectionState, Dispatch<SelectionAction>], selectedDataIndex: number): Array<[Selection, ViewportSelectionOptions]> { selectedDataIndex: number | null): Array<[Selection, ViewportSelectionOptions]> { const [configuration, updateConfiguration] = configurationReducer; const [globalSelections, dispatchGlobalSelections] = selectionsReducer; const [result, setResult] = useState<Array<[Selection, ViewportSelectionOptions]>>([]); useEffect(() => { if (!configuration.data || (Array.isArray(configuration.data) && configuration.data.length === 0)) { if (!configuration.data || selectedDataIndex == null || (Array.isArray(configuration.data) && configuration.data.length === 0)) { setResult(() => []); return; } const dataPartID = Array.isArray(configuration.data) ? configuration.data[selectedDataIndex] : configuration.data.id; const dataSelections = Array.isArray(configuration.data) ? configuration.data[selectedDataIndex].selections : configuration.data.selections const dataPartID: DataID | SelectionID | null = Array.isArray(configuration.data) ? configuration.data[selectedDataIndex]?.id || null : configuration.data.id; const dataSelections = Array.isArray(configuration.data) ? configuration.data[selectedDataIndex]?.selections || null : configuration.data.selections; const selections = dataPartID != null ? globalSelections.selections.filter(selection => selection.dataID === dataPartID) : []; const selectionsAssociatedData: Array<ViewportSelectionOptions> = (dataPartID != null && dataPartIndex != null) ? dataSelections.map(s => { return { ...s } }) : []; const selectionsAssociatedData: Array<ViewportSelectionOptions> = dataPartID ? dataSelections.map(s => { return { ...s } }) : []; if (dataPartIndex == null || dataPartID == null) return; if (dataPartID == null) return; const selectionsIDs = selections.map(s => s.id); const selectionsAssociatedDataIds = selectionsAssociatedData.map(s => s.selectionID); Loading @@ -107,10 +106,22 @@ export function useSelections<T extends ConfigurationsWithSelections>( } if (toRemoveAssociatedDataIds.length > 0 || toAddAssociatedDataIds.length > 0) { if (Array.isArray(configuration.data)) { const newData = [...configuration.data]; newData[selectedDataIndex] = { ...configuration.data[selectedDataIndex], selections: newSelectionsAssociatedData }; updateConfiguration({ ...configuration, data: newData }); } else { const newData = { ...configuration.data, selections: newSelectionsAssociatedData } }; updateConfiguration({ ...configuration, Loading @@ -118,6 +129,8 @@ export function useSelections<T extends ConfigurationsWithSelections>( }); } } const newResult: Array<[Selection, ViewportSelectionOptions]> = []; for (const selection of selections) { const associatedSelection: ViewportSelectionOptions | undefined = selectionsAssociatedData.filter(s => s.selectionID == selection.id).at(0); Loading @@ -127,7 +140,7 @@ export function useSelections<T extends ConfigurationsWithSelections>( } } setResult(() => newResult); }, [configuration, configuration.data, globalSelections, dataPartIndex]); }, [configuration, configuration.data, globalSelections, selectedDataIndex]); return result; } Loading