Untitled diff

Created Diff never expires
135 removals
142 lines
82 additions
91 lines
const {div, li, img, h, h2, p, a, makeDOMDriver} = CycleDOM;
const { run } = Cycle;
const { makeDOMDriver, h } = CycleDOM;
const { makeHTTPDriver } = CycleHTTPDriver;
const xs = xstream.default;


function intent(DOMSource) {
const getRandomItem = arr => arr[Math.floor(Math.random() * arr.length)];
// Create streams for the intents that will be observed
const refreshClickStream$ = DOMSource.select('.refresh').events('click');
const close1ClickStream$ = DOMSource.select('.close1').events('click');
const close2ClickStream$ = DOMSource.select('.close2').events('click');
const close3ClickStream$ = DOMSource.select('.close3').events('click');
// Return all the streams ready to be subscribed
return {refreshClickStream$, close1ClickStream$, close2ClickStream$, close3ClickStream$};
}


function createSuggestionStream(refreshClickStream, responseStream, closeClickStream) {
function intent(DOM, HTTP) {
return closeClickStream.startWith('startup click')
return {
.combineLatest(responseStream,
fetchBeers: HTTP.select('fetchBeers').flatten(),
function(click, listBeers) {
fetchBeer: HTTP.select('fetchBeer').flatten(),
return listBeers[Math.floor(Math.random()*listBeers.length)];
refresh: DOM.select('.refresh').events('click'),
}
refreshOne: DOM.select('.close').events('click')
)
.map(e => {
.merge(
e.preventDefault();
refreshClickStream.map(function(){
return e.target.dataset.beerNumber;
return null;
})
})
)
};
.startWith(null);
}

// Update UI elements every time somethign is streamed
function renderSuggestion(suggestedBeer, selector) {
var suggestionEl = document.querySelector(selector);
if (suggestedBeer != null) {
suggestionEl.style.visibility = 'visible';
var usernameEl = suggestionEl.querySelector('.username');
usernameEl.textContent = suggestedBeer.name;
var imgEl = suggestionEl.querySelector('img');
imgEl.src = suggestedBeer.image_url;
var descriptionEl = suggestionEl.querySelector('.description');
descriptionEl.textContent = suggestedBeer.description;
}
}
}


// Subscribe the observers to API results
function model(actions) {
function model(refreshClickStream$, close1ClickStream$, close2ClickStream$, close3ClickStream$) {
const allBeers$ = actions.fetchBeers
var requestStream = refreshClickStream$.startWith('startup click')
.map(res => res.body)
.map(function() {
.map(beers => [ getRandomItem(beers), getRandomItem(beers), getRandomItem(beers) ])
return 'https://api.punkapi.com/v2/beers';
.startWith([]);
});
const singleBeer$ = actions.fetchBeer

.map(res => [ getRandomItem(res.body), res.request.beerNumber ])
var responseStream = requestStream
.startWith([]);
.flatMap(function(requestUrl) {
return xs.combine(allBeers$, singleBeer$)
return Rx.Observable.fromPromise($.getJSON(requestUrl));
.map(([ allBeers, [ beer, beerNumber ] ]) => {
if (beer) allBeers[beerNumber - 1] = beer;
return allBeers;
});
});

var suggestion1Stream = createSuggestionStream(refreshClickStream$, responseStream, close1ClickStream$);
var suggestion2Stream = createSuggestionStream(refreshClickStream$, responseStream, close2ClickStream$);
var suggestion3Stream = createSuggestionStream(refreshClickStream$, responseStream, close3ClickStream$);

suggestion1Stream.subscribe(function(suggestedBeer) {
renderSuggestion(suggestedBeer, '.suggestion1');
});

suggestion2Stream.subscribe(function(suggestedBeer) {
renderSuggestion(suggestedBeer, '.suggestion2');
});

suggestion3Stream.subscribe(function(suggestedBeer) {
renderSuggestion(suggestedBeer, '.suggestion3');
});

return responseStream.merge(suggestion1Stream)
.merge(suggestion2Stream)
.merge(suggestion3Stream);
}
}


// Render the view
function view(state$) {
function view(state$) {
return state$.map(state =>
return state$.map(([beer1, beer2, beer3]) => h('div', [
div([
h('div.header', [
div('.info', [
h('h2', 'Brewdog\'s beer'),
p('Developed by Anderson Leite using RxJS and Cycle.js'),
h('a.refresh', { attrs: { href: '#' } } , 'refresh')
p('See the 3 part blog post')
]),
h('div.containerx', [
h('div.left.box', [
h('li.suggestion1', [
renderBeer(beer1, 1)
])
]),
]),
div('.header', [
h('div.middle.box', [
h2('Brewdog\'s beer'),
h('li.suggestion2', [
a('.refresh', {href: '#'}, 'refresh')
renderBeer(beer2, 2)
])
]),
]),
div('.containerx', [
h('div.right.box', [

h('li.suggestion3', [
div('.left .box', [
renderBeer(beer3, 3)
h('li.suggestion1', [
div('.beer', [
img()
]),
p('.username', 'loading...'),
p('.description', 'loading...'),
a('.close .close1', {href: '#'}, 'show me other')
])
]),

div('.middle .box', [
h('li.suggestion2', [
div('.beer', [
img()
]),
p('.username', 'loading...'),
p('.description', 'loading...'),
a('.close .close2', {href: '#'}, 'show me other')
])
]),

div('.right .box', [
h('li.suggestion3', [
div('.beer', [
img()
]),
p('.username', 'loading...'),
p('.description', 'loading...'),
a('.close .close3', {href: '#'}, 'show me other')
])
])
])

])
])
])
])
)
]));
}

function renderBeer(beer, beerNumber) {
return h('div', [
h('div.beer', [
h('img', { attrs: beer ? { src: beer.image_url } : null })
]),
h('p.username', beer ? beer.name : 'loading...'),
h('p.description', beer ? beer.description : 'loading...'),
h('a.close', { attrs: { 'data-beer-number': beerNumber, href: '#' } }, 'show me other')
]);
}
}


function main(sources) {
function main(sources) {
const {refreshClickStream$, close1ClickStream$, close2ClickStream$, close3ClickStream$} = intent(sources.DOM);
const actions = intent(sources.DOM, sources.HTTP);
const state$ = model(refreshClickStream$, close1ClickStream$, close2ClickStream$, close3ClickStream$);
const beersRequest$ = actions.refresh
const vtree$ = view(Rx.Observable.of(''));
.startWith()

.mapTo({ url: 'https://api.punkapi.com/v2/beers', category: 'fetchBeers' });
const beerRequest$ = actions.refreshOne
.map(beerNumber => ({ url: 'https://api.punkapi.com/v2/beers', category: 'fetchBeer', beerNumber }));
const request$ = xs.merge(beersRequest$, beerRequest$);
return {
return {
DOM: vtree$
DOM: view(model(actions)),
HTTP: request$
};
};
}
}


const drivers = {
run(main, {
DOM: makeDOMDriver('#app')
DOM: makeDOMDriver('#app'),
};
HTTP: makeHTTPDriver()

});
Cycle.run(main, drivers);