Beginning of TrackedMesurementContext
This commit is contained in:
parent
d510cc8ad2
commit
e748eb1974
@ -0,0 +1,70 @@
|
|||||||
|
import React, { useContext, useReducer } from 'react';
|
||||||
|
|
||||||
|
const TRACKED_MEASUREMENTS_INITIAL_STATE = {
|
||||||
|
/** StudyInstanceUID */
|
||||||
|
trackedStudy: '',
|
||||||
|
/** string[] of SeriesInstanceUID */
|
||||||
|
trackedSeries: [],
|
||||||
|
/** key, value => displaySetInstanceUID, string label */
|
||||||
|
viewportLabels: new Map(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const TrackedMeasurementsContext = React.createContext();
|
||||||
|
|
||||||
|
TrackedMeasurementsContext.displayName = 'TrackedMeasurementsContext';
|
||||||
|
|
||||||
|
const useTrackedMeasurements = () => useContext(TrackedMeasurementsContext);
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {*} param0
|
||||||
|
*/
|
||||||
|
function TrackedMeasurementsContextProvider({ children }) {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {object} state - previous state
|
||||||
|
* @param {object} action
|
||||||
|
* @param {string} action.type
|
||||||
|
* @param {object} action.payload
|
||||||
|
*/
|
||||||
|
const reducer = (state, action) => {
|
||||||
|
switch (action.type) {
|
||||||
|
case 'TRACK_SERIES':
|
||||||
|
const { StudyInstanceUID, SeriesInstanceUID } = action.payload;
|
||||||
|
return state;
|
||||||
|
case 'UNTRACK_SERIES':
|
||||||
|
return state;
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Computed:
|
||||||
|
// numTrackedSeries
|
||||||
|
|
||||||
|
// API
|
||||||
|
// -
|
||||||
|
// - TrackSeries(studyUid, seriesUid) (or... TrackViewport?)
|
||||||
|
// - Checks against tracked study + series
|
||||||
|
// - Initiates prompt if required
|
||||||
|
// - does nothing for SR modality? (how do we know SR viewport?????????)
|
||||||
|
// - UntrackSeries(seriesUid)
|
||||||
|
const [trackedMeasurements, dispatchTrackedMeasurements] = useReducer(
|
||||||
|
reducer,
|
||||||
|
TRACKED_MEASUREMENTS_INITIAL_STATE
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TrackedMeasurementsContext.Provider
|
||||||
|
value={[trackedMeasurements, dispatchTrackedMeasurements]}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</TrackedMeasurementsContext.Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
TrackedMeasurementsContext,
|
||||||
|
TrackedMeasurementsContextProvider,
|
||||||
|
useTrackedMeasurements,
|
||||||
|
};
|
||||||
@ -0,0 +1,116 @@
|
|||||||
|
import { Machine, interpret } from 'xstate';
|
||||||
|
|
||||||
|
// {
|
||||||
|
// "type": "TRACK_SERIES",
|
||||||
|
// "StudyInstanceUID": "study1",
|
||||||
|
// "SeriesInstanceUID": "series1"
|
||||||
|
// }
|
||||||
|
|
||||||
|
// TODO:
|
||||||
|
// userPrompts should invoke promises:
|
||||||
|
// https://egghead.io/lessons/xstate-invoking-a-promise-for-asynchronous-state-transitions-in-xstate
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
id: 'measurementTracking',
|
||||||
|
initial: 'notTracking',
|
||||||
|
context: {
|
||||||
|
prevTrackedStudy: '',
|
||||||
|
prevTrackedSeries: [],
|
||||||
|
trackedStudy: '',
|
||||||
|
trackedSeries: [],
|
||||||
|
},
|
||||||
|
states: {
|
||||||
|
notTracking: {
|
||||||
|
on: {
|
||||||
|
TRACK_SERIES: {
|
||||||
|
target: 'userPromptShouldTrack',
|
||||||
|
actions: 'trackSeries',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
userPromptShouldTrack: {
|
||||||
|
on: {
|
||||||
|
YES: 'tracking',
|
||||||
|
CANCEL: 'notTracking',
|
||||||
|
NEVER: 'neverTracking',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
neverTracking: {
|
||||||
|
type: 'final',
|
||||||
|
},
|
||||||
|
tracking: {
|
||||||
|
on: {
|
||||||
|
TRACK_SERIES: [
|
||||||
|
{ target: 'tracking', cond: 'hasNewSeriesForTrackedStudy', actions: 'trackSeries' },
|
||||||
|
{ target: 'userPromptTrackingConflict', cond: 'hasConflictingStudyInstanceUID', actions: ['setPrevTracked', 'clearTrackedSeries', 'trackSeries'] },
|
||||||
|
],
|
||||||
|
UNTRACK_SERIES: [
|
||||||
|
{ target: 'tracking', cond: '', actions: ''},
|
||||||
|
{ target: 'notTracking', cond: '', actions: '' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
userPromptShouldTrackNewStudy: {
|
||||||
|
on: {
|
||||||
|
CANCEL: {
|
||||||
|
target: 'tracking',
|
||||||
|
actions: 'restorePrevTracked',
|
||||||
|
},
|
||||||
|
YES: 'tracking',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
strict: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Actions:
|
||||||
|
// - entry
|
||||||
|
// - exit
|
||||||
|
// - transition (on)
|
||||||
|
|
||||||
|
// Activities:
|
||||||
|
// - can return a "clean-up" function to call on exit
|
||||||
|
|
||||||
|
// actions, guards, services, activities, delays
|
||||||
|
const options = {
|
||||||
|
actions: {
|
||||||
|
logStuff: (context, event) => { console.log(context, event ) },
|
||||||
|
setPrevTracked: assign(context => ({
|
||||||
|
prevTrackedStudy: context.trackedStudy,
|
||||||
|
prevTrackedSeries: context.trackedSeries.slice(),
|
||||||
|
})),
|
||||||
|
restorePrevTracked: assign(context => ({
|
||||||
|
trackedStudy: context.prevTrackedStudy,
|
||||||
|
trackedSeries: context.prevTrackedSeries.slice(),
|
||||||
|
})),
|
||||||
|
clearTrackedSeries: assign(() => ({
|
||||||
|
trackedStudy: '',
|
||||||
|
trackedSeries: [],
|
||||||
|
})),
|
||||||
|
trackSeries: assign((context, event) =>
|
||||||
|
{
|
||||||
|
console.log(context, event);
|
||||||
|
const prevTrackedSeries = context.trackedSeries.slice();
|
||||||
|
return {
|
||||||
|
trackedStudy: event.StudyInstanceUID || '',
|
||||||
|
trackedSeries: [...prevTrackedSeries, event.SeriesInstanceUID],
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
guards: {
|
||||||
|
hasConflictingStudyInstanceUID: (context, event) =>
|
||||||
|
context.StudyInstanceUID !== context.trackedStudy,
|
||||||
|
hasNewSeriesForTrackedStudy: (context, event) =>
|
||||||
|
event.StudyInstanceUID === context.trackedStudy &&
|
||||||
|
!context.trackedSeries.includes(event.SeriesInstanceUID),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const measurementTrackingMachine = Machine(config, options);
|
||||||
|
// .transition(state, eventArgument).value
|
||||||
|
const service = interpret(measurementTrackingMachine).start();
|
||||||
|
// .send(event): nextState
|
||||||
|
// .state (getter)
|
||||||
|
// .onTransition(state => { state.vale })
|
||||||
|
|
||||||
|
export default measurementTrackingMachine;
|
||||||
5
extensions/measurement-tracking/src/contexts/index.js
Normal file
5
extensions/measurement-tracking/src/contexts/index.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export {
|
||||||
|
TrackedMeasurementsContext,
|
||||||
|
TrackedMeasurementsContextProvider,
|
||||||
|
useTrackedMeasurements,
|
||||||
|
} from './TrackedMeasurementsContext';
|
||||||
Loading…
Reference in New Issue
Block a user