Created
September 13, 2015 23:16
-
-
Save jurStv/69a28a805438fabe592a to your computer and use it in GitHub Desktop.
The event handler detached in adressForm.js Do not pay attention to Validator instances, it's just for filtering table-items and checking valid.
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
import {Rx} from "@cycle/core"; | |
import {h} from '@cycle/dom'; | |
import filterInput from "./filter-input/index"; | |
import adressForm from "./adress-form/adress-form"; | |
import tableItem from "./table-item/index"; | |
import serialize from "./local-storage-sink"; | |
import deserialize from "./local-storage-source"; | |
import Validator from "./form-validator"; | |
import view from './view'; | |
var transformToValidator = (str) => (new Validator({ | |
name: RegExp(str), | |
lastname: RegExp(str), | |
email: RegExp(str) | |
})) ; | |
// constructing the state of table | |
function tableConstructor( {DOM, list$, validator$} ) { | |
var ti$ = Rx.Observable.combineLatest( list$, validator$, ( {list} , valid) => { | |
return list.filter( valid.sel.bind(valid) ).map( adress => tableItem( DOM, adress) ); | |
} ); | |
var vtree$ = ti$.map( (tis) => tis.map( (ti) => ti.DOM ) ); | |
var edit$ = ti$.flatMapLatest( (tis) => | |
tis.map( (ti) => ti.edit$ ) | |
.reduce( (acc, cur) => acc.merge( cur ), new Rx.Subject() ) | |
); | |
var delete$ = ti$.flatMapLatest( (tis) => | |
tis.map( (ti) => ti.delete$ ) | |
.reduce( (acc, cur) => acc.merge( cur ), new Rx.Subject() ) | |
); | |
return { | |
DOM: vtree$, | |
edit$, | |
delete$ | |
} | |
} | |
function model(startList$, delete$, submit$ ){ | |
return startList$.flatMap( ({list}) => { | |
let deleteFromList$ = delete$.map( (actAdr) => { | |
let index = list.findIndex( (adr) => adr._id === actAdr._id ); | |
(index !== -1) ? list.splice( index, 1 ) : void 0; | |
return {list}; | |
} ); | |
let pushToList$ = submit$.map( (actAdr) => { | |
list.push(actAdr); | |
return {list}; | |
} ); | |
return deleteFromList$.merge( pushToList$ ); | |
} ); | |
} | |
function adresses( {DOM, localStorageSink, localStorageSource } ) { | |
var filter = filterInput( DOM ); // returns {DOM, input$} | |
var validator$ = filter.input$.startWith("").map( transformToValidator ); //just crazy implementing of filter | |
var startList$ = deserialize( localStorageSource ); //this guy fires 4 times instead of 1 | |
var sinkList$ = deserialize( localStorageSink ); | |
var list$ = startList$.concat( sinkList$ ); | |
var table = tableConstructor( {DOM, list$, validator$} ); // returns {DOM: vtree$,edit$,delete$ } | |
var mainForm = adressForm( {DOM, edit$: table.edit$} ); // returns {DOM: vtree$, submit$} | |
var removeAfterEditing$ = table.edit$.sample( mainForm.submit$ ); | |
var delete$ = removeAfterEditing$.merge( table.delete$ ); | |
var storage$ = model(startList$, delete$, mainForm.submit$); | |
var vtree$ = view( filter.DOM, mainForm.DOM, table.DOM ); | |
return { | |
DOM: vtree$, | |
localStorageSink: serialize( storage$ ) | |
}; | |
} | |
export default adresses; |
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
import {Rx} from "@cycle/core"; | |
import {h} from '@cycle/dom'; | |
import Validator from "../form-validator"; | |
import cuid from "cuid"; | |
let formValidator = new Validator({ | |
name: /^\S+/, | |
lastname:/^\S+/, | |
email:/^\S+@\S+\.\S+/ | |
}); | |
function makeIcon(name = ""){ | |
return h("span.input-group-addon", [h(`span.glyphicon${name}`)]) | |
} | |
function makeInputGroup( {id, placeholder, value, error, icoName = ".glyphicon-user"} ){ | |
return h("div.input-group", [ | |
makeIcon(icoName), | |
h(`input${id}.form-control.input-sm${error}`, { | |
type: "text", | |
form: "form", | |
atributes: {placeholder}, | |
value | |
}) | |
]); | |
} | |
function makeForm( | |
{email="", firstname="", lastname=""} = {}, | |
{emailError = true, firstnameError=true, lastnameError=true} = {} | |
){ | |
return h("form#form", [ | |
h("feildset", [ | |
h("legend", "Add new contact"), | |
makeInputGroup( | |
{id: "#firstname", | |
placeholder: "First name", | |
error: firstnameError ? "" : ".error", | |
value: firstname} | |
), | |
makeInputGroup( | |
{id: "#lastname", | |
placeholder: "Last name", | |
error: lastnameError ? "" : ".error", | |
value: lastname} | |
), | |
makeInputGroup( | |
{id:"#email", | |
placeholder: "Email", | |
error: emailError ? "" : ".error", | |
icoName: ".glyphicon-envelope", | |
value: email} | |
), | |
h("button#btn.btn.btn-default.btn-sm", {type: "submit"}, [ | |
h("span.glyphicon.glyphicon-plus-sign"), | |
" Save" | |
]) | |
]) | |
]) | |
} | |
function intent(DOM) { | |
return DOM.get("#form", "submit").map( e => { | |
e.preventDefault(); | |
console.log("submitting"); //fires 4 times | |
return e.target.elements; | |
} ); | |
} | |
function model( submit$ ) { | |
var adres$ = submit$.map( | |
({email, firstname, lastname}) => ({email: email.value, | |
firstname: firstname.value, | |
lastname: lastname.value}) | |
); | |
var valid$ = adres$.filter( formValidator.valid.bind(formValidator) ) | |
.map( (adr) => { | |
adr._id = cuid(); | |
return adr; | |
} ); | |
var invalid$ = adres$.filter( formValidator.invalid.bind(formValidator) ); | |
return { valid$, invalid$ }; | |
} | |
function view( { valid$, invalid$ }, edit$ ) { | |
var vtreeSuccess$ = valid$.map( () => makeForm() ); | |
var vtreeFail$ = invalid$.map( ( invalidAdr ) => makeForm( invalidAdr, formValidator.checkFields(invalidAdr) ) ); | |
var vtreeEdit$ = edit$.map( (item) => makeForm( item )); | |
var vtree$ = vtreeSuccess$.startWith(makeForm()).merge(vtreeFail$, vtreeEdit$); | |
return vtree$; | |
} | |
function adressForm( {DOM, edit$} ) { | |
var action$ = intent(DOM); | |
var states = model(action$); | |
var vtree$ = view( states, edit$ ); | |
return { | |
DOM: vtree$, | |
submit$: states.valid$ | |
}; | |
} | |
export default adressForm; |
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
import {run} from "@cycle/core"; | |
import {makeDOMDriver} from '@cycle/dom'; | |
import adresses from "./components/adresses"; | |
import Drivers from "./drivers"; | |
const main = adresses; | |
run( main, { | |
DOM: makeDOMDriver("#app"), | |
localStorageSource: Drivers.makeLocalStorageSourceDriver("adress-book"), | |
localStorageSink: Drivers.makeLocalStorageSinkDriver("adress-book") | |
} ); |
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
import {Rx} from "@cycle/core"; | |
function makeLocalStorageSourceDriver(keyName) { | |
return () => Rx.Observable.just( localStorage.getItem(keyName) ); | |
} | |
function makeLocalStorageSinkDriver(keyName) { | |
var subject = new Rx.Subject(); | |
return function (keyValue$) { | |
keyValue$.subscribe( keyValue => { | |
localStorage.setItem( keyName, keyValue ); | |
subject.onNext(keyValue); | |
} ); | |
return subject; | |
}; | |
} | |
export default { makeLocalStorageSinkDriver, makeLocalStorageSourceDriver }; |
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
import {Rx} from "@cycle/core"; | |
import {h} from '@cycle/dom'; | |
function view( filter$, mainForm$, table$ ) { | |
return Rx.Observable.combineLatest( filter$, mainForm$, table$, | |
(filter, mainForm, table) => { | |
return h("div.content",[ | |
h("div.row", [ h("div.col-md-5", [h("h1", "Adress Book")]) ]), | |
h("div.row",[ | |
h("div.col-md-3", [ | |
filter, | |
mainForm | |
]), | |
h("div.col-md-9", [ | |
h("legend", "Contact List"), | |
h("table.table.table-striped.table-bordered.table-hover.table-condensed", | |
[h("tbody#tbody", [ | |
h("tr", [ | |
h("th", "First Name"), | |
h("th", "Last Name"), | |
h("th", "Email"), | |
h("th.text-center", "Edit"), | |
h("th.text-center", "Delete") | |
]) | |
].concat(table) | |
)]) | |
]) | |
]) | |
]); | |
} ); | |
} | |
export default view; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment