From fe2487dea56a51b9f2fffb1ad33d7714c6a05941 Mon Sep 17 00:00:00 2001 From: David Jay Date: Wed, 14 Dec 2016 15:02:26 -0500 Subject: [PATCH 01/24] Add streams option and sidebar. --- client/coral-admin/src/AppRouter.js | 2 + .../coral-admin/src/components/ui/Header.js | 2 + .../src/containers/Streams/Streams.css | 40 +++++++++++++++++++ .../src/containers/Streams/Streams.js | 40 +++++++++++++++++++ client/coral-admin/src/translations.json | 1 + 5 files changed, 85 insertions(+) create mode 100644 client/coral-admin/src/containers/Streams/Streams.css create mode 100644 client/coral-admin/src/containers/Streams/Streams.js diff --git a/client/coral-admin/src/AppRouter.js b/client/coral-admin/src/AppRouter.js index 6d55d7b18..bc9747f34 100644 --- a/client/coral-admin/src/AppRouter.js +++ b/client/coral-admin/src/AppRouter.js @@ -4,6 +4,7 @@ import {Router, Route, IndexRoute, browserHistory} from 'react-router'; import ModerationQueue from 'containers/ModerationQueue/ModerationQueue'; import CommentStream from 'containers/CommentStream/CommentStream'; import Configure from 'containers/Configure/Configure'; +import Streams from 'containers/Streams/Streams'; import CommunityContainer from 'containers/Community/CommunityContainer'; import LayoutContainer from 'containers/LayoutContainer'; @@ -13,6 +14,7 @@ const routes = ( + ); diff --git a/client/coral-admin/src/components/ui/Header.js b/client/coral-admin/src/components/ui/Header.js index e4d151d30..4c76424cc 100644 --- a/client/coral-admin/src/components/ui/Header.js +++ b/client/coral-admin/src/components/ui/Header.js @@ -16,6 +16,8 @@ export default ({handleLogout}) => ( activeClassName={styles.active}>{lang.t('configure.community')} {lang.t('configure.configure')} + {lang.t('configure.streams')}
    diff --git a/client/coral-admin/src/containers/Streams/Streams.css b/client/coral-admin/src/containers/Streams/Streams.css new file mode 100644 index 000000000..56d757863 --- /dev/null +++ b/client/coral-admin/src/containers/Streams/Streams.css @@ -0,0 +1,40 @@ +.container { + padding: 10px; + display: flex; +} + +.leftColumn { + width: 200px; +} + +.mainContent { + width: calc(70% - 300px) +} + +.searchIcon { + vertical-align: middle; + font-size: 18px; + color: #ccc; +} + +.searchBox { + padding: 3px; + border: 1px solid #ccc; + border-radius: 3px; + width: 90%; + display: flex; +} + +.searchBoxInput { + border: none; + flex: 1; + font-size: 14px; +} + +.searchBoxInput:focus { + outline: none; +} + +.hidden { + display: none; +} diff --git a/client/coral-admin/src/containers/Streams/Streams.js b/client/coral-admin/src/containers/Streams/Streams.js new file mode 100644 index 000000000..0e3e0d3f1 --- /dev/null +++ b/client/coral-admin/src/containers/Streams/Streams.js @@ -0,0 +1,40 @@ +import React from 'react'; +import styles from './Streams.css'; +import I18n from 'coral-framework/modules/i18n/i18n'; +import translations from '../../translations.json'; +import { + RadioGroup, + Radio, + Icon +} from 'react-mdl'; + +const Streams = () =>
    +
    +
    + + {}} + placeholder="Search"/> +
    +
    {lang.t('streams.filter-streams')}
    +
    {lang.t('streams.stream-status')}
    + + {lang.t('streams.all')} + {lang.t('streams.open')} + {lang.t('streams.closed')} + +
    {lang.t('streams.sort-by')}
    + + {lang.t('streams.newest')} + {lang.t('streams.oldest')} + +
    +
    +
    +
    ; + +export default Streams; + +const lang = new I18n(translations); diff --git a/client/coral-admin/src/translations.json b/client/coral-admin/src/translations.json index e462f7567..4d3525dd9 100644 --- a/client/coral-admin/src/translations.json +++ b/client/coral-admin/src/translations.json @@ -55,6 +55,7 @@ "moderate": "Moderate", "configure": "Configure", "community": "Community", + "streams": "Streams", "closed-comments-desc": "Write a message for closed threads", "closed-comments-label": "Write a message...", "comment-count-header": "Limit Comment Length", From dad46cc8defa45288d50041a0350d09b00be2562 Mon Sep 17 00:00:00 2001 From: David Jay Date: Wed, 14 Dec 2016 15:15:13 -0500 Subject: [PATCH 02/24] Add style and language to left nav. --- .../src/containers/Streams/Streams.css | 15 +++++++++++++ .../src/containers/Streams/Streams.js | 10 ++++----- client/coral-admin/src/translations.json | 22 +++++++++++++++++++ 3 files changed, 42 insertions(+), 5 deletions(-) diff --git a/client/coral-admin/src/containers/Streams/Streams.css b/client/coral-admin/src/containers/Streams/Streams.css index 56d757863..07724baa8 100644 --- a/client/coral-admin/src/containers/Streams/Streams.css +++ b/client/coral-admin/src/containers/Streams/Streams.css @@ -35,6 +35,21 @@ outline: none; } +.optionHeader { + font-size: 16px; + font-weight: 900; + margin-top: 15px; +} + +.optionDetail { + font-size: 16px; + margin-top: 3px; +} + +.radio { + display: block; +} + .hidden { display: none; } diff --git a/client/coral-admin/src/containers/Streams/Streams.js b/client/coral-admin/src/containers/Streams/Streams.js index 0e3e0d3f1..ee5d205ae 100644 --- a/client/coral-admin/src/containers/Streams/Streams.js +++ b/client/coral-admin/src/containers/Streams/Streams.js @@ -16,16 +16,16 @@ const Streams = () =>
    type='text' className={styles.searchBoxInput} onChange={() => {}} - placeholder="Search"/> + placeholder={lang.t('streams.search')}/>
    -
    {lang.t('streams.filter-streams')}
    -
    {lang.t('streams.stream-status')}
    - +
    {lang.t('streams.filter-streams')}
    +
    {lang.t('streams.stream-status')}
    + }> {lang.t('streams.all')} {lang.t('streams.open')} {lang.t('streams.closed')} -
    {lang.t('streams.sort-by')}
    +
    {lang.t('streams.sort-by')}
    {lang.t('streams.newest')} {lang.t('streams.oldest')} diff --git a/client/coral-admin/src/translations.json b/client/coral-admin/src/translations.json index 4d3525dd9..da859c49c 100644 --- a/client/coral-admin/src/translations.json +++ b/client/coral-admin/src/translations.json @@ -69,6 +69,17 @@ "note": "Note: Banning this user will also place this comment in the Rejected queue.", "cancel": "Cancel", "yes_ban_user": "Yes, Ban User" + }, + "streams": { + "search": "Search", + "filter-streams": "Filter Streams", + "stream-status": "Stream Status", + "all": "All", + "open": "Open", + "closed": "Closed", + "newest": "Newest", + "oldest": "Oldest", + "sort-by": "Sort By" } }, "es": { @@ -129,6 +140,17 @@ "note": "Nota: Suspender este usuario tambiƩn va a colocar este comentario en la cola de Rechazados.", "cancel": "Cancelar", "yes_ban_user": "Si, Suspendan el usuario" + }, + "streams": { + "search": "", + "filter-streams": "", + "stream-status": "", + "all": "", + "open": "", + "closed": "", + "newest": "", + "oldest": "", + "sort-by": "" } } } From 7c6299243f6ecd77f4eb49806736fc1d494925d7 Mon Sep 17 00:00:00 2001 From: David Jay Date: Wed, 14 Dec 2016 15:29:56 -0500 Subject: [PATCH 03/24] Connecting sorting options to state. --- .../src/containers/Streams/Streams.js | 80 ++++++++++++------- 1 file changed, 53 insertions(+), 27 deletions(-) diff --git a/client/coral-admin/src/containers/Streams/Streams.js b/client/coral-admin/src/containers/Streams/Streams.js index ee5d205ae..c6c9feeb3 100644 --- a/client/coral-admin/src/containers/Streams/Streams.js +++ b/client/coral-admin/src/containers/Streams/Streams.js @@ -1,4 +1,4 @@ -import React from 'react'; +import React, {Component} from 'react'; import styles from './Streams.css'; import I18n from 'coral-framework/modules/i18n/i18n'; import translations from '../../translations.json'; @@ -8,32 +8,58 @@ import { Icon } from 'react-mdl'; -const Streams = () =>
    -
    -
    - - {}} - placeholder={lang.t('streams.search')}/> -
    -
    {lang.t('streams.filter-streams')}
    -
    {lang.t('streams.stream-status')}
    - }> - {lang.t('streams.all')} - {lang.t('streams.open')} - {lang.t('streams.closed')} - -
    {lang.t('streams.sort-by')}
    - - {lang.t('streams.newest')} - {lang.t('streams.oldest')} - -
    -
    -
    -
    ; +class Streams extends Component { + + state = { + searchTerm: '', + sortBy: 'newest', + statusFilter: 'all' + } + + onSettingChange = (setting) => (e) => { + this.setState({[setting]: e.target.value}); + } + + render () { + const {searchTerm, sortBy, statusFilter} = this.state; + + return
    +
    +
    + + +
    +
    {lang.t('streams.filter-streams')}
    +
    {lang.t('streams.stream-status')}
    + + {lang.t('streams.all')} + {lang.t('streams.open')} + {lang.t('streams.closed')} + +
    {lang.t('streams.sort-by')}
    + + {lang.t('streams.newest')} + {lang.t('streams.oldest')} + +
    +
    +
    +
    ; + } +} export default Streams; From 65b308a0612789aeda3da097ad51942394938146 Mon Sep 17 00:00:00 2001 From: David Jay Date: Wed, 14 Dec 2016 16:01:43 -0500 Subject: [PATCH 04/24] Adding initial stream list. --- .../src/containers/Streams/Streams.css | 2 +- .../src/containers/Streams/Streams.js | 89 ++++++++++++------- 2 files changed, 60 insertions(+), 31 deletions(-) diff --git a/client/coral-admin/src/containers/Streams/Streams.css b/client/coral-admin/src/containers/Streams/Streams.css index 07724baa8..7ab1b5199 100644 --- a/client/coral-admin/src/containers/Streams/Streams.css +++ b/client/coral-admin/src/containers/Streams/Streams.css @@ -8,7 +8,7 @@ } .mainContent { - width: calc(70% - 300px) + width: calc(90% - 200px); } .searchIcon { diff --git a/client/coral-admin/src/containers/Streams/Streams.js b/client/coral-admin/src/containers/Streams/Streams.js index c6c9feeb3..bec61e995 100644 --- a/client/coral-admin/src/containers/Streams/Streams.js +++ b/client/coral-admin/src/containers/Streams/Streams.js @@ -5,7 +5,9 @@ import translations from '../../translations.json'; import { RadioGroup, Radio, - Icon + Icon, + DataTable, + TableHeader } from 'react-mdl'; class Streams extends Component { @@ -20,42 +22,69 @@ class Streams extends Component { this.setState({[setting]: e.target.value}); } + renderDate = (date) => { + const d = new Date(date); + return `${d.getMonth()}/${d.getDate()}/${d.getYear()}`; + } + + renderStatus = (status) => { + return
    {status}
    ; + } + render () { const {searchTerm, sortBy, statusFilter} = this.state; return
    -
    - - -
    -
    {lang.t('streams.filter-streams')}
    -
    {lang.t('streams.stream-status')}
    - - {lang.t('streams.all')} - {lang.t('streams.open')} - {lang.t('streams.closed')} - -
    {lang.t('streams.sort-by')}
    - - {lang.t('streams.newest')} - {lang.t('streams.oldest')} - + +
    + + +
    + +
    {lang.t('streams.filter-streams')}
    +
    {lang.t('streams.stream-status')}
    + + {lang.t('streams.all')} + {lang.t('streams.open')} + {lang.t('streams.closed')} + +
    {lang.t('streams.sort-by')}
    + + {lang.t('streams.newest')} + {lang.t('streams.oldest')} +
    +
    + + {lang.t('streams.article')} + + {lang.t('streams.pubdate')} + + + {lang.t('streams.status')} + +
    ; } From b98201afa3269c1bae428367effd03a33f4d6b08 Mon Sep 17 00:00:00 2001 From: David Jay Date: Wed, 14 Dec 2016 19:03:07 -0500 Subject: [PATCH 05/24] Adding and testing function to fetch assets in talk reducer. --- client/coral-admin/src/actions/assets.js | 0 client/coral-admin/src/constants/comments.js | 2 +- client/coral-admin/src/reducers/comments.js | 2 +- .../coral-admin/src/services/talk-adapter.js | 34 ++++++--- .../coral-admin/services/talk-adapter.js | 75 +++++++++++++++++++ .../{itemActions.spec.js => itemActions.js} | 0 .../{itemReducer.spec.js => itemReducer.js} | 0 7 files changed, 100 insertions(+), 13 deletions(-) create mode 100644 client/coral-admin/src/actions/assets.js create mode 100644 tests/client/coral-admin/services/talk-adapter.js rename tests/client/coral-framework/store/{itemActions.spec.js => itemActions.js} (100%) rename tests/client/coral-framework/store/{itemReducer.spec.js => itemReducer.js} (100%) diff --git a/client/coral-admin/src/actions/assets.js b/client/coral-admin/src/actions/assets.js new file mode 100644 index 000000000..e69de29bb diff --git a/client/coral-admin/src/constants/comments.js b/client/coral-admin/src/constants/comments.js index 856f619d0..16d72e889 100644 --- a/client/coral-admin/src/constants/comments.js +++ b/client/coral-admin/src/constants/comments.js @@ -1,3 +1,3 @@ export const SHOW_BANUSER_DIALOG = 'SHOW_BANUSER_DIALOG'; export const HIDE_BANUSER_DIALOG = 'HIDE_BANUSER_DIALOG'; -export const USER_BAN_SUCESS = 'USER_BAN_SUCESS'; +export const USER_BAN_SUCCESS = 'USER_BAN_SUCCESS'; diff --git a/client/coral-admin/src/reducers/comments.js b/client/coral-admin/src/reducers/comments.js index dca726b5e..d5fd85ab6 100644 --- a/client/coral-admin/src/reducers/comments.js +++ b/client/coral-admin/src/reducers/comments.js @@ -32,7 +32,7 @@ export default (state = initialState, action) => { case 'COMMENT_STREAM_FETCH_SUCCESS': return replaceComments(action, state); case actions.SHOW_BANUSER_DIALOG: return setBanUser(state, true, action); case actions.HIDE_BANUSER_DIALOG: return setBanUser(state, false, action); - case actions.USER_BAN_SUCESS: return setBanUser(state, false, action); + case actions.USER_BAN_SUCCESS: return setBanUser(state, false, action); default: return state; } }; diff --git a/client/coral-admin/src/services/talk-adapter.js b/client/coral-admin/src/services/talk-adapter.js index ab542b4a0..6dc4d5827 100644 --- a/client/coral-admin/src/services/talk-adapter.js +++ b/client/coral-admin/src/services/talk-adapter.js @@ -11,22 +11,20 @@ import coralApi from '../../../coral-framework/helpers/response'; // Intercept redux actions and act over the ones we are interested export default store => next => action => { + next(action); + switch (action.type) { case 'COMMENTS_MODERATION_QUEUE_FETCH': - fetchModerationQueueComments(store); - break; + return fetchModerationQueueComments(store); case 'COMMENT_UPDATE': - updateComment(store, action.comment); - break; + return updateComment(store, action.comment); case 'COMMENT_CREATE': - createComment(store, action.name, action.body); - break; + return createComment(store, action.name, action.body); case 'USER_BAN': - userStatusUpdate(store, action.status, action.userId, action.commentId); - break; + return userStatusUpdate(store, action.status, action.userId, action.commentId); + case 'ASSETS_FETCH': + return fetchAssets(store, action); } - - next(action); }; // Get comments to fill each of the three lists on the mod queue @@ -88,6 +86,20 @@ const createComment = (store, name, comment) => { // Ban a user const userStatusUpdate = (store, status, userId, commentId) => { return coralApi(`/users/${userId}/status`, {method: 'POST', body: {status: status, comment_id: commentId}}) - .then(res => store.dispatch({type: 'USER_BAN_SUCESS', res})) + .then(res => store.dispatch({type: 'USER_BAN_SUCCESS', res})) .catch(error => store.dispatch({type: 'USER_BAN_FAILED', error})); }; + +// Fetch a page of assets +// Get comments to fill each of the three lists on the mod queue +const fetchAssets = (store, action) => { + const {skip, limit, search} = action; + return coralApi(`/assets?skip=${skip}&limit=${limit}&search=${search}`) + .then(({result, count}) => + /* Post comments and users to redux store. Actions will be posted when they are needed. */ + store.dispatch({type: 'ASSETS_FETCH_SUCCESS', + assets: result, + count + })) + .catch(error => store.dispatch({type: 'ASSETS_FETCH_FAILED', error})); +}; diff --git a/tests/client/coral-admin/services/talk-adapter.js b/tests/client/coral-admin/services/talk-adapter.js new file mode 100644 index 000000000..27ae8efcb --- /dev/null +++ b/tests/client/coral-admin/services/talk-adapter.js @@ -0,0 +1,75 @@ +import 'react'; +import 'redux'; +import {expect} from 'chai'; +import fetchMock from 'fetch-mock'; +import adapter from '../../../../client/coral-admin/src/services/talk-adapter'; +import {Map} from 'immutable'; + +import configureStore from 'redux-mock-store'; + +const mockStore = configureStore(); + +describe('talk-adapter.js', () => { + let store; + + beforeEach(() => { + store = mockStore(new Map({})); + fetchMock.restore(); + }); + + describe('ASSETS_FETCH', () => { + + const assets = [ + { + url: 'http://test.com', + id: '123', + status: 'closed' + }, + { + url: 'http://test.org', + id: '456', + status: 'open' + } + ]; + + it('should fetch a list of assets', () => { + + const action = { + type: 'ASSETS_FETCH', + skip: 2, + limit: 20, + search: '' + }; + + fetchMock.get('*', JSON.stringify({ + result: assets, + count: 2 + })); + + return adapter(store)(()=>{})(action) + .then(() => { + expect(store.getActions()[0]).to.have.property('type', 'ASSETS_FETCH_SUCCESS'); + expect(store.getActions()[0]).to.have.property('count', 2); + expect(store.getActions()[0]).to.have.property('assets'). + and.to.deep.equal(assets); + }); + }); + + it('should return an error appropriatly', () => { + + const action = { + type: 'ASSETS_FETCH', + skip: 2, + limit: 20, + search: '' + }; + + fetchMock.get('*', 404); + + return adapter(store)(()=>{})(action) + .then(() => { + expect(store.getActions()[0]).to.have.property('type', 'ASSETS_FETCH_FAILED'); + }); + }); + }); +}); diff --git a/tests/client/coral-framework/store/itemActions.spec.js b/tests/client/coral-framework/store/itemActions.js similarity index 100% rename from tests/client/coral-framework/store/itemActions.spec.js rename to tests/client/coral-framework/store/itemActions.js diff --git a/tests/client/coral-framework/store/itemReducer.spec.js b/tests/client/coral-framework/store/itemReducer.js similarity index 100% rename from tests/client/coral-framework/store/itemReducer.spec.js rename to tests/client/coral-framework/store/itemReducer.js From 78c81aeaf4f538ae2419226490a5108036eab15f Mon Sep 17 00:00:00 2001 From: David Jay Date: Wed, 14 Dec 2016 19:30:59 -0500 Subject: [PATCH 06/24] Adding asset reducer. --- client/coral-admin/src/actions/assets.js | 0 client/coral-admin/src/reducers/assets.js | 20 +++++++++++ tests/client/coral-admin/reducers/assets.js | 39 +++++++++++++++++++++ 3 files changed, 59 insertions(+) delete mode 100644 client/coral-admin/src/actions/assets.js create mode 100644 client/coral-admin/src/reducers/assets.js create mode 100644 tests/client/coral-admin/reducers/assets.js diff --git a/client/coral-admin/src/actions/assets.js b/client/coral-admin/src/actions/assets.js deleted file mode 100644 index e69de29bb..000000000 diff --git a/client/coral-admin/src/reducers/assets.js b/client/coral-admin/src/reducers/assets.js new file mode 100644 index 000000000..bdd1bcaf9 --- /dev/null +++ b/client/coral-admin/src/reducers/assets.js @@ -0,0 +1,20 @@ +import {Map, List, fromJS} from 'immutable'; + +const initialState = Map({ + byId: Map(), + ids: List() +}); + +export default (state = initialState, action) => { + switch (action.type) { + case 'ASSETS_FETCH_SUCCESS': return replaceAssets(action, state); + default: return state; + } +}; + +const replaceAssets = (action, state) => { + const assets = fromJS(action.assets.reduce((prev, curr) => { prev[curr.id] = curr; return prev; }, {})); + return state.set('byId', assets) + .set('count', action.count) + .set('ids', List(assets.keys())); +}; diff --git a/tests/client/coral-admin/reducers/assets.js b/tests/client/coral-admin/reducers/assets.js new file mode 100644 index 000000000..cf3e0dac4 --- /dev/null +++ b/tests/client/coral-admin/reducers/assets.js @@ -0,0 +1,39 @@ +import {Map} from 'immutable'; +import {expect} from 'chai'; +import assetsReducer from '../../../../client/coral-admin/src/reducers/assets'; + +describe ('assetsReducer', () => { + describe('ASSETS_FETCH_SUCCESS', () => { + it('should replace the existing assets', () => { + const action = { + type: 'ASSETS_FETCH_SUCCESS', + count: 200, + assets: [ + { + id: '123', + url: 'http://test.com', + closedAt: 'tomorrow' + }, + { + id: '456', + url: 'http://test2.com', + closedAt: 'thursday' + }, + ] + }; + const store = new Map({}); + const result = assetsReducer(store, action); + console.log(result.getIn(['byId', '123']).toJS()); + expect(result.getIn(['byId', '123']).toJS()).to.deep.equal({ + url: 'http://test.com', + closedAt: 'tomorrow', + id: '123' + }); + expect(result.getIn(['ids']).toJS()).to.deep.equal([ + '123', + '456' + ]); + expect(result.getIn(['count'])).to.equal(200); + }); + }); +}); From faafbfa78cf3142b35430abb198002985910b173 Mon Sep 17 00:00:00 2001 From: David Jay Date: Wed, 14 Dec 2016 19:58:04 -0500 Subject: [PATCH 07/24] Loading assets and adding to store. --- client/coral-admin/src/constants/assets.js | 1 + .../src/containers/Streams/Streams.js | 23 ++++++++++++++++++- client/coral-admin/src/reducers/index.js | 4 +++- routes/api/assets/index.js | 4 ++-- 4 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 client/coral-admin/src/constants/assets.js diff --git a/client/coral-admin/src/constants/assets.js b/client/coral-admin/src/constants/assets.js new file mode 100644 index 000000000..59b76390f --- /dev/null +++ b/client/coral-admin/src/constants/assets.js @@ -0,0 +1 @@ +export const ASSETS_FETCH = 'ASSETS_FETCH'; diff --git a/client/coral-admin/src/containers/Streams/Streams.js b/client/coral-admin/src/containers/Streams/Streams.js index bec61e995..ea365d0d1 100644 --- a/client/coral-admin/src/containers/Streams/Streams.js +++ b/client/coral-admin/src/containers/Streams/Streams.js @@ -1,6 +1,8 @@ import React, {Component} from 'react'; import styles from './Streams.css'; +import {connect} from 'react-redux'; import I18n from 'coral-framework/modules/i18n/i18n'; +import {ASSETS_FETCH} from '../../constants/assets'; import translations from '../../translations.json'; import { RadioGroup, @@ -18,6 +20,10 @@ class Streams extends Component { statusFilter: 'all' } + componentDidMount () { + this.props.fetchAssets(0, 25, '', 'desc'); + } + onSettingChange = (setting) => (e) => { this.setState({[setting]: e.target.value}); } @@ -90,6 +96,21 @@ class Streams extends Component { } } -export default Streams; +const mapStateToProps = () => {}; +const mapDispatchToProps = (dispatch) => { + return { + fetchAssets: (skip, limit, search, sort) => { + dispatch({ + type: ASSETS_FETCH, + skip, + limit, + search, + sort + }); + } + }; +}; + +export default connect(mapStateToProps, mapDispatchToProps)(Streams); const lang = new I18n(translations); diff --git a/client/coral-admin/src/reducers/index.js b/client/coral-admin/src/reducers/index.js index 1f1b444fc..fca4694d8 100644 --- a/client/coral-admin/src/reducers/index.js +++ b/client/coral-admin/src/reducers/index.js @@ -4,6 +4,7 @@ import settings from 'reducers/settings'; import community from 'reducers/community'; import users from 'reducers/users'; import auth from 'reducers/auth'; +import assets from 'reducers/assets'; // Combine all reducers into a main one export default combineReducers({ @@ -11,5 +12,6 @@ export default combineReducers({ comments, community, auth, - users + users, + assets }); diff --git a/routes/api/assets/index.js b/routes/api/assets/index.js index 5aa9b8cc6..a602d7fd0 100644 --- a/routes/api/assets/index.js +++ b/routes/api/assets/index.js @@ -20,8 +20,8 @@ router.get('/', (req, res, next) => { Asset .search(search) .sort({[field]: (sort === 'asc') ? 1 : -1}) - .skip(skip) - .limit(limit), + .skip(parseInt(skip)) + .limit(parseInt(limit)), Asset .search(search) .count() From d5268989627c9e2f1e1bd2e1778e275c60716217 Mon Sep 17 00:00:00 2001 From: David Jay Date: Wed, 14 Dec 2016 20:19:27 -0500 Subject: [PATCH 08/24] Loading assets into Streams component. --- .../src/containers/Streams/Streams.css | 4 +++ .../src/containers/Streams/Streams.js | 26 ++++++++++--------- client/coral-admin/src/translations.json | 14 ++++++++-- 3 files changed, 30 insertions(+), 14 deletions(-) diff --git a/client/coral-admin/src/containers/Streams/Streams.css b/client/coral-admin/src/containers/Streams/Streams.css index 7ab1b5199..5ad875b35 100644 --- a/client/coral-admin/src/containers/Streams/Streams.css +++ b/client/coral-admin/src/containers/Streams/Streams.css @@ -46,6 +46,10 @@ margin-top: 3px; } +.streamsTable { + width: 100%; +} + .radio { display: block; } diff --git a/client/coral-admin/src/containers/Streams/Streams.js b/client/coral-admin/src/containers/Streams/Streams.js index ea365d0d1..7b1778012 100644 --- a/client/coral-admin/src/containers/Streams/Streams.js +++ b/client/coral-admin/src/containers/Streams/Streams.js @@ -30,15 +30,17 @@ class Streams extends Component { renderDate = (date) => { const d = new Date(date); - return `${d.getMonth()}/${d.getDate()}/${d.getYear()}`; + return `${d.getMonth() + 1}/${d.getDate()}/${d.getFullYear()}`; } - renderStatus = (status) => { + renderStatus = (closedAt) => { + const status = closedAt && new Date(closedAt) < Date.now ? lang.t('streams.closed') : lang.t('streams.open'); return
    {status}
    ; } render () { const {searchTerm, sortBy, statusFilter} = this.state; + const {assets} = this.props; return
    @@ -77,17 +79,13 @@ class Streams extends Component {
    - {lang.t('streams.article')} - + className={styles.streamsTable} + rows={assets.ids.map((id) => assets.byId[id])}> + {lang.t('streams.article')} + {lang.t('streams.pubdate')} - + {lang.t('streams.status')} @@ -96,7 +94,11 @@ class Streams extends Component { } } -const mapStateToProps = () => {}; +const mapStateToProps = ({assets}) => { + return { + assets: assets.toJS() + }; +}; const mapDispatchToProps = (dispatch) => { return { fetchAssets: (skip, limit, search, sort) => { diff --git a/client/coral-admin/src/translations.json b/client/coral-admin/src/translations.json index da859c49c..c093f7ae0 100644 --- a/client/coral-admin/src/translations.json +++ b/client/coral-admin/src/translations.json @@ -79,7 +79,12 @@ "closed": "Closed", "newest": "Newest", "oldest": "Oldest", - "sort-by": "Sort By" + "sort-by": "Sort By", + "open": "Open", + "closed": "Closed", + "article": "Article", + "pubdate": "Publication Date", + "status": "Status" } }, "es": { @@ -150,7 +155,12 @@ "closed": "", "newest": "", "oldest": "", - "sort-by": "" + "sort-by": "", + "open": "", + "closed": "", + "article": "", + "pubdate": "", + "status": "" } } } From 86eef68b163e9412a24a478a0e2dd3644cebf0b4 Mon Sep 17 00:00:00 2001 From: David Jay Date: Thu, 15 Dec 2016 12:25:43 -0500 Subject: [PATCH 09/24] Adding status menu. --- client/coral-admin/src/actions/assets.js | 13 +++++ client/coral-admin/src/constants/assets.js | 5 +- .../src/containers/Streams/Streams.css | 24 ++++++++ .../src/containers/Streams/Streams.js | 55 ++++++++++++++----- client/coral-admin/src/reducers/assets.js | 3 +- .../coral-admin/src/services/talk-adapter.js | 6 +- 6 files changed, 88 insertions(+), 18 deletions(-) create mode 100644 client/coral-admin/src/actions/assets.js diff --git a/client/coral-admin/src/actions/assets.js b/client/coral-admin/src/actions/assets.js new file mode 100644 index 000000000..1e5f2716d --- /dev/null +++ b/client/coral-admin/src/actions/assets.js @@ -0,0 +1,13 @@ +import {FETCH_ASSETS, UPDATE_ASSET} from '../constants/assets'; + +/** + * Action disptacher related to assets + */ + +export const updateAsset = (id, property, value) => (dispatch) => { + dispatch({type: UPDATE_ASSET, id, property, value}); +}; + +export const fetchAssets = (skip, limit, search, sort) => (dispatch) => { + dispatch({type: FETCH_ASSETS, skip, limit, search, sort}); +}; diff --git a/client/coral-admin/src/constants/assets.js b/client/coral-admin/src/constants/assets.js index 59b76390f..b13534726 100644 --- a/client/coral-admin/src/constants/assets.js +++ b/client/coral-admin/src/constants/assets.js @@ -1 +1,4 @@ -export const ASSETS_FETCH = 'ASSETS_FETCH'; +export const FETCH_ASSETS = 'FETCH_ASSETS'; +export const FETCH_ASSETS_SUCCESS = 'FETCH_ASSETS_SUCCESS'; +export const FETCH_ASSETS_FAILED = 'FETCH_ASSETS_FAILED'; +export const UPDATE_ASSET = 'UPDATE_ASSET'; diff --git a/client/coral-admin/src/containers/Streams/Streams.css b/client/coral-admin/src/containers/Streams/Streams.css index 5ad875b35..c64de7974 100644 --- a/client/coral-admin/src/containers/Streams/Streams.css +++ b/client/coral-admin/src/containers/Streams/Streams.css @@ -54,6 +54,30 @@ display: block; } +.statusMenu { + border-radius: 3px; + width: 10em; + text-align: center; + float: right; + border: 1px solid #ccc; + color: #fff; + cursor: pointer; +} + +.statusMenuOpen { + padding: 10px; + background-color: #4caf50; +} + +.statusMenuIcon { + float: right; +} + +.statusMenuClosed { + padding: 10px; + background-color: #000; +} + .hidden { display: none; } diff --git a/client/coral-admin/src/containers/Streams/Streams.js b/client/coral-admin/src/containers/Streams/Streams.js index 7b1778012..078f7c98a 100644 --- a/client/coral-admin/src/containers/Streams/Streams.js +++ b/client/coral-admin/src/containers/Streams/Streams.js @@ -2,7 +2,7 @@ import React, {Component} from 'react'; import styles from './Streams.css'; import {connect} from 'react-redux'; import I18n from 'coral-framework/modules/i18n/i18n'; -import {ASSETS_FETCH} from '../../constants/assets'; +import {fetchAssets, updateAsset} from '../../actions/assets'; import translations from '../../translations.json'; import { RadioGroup, @@ -17,7 +17,8 @@ class Streams extends Component { state = { searchTerm: '', sortBy: 'newest', - statusFilter: 'all' + statusFilter: 'all', + statusMenus: {} } componentDidMount () { @@ -33,9 +34,40 @@ class Streams extends Component { return `${d.getMonth() + 1}/${d.getDate()}/${d.getFullYear()}`; } - renderStatus = (closedAt) => { - const status = closedAt && new Date(closedAt) < Date.now ? lang.t('streams.closed') : lang.t('streams.open'); - return
    {status}
    ; + onStatusClick = (closeStream, id, statusMenuOpen) => () => { + if (statusMenuOpen) { + this.setState(prev => { + prev.statusMenus[id] = false; + return prev; + }); + this.props.updateAsset(id, 'closedAt', closeStream ? Date.now() : null); + } else { + this.setState(prev => { + prev.statusMenus[id] = true; + return prev; + }); + } + } + + renderStatus = (closedAt, id) => { + const closed = closedAt && new Date(closedAt) < Date.now; + const statusMenuOpen = this.state.statusMenus[id]; + return
    +
    + {closed ? lang.t('streams.closed') : lang.t('streams.open')} + {!statusMenuOpen && } +
    + { + statusMenuOpen && +
    + {!closed ? lang.t('streams.closed') : lang.t('streams.open')} +
    + } +
    ; } render () { @@ -101,14 +133,11 @@ const mapStateToProps = ({assets}) => { }; const mapDispatchToProps = (dispatch) => { return { - fetchAssets: (skip, limit, search, sort) => { - dispatch({ - type: ASSETS_FETCH, - skip, - limit, - search, - sort - }); + fetchAssets: (...args) => { + dispatch(fetchAssets.apply(this, args)); + }, + updateAsset: (...args) => { + dispatch(updateAsset.apply(this, args)); } }; }; diff --git a/client/coral-admin/src/reducers/assets.js b/client/coral-admin/src/reducers/assets.js index bdd1bcaf9..a1ca4c831 100644 --- a/client/coral-admin/src/reducers/assets.js +++ b/client/coral-admin/src/reducers/assets.js @@ -1,4 +1,5 @@ import {Map, List, fromJS} from 'immutable'; +import {FETCH_ASSETS_SUCCESS} from '../constants/assets'; const initialState = Map({ byId: Map(), @@ -7,7 +8,7 @@ const initialState = Map({ export default (state = initialState, action) => { switch (action.type) { - case 'ASSETS_FETCH_SUCCESS': return replaceAssets(action, state); + case FETCH_ASSETS_SUCCESS: return replaceAssets(action, state); default: return state; } }; diff --git a/client/coral-admin/src/services/talk-adapter.js b/client/coral-admin/src/services/talk-adapter.js index 6dc4d5827..1b824c13e 100644 --- a/client/coral-admin/src/services/talk-adapter.js +++ b/client/coral-admin/src/services/talk-adapter.js @@ -22,7 +22,7 @@ export default store => next => action => { return createComment(store, action.name, action.body); case 'USER_BAN': return userStatusUpdate(store, action.status, action.userId, action.commentId); - case 'ASSETS_FETCH': + case 'FETCH_ASSETS': return fetchAssets(store, action); } }; @@ -97,9 +97,9 @@ const fetchAssets = (store, action) => { return coralApi(`/assets?skip=${skip}&limit=${limit}&search=${search}`) .then(({result, count}) => /* Post comments and users to redux store. Actions will be posted when they are needed. */ - store.dispatch({type: 'ASSETS_FETCH_SUCCESS', + store.dispatch({type: 'FETCH_ASSETS_SUCCESS', assets: result, count })) - .catch(error => store.dispatch({type: 'ASSETS_FETCH_FAILED', error})); + .catch(error => store.dispatch({type: 'FETCH_ASSETS_FAILED', error})); }; From c7b232f0b3e89aafbe64531826138a323479581e Mon Sep 17 00:00:00 2001 From: David Jay Date: Thu, 15 Dec 2016 13:10:23 -0500 Subject: [PATCH 10/24] Adding action to upate asset state. --- client/coral-admin/src/actions/assets.js | 6 +- client/coral-admin/src/constants/assets.js | 4 +- .../coral-admin/src/services/talk-adapter.js | 28 ++++++- tests/client/coral-admin/reducers/assets.js | 4 +- .../coral-admin/services/talk-adapter.js | 73 ++++++++++++++----- 5 files changed, 87 insertions(+), 28 deletions(-) diff --git a/client/coral-admin/src/actions/assets.js b/client/coral-admin/src/actions/assets.js index 1e5f2716d..5918d1df8 100644 --- a/client/coral-admin/src/actions/assets.js +++ b/client/coral-admin/src/actions/assets.js @@ -1,11 +1,11 @@ -import {FETCH_ASSETS, UPDATE_ASSET} from '../constants/assets'; +import {FETCH_ASSETS, UPDATE_ASSET_STATE} from '../constants/assets'; /** * Action disptacher related to assets */ -export const updateAsset = (id, property, value) => (dispatch) => { - dispatch({type: UPDATE_ASSET, id, property, value}); +export const updateAssetState = (id, property, value) => (dispatch) => { + dispatch({type: UPDATE_ASSET_STATE, id, property, value}); }; export const fetchAssets = (skip, limit, search, sort) => (dispatch) => { diff --git a/client/coral-admin/src/constants/assets.js b/client/coral-admin/src/constants/assets.js index b13534726..8927b351d 100644 --- a/client/coral-admin/src/constants/assets.js +++ b/client/coral-admin/src/constants/assets.js @@ -1,4 +1,6 @@ export const FETCH_ASSETS = 'FETCH_ASSETS'; export const FETCH_ASSETS_SUCCESS = 'FETCH_ASSETS_SUCCESS'; export const FETCH_ASSETS_FAILED = 'FETCH_ASSETS_FAILED'; -export const UPDATE_ASSET = 'UPDATE_ASSET'; +export const UPDATE_ASSET_STATE = 'UPDATE_ASSET_STATE'; +export const UPDATE_ASSET_STATE_SUCCESS = 'UPDATE_ASSET_STATE_SUCCESS'; +export const UPDATE_ASSET_STATE_FAILED = 'UPDATE_ASSET_STATE_FAILED'; diff --git a/client/coral-admin/src/services/talk-adapter.js b/client/coral-admin/src/services/talk-adapter.js index 1b824c13e..dea4d7cb2 100644 --- a/client/coral-admin/src/services/talk-adapter.js +++ b/client/coral-admin/src/services/talk-adapter.js @@ -1,5 +1,12 @@ import coralApi from '../../../coral-framework/helpers/response'; - +import { + FETCH_ASSETS, + FETCH_ASSETS_FAILED, + FETCH_ASSETS_SUCCESS, + UPDATE_ASSET_STATE, + UPDATE_ASSET_STATE_SUCCESS, + UPDATE_ASSET_STATE_FAILED, +} from '../constants/assets'; /** * The adapter is a redux middleware that interecepts the actions that need * to interface with the backend, do the job and return the results. @@ -22,8 +29,10 @@ export default store => next => action => { return createComment(store, action.name, action.body); case 'USER_BAN': return userStatusUpdate(store, action.status, action.userId, action.commentId); - case 'FETCH_ASSETS': + case FETCH_ASSETS: return fetchAssets(store, action); + case UPDATE_ASSET_STATE: + return updateAssetState(store, action); } }; @@ -97,9 +106,20 @@ const fetchAssets = (store, action) => { return coralApi(`/assets?skip=${skip}&limit=${limit}&search=${search}`) .then(({result, count}) => /* Post comments and users to redux store. Actions will be posted when they are needed. */ - store.dispatch({type: 'FETCH_ASSETS_SUCCESS', + store.dispatch({type: FETCH_ASSETS_SUCCESS, assets: result, count })) - .catch(error => store.dispatch({type: 'FETCH_ASSETS_FAILED', error})); + .catch(error => store.dispatch({type: FETCH_ASSETS_FAILED, error})); +}; + +// Update an asset state +// Get comments to fill each of the three lists on the mod queue +const updateAssetState = (store, action) => { + const {id, closedAt} = action; + return coralApi(`/assets/${id}/status`, {method: 'PUT', body: {closedAt}}) + .then(() => + /* Post comments and users to redux store. Actions will be posted when they are needed. */ + store.dispatch({type: UPDATE_ASSET_STATE_SUCCESS, closedAt})) + .catch(error => store.dispatch({type: UPDATE_ASSET_STATE_FAILED, error})); }; diff --git a/tests/client/coral-admin/reducers/assets.js b/tests/client/coral-admin/reducers/assets.js index cf3e0dac4..2a3c15b45 100644 --- a/tests/client/coral-admin/reducers/assets.js +++ b/tests/client/coral-admin/reducers/assets.js @@ -3,10 +3,10 @@ import {expect} from 'chai'; import assetsReducer from '../../../../client/coral-admin/src/reducers/assets'; describe ('assetsReducer', () => { - describe('ASSETS_FETCH_SUCCESS', () => { + describe('FETCH_ASSETS_SUCCESS', () => { it('should replace the existing assets', () => { const action = { - type: 'ASSETS_FETCH_SUCCESS', + type: 'FETCH_ASSETS_SUCCESS', count: 200, assets: [ { diff --git a/tests/client/coral-admin/services/talk-adapter.js b/tests/client/coral-admin/services/talk-adapter.js index 27ae8efcb..b30ae3905 100644 --- a/tests/client/coral-admin/services/talk-adapter.js +++ b/tests/client/coral-admin/services/talk-adapter.js @@ -12,30 +12,30 @@ const mockStore = configureStore(); describe('talk-adapter.js', () => { let store; + const assets = [ + { + url: 'http://test.com', + id: '123', + status: 'closed' + }, + { + url: 'http://test.org', + id: '456', + status: 'open' + } + ]; + beforeEach(() => { store = mockStore(new Map({})); fetchMock.restore(); }); - describe('ASSETS_FETCH', () => { - - const assets = [ - { - url: 'http://test.com', - id: '123', - status: 'closed' - }, - { - url: 'http://test.org', - id: '456', - status: 'open' - } - ]; + describe('FETCH_ASSETS', () => { it('should fetch a list of assets', () => { const action = { - type: 'ASSETS_FETCH', + type: 'FETCH_ASSETS', skip: 2, limit: 20, search: '' @@ -48,7 +48,7 @@ describe('talk-adapter.js', () => { return adapter(store)(()=>{})(action) .then(() => { - expect(store.getActions()[0]).to.have.property('type', 'ASSETS_FETCH_SUCCESS'); + expect(store.getActions()[0]).to.have.property('type', 'FETCH_ASSETS_SUCCESS'); expect(store.getActions()[0]).to.have.property('count', 2); expect(store.getActions()[0]).to.have.property('assets'). and.to.deep.equal(assets); @@ -58,7 +58,7 @@ describe('talk-adapter.js', () => { it('should return an error appropriatly', () => { const action = { - type: 'ASSETS_FETCH', + type: 'FETCH_ASSETS', skip: 2, limit: 20, search: '' @@ -68,7 +68,44 @@ describe('talk-adapter.js', () => { return adapter(store)(()=>{})(action) .then(() => { - expect(store.getActions()[0]).to.have.property('type', 'ASSETS_FETCH_FAILED'); + expect(store.getActions()[0]).to.have.property('type', 'FETCH_ASSETS_FAILED'); + }); + }); + }); + + describe('UPDATE_ASSET_STATE', () => { + + it('should update an asset', () => { + const action = { + type: 'UPDATE_ASSET_STATE', + id: '123', + property: 'closedAt', + value: Date.now() + }; + + fetchMock.put('*', JSON.stringify(assets[0])); + + return adapter(store)(()=>{})(action) + .then(() => { + expect(store.getActions()[0]).to.have.property('type', 'UPDATE_ASSET_STATE_SUCCESS'); + }); + + }); + + it('should return an error appropriately', () => { + + const action = { + type: 'UPDATE_ASSET_STATE', + id: '123', + property: 'closedAt', + value: Date.now() + }; + + fetchMock.put('*', 404); + + return adapter(store)(()=>{})(action) + .then(() => { + expect(store.getActions()[0]).to.have.property('type', 'UPDATE_ASSET_STATE_FAILED'); }); }); }); From 328eaad8e521a35e7fce4dfa1207f6e6adbf8937 Mon Sep 17 00:00:00 2001 From: David Jay Date: Thu, 15 Dec 2016 14:05:10 -0500 Subject: [PATCH 11/24] Adding update state to reducer. --- client/coral-admin/src/reducers/assets.js | 7 +++-- tests/client/coral-admin/reducers/assets.js | 29 +++++++++++++++++++-- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/client/coral-admin/src/reducers/assets.js b/client/coral-admin/src/reducers/assets.js index a1ca4c831..f18aaec33 100644 --- a/client/coral-admin/src/reducers/assets.js +++ b/client/coral-admin/src/reducers/assets.js @@ -1,5 +1,5 @@ import {Map, List, fromJS} from 'immutable'; -import {FETCH_ASSETS_SUCCESS} from '../constants/assets'; +import {FETCH_ASSETS_SUCCESS, UPDATE_ASSET_STATE} from '../constants/assets'; const initialState = Map({ byId: Map(), @@ -8,7 +8,10 @@ const initialState = Map({ export default (state = initialState, action) => { switch (action.type) { - case FETCH_ASSETS_SUCCESS: return replaceAssets(action, state); + case FETCH_ASSETS_SUCCESS: + return replaceAssets(action, state); + case UPDATE_ASSET_STATE: + return state.setIn(['byId', action.id, 'closedAt'], action.closedAt); default: return state; } }; diff --git a/tests/client/coral-admin/reducers/assets.js b/tests/client/coral-admin/reducers/assets.js index 2a3c15b45..60972f47a 100644 --- a/tests/client/coral-admin/reducers/assets.js +++ b/tests/client/coral-admin/reducers/assets.js @@ -1,4 +1,4 @@ -import {Map} from 'immutable'; +import {Map, fromJS} from 'immutable'; import {expect} from 'chai'; import assetsReducer from '../../../../client/coral-admin/src/reducers/assets'; @@ -23,7 +23,6 @@ describe ('assetsReducer', () => { }; const store = new Map({}); const result = assetsReducer(store, action); - console.log(result.getIn(['byId', '123']).toJS()); expect(result.getIn(['byId', '123']).toJS()).to.deep.equal({ url: 'http://test.com', closedAt: 'tomorrow', @@ -36,4 +35,30 @@ describe ('assetsReducer', () => { expect(result.getIn(['count'])).to.equal(200); }); }); + + describe('UPDATE_ASSET_STATE', () => { + it('should update the state of a particular asset', () => { + const action = { + type: 'UPDATE_ASSET_STATE', + id: '123', + closedAt: null + }; + const store = new fromJS({ + byId: { + '123': { + id: '123', + url: 'http://test.com', + closedAt: Date.now() + }, + '456': { + id: '456', + url: 'http://test2.com', + closedAt: 'thursday' + } + } + }); + const result = assetsReducer(store, action); + expect(result.getIn(['byId', '123', 'closedAt'])).to.equal.null; + }); + }); }); From 1154b65c9166b86370e5e070faeb859cad606fd0 Mon Sep 17 00:00:00 2001 From: David Jay Date: Thu, 15 Dec 2016 14:19:44 -0500 Subject: [PATCH 12/24] Updating state from menu. --- client/coral-admin/src/actions/assets.js | 4 ++-- client/coral-admin/src/containers/Streams/Streams.js | 12 ++++++------ client/coral-admin/src/services/talk-adapter.js | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/client/coral-admin/src/actions/assets.js b/client/coral-admin/src/actions/assets.js index 5918d1df8..b13454a21 100644 --- a/client/coral-admin/src/actions/assets.js +++ b/client/coral-admin/src/actions/assets.js @@ -4,8 +4,8 @@ import {FETCH_ASSETS, UPDATE_ASSET_STATE} from '../constants/assets'; * Action disptacher related to assets */ -export const updateAssetState = (id, property, value) => (dispatch) => { - dispatch({type: UPDATE_ASSET_STATE, id, property, value}); +export const updateAssetState = (id, closedAt) => (dispatch) => { + dispatch({type: UPDATE_ASSET_STATE, id, closedAt}); }; export const fetchAssets = (skip, limit, search, sort) => (dispatch) => { diff --git a/client/coral-admin/src/containers/Streams/Streams.js b/client/coral-admin/src/containers/Streams/Streams.js index 078f7c98a..53db75c89 100644 --- a/client/coral-admin/src/containers/Streams/Streams.js +++ b/client/coral-admin/src/containers/Streams/Streams.js @@ -2,7 +2,7 @@ import React, {Component} from 'react'; import styles from './Streams.css'; import {connect} from 'react-redux'; import I18n from 'coral-framework/modules/i18n/i18n'; -import {fetchAssets, updateAsset} from '../../actions/assets'; +import {fetchAssets, updateAssetState} from '../../actions/assets'; import translations from '../../translations.json'; import { RadioGroup, @@ -40,7 +40,7 @@ class Streams extends Component { prev.statusMenus[id] = false; return prev; }); - this.props.updateAsset(id, 'closedAt', closeStream ? Date.now() : null); + this.props.updateAssetState(id, closeStream ? Date.now() : null); } else { this.setState(prev => { prev.statusMenus[id] = true; @@ -49,8 +49,8 @@ class Streams extends Component { } } - renderStatus = (closedAt, id) => { - const closed = closedAt && new Date(closedAt) < Date.now; + renderStatus = (closedAt, {id}) => { + const closed = closedAt && new Date(closedAt).getTime() < Date.now(); const statusMenuOpen = this.state.statusMenus[id]; return
    { fetchAssets: (...args) => { dispatch(fetchAssets.apply(this, args)); }, - updateAsset: (...args) => { - dispatch(updateAsset.apply(this, args)); + updateAssetState: (...args) => { + dispatch(updateAssetState.apply(this, args)); } }; }; diff --git a/client/coral-admin/src/services/talk-adapter.js b/client/coral-admin/src/services/talk-adapter.js index dea4d7cb2..67835e30d 100644 --- a/client/coral-admin/src/services/talk-adapter.js +++ b/client/coral-admin/src/services/talk-adapter.js @@ -120,6 +120,6 @@ const updateAssetState = (store, action) => { return coralApi(`/assets/${id}/status`, {method: 'PUT', body: {closedAt}}) .then(() => /* Post comments and users to redux store. Actions will be posted when they are needed. */ - store.dispatch({type: UPDATE_ASSET_STATE_SUCCESS, closedAt})) + store.dispatch({type: UPDATE_ASSET_STATE_SUCCESS})) .catch(error => store.dispatch({type: UPDATE_ASSET_STATE_FAILED, error})); }; From d4880ff183423306cf925e12d8f9816f69a7f00c Mon Sep 17 00:00:00 2001 From: David Jay Date: Fri, 16 Dec 2016 15:35:15 -0500 Subject: [PATCH 13/24] Adding asset sorting to endpoint. --- .../src/containers/Streams/Streams.js | 13 ++++--- routes/api/assets/index.js | 28 +++++++++++--- tests/routes/api/assets/index.js | 38 ++++++++++++++++++- 3 files changed, 67 insertions(+), 12 deletions(-) diff --git a/client/coral-admin/src/containers/Streams/Streams.js b/client/coral-admin/src/containers/Streams/Streams.js index 53db75c89..5d8508f33 100644 --- a/client/coral-admin/src/containers/Streams/Streams.js +++ b/client/coral-admin/src/containers/Streams/Streams.js @@ -12,21 +12,24 @@ import { TableHeader } from 'react-mdl'; +const limit = 25; + class Streams extends Component { state = { - searchTerm: '', - sortBy: 'newest', + search: '', + sort: 'desc', statusFilter: 'all', statusMenus: {} } componentDidMount () { - this.props.fetchAssets(0, 25, '', 'desc'); + this.props.fetchAssets(0, limit, '', this.state.sortBy); } onSettingChange = (setting) => (e) => { this.setState({[setting]: e.target.value}); + this.props.fetchAssets(0, limit, this.state.search, this.state.sort); } renderDate = (date) => { @@ -104,8 +107,8 @@ class Streams extends Component { value={sortBy} childContainer='div' onChange={this.onSettingChange('sortBy')}> - {lang.t('streams.newest')} - {lang.t('streams.oldest')} + {lang.t('streams.newest')} + {lang.t('streams.oldest')}
    diff --git a/routes/api/assets/index.js b/routes/api/assets/index.js index a602d7fd0..a661d64e8 100644 --- a/routes/api/assets/index.js +++ b/routes/api/assets/index.js @@ -12,22 +12,40 @@ router.get('/', (req, res, next) => { skip = 0, sort = 'asc', field = 'created_at', + filter = 'all', search = '' } = req.query; + const assets = (filter, search) => { + switch(filter) { + case 'open': + return Asset.search(search) + .find({ + $or: [ + {closedAt: null}, + {closedAt: {$gt: Date.now()}} + ] + }); + case 'closed': + return Asset.search(search) + .find({ + closedAt: {$lt: Date.now()} + }); + default: + return Asset.search(search); + } + }; + // Find all the assets. Promise.all([ - Asset - .search(search) + assets(filter, search) .sort({[field]: (sort === 'asc') ? 1 : -1}) .skip(parseInt(skip)) .limit(parseInt(limit)), - Asset - .search(search) + assets(filter, search) .count() ]) .then(([result, count]) => { - // Send back the asset data. res.json({ result, diff --git a/tests/routes/api/assets/index.js b/tests/routes/api/assets/index.js index 8e94c81fc..da011bf7b 100644 --- a/tests/routes/api/assets/index.js +++ b/tests/routes/api/assets/index.js @@ -18,12 +18,14 @@ describe('/api/v1/assets', () => { url: 'https://coralproject.net/news/asset1', title: 'Asset 1', description: 'term1', - id: '1' + id: '1', + closedAt: Date.now() }, { url: 'https://coralproject.net/news/asset2', title: 'Asset 2', - description: 'term2' + description: 'term2', + closedAt: null } ]); }); @@ -81,6 +83,38 @@ describe('/api/v1/assets', () => { }); }); + it('should return only closed assets', () => { + return chai.request(app) + .get('/api/v1/assets?filter=closed') + .set(passport.inject({roles: ['admin']})) + .then((res) => { + const body = res.body; + + expect(body).to.have.property('count', 1); + expect(body).to.have.property('result'); + + const assets = body.result; + + expect(assets[0]).to.have.property('title', 'Asset 1'); + }); + }); + + it('should return only opened assets', () => { + return chai.request(app) + .get('/api/v1/assets?filter=open') + .set(passport.inject({roles: ['admin']})) + .then((res) => { + const body = res.body; + + expect(body).to.have.property('count', 1); + expect(body).to.have.property('result'); + + const assets = body.result; + + expect(assets[0]).to.have.property('title', 'Asset 2'); + }); + }); + }); describe('#put', () => { From 979b54166bbb3060b3944d612f4bf66e332a6ebc Mon Sep 17 00:00:00 2001 From: David Jay Date: Fri, 16 Dec 2016 16:24:32 -0500 Subject: [PATCH 14/24] Updating search with delay. --- client/coral-admin/src/actions/assets.js | 4 +-- .../src/containers/Streams/Streams.js | 35 +++++++++++++------ .../coral-admin/src/services/talk-adapter.js | 4 +-- 3 files changed, 29 insertions(+), 14 deletions(-) diff --git a/client/coral-admin/src/actions/assets.js b/client/coral-admin/src/actions/assets.js index b13454a21..df2e1bd60 100644 --- a/client/coral-admin/src/actions/assets.js +++ b/client/coral-admin/src/actions/assets.js @@ -8,6 +8,6 @@ export const updateAssetState = (id, closedAt) => (dispatch) => { dispatch({type: UPDATE_ASSET_STATE, id, closedAt}); }; -export const fetchAssets = (skip, limit, search, sort) => (dispatch) => { - dispatch({type: FETCH_ASSETS, skip, limit, search, sort}); +export const fetchAssets = (skip, limit, search, sort, filter) => (dispatch) => { + dispatch({type: FETCH_ASSETS, skip, limit, search, sort, filter}); }; diff --git a/client/coral-admin/src/containers/Streams/Streams.js b/client/coral-admin/src/containers/Streams/Streams.js index 5d8508f33..58c1c9b61 100644 --- a/client/coral-admin/src/containers/Streams/Streams.js +++ b/client/coral-admin/src/containers/Streams/Streams.js @@ -19,8 +19,9 @@ class Streams extends Component { state = { search: '', sort: 'desc', - statusFilter: 'all', - statusMenus: {} + filter: 'all', + statusMenus: {}, + timer: null } componentDidMount () { @@ -28,8 +29,22 @@ class Streams extends Component { } onSettingChange = (setting) => (e) => { + let options = this.state; this.setState({[setting]: e.target.value}); - this.props.fetchAssets(0, limit, this.state.search, this.state.sort); + options[setting] = e.target.value; + this.props.fetchAssets(0, limit, options.search, options.sort, options.filter); + } + + onSearchChange = (e) => { + this.setState({search: e.target.value}); + this.setState((prevState) => { + clearTimeout(prevState.timer); + const fetchAssets = this.props.fetchAssets; + prevState.timer = setTimeout(() => { + fetchAssets(0, limit, this.state.search, this.state.sort, this.state.filter); + }, 350); + return prevState; + }); } renderDate = (date) => { @@ -74,7 +89,7 @@ class Streams extends Component { } render () { - const {searchTerm, sortBy, statusFilter} = this.state; + const {search, sort, filter} = this.state; const {assets} = this.props; return
    @@ -84,9 +99,9 @@ class Streams extends Component {
    @@ -94,9 +109,9 @@ class Streams extends Component {
    {lang.t('streams.stream-status')}
    + onChange={this.onSettingChange('filter')}> {lang.t('streams.all')} {lang.t('streams.open')} {lang.t('streams.closed')} @@ -104,9 +119,9 @@ class Streams extends Component {
    {lang.t('streams.sort-by')}
    + onChange={this.onSettingChange('sort')}> {lang.t('streams.newest')} {lang.t('streams.oldest')} diff --git a/client/coral-admin/src/services/talk-adapter.js b/client/coral-admin/src/services/talk-adapter.js index 67835e30d..fcc334953 100644 --- a/client/coral-admin/src/services/talk-adapter.js +++ b/client/coral-admin/src/services/talk-adapter.js @@ -102,8 +102,8 @@ const userStatusUpdate = (store, status, userId, commentId) => { // Fetch a page of assets // Get comments to fill each of the three lists on the mod queue const fetchAssets = (store, action) => { - const {skip, limit, search} = action; - return coralApi(`/assets?skip=${skip}&limit=${limit}&search=${search}`) + const {skip, limit, sort, search, filter} = action; + return coralApi(`/assets?skip=${skip}&limit=${limit}&sort=${sort}&search=${search}&filter=${filter}`) .then(({result, count}) => /* Post comments and users to redux store. Actions will be posted when they are needed. */ store.dispatch({type: FETCH_ASSETS_SUCCESS, From 0d2d6b52a5d0468d020f672745844dfacb474ed8 Mon Sep 17 00:00:00 2001 From: David Jay Date: Fri, 16 Dec 2016 17:07:59 -0500 Subject: [PATCH 15/24] Adding pagination. --- .../src/containers/Community/Community.js | 2 +- .../src/containers/Streams/Streams.js | 19 +++++++++++++++++-- .../components}/Pager.css | 0 .../components}/Pager.js | 0 4 files changed, 18 insertions(+), 3 deletions(-) rename client/{coral-admin/src/containers/Community => coral-ui/components}/Pager.css (100%) rename client/{coral-admin/src/containers/Community => coral-ui/components}/Pager.js (100%) diff --git a/client/coral-admin/src/containers/Community/Community.js b/client/coral-admin/src/containers/Community/Community.js index e798266f0..286a7f364 100644 --- a/client/coral-admin/src/containers/Community/Community.js +++ b/client/coral-admin/src/containers/Community/Community.js @@ -7,7 +7,7 @@ import styles from './Community.css'; import Table from './Table'; import Loading from './Loading'; import NoResults from './NoResults'; -import Pager from './Pager'; +import Pager from 'coral-ui/components/Pager'; const lang = new I18n(translations); diff --git a/client/coral-admin/src/containers/Streams/Streams.js b/client/coral-admin/src/containers/Streams/Streams.js index 58c1c9b61..4841d2a1b 100644 --- a/client/coral-admin/src/containers/Streams/Streams.js +++ b/client/coral-admin/src/containers/Streams/Streams.js @@ -11,8 +11,9 @@ import { DataTable, TableHeader } from 'react-mdl'; +import Pager from 'coral-ui/components/Pager'; -const limit = 25; +const limit = 10; class Streams extends Component { @@ -21,7 +22,8 @@ class Streams extends Component { sort: 'desc', filter: 'all', statusMenus: {}, - timer: null + timer: null, + page: 0 } componentDidMount () { @@ -88,10 +90,18 @@ class Streams extends Component {
    ; } + onPageClick = (page) => { + this.setState({page}); + const {search, sort, filter} = this.state; + this.props.fetchAssets((page - 1) * limit, limit, search, sort, filter); + } + render () { const {search, sort, filter} = this.state; const {assets} = this.props; + console.log(assets); + return
    @@ -139,6 +149,11 @@ class Streams extends Component { {lang.t('streams.status')} +
    ; } diff --git a/client/coral-admin/src/containers/Community/Pager.css b/client/coral-ui/components/Pager.css similarity index 100% rename from client/coral-admin/src/containers/Community/Pager.css rename to client/coral-ui/components/Pager.css diff --git a/client/coral-admin/src/containers/Community/Pager.js b/client/coral-ui/components/Pager.js similarity index 100% rename from client/coral-admin/src/containers/Community/Pager.js rename to client/coral-ui/components/Pager.js From c34bf5036e10348796485af8643a52004a176437 Mon Sep 17 00:00:00 2001 From: David Jay Date: Fri, 16 Dec 2016 17:20:31 -0500 Subject: [PATCH 16/24] Updating page count. --- client/coral-admin/src/containers/Streams/Streams.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/coral-admin/src/containers/Streams/Streams.js b/client/coral-admin/src/containers/Streams/Streams.js index 4841d2a1b..55fe10fc2 100644 --- a/client/coral-admin/src/containers/Streams/Streams.js +++ b/client/coral-admin/src/containers/Streams/Streams.js @@ -13,7 +13,7 @@ import { } from 'react-mdl'; import Pager from 'coral-ui/components/Pager'; -const limit = 10; +const limit = 25; class Streams extends Component { From dc966afe8e0c5d81f62b6f006657b1969b678366 Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Fri, 16 Dec 2016 17:06:56 -0700 Subject: [PATCH 17/24] adjusted query style --- routes/api/assets/index.js | 42 +++++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/routes/api/assets/index.js b/routes/api/assets/index.js index a661d64e8..e92eab72e 100644 --- a/routes/api/assets/index.js +++ b/routes/api/assets/index.js @@ -16,36 +16,47 @@ router.get('/', (req, res, next) => { search = '' } = req.query; - const assets = (filter, search) => { + const FilterOpenAssets = (query, filter) => { switch(filter) { case 'open': - return Asset.search(search) - .find({ - $or: [ - {closedAt: null}, - {closedAt: {$gt: Date.now()}} - ] - }); + return query.merge({ + $or: [ + { + closedAt: null + }, + { + closedAt: { + $gt: Date.now() + } + } + ] + }); case 'closed': - return Asset.search(search) - .find({ - closedAt: {$lt: Date.now()} - }); + return query.merge({ + closedAt: { + $lt: Date.now() + } + }); default: - return Asset.search(search); + return query; } }; // Find all the assets. Promise.all([ - assets(filter, search) + + // Find the actuall assets. + FilterOpenAssets(Asset.search(search), filter) .sort({[field]: (sort === 'asc') ? 1 : -1}) .skip(parseInt(skip)) .limit(parseInt(limit)), - assets(filter, search) + + // Get the count of actual assets. + FilterOpenAssets(Asset.search(search), filter) .count() ]) .then(([result, count]) => { + // Send back the asset data. res.json({ result, @@ -124,7 +135,6 @@ router.put('/:asset_id/status', (req, res, next) => { } }) .then(() => { - res.status(204).json(); }) .catch((err) => { From 29fa26260c4817e0a0db4cb7915a1e0edda5a217 Mon Sep 17 00:00:00 2001 From: David Jay Date: Wed, 21 Dec 2016 11:39:21 -0800 Subject: [PATCH 18/24] Handling undefined values in fetchAssets call. --- client/coral-admin/src/actions/assets.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/coral-admin/src/actions/assets.js b/client/coral-admin/src/actions/assets.js index fce4bf4e9..30bd7909b 100644 --- a/client/coral-admin/src/actions/assets.js +++ b/client/coral-admin/src/actions/assets.js @@ -16,7 +16,7 @@ import coralApi from '../../../coral-framework/helpers/response'; // Get comments to fill each of the three lists on the mod queue export const fetchAssets = (skip, limit, sort, search, filter) => (dispatch) => { dispatch({type: FETCH_ASSETS}); - return coralApi(`/assets?skip=${skip}&limit=${limit}&sort=${sort}&search=${search}&filter=${filter}`) + return coralApi(`/assets?skip=${skip || ''}&limit=${limit || ''}&sort=${sort || ''}&search=${search || ''}&filter=${filter || ''}`) .then(({result, count}) => dispatch({type: FETCH_ASSETS_SUCCESS, assets: result, From cfed42be2c09936f51292eb4749fd8c2e37c7a02 Mon Sep 17 00:00:00 2001 From: David Jay Date: Wed, 21 Dec 2016 12:05:25 -0800 Subject: [PATCH 19/24] Correcting bug in fetchAssets. --- client/coral-admin/src/actions/assets.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/coral-admin/src/actions/assets.js b/client/coral-admin/src/actions/assets.js index 30bd7909b..92f511d5f 100644 --- a/client/coral-admin/src/actions/assets.js +++ b/client/coral-admin/src/actions/assets.js @@ -14,7 +14,7 @@ import coralApi from '../../../coral-framework/helpers/response'; // Fetch a page of assets // Get comments to fill each of the three lists on the mod queue -export const fetchAssets = (skip, limit, sort, search, filter) => (dispatch) => { +export const fetchAssets = (skip, limit, search, sort, filter) => (dispatch) => { dispatch({type: FETCH_ASSETS}); return coralApi(`/assets?skip=${skip || ''}&limit=${limit || ''}&sort=${sort || ''}&search=${search || ''}&filter=${filter || ''}`) .then(({result, count}) => From c867ae8eeb8ae4c11d14f456ff2158cb75303fc4 Mon Sep 17 00:00:00 2001 From: David Jay Date: Wed, 21 Dec 2016 12:11:42 -0800 Subject: [PATCH 20/24] Removing Next and Prev from pager and updating tests. --- client/coral-ui/components/Pager.js | 5 ++--- tests/routes/api/assets/index.js | 1 - 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/client/coral-ui/components/Pager.js b/client/coral-ui/components/Pager.js index 3184cfca0..3d96660ad 100644 --- a/client/coral-ui/components/Pager.js +++ b/client/coral-ui/components/Pager.js @@ -12,7 +12,7 @@ const Pager = ({totalPages, page, onNewPageHandler}) => (
      { - (totalPages > page) ? + (totalPages > page && totalPages >= 1) ?
    • onNewPageHandler(page - 1)}> @@ -23,7 +23,7 @@ const Pager = ({totalPages, page, onNewPageHandler}) => ( } {Rows(page, totalPages, onNewPageHandler)} { - (page < totalPages) ? + (page < totalPages && totalPages >= 1) ?
    • onNewPageHandler(page + 1)}> @@ -42,4 +42,3 @@ Pager.propTypes = { }; export default Pager; - diff --git a/tests/routes/api/assets/index.js b/tests/routes/api/assets/index.js index da011bf7b..3354f9671 100644 --- a/tests/routes/api/assets/index.js +++ b/tests/routes/api/assets/index.js @@ -18,7 +18,6 @@ describe('/api/v1/assets', () => { url: 'https://coralproject.net/news/asset1', title: 'Asset 1', description: 'term1', - id: '1', closedAt: Date.now() }, { From 7cbd06834f9cbc7f31cff74153fbde249414b57b Mon Sep 17 00:00:00 2001 From: Riley Davis Date: Wed, 21 Dec 2016 16:39:29 -0700 Subject: [PATCH 21/24] set defaults on fetchAssets --- client/coral-admin/src/actions/assets.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/coral-admin/src/actions/assets.js b/client/coral-admin/src/actions/assets.js index 92f511d5f..930feba5e 100644 --- a/client/coral-admin/src/actions/assets.js +++ b/client/coral-admin/src/actions/assets.js @@ -14,9 +14,9 @@ import coralApi from '../../../coral-framework/helpers/response'; // Fetch a page of assets // Get comments to fill each of the three lists on the mod queue -export const fetchAssets = (skip, limit, search, sort, filter) => (dispatch) => { +export const fetchAssets = (skip = '', limit = '', search = '', sort = '', filter = '') => (dispatch) => { dispatch({type: FETCH_ASSETS}); - return coralApi(`/assets?skip=${skip || ''}&limit=${limit || ''}&sort=${sort || ''}&search=${search || ''}&filter=${filter || ''}`) + return coralApi(`/assets?skip=${skip}&limit=${limit}&sort=${sort}&search=${search}&filter=${filter}`) .then(({result, count}) => dispatch({type: FETCH_ASSETS_SUCCESS, assets: result, From 7fc3dffc77252413e1cfc90b53cde43182d29e74 Mon Sep 17 00:00:00 2001 From: Riley Davis Date: Wed, 21 Dec 2016 16:49:53 -0700 Subject: [PATCH 22/24] reload assets after updating state --- client/coral-admin/src/containers/Streams/Streams.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/client/coral-admin/src/containers/Streams/Streams.js b/client/coral-admin/src/containers/Streams/Streams.js index 55fe10fc2..559621fc5 100644 --- a/client/coral-admin/src/containers/Streams/Streams.js +++ b/client/coral-admin/src/containers/Streams/Streams.js @@ -60,7 +60,11 @@ class Streams extends Component { prev.statusMenus[id] = false; return prev; }); - this.props.updateAssetState(id, closeStream ? Date.now() : null); + this.props.updateAssetState(id, closeStream ? Date.now() : null) + .then(() => { + const {search, sort, filter, page} = this.state; + this.props.fetchAssets(page, limit, search, sort, filter); + }); } else { this.setState(prev => { prev.statusMenus[id] = true; @@ -169,9 +173,7 @@ const mapDispatchToProps = (dispatch) => { fetchAssets: (...args) => { dispatch(fetchAssets.apply(this, args)); }, - updateAssetState: (...args) => { - dispatch(updateAssetState.apply(this, args)); - } + updateAssetState: (...args) => dispatch(updateAssetState.apply(this, args)) }; }; From b8b47e9c2c987382e27fe872e0e4f8b6e46cb7dc Mon Sep 17 00:00:00 2001 From: Riley Davis Date: Wed, 21 Dec 2016 16:56:29 -0700 Subject: [PATCH 23/24] normalize constant names --- client/coral-admin/src/actions/assets.js | 16 ++++++++-------- client/coral-admin/src/constants/assets.js | 8 ++++---- client/coral-admin/src/reducers/assets.js | 4 ++-- tests/client/coral-admin/actions/assets.js | 16 ++++++++-------- tests/client/coral-admin/reducers/assets.js | 4 ++-- 5 files changed, 24 insertions(+), 24 deletions(-) diff --git a/client/coral-admin/src/actions/assets.js b/client/coral-admin/src/actions/assets.js index 930feba5e..f431f1ad6 100644 --- a/client/coral-admin/src/actions/assets.js +++ b/client/coral-admin/src/actions/assets.js @@ -1,10 +1,10 @@ import { - FETCH_ASSETS, + FETCH_ASSETS_REQUEST, FETCH_ASSETS_SUCCESS, - FETCH_ASSETS_FAILED, - UPDATE_ASSET_STATE, + FETCH_ASSETS_FAILURE, + UPDATE_ASSET_STATE_REQUEST, UPDATE_ASSET_STATE_SUCCESS, - UPDATE_ASSET_STATE_FAILED + UPDATE_ASSET_STATE_FAILURE } from '../constants/assets'; import coralApi from '../../../coral-framework/helpers/response'; @@ -15,22 +15,22 @@ import coralApi from '../../../coral-framework/helpers/response'; // Fetch a page of assets // Get comments to fill each of the three lists on the mod queue export const fetchAssets = (skip = '', limit = '', search = '', sort = '', filter = '') => (dispatch) => { - dispatch({type: FETCH_ASSETS}); + dispatch({type: FETCH_ASSETS_REQUEST}); return coralApi(`/assets?skip=${skip}&limit=${limit}&sort=${sort}&search=${search}&filter=${filter}`) .then(({result, count}) => dispatch({type: FETCH_ASSETS_SUCCESS, assets: result, count })) - .catch(error => dispatch({type: FETCH_ASSETS_FAILED, error})); + .catch(error => dispatch({type: FETCH_ASSETS_FAILURE, error})); }; // Update an asset state // Get comments to fill each of the three lists on the mod queue export const updateAssetState = (id, closedAt) => (dispatch) => { - dispatch({type: UPDATE_ASSET_STATE}); + dispatch({type: UPDATE_ASSET_STATE_REQUEST}); return coralApi(`/assets/${id}/status`, {method: 'PUT', body: {closedAt}}) .then(() => dispatch({type: UPDATE_ASSET_STATE_SUCCESS})) - .catch(error => dispatch({type: UPDATE_ASSET_STATE_FAILED, error})); + .catch(error => dispatch({type: UPDATE_ASSET_STATE_FAILURE, error})); }; diff --git a/client/coral-admin/src/constants/assets.js b/client/coral-admin/src/constants/assets.js index 8927b351d..0a2ecf73c 100644 --- a/client/coral-admin/src/constants/assets.js +++ b/client/coral-admin/src/constants/assets.js @@ -1,6 +1,6 @@ -export const FETCH_ASSETS = 'FETCH_ASSETS'; +export const FETCH_ASSETS_REQUEST = 'FETCH_ASSETS_REQUEST'; export const FETCH_ASSETS_SUCCESS = 'FETCH_ASSETS_SUCCESS'; -export const FETCH_ASSETS_FAILED = 'FETCH_ASSETS_FAILED'; -export const UPDATE_ASSET_STATE = 'UPDATE_ASSET_STATE'; +export const FETCH_ASSETS_FAILURE = 'FETCH_ASSETS_FAILURE'; +export const UPDATE_ASSET_STATE_REQUEST = 'UPDATE_ASSET_STATE_REQUEST'; export const UPDATE_ASSET_STATE_SUCCESS = 'UPDATE_ASSET_STATE_SUCCESS'; -export const UPDATE_ASSET_STATE_FAILED = 'UPDATE_ASSET_STATE_FAILED'; +export const UPDATE_ASSET_STATE_FAILURE = 'UPDATE_ASSET_STATE_FAILURE'; diff --git a/client/coral-admin/src/reducers/assets.js b/client/coral-admin/src/reducers/assets.js index f18aaec33..77d0bf081 100644 --- a/client/coral-admin/src/reducers/assets.js +++ b/client/coral-admin/src/reducers/assets.js @@ -1,5 +1,5 @@ import {Map, List, fromJS} from 'immutable'; -import {FETCH_ASSETS_SUCCESS, UPDATE_ASSET_STATE} from '../constants/assets'; +import {FETCH_ASSETS_SUCCESS, UPDATE_ASSET_STATE_REQUEST} from '../constants/assets'; const initialState = Map({ byId: Map(), @@ -10,7 +10,7 @@ export default (state = initialState, action) => { switch (action.type) { case FETCH_ASSETS_SUCCESS: return replaceAssets(action, state); - case UPDATE_ASSET_STATE: + case UPDATE_ASSET_STATE_REQUEST: return state.setIn(['byId', action.id, 'closedAt'], action.closedAt); default: return state; } diff --git a/tests/client/coral-admin/actions/assets.js b/tests/client/coral-admin/actions/assets.js index 55addb805..24a28daef 100644 --- a/tests/client/coral-admin/actions/assets.js +++ b/tests/client/coral-admin/actions/assets.js @@ -30,7 +30,7 @@ describe('Asset actions', () => { fetchMock.restore(); }); - describe('FETCH_ASSETS', () => { + describe('FETCH_ASSETS_REQUEST', () => { it('should fetch a list of assets', () => { @@ -41,7 +41,7 @@ describe('Asset actions', () => { return actions.fetchAssets(2, 20)(store.dispatch) .then(() => { - expect(store.getActions()[0]).to.have.property('type', 'FETCH_ASSETS'); + expect(store.getActions()[0]).to.have.property('type', 'FETCH_ASSETS_REQUEST'); expect(store.getActions()[1]).to.have.property('type', 'FETCH_ASSETS_SUCCESS'); expect(store.getActions()[1]).to.have.property('count', 2); expect(store.getActions()[1]).to.have.property('assets'). @@ -55,13 +55,13 @@ describe('Asset actions', () => { return actions.fetchAssets(2, 20)(store.dispatch) .then(() => { - expect(store.getActions()[0]).to.have.property('type', 'FETCH_ASSETS'); - expect(store.getActions()[1]).to.have.property('type', 'FETCH_ASSETS_FAILED'); + expect(store.getActions()[0]).to.have.property('type', 'FETCH_ASSETS_REQUEST'); + expect(store.getActions()[1]).to.have.property('type', 'FETCH_ASSETS_FAILURE'); }); }); }); - describe('UPDATE_ASSET_STATE', () => { + describe('UPDATE_ASSET_STATE_REQUEST', () => { it('should update an asset', () => { @@ -69,7 +69,7 @@ describe('Asset actions', () => { return actions.updateAssetState('123', 'status', 'open')(store.dispatch) .then(() => { - expect(store.getActions()[0]).to.have.property('type', 'UPDATE_ASSET_STATE'); + expect(store.getActions()[0]).to.have.property('type', 'UPDATE_ASSET_STATE_REQUEST'); expect(store.getActions()[1]).to.have.property('type', 'UPDATE_ASSET_STATE_SUCCESS'); }); @@ -81,8 +81,8 @@ describe('Asset actions', () => { return actions.updateAssetState('123', 'status', 'open')(store.dispatch) .then(() => { - expect(store.getActions()[0]).to.have.property('type', 'UPDATE_ASSET_STATE'); - expect(store.getActions()[1]).to.have.property('type', 'UPDATE_ASSET_STATE_FAILED'); + expect(store.getActions()[0]).to.have.property('type', 'UPDATE_ASSET_STATE_REQUEST'); + expect(store.getActions()[1]).to.have.property('type', 'UPDATE_ASSET_STATE_FAILURE'); }); }); }); diff --git a/tests/client/coral-admin/reducers/assets.js b/tests/client/coral-admin/reducers/assets.js index 60972f47a..753061612 100644 --- a/tests/client/coral-admin/reducers/assets.js +++ b/tests/client/coral-admin/reducers/assets.js @@ -36,10 +36,10 @@ describe ('assetsReducer', () => { }); }); - describe('UPDATE_ASSET_STATE', () => { + describe('UPDATE_ASSET_STATE_REQUEST', () => { it('should update the state of a particular asset', () => { const action = { - type: 'UPDATE_ASSET_STATE', + type: 'UPDATE_ASSET_STATE_REQUEST', id: '123', closedAt: null }; From 0fc3e09c74cb7ba240a6f35387efdc89f83af98d Mon Sep 17 00:00:00 2001 From: David Jay Date: Wed, 21 Dec 2016 18:08:57 -0800 Subject: [PATCH 24/24] Removing unused log statement and combining setState functions. --- client/coral-admin/src/containers/Streams/Streams.js | 6 ++---- client/coral-ui/components/Pager.js | 4 ++-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/client/coral-admin/src/containers/Streams/Streams.js b/client/coral-admin/src/containers/Streams/Streams.js index 55fe10fc2..49c0b49cc 100644 --- a/client/coral-admin/src/containers/Streams/Streams.js +++ b/client/coral-admin/src/containers/Streams/Streams.js @@ -38,12 +38,12 @@ class Streams extends Component { } onSearchChange = (e) => { - this.setState({search: e.target.value}); this.setState((prevState) => { + prevState.search = e.target.value; clearTimeout(prevState.timer); const fetchAssets = this.props.fetchAssets; prevState.timer = setTimeout(() => { - fetchAssets(0, limit, this.state.search, this.state.sort, this.state.filter); + fetchAssets(0, limit, e.target.value, this.state.sort, this.state.filter); }, 350); return prevState; }); @@ -100,8 +100,6 @@ class Streams extends Component { const {search, sort, filter} = this.state; const {assets} = this.props; - console.log(assets); - return
      diff --git a/client/coral-ui/components/Pager.js b/client/coral-ui/components/Pager.js index 3d96660ad..fca20b0db 100644 --- a/client/coral-ui/components/Pager.js +++ b/client/coral-ui/components/Pager.js @@ -12,7 +12,7 @@ const Pager = ({totalPages, page, onNewPageHandler}) => (
        { - (totalPages > page && totalPages >= 1) ? + (totalPages > page && totalPages > 1) ?
      • onNewPageHandler(page - 1)}> @@ -23,7 +23,7 @@ const Pager = ({totalPages, page, onNewPageHandler}) => ( } {Rows(page, totalPages, onNewPageHandler)} { - (page < totalPages && totalPages >= 1) ? + (page < totalPages && totalPages > 1) ?
      • onNewPageHandler(page + 1)}>