import { Template } from 'meteor/templating'; import { ReactiveVar } from 'meteor/reactive-var'; import { OHIF } from 'meteor/ohif:core'; Template.caseProgress.onCreated(() => { const instance = Template.instance(); instance.progressPercent = new ReactiveVar(); instance.progressText = new ReactiveVar(); instance.isLocked = new ReactiveVar(false); instance.isFollowUp = new ReactiveVar(false); }); Template.caseProgress.onRendered(() => { const instance = Template.instance(); const { timepointApi, measurementApi, timepointId } = instance.data; // Stop here if we have no current timepoint ID (and therefore no defined timepointAPI) if (!timepointApi) { instance.progressPercent.set(100); return; } // Get the current and prior timepoints const current = timepointApi.timepoints.findOne({ timepointId }); const priorFilter = { latestDate: { $lt: current.latestDate }, patientId: current.patientId }; const priorSorting = { sort: { latestDate: -1 } }; const prior = timepointApi.timepoints.findOne(priorFilter, priorSorting); // Stop here if timepoint is locked if (current && current.isLocked) { return instance.isLocked.set(true); } else { instance.isLocked.set(false); } // Stop here if no current or prior timepoint was found if (!current || !prior || !current.timepointId) { return instance.progressPercent.set(100); } // Retrieve the initial number of targets left to measure at this // follow-up. Note that this is done outside of the reactive function // below so that new lesions don't change the initial target count. const config = OHIF.measurements.MeasurementApi.getConfiguration(); const toolGroups = config.measurementTools; const toolIds = []; toolGroups.forEach(toolGroup => toolGroup.childTools.forEach(tool => { const option = 'options.caseProgress.include'; if (OHIF.utils.ObjectPath.get(tool, option)) { toolIds.push(tool.id); } })); const getTimepointFilter = timepointId => ({ timepointId, toolId: { $in: toolIds } }); const getNumMeasurementsAtTimepoint = timepointId => { OHIF.log.info('getNumMeasurementsAtTimepoint'); const filter = getTimepointFilter(timepointId); let count = 0; toolGroups.forEach(toolGroup => { count += measurementApi.fetch(toolGroup.id, filter).length; }); return count; }; const getNumRemainingBetweenTimepoints = (currentTimepointId, priorTimepointId) => { const currentFilter = getTimepointFilter(currentTimepointId); const priorFilter = getTimepointFilter(priorTimepointId); let totalRemaining = 0; toolGroups.forEach(toolGroup => { const toolGroupId = toolGroup.id; const numCurrent = measurementApi.fetch(toolGroupId, currentFilter).length; const numPrior = measurementApi.fetch(toolGroupId, priorFilter).length; const remaining = Math.max(numPrior - numCurrent, 0); totalRemaining += remaining; }); return totalRemaining; }; // If we're currently reviewing a Baseline timepoint, don't do any // progress measurement. if (current.timepointType === 'baseline') { instance.progressPercent.set(100); instance.isFollowUp.set(false); } else { instance.isFollowUp.set(true); // Setup a reactive function to update the progress whenever // a measurement is made instance.autorun(() => { measurementApi.changeObserver.depend(); // Obtain the number of Measurements for which the current Timepoint has // no Measurement data const totalMeasurements = getNumMeasurementsAtTimepoint(prior.timepointId); const numRemainingMeasurements = getNumRemainingBetweenTimepoints(current.timepointId, prior.timepointId); const numMeasurementsMade = totalMeasurements - numRemainingMeasurements; // Update the Case Progress text with the remaining measurement count instance.progressText.set(numRemainingMeasurements); // Calculate the Case Progress as a percentage in order to update the // radial progress bar const progressPercent = Math.min(100, Math.round(100 * numMeasurementsMade / totalMeasurements)); instance.progressPercent.set(progressPercent); }); } }); Template.caseProgress.helpers({ progressPercent() { return Template.instance().progressPercent.get(); }, progressText() { return Template.instance().progressText.get(); }, isLocked() { return Template.instance().isLocked.get(); }, progressComplete() { const instance = Template.instance(); if (!instance.data.timepointApi) { return true; } const progressPercent = instance.progressPercent.get(); return progressPercent === 100; } });