Skip to content

Instantly share code, notes, and snippets.

@AndresRodH
Last active October 28, 2020 13:06
Show Gist options
  • Save AndresRodH/0cc89e7e28f39692a4bb5f9395f0bac2 to your computer and use it in GitHub Desktop.
Save AndresRodH/0cc89e7e28f39692a4bb5f9395f0bac2 to your computer and use it in GitHub Desktop.
Generated by XState Viz: https://xstate.js.org/viz
// 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