Last active
September 27, 2019 05:11
-
-
Save enjoylife/307c0fc78310fb5af004568a0df8ca3b to your computer and use it in GitHub Desktop.
Generated by XState Viz: https://xstate.js.org/viz
This file contains 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
const resetableEditableContext = () => { | |
return { | |
pushing: { | |
updates: [], | |
error: null, | |
lastSuccess: null, | |
}, | |
pulling: { | |
error: null, | |
lastSuccess: null, | |
updates: [], | |
}, | |
}; | |
}; | |
const editableMachineError = key => { | |
return assign({ | |
[key]: (context, event) => { | |
// using an immutable pattern | |
return { | |
...context[key], | |
error: event.error, | |
}; | |
}, | |
}); | |
}; | |
const editableMachineSuccess = key => { | |
return assign({ | |
[key]: (context, event) => { | |
// using an immutable pattern | |
return { | |
...context[key], | |
lastSuccess: new Date().getTime(), | |
error: null, | |
updates: [], | |
}; | |
}, | |
}); | |
}; | |
// A editableMachine provides a state machine to manage a component which | |
// can take on a viewable or editable state. More importantly when | |
// edits do occur the process and constraints to make sure no changes are lost are provided by the state machine. | |
const editableMachine = Machine( | |
{ | |
id: 'editable', | |
strict: true, | |
initial: 'viewing', | |
context: { | |
canEdit: true, | |
...resetableEditableContext(), | |
}, | |
states: { | |
viewing: { | |
on: {EDIT: {target: 'editing', cond: 'canEdit'}}, | |
}, | |
unsaved_prompt: { | |
exit: ['resetContext'], | |
on: { | |
DONE: {target: 'viewing'}, | |
}, | |
}, | |
editing: { | |
type: 'parallel', | |
on: { | |
DONE: [ | |
{target: 'viewing', cond: 'isSaved' /*actions: 'flush', */}, | |
{target: 'unsaved_prompt', cond: 'waitingOnSave'}, | |
], | |
CHANGE: { | |
target: 'editing', | |
actions: assign({ | |
pushing: (context, event) => { | |
// using an immutable pattern | |
return { | |
...context.pushing, | |
updates: [...context.pushing.updates, event.change], | |
}; | |
}, | |
}), | |
}, | |
}, | |
states: { | |
pushing: { | |
initial: 'idle', | |
states: { | |
idle: { | |
on: { | |
PUSH: {target: 'sync'}, | |
}, | |
}, | |
sync: { | |
on: { | |
SUCCESS: {target: 'idle', actions: ['pushingSuccess']}, | |
FAILURE: {target: 'idle', actions: ['pushingError']}, | |
}, | |
}, | |
}, | |
}, | |
pulling: { | |
initial: 'idle', | |
states: { | |
idle: { | |
on: { | |
PULL: {target: 'sync'}, | |
}, | |
}, | |
sync: { | |
on: { | |
SUCCESS: {target: 'idle', actions: ['pullingSuccess']}, | |
FAILURE: {target: 'idle', actions: ['pullingError']}, | |
}, | |
}, | |
}, | |
}, | |
}, | |
// invoke: { | |
// id: 'syncMachine', | |
// src: syncMachine, | |
// // Deriving child context from parent context | |
// data: { | |
// duration: (context, event) => context.customDuration | |
// } | |
// } | |
}, | |
// TODO: state waiting for confirmation that FORCE_DONE is ok | |
}, | |
}, | |
{ | |
actions: { | |
resetContext: assign({ | |
...resetableEditableContext(), | |
}), | |
pushingError: editableMachineError('pushing'), | |
pullingError: editableMachineError('pulling'), | |
pushingSuccess: editableMachineSuccess('pushing'), | |
pullingSuccess: editableMachineSuccess('pulling'), | |
}, | |
guards: { | |
canEdit: (context, event) => context.canEdit, | |
isSaved: (context, event) => | |
context.pushing.updates.length === 0 && !context.error, | |
waitingOnSave: (context, event) => | |
context.pushing.updates.length !== 0 && | |
!context.pushing.error && | |
!context.pulling.error, | |
}, | |
} | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment