Last active
October 28, 2020 13:06
-
-
Save AndresRodH/0cc89e7e28f39692a4bb5f9395f0bac2 to your computer and use it in GitHub Desktop.
Generated by XState Viz: https://xstate.js.org/viz
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Available variables: | |
// - Machine | |
// - interpret | |
// - assign | |
// - send | |
// - sendParent | |
// - spawn | |
// - raise | |
// - actions | |
// - XState (all XState exports) | |
const TaskStatus = { | |
OPEN: 0, | |
IN_PROGRESS: 1, | |
CLOSED: 2 | |
} | |
const testSession = { | |
status: TaskStatus.OPEN, | |
// the real date "this" stated | |
actualStartDate: null, | |
// the real date "this" was closed | |
actualStopDate: null, | |
// in minutes | |
duration: null, | |
// date that this task/session could be done | |
estimatedDueDate: null, | |
// the actual time in minutes that took to complete this session/task | |
totalTimeToComplete: null, | |
} | |
function determineStateFromEnum(status) { | |
return status === TaskStatus.OPEN | |
? "open" | |
: status === TaskStatus.IN_PROGRESS | |
? "inProgress" | |
: "closed" | |
} | |
const createSessionUpdateMachine = (session) => Machine( | |
{ | |
id: 'sessionUpdates', | |
context: testSession, | |
type: 'parallel', | |
states: { | |
statusTransition: { | |
id: 'transitionableEntity', | |
initial: determineStateFromEnum(testSession.status), | |
context: { | |
// the real date "this" stated | |
actualStartDate: null, | |
// the real date "this" was closed | |
actualStopDate: null, | |
// in minutes | |
duration: null, | |
// date that this task/session could be done | |
estimatedDueDate: null, | |
// the actual time in minutes that took to complete this session/task | |
totalTimeToComplete: null, | |
}, | |
states: { | |
open: { | |
on: { | |
START: { | |
target: 'inProgress', | |
actions: ['setActualStartDate', 'calculateEstimatedDueDate'], | |
}, | |
CLOSE: { | |
target: 'closed', | |
actions: ['setActualStopDate'], | |
}, | |
UPDATE_DURATION: { | |
actions: ['setDuration'], | |
}, | |
}, | |
}, | |
inProgress: { | |
on: { | |
RESET: { | |
target: 'open', | |
actions: ['clearActualStartDate', 'clearEstimatedDueDate'], | |
}, | |
CLOSE: { | |
target: 'closed', | |
actions: ['setActualStopDate', 'calculateTotalTime'], | |
}, | |
UPDATE_DURATION: { | |
actions: ['setDuration', 'calculateEstimatedDueDate'], | |
}, | |
}, | |
}, | |
closed: { | |
on: { | |
RESET: { | |
target: 'open', | |
actions: [ | |
'clearActualStopDate', | |
'clearActualStartDate', | |
'clearTotalTimeToComplete', | |
'clearEstimatedDueDate', | |
], | |
}, | |
START: { | |
target: 'inProgress', | |
actions: [ | |
'setActualStartDate', | |
'clearActualStopDate', | |
'calculateEstimatedDueDate', | |
'clearTotalTimeToComplete', | |
], | |
}, | |
}, | |
}, | |
}, | |
}, | |
}, | |
}, | |
{ | |
guards: { | |
isOpen: (ctx, event) => | |
ctx.status === 'open' || ctx.status === TaskStatus.OPEN, | |
isInProgress: (ctx, event) => | |
ctx.status === 'in_progress' || ctx.status === TaskStatus.IN_PROGRESS, | |
isClosed: (ctx, event) => | |
ctx.status === 'closed' || ctx.status === TaskStatus.CLOSED, | |
}, | |
actions: { | |
initialize: assign({ | |
actualStartDate: (_ctx, event) => | |
event.type === 'INIT' && event.entity.actualStartDate, | |
actualStopDate: (_ctx, event) => | |
event.type === 'INIT' && event.entity.actualStopDate, | |
duration: (_ctx, event) => | |
event.type === 'INIT' && event.entity.duration, | |
estimatedDueDate: (_ctx, event) => | |
event.type === 'INIT' && event.entity.estimatedDueDate, | |
totalTimeToComplete: (_ctx, event) => | |
event.type === 'INIT' && event.entity.totalTimeToComplete, | |
}), | |
setActualStartDate: assign({ actualStartDate: () => new Date() }), | |
setActualStopDate: assign({ actualStopDate: () => new Date() }), | |
calculateEstimatedDueDate: assign({ | |
estimatedDueDate: (ctx) => | |
ctx.duration && ctx.actualStartDate | |
? new Date(ctx.actualStartDate.getTime() + ctx.duration * 60000) | |
: null, | |
}), | |
clearActualStartDate: assign({ actualStartDate: () => null }), | |
clearActualStopDate: assign({ actualStopDate: () => null }), | |
clearTotalTimeToComplete: assign({ totalTimeToComplete: () => null }), | |
clearEstimatedDueDate: assign({ estimatedDueDate: () => null }), | |
calculateTotalTime: assign({ | |
totalTimeToComplete: (ctx) => | |
// can only be calculated if there's both start and stop dates | |
// and sessions and tasks can be transitioned from open to closed directly | |
ctx.actualStartDate && ctx.actualStopDate | |
? Math.round( | |
(ctx.actualStopDate.getTime() - ctx.actualStartDate.getTime()) / | |
60000 | |
) | |
: null, | |
}), | |
setDuration: assign({ | |
duration: (ctx, event) => { | |
let duration = ctx.duration; | |
if (event.type === 'UPDATE_DURATION') duration = event.duration; | |
return duration; | |
}, | |
}), | |
setNewUsers: assign({ | |
newUsers: (ctx, event) => event.users || [] | |
}) | |
}, | |
} | |
); | |
const sessionUpdateMachine = createSessionUpdateMachine(testSession) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment