diff --git a/LesionTracker/client/components/viewerSection/viewerSection.js b/LesionTracker/client/components/viewerSection/viewerSection.js index 4ec727a0e..92685b1ca 100644 --- a/LesionTracker/client/components/viewerSection/viewerSection.js +++ b/LesionTracker/client/components/viewerSection/viewerSection.js @@ -8,7 +8,9 @@ Template.viewerSection.onCreated(() => { instance.isTimepointBrowser = () => !!OHIF.viewer.data.currentTimepointId; + OHIF.viewer.quickSwitchStudyBrowserTemplate = 'timepointBrowserQuickSwitch'; if (!instance.isTimepointBrowser()) { + OHIF.viewer.quickSwitchStudyBrowserTemplate = 'studyBrowserQuickSwitch'; instance.loading = new ReactiveVar(true); instance.studiesInformation = new ReactiveVar([]); const filter = { studyInstanceUid: OHIF.viewer.data.studyInstanceUids }; diff --git a/Packages/ohif-lesiontracker/client/components/timepointBrowser/index.js b/Packages/ohif-lesiontracker/client/components/timepointBrowser/index.js index c8c8f6526..2ef72e316 100644 --- a/Packages/ohif-lesiontracker/client/components/timepointBrowser/index.js +++ b/Packages/ohif-lesiontracker/client/components/timepointBrowser/index.js @@ -2,6 +2,8 @@ import './item.html'; import './item.js'; import './list.html'; import './list.styl'; +import './quickSwitch.html'; +import './quickSwitch.js'; import './sidebar.html'; import './sidebar.js'; import './studies.html'; diff --git a/Packages/ohif-lesiontracker/client/components/timepointBrowser/item.js b/Packages/ohif-lesiontracker/client/components/timepointBrowser/item.js index 0c7580b2d..5eaa78693 100644 --- a/Packages/ohif-lesiontracker/client/components/timepointBrowser/item.js +++ b/Packages/ohif-lesiontracker/client/components/timepointBrowser/item.js @@ -5,8 +5,6 @@ import { $ } from 'meteor/jquery'; import { _ } from 'meteor/underscore'; import { OHIF } from 'meteor/ohif:core'; -const studySearchPromises = new Map(); - Template.timepointBrowserItem.onCreated(() => { const instance = Template.instance(); const { timepoint, timepointApi } = instance.data; @@ -30,18 +28,7 @@ Template.timepointBrowserItem.onCreated(() => { }; const filter = { studyInstanceUid: timepoint.studyInstanceUids }; - instance.loadStudies = () => { - const promiseKey = JSON.stringify(filter); - if (studySearchPromises.has(promiseKey)) { - return studySearchPromises.get(promiseKey); - } else { - const promise = instance.performLoad(); - studySearchPromises.set(promiseKey, promise); - return promise; - } - }; - - instance.performLoad = () => OHIF.studies.searchStudies(filter).then(studiesData => { + instance.loadStudies = () => OHIF.studies.searchStudies(filter).then(studiesData => { timepoint.studiesData = studiesData; timepointApi.timepoints.update(timepoint._id, { $set: { studiesData } }); instance.loaded = true; diff --git a/Packages/ohif-lesiontracker/client/components/timepointBrowser/quickSwitch.html b/Packages/ohif-lesiontracker/client/components/timepointBrowser/quickSwitch.html new file mode 100644 index 000000000..5e7d638cc --- /dev/null +++ b/Packages/ohif-lesiontracker/client/components/timepointBrowser/quickSwitch.html @@ -0,0 +1,6 @@ + diff --git a/Packages/ohif-lesiontracker/client/components/timepointBrowser/quickSwitch.js b/Packages/ohif-lesiontracker/client/components/timepointBrowser/quickSwitch.js new file mode 100644 index 000000000..51ce41925 --- /dev/null +++ b/Packages/ohif-lesiontracker/client/components/timepointBrowser/quickSwitch.js @@ -0,0 +1,94 @@ +import { Meteor } from 'meteor/meteor'; +import { Template } from 'meteor/templating'; +import { ReactiveVar } from 'meteor/reactive-var'; +import { Tracker } from 'meteor/tracker'; +import { OHIF } from 'meteor/ohif:core'; + +Template.timepointBrowserQuickSwitch.onCreated(() => { + const instance = Template.instance(); + instance.showAdditional = new ReactiveVar(false); + instance.currentTimepoint = new ReactiveVar(); + + instance.updateCurrentTimepoint = studyInstanceUid => { + const currentTimepoint = OHIF.viewer.timepointApi.study(studyInstanceUid)[0]; + instance.currentTimepoint.set(currentTimepoint); + }; + + const { viewportIndex } = instance.data; + instance.autorun(() => { + OHIF.viewerbase.layoutManager.observer.depend(); + const viewportData = OHIF.viewerbase.layoutManager.viewportData[viewportIndex]; + instance.updateCurrentTimepoint(viewportData.studyInstanceUid); + }); + + instance.autorun(() => { + instance.data.currentStudy.dep.depend(); + instance.showAdditional.set(false); + }); +}); + +Template.timepointBrowserQuickSwitch.onRendered(() => { + const instance = Template.instance(); + + instance.autorun(() => { + const currentTimepoint = instance.currentTimepoint.get(); + const currentTimepointId = (currentTimepoint && currentTimepoint.timepointId) || ''; + const $allBrowserItems = instance.$('.timepoint-browser-item'); + const $browserItem = $allBrowserItems.filter(`[data-id=${currentTimepointId}]`); + if (!$browserItem.hasClass('active')) { + $browserItem.find('.timepoint-item').trigger('click'); + } + }); + + instance.autorun(() => { + const currentStudy = instance.data.currentStudy.get(); + const studyInstanceUid = (currentStudy && currentStudy.studyInstanceUid) || ''; + Tracker.afterFlush(() => { + const $studyBrowserItems = instance.$('.study-browser-item'); + $studyBrowserItems.removeClass('active'); + $studyBrowserItems.filter(`[data-uid="${studyInstanceUid}"]`).addClass('active'); + }); + }); +}); + +Template.timepointBrowserQuickSwitch.events({ + 'ohif.lesiontracker.timepoint.click'(event, instance) { + const $element = $(event.currentTarget); + + // Defer the active class toggling to wait for child template rendering + Meteor.defer(() => $element.toggleClass('active')); + }, + + 'ohif.studies.study.click'(event, instance, studyInformation) { + const { studyInstanceUid } = studyInformation; + const study = OHIF.viewer.Studies.findBy({ studyInstanceUid }); + instance.data.currentStudy.set(study); + const $studySwitch = $(event.currentTarget).closest('.study-switch'); + $studySwitch.siblings('.series-switch').trigger('rescale'); + instance.updateCurrentTimepoint(studyInformation.studyInstanceUid); + }, + + 'click .show-additional'(event, instance) { + instance.showAdditional.set(true); + }, +}); + +Template.timepointBrowserQuickSwitch.helpers({ + timepointBrowserData() { + const instance = Template.instance(); + const { timepointApi } = OHIF.viewer; + const currentTimepoint = instance.currentTimepoint.get(); + let timepoints; + if (instance.showAdditional.get()) { + timepoints = timepointApi.key(); + } else { + timepoints = [currentTimepoint]; + } + + return { + timepointApi, + timepoints, + timepointChildTemplate: 'timepointBrowserStudies' + }; + } +}); diff --git a/Packages/ohif-lesiontracker/client/components/timepointBrowser/sidebar.html b/Packages/ohif-lesiontracker/client/components/timepointBrowser/sidebar.html index 6f760af62..bb2762f50 100644 --- a/Packages/ohif-lesiontracker/client/components/timepointBrowser/sidebar.html +++ b/Packages/ohif-lesiontracker/client/components/timepointBrowser/sidebar.html @@ -5,7 +5,7 @@ {{>roundedButtonGroup viewTypeButtonGroupData}} - {{#scrollArea class='flex-grow' class='fit' scrollableClass='p-a-1' scrollStep=191}} + {{#scrollArea class='flex-grow fit' scrollableClass='p-a-1' scrollStep=191}} {{>timepointBrowserList (extend timepointBrowserData)}} {{/scrollArea}} diff --git a/Packages/ohif-studies/imports/client/components/browser/index.js b/Packages/ohif-studies/imports/client/components/browser/index.js index 1e199fc33..5474d5ef4 100644 --- a/Packages/ohif-studies/imports/client/components/browser/index.js +++ b/Packages/ohif-studies/imports/client/components/browser/index.js @@ -1,7 +1,9 @@ -import './list.html'; -import './list.styl'; import './item.html'; import './item.js'; +import './list.html'; +import './list.styl'; +import './quickSwitch.html'; +import './quickSwitch.js'; import './series.html'; import './series.js'; import './sidebar.html'; diff --git a/Packages/ohif-studies/imports/client/components/browser/quickSwitch.html b/Packages/ohif-studies/imports/client/components/browser/quickSwitch.html new file mode 100644 index 000000000..5491cae86 --- /dev/null +++ b/Packages/ohif-studies/imports/client/components/browser/quickSwitch.html @@ -0,0 +1,3 @@ + diff --git a/Packages/ohif-studies/imports/client/components/browser/quickSwitch.js b/Packages/ohif-studies/imports/client/components/browser/quickSwitch.js new file mode 100644 index 000000000..25cf327bb --- /dev/null +++ b/Packages/ohif-studies/imports/client/components/browser/quickSwitch.js @@ -0,0 +1,43 @@ +import { Template } from 'meteor/templating'; +import { ReactiveVar } from 'meteor/reactive-var'; +import { Tracker } from 'meteor/tracker'; +import { OHIF } from 'meteor/ohif:core'; + +Template.studyBrowserQuickSwitch.onCreated(() => { + const instance = Template.instance(); + instance.studiesInformation = new ReactiveVar(); + const filter = { studyInstanceUid: OHIF.viewer.data.studyInstanceUids }; + OHIF.studies.searchStudies(filter).then(studies => instance.studiesInformation.set(studies)); +}); + +Template.studyBrowserQuickSwitch.onRendered(() => { + const instance = Template.instance(); + instance.autorun(() => { + instance.studiesInformation.dep.depend(); + const currentStudy = instance.data.currentStudy.get(); + const studyInstanceUid = (currentStudy && currentStudy.studyInstanceUid) || ''; + Tracker.afterFlush(() => { + const $studyBrowserItems = instance.$('.study-browser-item'); + $studyBrowserItems.removeClass('active'); + $studyBrowserItems.filter(`[data-uid="${studyInstanceUid}"]`).addClass('active'); + }); + }); +}); + +Template.studyBrowserQuickSwitch.events({ + 'ohif.studies.study.click'(event, instance, studyInformation) { + const { studyInstanceUid } = studyInformation; + const study = OHIF.viewer.Studies.findBy({ studyInstanceUid }); + instance.data.currentStudy.set(study); + const $studySwitch = $(event.currentTarget).closest('.study-switch'); + $studySwitch.siblings('.series-switch').trigger('rescale'); + } +}); + +Template.studyBrowserQuickSwitch.helpers({ + studyBrowserData() { + const instance = Template.instance(); + const studiesInformation = instance.studiesInformation.get(); + return { studiesInformation }; + } +}); diff --git a/Packages/ohif-studies/imports/client/components/browser/sidebar.html b/Packages/ohif-studies/imports/client/components/browser/sidebar.html index 06d6d951f..505033faa 100644 --- a/Packages/ohif-studies/imports/client/components/browser/sidebar.html +++ b/Packages/ohif-studies/imports/client/components/browser/sidebar.html @@ -1,5 +1,5 @@ diff --git a/Packages/ohif-studies/imports/client/lib/searchStudies.js b/Packages/ohif-studies/imports/client/lib/searchStudies.js index 98639c890..5a7b5a5a0 100644 --- a/Packages/ohif-studies/imports/client/lib/searchStudies.js +++ b/Packages/ohif-studies/imports/client/lib/searchStudies.js @@ -1,18 +1,29 @@ import { Meteor } from 'meteor/meteor'; import { OHIF } from 'meteor/ohif:core'; +const studySearchPromises = new Map(); + /** * Search for studies information by the given filter * * @param {Object} filter Filter that will be used on search * @returns {Promise} resolved with an array of studies information or rejected with an error */ -OHIF.studies.searchStudies = filter => new Promise((resolve, reject) => { - Meteor.call('StudyListSearch', filter, (error, studiesData) => { - if (error) { - reject(error); - } else { - resolve(studiesData); - } - }); -}); +OHIF.studies.searchStudies = filter => { + const promiseKey = JSON.stringify(filter); + if (studySearchPromises.has(promiseKey)) { + return studySearchPromises.get(promiseKey); + } else { + const promise = new Promise((resolve, reject) => { + Meteor.call('StudyListSearch', filter, (error, studiesData) => { + if (error) { + reject(error); + } else { + resolve(studiesData); + } + }); + }); + studySearchPromises.set(promiseKey, promise); + return promise; + } +}; diff --git a/Packages/ohif-viewerbase/client/components/viewer/gridLayout/gridLayout.html b/Packages/ohif-viewerbase/client/components/viewer/gridLayout/gridLayout.html index e44715abc..e5f1a522e 100644 --- a/Packages/ohif-viewerbase/client/components/viewer/gridLayout/gridLayout.html +++ b/Packages/ohif-viewerbase/client/components/viewer/gridLayout/gridLayout.html @@ -5,7 +5,7 @@
{{>imageViewerViewport (clone viewport)}}
- {{>seriesQuickSwitch (clone this viewportIndex=@index)}} + {{>seriesQuickSwitch (clone this viewport=viewport viewportIndex=@index)}} {{/each}} diff --git a/Packages/ohif-viewerbase/client/components/viewer/seriesQuickSwitch/seriesQuickSwitch.html b/Packages/ohif-viewerbase/client/components/viewer/seriesQuickSwitch/seriesQuickSwitch.html index 264bc52f8..1406b8fcf 100644 --- a/Packages/ohif-viewerbase/client/components/viewer/seriesQuickSwitch/seriesQuickSwitch.html +++ b/Packages/ohif-viewerbase/client/components/viewer/seriesQuickSwitch/seriesQuickSwitch.html @@ -20,7 +20,7 @@
Study
{{#scrollArea class='study-browser'}} -
AAAAA
+ {{>Template.dynamic template=studyBrowserTemplate data=(clone this currentStudy=instance.currentStudy)}} {{/scrollArea}}
diff --git a/Packages/ohif-viewerbase/client/components/viewer/seriesQuickSwitch/seriesQuickSwitch.js b/Packages/ohif-viewerbase/client/components/viewer/seriesQuickSwitch/seriesQuickSwitch.js index b8444fa36..023b6172d 100644 --- a/Packages/ohif-viewerbase/client/components/viewer/seriesQuickSwitch/seriesQuickSwitch.js +++ b/Packages/ohif-viewerbase/client/components/viewer/seriesQuickSwitch/seriesQuickSwitch.js @@ -94,11 +94,15 @@ Template.seriesQuickSwitch.helpers({ } return seriesItems; + }, + + studyBrowserTemplate() { + return OHIF.viewer.quickSwitchStudyBrowserTemplate || 'studyBrowserQuickSwitch'; } }); Template.seriesQuickSwitch.events({ - 'mouseenter .series-switch'(event, instance) { + 'mouseenter .series-switch, rescale .series-switch'(event, instance) { // Control the width of the series browser const $switch = $(event.currentTarget); const browserWidth = $switch.offset().left + $switch.outerWidth(); diff --git a/Packages/ohif-viewerbase/client/components/viewer/seriesQuickSwitch/seriesQuickSwitch.styl b/Packages/ohif-viewerbase/client/components/viewer/seriesQuickSwitch/seriesQuickSwitch.styl index c3ebec0a0..35d56ebcf 100644 --- a/Packages/ohif-viewerbase/client/components/viewer/seriesQuickSwitch/seriesQuickSwitch.styl +++ b/Packages/ohif-viewerbase/client/components/viewer/seriesQuickSwitch/seriesQuickSwitch.styl @@ -66,13 +66,27 @@ float: left position: relative - .study-browser - background: purple + .study-switch:hover:after + content: '' + display: block + height: 100px left: 0 + position: absolute + top: 0 + width: 300px + + .study-browser + left: 0 + margin-top: 100px + max-height: calc(100vh - 100px) transform-origin(1em calc(1em + 17px)) - width: 285px + width: 300px + + .study-browser-list + padding: 0 10px .series-browser + max-height: 100vh max-width: 711px right: 0 transform-origin(calc(100% - 1em) calc(1em + 15px)) @@ -95,7 +109,6 @@ .series-browser, .study-browser - max-height: 100vh min-height: 120px opacity: 0 position: absolute @@ -164,6 +177,9 @@ transform(translateY(0)) transition-delay(0.3s) + .study-browser-item.active .study-item-box + theme('box-shadow', 'inset 0 0 0 3px $activeColor') + @media screen and (max-width: 1599px) .series-quick-switch