Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
bd5009e
Merge branch 'release/1.2.0' into develop
daveatsho May 17, 2018
0e76064
readme
daveatsho Aug 29, 2018
1a75763
comments
daveatsho Sep 6, 2018
cd73a4f
Merge branch 'feature/infinite-scroll-take-3' into develop
daveatsho Sep 6, 2018
f134568
steps for remembering the page num
daveatsho Sep 6, 2018
a72d25b
no method yet
daveatsho Sep 6, 2018
91454be
counter exists but is not incremented
daveatsho Sep 6, 2018
6d4d213
passing tests
daveatsho Sep 6, 2018
ecff2ca
dont allow null `last_page` at startup
daveatsho Sep 6, 2018
48f8601
edits
daveatsho Sep 6, 2018
d20f741
Merge branch 'feature/store-last-page-used-in-platform-refresh' into …
daveatsho Sep 6, 2018
18193ca
readme
daveatsho Sep 6, 2018
ca44a0d
comments and pagiantion tweaks
daveatsho Sep 11, 2018
a2bbb2b
misc test issues fixed
daveatsho Nov 16, 2018
dd3f9c4
increment last_page aftet fetch in mock api
daveatsho Nov 16, 2018
2b74c17
added last_page to mock platforms
daveatsho Nov 16, 2018
deb61b0
last_page tests
daveatsho Nov 16, 2018
5842a16
bumped implicit year to 2019
daveatsho Oct 8, 2019
f3772c7
updated souncloud embed test to expect https in url
daveatsho Oct 8, 2019
626917f
had to update attr-map in nts
daveatsho Oct 18, 2019
ae64db7
added empty tag
daveatsho Oct 18, 2019
018258f
fixed by updating stub html in feature
daveatsho Oct 18, 2019
e5acbf9
fixed mixcloud test by refeshing html snippet
daveatsho Oct 18, 2019
2a46c98
refreshed html
daveatsho Oct 18, 2019
40b045a
updated fixtures and tests
daveatsho Oct 18, 2019
d66b47b
expose date format in form
daveatsho Oct 18, 2019
30eb3e0
updated feature
daveatsho Feb 26, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 5 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,7 @@
# README
asbo:
an aggregator of a few London-based internet radio stations - using Nokogiri to scrape the html where needed, caching the resulting objects in a local db

This README would normally document whatever steps are necessary to get the
application up and running.
backend is in rails, front-end is in react/redux

Things you may want to cover:

* Ruby version

* System dependencies

* Configuration

* Database creation

* Database initialization

* How to run the test suite

* Services (job queues, cache servers, search engines, etc.)

* Deployment instructions

