Skip to content

Commit 002d010

Browse files
author
VikasDayananda
committed
Sort by Date Implemented #96
1 parent 4b185e5 commit 002d010

File tree

15 files changed

+187
-9
lines changed

15 files changed

+187
-9
lines changed

src/actions/index.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { setToggle } from './toggle';
88
import { activateTrack, activateIteratedPlaylistTrack, activateIteratedStreamTrack, addTrackToPlaylist, removeTrackFromPlaylist, clearPlaylist, togglePlayTrack, toggleShuffleMode, toggleRepeatMode, changeVolume } from './player';
99
import { openComments, fetchComments } from './comments';
1010
import { filterDuration, filterName } from './filter';
11-
import { sortStream } from './sort';
11+
import { sortStream, dateSortStream } from './sort';
1212
/* eslint-enable max-len */
1313

1414
export {
@@ -35,6 +35,7 @@ export {
3535
filterDuration,
3636
filterName,
3737
sortStream,
38+
dateSortStream,
3839
toggleShuffleMode,
3940
toggleRepeatMode,
4041
changeVolume,

src/actions/sort/index.js

+6
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,9 @@ export function sortStream(sortType) {
66
sortType
77
};
88
}
9+
export function dateSortStream(dateSortType) {
10+
return {
11+
type: actionTypes.DATE_SORT_STREAM,
12+
dateSortType
13+
};
14+
}

src/components/Activities/index.js

+4-2
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,12 @@ function Activities({
2727
entities,
2828
activeFilter,
2929
activeSort,
30+
activeDateSort
3031
}) {
3132
const matchedEntities = getMatchedEntities(ids, entities);
3233
const filteredEntities = matchedEntities.filter(activeFilter);
33-
const sortedEntities = activeSort(filteredEntities);
34-
34+
const sortedDateEntities = activeDateSort(filteredEntities);
35+
const sortedEntities = activeSort(sortedDateEntities);
3536
return (
3637
<div>
3738
<div>
@@ -51,6 +52,7 @@ Activities.propTypes = {
5152
entities: PropTypes.object,
5253
activeFilter: PropTypes.func,
5354
activeSort: PropTypes.func,
55+
activeDateSort: PropTypes.func,
5456
};
5557

5658
export default withLoadingSpinner(withFetchOnScroll(Activities));

src/components/Browse/index.js

+5-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import PropTypes from 'prop-types';
22
import React from 'react';
33
import { connect } from 'react-redux';
44
import { bindActionCreators } from 'redux';
5-
import { SORT_FUNCTIONS } from '../../constants/sort';
5+
import { SORT_FUNCTIONS, DATE_SORT_FUNCTIONS } from '../../constants/sort';
66
import { DURATION_FILTER_FUNCTIONS } from '../../constants/durationFilter';
77
import * as actions from '../../actions/index';
88
import * as requestTypes from '../../constants/requestTypes';
@@ -62,7 +62,8 @@ class Browse extends React.Component {
6262
}
6363

6464
render() {
65-
const { browseActivities, match, requestsInProcess, trackEntities, activeFilter, activeSort } = this.props;
65+
const { browseActivities, match, requestsInProcess, trackEntities,
66+
activeFilter, activeSort, activeDateSort } = this.props;
6667
const genre = match.params.genre;
6768
return (
6869
<div className="browse">
@@ -73,6 +74,7 @@ class Browse extends React.Component {
7374
entities={trackEntities}
7475
activeFilter={activeFilter}
7576
activeSort={activeSort}
77+
activeDateSort={activeDateSort}
7678
scrollFunction={this.fetchActivitiesByGenre}
7779
/>
7880
<LoadingSpinner isLoading={!!(requestsInProcess[requestTypes.GENRES] && browseActivities[genre])} />
@@ -99,6 +101,7 @@ function mapStateToProps(state) {
99101
userEntities: state.entities.users,
100102
activeFilter: getAndCombined(filters),
101103
activeSort: SORT_FUNCTIONS[state.sort.sortType],
104+
activeDateSort: DATE_SORT_FUNCTIONS[state.sort.dateSortType],
102105
};
103106
}
104107

src/components/Dashboard/index.js

+2
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,12 @@ class Dashboard extends React.Component {
2020
}
2121

2222
return (
23+
<div>
2324
<div className="dashboard">
2425
<div className="dashboard-main">
2526
<StreamActivities />
2627
</div>
28+
</div>
2729
<div className="dashboard-side">
2830
<FollowingsList />
2931
<FollowersList />

src/components/DateSort/index.js

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import PropTypes from 'prop-types';
2+
import React from 'react';
3+
import map from '../../services/map';
4+
import classNames from 'classnames';
5+
import { connect } from 'react-redux';
6+
import { bindActionCreators } from 'redux';
7+
import * as actions from '../../actions/index';
8+
import * as dateSortTypes from '../../constants/dateSortTypes';
9+
import { DATE_SORT_NAMES } from '../../constants/sort';
10+
import ButtonActive from '../../components/ButtonActive';
11+
import ButtonInline from '../../components/ButtonInline';
12+
13+
function hasActiveSort(activeDateSort) {
14+
return activeDateSort !== dateSortTypes.NONE;
15+
}
16+
17+
function DateSort({
18+
activeDateSort,
19+
onSort,
20+
}) {
21+
const sortIconClass = classNames(
22+
'stream-interaction-icon',
23+
{
24+
'stream-interaction-icon-active': hasActiveSort(activeDateSort)
25+
}
26+
);
27+
28+
return (
29+
<div className="stream-interaction">
30+
<div className={sortIconClass} title={'Sort Stream'}>
31+
<ButtonInline onClick={() => onSort(dateSortTypes.NONE)}>
32+
<i className="fa fa-sort"/>
33+
</ButtonInline>
34+
</div>
35+
<div className="stream-interaction-content">
36+
{
37+
map((value, key) => {
38+
return (
39+
<span key={key}>
40+
<ButtonActive onClick={() => onSort(value)} isActive={value === activeDateSort}>
41+
{DATE_SORT_NAMES[value]}
42+
</ButtonActive>
43+
</span>
44+
);
45+
}, dateSortTypes)
46+
}
47+
</div>
48+
</div>
49+
);
50+
}
51+
52+
function mapStateToProps(state) {
53+
return {
54+
activeDateSort: state.sort.dateSortType
55+
};
56+
}
57+
58+
function mapDispatchToProps(dispatch) {
59+
return {
60+
onSort: (dateSortType) => bindActionCreators(actions.dateSortStream, dispatch)(dateSortType)
61+
};
62+
}
63+
64+
DateSort.propTypes = {
65+
activeDateSort: PropTypes.string,
66+
onSort: PropTypes.func
67+
};
68+
69+
export default connect(mapStateToProps, mapDispatchToProps)(DateSort);

src/components/StreamActivities/index.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import LoadingSpinner from '../../components/LoadingSpinner';
1111
import StreamInteractions from '../../components/StreamInteractions';
1212
import { DURATION_FILTER_FUNCTIONS } from '../../constants/durationFilter';
1313
import { getTracknameFilter } from '../../constants/nameFilter';
14-
import { SORT_FUNCTIONS } from '../../constants/sort';
14+
import { SORT_FUNCTIONS, DATE_SORT_FUNCTIONS } from '../../constants/sort';
1515
import { getArtistFilter } from '../../constants/artistFilter';
1616

1717
function StreamActivities({
@@ -21,6 +21,7 @@ function StreamActivities({
2121
trackEntities,
2222
activeFilter,
2323
activeSort,
24+
activeDateSort,
2425
onFetchActivities,
2526
}) {
2627
return (
@@ -32,6 +33,7 @@ function StreamActivities({
3233
ids={activities}
3334
activeFilter={activeFilter}
3435
activeSort={activeSort}
36+
activeDateSort={activeDateSort}
3537
scrollFunction={() => onFetchActivities(null, nextHref)}
3638
/>
3739
<LoadingSpinner isLoading={!!(requestInProcess && activities)} />
@@ -55,6 +57,7 @@ function mapStateToProps(state) {
5557
nextHref: state.paginate[paginateLinkTypes.ACTIVITIES],
5658
activeFilter: getAndCombined(filters),
5759
activeSort: SORT_FUNCTIONS[state.sort.sortType],
60+
activeDateSort: DATE_SORT_FUNCTIONS[state.sort.dateSortType],
5861
};
5962
}
6063

@@ -71,6 +74,7 @@ StreamActivities.propTypes = {
7174
nextHref: PropTypes.string,
7275
activeFilter: PropTypes.func,
7376
activeSort: PropTypes.func,
77+
activeDateSort: PropTypes.func,
7478
onFetchActivities: PropTypes.func,
7579
};
7680

src/components/StreamInteractions/index.js

+4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React from 'react';
22
import FilterDuration from '../../components/FilterDuration';
33
import FilterName from '../../components/FilterName';
44
import Sort from '../../components/Sort';
5+
import DateSort from '../../components/DateSort';
56

67
function StreamInteractions() {
78
return (
@@ -12,6 +13,9 @@ function StreamInteractions() {
1213
<div className="stream-interactions-item">
1314
<Sort />
1415
</div>
16+
<div className="stream-interactions-item">
17+
<DateSort />
18+
</div>
1519
<div className="stream-interactions-item">
1620
<FilterName />
1721
</div>

src/components/Track/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ function mapStateToProps(state, props) {
1717
isPlaying: state.player.isPlaying,
1818
activeTrackId: state.player.activeTrackId,
1919
activeSortType: state.sort.sortType,
20+
activeDateSortType: state.sort.dateSortType,
2021
activeDurationFilterType: state.filter.durationFilterType,
2122
};
2223
}

src/components/Track/stream.js

+21-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import PropTypes from 'prop-types';
22
import React from 'react';
33
import classNames from 'classnames';
44
import * as sortTypes from '../../constants/sortTypes';
5+
import * as dateSortTypes from '../../constants/dateSortTypes';
56
import * as filterTypes from '../../constants/filterTypes';
67
import WaveformSc from '../../components/WaveformSc';
78
import TrackActions from '../../components/TrackActions';
@@ -26,6 +27,18 @@ function Duration({ duration, isActive }) {
2627
);
2728
}
2829

30+
function Created({ created_at, isActive }) {
31+
const durationClass = classNames({
32+
'active-duration-filter': isActive
33+
});
34+
35+
return (
36+
<span className={durationClass}>
37+
{fromNow(created_at)}
38+
</span>
39+
);
40+
}
41+
2942
function TrackStream({
3043
activity,
3144
activeTrackId,
@@ -34,6 +47,7 @@ function TrackStream({
3447
typeReposts,
3548
typeTracks,
3649
activeSortType,
50+
activeDateSortType,
3751
activeDurationFilterType,
3852
onActivateTrack,
3953
}) {
@@ -50,7 +64,6 @@ function TrackStream({
5064
permalink_url,
5165
created_at
5266
} = activity;
53-
5467
const userEntity = userEntities[user];
5568
const { avatar_url, username } = userEntity;
5669

@@ -123,7 +136,12 @@ function TrackStream({
123136
<Duration
124137
duration={duration}
125138
isActive={activeDurationFilterType !== filterTypes.ALL}
126-
/> / {fromNow(created_at)}</div>
139+
/> /
140+
<Created
141+
created_at={created_at}
142+
isActive={activeDateSortType !== dateSortTypes.NONE}
143+
/>
144+
</div>
127145
</div>
128146
<div className="track-content-footer">
129147
<div>
@@ -159,6 +177,7 @@ TrackStream.propTypes = {
159177
isPlaying: PropTypes.bool,
160178
activeTrackId: PropTypes.number,
161179
activeSortType: PropTypes.string,
180+
activeDateSortType: PropTypes.string,
162181
activeDurationFilterType: PropTypes.string,
163182
onActivateTrack: PropTypes.func,
164183
};

src/constants/actionTypes.js

+1
Original file line numberDiff line numberDiff line change
@@ -46,5 +46,6 @@ export const FILTER_DURATION = 'FILTER_DURATION';
4646
export const FILTER_NAME = 'FILTER_NAME';
4747

4848
export const SORT_STREAM = 'SORT_STREAM';
49+
export const DATE_SORT_STREAM = 'DATE_SORT_STREAM';
4950

5051
export const SET_SELECTED_GENRE = 'SET_SELECTED_GENRE';

src/constants/dateSortTypes.js

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export const NONE = 'NONE';
2+
3+
export const PAST_6MONTH = 'PAST_6MONTH';
4+
export const PAST_YEAR = 'PAST_YEAR';
5+
export const OLDER = 'OLDER';

src/constants/sort.js

+52
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,26 @@
11
import { orderBy } from 'lodash';
22
import * as sortTypes from '../constants/sortTypes';
3+
import * as dateSortTypes from './dateSortTypes';
4+
import moment from 'moment';
35

46
const SORT_NAMES = {
57
[sortTypes.NONE]: 'NONE',
68
[sortTypes.SORT_PLAYS]: 'PLAYS',
79
[sortTypes.SORT_FAVORITES]: 'FAVORITES',
810
[sortTypes.SORT_REPOSTS]: 'REPOSTS',
911
};
12+
const DATE_SORT_NAMES = {
13+
[dateSortTypes.NONE]: 'NONE',
14+
[dateSortTypes.PAST_6MONTH]: 'PAST 6 MONTHS',
15+
[dateSortTypes.PAST_YEAR]: 'PAST YEAR',
16+
[dateSortTypes.OLDER]: 'OLDER'
17+
};
18+
const DATE_SORT_FUNCTIONS = {
19+
[dateSortTypes.NONE]: (objs) => objs,
20+
[dateSortTypes.PAST_6MONTH]: (activities) => sortByMonth(activities),
21+
[dateSortTypes.PAST_YEAR]: (activities) => sortByYear(activities),
22+
[dateSortTypes.OLDER]: (activities) => sortByOld(activities),
23+
};
1024

1125
const SORT_FUNCTIONS = {
1226
[sortTypes.NONE]: (objs) => objs,
@@ -15,6 +29,42 @@ const SORT_FUNCTIONS = {
1529
[sortTypes.SORT_REPOSTS]: (activities) => sortByReposts(activities),
1630
};
1731

32+
function sortDates(dt1, dt2) {
33+
const dateA = new Date(dt1.created_at);
34+
const dateB = new Date(dt2.created_at);
35+
return dateA - dateB;
36+
}
37+
38+
function sortByMonth(activities) {
39+
const sortDt = new moment().subtract(6, 'months').date(1);
40+
const act = activities.filter(obj => {
41+
return moment(obj.created_at) >= sortDt;
42+
});
43+
return act.sort((a, b) => {
44+
return sortDates(a, b);
45+
});
46+
}
47+
48+
function sortByYear(activities) {
49+
const sortDt = new moment().subtract(1, 'year').date(1);
50+
const act = activities.filter(obj => {
51+
return moment(obj.created_at) >= sortDt;
52+
});
53+
return act.sort((a, b) => {
54+
return sortDates(a, b);
55+
});
56+
}
57+
58+
function sortByOld(activities) {
59+
const sortDt = new moment().subtract(1, 'year').date(1);
60+
const act = activities.filter(obj => {
61+
return moment(obj.created_at) < sortDt;
62+
});
63+
return act.sort((a, b) => {
64+
return sortDates(a, b);
65+
});
66+
}
67+
1868
function sortByPlays(activities) {
1969
return orderBy(activities, (activity) => activity.playback_count, 'desc');
2070
}
@@ -30,4 +80,6 @@ function sortByReposts(activities) {
3080
export {
3181
SORT_NAMES,
3282
SORT_FUNCTIONS,
83+
DATE_SORT_NAMES,
84+
DATE_SORT_FUNCTIONS
3385
};

0 commit comments

Comments
 (0)