Skip to content

Instantly share code, notes, and snippets.

@gleuch
Last active January 14, 2021 05:19
Show Gist options
  • Save gleuch/0bcd37541b85148bfde3f76480f311ae to your computer and use it in GitHub Desktop.
Save gleuch/0bcd37541b85148bfde3f76480f311ae to your computer and use it in GitHub Desktop.
Generated by XState Viz: https://xstate.js.org/viz
const generateSectionMachines = () => null
const mach = Machine(
{
id: 'page',
initial: 'loading',
context: { page: {} },
on: {
SET: { target: 'ready', actions: 'setData' },
},
states: {
loading: {},
ready: {
on: {
EDIT: { target: 'editing', cond: 'canEditPage' },
},
},
editing: {
entry: ['sendEditingStatus'],
exit: ['sendEditingStatus'],
initial: 'ready',
states: {
ready: {
initial: 'ready',
states: {
ready: {
on: {
// CANCEL: { target: '#page.ready', actions: 'cancel' },
EDIT: { target: '#page.editing.editing', cond: 'canEditPage' },
PREVIEW: { target: '#page.editing.previewing' },
PUBLISH: { target: 'publishing', cond: 'canPublishPage' },
// SECTION_ADD: { actions: 'addSection', cond: 'canAddSection' },
SECTION_COMMIT: { actions: 'commitSection' },
// SECTION_EDIT: { actions: 'editSection', cond: 'canEditSection' },
SECTION_REMOVE: { target: 'updating', actions: 'removeSection', cond: 'canRemoveSection' },
SECTION_REPOSITION: { target: 'updating', actions: 'repositionSection', cond: 'canRepositionSection' },
},
},
publishing: {
invoke: {
id: 'publish',
src: 'publish',
onDone: { target: '#page.ready', actions: 'clear' },
onError: { target: 'ready', actions: 'error' },
},
},
updating: {
invoke: {
id: 'update',
src: 'update',
onDone: { target: 'ready', actions: 'snapshot' },
onError: { target: 'ready', actions: 'error' },
},
},
}
},
editing: {
entry: ['snapshot'],
initial: 'editing',
states: {
editing: {
on: {
CANCEL: { target: '#page.editing', actions: 'cancel' },
CHANGE: { actions: 'change' },
SAVE: { target: 'updating', cond: 'canEditPage' },
},
},
updating: {
invoke: {
id: 'update',
src: 'update',
onDone: { target: '#page.editing', actions: 'snapshot' },
onError: { target: 'editing', actions: 'error' },
},
},
},
},
previewing: {
on: {
CANCEL: { target: 'ready' },
},
},
},
},
},
},
{
actions: {
cancel: assign({
page: ({ hist }) => hist,
hist: undefined,
}),
change: assign({
page: ({ page }, { data }) => merge(page, data || {}),
}),
clear: assign({
hist: undefined,
}),
// @TODO : LOG ERRORS
errors: () => true,
sendEditingStatus: ({ page }, evt, { state }) => {
const action = state.matches('editing') ? 'EDITABLE' : 'UNEDITABLE';
page.sections.forEach(({ ref }) => ref?.send(action));
},
setData: assign({
page: ({ page }, { data }) => ({ ...page, ...data, sections: generateSectionMachines(data?.sections) }),
}),
snapshot: assign({
hist: ({ page }) => page,
}),
// Section handling
// addSection: assign({
// page: ({ page }, { data }) => {
// const [section] = generateSectionMachines({ ...data, _new: true, id: Date.now() });
// section.ref?.send('EDIT');
// return { ...page, sections: [...(page.sections || []), section] };
// },
// }),
commitSection: assign({
page: ({ page }, { section }) => {
const sections = page.sections.map(pageSection => {
if (pageSection.id === section.id) {
return { ...pageSection, ...section };
}
return pageSection;
});
return { ...page, sections };
},
}),
// editSection: ({ page }, { id }) => {
// page.sections.forEach(section => section.ref?.send(section.id === id ? 'EDIT' : 'CANCEL'));
// },
removeSection: assign({
page: ({ page }, { id }) => {
const sections = page.sections.map(section => {
if (section.id === id) {
return { ...section, _delete: true };
}
return section;
});
return { ...page, sections };
},
}),
repositionSection: assign({
page: ({ page }, { id, direction, position }) => {
const sections = Array.from(page.sections);
const [removed] = sections.splice(position, 1);
sections.splice(position + direction, 0, removed);
return { ...page, sections };
},
}),
},
guards: {
// canAddSection: ({ page }, { data }) => {
// // @TODO - PREVENT IF MAX
// // @TODO - PREVENT IF PAGE NOT ADDABLE
// return true;
// },
// canEditSection: () => true,
canEditPage: () => true,
canPublishPage: () => true,
canRemoveSection: () => true,
canRepositionSection: () => true,
},
services: {
publish: async () => {
await new Promise(r => setTimeout(r, 2000));
return {};
},
update: async () => {
await new Promise(r => setTimeout(r, 2000));
return {};
},
},
},
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment