From 57d27420ca75a330e89cc48441cc668e73cbf805 Mon Sep 17 00:00:00 2001 From: mgabdev <> Date: Fri, 7 Aug 2020 17:59:39 -0500 Subject: [PATCH] Updated group timelines and sorting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit • Updated: - group timelines and sorting --- app/javascript/gabsocial/actions/streaming.js | 2 +- app/javascript/gabsocial/actions/timelines.js | 4 +- .../group_timeline_sort_options_popover.js | 6 +- ...group_timeline_sort_top_options_popover.js | 7 +- .../features/group_collection_timeline.js | 145 +++++++++++++++--- .../gabsocial/features/group_timeline.js | 91 ++++++++--- app/javascript/gabsocial/pages/groups_page.js | 28 +++- app/models/group_categories.rb | 8 +- 8 files changed, 222 insertions(+), 69 deletions(-) diff --git a/app/javascript/gabsocial/actions/streaming.js b/app/javascript/gabsocial/actions/streaming.js index 2469970d..ea43aecd 100644 --- a/app/javascript/gabsocial/actions/streaming.js +++ b/app/javascript/gabsocial/actions/streaming.js @@ -55,7 +55,7 @@ export const connectProStream = () => connectTimelineStream('pro', 'pro'); export const connectHashtagStream = (id, tag, accept) => connectTimelineStream(`hashtag:${id}`, `hashtag&tag=${tag}`, null, accept); export const connectListStream = id => connectTimelineStream(`list:${id}`, `list&list=${id}`); export const connectGroupStream = id => connectTimelineStream(`group:${id}`, `group&group=${id}`); -export const connectGroupCollectionStream = (id) => connectTimelineStream(`group:collection:${id}`, `group&group:collection=${id}`); +export const connectGroupCollectionStream = (collectionType, sortBy) => connectTimelineStream(`group_collection:${collectionType}:${sortBy}`, `group_collection&group_collection=${collectionType}`); export const connectStatusUpdateStream = () => { return connectStream('statuscard', null, (dispatch, getState) => { diff --git a/app/javascript/gabsocial/actions/timelines.js b/app/javascript/gabsocial/actions/timelines.js index f1392fd0..798e0e54 100644 --- a/app/javascript/gabsocial/actions/timelines.js +++ b/app/javascript/gabsocial/actions/timelines.js @@ -172,8 +172,8 @@ export const expandAccountTimeline = (accountId, { maxId, withReplies, commentsO export const expandAccountFeaturedTimeline = accountId => expandTimeline(`account:${accountId}:pinned`, `/api/v1/accounts/${accountId}/statuses`, { pinned: true }); export const expandAccountMediaTimeline = (accountId, { maxId, limit, mediaType } = {}) => expandTimeline(`account:${accountId}:media`, `/api/v1/accounts/${accountId}/statuses`, { max_id: maxId, only_media: true, limit: limit || 20, media_type: mediaType }); export const expandListTimeline = (id, { maxId } = {}, done = noOp) => expandTimeline(`list:${id}`, `/api/v1/timelines/list/${id}`, { max_id: maxId }, done); -export const expandGroupTimeline = (id, { sortBy, maxId } = {}, done = noOp) => expandTimeline(`group:${id}`, `/api/v1/timelines/group/${id}`, { sort_by: sortBy, max_id: maxId }, done); -export const expandGroupCollectionTimeline = (collectionType, { sortBy, maxId } = {}, done = noOp) => expandTimeline(`group:collection:${collectionType}`, `/api/v1/timelines/group_collection/${collectionType}`, { sort_by: sortBy, max_id: maxId }, done); +export const expandGroupTimeline = (id, { sortBy, maxId, onlyMedia } = {}, done = noOp) => expandTimeline(`group:${id}`, `/api/v1/timelines/group/${id}`, { sort_by: sortBy, max_id: maxId, only_media: onlyMedia }, done); +export const expandGroupCollectionTimeline = (collectionType, { sortBy, maxId } = {}, done = noOp) => expandTimeline(`group_collection:${collectionType}`, `/api/v1/timelines/group_collection/${collectionType}`, { sort_by: sortBy, max_id: maxId }, done); export const expandHashtagTimeline = (hashtag, { maxId, tags } = {}, done = noOp) => { return expandTimeline(`hashtag:${hashtag}`, `/api/v1/timelines/tag/${hashtag}`, { max_id: maxId, diff --git a/app/javascript/gabsocial/components/popover/group_timeline_sort_options_popover.js b/app/javascript/gabsocial/components/popover/group_timeline_sort_options_popover.js index 6fe7d4a3..f40f480d 100644 --- a/app/javascript/gabsocial/components/popover/group_timeline_sort_options_popover.js +++ b/app/javascript/gabsocial/components/popover/group_timeline_sort_options_popover.js @@ -24,8 +24,8 @@ const mapStateToProps = (state) => ({ }) const mapDispatchToProps = (dispatch) => ({ - onSort(sort, options) { - dispatch(setGroupTimelineSort(sort, options)) + onSort(sort) { + dispatch(setGroupTimelineSort(sort)) dispatch(closePopover()) }, onClosePopover: () => dispatch(closePopover()), @@ -46,7 +46,7 @@ class GroupTimelineSortOptionsPopover extends PureComponent { } handleOnClick = (type) => { - this.props.onSort(type, this.props.options) + this.props.onSort(type) } handleOnClosePopover = () => { diff --git a/app/javascript/gabsocial/components/popover/group_timeline_sort_top_options_popover.js b/app/javascript/gabsocial/components/popover/group_timeline_sort_top_options_popover.js index 798f9e85..bfbadae6 100644 --- a/app/javascript/gabsocial/components/popover/group_timeline_sort_top_options_popover.js +++ b/app/javascript/gabsocial/components/popover/group_timeline_sort_top_options_popover.js @@ -24,8 +24,8 @@ const mapStateToProps = (state) => ({ }) const mapDispatchToProps = (dispatch) => ({ - onSort(sort, options) { - dispatch(setGroupTimelineTopSort(sort, options)) + onSort(sort) { + dispatch(setGroupTimelineTopSort(sort)) dispatch(closePopover()) }, onClosePopover: () => dispatch(closePopover()), @@ -42,11 +42,10 @@ class GroupTimelineSortTopOptionsPopover extends PureComponent { isXS: PropTypes.bool, onClosePopover: PropTypes.func.isRequired, onSort: PropTypes.func.isRequired, - options: PropTypes.object.isRequired, } handleOnClick = (type) => { - this.props.onSort(type, this.props.options) + this.props.onSort(type) } handleOnClosePopover = () => { diff --git a/app/javascript/gabsocial/features/group_collection_timeline.js b/app/javascript/gabsocial/features/group_collection_timeline.js index c771033d..459876e6 100644 --- a/app/javascript/gabsocial/features/group_collection_timeline.js +++ b/app/javascript/gabsocial/features/group_collection_timeline.js @@ -1,63 +1,145 @@ import { Fragment } from 'react' import { injectIntl, defineMessages } from 'react-intl' +import { List as ImmutableList } from 'immutable' import { me } from '../initial_state' -import { GROUP_TIMELINE_SORTING_TYPE_TOP } from '../constants' import { connectGroupCollectionStream } from '../actions/streaming' -import { expandGroupCollectionTimeline } from '../actions/timelines' +import { + clearTimeline, + expandGroupCollectionTimeline, +} from '../actions/timelines' +import { + setGroupTimelineSort, + setGroupTimelineTopSort, +} from '../actions/groups' +import { + GROUP_TIMELINE_SORTING_TYPE_TOP, + GROUP_TIMELINE_SORTING_TYPE_TOP_OPTION_WEEKLY, + GROUP_TIMELINE_SORTING_TYPE_NEWEST, +} from '../constants' +import getSortBy from '../utils/group_sort_by' +import Text from '../components/text' import StatusList from '../components/status_list' import GroupSortBlock from '../components/group_sort_block' +import GroupsCollection from './groups_collection' const messages = defineMessages({ empty: { id: 'empty_column.group_collection_timeline', defaultMessage: 'There are no gabs to display.' }, }) -const mapStateToProps = (state) => ({ - sortByValue: state.getIn(['group_lists', 'sortByValue']), - sortByTopValue: state.getIn(['group_lists', 'sortByTopValue']), +const mapStateToProps = (state, { collectionType }) => { + + let dontShowGroupSort = true + try { + dontShowGroupSort = !!me && collectionType === 'member' && state.getIn(['timelines', `group_collection:${collectionType}`, 'items'], ImmutableList()).count() === 0 + } catch (error) { + // + } + + return { + dontShowGroupSort, + sortByValue: state.getIn(['group_lists', 'sortByValue']), + sortByTopValue: state.getIn(['group_lists', 'sortByTopValue']), + } +} + +const mapDispatchToProps = (dispatch) => ({ + onConnectGroupCollectionStream(collectionType, sortBy) { + dispatch(connectGroupCollectionStream(collectionType, sortBy)) + }, + onClearTimeline(timeline) { + dispatch(clearTimeline(timeline)) + }, + onExpandGroupCollectionTimeline(collectionType, options) { + dispatch(expandGroupCollectionTimeline(collectionType, options)) + }, + setFeaturedTop() { + dispatch(setGroupTimelineSort(GROUP_TIMELINE_SORTING_TYPE_TOP)) + dispatch(setGroupTimelineTopSort(GROUP_TIMELINE_SORTING_TYPE_TOP_OPTION_WEEKLY)) + }, + setMemberNewest() { + dispatch(setGroupTimelineSort(GROUP_TIMELINE_SORTING_TYPE_NEWEST)) + }, }) export default @injectIntl -@connect(mapStateToProps) +@connect(mapStateToProps, mapDispatchToProps) class GroupCollectionTimeline extends PureComponent { static propTypes = { params: PropTypes.object.isRequired, - dispatch: PropTypes.func.isRequired, + onConnectGroupCollectionStream: PropTypes.func.isRequired, + onClearTimeline: PropTypes.func.isRequired, + onExpandGroupCollectionTimeline: PropTypes.func.isRequired, + setFeaturedTop: PropTypes.func.isRequired, + setMemberNewest: PropTypes.func.isRequired, intl: PropTypes.object.isRequired, + collectionType: PropTypes.string.isRequired, sortByValue: PropTypes.string.isRequired, sortByTopValue: PropTypes.string, + hasStatuses: PropTypes.bool.isRequired, + } + + state = { + //keep track of loads for if no user, + //only allow 2 loads before showing sign up msg + loadCount: 0, + } + + _unsubscribe() { + if (this.disconnect && !!me) { + this.disconnect() + this.disconnect = null + } + } + + _subscribe = () => { + if (!!me) { + const { + collectionType, + sortByValue, + sortByTopValue, + } = this.props + + if (collectionType === 'member' && sortByValue === 'new') { + const sortBy = getSortBy(sortByValue, sortByTopValue) + this.disconnect = this.props.onConnectGroupCollectionStream(collectionType, sortBy) + } + } } componentDidMount() { const { collectionType, - dispatch, sortByValue, sortByTopValue, } = this.props - const sortBy = sortByValue === GROUP_TIMELINE_SORTING_TYPE_TOP ? `${sortByValue}_${sortByTopValue}` : sortByValue - const options = { sortBy } - - dispatch(expandGroupCollectionTimeline(collectionType, options)) + if (this.props.collectionType === 'featured' && sortByValue !== GROUP_TIMELINE_SORTING_TYPE_TOP) { + this.props.setFeaturedTop() + } else if (!!me && this.props.collectionType === 'member' && sortByValue !== GROUP_TIMELINE_SORTING_TYPE_NEWEST) { + this.props.setMemberNewest() + } else { + const sortBy = getSortBy(sortByValue, sortByTopValue) + this.props.onExpandGroupCollectionTimeline(collectionType, { sortBy }) - if (!!me) { - this.disconnect = dispatch(connectGroupCollectionStream(collectionType)) + this._subscribe() } } componentDidUpdate(prevProps) { - if (prevProps.sortByValue !== this.props.sortByValue || prevProps.sortByTopValue !== this.props.sortByTopValue) { - this.handleLoadMore() + if (prevProps.sortByValue !== this.props.sortByValue || + prevProps.sortByTopValue !== this.props.sortByTopValue || + prevProps.collectionType !== this.props.collectionType) { + this._unsubscribe() + this._subscribe() + this.props.onClearTimeline(`group_collection:${prevProps.collectionType}`) + this.handleLoadMore() } } componentWillUnmount() { - if (this.disconnect && !!me) { - this.disconnect() - this.disconnect = null - } + this._unsubscribe() } handleLoadMore = (maxId) => { @@ -67,26 +149,39 @@ class GroupCollectionTimeline extends PureComponent { sortByTopValue, } = this.props - const sortBy = sortByValue === GROUP_TIMELINE_SORTING_TYPE_TOP ? `${sortByValue}_${sortByTopValue}` : sortByValue + const sortBy = getSortBy(sortByValue, sortByTopValue) const options = { sortBy, maxId } - this.props.dispatch(expandGroupCollectionTimeline(collectionType, options)) + this.props.onExpandGroupCollectionTimeline(collectionType, options) } render() { const { collectionType, intl, + dontShowGroupSort, } = this.props + const emptyMessage = !!me && collectionType === 'member' ? ( +