diff --git a/package-lock.json b/package-lock.json index abfc3f32e..3574cdf6a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,10 +8,10 @@ "name": "chrisui", "version": "0.0.0", "dependencies": { - "@cornerstonejs/core": "^1.58.5", + "@cornerstonejs/core": "^1.61.1", "@cornerstonejs/dicom-image-loader": "^1.57.0", - "@cornerstonejs/streaming-image-volume-loader": "^1.58.5", - "@cornerstonejs/tools": "^1.58.5", + "@cornerstonejs/streaming-image-volume-loader": "^1.61.1", + "@cornerstonejs/tools": "^1.61.1", "@fnndsc/chrisapi": "^1.15.0", "@heroicons/react": "^2.1.1", "@niivue/niivue": "^0.38.8", @@ -873,9 +873,9 @@ } }, "node_modules/@cornerstonejs/core": { - "version": "1.58.5", - "resolved": "https://registry.npmjs.org/@cornerstonejs/core/-/core-1.58.5.tgz", - "integrity": "sha512-e9OqcquEMuNOt643MyMrk3as74Xu9Az4ikMdtr1K8W5V0GYQYwLugNMEVwFCkjoPVOimYcKpLvhEcE47P5dFVA==", + "version": "1.61.1", + "resolved": "https://registry.npmjs.org/@cornerstonejs/core/-/core-1.61.1.tgz", + "integrity": "sha512-E/BeEeolc+ZJaEKeNdgvTmLNJkGNIM/4FQ758zPRrW3iFJAhNh0kiBDFYE7F7mPF/nqyS2lxxlR1KNJy0mKjXQ==", "dependencies": { "@kitware/vtk.js": "29.7.0", "comlink": "^4.4.1", @@ -909,11 +909,11 @@ "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==" }, "node_modules/@cornerstonejs/streaming-image-volume-loader": { - "version": "1.58.5", - "resolved": "https://registry.npmjs.org/@cornerstonejs/streaming-image-volume-loader/-/streaming-image-volume-loader-1.58.5.tgz", - "integrity": "sha512-mMdyuvMD4y2sgbP0bNrwbKeMQkphFNOT/EZQLVvfvFNhmAmiqQTeCfm4pOmql0rJt8j23O+Pvwhx2DjwM9i34g==", + "version": "1.61.1", + "resolved": "https://registry.npmjs.org/@cornerstonejs/streaming-image-volume-loader/-/streaming-image-volume-loader-1.61.1.tgz", + "integrity": "sha512-mVQTtCrOKswGD49VxZ57a5p/5gLWgvUPxg3cgiblLnaDGVffLAdinN8PFo/XdiQPsb49B2hlVWPe17X6a7JnWw==", "dependencies": { - "@cornerstonejs/core": "^1.58.5", + "@cornerstonejs/core": "^1.61.1", "comlink": "^4.4.1" }, "funding": { @@ -922,11 +922,11 @@ } }, "node_modules/@cornerstonejs/tools": { - "version": "1.58.5", - "resolved": "https://registry.npmjs.org/@cornerstonejs/tools/-/tools-1.58.5.tgz", - "integrity": "sha512-+mw74BHSM0P318Ipy9Z5dpgA+NGXxTyWYDnsTDg9kl+36bAgxHlnwReyHEJh2vsv7lJI351wLe8IHjj/xJNN+w==", + "version": "1.61.1", + "resolved": "https://registry.npmjs.org/@cornerstonejs/tools/-/tools-1.61.1.tgz", + "integrity": "sha512-Gpt7AFaYBS05wT3WmXOJwtB6VsBYRWoEiV68haW30P0rILEI060J2Q+zjc7V5JM63samdKZRrwnXjL9VjfEKKA==", "dependencies": { - "@cornerstonejs/core": "^1.58.5", + "@cornerstonejs/core": "^1.61.1", "@icr/polyseg-wasm": "0.4.0", "@types/offscreencanvas": "2019.7.3", "comlink": "^4.4.1", diff --git a/package.json b/package.json index 1562ba652..1e2f69483 100644 --- a/package.json +++ b/package.json @@ -24,10 +24,10 @@ "print-version": "./print_version.sh" }, "dependencies": { - "@cornerstonejs/core": "^1.58.5", + "@cornerstonejs/core": "^1.61.1", "@cornerstonejs/dicom-image-loader": "^1.57.0", - "@cornerstonejs/streaming-image-volume-loader": "^1.58.5", - "@cornerstonejs/tools": "^1.58.5", + "@cornerstonejs/streaming-image-volume-loader": "^1.61.1", + "@cornerstonejs/tools": "^1.61.1", "@fnndsc/chrisapi": "^1.15.0", "@heroicons/react": "^2.1.1", "@niivue/niivue": "^0.38.8", diff --git a/src/components/FeedDetails/feed-details.css b/src/components/FeedDetails/feed-details.css index 18049c40c..f19eee466 100644 --- a/src/components/FeedDetails/feed-details.css +++ b/src/components/FeedDetails/feed-details.css @@ -23,5 +23,5 @@ .ant-badge-dot { width: 8px !important; height: 8px !important; - minwidth: 8px !important; + min-width: 8px !important; } diff --git a/src/components/FeedOutputBrowser/FeedOutputBrowser.tsx b/src/components/FeedOutputBrowser/FeedOutputBrowser.tsx index 2096b4273..8cd491e3f 100644 --- a/src/components/FeedOutputBrowser/FeedOutputBrowser.tsx +++ b/src/components/FeedOutputBrowser/FeedOutputBrowser.tsx @@ -110,10 +110,9 @@ const SidebarTree = (props: { const [tree, setTreeData] = React.useState(); React.useEffect(() => { const pluginSidebarTree = getFeedTree(plugins); - //@ts-ignore setTreeData(pluginSidebarTree); - }, [plugins, selected]); + }, [plugins]); //@ts-ignore return ( diff --git a/src/components/FeedTree/FeedTree.tsx b/src/components/FeedTree/FeedTree.tsx index b9b356b5f..c9fcb6b6d 100644 --- a/src/components/FeedTree/FeedTree.tsx +++ b/src/components/FeedTree/FeedTree.tsx @@ -150,12 +150,16 @@ const FeedTree = (props: AllProps) => { const newLinksToAdd: any[] = []; if (tsIds) { - links.forEach((link) => { + for (const link of links) { + // Extract target and source IDs from the link const targetId = link.target.data.id; - const sourceId = link.target.data.id; + const sourceId = link.target.data.id; // Corrected to use link.target.data.id + // Check if targetId and sourceId exist and if at least one of them is in 'tsIds' if (targetId && sourceId && (tsIds[targetId] || tsIds[sourceId])) { - // tsPlugin found + // 'tsPlugin' found + + // Determine the topological link based on 'tsIds' let topologicalLink: any; if (tsIds[targetId]) { @@ -164,27 +168,33 @@ const FeedTree = (props: AllProps) => { topologicalLink = link.source; } + // Get the parents from 'tsIds' const parents = tsIds[topologicalLink.data.id]; - const dict: any = {}; - links && - links.forEach((link) => { - for (let i = 0; i < parents.length; i++) { - if ( - link.source.data.id === parents[i] && - !dict[link.source.data.id] - ) { - dict[link.source.data.id] = link.source; - } else if ( - link.target.data.id === parents[i] && - !dict[link.target.data.id] - ) { - dict[link.target.data.id] = link.target; - } - } - return dict; - }); + // Create a dictionary to store unique source and target nodes + const dict: { [key: string]: any } = {}; + + // Iterate over all links to find nodes related to parents + for (const innerLink of links) { + for (let i = 0; i < parents.length; i++) { + // Check if the source ID matches any parent and it is not already in the dictionary + if ( + innerLink.source.data.id === parents[i] && + !dict[innerLink.source.data.id] + ) { + dict[innerLink.source.data.id] = innerLink.source; + } + // Check if the target ID matches any parent and it is not already in the dictionary + else if ( + innerLink.target.data.id === parents[i] && + !dict[innerLink.target.data.id] + ) { + dict[innerLink.target.data.id] = innerLink.target; + } + } + } + // Add new links to the array based on the dictionary for (const i in dict) { newLinksToAdd.push({ source: dict[i], @@ -192,7 +202,7 @@ const FeedTree = (props: AllProps) => { }); } } - }); + } } newLinks = [...links, ...newLinksToAdd]; @@ -212,7 +222,7 @@ const FeedTree = (props: AllProps) => { React.useEffect(() => { //@ts-ignore - if (size && size.width) { + if (size?.width) { //@ts-ignore dispatch(setTranslate({ x: size.width / 2, y: 90 })); } @@ -294,7 +304,7 @@ const FeedTree = (props: AllProps) => { }; }); } - }, [props.data, props.tsIds, generateTree]); + }, [props.data, generateTree]); const handleChange = (feature: string, data?: any) => { if (feature === "scale_enabled") { @@ -439,8 +449,8 @@ const FeedTree = (props: AllProps) => { className={`${svgClassName}`} width="100%" height="100%" - tabIndex={0} > + Feed Tree { return ( @@ -460,7 +470,7 @@ const FeedTree = (props: AllProps) => { {nodes?.map(({ data, x, y, parent }, i) => { return ( { source: [sourceX, sourceY], target: [targetX, targetY], }); - } else { - return orientation === "horizontal" - ? `M${sourceY} ${sourceX} L${targetY} ${targetX}` - : `M${sourceX} ${sourceY} L${targetX} ${targetY}`; } + return orientation === "horizontal" + ? `M${sourceY} ${sourceX} L${targetY} ${targetX}` + : `M${sourceX} ${sourceY} L${targetX} ${targetY}`; }; render() { diff --git a/src/components/Preview/FileDetailView.tsx b/src/components/Preview/FileDetailView.tsx index 14504c50d..9a8edde87 100644 --- a/src/components/Preview/FileDetailView.tsx +++ b/src/components/Preview/FileDetailView.tsx @@ -8,6 +8,7 @@ import { Toolbar, ToolbarItem, } from "@patternfly/react-core"; +import { Alert } from "antd"; import { useQuery } from "@tanstack/react-query"; import { ErrorBoundary } from "react-error-boundary"; import ZoomIcon from "@patternfly/react-icons/dist/esm/icons/search-plus-icon"; @@ -20,7 +21,6 @@ import { LightBulbIcon, MagnifyingGlassCircleIcon, } from "@heroicons/react/24/solid"; - import { useTypedSelector } from "../../store/hooks"; import type { FeedFile } from "@fnndsc/chrisapi"; import { getFileExtension } from "../../api/model"; @@ -41,13 +41,16 @@ interface AllProps { } export interface ActionState { - [key: string]: boolean; + [key: string]: boolean | string; } const FileDetailView = (props: AllProps) => { const [tagInfo, setTagInfo] = React.useState(); - const [actionState, setActionState] = React.useState({}); - const [error, setError] = React.useState(false); + const [actionState, setActionState] = React.useState({ + Zoom: false, + previouslyActive: "", + }); + const [error, setError] = React.useState(""); const drawerState = useTypedSelector((state) => state.drawers); const handleKeyboardEvents = (event: any) => { @@ -94,6 +97,7 @@ const FileDetailView = (props: AllProps) => { setTagInfo(merged); } } catch (error) { + setError("Failed to parse the file for dicom tags"); return { blob: undefined, file: undefined, @@ -110,6 +114,7 @@ const FileDetailView = (props: AllProps) => { const { selectedFile, preview } = props; const fetchData = async (selectedFile: FeedFile) => { + setError(""); const fileName = selectedFile.data.fname; const fileType = getFileExtension(fileName); @@ -121,9 +126,8 @@ const FileDetailView = (props: AllProps) => { fileType, }; } catch (error: any) { - const errorMessage = error.response || error.message; - setError(errorMessage); - return {}; + setError("Failed to fetch the data for preview"); + throw error; } }; @@ -145,25 +149,31 @@ const FileDetailView = (props: AllProps) => { } } - const handleEvents = (action: string) => { + const handleEvents = (action: string, previouslyActive: string) => { if (action === "TagInfo" && data) { displayTagInfo(data.blob); } const currentAction = actionState[action]; setActionState({ [action]: !currentAction, + previouslyActive, }); }; - const handleModalToggle = (actionName: string, value: boolean) => { + const handleModalToggle = ( + actionName: string, + value: boolean, + previouslyActive: string, + ) => { setActionState({ [actionName]: value, + previouslyActive, }); }; const previewType = preview === "large" ? "large-preview" : "small-preview"; - const errorComponent = (error?: any) => ( + const errorComponent = (error?: string) => (