fix(studybrowser): Differentiate recent and all in study panel based on a provided time period (#4242)
Co-authored-by: Salim Kanoun <salim.kanoun@gmail.com>
This commit is contained in:
parent
e462fd31f7
commit
6f93449149
@ -4,7 +4,7 @@ import { StudyBrowser, useImageViewer, useViewportGrid } from '@ohif/ui';
|
|||||||
import { utils } from '@ohif/core';
|
import { utils } from '@ohif/core';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
const { sortStudyInstances, formatDate } = utils;
|
const { sortStudyInstances, formatDate, createStudyBrowserTabs } = utils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -206,7 +206,7 @@ function PanelStudyBrowser({
|
|||||||
};
|
};
|
||||||
}, [StudyInstanceUIDs, thumbnailImageSrcMap, displaySetService]);
|
}, [StudyInstanceUIDs, thumbnailImageSrcMap, displaySetService]);
|
||||||
|
|
||||||
const tabs = _createStudyBrowserTabs(StudyInstanceUIDs, studyDisplayList, displaySets);
|
const tabs = createStudyBrowserTabs(StudyInstanceUIDs, studyDisplayList, displaySets);
|
||||||
|
|
||||||
// TODO: Should not fire this on "close"
|
// TODO: Should not fire this on "close"
|
||||||
function _handleStudyClick(StudyInstanceUID) {
|
function _handleStudyClick(StudyInstanceUID) {
|
||||||
@ -324,58 +324,3 @@ function _getComponentType(ds) {
|
|||||||
|
|
||||||
return 'thumbnail';
|
return 'thumbnail';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {string[]} primaryStudyInstanceUIDs
|
|
||||||
* @param {object[]} studyDisplayList
|
|
||||||
* @param {string} studyDisplayList.studyInstanceUid
|
|
||||||
* @param {string} studyDisplayList.date
|
|
||||||
* @param {string} studyDisplayList.description
|
|
||||||
* @param {string} studyDisplayList.modalities
|
|
||||||
* @param {number} studyDisplayList.numInstances
|
|
||||||
* @param {object[]} displaySets
|
|
||||||
* @returns tabs - The prop object expected by the StudyBrowser component
|
|
||||||
*/
|
|
||||||
function _createStudyBrowserTabs(primaryStudyInstanceUIDs, studyDisplayList, displaySets) {
|
|
||||||
const primaryStudies = [];
|
|
||||||
const recentStudies = [];
|
|
||||||
const allStudies = [];
|
|
||||||
|
|
||||||
studyDisplayList.forEach(study => {
|
|
||||||
const displaySetsForStudy = displaySets.filter(
|
|
||||||
ds => ds.StudyInstanceUID === study.studyInstanceUid
|
|
||||||
);
|
|
||||||
const tabStudy = Object.assign({}, study, {
|
|
||||||
displaySets: displaySetsForStudy,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (primaryStudyInstanceUIDs.includes(study.studyInstanceUid)) {
|
|
||||||
primaryStudies.push(tabStudy);
|
|
||||||
} else {
|
|
||||||
// TODO: Filter allStudies to dates within one year of current date
|
|
||||||
recentStudies.push(tabStudy);
|
|
||||||
allStudies.push(tabStudy);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const tabs = [
|
|
||||||
{
|
|
||||||
name: 'primary',
|
|
||||||
label: 'Primary',
|
|
||||||
studies: primaryStudies,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'recent',
|
|
||||||
label: 'Recent',
|
|
||||||
studies: recentStudies,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'all',
|
|
||||||
label: 'All',
|
|
||||||
studies: allStudies,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
return tabs;
|
|
||||||
}
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import { utils } from '@ohif/core';
|
|||||||
import { StudyBrowser, useImageViewer, useViewportGrid, Dialog, ButtonEnums } from '@ohif/ui';
|
import { StudyBrowser, useImageViewer, useViewportGrid, Dialog, ButtonEnums } from '@ohif/ui';
|
||||||
import { useTrackedMeasurements } from '../../getContextModule';
|
import { useTrackedMeasurements } from '../../getContextModule';
|
||||||
|
|
||||||
const { formatDate } = utils;
|
const { formatDate, createStudyBrowserTabs } = utils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -272,11 +272,10 @@ function PanelStudyBrowserTracking({
|
|||||||
};
|
};
|
||||||
}, [thumbnailImageSrcMap, trackedSeries, viewports, dataSource, displaySetService]);
|
}, [thumbnailImageSrcMap, trackedSeries, viewports, dataSource, displaySetService]);
|
||||||
|
|
||||||
const tabs = _createStudyBrowserTabs(
|
const tabs = createStudyBrowserTabs(
|
||||||
StudyInstanceUIDs,
|
StudyInstanceUIDs,
|
||||||
studyDisplayList,
|
studyDisplayList,
|
||||||
displaySets,
|
displaySets,
|
||||||
hangingProtocolService
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// TODO: Should not fire this on "close"
|
// TODO: Should not fire this on "close"
|
||||||
@ -590,97 +589,6 @@ function _getComponentType(ds) {
|
|||||||
return 'thumbnailTracked';
|
return 'thumbnailTracked';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {string[]} primaryStudyInstanceUIDs
|
|
||||||
* @param {object[]} studyDisplayList
|
|
||||||
* @param {string} studyDisplayList.studyInstanceUid
|
|
||||||
* @param {string} studyDisplayList.date
|
|
||||||
* @param {string} studyDisplayList.description
|
|
||||||
* @param {string} studyDisplayList.modalities
|
|
||||||
* @param {number} studyDisplayList.numInstances
|
|
||||||
* @param {object[]} displaySets
|
|
||||||
* @returns tabs - The prop object expected by the StudyBrowser component
|
|
||||||
*/
|
|
||||||
function _createStudyBrowserTabs(
|
|
||||||
primaryStudyInstanceUIDs,
|
|
||||||
studyDisplayList,
|
|
||||||
displaySets,
|
|
||||||
hangingProtocolService
|
|
||||||
) {
|
|
||||||
const primaryStudies = [];
|
|
||||||
const recentStudies = [];
|
|
||||||
const allStudies = [];
|
|
||||||
|
|
||||||
// Iterate over each study...
|
|
||||||
studyDisplayList.forEach(study => {
|
|
||||||
// Find it's display sets
|
|
||||||
const displaySetsForStudy = displaySets.filter(
|
|
||||||
ds => ds.StudyInstanceUID === study.studyInstanceUid
|
|
||||||
);
|
|
||||||
|
|
||||||
// Sort them
|
|
||||||
const dsSortFn = hangingProtocolService.getDisplaySetSortFunction();
|
|
||||||
displaySetsForStudy.sort(dsSortFn);
|
|
||||||
|
|
||||||
/* Sort by series number, then by series date
|
|
||||||
displaySetsForStudy.sort((a, b) => {
|
|
||||||
if (a.seriesNumber !== b.seriesNumber) {
|
|
||||||
return a.seriesNumber - b.seriesNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
const seriesDateA = Date.parse(a.seriesDate);
|
|
||||||
const seriesDateB = Date.parse(b.seriesDate);
|
|
||||||
|
|
||||||
return seriesDateA - seriesDateB;
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Map the study to it's tab/view representation
|
|
||||||
const tabStudy = Object.assign({}, study, {
|
|
||||||
displaySets: displaySetsForStudy,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Add the "tab study" to the 'primary', 'recent', and/or 'all' tab group(s)
|
|
||||||
if (primaryStudyInstanceUIDs.includes(study.studyInstanceUid)) {
|
|
||||||
primaryStudies.push(tabStudy);
|
|
||||||
allStudies.push(tabStudy);
|
|
||||||
} else {
|
|
||||||
// TODO: Filter allStudies to dates within one year of current date
|
|
||||||
recentStudies.push(tabStudy);
|
|
||||||
allStudies.push(tabStudy);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Newest first
|
|
||||||
const _byDate = (a, b) => {
|
|
||||||
const dateA = Date.parse(a);
|
|
||||||
const dateB = Date.parse(b);
|
|
||||||
|
|
||||||
return dateB - dateA;
|
|
||||||
};
|
|
||||||
|
|
||||||
const tabs = [
|
|
||||||
{
|
|
||||||
name: 'primary',
|
|
||||||
label: 'Primary',
|
|
||||||
studies: primaryStudies.sort((studyA, studyB) => _byDate(studyA.date, studyB.date)),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'recent',
|
|
||||||
label: 'Recent',
|
|
||||||
studies: recentStudies.sort((studyA, studyB) => _byDate(studyA.date, studyB.date)),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'all',
|
|
||||||
label: 'All',
|
|
||||||
studies: allStudies.sort((studyA, studyB) => _byDate(studyA.date, studyB.date)),
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
return tabs;
|
|
||||||
}
|
|
||||||
|
|
||||||
function _findTabAndStudyOfDisplaySet(displaySetInstanceUID, tabs) {
|
function _findTabAndStudyOfDisplaySet(displaySetInstanceUID, tabs) {
|
||||||
for (let t = 0; t < tabs.length; t++) {
|
for (let t = 0; t < tabs.length; t++) {
|
||||||
const { studies } = tabs[t];
|
const { studies } = tabs[t];
|
||||||
|
|||||||
77
platform/core/src/utils/createStudyBrowserTabs.ts
Normal file
77
platform/core/src/utils/createStudyBrowserTabs.ts
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string[]} primaryStudyInstanceUIDs
|
||||||
|
* @param {object[]} studyDisplayList
|
||||||
|
* @param {string} studyDisplayList.studyInstanceUid
|
||||||
|
* @param {string} studyDisplayList.date
|
||||||
|
* @param {string} studyDisplayList.description
|
||||||
|
* @param {string} studyDisplayList.modalities
|
||||||
|
* @param {number} studyDisplayList.numInstances
|
||||||
|
* @param {object[]} displaySets
|
||||||
|
* @param {number} recentTimeframe - The number of milliseconds to consider a study recent
|
||||||
|
* @returns tabs - The prop object expected by the StudyBrowser component
|
||||||
|
*/
|
||||||
|
|
||||||
|
export function createStudyBrowserTabs(primaryStudyInstanceUIDs, studyDisplayList, displaySets, recentTimeframeMS = 31536000000) {
|
||||||
|
const primaryStudies = [];
|
||||||
|
const allStudies = [];
|
||||||
|
|
||||||
|
studyDisplayList.forEach(study => {
|
||||||
|
const displaySetsForStudy = displaySets.filter(
|
||||||
|
ds => ds.StudyInstanceUID === study.studyInstanceUid
|
||||||
|
);
|
||||||
|
const tabStudy = Object.assign({}, study, {
|
||||||
|
displaySets: displaySetsForStudy,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (primaryStudyInstanceUIDs.includes(study.studyInstanceUid)) {
|
||||||
|
primaryStudies.push(tabStudy);
|
||||||
|
}
|
||||||
|
allStudies.push(tabStudy);
|
||||||
|
});
|
||||||
|
|
||||||
|
const primaryStudiesTimestamps = primaryStudies
|
||||||
|
.filter(study => study.date)
|
||||||
|
.map(study => new Date(study.date).getTime());
|
||||||
|
|
||||||
|
const recentStudies =
|
||||||
|
primaryStudiesTimestamps.length > 0
|
||||||
|
? allStudies.filter(study => {
|
||||||
|
const oldestPrimaryTimeStamp = Math.min(...primaryStudiesTimestamps);
|
||||||
|
|
||||||
|
if (!study.date) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const studyTimeStamp = new Date(study.date).getTime();
|
||||||
|
console.log(oldestPrimaryTimeStamp, studyTimeStamp, recentTimeframeMS)
|
||||||
|
return oldestPrimaryTimeStamp - studyTimeStamp < recentTimeframeMS;
|
||||||
|
})
|
||||||
|
: [];
|
||||||
|
|
||||||
|
// Newest first
|
||||||
|
const _byDate = (a, b) => {
|
||||||
|
const dateA = Date.parse(a);
|
||||||
|
const dateB = Date.parse(b);
|
||||||
|
|
||||||
|
return dateB - dateA;
|
||||||
|
};
|
||||||
|
const tabs = [
|
||||||
|
{
|
||||||
|
name: 'primary',
|
||||||
|
label: 'Primary',
|
||||||
|
studies: primaryStudies.sort((studyA, studyB) => _byDate(studyA.date, studyB.date)),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'recent',
|
||||||
|
label: 'Recent',
|
||||||
|
studies: recentStudies.sort((studyA, studyB) => _byDate(studyA.date, studyB.date)),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'all',
|
||||||
|
label: 'All',
|
||||||
|
studies: allStudies.sort((studyA, studyB) => _byDate(studyA.date, studyB.date)),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return tabs;
|
||||||
|
}
|
||||||
@ -37,6 +37,7 @@ import {
|
|||||||
} from './sortStudy';
|
} from './sortStudy';
|
||||||
import { subscribeToNextViewportGridChange } from './subscribeToNextViewportGridChange';
|
import { subscribeToNextViewportGridChange } from './subscribeToNextViewportGridChange';
|
||||||
import { splitComma, getSplitParam } from './splitComma';
|
import { splitComma, getSplitParam } from './splitComma';
|
||||||
|
import { createStudyBrowserTabs } from './createStudyBrowserTabs';
|
||||||
|
|
||||||
// Commented out unused functionality.
|
// Commented out unused functionality.
|
||||||
// Need to implement new mechanism for derived displaySets using the displaySetManager.
|
// Need to implement new mechanism for derived displaySets using the displaySetManager.
|
||||||
@ -80,6 +81,7 @@ const utils = {
|
|||||||
splitComma,
|
splitComma,
|
||||||
getSplitParam,
|
getSplitParam,
|
||||||
generateAcceptHeader,
|
generateAcceptHeader,
|
||||||
|
createStudyBrowserTabs,
|
||||||
};
|
};
|
||||||
|
|
||||||
export {
|
export {
|
||||||
@ -112,6 +114,7 @@ export {
|
|||||||
splitComma,
|
splitComma,
|
||||||
getSplitParam,
|
getSplitParam,
|
||||||
generateAcceptHeader,
|
generateAcceptHeader,
|
||||||
|
createStudyBrowserTabs,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default utils;
|
export default utils;
|
||||||
|
|||||||
14
yarn.lock
14
yarn.lock
@ -7732,7 +7732,7 @@ class-variance-authority@^0.7.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
clsx "2.0.0"
|
clsx "2.0.0"
|
||||||
|
|
||||||
classnames@^2.2.5, classnames@^2.3.2:
|
classnames@^2.3.2:
|
||||||
version "2.5.1"
|
version "2.5.1"
|
||||||
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.5.1.tgz#ba774c614be0f016da105c858e7159eae8e7687b"
|
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.5.1.tgz#ba774c614be0f016da105c858e7159eae8e7687b"
|
||||||
integrity sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==
|
integrity sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==
|
||||||
@ -17893,13 +17893,13 @@ react-dom@^18.3.1:
|
|||||||
loose-envify "^1.1.0"
|
loose-envify "^1.1.0"
|
||||||
scheduler "^0.23.2"
|
scheduler "^0.23.2"
|
||||||
|
|
||||||
react-draggable@4.4.3:
|
react-draggable@^4.4.6:
|
||||||
version "4.4.3"
|
version "4.4.6"
|
||||||
resolved "https://registry.yarnpkg.com/react-draggable/-/react-draggable-4.4.3.tgz#0727f2cae5813e36b0e4962bf11b2f9ef2b406f3"
|
resolved "https://registry.yarnpkg.com/react-draggable/-/react-draggable-4.4.6.tgz#63343ee945770881ca1256a5b6fa5c9f5983fe1e"
|
||||||
integrity sha512-jV4TE59MBuWm7gb6Ns3Q1mxX8Azffb7oTtDtBgFkxRvhDp38YAARmRplrj0+XGkhOJB5XziArX+4HUUABtyZ0w==
|
integrity sha512-LtY5Xw1zTPqHkVmtM3X8MUOxNDOUhv/khTgBgrUvwaS064bwVvxT+q5El0uUFNx5IEPKXuRejr7UqLwBIg5pdw==
|
||||||
dependencies:
|
dependencies:
|
||||||
classnames "^2.2.5"
|
clsx "^1.1.1"
|
||||||
prop-types "^15.6.0"
|
prop-types "^15.8.1"
|
||||||
|
|
||||||
react-dropzone@^10.1.7:
|
react-dropzone@^10.1.7:
|
||||||
version "10.2.2"
|
version "10.2.2"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user