Updated group sorting in frontend
• Updated: - group sorting in frontend
This commit is contained in:
parent
6328b21186
commit
f9f2744a63
|
@ -9,6 +9,7 @@ import { fetchRelationships } from './accounts';
|
|||
import {
|
||||
GROUP_LIST_SORTING_TYPE_ALPHABETICAL,
|
||||
GROUP_LIST_SORTING_TYPE_MOST_POPULAR,
|
||||
GROUP_TIMELINE_SORTING_TYPE_TOP,
|
||||
} from '../constants'
|
||||
|
||||
export const GROUP_FETCH_REQUEST = 'GROUP_FETCH_REQUEST';
|
||||
|
@ -619,14 +620,14 @@ export function groupsSort(tab, groupIds) {
|
|||
}
|
||||
}
|
||||
|
||||
export const setGroupTimelineSort = (sortValue) => (dispatch) => {
|
||||
export const setGroupTimelineSort = (sortValue, options) => (dispatch, getState) => {
|
||||
dispatch({
|
||||
type: GROUP_TIMELINE_SORT,
|
||||
sortValue,
|
||||
})
|
||||
}
|
||||
|
||||
export const setGroupTimelineTopSort = (sortValue) => (dispatch) => {
|
||||
export const setGroupTimelineTopSort = (sortValue, options) => (dispatch, getState) => {
|
||||
dispatch({
|
||||
type: GROUP_TIMELINE_TOP_SORT,
|
||||
sortValue,
|
||||
|
|
|
@ -32,15 +32,17 @@ const mapStateToProps = (state) => ({
|
|||
})
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
onOpenSortingOptions(targetRef) {
|
||||
onOpenSortingOptions(targetRef, options) {
|
||||
dispatch(openPopover(POPOVER_GROUP_TIMELINE_SORT_OPTIONS, {
|
||||
targetRef,
|
||||
options,
|
||||
position: 'bottom',
|
||||
}))
|
||||
},
|
||||
onOpenSortingTopOptions(targetRef) {
|
||||
onOpenSortingTopOptions(targetRef, options) {
|
||||
dispatch(openPopover(POPOVER_GROUP_TIMELINE_SORT_TOP_OPTIONS, {
|
||||
targetRef,
|
||||
options,
|
||||
position: 'bottom',
|
||||
}))
|
||||
},
|
||||
|
@ -53,6 +55,8 @@ class GroupSortBlock extends PureComponent {
|
|||
|
||||
static propTypes = {
|
||||
intl: PropTypes.object.isRequired,
|
||||
groupId: PropTypes.string,
|
||||
collectionType: PropTypes.string,
|
||||
sortByValue: PropTypes.string.isRequired,
|
||||
sortByTopValue: PropTypes.string,
|
||||
onOpenSortingOptions: PropTypes.func.isRequired,
|
||||
|
@ -60,11 +64,17 @@ class GroupSortBlock extends PureComponent {
|
|||
}
|
||||
|
||||
handleOnClickValue = (btn) => {
|
||||
this.props.onOpenSortingOptions(btn)
|
||||
this.props.onOpenSortingOptions(btn, {
|
||||
groupId: this.props.groupId,
|
||||
collectionType: this.props.collectionType,
|
||||
})
|
||||
}
|
||||
|
||||
handleOnClickSubValue = (btn) => {
|
||||
this.props.onOpenSortingTopOptions(btn)
|
||||
this.props.onOpenSortingTopOptions(btn, {
|
||||
groupId: this.props.groupId,
|
||||
collectionType: this.props.collectionType,
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { defineMessages, injectIntl } from 'react-intl'
|
||||
import isObject from 'lodash.isobject'
|
||||
import { closePopover } from '../../actions/popover'
|
||||
import { setGroupTimelineSort } from '../../actions/groups'
|
||||
import {
|
||||
|
@ -23,8 +24,8 @@ const mapStateToProps = (state) => ({
|
|||
})
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
onSort(sort) {
|
||||
dispatch(setGroupTimelineSort(sort))
|
||||
onSort(sort, options) {
|
||||
dispatch(setGroupTimelineSort(sort, options))
|
||||
dispatch(closePopover())
|
||||
},
|
||||
onClosePopover: () => dispatch(closePopover()),
|
||||
|
@ -41,10 +42,11 @@ class GroupTimelineSortOptionsPopover 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.onSort(type, this.props.options)
|
||||
}
|
||||
|
||||
handleOnClosePopover = () => {
|
||||
|
@ -56,8 +58,11 @@ class GroupTimelineSortOptionsPopover extends PureComponent {
|
|||
sorting,
|
||||
intl,
|
||||
isXS,
|
||||
options,
|
||||
} = this.props
|
||||
|
||||
const isFeaturedTimeline = isObject(options) && options.collectionType === 'featured'
|
||||
|
||||
const items = [
|
||||
{
|
||||
hideArrow: true,
|
||||
|
@ -65,22 +70,25 @@ class GroupTimelineSortOptionsPopover extends PureComponent {
|
|||
title: intl.formatMessage(messages.topTitle),
|
||||
subtitle: intl.formatMessage(messages.topSubtitle),
|
||||
onClick: () => this.handleOnClick(GROUP_TIMELINE_SORTING_TYPE_TOP),
|
||||
},
|
||||
{
|
||||
}
|
||||
]
|
||||
|
||||
if (!isFeaturedTimeline) {
|
||||
items.push({
|
||||
hideArrow: true,
|
||||
isActive: sorting === GROUP_TIMELINE_SORTING_TYPE_NEWEST,
|
||||
title: intl.formatMessage(messages.newTitle),
|
||||
subtitle: intl.formatMessage(messages.newSubtitle),
|
||||
onClick: () => this.handleOnClick(GROUP_TIMELINE_SORTING_TYPE_NEWEST),
|
||||
},
|
||||
{
|
||||
})
|
||||
items.push({
|
||||
hideArrow: true,
|
||||
isActive: sorting === GROUP_TIMELINE_SORTING_TYPE_RECENT_ACTIVITY,
|
||||
title: intl.formatMessage(messages.recentTitle),
|
||||
subtitle: intl.formatMessage(messages.recentSubtitle),
|
||||
onClick: () => this.handleOnClick(GROUP_TIMELINE_SORTING_TYPE_RECENT_ACTIVITY),
|
||||
},
|
||||
]
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<PopoverLayout
|
||||
|
|
|
@ -24,8 +24,8 @@ const mapStateToProps = (state) => ({
|
|||
})
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
onSort(sort) {
|
||||
dispatch(setGroupTimelineTopSort(sort))
|
||||
onSort(sort, options) {
|
||||
dispatch(setGroupTimelineTopSort(sort, options))
|
||||
dispatch(closePopover())
|
||||
},
|
||||
onClosePopover: () => dispatch(closePopover()),
|
||||
|
@ -42,10 +42,11 @@ 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.onSort(type, this.props.options)
|
||||
}
|
||||
|
||||
handleOnClosePopover = () => {
|
||||
|
|
|
@ -1,14 +1,17 @@
|
|||
import { Fragment } from 'react'
|
||||
import { injectIntl, defineMessages } from 'react-intl'
|
||||
import { me } from '../initial_state'
|
||||
import { GROUP_TIMELINE_SORTING_TYPE_TOP } from '../constants'
|
||||
import { connectGroupCollectionStream } from '../actions/streaming'
|
||||
import { expandGroupCollectionTimeline } from '../actions/timelines'
|
||||
import StatusList from '../components/status_list'
|
||||
import GroupSortBlock from '../components/group_sort_block'
|
||||
|
||||
const messages = defineMessages({
|
||||
empty: { id: 'empty_column.group_collection_timeline', defaultMessage: 'There are no gabs to display.' },
|
||||
})
|
||||
|
||||
const mapStateToProps = (state) = ({
|
||||
const mapStateToProps = (state) => ({
|
||||
sortByValue: state.getIn(['group_lists', 'sortByValue']),
|
||||
sortByTopValue: state.getIn(['group_lists', 'sortByTopValue']),
|
||||
})
|
||||
|
@ -27,15 +30,29 @@ class GroupCollectionTimeline extends PureComponent {
|
|||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { collectionType, dispatch } = this.props
|
||||
const {
|
||||
collectionType,
|
||||
dispatch,
|
||||
sortByValue,
|
||||
sortByTopValue,
|
||||
} = this.props
|
||||
|
||||
dispatch(expandGroupCollectionTimeline(collectionType))
|
||||
const sortBy = sortByValue === GROUP_TIMELINE_SORTING_TYPE_TOP ? `${sortByValue}_${sortByTopValue}` : sortByValue
|
||||
const options = { sortBy }
|
||||
|
||||
dispatch(expandGroupCollectionTimeline(collectionType, options))
|
||||
|
||||
if (!!me) {
|
||||
this.disconnect = dispatch(connectGroupCollectionStream(collectionType))
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
if (prevProps.sortByValue !== this.props.sortByValue || prevProps.sortByTopValue !== this.props.sortByTopValue) {
|
||||
this.handleLoadMore()
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.disconnect && !!me) {
|
||||
this.disconnect()
|
||||
|
@ -44,8 +61,16 @@ class GroupCollectionTimeline extends PureComponent {
|
|||
}
|
||||
|
||||
handleLoadMore = (maxId) => {
|
||||
const { collectionType } = this.props
|
||||
this.props.dispatch(expandGroupCollectionTimeline(collectionType, { maxId }))
|
||||
const {
|
||||
collectionType,
|
||||
sortByValue,
|
||||
sortByTopValue,
|
||||
} = this.props
|
||||
|
||||
const sortBy = sortByValue === GROUP_TIMELINE_SORTING_TYPE_TOP ? `${sortByValue}_${sortByTopValue}` : sortByValue
|
||||
const options = { sortBy, maxId }
|
||||
|
||||
this.props.dispatch(expandGroupCollectionTimeline(collectionType, options))
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -55,12 +80,15 @@ class GroupCollectionTimeline extends PureComponent {
|
|||
} = this.props
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<GroupSortBlock collectionType={collectionType} />
|
||||
<StatusList
|
||||
scrollKey={`group-collection-timeline-${collectionType}`}
|
||||
timelineId={`group:collection:${collectionType}`}
|
||||
onLoadMore={this.handleLoadMore}
|
||||
emptyMessage={intl.formatMessage(messages.empty)}
|
||||
/>
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
import { Fragment } from 'react'
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
import { injectIntl, defineMessages } from 'react-intl'
|
||||
import { me } from '../initial_state'
|
||||
import { GROUP_TIMELINE_SORTING_TYPE_TOP } from '../constants'
|
||||
import { connectGroupStream } from '../actions/streaming'
|
||||
import { expandGroupTimeline } from '../actions/timelines'
|
||||
import StatusList from '../components/status_list'
|
||||
import ColumnIndicator from '../components/column_indicator'
|
||||
import GroupSortBlock from '../components/group_sort_block'
|
||||
|
||||
const messages = defineMessages({
|
||||
empty: { id: 'empty_column.group', defaultMessage: 'There is nothing in this group yet.\nWhen members of this group post new statuses, they will appear here.' },
|
||||
|
@ -13,6 +16,8 @@ const messages = defineMessages({
|
|||
|
||||
const mapStateToProps = (state, props) => ({
|
||||
group: state.getIn(['groups', props.params.id]),
|
||||
sortByValue: state.getIn(['group_lists', 'sortByValue']),
|
||||
sortByTopValue: state.getIn(['group_lists', 'sortByTopValue']),
|
||||
})
|
||||
|
||||
export default
|
||||
|
@ -28,19 +33,34 @@ class GroupTimeline extends ImmutablePureComponent {
|
|||
PropTypes.bool,
|
||||
]),
|
||||
intl: PropTypes.object.isRequired,
|
||||
sortByValue: PropTypes.string.isRequired,
|
||||
sortByTopValue: PropTypes.string,
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { dispatch } = this.props
|
||||
const {
|
||||
dispatch,
|
||||
sortByValue,
|
||||
sortByTopValue,
|
||||
} = this.props
|
||||
const { id } = this.props.params
|
||||
|
||||
dispatch(expandGroupTimeline(id))
|
||||
const sortBy = sortByValue === GROUP_TIMELINE_SORTING_TYPE_TOP ? `${sortByValue}_${sortByTopValue}` : sortByValue
|
||||
const options = { sortBy }
|
||||
|
||||
dispatch(expandGroupTimeline(id, options))
|
||||
|
||||
if (!!me) {
|
||||
this.disconnect = dispatch(connectGroupStream(id))
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
if (prevProps.sortByValue !== this.props.sortByValue || prevProps.sortByTopValue !== this.props.sortByTopValue) {
|
||||
this.handleLoadMore()
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.disconnect && !!me) {
|
||||
this.disconnect()
|
||||
|
@ -48,9 +68,18 @@ class GroupTimeline extends ImmutablePureComponent {
|
|||
}
|
||||
}
|
||||
|
||||
handleLoadMore = maxId => {
|
||||
handleLoadMore = (maxId) => {
|
||||
const {
|
||||
dispatch,
|
||||
sortByValue,
|
||||
sortByTopValue,
|
||||
} = this.props
|
||||
const { id } = this.props.params
|
||||
this.props.dispatch(expandGroupTimeline(id, { maxId }))
|
||||
|
||||
const sortBy = sortByValue === GROUP_TIMELINE_SORTING_TYPE_TOP ? `${sortByValue}_${sortByTopValue}` : sortByValue
|
||||
const options = { sortBy, maxId }
|
||||
|
||||
dispatch(expandGroupTimeline(id, options))
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -64,12 +93,15 @@ class GroupTimeline extends ImmutablePureComponent {
|
|||
}
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<GroupSortBlock groupId={id} />
|
||||
<StatusList
|
||||
scrollKey={`group-timeline-${id}`}
|
||||
timelineId={`group:${id}`}
|
||||
onLoadMore={this.handleLoadMore}
|
||||
emptyMessage={intl.formatMessage(messages.empty)}
|
||||
/>
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -71,7 +71,6 @@ class ListTimeline extends ImmutablePureComponent {
|
|||
}
|
||||
|
||||
handleEditClick = () => {
|
||||
// console.log("handleEditClick:", this.props.params.id)
|
||||
this.props.dispatch(openModal('LIST_EDITOR', { id: this.props.params.id }))
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import throttle from 'lodash.throttle'
|
||||
import Sticky from 'react-stickynode'
|
||||
import { BREAKPOINT_EXTRA_SMALL } from '../constants'
|
||||
import Layout from './layout'
|
||||
|
@ -9,9 +10,8 @@ import SignUpLogInPanel from '../components/panel/sign_up_log_in_panel'
|
|||
import SidebarPanelGroup from '../components/sidebar_panel_group'
|
||||
import Responsive from '../features/ui/util/responsive_component'
|
||||
import Heading from '../components/heading'
|
||||
import GroupSortBlock from '../components/group_sort_block'
|
||||
|
||||
export default class GroupLayout extends ImmutablePureComponent {
|
||||
export default class ExploreLayout extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
actions: PropTypes.array,
|
||||
|
@ -23,11 +23,44 @@ export default class GroupLayout extends ImmutablePureComponent {
|
|||
title: PropTypes.string,
|
||||
}
|
||||
|
||||
state = {
|
||||
lazyLoaded: false,
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.window = window
|
||||
this.documentElement = document.scrollingElement || document.documentElement
|
||||
|
||||
this.window.addEventListener('scroll', this.handleScroll)
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.detachScrollListener()
|
||||
}
|
||||
|
||||
detachScrollListener = () => {
|
||||
this.window.removeEventListener('scroll', this.handleScroll)
|
||||
}
|
||||
|
||||
handleScroll = throttle(() => {
|
||||
if (this.window) {
|
||||
const { scrollTop } = this.documentElement
|
||||
|
||||
if (scrollTop > 25 && !this.state.lazyLoaded) {
|
||||
this.setState({ lazyLoaded: true })
|
||||
this.detachScrollListener()
|
||||
}
|
||||
}
|
||||
}, 150, {
|
||||
trailing: true,
|
||||
})
|
||||
|
||||
render() {
|
||||
const { children, title } = this.props
|
||||
const { lazyLoaded } = this.state
|
||||
|
||||
const pageTitleBlock = (
|
||||
<div className={[_s.default, _s.pl15, _s.py10].join(' ')}>
|
||||
<div className={[_s.default, _s.pl15, _s.pb10].join(' ')}>
|
||||
<Heading size='h2'>Popular posts across Gab</Heading>
|
||||
</div>
|
||||
)
|
||||
|
@ -47,11 +80,7 @@ export default class GroupLayout extends ImmutablePureComponent {
|
|||
<div className={[_s.default, _s.mt15, _s.px10].join(' ')}>
|
||||
<SignUpLogInPanel key='explore-page-signup-login-panel' isXS />
|
||||
</div>
|
||||
|
||||
{pageTitleBlock}
|
||||
|
||||
<GroupSortBlock />
|
||||
|
||||
{children}
|
||||
</div>
|
||||
|
||||
|
@ -66,9 +95,6 @@ export default class GroupLayout extends ImmutablePureComponent {
|
|||
|
||||
<div className={_s.default}>
|
||||
{pageTitleBlock}
|
||||
|
||||
<GroupSortBlock />
|
||||
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -81,7 +107,7 @@ export default class GroupLayout extends ImmutablePureComponent {
|
|||
layout={[
|
||||
<SignUpLogInPanel key='explore-page-signup-login-panel' />,
|
||||
<GroupSidebarPanel groupType='featured' key='explore-page-group-panel' />,
|
||||
<TrendsPanel key='explore-page-trends-panel' />,
|
||||
<TrendsPanel key='explore-page-trends-panel' isLazy shouldLoad={lazyLoaded} />,
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -7,7 +7,6 @@ import PageTitle from '../features/ui/util/page_title'
|
|||
import GroupLayout from '../layouts/group_layout'
|
||||
import TimelineComposeBlock from '../components/timeline_compose_block'
|
||||
import Divider from '../components/divider'
|
||||
import GroupSortBlock from '../components/group_sort_block'
|
||||
|
||||
const messages = defineMessages({
|
||||
group: { id: 'group', defaultMessage: 'Group' },
|
||||
|
@ -75,10 +74,6 @@ class GroupPage extends ImmutablePureComponent {
|
|||
</Fragment>
|
||||
}
|
||||
|
||||
{
|
||||
isTimeline && <GroupSortBlock />
|
||||
}
|
||||
|
||||
{children}
|
||||
</GroupLayout>
|
||||
)
|
||||
|
|
|
@ -40,7 +40,7 @@ const initialState = ImmutableMap({
|
|||
})
|
||||
|
||||
export default function groupLists(state = initialState, action) {
|
||||
if (tabs.indexOf(action.tab) === -1) return state
|
||||
// if (tabs.indexOf(action.tab) === -1) return state
|
||||
|
||||
switch(action.type) {
|
||||
case GROUPS_FETCH_REQUEST:
|
||||
|
|
Loading…
Reference in New Issue