From f8150772f22d09e8fb29d2d3c56dfa771f167204 Mon Sep 17 00:00:00 2001 From: Sophie Labyt Date: Tue, 15 Oct 2024 11:28:08 +0200 Subject: [PATCH 1/5] refac --- src/admin/general/OrthancCard.tsx | 4 +- src/anonymize/AnonymizeRoot.tsx | 42 +++++++++++---- src/anonymize/PatientTable.tsx | 71 ++++++++++++++++++------- src/anonymize/StudyTable.tsx | 39 ++++++++++---- src/assets/Anon.svg | 12 ----- src/content/ContentRoot.tsx | 5 +- src/delete/DeleteRoot.tsx | 3 +- src/{ui/AnonIcon.tsx => icons/Anon.tsx} | 10 ++-- src/icons/index.ts | 2 + src/queue/ProgressQueueBar.tsx | 17 +++--- src/reducers/AnonymizeSlice.ts | 22 +++++--- src/root/ToolList.tsx | 5 +- src/utils/enums.ts | 4 +- src/utils/types.ts | 6 +++ tailwind.config.js | 4 +- 15 files changed, 162 insertions(+), 84 deletions(-) delete mode 100644 src/assets/Anon.svg rename src/{ui/AnonIcon.tsx => icons/Anon.tsx} (85%) diff --git a/src/admin/general/OrthancCard.tsx b/src/admin/general/OrthancCard.tsx index a9a84fe0..70a27e9d 100644 --- a/src/admin/general/OrthancCard.tsx +++ b/src/admin/general/OrthancCard.tsx @@ -172,7 +172,9 @@ const OrthancSettingsCard = ({ orthancData }: OrthancCardProps) => { )} - diff --git a/src/anonymize/AnonymizeRoot.tsx b/src/anonymize/AnonymizeRoot.tsx index 60c2a8d8..ec731a72 100644 --- a/src/anonymize/AnonymizeRoot.tsx +++ b/src/anonymize/AnonymizeRoot.tsx @@ -1,19 +1,23 @@ import { useDispatch, useSelector } from "react-redux"; -import { Card, CardHeader, CardBody, CardFooter, Button } from "../ui"; +import { Card, CardHeader, CardBody, CardFooter, Button, SelectInput } from "../ui"; import { Colors } from "../utils"; import PatientTable from "./PatientTable"; import StudyTable from "./StudyTable"; import { RootState } from "../store"; import { useMemo, useState } from "react"; -import { flushAnonymizeList, removeStudyFromAnonymizeList, updateAnonymizePatientValue, updateAnonymizeStudyValue } from "../reducers/AnonymizeSlice"; -import { Empty } from "../icons"; -import { Patient } from "../utils/types"; +import { flushAnonymizeList, removeStudyFromAnonymizeList, updateAnonymizationProfile, updateAnonymizePatientValue, updateAnonymizeStudyValue } from "../reducers/AnonymizeSlice"; +import { Anon, Empty } from "../icons"; +const profileOptions = [ + { value : 'default', label: 'Default' }, + {value : 'full', label: 'Full' }, +] const AnonymizeRoot = () => { const dispatch = useDispatch(); const anonList = useSelector((state: RootState) => state.anonymize); const [selectedPatientId, setSelectedPatientId] = useState(null) + const patients = useMemo(() => { return Object.values(anonList.patients); }, [anonList]); @@ -23,8 +27,8 @@ const AnonymizeRoot = () => { return Object.values(anonList.studies).filter(study => study.originalStudy.parentPatient === selectedPatientId); }, [anonList, selectedPatientId]); - const handlePatientSelect = (patient: Patient) => { - setSelectedPatientId(patient.id) + const handlePatientSelect = (patientId :string) => { + setSelectedPatientId(patientId) } const handleRemovePatient = (patientId: string) => { const studiesIds = studies @@ -39,12 +43,11 @@ const AnonymizeRoot = () => { dispatch(removeStudyFromAnonymizeList({ studyId })); }; - const handleChangeStudy = (studyId: string, key: string, newStudyDescription: string) => { - console.log(studyId, key, newStudyDescription) + const handleChangeStudy = (studyId: string, newStudyDescription: string) => { dispatch(updateAnonymizeStudyValue({ newStudyDescription, studyId })); }; - const handleChangePatient = (patientId: string, key: string, value: string) => { + const handleChangePatient = (patientId: string, key: 'newPatientId' | 'newPatientName', value: string) => { dispatch(updateAnonymizePatientValue({ patientId, [key]: value })); } @@ -52,6 +55,10 @@ const AnonymizeRoot = () => { dispatch(flushAnonymizeList()); }; + const handleProfileChange = (option) =>{ + dispatch(updateAnonymizationProfile({anonymizationProfile: option.value})) + } + return ( {
- +
- +
+ + +
); }; diff --git a/src/anonymize/PatientTable.tsx b/src/anonymize/PatientTable.tsx index 8a4cd809..8ae3e84f 100644 --- a/src/anonymize/PatientTable.tsx +++ b/src/anonymize/PatientTable.tsx @@ -1,30 +1,38 @@ +import React, { useMemo } from "react"; import { ColumnDef } from "@tanstack/react-table"; -import { Button, Input, Table } from "../ui" -import { useMemo } from "react"; -import { Patient } from "../utils/types"; +import { Button, Table } from "../ui"; +import { AnonPatient } from "../utils/types"; import { Colors } from "../utils"; import { Trash } from "../icons"; type PatientTableProps = { - patients: Patient[] - onClickRow: (patient: Patient) => void; - onRemovePatient: (patientId: string) => void - onCellEdit: (patientId: string | number, columnId: any, value: any) => void -} -const PatientTable = ({ patients, onClickRow, onRemovePatient, onCellEdit }: PatientTableProps) => { + patients: AnonPatient[]; + selectedRows?: Record; + onClickRow: (patientId :string) => void; + onRemovePatient: (patientId: string) => void; + onChangePatient: (patientId: string | number, columnId: any, value: any) => void; + onRowSelectionChange?: (selectedRow: Record) => void; +}; - - const columns: ColumnDef[] = useMemo(() => [ +const PatientTable = ({ + patients, + selectedRows, + onClickRow, + onRemovePatient, + onChangePatient, + onRowSelectionChange, +}: PatientTableProps) => { + const columns: ColumnDef[] = useMemo(() => [ { id: "id", accessorKey: "id" }, { - accessorKey: "mainDicomTags.patientId", + accessorKey: "originalPatient.mainDicomTags.patientId", header: "Patient ID", }, { - accessorKey: "mainDicomTags.patientName", + accessorKey: "originalPatient.mainDicomTags.patientName", header: "Patient Name", }, { @@ -40,14 +48,39 @@ const PatientTable = ({ patients, onClickRow, onRemovePatient, onCellEdit }: Pat { header: "remove", cell: ({ row }) => { - return ; + return ( + + ); }, }, - ], []); + ], [onRemovePatient]); + + const getRowClasses = (row: AnonPatient) => { + if (selectedRows?.[row.originalPatient.id]) { + return 'bg-primary hover:cursor-pointer'; + } else { + return 'hover:bg-indigo-100 hover:cursor-pointer'; + } + }; return ( - - ) -} +
onClickRow(row.originalPatient.id)} + onCellEdit={onChangePatient} + getRowClasses={getRowClasses} + enableRowSelection={true} + selectedRow={selectedRows} + onRowSelectionChange={onRowSelectionChange} + /> + ); +}; -export default PatientTable \ No newline at end of file +export default PatientTable; diff --git a/src/anonymize/StudyTable.tsx b/src/anonymize/StudyTable.tsx index e73331c9..0f313062 100644 --- a/src/anonymize/StudyTable.tsx +++ b/src/anonymize/StudyTable.tsx @@ -1,21 +1,20 @@ -import { Button, Table } from "../ui"; +import { Button, Input, Table } from "../ui"; import { Colors } from "../utils"; import { Trash } from "../icons"; import { ColumnDef } from "@tanstack/react-table"; import { AnonStudy } from "../utils/types"; -import { useMemo } from "react"; type StudyTableProps = { studies: AnonStudy[]; + onChangeStudy: (studyId: string, studyDescription: string) => void; onRemoveStudy: (studyId: string) => void; - onCellEdit: (studyId: string | number, columnId: any, value: any) => void }; -const StudyTable = ({ studies, onRemoveStudy, onCellEdit }: StudyTableProps) => { - const columns: ColumnDef[] = useMemo(() => [ +const StudyTable = ({ studies, onChangeStudy, onRemoveStudy }: StudyTableProps) => { + const columns: ColumnDef[] = [ { id: "id", - accessorFn: (row)=> row.originalStudy.id, + accessorKey: "originalStudy.id", }, { accessorKey: "originalStudy.mainDicomTags.studyDate", @@ -26,9 +25,22 @@ const StudyTable = ({ studies, onRemoveStudy, onCellEdit }: StudyTableProps) => header: "Study Description", }, { - id: "newStudyDescription", + accessorKey: "newStudyDescription", header: "New Study Description", - isEditable: true + cell: ({ row }) => { + return ( + + onChangeStudy( + row.original.originalStudy.id, + event.target.value + ) + } + /> + ); + }, }, { header: "Remove", @@ -45,9 +57,16 @@ const StudyTable = ({ studies, onRemoveStudy, onCellEdit }: StudyTableProps) => ); }, }, - ], []); + ]; + + return
; - return
; }; export default StudyTable; diff --git a/src/assets/Anon.svg b/src/assets/Anon.svg deleted file mode 100644 index 61294a7f..00000000 --- a/src/assets/Anon.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - \ No newline at end of file diff --git a/src/content/ContentRoot.tsx b/src/content/ContentRoot.tsx index dda67149..f457b86c 100644 --- a/src/content/ContentRoot.tsx +++ b/src/content/ContentRoot.tsx @@ -25,8 +25,7 @@ import { addStudyIdToAnonymizeList, } from "../utils/actionsUtils"; import { Colors } from "../utils"; -import AnonIcon from "../assets/Anon.svg?react"; -import { Export } from "../icons"; +import { Anon, Export } from "../icons"; import Labels from "./Labels"; @@ -173,7 +172,7 @@ const ContentRoot: React.FC = () => { className="flex items-center text-sm transition-transform duration-200 bg-blue-700 hover:scale-105" onClick={handleSendAnonymizeList} > - + Send to Anonymize diff --git a/src/delete/DeleteRoot.tsx b/src/delete/DeleteRoot.tsx index 81988239..84368c36 100644 --- a/src/delete/DeleteRoot.tsx +++ b/src/delete/DeleteRoot.tsx @@ -55,7 +55,8 @@ const DeleteRoot = () => { - + ( +type AnonProps = { + className?: string; +} +const Anon = ({ className = "" } : AnonProps) => ( ( ); -export default AnonIcon; +export default Anon; diff --git a/src/icons/index.ts b/src/icons/index.ts index 1c6d5324..e2da62e5 100644 --- a/src/icons/index.ts +++ b/src/icons/index.ts @@ -1,5 +1,6 @@ import Add from './Add' import Admin from './Admin' +import Anon from './Anon' import ArrowLeft from './ArrowLeft' import Brain from './Brain' import Cancel from './Cancel' @@ -53,6 +54,7 @@ import ZoomQuestion from './ZoomQuestion' export { Add, Admin, + Anon, ArrowLeft, Brain, Cancel, diff --git a/src/queue/ProgressQueueBar.tsx b/src/queue/ProgressQueueBar.tsx index 0b352959..0726c4f3 100644 --- a/src/queue/ProgressQueueBar.tsx +++ b/src/queue/ProgressQueueBar.tsx @@ -7,7 +7,7 @@ type ProgressQueueProps = { uuid: string; }; -const ProgressQueueBar= ({ uuid }: ProgressQueueProps) => { +const ProgressQueueBar = ({ uuid }: ProgressQueueProps) => { const { data, isPending } = useCustomQuery( ['queue', 'delete', uuid], () => getDeleteQueue(uuid), @@ -22,17 +22,18 @@ const ProgressQueueBar= ({ uuid }: ProgressQueueProps) => { if (isPending) return ; return ( -
- -
{data?.state}
-
+
+ +
{/* Implement pause functionality here */ }} + onClick={() => { + // Implement pause functionality here + }} /> mutateDeleteQueue({})} />
diff --git a/src/reducers/AnonymizeSlice.ts b/src/reducers/AnonymizeSlice.ts index 6e7d62f4..271bb71f 100644 --- a/src/reducers/AnonymizeSlice.ts +++ b/src/reducers/AnonymizeSlice.ts @@ -1,9 +1,9 @@ import { PayloadAction, createSlice } from "@reduxjs/toolkit"; -import { AnonStudy, Patient } from "../utils/types"; +import { AnonPatient, AnonStudy } from "../utils/types"; export type AnonymizeState = { patients: { - [patientId: string]: Patient; + [patientId: string]: AnonPatient; }; studies: { [studyId: string]: AnonStudy; @@ -16,7 +16,7 @@ type setAnonymizationProfilePayload = { }; type AddAnonymizePayload = { - patient: Patient; + patient: AnonPatient; study: AnonStudy; }; @@ -46,7 +46,7 @@ const anonymizeSlice = createSlice({ name: "anonymize", initialState, reducers: { - setAnonymizationProfile: ( + updateAnonymizationProfile: ( state, action: PayloadAction ) => { @@ -57,7 +57,7 @@ const anonymizeSlice = createSlice({ action: PayloadAction ) => { const study = action.payload.study; - const patientId = action.payload.patient.id; + const patientId = action.payload.patient.originalPatient.id; state.studies[study.originalStudy.id] = study; state.patients[patientId] = action.payload.patient; }, @@ -67,15 +67,21 @@ const anonymizeSlice = createSlice({ ) => { const patientId = action.payload.patientId; + const studyIdsToUpdate = Object.values(state.studies) .filter((study) => study.originalStudy.parentPatient === patientId) .map((study) => study.originalStudy.id); for (const studyId of studyIdsToUpdate) { - if (action.payload.newPatientName) + if (action.payload.newPatientName) { state.studies[studyId].newPatientName = action.payload.newPatientName; - if (action.payload.newPatientId) + state[patientId].newPatientName = action.payload.newPatientName; + } + + if (action.payload.newPatientId) { state.studies[studyId].newPatientId = action.payload.newPatientId; + state[patientId].newPatientId = action.payload.newPatientId; + } } }, @@ -114,7 +120,7 @@ const anonymizeSlice = createSlice({ }); export const { - setAnonymizationProfile, + updateAnonymizationProfile, addStudyToAnonymizeList, removeStudyFromAnonymizeList, flushAnonymizeList, diff --git a/src/root/ToolList.tsx b/src/root/ToolList.tsx index e8a4f832..0d6c11d2 100644 --- a/src/root/ToolList.tsx +++ b/src/root/ToolList.tsx @@ -1,10 +1,9 @@ import { useSelector } from "react-redux" import { RootState } from "../store" -import AnonIcon from "../ui/AnonIcon" import ToolItem from "./ToolItem" import { useNavigate } from "react-router-dom" -import { Export, Trash } from "../icons" +import { Anon, Export, Trash } from "../icons" const ToolList = () => { @@ -18,7 +17,7 @@ const ToolList = () => {
navigate('/anonymize')}> - diff --git a/src/utils/enums.ts b/src/utils/enums.ts index 9841a824..9d214d29 100644 --- a/src/utils/enums.ts +++ b/src/utils/enums.ts @@ -1,8 +1,8 @@ export enum Colors { almond = 'almond', almondHover = 'almond-hover', - blueCustom = 'buel-custom', - blusCustomHover = 'buel-custom-hover', + blueCustom = 'blue-custom', + blueCustomHover = 'blue-custom-hover', danger = 'danger', dangerHover = "danger-hover", dark = 'dark', diff --git a/src/utils/types.ts b/src/utils/types.ts index 95323f59..fe967e23 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -365,6 +365,12 @@ export type Study = { type: string; }; +export type AnonPatient = { + newPatientName : string, + newPatientId : string, + originalPatient : Patient +} + export type AnonStudy = { newPatientName : string, newPatientId : string, diff --git a/tailwind.config.js b/tailwind.config.js index 4456e4fb..0dcf977c 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -63,8 +63,8 @@ export default { 'warning-hover': '#A88400', 'dark': '#484544', 'redCustom': '#f8d7da', - 'blueCustom': '#0595a0', - 'blue-custom-hover': '#0a7e87', + 'blueCustom': '#2F77BA', + 'blue-custom-hover': '#245D92', 'grayCustom': '#D4CFCF', 'light': '#FFFFFF', 'light-gray': '#EFEFEF', From aa83604b3da2d4a9d3d2fcf14ab97ff08293609e Mon Sep 17 00:00:00 2001 From: Sophie Labyt Date: Tue, 15 Oct 2024 16:09:15 +0200 Subject: [PATCH 2/5] add button anon fill , correction problem popover selectransfersyntax --- src/anonymize/AnonymizeRoot.tsx | 153 +++++++++++++++++----------- src/anonymize/PatientTable.tsx | 5 +- src/anonymize/StudyTable.tsx | 23 ++--- src/export/ExportRoot.tsx | 24 ++++- src/export/SelectTransferSyntax.tsx | 78 +++++++++++--- src/icons/AutofIll.tsx | 9 ++ src/queue/ProgressQueueBar.tsx | 1 - src/reducers/AnonymizeSlice.ts | 8 +- src/ui/Popover.tsx | 38 ++++++- src/ui/table/Table.tsx | 4 +- src/utils/actionsUtils.ts | 6 +- src/utils/types.ts | 54 ++++++---- 12 files changed, 275 insertions(+), 128 deletions(-) create mode 100644 src/icons/AutofIll.tsx diff --git a/src/anonymize/AnonymizeRoot.tsx b/src/anonymize/AnonymizeRoot.tsx index ec731a72..5e7eaa3a 100644 --- a/src/anonymize/AnonymizeRoot.tsx +++ b/src/anonymize/AnonymizeRoot.tsx @@ -5,74 +5,79 @@ import PatientTable from "./PatientTable"; import StudyTable from "./StudyTable"; import { RootState } from "../store"; import { useMemo, useState } from "react"; -import { flushAnonymizeList, removeStudyFromAnonymizeList, updateAnonymizationProfile, updateAnonymizePatientValue, updateAnonymizeStudyValue } from "../reducers/AnonymizeSlice"; +import { + flushAnonymizeList, + removeStudyFromAnonymizeList, + updateAnonymizationProfile, + updateAnonymizePatientValue, + updateAnonymizeStudyValue, +} from "../reducers/AnonymizeSlice"; import { Anon, Empty } from "../icons"; - +import AutoFill from "../icons/AutofIll"; const profileOptions = [ - { value : 'default', label: 'Default' }, - {value : 'full', label: 'Full' }, -] + { value: "default", label: "Default" }, + { value: "full", label: "Full" }, +]; + const AnonymizeRoot = () => { const dispatch = useDispatch(); const anonList = useSelector((state: RootState) => state.anonymize); - const [selectedPatientId, setSelectedPatientId] = useState(null) - + const [selectedPatientId, setSelectedPatientId] = useState( + null + ); - const patients = useMemo(() => { - return Object.values(anonList.patients); - }, [anonList]); + const patients = useMemo(() => Object.values(anonList.patients), [anonList]); const studies = useMemo(() => { - if (!selectedPatientId) return [] - return Object.values(anonList.studies).filter(study => study.originalStudy.parentPatient === selectedPatientId); + if (!selectedPatientId) return []; + return Object.values(anonList.studies).filter( + (study) => study.originalStudy.parentPatient === selectedPatientId + ); }, [anonList, selectedPatientId]); - const handlePatientSelect = (patientId :string) => { - setSelectedPatientId(patientId) - } - const handleRemovePatient = (patientId: string) => { - const studiesIds = studies - .filter((study) => study.originalStudy.parentPatient === patientId) - .map((study) => study.originalStudy.id); - for (const studyId of studiesIds) { - dispatch(removeStudyFromAnonymizeList({ studyId })); - } - }; - - const handleRemoveStudy = (studyId: string) => { - dispatch(removeStudyFromAnonymizeList({ studyId })); - }; - - const handleChangeStudy = (studyId: string, newStudyDescription: string) => { - dispatch(updateAnonymizeStudyValue({ newStudyDescription, studyId })); - }; - - const handleChangePatient = (patientId: string, key: 'newPatientId' | 'newPatientName', value: string) => { - dispatch(updateAnonymizePatientValue({ patientId, [key]: value })); - } + const handleAutoFill = () => { + patients.forEach((patient) => { + dispatch( + updateAnonymizePatientValue({ + patientId: patient.originalPatient.id, + newPatientName: `Patient_${patient.originalPatient.id}`, + newPatientId: `ID_${patient.originalPatient.id}`, + }) + ); + }); - const handleClearList = () => { - dispatch(flushAnonymizeList()); + studies.forEach((study) => { + dispatch( + updateAnonymizeStudyValue({ + studyId: study.originalStudy.id, + newStudyDescription: `Study_${study.originalStudy.id}`, + newAccessionNumber: `Acc_${study.originalStudy.id}`, + }) + ); + }); }; - const handleProfileChange = (option) =>{ - dispatch(updateAnonymizationProfile({anonymizationProfile: option.value})) - } - return ( - +
-
Anonymize Ressources
+
+ Anonymiser les ressources +
+
@@ -80,28 +85,56 @@ const AnonymizeRoot = () => {
- + + dispatch( + updateAnonymizePatientValue({ patientId, [key]: value }) + ) + } + onRemovePatient={(patientId) => + studies + .filter( + (study) => study.originalStudy.parentPatient === patientId + ) + .forEach((study) => + dispatch( + removeStudyFromAnonymizeList({ studyId: study.originalStudy.id }) + ) + ) + } + />
- + + dispatch( + updateAnonymizeStudyValue({ studyId, [key]: value }) + ) + } + onRemoveStudy={(studyId) => + dispatch(removeStudyFromAnonymizeList({ studyId })) + } + />
- + dispatch(updateAnonymizationProfile({ anonymizationProfile: option.value })) + } /> -
); }; diff --git a/src/anonymize/PatientTable.tsx b/src/anonymize/PatientTable.tsx index 8ae3e84f..40210b4f 100644 --- a/src/anonymize/PatientTable.tsx +++ b/src/anonymize/PatientTable.tsx @@ -22,6 +22,7 @@ const PatientTable = ({ onChangePatient, onRowSelectionChange, }: PatientTableProps) => { + console.log(patients) const columns: ColumnDef[] = useMemo(() => [ { id: "id", @@ -37,11 +38,13 @@ const PatientTable = ({ }, { id: "newPatientId", + accessorKey: "newPatientId", header: "New Patient ID", isEditable: true }, { id: "newPatientName", + accessorKey: "newPatientName", header: "New Patient Name", isEditable: true }, @@ -76,9 +79,9 @@ const PatientTable = ({ onRowClick={(row) => onClickRow(row.originalPatient.id)} onCellEdit={onChangePatient} getRowClasses={getRowClasses} - enableRowSelection={true} selectedRow={selectedRows} onRowSelectionChange={onRowSelectionChange} + getRowId={(row) => row.originalPatient.id} /> ); }; diff --git a/src/anonymize/StudyTable.tsx b/src/anonymize/StudyTable.tsx index 0f313062..3a0f085e 100644 --- a/src/anonymize/StudyTable.tsx +++ b/src/anonymize/StudyTable.tsx @@ -6,7 +6,7 @@ import { AnonStudy } from "../utils/types"; type StudyTableProps = { studies: AnonStudy[]; - onChangeStudy: (studyId: string, studyDescription: string) => void; + onChangeStudy: (studyId: string, key:string, value: string) => void; onRemoveStudy: (studyId: string) => void; }; @@ -25,22 +25,10 @@ const StudyTable = ({ studies, onChangeStudy, onRemoveStudy }: StudyTableProps) header: "Study Description", }, { + id : "newStudyDescription", accessorKey: "newStudyDescription", header: "New Study Description", - cell: ({ row }) => { - return ( - - onChangeStudy( - row.original.originalStudy.id, - event.target.value - ) - } - /> - ); - }, + isEditable: true, }, { header: "Remove", @@ -61,9 +49,12 @@ const StudyTable = ({ studies, onChangeStudy, onRemoveStudy }: StudyTableProps) return
row.originalStudy.id} />; diff --git a/src/export/ExportRoot.tsx b/src/export/ExportRoot.tsx index ed57825b..24cc851a 100644 --- a/src/export/ExportRoot.tsx +++ b/src/export/ExportRoot.tsx @@ -176,7 +176,10 @@ const ExportRoot = () => { - setTrasferSyntax(value)} /> + setTrasferSyntax(value)} + /> @@ -196,12 +199,23 @@ const ExportRoot = () => {
- - + + {storeJobId && } - + {sendPeerJobId && } -
diff --git a/src/export/SelectTransferSyntax.tsx b/src/export/SelectTransferSyntax.tsx index 2cb4534b..763ca412 100644 --- a/src/export/SelectTransferSyntax.tsx +++ b/src/export/SelectTransferSyntax.tsx @@ -1,12 +1,11 @@ +import { useState, useEffect } from "react"; import { Gear } from "../icons"; -import { Button, Popover, SelectInput } from "../ui"; -import { Colors } from "../utils"; +import { Popover, SelectInput } from "../ui"; type SelectTransferSyntaxProps = { value: string; - onChange: (value: string) => void -} - + onChange: (value: string) => void; +}; const TRANSCODING_OPTIONS = [ { value: 'None', label: 'None (use Original TS)' }, @@ -23,24 +22,75 @@ const TRANSCODING_OPTIONS = [ { value: '1.2.840.10008.1.2.4.90', label: 'JPEG 2000 (90)' }, { value: '1.2.840.10008.1.2.4.91', label: 'JPEG 2000 (91)' }, { value: '1.2.840.10008.1.2.4.92', label: 'JPEG 2000 (92)' }, - { value: '1.2.840.10008.1.2.4.93', label: 'JPEG 2000 (93)' } -] + { value: '1.2.840.10008.1.2.4.93', label: 'JPEG 2000 (93)' }, +]; const SelectTransferSyntax = ({ value, onChange }: SelectTransferSyntaxProps) => { + const [clicked, setClicked] = useState(false); + const [hovered, setHovered] = useState(false); + + const handleClick = () => { + setClicked(prev => !prev); + setHovered(false); + }; + + const handleMouseEnter = () => { + if (!clicked) { + setHovered(true); + } + }; + + const handleMouseLeave = () => { + setHovered(false); + }; + + useEffect(() => { + const handleOutsideClick = (event: MouseEvent) => { + if (!event.target.closest('.popover-container')) { + setClicked(false); + setHovered(false); + } + }; + + if (clicked) { + document.addEventListener('mousedown', handleOutsideClick); + } + + return () => { + document.removeEventListener('mousedown', handleOutsideClick); + }; + }, [clicked]); return ( onChange(option?.value)} />} + { + onChange(option?.value); + setClicked(false); + }} + /> + } + backgroundColor="bg-secondary" > -
- +
+
- ) - -} + ); +}; -export default SelectTransferSyntax \ No newline at end of file +export default SelectTransferSyntax; \ No newline at end of file diff --git a/src/icons/AutofIll.tsx b/src/icons/AutofIll.tsx new file mode 100644 index 00000000..d3a94753 --- /dev/null +++ b/src/icons/AutofIll.tsx @@ -0,0 +1,9 @@ +import { MdAutoFixHigh } from 'react-icons/md'; + +const AutoFill = (props) => { + return ( + + ); +}; + +export default AutoFill; diff --git a/src/queue/ProgressQueueBar.tsx b/src/queue/ProgressQueueBar.tsx index 0726c4f3..c14b7aeb 100644 --- a/src/queue/ProgressQueueBar.tsx +++ b/src/queue/ProgressQueueBar.tsx @@ -29,7 +29,6 @@ const ProgressQueueBar = ({ uuid }: ProgressQueueProps) => { className="mr-2 text-sm cursor-pointer hover:text-yellow-500" disabled onClick={() => { - // Implement pause functionality here }} /> ) => { - const study = action.payload.study; + const studyId = action.payload.study.originalStudy.id; const patientId = action.payload.patient.originalPatient.id; - state.studies[study.originalStudy.id] = study; + state.studies[studyId] = action.payload.study; state.patients[patientId] = action.payload.patient; }, updateAnonymizePatientValue: ( @@ -75,12 +75,12 @@ const anonymizeSlice = createSlice({ for (const studyId of studyIdsToUpdate) { if (action.payload.newPatientName) { state.studies[studyId].newPatientName = action.payload.newPatientName; - state[patientId].newPatientName = action.payload.newPatientName; + state.patients[patientId].newPatientName = action.payload.newPatientName; } if (action.payload.newPatientId) { state.studies[studyId].newPatientId = action.payload.newPatientId; - state[patientId].newPatientId = action.payload.newPatientId; + state.patients[patientId].newPatientId = action.payload.newPatientId; } } diff --git a/src/ui/Popover.tsx b/src/ui/Popover.tsx index 8f9a2500..d3f5b16b 100644 --- a/src/ui/Popover.tsx +++ b/src/ui/Popover.tsx @@ -1,11 +1,12 @@ -import React, { useState } from 'react'; +import React, { useState, useEffect, useRef } from 'react'; type PopoverProps = { children: React.ReactNode; withOnClick: boolean; popover: React.ReactNode; - placement?: 'top' | 'right' | 'bottom' | 'left'; + placement?: 'top' | 'right' | 'bottom' | 'left' | 'bottom-left' | 'bottom-right'; className?: string; + backgroundColor?: string; }; const Popover: React.FC = ({ @@ -14,8 +15,11 @@ const Popover: React.FC = ({ withOnClick = false, placement = 'bottom', className = '', + backgroundColor = 'bg-secondary', }) => { const [isOpen, setIsOpen] = useState(false); + const popoverRef = useRef(null); + const triggerRef = useRef(null); const getPlacementClasses = (placement: string) => { switch (placement) { @@ -27,6 +31,10 @@ const Popover: React.FC = ({ return 'top-full left-1/2 transform -translate-x-1/2 mt-2'; case 'left': return 'right-full top-1/2 transform -translate-y-1/2 mr-2'; + case 'bottom-left': + return 'top-full left-0 transform mt-2'; + case 'bottom-right': + return 'top-full right-0 transform mt-2'; default: return 'top-full left-1/2 transform -translate-x-1/2 mt-2'; } @@ -36,14 +44,36 @@ const Popover: React.FC = ({ ? { onClick: () => setIsOpen(!isOpen) } : { onMouseEnter: () => setIsOpen(true), onMouseLeave: () => setIsOpen(false) }; + const handleOutsideClick = (event: MouseEvent) => { + if ( + popoverRef.current && !popoverRef.current.contains(event.target as Node) && + triggerRef.current && !triggerRef.current.contains(event.target as Node) + ) { + setIsOpen(false); + } + }; + + useEffect(() => { + if (isOpen) { + document.addEventListener('mousedown', handleOutsideClick); + } else { + document.removeEventListener('mousedown', handleOutsideClick); + } + + return () => { + document.removeEventListener('mousedown', handleOutsideClick); + }; + }, [isOpen]); + return (
- + {children} {isOpen && (
{popover}
diff --git a/src/ui/table/Table.tsx b/src/ui/table/Table.tsx index 950600bf..df870614 100644 --- a/src/ui/table/Table.tsx +++ b/src/ui/table/Table.tsx @@ -39,6 +39,7 @@ type TableProps = { getRowStyles?: (row: TData) => React.CSSProperties | undefined; getRowClasses?: (row: TData) => string | undefined; onCellEdit?: (rowIndex: string | number, columnId: any, value: any) => void + getRowId?: (originalRow: TData, index: number) => string }; function Table({ @@ -61,6 +62,7 @@ function Table({ getRowStyles, getRowClasses = (row) => 'bg-indigo-50', onCellEdit = () => { }, + getRowId = (originalRow, index) => { return originalRow?.[id] ?? index} }: TableProps) { const [sorting, setSorting] = useState([]); const [columnFilters, setColumnFilters] = useState([]); @@ -115,7 +117,7 @@ function Table({ rowSelection: selectedRow, columnVisibility: columnVisibility }, - getRowId: (originalRow, index) => { return originalRow?.[id] ?? index}, + getRowId: getRowId, onPaginationChange: setPagination, onSortingChange: setSorting, onColumnFiltersChange: setColumnFilters, diff --git a/src/utils/actionsUtils.ts b/src/utils/actionsUtils.ts index 0bdd3972..8fec8b1a 100644 --- a/src/utils/actionsUtils.ts +++ b/src/utils/actionsUtils.ts @@ -16,7 +16,11 @@ export const addStudyIdToAnonymizeList = async (studyId: string) => { const study = await getStudy(studyId) const patient = await getPatient(study.parentPatient) store.dispatch(addStudyToAnonymizeList({ - patient : patient, + patient : { + newPatientId: null, + newPatientName: null, + originalPatient: patient + }, study: { newPatientId: null, newPatientName: null, diff --git a/src/utils/types.ts b/src/utils/types.ts index fe967e23..dd66e9d9 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -139,7 +139,7 @@ export type ProcessingJob = { progress: number; state: string; id: string; - results : Record + results: Record }; export type Peer = { @@ -206,8 +206,8 @@ type QuerySeries = { SeriesDescription?: string; SeriesNumber?: string; SeriesInstanceUID?: string; - NumberOfSeriesRelatedInstances? : string; - ProtocolName? :string; + NumberOfSeriesRelatedInstances?: string; + ProtocolName?: string; }; type Level = "Series" | "Study"; @@ -304,7 +304,7 @@ export type Instances = { instanceCreationTime: string | null; instanceNumber: string | null; sopInstanceUID: string | null; - numberOfFrames: string|null; + numberOfFrames: string | null; }; parentSeries: string; type: string; @@ -345,7 +345,7 @@ export type PatientModifyPayload = { force: boolean; synchronous: boolean; keepSource: boolean; - keep : string[]; + keep: string[]; }; export type OrthancResponse = { @@ -366,25 +366,25 @@ export type Study = { }; export type AnonPatient = { - newPatientName : string, - newPatientId : string, - originalPatient : Patient + newPatientName: string, + newPatientId: string, + originalPatient: Patient } export type AnonStudy = { - newPatientName : string, - newPatientId : string, - newStudyDescription : string, - newAccessionNumber : string, - originalStudy : Study; + newPatientName: string, + newPatientId: string, + newStudyDescription: string, + newAccessionNumber: string, + originalStudy: Study; } export type StudyModifyPayload = { - replace: Partial; + replace: Partial; remove: string[]; removePrivateTags: boolean; force: boolean; - keep : string[]; + keep: string[]; synchronous: boolean; keepSource: boolean; }; @@ -396,13 +396,25 @@ export type SeriesModifyPayload = { keepSource: boolean; force: boolean; synchronous: boolean; - keep : string[]; + keep: string[]; }; export type Queue = { - progress : number - state : string - id : string - results : Record - userId : number + progress: number + state: string + id: string + results: Record + userId: number +} + +export type AnonItem = { + OrthancStudyID: string, + Profile: 'full' | 'default', + NewAccessionNumber: string + NewPatientID: string + NewPatientName: string +} + +export type AnonymizePayload = { + Anonymizes: AnonItem[] } \ No newline at end of file From 473aec11832bd1db4f876efa10867650dd420313 Mon Sep 17 00:00:00 2001 From: Sophie Labyt Date: Wed, 16 Oct 2024 11:13:46 +0200 Subject: [PATCH 3/5] wip --- src/anonymize/AnonymizeRoot.tsx | 65 +++++++++++++++++++-------------- src/anonymize/PatientTable.tsx | 2 +- src/delete/DeleteQueues.tsx | 19 +++++----- src/delete/DeleteRoot.tsx | 33 +++++++++-------- src/delete/DeleteStudyTable.tsx | 2 +- src/queue/ProgressQueueBar.tsx | 2 +- src/ui/ProgressBar.tsx | 9 +++-- src/ui/table/EditableCell.tsx | 3 -- 8 files changed, 72 insertions(+), 63 deletions(-) diff --git a/src/anonymize/AnonymizeRoot.tsx b/src/anonymize/AnonymizeRoot.tsx index 5e7eaa3a..1c392099 100644 --- a/src/anonymize/AnonymizeRoot.tsx +++ b/src/anonymize/AnonymizeRoot.tsx @@ -57,6 +57,37 @@ const AnonymizeRoot = () => { }); }; + const onChangeStudy = (studyId, key, value) => { + dispatch( + updateAnonymizeStudyValue({ studyId, [key]: value }) + ) + } + + const onRemoveStudy = (studyId) => { + dispatch(removeStudyFromAnonymizeList({ studyId })) + } + + const onChangePatient = (patientId, key, value) => { + dispatch( + updateAnonymizePatientValue({ patientId, [key]: value }) + ) + } + + const onRemovePatient = (patientId) => { + studies.filter((study) => study.originalStudy.parentPatient === patientId). + forEach((study) =>{ + console.log(study.originalStudy.id) + dispatch( + removeStudyFromAnonymizeList({ studyId: study.originalStudy.id }) + )} + ) + + } + + const onChangeProfile = (option) =>{ + dispatch(updateAnonymizationProfile({ anonymizationProfile: option.value })) + } + return ( @@ -88,35 +119,15 @@ const AnonymizeRoot = () => { - dispatch( - updateAnonymizePatientValue({ patientId, [key]: value }) - ) - } - onRemovePatient={(patientId) => - studies - .filter( - (study) => study.originalStudy.parentPatient === patientId - ) - .forEach((study) => - dispatch( - removeStudyFromAnonymizeList({ studyId: study.originalStudy.id }) - ) - ) - } + onChangePatient={onChangePatient} + onRemovePatient={onRemovePatient} />
- dispatch( - updateAnonymizeStudyValue({ studyId, [key]: value }) - ) - } - onRemoveStudy={(studyId) => - dispatch(removeStudyFromAnonymizeList({ studyId })) - } + onChangeStudy={onChangeStudy} + onRemoveStudy={onRemoveStudy} />
@@ -127,12 +138,10 @@ const AnonymizeRoot = () => { Anonymiser - dispatch(updateAnonymizationProfile({ anonymizationProfile: option.value })) - } + onChange={onChangeProfile} />
diff --git a/src/anonymize/PatientTable.tsx b/src/anonymize/PatientTable.tsx index 40210b4f..1ac3ce1f 100644 --- a/src/anonymize/PatientTable.tsx +++ b/src/anonymize/PatientTable.tsx @@ -52,7 +52,7 @@ const PatientTable = ({ header: "remove", cell: ({ row }) => { return ( - ); diff --git a/src/delete/DeleteQueues.tsx b/src/delete/DeleteQueues.tsx index 982515b3..bfdf7d1a 100644 --- a/src/delete/DeleteQueues.tsx +++ b/src/delete/DeleteQueues.tsx @@ -16,15 +16,16 @@ const DeleteQueues = () => { if (isPending) return ; return ( -
- {existingDeleteQueues?.map((uuid) => ( -
- -
- ))} -
+
+ {existingDeleteQueues?.map((uuid) => ( +
+ +
+ ))} +
); }; diff --git a/src/delete/DeleteRoot.tsx b/src/delete/DeleteRoot.tsx index 84368c36..1897b1a8 100644 --- a/src/delete/DeleteRoot.tsx +++ b/src/delete/DeleteRoot.tsx @@ -55,25 +55,26 @@ const DeleteRoot = () => { - + - - + +
+ - - +
+ +
+
+ ); }; diff --git a/src/delete/DeleteStudyTable.tsx b/src/delete/DeleteStudyTable.tsx index d0d22c27..655927ad 100644 --- a/src/delete/DeleteStudyTable.tsx +++ b/src/delete/DeleteStudyTable.tsx @@ -52,7 +52,7 @@ const DeleteStudyTable = ({ studies }: DeleteStudyTableProps) => {
diff --git a/src/queue/ProgressQueueBar.tsx b/src/queue/ProgressQueueBar.tsx index c14b7aeb..052872e3 100644 --- a/src/queue/ProgressQueueBar.tsx +++ b/src/queue/ProgressQueueBar.tsx @@ -26,7 +26,7 @@ const ProgressQueueBar = ({ uuid }: ProgressQueueProps) => {
{ }} diff --git a/src/ui/ProgressBar.tsx b/src/ui/ProgressBar.tsx index 8d264d8a..6371c05a 100644 --- a/src/ui/ProgressBar.tsx +++ b/src/ui/ProgressBar.tsx @@ -1,4 +1,3 @@ - import React from 'react'; type ProgressIndicatorProps = { @@ -8,13 +7,15 @@ type ProgressIndicatorProps = { const ProgressBar: React.FC = ({ progress }) => { return (
-
+
+ + {progress}% +
-

{progress}%

); }; diff --git a/src/ui/table/EditableCell.tsx b/src/ui/table/EditableCell.tsx index 0037652a..69a50e83 100644 --- a/src/ui/table/EditableCell.tsx +++ b/src/ui/table/EditableCell.tsx @@ -55,9 +55,6 @@ const EditableCell = ({ placeholder={placeholder} value={value ?? ""} onChange={onChange} - onClick={(e) => { - e.stopPropagation() - }} onBlur={onBlur} /> ) From beed01ef180ceed86d16ed815768dee6a70b5a17 Mon Sep 17 00:00:00 2001 From: Sophie Labyt Date: Wed, 16 Oct 2024 11:26:33 +0200 Subject: [PATCH 4/5] clean colors --- src/import/import/ImportRoot.tsx | 2 +- src/ui/BannerAlert.tsx | 4 ++-- src/ui/Button.tsx | 13 ------------- src/ui/Card.tsx | 11 ++--------- src/ui/table/Table.tsx | 2 +- src/utils/enums.ts | 16 +--------------- src/welcome/ForgotPasswordForm.tsx | 4 ++-- tailwind.config.js | 8 ++------ 8 files changed, 11 insertions(+), 49 deletions(-) diff --git a/src/import/import/ImportRoot.tsx b/src/import/import/ImportRoot.tsx index 360e9d27..4993a9a2 100644 --- a/src/import/import/ImportRoot.tsx +++ b/src/import/import/ImportRoot.tsx @@ -70,7 +70,7 @@ const ImportRoot: React.FC = () => { {errors.length > 0 && ( = ({ - color = Colors.red, + color = Colors.danger, className = '', children, buttonLabel = 'See Errors', @@ -29,7 +29,7 @@ const BannerAlert: React.FC = ({ return 'text-yellow-800 border-yellow-300 bg-yellow-50 dark:text-yellow-300 dark:border-yellow-800 dark:bg-gray-800'; case Colors.dark: return 'text-gray-800 border-gray-300 bg-gray-50 dark:text-gray-300 dark:border-gray-600 dark:bg-gray-800'; - case Colors.red: + case Colors.danger: return 'text-red-800 border-red-800 bg-white dark:text-red-400 dark:border-red-800 dark:bg-gray-800'; case Colors.gray: return 'text-gray-800 border-gray-300 bg-gray-50 dark:text-gray-300 dark:border-gray-600 dark:bg-gray-800'; diff --git a/src/ui/Button.tsx b/src/ui/Button.tsx index 0ce09fcf..174c9806 100644 --- a/src/ui/Button.tsx +++ b/src/ui/Button.tsx @@ -21,25 +21,12 @@ const Button: React.FC = ({ danger: "bg-danger hover:bg-danger-hover", success: "bg-success hover:bg-success-hover", blueCustom: "bg-blue-custom hover:bg-blue-custom-hover", - disabled: "bg-disabled", warning: "bg-warning hover:bg-warning-hover", dark: "bg-dark", - red: "bg-red", gray: "bg-gray", light: "bg-light", - grayCustom: "", - almondHover: '', - dangerHover: '', lightGray: '', - warningHover: '', - primaryActive: '', - primaryHover: '', - secondaryLight: '', - secondaryHover: '', - successHover: '', - sucessLight: '', white: '', - transparent: '' }; const isDisabled = props.disabled; diff --git a/src/ui/Card.tsx b/src/ui/Card.tsx index 8cb42b46..4261d334 100644 --- a/src/ui/Card.tsx +++ b/src/ui/Card.tsx @@ -34,23 +34,16 @@ type CardFooterProps = { const colorClasses: Record = { almond: "bg-almond", primary: "bg-primary", - transparent : "bg-transparent", - primaryHover: "hover:bg-primary-hover", secondary: "bg-secondary", - secondaryHover: "hover:bg-secondary-hover", danger: "bg-danger", - dangerHover: "hover:bg-danger-hover", - grayCustom: "bg-grayCustom", success: "bg-success", - successHover: "hover:bg-success-hover", - disabled: "bg-disabled", warning: "bg-warning", - warningHover: "hover:bg-warning-hover", dark: "bg-dark", - red: "bg-red", gray: "bg-gray", light: "bg-light", white: "bg-white", + [Colors.blueCustom]: '', + [Colors.lightGray]: '' }; const getColorClass = (color?: Colors) => color ? colorClasses[color] ?? "" : ""; diff --git a/src/ui/table/Table.tsx b/src/ui/table/Table.tsx index df870614..aeebeda7 100644 --- a/src/ui/table/Table.tsx +++ b/src/ui/table/Table.tsx @@ -162,7 +162,7 @@ function Table({ return (
-
+
{table.getHeaderGroups().map(headerGroup => ( diff --git a/src/utils/enums.ts b/src/utils/enums.ts index 9d214d29..3bf5c04d 100644 --- a/src/utils/enums.ts +++ b/src/utils/enums.ts @@ -1,28 +1,14 @@ export enum Colors { almond = 'almond', - almondHover = 'almond-hover', - blueCustom = 'blue-custom', - blueCustomHover = 'blue-custom-hover', + blueCustom = 'blueCustom', danger = 'danger', - dangerHover = "danger-hover", dark = 'dark', - disabled = 'disabled', gray = 'gray', - grayCustom = 'gray-custom', light = 'light', lightGray = 'light-gray', warning = 'warning', - warningHover = 'warning-hover', primary = 'primary', - primaryActive = 'primary-active', - primaryHover = 'primary-hover', - red = 'red', secondary = 'secondary', - secondaryLight = 'secondary-light', - secondaryHover = 'secondary-hover', success = 'success', - successHover = 'success-hover', - sucessLight = 'sucess-light', white = 'white', - transparent = 'transparent' } diff --git a/src/welcome/ForgotPasswordForm.tsx b/src/welcome/ForgotPasswordForm.tsx index bf7b44a6..f8f3c1bd 100644 --- a/src/welcome/ForgotPasswordForm.tsx +++ b/src/welcome/ForgotPasswordForm.tsx @@ -55,9 +55,9 @@ const ForgotPasswordForm = () => { />
{ options={profileOptions} onChange={onChangeProfile} /> + ); diff --git a/src/anonymize/PatientTable.tsx b/src/anonymize/PatientTable.tsx index 1ac3ce1f..75907cb0 100644 --- a/src/anonymize/PatientTable.tsx +++ b/src/anonymize/PatientTable.tsx @@ -74,7 +74,7 @@ const PatientTable = ({ columns={columns} data={patients} headerTextSize="xs" - className="text-xs bg-gray-100" + className="text-sm break-words bg-gray-100" columnVisibility={{ id: false }} onRowClick={(row) => onClickRow(row.originalPatient.id)} onCellEdit={onChangePatient} diff --git a/src/delete/DeleteQueues.tsx b/src/delete/DeleteQueues.tsx index bfdf7d1a..d35ac789 100644 --- a/src/delete/DeleteQueues.tsx +++ b/src/delete/DeleteQueues.tsx @@ -1,18 +1,40 @@ import { useSelector } from "react-redux"; -import { getExistingDeleteQueues } from "../services/queues"; -import { useCustomQuery } from "../utils"; +import { deleteDeleteQueue, getDeleteQueue, getExistingDeleteQueues } from "../services/queues"; +import { useCustomMutation, useCustomQuery } from "../utils"; import { RootState } from "../store"; -import { Spinner } from "../ui"; +import { ProgressCircle, Spinner } from "../ui"; import ProgressQueueBar from "../queue/ProgressQueueBar"; +import { Queue } from "../utils/types"; +import ProgressQueueCircle from "../queue/ProgressQueueCircle"; -const DeleteQueues = () => { +type DeleteQueueProps = { + circle?: boolean +} + +const DeleteQueues = ({ circle = false }: DeleteQueueProps) => { const currentUserId = useSelector((state: RootState) => state.user.currentUserId); - const { data: existingDeleteQueues, isPending } = useCustomQuery( + const { data: existingDeleteQueues } = useCustomQuery( ['queue', 'delete', currentUserId?.toString() || ''], () => getExistingDeleteQueues(currentUserId) ); + const firstQueue = existingDeleteQueues?.[0] + + const { data, isPending } = useCustomQuery( + ['queue', 'delete', firstQueue], + () => getDeleteQueue(firstQueue), + { + refetchInterval: 2000, + enabled: existingDeleteQueues?.length > 0 + } + ); + + const { mutate: mutateDeleteQueue } = useCustomMutation( + () => deleteDeleteQueue(firstQueue), + [['queue', 'delete']] + ); + if (isPending) return ; return ( @@ -20,9 +42,15 @@ const DeleteQueues = () => { {existingDeleteQueues?.map((uuid) => (
- + { + circle ? + mutateDeleteQueue({})} /> + : + mutateDeleteQueue({})} /> + } +
))}
diff --git a/src/delete/DeleteRoot.tsx b/src/delete/DeleteRoot.tsx index 1897b1a8..60878b6a 100644 --- a/src/delete/DeleteRoot.tsx +++ b/src/delete/DeleteRoot.tsx @@ -65,7 +65,8 @@ const DeleteRoot = () => { color={Colors.danger} className="flex items-center justify-center" > - + Delete List diff --git a/src/export/ExportRoot.tsx b/src/export/ExportRoot.tsx index 24cc851a..779cf874 100644 --- a/src/export/ExportRoot.tsx +++ b/src/export/ExportRoot.tsx @@ -191,8 +191,7 @@ const ExportRoot = () => { - -
+
diff --git a/src/export/ExportStudyTable.tsx b/src/export/ExportStudyTable.tsx index 47800299..4582ef6e 100644 --- a/src/export/ExportStudyTable.tsx +++ b/src/export/ExportStudyTable.tsx @@ -9,7 +9,7 @@ import { Trash } from "../icons"; type ExportStudyTableProps = { studies: Study[]; - onClickStudy : (study : Study) => void + onClickStudy: (study: Study) => void }; const ExportStudyTable = ({ studies, onClickStudy }: ExportStudyTableProps) => { @@ -17,8 +17,8 @@ const ExportStudyTable = ({ studies, onClickStudy }: ExportStudyTableProps) => { const handleDelete = (studyId: string) => { const studyToDelete = studies.find(study => study.id === studyId) - for(const seriesId of studyToDelete.series){ - dispatch(removeSeriesFromExportList({seriesId : seriesId})) + for (const seriesId of studyToDelete.series) { + dispatch(removeSeriesFromExportList({ seriesId: seriesId })) } }; @@ -65,7 +65,12 @@ const ExportStudyTable = ({ studies, onClickStudy }: ExportStudyTableProps) => { [] ); - return
; + return
; }; export default ExportStudyTable; diff --git a/src/queue/ProgressQueueBar.tsx b/src/queue/ProgressQueueBar.tsx index 052872e3..f3798171 100644 --- a/src/queue/ProgressQueueBar.tsx +++ b/src/queue/ProgressQueueBar.tsx @@ -2,38 +2,22 @@ import { deleteDeleteQueue, getDeleteQueue } from "../services/queues"; import { useCustomMutation, useCustomQuery } from "../utils"; import { ProgressBar, ProgressCircle, Spinner } from "../ui"; import { Cancel, Pause } from "../icons"; +import { Queue } from "../utils/types"; type ProgressQueueProps = { - uuid: string; + queueData : Queue, + onDelete: (event: React.MouseEvent) => void }; -const ProgressQueueBar = ({ uuid }: ProgressQueueProps) => { - const { data, isPending } = useCustomQuery( - ['queue', 'delete', uuid], - () => getDeleteQueue(uuid), - { refetchInterval: 2000 } - ); - - const { mutate: mutateDeleteQueue } = useCustomMutation( - () => deleteDeleteQueue(uuid), - [['queue', 'delete']] - ); - - if (isPending) return ; +const ProgressQueueBar = ({ queueData, onDelete }: ProgressQueueProps) => { return (
- +
- { - }} - /> mutateDeleteQueue({})} + onClick={onDelete} />
diff --git a/src/queue/ProgressQueueCircle.tsx b/src/queue/ProgressQueueCircle.tsx index c8b5e61d..676488ec 100644 --- a/src/queue/ProgressQueueCircle.tsx +++ b/src/queue/ProgressQueueCircle.tsx @@ -1,39 +1,22 @@ -import { deleteDeleteQueue, getDeleteQueue } from "../services/queues"; -import { useCustomMutation, useCustomQuery } from "../utils"; -import { ProgressCircle, Spinner } from "../ui"; -import { Cancel, Pause } from "../icons"; +import { ProgressCircle } from "../ui"; +import { Cancel } from "../icons"; +import { Queue } from "../utils/types"; type ProgressQueueProps = { - uuid: string; + queueData: Queue, + onDelete: (event: React.MouseEvent) => void }; -const ProgressQueueCircle = ({ uuid }: ProgressQueueProps) => { - const { data, isPending } = useCustomQuery( - ['queue', 'delete', uuid], - () => getDeleteQueue(uuid), - { refetchInterval: 2000 } - ); - - const { mutate: mutateDeleteQueue } = useCustomMutation( - () => deleteDeleteQueue(uuid), - [['queue', 'delete']] - ); - - if (isPending) return ; +const ProgressQueueCircle = ({ queueData, onDelete }: ProgressQueueProps) => { return (
- +
- {/* Implement pause functionality here */ }} - /> mutateDeleteQueue({})} - /> + className={`text-sm text-danger cursor-pointer hover:text-danger-hover `} + onClick={onDelete} + />
diff --git a/src/root/ToolItem.tsx b/src/root/ToolItem.tsx index 1bcb7e2b..38ff964d 100644 --- a/src/root/ToolItem.tsx +++ b/src/root/ToolItem.tsx @@ -6,7 +6,7 @@ type ToolItemProps = { const ToolItem = ({ children, count, onClick }: ToolItemProps) => { return ( -
+
{children} {count} diff --git a/src/root/ToolList.tsx b/src/root/ToolList.tsx index 0d6c11d2..5606669c 100644 --- a/src/root/ToolList.tsx +++ b/src/root/ToolList.tsx @@ -15,10 +15,10 @@ const ToolList = () => { return ( -
+
navigate('/anonymize')}> navigate('/export')}> diff --git a/src/services/queues.ts b/src/services/queues.ts index 1fbd007c..c2fe226a 100644 --- a/src/services/queues.ts +++ b/src/services/queues.ts @@ -1,5 +1,5 @@ import axios from "axios"; -import { Queue } from "../utils/types"; +import { AnonItem, AnonymizePayload, Queue } from "../utils/types"; export const createDeleteQueue = (seriesId: string[]): Promise => { const payload = { @@ -63,4 +63,70 @@ export const getExistingDeleteQueues = (userId: number | undefined): Promise => { + const payload : AnonymizePayload = { + Anonymizes: anonItems + } + return axios + .post(`/api/queues/anonymize`, payload) + .then((response) => response.data.Uuid) + .catch(function (error) { + if (error.response) { + throw error.response; + } + throw error; + }); +}; + +export const getExistingAnonymizeQueues = (userId: number | undefined): Promise => { + const url = userId ? `/api/queues/anonymize?userId=${userId}` : '/api/queues/anon' + return axios + .get(url) + .then((response) => response.data) + .catch(function (error) { + if (error.response) { + throw error.response; + } + throw error; + }); +}; + + +export const getAnonymizeQueue = (uuid: string): Promise => { + + return axios + .get(`/api/queues/anonymize/${uuid}`) + .then((response) => { + const data: any = Object.values(response.data)[0]; + return { + userId: data.UserId, + progress: data.Progress, + state: data.State, + id: data.Id, + results: data.Results + } + }) + .catch(function (error) { + if (error.response) { + throw error.response; + } + throw error; + }); +}; + + +export const deleteAnonymizeQueue = (uuid: string): Promise => { + + return axios + .delete(`/api/queues/anonymize/${uuid}`) + .then(() => undefined) + .catch(function (error) { + if (error.response) { + throw error.response; + } + throw error; + }); }; \ No newline at end of file diff --git a/src/ui/ProgressBar.tsx b/src/ui/ProgressBar.tsx index 6371c05a..863812eb 100644 --- a/src/ui/ProgressBar.tsx +++ b/src/ui/ProgressBar.tsx @@ -7,12 +7,12 @@ type ProgressIndicatorProps = { const ProgressBar: React.FC = ({ progress }) => { return (
-
+
- + {progress}%
diff --git a/src/ui/menu/DropDownButton.tsx b/src/ui/menu/DropDownButton.tsx index eb173d19..465e0a19 100644 --- a/src/ui/menu/DropDownButton.tsx +++ b/src/ui/menu/DropDownButton.tsx @@ -13,9 +13,11 @@ type DropdownButtonProps = { row: any; options: DropdownOption[]; buttonText?: string; + children?: React.ReactNode; + className?: string; }; -const DropdownButton: React.FC = ({ row, options, buttonText = "Action" }) => { +const DropdownButton: React.FC = ({ row, options, buttonText = "Action", children, className }) => { const dropdownRef = useRef(null); useEffect(() => { @@ -25,11 +27,11 @@ const DropdownButton: React.FC = ({ row, options, buttonTex }, []); const handleOptionClick = (option: DropdownOption) => { - option.action? option.action(row) : null; + option.action ? option.action(row) : null; }; return ( -
+
@@ -232,6 +232,7 @@ function Table({ ))} +
@@ -223,7 +223,7 @@ function Table({ {row.getVisibleCells().map((cell, cellIndex) => (
{flexRender(cell.column.columnDef.cell, cell.getContext())}
{data.length > 0 && table ? ( diff --git a/src/utils/actionsUtils.ts b/src/utils/actionsUtils.ts index 8fec8b1a..296cbc04 100644 --- a/src/utils/actionsUtils.ts +++ b/src/utils/actionsUtils.ts @@ -24,7 +24,7 @@ export const addStudyIdToAnonymizeList = async (studyId: string) => { study: { newPatientId: null, newPatientName: null, - newAccessionNumber: null, + newAccessionNumber: "GaelO-Flow", newStudyDescription: null, originalStudy: study }