Skip to content

Instantly share code, notes, and snippets.

@el-chogo
Last active July 29, 2016 23:53
Show Gist options
  • Save el-chogo/d69b2354ef626b5e8292dfdb2fcd94ee to your computer and use it in GitHub Desktop.
Save el-chogo/d69b2354ef626b5e8292dfdb2fcd94ee to your computer and use it in GitHub Desktop.
import xs from 'xstream';
import R from 'ramda';
import {div,ul,h1,button,input,p,li} from '@cycle/dom';
import debounce from 'xstream/extra/debounce';
function showElementD(className, selectedElements, element) {
const included = selectedElements.includes(element.id);
return element === null ?
li('.list-element', 'No element received')
:
li('.list-element'
,[
div('.list-element-container'
,{attrs:
{
'data-id': element.id
,'data-selected': included
}
}
,[
div(`.list-element-details ${className}`
, [
h1('.element-title'
,element.name),
p('.element-description'
,'Lorem ipsum dolor asimet')
])
])
]);
}
function showListActions(listActions, selectedElements) {
return listActions
.map(action =>
li('.list-actions-element', [action.display(selectedElements)]));
}
function defaultShowList(showElementP
,selectedElements
,className
,collection
,listActions) {
const showElement = showElementP === null ? showElementP : showElementD;
const showElementC = R.curry(showElement);
return collection === null ?
div('.top-level-list-container', [
div('.list-container', 'No elements loaded...')
])
:
div('.top-level-list-container', [
div('.list-actions-container',
[div('.list-actions-title-container',
[h1('.list-actions-title', 'Actions')])
,ul('.list-actions', showListActions(listActions
,selectedElements))])
,div('.list-container', [
div('.list-filter-container', [
input('.list-filter', {attrs: {type: 'text'}})
])
,div('.list-elements-container', [
ul('.list-elements',
collection.map(
showElementC(className
,selectedElements)))])
])
]);
}
function intent(sources) {
const className$ = sources.props$
.map(({className}) => className);
const selected$ = sources.DOM
.select('.list-element-container')
.events('click')
.map(ev => parseInt(ev.currentTarget.getAttribute('data-id')));
const filter$ = sources.DOM
.select('.list-filter')
.events('input')
.map(ev => ev.target.value)
.compose(debounce(1000));
const action$ = sources.listActions$
.map(actions => {
return R.apply(xs.merge, actions.map(action => {
return sources.DOM
.select(action.selector)
.events('click')
.filter(ev => ev.currentTarget.disabled === false)
.mapTo(action.category);
}));
})
.flatten();
return {
selected$: selected$
,className$: className$
,filter$: filter$
,action$: action$
};
}
function model(actions, sources) {
const collection$ = sources.collection$;
const showElement$ = sources.props$
.map(({showElement}) => showElement);
const selected$ = actions.selected$
.startWith(null);
const selectedElements$ = actions.selected$
.fold((acc, id) => acc.includes(id) ?
R.without([id], acc) : R.concat(acc, [id]), []);
const className$ = actions.className$;
const filter$ = actions.filter$.startWith(null);
const listActions$ = sources.listActions$;
const action$ = actions.action$;
const viewState$ = xs.combine(collection$
,showElement$
,selected$
,className$
,filter$
,selectedElements$
,listActions$)
.map(([collection
,showElement
,selected
,className
,filter
,selectedElements
,listActions]) => {
return {
collection: collection
,selected: selected
,showElement: showElement
,selectedElements: selectedElements
,className: className
,filter: filter
,listActions: listActions
};
});
const exportedState$ = xs.of({
selectedElements$: selectedElements$
,filter$: filter$
,action$: action$
});
const state$ = xs.of({
viewState$: viewState$
,exportedState$: exportedState$
});
return state$;
}
function view(state$) {
const vdom$ = state$.map(
({collection
,showElement
,selectedElements
,className
,listActions}) => {
return defaultShowList(showElement
,selectedElements
,className
,collection
,listActions);
});
return vdom$;
}
function getExportedStream(metaStream, prop) {
return metaStream.map(streams => streams[prop]).flatten();
}
function ListComponent(sources) {
const actions = intent(sources);
const state$ = model(actions, sources);
const viewState$ = state$.map(({viewState$}) => viewState$).flatten();
const exportedState$ = state$.map(({exportedState$}) => exportedState$).flatten();
const vdom$ = view(viewState$);
const sinks = {
DOM: vdom$
,selectedElements$: getExportedStream(exportedState$, 'selectedElements$')
,filter$: getExportedStream(exportedState$, 'filter$')
,action$: getExportedStream(exportedState$, 'action$')
};
return sinks;
}
export default ListComponent;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment