Last active
May 21, 2017 17:09
-
-
Save johanalkstal/b225d7827e2a35bd6229ef519eb3591f to your computer and use it in GitHub Desktop.
Mithril stream experiment
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
// @flow | |
export const UPDATE_USER = 'UPDATE_USER' | |
export const updateUser = (payload: Object) => ({ | |
type: UPDATE_USER, | |
payload | |
}) |
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
// @flow | |
import m from 'mithril' | |
import { model, update } from './state' | |
import home from './views/home' | |
import layout from './views/layout' | |
import signIn from './views/signIn' | |
import { vmUpdateUser } from './view-models' | |
/** | |
* Application routes and their components. | |
*/ | |
export default { | |
'/': protectedRoute(home), | |
'/sign-in': route(signIn, vmUpdateUser()) | |
} | |
/** | |
* Creates a RouteResolver object that will render the given view. | |
* @param {Object} view - the view to render. | |
* @param {Function} viewModel - a function that returns a view model. | |
* @returns {Object} a RouteResolver. | |
*/ | |
function route (view: { view: Function }, viewModel?: Function) { | |
return { | |
render () { | |
return m(layout, m(view, { | |
vm: viewModel ? model.map(viewModel): null | |
})) | |
} | |
} | |
} | |
/** | |
* A route that is only accessible to authenticated users. | |
* Redirects to the sign in view when unauthenticated. | |
* @param {Object} view - the view to render. | |
* @param {Function} viewModel - a function that returns a view model. | |
* @returns {Object} a RouteResolver. | |
*/ | |
function protectedRoute (view: { view: Function }, viewModel?: Function) { | |
return Object.assign({}, route(view, viewModel), { | |
onmatch () { | |
return model().isAuthenticated ? view : m.route.set('/sign-in') | |
} | |
}) | |
} |
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
// @flow | |
import stream from 'mithril/stream' | |
import { UPDATE_USER } from './actions' | |
const { assign } = Object | |
const initialModel = { | |
isAuthenticated: false, | |
user: { | |
firstName: 'Johan', | |
lastName: 'Alkstål' | |
} | |
} | |
/** | |
* The application model stream. | |
*/ | |
export const model = stream(initialModel) | |
/** | |
* The update function that updates the model stream. | |
* @param action {Object} - An action object. | |
*/ | |
export const update = (action: Object) => { | |
switch (action.type) { | |
case UPDATE_USER: | |
model(assign({}, model(), { | |
user: assign({}, model().user, action.payload) | |
})) | |
return | |
default: | |
model(model()) | |
} | |
} |
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
// @flow | |
import m from 'mithril' | |
import styles from './user.css' | |
export default { | |
view: (viewnode: Object) => | |
m('div', [ | |
m('h1', { class: styles.title }, 'User'), | |
m('p', { class: styles.text }, viewnode.attrs.vm().userName), | |
m('input', { | |
type: 'text', | |
placeholder: 'First name', | |
value: viewnode.attrs.vm().user.firstName, | |
oninput: (event) => { | |
viewnode.attrs.vm().actions.updateFirstName(event.target.value) | |
} | |
}), | |
m('input', { | |
type: 'text', | |
placeholder: 'Last name', | |
value: viewnode.attrs.vm().user.lastName, | |
oninput: (event) => { | |
viewnode.attrs.vm().actions.updateLastName(event.target.value) | |
} | |
}) | |
]) | |
} |
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
// @flow | |
import { update } from '../state' | |
import { updateUser } from '../actions' | |
// Actions. | |
const updateFirstName = (firstName: string) => update(updateUser({ firstName })) | |
const updateLastName = (lastName: string) => update(updateUser({ lastName })) | |
/** | |
* View model for user data. | |
* @param actions {Object} - Optional actions for the view model. | |
* returns {Function} A stream callback that expects the model as its parameter. | |
*/ | |
export const vmUser = (actions?: Object) => (model: Object) => ({ | |
user: model.user, | |
userName: `${model.user.firstName} ${model.user.lastName}`, | |
actions | |
}) | |
/** | |
* View model for updating user data. | |
* It has actions provided to the view model by default. | |
* returns {Function} A stream callback that expects the model as its parameter. | |
*/ | |
export const vmUpdateUser = () => vmUser({ | |
updateFirstName, | |
updateLastName | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment