Skip to content

Instantly share code, notes, and snippets.

@kevinfoerster
Last active April 10, 2020 21:47
Show Gist options
  • Save kevinfoerster/73647b65d7456901df12f1be0374013f to your computer and use it in GitHub Desktop.
Save kevinfoerster/73647b65d7456901df12f1be0374013f to your computer and use it in GitHub Desktop.
Generated by XState Viz: https://xstate.js.org/viz
const process = {
env: {
GATSBY_FUNCTION_ENDPOINT: 'https://trinity-agency-dev-preview.kevinfoerster.com/.netlify/functions/auth/'
}
}
const fetchToken = (username, password) => {
const url = process.env.GATSBY_FUNCTION_ENDPOINT;
return fetch(url, {
method: 'POST',
headers: {
'content-type': 'application/json',
},
body: JSON.stringify({
username,
password,
}),
}).then(response => response.json());
};
const fetchVimeoId = (id, token) => {
const url = `${process.env.GATSBY_FUNCTION_ENDPOINT}video`;
return fetch(url, {
method: 'POST',
headers: {
'content-type': 'application/json',
},
body: JSON.stringify({
id,
token,
}),
}).then(response => {
let json = response.json();
if (response.status >= 200 && response.status < 300) {
return json;
} else {
return json.then(Promise.reject.bind(Promise));
}
});
};
const checkVideo = id => {
const url = `${process.env.GATSBY_FUNCTION_ENDPOINT}has-video`;
console.log({url})
return fetch(url, {
method: 'POST',
headers: {
'content-type': 'application/json',
},
body: JSON.stringify({
id
}),
}).then(response => {
let json = response.json();
console.log({response})
if (response.status >= 200 && response.status < 300) {
return json;
} else {
return json.then(Promise.reject.bind(Promise));
}
});
};
// const isLoggedIn = false;
const hasVideo = false;
const guards = {
isLoggedIn: (context, event) => {
return !!context.token;
},
canSubmit: (context, event) => {
return !!context.username && !!context.password;
},
isAlreadyOpen: (context, event) => {
return context.showModal;
},
hasVideo: (context, event) => {
return context.hasVideo;
},
hasNoVideo: (context, event) => {
return !context.hasVideo;
},
};
const actionsList = {
updateCanSubmit: assign((context, event) => ({
canSubmit: !!context.username && !!context.password,
})),
updateHasVideo: assign((context, event) => ({
hasVideo: event.data.hasVideo,
})),
resetToken: assign((context, event) => {
hasWindow && sessionStorage.setItem('token', null);
return { token: null };
}),
updateVimeoId: assign((context, event) => {
return {
vimeoId: event.data.vimeoId,
};
}),
updateToken: assign((context, event) => {
hasWindow && sessionStorage.setItem('token', event.data.token);
return {
token: event.data.token,
};
}),
showModal: assign((context, event) => ({
showModal: true,
})),
hideModal: assign((context, event) => ({
showModal: false,
})),
setVideoId: assign((context, event) => {
return event.type
? {
id: event.id,
hasVideo: event.hasVideo,
}
: {
id: context.id,
hasVideo: context.hasVideo,
};
}),
setError: assign((context, event) => {
return {
hasError: true,
};
}),
updateUsername: assign((context, event) => ({
username: event.value,
hasError: false,
})),
updatePassword: assign((context, event) => ({
password: event.value,
hasError: false,
})),
};
const videoMachine = {
id: 'video',
initial: 'requesting',
states: {
requesting: {
invoke: {
id: 'requestVideo',
src: (context, event) => fetchVimeoId(context.id, context.token),
onDone: {
target: 'showVideoPlayer',
actions: 'updateVimeoId',
},
onError: {
target: '#login',
actions: 'resetToken',
},
},
},
showVideoPlayer: {},
},
};
const loginMachine = {
id: 'login',
initial: 'initial',
states: {
initial: {
entry: 'updateCanSubmit',
on: {
UPDATE_USER: {
target: 'initial',
actions: 'updateUsername',
},
UPDATE_PASSWORD: {
target: 'initial',
actions: 'updatePassword',
},
SUBMIT: {
target: 'submitting',
cond: 'canSubmit',
},
// REJECT: 'failure',
},
},
submitting: {
invoke: {
id: 'submitLogin',
src: (context, event) => fetchToken(context.username, context.password),
onDone: {
target: '#overlay.initial',
actions: 'updateToken',
},
onError: {
target: 'error',
actions: 'setError',
},
},
},
error: {
on: {
'': 'initial',
},
},
success: {
on: {
entry: 'initial',
},
},
},
};
const overlayMachine = {
// initial: 'initial',
id: 'overlay',
states: {
checkVideo: {
invoke: {
id: 'checkVideo',
src: (context, event) => checkVideo(context.id),
onDone: {
target: '#overlay.initial',
actions: 'updateHasVideo',
},
onError: {
target: 'error',
actions: 'setError',
},
},
},
error: {
// on: {
// '': 'initial',
// },
},
initial: {
entry: 'showModal',
on: {
'': [
{
target: 'requestVideoModal',
cond: 'hasNoVideo',
},
{
target: 'video',
cond: 'isLoggedIn',
},
{
target: 'login',
cond: 'hasVideo',
},
],
},
},
requestVideoModal: {
// type: 'final'
},
login: {
...loginMachine,
},
video: {
...videoMachine,
},
},
};
const stateMachine = Machine(
{
id: 'fetch',
initial: 'idle',
context: {
retries: 0,
username: '',
password: '',
token: '',
id: '6cc210e7-2c1f-3462-9ed9-29a6f30a4e6c',
vimeoId: null,
canSubmit: false,
hasError: false,
showModal: false,
hasVideo,
},
states: {
idle: {
on: {
'': {
target: '#overlay.checkVideo',
actions: { type: 'setVideoId', payload: { hasVideo: true } },
cond: 'isAlreadyOpen',
},
OPEN: { target: '#overlay.checkVideo', actions: 'setVideoId' },
},
},
overlayOpen: {
on: {
CLOSE: { target: '#fetch.idle', actions: 'hideModal' },
PREV: { target: '#overlay.checkVideo', actions: 'setVideoId' },
NEXT: { target: '#overlay.checkVideo', actions: 'setVideoId' },
},
...overlayMachine,
},
},
},
{
guards,
actions: actionsList,
}
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment