Skip to content

Instantly share code, notes, and snippets.

@mikaelkaron
Last active September 27, 2019 12:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mikaelkaron/ea0a2154d69e57c3ee4971a24146ff1e to your computer and use it in GitHub Desktop.
Save mikaelkaron/ea0a2154d69e57c3ee4971a24146ff1e 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 Step = {
none: 0,
profile: 1,
evaluation: 2,
references: 4
};
const Flag = {
none: 0,
tc: 1,
onboarding: 2
}
const config = {
id: "app",
initial: "boot",
entry: "params",
context: {},
states: {
boot: {
id: "boot",
initial: "pending",
states: {
pending: {
invoke: {
src: "boot",
onDone: { target: "success", actions: "login" },
onError: "failure"
},
after: { TIMEOUT: "failure" }
},
success: { type: "final" },
failure: { type: "final" }
},
onDone: [{ target: "auth", cond: "isAuth" }, { target: "anon" }]
},
anon: {
id: "anon",
initial: "check",
states: {
check: {
on: {
"": [{ target: "signup", cond: "goSignup" }, { target: "signin" }]
}
},
signup: {
entry: "signupEntry",
exit: "signupExit",
on: {
"done.invoke.signup": { target: "done", actions: "login" },
SIGNIN: "signin"
},
meta: { component: "page-signup" }
},
signin: {
entry: "signinEntry",
exit: "signinExit",
on: {
"done.invoke.signin": { target: "done", actions: "login" },
SIGNUP: "signup"
},
meta: { component: "page-signin" }
},
done: { type: "final" }
},
onDone: "#auth",
on: { "": { target: "boot", cond: "isAuth" } }
},
auth: {
id: "auth",
initial: "welcome",
states: {
welcome: {
entry: "welcomeEntry",
exit: "welcomExit",
initial: "incomplete",
states: {
incomplete: {
on: { "": { target: "done", cond: "welcomeCompleted" } }
},
done: { type: "final" }
},
onDone: "onboarding",
on: {
"done.invoke.welcome": {
target: ".done",
actions: ["account", "welcomeComplete"]
},
ACCOUNT: undefined
},
meta: { component: "page-welcome" }
},
onboarding: {
initial: "incomplete",
states: {
incomplete: {
on: { "": { target: "done", cond: "onboardingCompleted" } }
},
done: { type: "final" }
},
onDone: "application",
on: {
"done.invoke.onboarding": {
target: ".done",
actions: ["account", "onboardingComplete"]
},
ACCOUNT: undefined
},
meta: { component: "page-onboarding" }
},
application: {
initial: "pending",
states: {
pending: {
invoke: {
src: "application",
onDone: [
{ target: "create", cond: "noData" },
{ target: "success", actions: "applicationLoad" }
],
onError: "failure"
},
after: { TIMEOUT: "failure" }
},
create: {
invoke: {
src: "applicationCreate",
onDone: { target: "success", actions: "applicationLoad" },
onError: "failure"
},
after: { TIMEOUT: "failure" }
},
success: { type: "final" },
failure: { type: "final" }
},
onDone: "#hist"
},
account: {
initial: "incomplete",
states: {
incomplete: {
on: { "": { target: "completed", cond: "welcomeCompleted" } }
},
completed: { on: { NEXT: "done" } },
done: { type: "final" }
},
onDone: "#hist",
on: {
"done.invoke.account": {
target: ".done",
actions: ["account"]
}
},
meta: { component: "page-account" }
},
signout: {
initial: "pending",
states: {
pending: {
invoke: { src: "signout", onDone: "success", onError: "failure" },
after: { TIMEOUT: "failure" }
},
success: { type: "final" },
failure: {
on: {
"": "#hist"
}
}
},
onDone: { target: "#auth.done", actions: "logout" },
meta: { component: "page-signout" }
},
apply: {
initial: "home",
states: {
home: {
on: {
NEXT: 'evaluation'
},
meta: { component: "page-home" }
},
profile: {
entry: "profileEntry",
exit: "profileExit",
initial: "incomplete",
states: {
incomplete: {
on: { "": { target: "completed", cond: "profileCompleted" } }
},
completed: { on: { NEXT: "done" } },
done: { type: "final" }
},
onDone: "evaluation",
on: {
"done.invoke.profile": {
target: ".done",
actions: ["profileUpdate", "profileComplete"]
}
},
meta: { component: "page-profile" }
},
evaluation: {
entry: "evaluationEntry",
exit: "evaluationExit",
initial: "incomplete",
states: {
incomplete: {
on: {
"": { target: "completed", cond: "evaluationCompleted" }
}
},
completed: { on: { NEXT: "done" } },
done: { type: "final" }
},
onDone: "references",
on: {
PREV: "home",
"done.invoke.evaluation": {
target: ".done",
actions: ["evaluationUpdate", "evaluationComplete"]
}
},
meta: { component: "page-evaluation" }
},
references: {
entry: "referencesEntry",
exit: "referencesExit",
initial: "incomplete",
states: {
incomplete: {
on: {
"": { target: "completed", cond: "referencesCompleted" }
}
},
completed: { on: { NEXT: "done" } },
done: { type: "final" }
},
onDone: "report",
on: {
"": { target: "evaluation", cond: "evaluationPending" },
"done.invoke.references": {
target: ".done",
actions: ["referencesUpdate", "referencesComplete"]
},
PREV: "evaluation"
},
meta: { component: "page-references" }
},
report: {
on: {
"": { target: "references", cond: "referencesPending" },
PREV: "references"
},
meta: { component: "page-report" }
},
hist: { id: "hist", type: "history", history: "deep" }
}
},
done: { type: "final" }
},
onDone: "#anon",
on: {
"": {
target: "#boot",
cond: "isAnon"
},
ACCOUNT: ".account",
SIGNOUT: ".signout"
}
}
},
on: {
BOOT: "#app.boot",
HOME: {
target: "auth.apply.home",
internal: true,
cond: "isAuth"
},
PROFILE: {
target: "auth.apply.profile",
internal: true,
cond: "isAuth"
},
EVALUATION: {
target: "auth.apply.evaluation",
internal: true,
cond: "isAuth"
},
REFERENCES: {
target: "auth.apply.references",
internal: true,
cond: "isAuth"
},
REPORT: { target: "auth.apply.report", internal: true, cond: "isAuth" }
}
};
config.states.anon.states.signup.on["SUBMIT"] = {
actions: send({
type: "done.invoke.signup",
data: { account: {} }
})
};
config.states.anon.states.signin.on["SUBMIT"] = {
actions: send({
type: "done.invoke.signin",
data: { account: { flags: Flag.tc} }
})
};
config.states.auth.states.welcome.on["SUBMIT"] = {
actions: send({
type: "done.invoke.welcome",
data: { }
})
};
config.states.auth.states.onboarding.on["SUBMIT"] = {
actions: send({
type: "done.invoke.onboarding",
data: { flags: Flag.tc }
})
};
config.states.auth.states.apply.states.profile.on["SUBMIT"] = {
actions: send({
type: "done.invoke.profile",
data: { first: "mikael", last: "karon" }
})
};
config.states.auth.states.apply.states.evaluation.on["SUBMIT"] = {
actions: send({
type: "done.invoke.evaluation",
data: { skill1: 1, skill2: 2 }
})
};
config.states.auth.states.apply.states.references.on["SUBMIT"] = {
actions: send({
type: "done.invoke.references",
data: { ref1: { email: "e@mail" } }
})
};
const set = flag =>
assign({
account: ({ account }) => ({
...account,
flags: account.flags | flag
})
});
const has = flag => ({ account: { flags } = {} }) =>
!!(flags & flag);
const not = flag => ({ account: { flags } = {} }) =>
!(flags & flag);
const complete = step =>
assign({
application: ({ application = {} }) => ({
...application,
completed: application.completed | step
})
});
const completed = step => ({ application: { completed } = {} }) =>
!!(completed & step);
const pending = step => ({ application: { completed } = {} }) =>
!(completed & step);
const update = key =>
assign({
application: ({ application = {} }, { data }) => ({
...application,
[key]: data
})
});
const options = {
actions: {
login: assign((ctx, { data }) => ({ ...ctx, ...data })),
logout: assign({
account: undefined,
profile: undefined,
application: undefined
}),
account: assign({ account: (ctx, { data }) => ({ ...data }) }),
application: assign({ application: (ctx, { data }) => ({ ...data }) }),
applicationCreate: assign({ application: { completed: Step.none } }),
welcomeComplete: set(Flag.tc),
onboardingComplete: set(Flag.onboarding),
profileComplete: complete(Step.profile),
evaluationComplete: complete(Step.evaluation),
referencesComplete: complete(Step.references),
profileUpdate: update("profile"),
evaluationUpdate: update("evaluation"),
referencesUpdate: update("references")
},
guards: {
isAnon: ctx => !ctx.account,
isAuth: ctx => !!ctx.account,
noData: (_ctx, event) => !event.data,
goSignup: () => false,
welcomeCompleted: has(Flag.tc),
onboardingCompleted: has(Flag.onboarding),
profilePending: pending(Step.profile),
profileCompleted: completed(Step.profile),
evaluationPending: pending(Step.evaluation),
evaluationCompleted: completed(Step.evaluation),
referencesPending: pending(Step.references),
referencesCompleted: completed(Step.references)
},
services: {
account: Promise.resolve({ flags: 3 }),
application: Promise.resolve({ completed: Step.profile })
},
delays: {
TIMEOUT: 2000
}
};
const machine = Machine(config, options);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment