diff --git a/src/actions/index.js b/src/actions/index.js index fed6e37..9a08d1e 100644 --- a/src/actions/index.js +++ b/src/actions/index.js @@ -8,7 +8,7 @@ import { setToggle } from './toggle'; import { activateTrack, activateIteratedPlaylistTrack, activateIteratedStreamTrack, addTrackToPlaylist, removeTrackFromPlaylist, clearPlaylist, togglePlayTrack, toggleShuffleMode, toggleRepeatMode, changeVolume } from './player'; import { openComments, fetchComments } from './comments'; import { filterDuration, filterName } from './filter'; -import { sortStream } from './sort'; +import { sortStream, dateSortStream } from './sort'; /* eslint-enable max-len */ export { @@ -35,6 +35,7 @@ export { filterDuration, filterName, sortStream, + dateSortStream, toggleShuffleMode, toggleRepeatMode, changeVolume, diff --git a/src/actions/sort/index.js b/src/actions/sort/index.js index ac791b7..0ef250f 100644 --- a/src/actions/sort/index.js +++ b/src/actions/sort/index.js @@ -6,3 +6,9 @@ export function sortStream(sortType) { sortType }; } +export function dateSortStream(dateSortType) { + return { + type: actionTypes.DATE_SORT_STREAM, + dateSortType + }; +} diff --git a/src/components/Activities/index.js b/src/components/Activities/index.js index a328b4f..d3675ee 100644 --- a/src/components/Activities/index.js +++ b/src/components/Activities/index.js @@ -27,11 +27,12 @@ function Activities({ entities, activeFilter, activeSort, + activeDateSort }) { const matchedEntities = getMatchedEntities(ids, entities); const filteredEntities = matchedEntities.filter(activeFilter); - const sortedEntities = activeSort(filteredEntities); - + const sortedDateEntities = activeDateSort(filteredEntities); + const sortedEntities = activeSort(sortedDateEntities); return (
@@ -51,6 +52,7 @@ Activities.propTypes = { entities: PropTypes.object, activeFilter: PropTypes.func, activeSort: PropTypes.func, + activeDateSort: PropTypes.func, }; export default withLoadingSpinner(withFetchOnScroll(Activities)); diff --git a/src/components/Browse/index.js b/src/components/Browse/index.js index 782ff29..14c076a 100644 --- a/src/components/Browse/index.js +++ b/src/components/Browse/index.js @@ -2,7 +2,7 @@ import PropTypes from 'prop-types'; import React from 'react'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; -import { SORT_FUNCTIONS } from '../../constants/sort'; +import { SORT_FUNCTIONS, DATE_SORT_FUNCTIONS } from '../../constants/sort'; import { DURATION_FILTER_FUNCTIONS } from '../../constants/durationFilter'; import * as actions from '../../actions/index'; import * as requestTypes from '../../constants/requestTypes'; @@ -62,7 +62,8 @@ class Browse extends React.Component { } render() { - const { browseActivities, match, requestsInProcess, trackEntities, activeFilter, activeSort } = this.props; + const { browseActivities, match, requestsInProcess, trackEntities, + activeFilter, activeSort, activeDateSort } = this.props; const genre = match.params.genre; return (
@@ -73,6 +74,7 @@ class Browse extends React.Component { entities={trackEntities} activeFilter={activeFilter} activeSort={activeSort} + activeDateSort={activeDateSort} scrollFunction={this.fetchActivitiesByGenre} /> @@ -99,6 +101,7 @@ function mapStateToProps(state) { userEntities: state.entities.users, activeFilter: getAndCombined(filters), activeSort: SORT_FUNCTIONS[state.sort.sortType], + activeDateSort: DATE_SORT_FUNCTIONS[state.sort.dateSortType], }; } diff --git a/src/components/Dashboard/index.js b/src/components/Dashboard/index.js index 8a83cbb..076cf50 100644 --- a/src/components/Dashboard/index.js +++ b/src/components/Dashboard/index.js @@ -20,10 +20,12 @@ class Dashboard extends React.Component { } return ( +
+
diff --git a/src/components/DateSort/index.js b/src/components/DateSort/index.js new file mode 100644 index 0000000..76d97d4 --- /dev/null +++ b/src/components/DateSort/index.js @@ -0,0 +1,69 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import map from '../../services/map'; +import classNames from 'classnames'; +import { connect } from 'react-redux'; +import { bindActionCreators } from 'redux'; +import * as actions from '../../actions/index'; +import * as dateSortTypes from '../../constants/dateSortTypes'; +import { DATE_SORT_NAMES } from '../../constants/sort'; +import ButtonActive from '../../components/ButtonActive'; +import ButtonInline from '../../components/ButtonInline'; + +function hasActiveSort(activeDateSort) { + return activeDateSort !== dateSortTypes.NONE; +} + +function DateSort({ + activeDateSort, + onSort, + }) { + const sortIconClass = classNames( + 'stream-interaction-icon', + { + 'stream-interaction-icon-active': hasActiveSort(activeDateSort) + } + ); + + return ( +
+
+ onSort(dateSortTypes.NONE)}> + + +
+
+ { + map((value, key) => { + return ( + + onSort(value)} isActive={value === activeDateSort}> + {DATE_SORT_NAMES[value]} + + + ); + }, dateSortTypes) + } +
+
+ ); +} + +function mapStateToProps(state) { + return { + activeDateSort: state.sort.dateSortType + }; +} + +function mapDispatchToProps(dispatch) { + return { + onSort: (dateSortType) => bindActionCreators(actions.dateSortStream, dispatch)(dateSortType) + }; +} + +DateSort.propTypes = { + activeDateSort: PropTypes.string, + onSort: PropTypes.func +}; + +export default connect(mapStateToProps, mapDispatchToProps)(DateSort); diff --git a/src/components/StreamActivities/index.js b/src/components/StreamActivities/index.js index 49a8065..b818b62 100644 --- a/src/components/StreamActivities/index.js +++ b/src/components/StreamActivities/index.js @@ -11,7 +11,7 @@ import LoadingSpinner from '../../components/LoadingSpinner'; import StreamInteractions from '../../components/StreamInteractions'; import { DURATION_FILTER_FUNCTIONS } from '../../constants/durationFilter'; import { getTracknameFilter } from '../../constants/nameFilter'; -import { SORT_FUNCTIONS } from '../../constants/sort'; +import { SORT_FUNCTIONS, DATE_SORT_FUNCTIONS } from '../../constants/sort'; import { getArtistFilter } from '../../constants/artistFilter'; function StreamActivities({ @@ -21,6 +21,7 @@ function StreamActivities({ trackEntities, activeFilter, activeSort, + activeDateSort, onFetchActivities, }) { return ( @@ -32,6 +33,7 @@ function StreamActivities({ ids={activities} activeFilter={activeFilter} activeSort={activeSort} + activeDateSort={activeDateSort} scrollFunction={() => onFetchActivities(null, nextHref)} /> @@ -55,6 +57,7 @@ function mapStateToProps(state) { nextHref: state.paginate[paginateLinkTypes.ACTIVITIES], activeFilter: getAndCombined(filters), activeSort: SORT_FUNCTIONS[state.sort.sortType], + activeDateSort: DATE_SORT_FUNCTIONS[state.sort.dateSortType], }; } @@ -71,6 +74,7 @@ StreamActivities.propTypes = { nextHref: PropTypes.string, activeFilter: PropTypes.func, activeSort: PropTypes.func, + activeDateSort: PropTypes.func, onFetchActivities: PropTypes.func, }; diff --git a/src/components/StreamInteractions/index.js b/src/components/StreamInteractions/index.js index cba4acb..ac78941 100644 --- a/src/components/StreamInteractions/index.js +++ b/src/components/StreamInteractions/index.js @@ -2,6 +2,7 @@ import React from 'react'; import FilterDuration from '../../components/FilterDuration'; import FilterName from '../../components/FilterName'; import Sort from '../../components/Sort'; +import DateSort from '../../components/DateSort'; function StreamInteractions() { return ( @@ -12,6 +13,9 @@ function StreamInteractions() {
+
+ +
diff --git a/src/components/Track/index.js b/src/components/Track/index.js index bbefd6d..6508126 100644 --- a/src/components/Track/index.js +++ b/src/components/Track/index.js @@ -17,6 +17,7 @@ function mapStateToProps(state, props) { isPlaying: state.player.isPlaying, activeTrackId: state.player.activeTrackId, activeSortType: state.sort.sortType, + activeDateSortType: state.sort.dateSortType, activeDurationFilterType: state.filter.durationFilterType, }; } diff --git a/src/components/Track/stream.js b/src/components/Track/stream.js index 1dc1e97..ac4efb7 100644 --- a/src/components/Track/stream.js +++ b/src/components/Track/stream.js @@ -2,6 +2,7 @@ import PropTypes from 'prop-types'; import React from 'react'; import classNames from 'classnames'; import * as sortTypes from '../../constants/sortTypes'; +import * as dateSortTypes from '../../constants/dateSortTypes'; import * as filterTypes from '../../constants/filterTypes'; import WaveformSc from '../../components/WaveformSc'; import TrackActions from '../../components/TrackActions'; @@ -26,6 +27,18 @@ function Duration({ duration, isActive }) { ); } +function Created({ created_at, isActive }) { + const durationClass = classNames({ + 'active-duration-filter': isActive + }); + + return ( + + {fromNow(created_at)} + + ); +} + function TrackStream({ activity, activeTrackId, @@ -34,6 +47,7 @@ function TrackStream({ typeReposts, typeTracks, activeSortType, + activeDateSortType, activeDurationFilterType, onActivateTrack, }) { @@ -50,7 +64,6 @@ function TrackStream({ permalink_url, created_at } = activity; - const userEntity = userEntities[user]; const { avatar_url, username } = userEntity; @@ -123,7 +136,12 @@ function TrackStream({ / {fromNow(created_at)}
+ /> / + +
@@ -159,6 +177,7 @@ TrackStream.propTypes = { isPlaying: PropTypes.bool, activeTrackId: PropTypes.number, activeSortType: PropTypes.string, + activeDateSortType: PropTypes.string, activeDurationFilterType: PropTypes.string, onActivateTrack: PropTypes.func, }; diff --git a/src/constants/actionTypes.js b/src/constants/actionTypes.js index 1778a9f..b4ab108 100644 --- a/src/constants/actionTypes.js +++ b/src/constants/actionTypes.js @@ -46,5 +46,6 @@ export const FILTER_DURATION = 'FILTER_DURATION'; export const FILTER_NAME = 'FILTER_NAME'; export const SORT_STREAM = 'SORT_STREAM'; +export const DATE_SORT_STREAM = 'DATE_SORT_STREAM'; export const SET_SELECTED_GENRE = 'SET_SELECTED_GENRE'; diff --git a/src/constants/dateSortTypes.js b/src/constants/dateSortTypes.js new file mode 100644 index 0000000..6c6e696 --- /dev/null +++ b/src/constants/dateSortTypes.js @@ -0,0 +1,5 @@ +export const NONE = 'NONE'; + +export const PAST_6MONTH = 'PAST_6MONTH'; +export const PAST_YEAR = 'PAST_YEAR'; +export const OLDER = 'OLDER'; diff --git a/src/constants/sort.js b/src/constants/sort.js index d7af9d1..ecf14b2 100644 --- a/src/constants/sort.js +++ b/src/constants/sort.js @@ -1,5 +1,7 @@ import { orderBy } from 'lodash'; import * as sortTypes from '../constants/sortTypes'; +import * as dateSortTypes from './dateSortTypes'; +import moment from 'moment'; const SORT_NAMES = { [sortTypes.NONE]: 'NONE', @@ -7,6 +9,18 @@ const SORT_NAMES = { [sortTypes.SORT_FAVORITES]: 'FAVORITES', [sortTypes.SORT_REPOSTS]: 'REPOSTS', }; +const DATE_SORT_NAMES = { + [dateSortTypes.NONE]: 'NONE', + [dateSortTypes.PAST_6MONTH]: 'PAST 6 MONTHS', + [dateSortTypes.PAST_YEAR]: 'PAST YEAR', + [dateSortTypes.OLDER]: 'OLDER' +}; +const DATE_SORT_FUNCTIONS = { + [dateSortTypes.NONE]: (objs) => objs, + [dateSortTypes.PAST_6MONTH]: (activities) => sortByMonth(activities), + [dateSortTypes.PAST_YEAR]: (activities) => sortByYear(activities), + [dateSortTypes.OLDER]: (activities) => sortByOld(activities), +}; const SORT_FUNCTIONS = { [sortTypes.NONE]: (objs) => objs, @@ -15,6 +29,42 @@ const SORT_FUNCTIONS = { [sortTypes.SORT_REPOSTS]: (activities) => sortByReposts(activities), }; +function sortDates(dt1, dt2) { + const dateA = new Date(dt1.created_at); + const dateB = new Date(dt2.created_at); + return dateA - dateB; +} + +function sortByMonth(activities) { + const sortDt = new moment().subtract(6, 'months').date(1); + const act = activities.filter(obj => { + return moment(obj.created_at) >= sortDt; + }); + return act.sort((a, b) => { + return sortDates(a, b); + }); +} + +function sortByYear(activities) { + const sortDt = new moment().subtract(1, 'year').date(1); + const act = activities.filter(obj => { + return moment(obj.created_at) >= sortDt; + }); + return act.sort((a, b) => { + return sortDates(a, b); + }); +} + +function sortByOld(activities) { + const sortDt = new moment().subtract(1, 'year').date(1); + const act = activities.filter(obj => { + return moment(obj.created_at) < sortDt; + }); + return act.sort((a, b) => { + return sortDates(a, b); + }); +} + function sortByPlays(activities) { return orderBy(activities, (activity) => activity.playback_count, 'desc'); } @@ -30,4 +80,6 @@ function sortByReposts(activities) { export { SORT_NAMES, SORT_FUNCTIONS, + DATE_SORT_NAMES, + DATE_SORT_FUNCTIONS }; diff --git a/src/reducers/sort/index.js b/src/reducers/sort/index.js index 38e1f2c..e49fb6a 100644 --- a/src/reducers/sort/index.js +++ b/src/reducers/sort/index.js @@ -1,14 +1,18 @@ import * as actionTypes from '../../constants/actionTypes'; import * as sortTypes from '../../constants/sortTypes'; +import * as dateSortTypes from '../../constants/dateSortTypes'; const initialState = { sortType: sortTypes.NONE, + dateSortType: dateSortTypes.NONE, }; export default function(state = initialState, action) { switch (action.type) { case actionTypes.SORT_STREAM: return setSortStream(state, action.sortType); + case actionTypes.DATE_SORT_STREAM: + return setDateSortStream(state, action.dateSortType); } return state; } @@ -16,3 +20,6 @@ export default function(state = initialState, action) { function setSortStream(state, sortType) { return { ...state, sortType }; } +function setDateSortStream(state, dateSortType) { + return { ...state, dateSortType }; +} diff --git a/styles/components/dashboard.scss b/styles/components/dashboard.scss index 4fb38bd..5ecda7c 100644 --- a/styles/components/dashboard.scss +++ b/styles/components/dashboard.scss @@ -10,6 +10,8 @@ &-side { flex: 1; + float:right; + width:25%; } -} \ No newline at end of file +}