Loading app/package-lock.json +59 −13 Original line number Diff line number Diff line Loading @@ -44,7 +44,8 @@ "simple-statistics": "^7.7.0", "stream": "^0.0.2", "ua-parser-js": "^1.0.2", "use-deep-compare-effect": "^1.8.1" "use-deep-compare-effect": "^1.8.1", "uuid": "^9.0.0" }, "devDependencies": { "@fluentui/react": "^8.30.3", Loading @@ -65,6 +66,7 @@ "@types/react-dom": "^17.0.9", "@types/react-redux": "^7.1.18", "@types/resize-observer-browser": "^0.1.6", "@types/uuid": "^8.3.4", "@typescript-eslint/eslint-plugin": "^4.30.0", "@typescript-eslint/parser": "^4.30.0", "@webgpu/types": "^0.1.21", Loading Loading @@ -1646,6 +1648,12 @@ "resolved": "https://registry.npmjs.org/@types/ua-parser-js/-/ua-parser-js-0.7.36.tgz", "integrity": "sha512-N1rW+njavs70y2cApeIw1vLMYXRwfBy+7trgavGuuTfOd7j1Yh7QTRc/yqsPl6ncokt72ZXuxEU0PiCp9bSwNQ==" }, "node_modules/@types/uuid": { "version": "8.3.4", "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz", "integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==", "dev": true }, "node_modules/@types/ws": { "version": "8.2.2", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.2.2.tgz", Loading Loading @@ -4556,6 +4564,14 @@ "react-dom": "^17.0.2" } }, "node_modules/flexlayout-react/node_modules/uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "bin": { "uuid": "dist/bin/uuid" } }, "node_modules/fmin": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/fmin/-/fmin-0.0.2.tgz", Loading Loading @@ -8381,9 +8397,9 @@ } }, "node_modules/rtl-css-js": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/rtl-css-js/-/rtl-css-js-1.15.0.tgz", "integrity": "sha512-99Cu4wNNIhrI10xxUaABHsdDqzalrSRTie4GeCmbGVuehm4oj+fIy8fTzB+16pmKe8Bv9rl+hxIBez6KxExTew==", "version": "1.16.0", "resolved": "https://registry.npmjs.org/rtl-css-js/-/rtl-css-js-1.16.0.tgz", "integrity": "sha512-Oc7PnzwIEU4M0K1J4h/7qUUaljXhQ0kCObRsZjxs2HjkpKsnoTMvSmvJ4sqgJZd0zBoEfAyTdnK/jMIYvrjySQ==", "dependencies": { "@babel/runtime": "^7.1.2" } Loading Loading @@ -8828,6 +8844,15 @@ "websocket-driver": "^0.7.4" } }, "node_modules/sockjs/node_modules/uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "dev": true, "bin": { "uuid": "dist/bin/uuid" } }, "node_modules/source-map": { "version": "0.7.3", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", Loading Loading @@ -9690,9 +9715,9 @@ } }, "node_modules/uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "version": "9.0.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", "bin": { "uuid": "dist/bin/uuid" } Loading Loading @@ -11493,6 +11518,12 @@ "resolved": "https://registry.npmjs.org/@types/ua-parser-js/-/ua-parser-js-0.7.36.tgz", "integrity": "sha512-N1rW+njavs70y2cApeIw1vLMYXRwfBy+7trgavGuuTfOd7j1Yh7QTRc/yqsPl6ncokt72ZXuxEU0PiCp9bSwNQ==" }, "@types/uuid": { "version": "8.3.4", "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz", "integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==", "dev": true }, "@types/ws": { "version": "8.2.2", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.2.2.tgz", Loading Loading @@ -13768,6 +13799,13 @@ "integrity": "sha512-rqXkYADckkxi2I5On2ZtxVXcb8tfAP75Semf38ognWd3UHu4rEjKbSM4UqJtSMK9xIqo0PlpyVCOTc4E1N3CPg==", "requires": { "uuid": "^8.3.2" }, "dependencies": { "uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" } } }, "fmin": { Loading Loading @@ -16686,9 +16724,9 @@ } }, "rtl-css-js": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/rtl-css-js/-/rtl-css-js-1.15.0.tgz", "integrity": "sha512-99Cu4wNNIhrI10xxUaABHsdDqzalrSRTie4GeCmbGVuehm4oj+fIy8fTzB+16pmKe8Bv9rl+hxIBez6KxExTew==", "version": "1.16.0", "resolved": "https://registry.npmjs.org/rtl-css-js/-/rtl-css-js-1.16.0.tgz", "integrity": "sha512-Oc7PnzwIEU4M0K1J4h/7qUUaljXhQ0kCObRsZjxs2HjkpKsnoTMvSmvJ4sqgJZd0zBoEfAyTdnK/jMIYvrjySQ==", "requires": { "@babel/runtime": "^7.1.2" } Loading Loading @@ -17014,6 +17052,14 @@ "faye-websocket": "^0.11.3", "uuid": "^8.3.2", "websocket-driver": "^0.7.4" }, "dependencies": { "uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "dev": true } } }, "source-map": { Loading Loading @@ -17671,9 +17717,9 @@ "dev": true }, "uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" "version": "9.0.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==" }, "v8-compile-cache": { "version": "2.3.0", app/package.json +3 −1 Original line number Diff line number Diff line Loading @@ -48,7 +48,8 @@ "simple-statistics": "^7.7.0", "stream": "^0.0.2", "ua-parser-js": "^1.0.2", "use-deep-compare-effect": "^1.8.1" "use-deep-compare-effect": "^1.8.1", "uuid": "^9.0.0" }, "devDependencies": { "@fluentui/react": "^8.30.3", Loading @@ -69,6 +70,7 @@ "@types/react-dom": "^17.0.9", "@types/react-redux": "^7.1.18", "@types/resize-observer-browser": "^0.1.6", "@types/uuid": "^8.3.4", "@typescript-eslint/eslint-plugin": "^4.30.0", "@typescript-eslint/parser": "^4.30.0", "@webgpu/types": "^0.1.21", Loading app/src/components/RightPanel/TADMapViewportConfiguration.tsx +7 −6 Original line number Diff line number Diff line Loading @@ -8,7 +8,7 @@ import { ConfigurationAction, ConfigurationState, DistanceDataConfiguration, Dis import { DataAction, DataID, DataState, isoDataID } from "../../modules/storage/models/data"; import { isoSelectionID, SelectionAction, SelectionState } from "../../modules/storage/models/selections"; import { useConfiguration, useSelections, useViewportName } from '../hooks'; import { SelectionsPart } from './SelectionsPart'; import { SelectionsTrack } from './tracks/SelectionsTrack'; export function TADMapViewportConfiguration(props: { model: Model, Loading Loading @@ -120,12 +120,13 @@ export function TADMapViewportConfiguration(props: { /> <div style={{ display: 'block', width: '100%', marginTop: '32px' }}></div> <Separator></Separator> <SelectionsPart selections={selections} configurationReducer={configurationReducer} {configuration.selectedTrackID != null && (<SelectionsTrack configurationID={props.node.getConfig()} configurationsReducer={props.configurationsReducer} dataReducer={props.dataReducer} selectionsReducer={props.selectionsReducer} selectedDataIndex={0} ></SelectionsPart> trackID={configuration.selectedTrackID} ></SelectionsTrack> )} </div> } app/src/components/RightPanel/tracks/SelectionsTrack.tsx 0 → 100644 +105 −0 Original line number Diff line number Diff line import React, { Dispatch, Fragment, useMemo } from "react"; import { ConfigurationAction, ConfigurationState, DistanceDataConfiguration, DistanceMapDataConfiguration, DistanceViewportConfiguration, TrackType } from '../../../modules/storage/models/viewports'; import { DataAction, DataState } from "../../../modules/storage/models/data"; import { isoSelectionID, SelectionAction, SelectionState } from "../../../modules/storage/models/selections"; import { useConfiguration } from '../../hooks'; import { Delete16Regular } from "@fluentui/react-icons"; import { ComboBox, DefaultButton, IComboBox, IComboBoxOption } from "@fluentui/react"; import { Text } from '@fluentui/react/lib/Text'; import { notEmpty } from "../../../modules/utils"; export function SelectionsTrack(props: { configurationID: number, configurationsReducer: [ConfigurationState, Dispatch<ConfigurationAction>], dataReducer: [DataState, Dispatch<DataAction>], selectionsReducer: [SelectionState, Dispatch<SelectionAction>], trackID: string, }): JSX.Element { // Configuration/Data const configurationReducer = useConfiguration<DistanceViewportConfiguration>(props.configurationID, props.configurationsReducer); const [configuration, updateConfiguration] = configurationReducer; const [data, dataDispatch] = props.dataReducer; const [allSelections, allSelectionsDispatch] = props.selectionsReducer; const trackIndex = configuration.tracks.findIndex(t => t.id === props.trackID); const track = configuration.tracks[trackIndex]; if (track.type != TrackType.Selections) { throw ""; } const selectionsList = allSelections.selections.map(s => { return { key: isoSelectionID.unwrap(s.id), text: s.name, } as IComboBoxOption; }); const addSelection = (event: React.FormEvent<IComboBox>, option?: IComboBoxOption) => { if (!option) return; const key = option.key as number; const selectionID = isoSelectionID.wrap(key); const newTracks = [...configuration.tracks]; const oldTrack = newTracks[trackIndex]; if (oldTrack.type === TrackType.Selections) { const newSelections = [...new Set([...oldTrack.selections, selectionID])]; newTracks[trackIndex] = { ...oldTrack, selections: newSelections }; } updateConfiguration({ ...configuration, tracks: newTracks }); }; const selections = useMemo(() => track.selections.map(selectionID => { if (configuration.data == null || configuration.data.type != DistanceMapDataConfiguration.Data) { return undefined; } else { const d = configuration.data as DistanceDataConfiguration; return allSelections.selections.find(s => s.id == selectionID && s.dataID == d.id); } }).filter(notEmpty), [configuration.data, track.selections, allSelections]); return <Fragment><ComboBox label="Add a selection" allowFreeform={true} autoComplete={'on'} options={selectionsList} onChange={addSelection} /><div className="treeViewList" style={{ marginTop: '16px' }}> {track.type == TrackType.Selections && (selections.map(selection => { return <div className="treeViewListItem" key={isoSelectionID.unwrap(selection.id)}> <DefaultButton id="selectionColorButton" style={{ padding: 0, minWidth: "0px", }} onRenderText={(p) => <div style={{ width: '1.2rem', height: '1.2rem', margin: '0px 4px', backgroundColor: `rgb(${selection.color.r * 255}, ${selection.color.g * 255}, ${selection.color.b * 255})`, }} ></div>} disabled={true} /> <span style={{ display: 'block', width: '4px' }}></span> <Text className="text" nowrap>{selection.name}</Text> <Delete16Regular primaryFill={'white'} className='icon iconHoverRed'></Delete16Regular> </div> }) )} </div> </Fragment >; } app/src/components/viewports/TADViewport.tsx +30 −3 Original line number Diff line number Diff line Loading @@ -12,8 +12,10 @@ import { useConfiguration, useSelections } from "../hooks"; import { sasa } from "../../modules/sasa"; import { SelectionsTrack } from "./tracks/SelectionsTrack"; import { Dropdown, IDropdownOption } from "@fluentui/react"; import { v4 } from 'uuid'; import './Tracks.css'; import { BreakoutRoom20Filled } from "@fluentui/react-icons"; export function TADViewport(props: { graphicsLibrary: GraphicsModule.GraphicsLibrary, Loading Loading @@ -59,7 +61,7 @@ export function TADViewport(props: { useEffect(() => { viewport.cameraConfiguration = cameraConfiguration; }, [cameraConfiguration]); }, [viewport, cameraConfiguration]); const [isControlPressed, setControlPressed] = useState(false); const [isAltPressed, setAltPressed] = useState(false); Loading Loading @@ -374,6 +376,27 @@ export function TADViewport(props: { { key: TrackType.Selections, text: 'Selections' } ]; const addTrack = (event: React.FormEvent<HTMLDivElement>, option?: IDropdownOption, index?: number): void => { if (!option) return; const trackType = option.key as TrackType; switch (trackType) { case TrackType.Selections: { updateConfiguration({ ...configuration, tracks: [...configuration.tracks, { id: v4(), type: TrackType.Selections, selections: [], }] }) break; } } }; // console.log(configuration.tracks); return (<div style={{ width: '100%', height: '100%', overflow: 'hidden', position: 'relative' }}> <canvas ref={canvasElement} style={{ width: '100%', height: '100%', overflow: 'hidden', position: 'absolute', top: 0, left: 0, right: 0, bottom: 0 }} onClick={onClick} Loading @@ -392,22 +415,26 @@ export function TADViewport(props: { switch (t.type) { case TrackType.Selections: { return <SelectionsTrack key={t.id} graphicsLibrary={props.graphicsLibrary} configurationID={props.configurationID} configurationsReducer={props.configurationsReducer} dataReducer={props.dataReducer} selectionsReducer={props.selectionsReducer} track={t} viewport={viewport} ></SelectionsTrack> } } })} <div className="track-add"> <div className="track track-add"> <Dropdown placeholder="Select a track to add" label="" options={tracksDropdownOptions} style={{pointerEvents: 'all', maxWidth: 200, margin: 'auto'}} style={{ pointerEvents: 'all', maxWidth: 200, margin: 'auto' }} onChange={addTrack} notifyOnReselect={true} ></Dropdown> </div> </div> Loading Loading
app/package-lock.json +59 −13 Original line number Diff line number Diff line Loading @@ -44,7 +44,8 @@ "simple-statistics": "^7.7.0", "stream": "^0.0.2", "ua-parser-js": "^1.0.2", "use-deep-compare-effect": "^1.8.1" "use-deep-compare-effect": "^1.8.1", "uuid": "^9.0.0" }, "devDependencies": { "@fluentui/react": "^8.30.3", Loading @@ -65,6 +66,7 @@ "@types/react-dom": "^17.0.9", "@types/react-redux": "^7.1.18", "@types/resize-observer-browser": "^0.1.6", "@types/uuid": "^8.3.4", "@typescript-eslint/eslint-plugin": "^4.30.0", "@typescript-eslint/parser": "^4.30.0", "@webgpu/types": "^0.1.21", Loading Loading @@ -1646,6 +1648,12 @@ "resolved": "https://registry.npmjs.org/@types/ua-parser-js/-/ua-parser-js-0.7.36.tgz", "integrity": "sha512-N1rW+njavs70y2cApeIw1vLMYXRwfBy+7trgavGuuTfOd7j1Yh7QTRc/yqsPl6ncokt72ZXuxEU0PiCp9bSwNQ==" }, "node_modules/@types/uuid": { "version": "8.3.4", "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz", "integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==", "dev": true }, "node_modules/@types/ws": { "version": "8.2.2", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.2.2.tgz", Loading Loading @@ -4556,6 +4564,14 @@ "react-dom": "^17.0.2" } }, "node_modules/flexlayout-react/node_modules/uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "bin": { "uuid": "dist/bin/uuid" } }, "node_modules/fmin": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/fmin/-/fmin-0.0.2.tgz", Loading Loading @@ -8381,9 +8397,9 @@ } }, "node_modules/rtl-css-js": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/rtl-css-js/-/rtl-css-js-1.15.0.tgz", "integrity": "sha512-99Cu4wNNIhrI10xxUaABHsdDqzalrSRTie4GeCmbGVuehm4oj+fIy8fTzB+16pmKe8Bv9rl+hxIBez6KxExTew==", "version": "1.16.0", "resolved": "https://registry.npmjs.org/rtl-css-js/-/rtl-css-js-1.16.0.tgz", "integrity": "sha512-Oc7PnzwIEU4M0K1J4h/7qUUaljXhQ0kCObRsZjxs2HjkpKsnoTMvSmvJ4sqgJZd0zBoEfAyTdnK/jMIYvrjySQ==", "dependencies": { "@babel/runtime": "^7.1.2" } Loading Loading @@ -8828,6 +8844,15 @@ "websocket-driver": "^0.7.4" } }, "node_modules/sockjs/node_modules/uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "dev": true, "bin": { "uuid": "dist/bin/uuid" } }, "node_modules/source-map": { "version": "0.7.3", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", Loading Loading @@ -9690,9 +9715,9 @@ } }, "node_modules/uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "version": "9.0.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", "bin": { "uuid": "dist/bin/uuid" } Loading Loading @@ -11493,6 +11518,12 @@ "resolved": "https://registry.npmjs.org/@types/ua-parser-js/-/ua-parser-js-0.7.36.tgz", "integrity": "sha512-N1rW+njavs70y2cApeIw1vLMYXRwfBy+7trgavGuuTfOd7j1Yh7QTRc/yqsPl6ncokt72ZXuxEU0PiCp9bSwNQ==" }, "@types/uuid": { "version": "8.3.4", "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz", "integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==", "dev": true }, "@types/ws": { "version": "8.2.2", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.2.2.tgz", Loading Loading @@ -13768,6 +13799,13 @@ "integrity": "sha512-rqXkYADckkxi2I5On2ZtxVXcb8tfAP75Semf38ognWd3UHu4rEjKbSM4UqJtSMK9xIqo0PlpyVCOTc4E1N3CPg==", "requires": { "uuid": "^8.3.2" }, "dependencies": { "uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" } } }, "fmin": { Loading Loading @@ -16686,9 +16724,9 @@ } }, "rtl-css-js": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/rtl-css-js/-/rtl-css-js-1.15.0.tgz", "integrity": "sha512-99Cu4wNNIhrI10xxUaABHsdDqzalrSRTie4GeCmbGVuehm4oj+fIy8fTzB+16pmKe8Bv9rl+hxIBez6KxExTew==", "version": "1.16.0", "resolved": "https://registry.npmjs.org/rtl-css-js/-/rtl-css-js-1.16.0.tgz", "integrity": "sha512-Oc7PnzwIEU4M0K1J4h/7qUUaljXhQ0kCObRsZjxs2HjkpKsnoTMvSmvJ4sqgJZd0zBoEfAyTdnK/jMIYvrjySQ==", "requires": { "@babel/runtime": "^7.1.2" } Loading Loading @@ -17014,6 +17052,14 @@ "faye-websocket": "^0.11.3", "uuid": "^8.3.2", "websocket-driver": "^0.7.4" }, "dependencies": { "uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "dev": true } } }, "source-map": { Loading Loading @@ -17671,9 +17717,9 @@ "dev": true }, "uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" "version": "9.0.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==" }, "v8-compile-cache": { "version": "2.3.0",
app/package.json +3 −1 Original line number Diff line number Diff line Loading @@ -48,7 +48,8 @@ "simple-statistics": "^7.7.0", "stream": "^0.0.2", "ua-parser-js": "^1.0.2", "use-deep-compare-effect": "^1.8.1" "use-deep-compare-effect": "^1.8.1", "uuid": "^9.0.0" }, "devDependencies": { "@fluentui/react": "^8.30.3", Loading @@ -69,6 +70,7 @@ "@types/react-dom": "^17.0.9", "@types/react-redux": "^7.1.18", "@types/resize-observer-browser": "^0.1.6", "@types/uuid": "^8.3.4", "@typescript-eslint/eslint-plugin": "^4.30.0", "@typescript-eslint/parser": "^4.30.0", "@webgpu/types": "^0.1.21", Loading
app/src/components/RightPanel/TADMapViewportConfiguration.tsx +7 −6 Original line number Diff line number Diff line Loading @@ -8,7 +8,7 @@ import { ConfigurationAction, ConfigurationState, DistanceDataConfiguration, Dis import { DataAction, DataID, DataState, isoDataID } from "../../modules/storage/models/data"; import { isoSelectionID, SelectionAction, SelectionState } from "../../modules/storage/models/selections"; import { useConfiguration, useSelections, useViewportName } from '../hooks'; import { SelectionsPart } from './SelectionsPart'; import { SelectionsTrack } from './tracks/SelectionsTrack'; export function TADMapViewportConfiguration(props: { model: Model, Loading Loading @@ -120,12 +120,13 @@ export function TADMapViewportConfiguration(props: { /> <div style={{ display: 'block', width: '100%', marginTop: '32px' }}></div> <Separator></Separator> <SelectionsPart selections={selections} configurationReducer={configurationReducer} {configuration.selectedTrackID != null && (<SelectionsTrack configurationID={props.node.getConfig()} configurationsReducer={props.configurationsReducer} dataReducer={props.dataReducer} selectionsReducer={props.selectionsReducer} selectedDataIndex={0} ></SelectionsPart> trackID={configuration.selectedTrackID} ></SelectionsTrack> )} </div> }
app/src/components/RightPanel/tracks/SelectionsTrack.tsx 0 → 100644 +105 −0 Original line number Diff line number Diff line import React, { Dispatch, Fragment, useMemo } from "react"; import { ConfigurationAction, ConfigurationState, DistanceDataConfiguration, DistanceMapDataConfiguration, DistanceViewportConfiguration, TrackType } from '../../../modules/storage/models/viewports'; import { DataAction, DataState } from "../../../modules/storage/models/data"; import { isoSelectionID, SelectionAction, SelectionState } from "../../../modules/storage/models/selections"; import { useConfiguration } from '../../hooks'; import { Delete16Regular } from "@fluentui/react-icons"; import { ComboBox, DefaultButton, IComboBox, IComboBoxOption } from "@fluentui/react"; import { Text } from '@fluentui/react/lib/Text'; import { notEmpty } from "../../../modules/utils"; export function SelectionsTrack(props: { configurationID: number, configurationsReducer: [ConfigurationState, Dispatch<ConfigurationAction>], dataReducer: [DataState, Dispatch<DataAction>], selectionsReducer: [SelectionState, Dispatch<SelectionAction>], trackID: string, }): JSX.Element { // Configuration/Data const configurationReducer = useConfiguration<DistanceViewportConfiguration>(props.configurationID, props.configurationsReducer); const [configuration, updateConfiguration] = configurationReducer; const [data, dataDispatch] = props.dataReducer; const [allSelections, allSelectionsDispatch] = props.selectionsReducer; const trackIndex = configuration.tracks.findIndex(t => t.id === props.trackID); const track = configuration.tracks[trackIndex]; if (track.type != TrackType.Selections) { throw ""; } const selectionsList = allSelections.selections.map(s => { return { key: isoSelectionID.unwrap(s.id), text: s.name, } as IComboBoxOption; }); const addSelection = (event: React.FormEvent<IComboBox>, option?: IComboBoxOption) => { if (!option) return; const key = option.key as number; const selectionID = isoSelectionID.wrap(key); const newTracks = [...configuration.tracks]; const oldTrack = newTracks[trackIndex]; if (oldTrack.type === TrackType.Selections) { const newSelections = [...new Set([...oldTrack.selections, selectionID])]; newTracks[trackIndex] = { ...oldTrack, selections: newSelections }; } updateConfiguration({ ...configuration, tracks: newTracks }); }; const selections = useMemo(() => track.selections.map(selectionID => { if (configuration.data == null || configuration.data.type != DistanceMapDataConfiguration.Data) { return undefined; } else { const d = configuration.data as DistanceDataConfiguration; return allSelections.selections.find(s => s.id == selectionID && s.dataID == d.id); } }).filter(notEmpty), [configuration.data, track.selections, allSelections]); return <Fragment><ComboBox label="Add a selection" allowFreeform={true} autoComplete={'on'} options={selectionsList} onChange={addSelection} /><div className="treeViewList" style={{ marginTop: '16px' }}> {track.type == TrackType.Selections && (selections.map(selection => { return <div className="treeViewListItem" key={isoSelectionID.unwrap(selection.id)}> <DefaultButton id="selectionColorButton" style={{ padding: 0, minWidth: "0px", }} onRenderText={(p) => <div style={{ width: '1.2rem', height: '1.2rem', margin: '0px 4px', backgroundColor: `rgb(${selection.color.r * 255}, ${selection.color.g * 255}, ${selection.color.b * 255})`, }} ></div>} disabled={true} /> <span style={{ display: 'block', width: '4px' }}></span> <Text className="text" nowrap>{selection.name}</Text> <Delete16Regular primaryFill={'white'} className='icon iconHoverRed'></Delete16Regular> </div> }) )} </div> </Fragment >; }
app/src/components/viewports/TADViewport.tsx +30 −3 Original line number Diff line number Diff line Loading @@ -12,8 +12,10 @@ import { useConfiguration, useSelections } from "../hooks"; import { sasa } from "../../modules/sasa"; import { SelectionsTrack } from "./tracks/SelectionsTrack"; import { Dropdown, IDropdownOption } from "@fluentui/react"; import { v4 } from 'uuid'; import './Tracks.css'; import { BreakoutRoom20Filled } from "@fluentui/react-icons"; export function TADViewport(props: { graphicsLibrary: GraphicsModule.GraphicsLibrary, Loading Loading @@ -59,7 +61,7 @@ export function TADViewport(props: { useEffect(() => { viewport.cameraConfiguration = cameraConfiguration; }, [cameraConfiguration]); }, [viewport, cameraConfiguration]); const [isControlPressed, setControlPressed] = useState(false); const [isAltPressed, setAltPressed] = useState(false); Loading Loading @@ -374,6 +376,27 @@ export function TADViewport(props: { { key: TrackType.Selections, text: 'Selections' } ]; const addTrack = (event: React.FormEvent<HTMLDivElement>, option?: IDropdownOption, index?: number): void => { if (!option) return; const trackType = option.key as TrackType; switch (trackType) { case TrackType.Selections: { updateConfiguration({ ...configuration, tracks: [...configuration.tracks, { id: v4(), type: TrackType.Selections, selections: [], }] }) break; } } }; // console.log(configuration.tracks); return (<div style={{ width: '100%', height: '100%', overflow: 'hidden', position: 'relative' }}> <canvas ref={canvasElement} style={{ width: '100%', height: '100%', overflow: 'hidden', position: 'absolute', top: 0, left: 0, right: 0, bottom: 0 }} onClick={onClick} Loading @@ -392,22 +415,26 @@ export function TADViewport(props: { switch (t.type) { case TrackType.Selections: { return <SelectionsTrack key={t.id} graphicsLibrary={props.graphicsLibrary} configurationID={props.configurationID} configurationsReducer={props.configurationsReducer} dataReducer={props.dataReducer} selectionsReducer={props.selectionsReducer} track={t} viewport={viewport} ></SelectionsTrack> } } })} <div className="track-add"> <div className="track track-add"> <Dropdown placeholder="Select a track to add" label="" options={tracksDropdownOptions} style={{pointerEvents: 'all', maxWidth: 200, margin: 'auto'}} style={{ pointerEvents: 'all', maxWidth: 200, margin: 'auto' }} onChange={addTrack} notifyOnReselect={true} ></Dropdown> </div> </div> Loading