* ...
to start the backend api and the client, use the following command:
$ foreman start
1 change: 1 addition & 0 deletions app/controllers/platforms_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ def delete_episodes
begin
platform_from_nickname_param
@platform.episodes.delete_all
@platform.update(last_page: 0)
render json: {
:success => :true,
:platform => platform_with_episodes
Expand Down
11 changes: 7 additions & 4 deletions app/javascripts/__mocks__/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ const MockAPI = class {
}

getPlatform({nickname}){
// console.log(`mockAPI.fetch /platforms/${nickname}`)
const platform = platforms.find(p => p.nickname == nickname)
console.log(`mockAPI.fetch /platforms/${nickname}`)
let platform = platforms.find(p => p.nickname == nickname)

return new Promise((resolve,reject) => {
if(!!platform) {
setTimeout(resolve, 0, {
Expand All @@ -38,7 +39,7 @@ const MockAPI = class {
// in the real api, filter is passed to backend so repsonse contains a sub-set of total items..
// in the mock api, the filter is just post-processing in the callback
refreshPlatform({nickname,filter,page}){
console.log(`mockAPI.fetch /platforms/${nickname}/refresh ${JSON.stringify({filter,page})}`);
// console.log(`mockAPI.fetch /platforms/${nickname}/refresh ${JSON.stringify({filter,page})}`);
const platform = platforms.find(p => p.nickname == nickname)
return new Promise((resolve,reject) => {
if(!platform) {
Expand All @@ -51,7 +52,9 @@ const MockAPI = class {
//console.log(totalEps.map(ep => ep.name))
const matches = totalEps.filter(e => this.isMatchingEpisode(e, filter))
setTimeout(resolve, 0, {
...platform, episodes: matches
...platform,
last_page: (platform.last_page + 1),
episodes: matches
})
}
})
Expand Down
9 changes: 6 additions & 3 deletions app/javascripts/__mocks__/platforms.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ export default [{
"100x100",
"800x800"
]
}]
}],
"last_page" : 0
},
{
"id": 2,
Expand All @@ -51,7 +52,8 @@ export default [{
"nickname": "rinse",
"use_relative_images": false,
"default_image": "https://etc.levels.io/rinse-fm/logo.png",
"post_processing_rules": null
"post_processing_rules": null,
"last_page" : 3
}, {
"id": 3,
"name": "radar radio",
Expand All @@ -75,5 +77,6 @@ export default [{
"nickname": "radar",
"use_relative_images": true,
"default_image": null,
"post_processing_rules": null
"post_processing_rules": null,
"last_page" : 2
}]
4 changes: 3 additions & 1 deletion app/javascripts/components/PlatformDetails.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class PlatformDetails extends Component {
pagination,
refreshPlatform,
episodes,
last_page,
currentPage
} = this.props

Expand Down Expand Up @@ -53,7 +54,8 @@ class PlatformDetails extends Component {
<Link to={`/platforms/${nickname}/edit`}>Edit Platform</Link><br />
</p>
<p>
<b>Episodes</b>{' '}{this.refreshButton()}{' '}{this.deleteEpisodesButton()}
<b>Episodes</b>{' '}{this.refreshButton()}{' '}{this.deleteEpisodesButton()}<br />
<em>Last page fetched: {last_page} </em>
</p>
<p>
{this.episodeGrid()}
Expand Down
3 changes: 2 additions & 1 deletion app/javascripts/components/PlatformForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class PlatformForm extends Component {
render() {
const {initialValues, handleSubmit, pristine, reset, submitting, loading, isNew } = this.props
const {nickname} = initialValues || {}

console.log(initialValues)
return (
<div className={`form-container ${submitting || loading ? ' form-container--loading' : ''}`}>
<form onSubmit={handleSubmit}>
Expand All @@ -29,6 +29,7 @@ class PlatformForm extends Component {
parent='pagination'
attrs='param,url,itemsPerPage'
/>
<TextInput name='date_format' />
<p>
<button className='btn btn-primary' type="submit" disabled={pristine || submitting}>
Submit
Expand Down
18 changes: 15 additions & 3 deletions app/javascripts/redux/pagination.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {combineReducers} from 'redux'
import {createAction,createActions,handleActions} from 'redux-actions'
import {refreshPlatform} from './platforms'
import {refreshPlatform, LOAD_PLATFORM} from './platforms'
// constants
export const SET_PAGE = 'SET_PAGE';
// export const SET_PAGE_AND_REFRESH_PLATFORM = 'SET_PAGE_AND_REFRESH_PLATFORM'
Expand All @@ -25,8 +25,20 @@ export const setPage = createAction(SET_PAGE)


// reducers
export const currentPage = (currentPage = 1, action = {}) => {
return action.type == SET_PAGE ? action.payload.page : currentPage
export const currentPage = (currentPage=0, action = {}) => {
switch (action.type){

case `${LOAD_PLATFORM}_FULFILLED`:
const {platform} = action.payload
const last_page = platform.last_page
return last_page !== undefined ? last_page : currentPage // sync counter with db

case SET_PAGE:
return action.payload.page

default:
return currentPage
}
}

export const pages = (pages={}, action={}) => {
Expand Down
5 changes: 4 additions & 1 deletion app/javascripts/redux/platforms.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,12 +103,15 @@ export const refreshPlatform = function({nickname}) {
type: REFRESH_PLATFORM,
payload: API.refreshPlatform({nickname,filter,page})
.then (json => {
// handle with middleware or chaining?
console.log(`|platforms| on refresh, set last_page to ${json.last_page +1}`)
return {
platform: json
}
})
})
})
}

}

export const destroyPlatform = function({nickname}){
Expand Down
5 changes: 3 additions & 2 deletions app/javascripts/tests/episodes.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,17 +82,18 @@ describe('Episodes', () => {
describe('episodes#show', () => {
it('dispatches an action to get the episode entry', async () => {
const store = mockStore({})
const opts = {'id':'1960'}
const opts = {'id':1960}
await store.dispatch(e.loadEpisode(opts))
.then(() => {
expectActions(store, [
"LOAD_EPISODE_PENDING",
"FETCH_EMBED_PENDING",
"LOAD_EPISODE_FULFILLED"
]);

const state = resultingState(store, reducer)
expect(state.episode).toBeTruthy()
// expect(state.episode.id).toEqual(opts.id)
expect(state.episode.id).toEqual(opts.id)
})
})
})
Expand Down
4 changes: 2 additions & 2 deletions app/javascripts/tests/pagination.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import {
describe('Pagination', () => {

describe('currentPage', () => {
it('is set to 1 at init', () => {
expect(reducer().currentPage).toBe(1)
it('is set to 0 at init', () => {
expect(reducer().currentPage).toBe(0)
})
it('can be changed by setPage action', () => {
const store = mockStore()
Expand Down
52 changes: 40 additions & 12 deletions app/javascripts/tests/platforms.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,19 +68,20 @@ describe('Platforms', () => {
})
})

const refreshPlatform = ({nickname}) => {
const store = mockStore({})
return store.dispatch(p.refreshPlatform({nickname}))
.then(() => {
expectActions(store, [
`${p.REFRESH_PLATFORM}_PENDING`,
`${p.REFRESH_PLATFORM}_FULFILLED`,
])
const state = resultingState(store, combinedRootReducer)
return {state, store: mockStore(state)}
})
}

describe('platforms#refresh', () => {
const refreshPlatform = ({nickname}) => {
const store = mockStore({})
return store.dispatch(p.refreshPlatform({nickname}))
.then(() => {
expectActions(store, [
`${p.REFRESH_PLATFORM}_PENDING`,
`${p.REFRESH_PLATFORM}_FULFILLED`,
])
const state = resultingState(store, combinedRootReducer)
return {state, store: mockStore(state)}
})
}

const nickname = 'rinse'
const opts = {nickname}
Expand Down Expand Up @@ -159,6 +160,33 @@ describe('Platforms', () => {
})
})


describe('lastPage', () => {
it('is incremented when after api returns a page of episodes', (done) => {
const opts = {'nickname':'rinse'}

let lastPageBefore,
lastPageAfter,
refreshedState

// 1. get a platform
getPlatform(opts).then((state1) => {
lastPageBefore = state1.platforms.platform.last_page
})
.then(() => {
// 2. get a page of episodes
return refreshPlatform(opts).then((xhr) => {
refreshedState = xhr.state
})
}).then(() => {
// 3. compare last_page before and after
lastPageAfter = refreshedState.platforms.platform.last_page
expect(lastPageAfter).toBeGreaterThan(lastPageBefore)
return done()
})
})
})

describe('platforms#delete_episodes', () => {
// see episodes tests
})
Expand Down
13 changes: 13 additions & 0 deletions app/models/platform.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ def initialize(opts={})
end

after_find do
initialize_last_page
init_client
end

Expand Down Expand Up @@ -180,9 +181,21 @@ def refresh(opts={})
def ready(result)
puts "platform#ready"
if result[:success]
increment_last_page!
return create_episodes_from_html result[:body]
else
raise "#{result[:code]} error\n #{result[:message]} "
end
end

def initialize_last_page
if self.last_page.nil?
self.last_page = 0
end
end

def increment_last_page!
self.last_page += 1
save
end
end
5 changes: 5 additions & 0 deletions db/migrate/20180906153751_add_last_page_to_platform.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddLastPageToPlatform < ActiveRecord::Migration[5.1]
def change
add_column :platforms, :last_page, :integer
end
end
54 changes: 21 additions & 33 deletions db/platforms.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ def self.sample_attributes
has_details: true,
use_relative_images: false,
attr_map: {
"item" => ".nts-grid-item",
"name" => ".nts-grid-item__img img[alt]",
"image" => ".nts-grid-item__img img[src]",
"media" => ".nts-grid-item__img__play-btn[data-src]",
"details" => ".nts-grid-item__img__play-btn[data-permalink]",
"date_str" => ".nts-grid-item__subtitle__left"
"item" => ".nts-grid-v2-item",
"name" => ".nts-grid-picture__img[alt]",
"image" => ".nts-grid-picture__img[src]",
"media" => ".nts-grid-picture__overlay.mixcloud-btn[data-src]",
"date_str" => ".nts-grid-v2-item__header span:first-child",
"details" => ".nts-grid-picture__overlay.mixcloud-btn[data-permalink]"
},
pagination: {
"route" => "/page/:page",
Expand Down Expand Up @@ -69,33 +69,21 @@ def self.sample_attributes

def self.sample_html_entries
<<-END
<div class="nts-grid-item">
<div class="nts-grid-item__img"><img src="https://media.ntslive.co.uk/resize/800x800/24463c4a-6d6d-48d7-9026-62c9af3b996f_1456963200.jpeg" data-src="https://media.ntslive.co.uk/resize/800x800/24463c4a-6d6d-48d7-9026-62c9af3b996f_1456963200.jpeg" alt="Murlo 31.01.18 Radio Episode"
class="img preload-img">
<div class="nts-grid-item__img__overlay">
<div class="nts-grid-item__img__play-btn mixcloud-btn" data-src="https://www.mixcloud.com/NTSRadio/murlo-31st-february-2018/" data-permalink="/shows/murlo/episodes/murlo-31st-january-2018"><span class="nts-grid-item__img__play-btn__text"><span class="icon icon-play text-bold"></span></span>
</div>
</div>
</div>
<div class="nts-grid-item__img nts-grid-item__img--link nts-app" data-href="/shows/murlo/episodes/murlo-31st-january-2018"><img src="https://media.ntslive.co.uk/resize/800x800/24463c4a-6d6d-48d7-9026-62c9af3b996f_1456963200.jpeg" data-src="https://media.ntslive.co.uk/resize/800x800/24463c4a-6d6d-48d7-9026-62c9af3b996f_1456963200.jpeg" alt="Murlo 31.01.18 Radio Episode"
class="img preload-img"></div>
<a href="/shows/murlo/episodes/murlo-31st-january-2018" class="nts-app nts-link nts-link--nohover">
<div class="nts-grid-item__header text-bold nts-link nts-link--highlighted">
<div class="nts-grid-item__title">Murlo</div>
<div class="nts-grid-item__subtitle">
<p class="nts-grid-item__subtitle__left">31.01.18</p>
<p class="nts-grid-item__subtitle__right">LDN</p>
</div>
</div>
</a>
<div class="nts-grid-item__footer">
<div class="nts-grid-item__genres"> <a class="genre-tag nts-app nts-link nts-link--highlighted genre-search-click-event" data-tag-id="caribbean-dancehall" href="/explore/genre/caribbean-dancehall">Dancehall</a> <a class="genre-tag nts-app nts-link nts-link--highlighted genre-search-click-event"
data-tag-id="ukdance-ukgarage" href="/explore/genre/ukdance-ukgarage">Garage</a> <a class="genre-tag nts-app nts-link nts-link--highlighted genre-search-click-event" data-tag-id="ukdance-grime" href="/explore/genre/ukdance-grime">Grime</a> <a class="genre-tag nts-app nts-link nts-link--highlighted genre-search-click-event"
data-tag-id="caribbean-soca" href="/explore/genre/caribbean-soca">Soca</a> </div>
<div class="nts-grid-item__action-btns">
<button class="nts-btn mixcloud-btn" data-src="https://www.mixcloud.com/NTSRadio/murlo-31st-february-2018/" data-permalink="/shows/murlo/episodes/murlo-31st-january-2018"><span class="icon icon-play text-bold"></span></button> <a class="nts-app nts-btn" href="/shows/murlo/episodes/murlo-31st-january-2018">TRACKLIST</a></div>
</div>
</div>
<article class="nts-grid-v2-item ">
<div class="nts-grid-v2-item__content">
<div class="nts-grid-picture"><img class="nts-grid-picture__img" src="https://media.ntslive.co.uk/resize/400x400/24463c4a-6d6d-48d7-9026-62c9af3b996f_1456963200.jpeg" alt="Murlo 18.07.18 Radio Episode">
<div role="button" tabindex="0" class="nts-grid-picture__overlay mixcloud-btn" data-src="https://www.mixcloud.com/NTSRadio/murlo-18th-july-2018/" data-permalink="/shows/murlo/episodes/murlo-18th-july-2018" data-event-label=""><svg
class="nts-icon nts-icon--l nts-icon--overlay" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 600">
<title>Play</title>
</svg></div>
</div><a class="nts-grid-v2-item__header nts-app" href="/shows/murlo/episodes/murlo-18th-july-2018"><span>18.07.18</span><span>LDN</span>
<div class="nts-grid-v2-item__header__title">Murlo</div>
</a>
<div class="nts-grid-v2-item__footer"><a class="nts-tag nts-app" data-tag-id="newclub-reggaeton" href="/explore/genre/newclub-reggaeton">Reggaeton</a><a class="nts-tag nts-app" data-tag-id="caribbean-bashment"
href="/explore/genre/caribbean-bashment">Bashment</a><a class="nts-tag nts-app" data-tag-id="caribbean-dancehall" href="/explore/genre/caribbean-dancehall">Dancehall</a><a class="nts-tag nts-app" data-tag-id="ukdance-grime"
href="/explore/genre/ukdance-grime">Grime</a></div>
</div><a class="nts-grid-v2-item__extra nts-app nts-link" href="/shows/murlo/episodes/murlo-18th-july-2018">Tracklist</a>
</article>
_BREAK_
<div class="borderbottom left podcast-list-item" id="swamp81040218">
<div class="left w8-16">
Expand Down
Loading