Added pages and routes for Groups by tag and category
• Added: - pages and routes for Groups by tag and category
This commit is contained in:
parent
cb30e0dcbf
commit
fafd1ef658
@ -7,7 +7,7 @@ class Api::V1::GroupsController < Api::BaseController
|
|||||||
before_action -> { doorkeeper_authorize! :write, :'write:groups' }, except: [:index, :show]
|
before_action -> { doorkeeper_authorize! :write, :'write:groups' }, except: [:index, :show]
|
||||||
|
|
||||||
before_action :require_user!, except: [:index, :show]
|
before_action :require_user!, except: [:index, :show]
|
||||||
before_action :set_group, except: [:index, :create]
|
before_action :set_group, except: [:index, :create, :by_category, :by_tag]
|
||||||
|
|
||||||
def index
|
def index
|
||||||
case current_tab
|
case current_tab
|
||||||
@ -34,6 +34,26 @@ class Api::V1::GroupsController < Api::BaseController
|
|||||||
render json: @groups, each_serializer: REST::GroupSerializer
|
render json: @groups, each_serializer: REST::GroupSerializer
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def by_category
|
||||||
|
if !current_user
|
||||||
|
render json: { error: 'This method requires an authenticated user' }, status: 422
|
||||||
|
end
|
||||||
|
|
||||||
|
@groups = []
|
||||||
|
|
||||||
|
render json: @groups, each_serializer: REST::GroupSerializer
|
||||||
|
end
|
||||||
|
|
||||||
|
def by_tag
|
||||||
|
if !current_user
|
||||||
|
render json: { error: 'This method requires an authenticated user' }, status: 422
|
||||||
|
end
|
||||||
|
|
||||||
|
@groups = []
|
||||||
|
|
||||||
|
render json: @groups, each_serializer: REST::GroupSerializer
|
||||||
|
end
|
||||||
|
|
||||||
def current_tab
|
def current_tab
|
||||||
tab = 'featured'
|
tab = 'featured'
|
||||||
tab = params[:tab] if ['featured', 'member', 'admin', 'new'].include? params[:tab]
|
tab = params[:tab] if ['featured', 'member', 'admin', 'new'].include? params[:tab]
|
||||||
|
@ -90,6 +90,14 @@ export const GROUP_UNPIN_STATUS_REQUEST = 'GROUP_UNPIN_STATUS_REQUEST'
|
|||||||
export const GROUP_UNPIN_STATUS_SUCCESS = 'GROUP_UNPIN_STATUS_SUCCESS'
|
export const GROUP_UNPIN_STATUS_SUCCESS = 'GROUP_UNPIN_STATUS_SUCCESS'
|
||||||
export const GROUP_UNPIN_STATUS_FAIL = 'GROUP_UNPIN_STATUS_FAIL'
|
export const GROUP_UNPIN_STATUS_FAIL = 'GROUP_UNPIN_STATUS_FAIL'
|
||||||
|
|
||||||
|
export const GROUPS_BY_CATEGORY_FETCH_REQUEST = 'GROUPS_BY_CATEGORY_FETCH_REQUEST'
|
||||||
|
export const GROUPS_BY_CATEGORY_FETCH_SUCCESS = 'GROUPS_BY_CATEGORY_FETCH_SUCCESS'
|
||||||
|
export const GROUPS_BY_CATEGORY_FETCH_FAIL = 'GROUPS_BY_CATEGORY_FETCH_FAIL'
|
||||||
|
|
||||||
|
export const GROUPS_BY_TAG_FETCH_REQUEST = 'GROUPS_BY_TAG_FETCH_REQUEST'
|
||||||
|
export const GROUPS_BY_TAG_FETCH_SUCCESS = 'GROUPS_BY_TAG_FETCH_SUCCESS'
|
||||||
|
export const GROUPS_BY_TAG_FETCH_FAIL = 'GROUPS_BY_TAG_FETCH_FAIL'
|
||||||
|
|
||||||
export const GROUP_TIMELINE_SORT = 'GROUP_TIMELINE_SORT'
|
export const GROUP_TIMELINE_SORT = 'GROUP_TIMELINE_SORT'
|
||||||
export const GROUP_TIMELINE_TOP_SORT = 'GROUP_TIMELINE_TOP_SORT'
|
export const GROUP_TIMELINE_TOP_SORT = 'GROUP_TIMELINE_TOP_SORT'
|
||||||
|
|
||||||
@ -210,6 +218,72 @@ export const fetchGroupsFail = (error, tab) => ({
|
|||||||
tab,
|
tab,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const fetchGroupsByCategory = (category) => (dispatch, getState) => {
|
||||||
|
// Don't refetch or fetch when loading
|
||||||
|
const isLoading = getState().getIn(['group_lists', 'by_category', category, 'isLoading'], false)
|
||||||
|
|
||||||
|
if (isLoading) return
|
||||||
|
|
||||||
|
dispatch(fetchGroupsByCategoryRequest(category))
|
||||||
|
|
||||||
|
api(getState).get(`/api/v1/groups/_/category/${category}`)
|
||||||
|
.then(({ data }) => {
|
||||||
|
dispatch(fetchGroupsByCategorySuccess(data, category))
|
||||||
|
dispatch(fetchGroupRelationships(data.map(item => item.id)))
|
||||||
|
})
|
||||||
|
.catch((err) => dispatch(fetchGroupsByCategoryFail(err, category)))
|
||||||
|
}
|
||||||
|
|
||||||
|
export const fetchGroupsByCategoryRequest = (category) => ({
|
||||||
|
type: GROUPS_BY_CATEGORY_FETCH_REQUEST,
|
||||||
|
category,
|
||||||
|
})
|
||||||
|
|
||||||
|
export const fetchGroupsByCategorySuccess = (groups, category) => ({
|
||||||
|
type: GROUPS_BY_CATEGORY_FETCH_SUCCESS,
|
||||||
|
groups,
|
||||||
|
category,
|
||||||
|
})
|
||||||
|
|
||||||
|
export const fetchGroupsByCategoryFail = (error, category) => ({
|
||||||
|
type: GROUPS_BY_CATEGORY_FETCH_FAIL,
|
||||||
|
error,
|
||||||
|
category,
|
||||||
|
})
|
||||||
|
|
||||||
|
export const fetchGroupsByTag = (tag) => (dispatch, getState) => {
|
||||||
|
// Don't refetch or fetch when loading
|
||||||
|
const isLoading = getState().getIn(['group_lists', 'by_tag', tag, 'isLoading'], false)
|
||||||
|
|
||||||
|
if (isLoading) return
|
||||||
|
|
||||||
|
dispatch(fetchGroupsByTagRequest(tag))
|
||||||
|
|
||||||
|
api(getState).get(`/api/v1/groups/_/tag/${tag}`)
|
||||||
|
.then(({ data }) => {
|
||||||
|
dispatch(fetchGroupsByTagSuccess(data, tag))
|
||||||
|
dispatch(fetchGroupRelationships(data.map(item => item.id)))
|
||||||
|
})
|
||||||
|
.catch((err) => dispatch(fetchGroupsByTagFail(err, tag)))
|
||||||
|
}
|
||||||
|
|
||||||
|
export const fetchGroupsByTagRequest = (tag) => ({
|
||||||
|
type: GROUPS_BY_TAG_FETCH_REQUEST,
|
||||||
|
tag,
|
||||||
|
})
|
||||||
|
|
||||||
|
export const fetchGroupsByTagSuccess = (groups, tag) => ({
|
||||||
|
type: GROUPS_BY_TAG_FETCH_SUCCESS,
|
||||||
|
groups,
|
||||||
|
tag,
|
||||||
|
})
|
||||||
|
|
||||||
|
export const fetchGroupsByTagFail = (error, tag) => ({
|
||||||
|
type: GROUPS_BY_TAG_FETCH_FAIL,
|
||||||
|
error,
|
||||||
|
tag,
|
||||||
|
})
|
||||||
|
|
||||||
export function joinGroup(id) {
|
export function joinGroup(id) {
|
||||||
return (dispatch, getState) => {
|
return (dispatch, getState) => {
|
||||||
if (!me) return;
|
if (!me) return;
|
||||||
|
103
app/javascript/gabsocial/features/group_category.js
Normal file
103
app/javascript/gabsocial/features/group_category.js
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import PropTypes from 'prop-types'
|
||||||
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
|
import { connect } from 'react-redux'
|
||||||
|
import { FormattedMessage } from 'react-intl'
|
||||||
|
import slugify from '../utils/slugify'
|
||||||
|
import unslugify from '../utils/unslugify'
|
||||||
|
import { fetchGroupsByCategory } from '../actions/groups'
|
||||||
|
import Block from '../components/block'
|
||||||
|
import ColumnIndicator from '../components/column_indicator'
|
||||||
|
import Heading from '../components/heading'
|
||||||
|
import GroupListItem from '../components/group_list_item'
|
||||||
|
|
||||||
|
class GroupCategory extends ImmutablePureComponent {
|
||||||
|
|
||||||
|
state = {
|
||||||
|
category: this.props.params.sluggedCategory,
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate(prevProps) {
|
||||||
|
if (this.props.params.sluggedCategory !== prevProps.params.sluggedCategory) {
|
||||||
|
this.handleLoad(this.props.params.sluggedCategory)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.handleLoad(this.props.params.sluggedCategory)
|
||||||
|
}
|
||||||
|
|
||||||
|
handleLoad = (sluggedCategory) => {
|
||||||
|
const category = unslugify(sluggedCategory)
|
||||||
|
this.setState({ category })
|
||||||
|
this.props.onFetchGroupsByCategory(category)
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {
|
||||||
|
isFetched,
|
||||||
|
isLoading,
|
||||||
|
groupIds,
|
||||||
|
} = this.props
|
||||||
|
const { category } = this.state
|
||||||
|
|
||||||
|
let errorMessage
|
||||||
|
if (!groupIds || (isFetched && groupIds.size === 0)) {
|
||||||
|
errorMessage = <ColumnIndicator type='error' message={<FormattedMessage id='groups.empty' defaultMessage='There are no groups to display' />} />
|
||||||
|
} else if (isLoading && groupIds.size === 0) {
|
||||||
|
errorMessage = <ColumnIndicator type='loading' />
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Block>
|
||||||
|
<div className={[_s.d, _s.flexRow, _s.px15, _s.pt10].join(' ')}>
|
||||||
|
<div className={[_s.d, _s.aiStart, _s.overflowHidden].join(' ')}>
|
||||||
|
<Heading size='h2'>
|
||||||
|
Groups by category: {category}
|
||||||
|
</Heading>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={[_s.d, _s.py10, _s.w100PC].join(' ')}>
|
||||||
|
{
|
||||||
|
!errorMessage &&
|
||||||
|
groupIds.map((groupId, i) => (
|
||||||
|
<GroupListItem
|
||||||
|
isAddable
|
||||||
|
key={`group-collection-item-${i}`}
|
||||||
|
id={groupId}
|
||||||
|
isLast={groupIds.count() - 1 === i}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
{ !!errorMessage && errorMessage}
|
||||||
|
</div>
|
||||||
|
</Block>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapStateToProps = (state, { params: { sluggedCategory } }) => {
|
||||||
|
const cleanSluggedCategory = slugify(sluggedCategory)
|
||||||
|
|
||||||
|
return {
|
||||||
|
groupIds: state.getIn(['group_lists', 'by_category', cleanSluggedCategory, 'items']),
|
||||||
|
isFetched: state.getIn(['group_lists', 'by_category', cleanSluggedCategory, 'isFetched']),
|
||||||
|
isLoading: state.getIn(['group_lists', 'by_category', cleanSluggedCategory, 'isLoading']),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
|
onFetchGroupsByCategory: (category) => dispatch(fetchGroupsByCategory(category)),
|
||||||
|
})
|
||||||
|
|
||||||
|
GroupCategory.propTypes = {
|
||||||
|
groupIds: ImmutablePropTypes.list,
|
||||||
|
isFetched: PropTypes.bool.isRequired,
|
||||||
|
isLoading: PropTypes.bool.isRequired,
|
||||||
|
onFetchGroupsByCategory: PropTypes.func.isRequired,
|
||||||
|
sluggedCategory: PropTypes.string.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(GroupCategory)
|
103
app/javascript/gabsocial/features/group_tag.js
Normal file
103
app/javascript/gabsocial/features/group_tag.js
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import PropTypes from 'prop-types'
|
||||||
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
|
import { connect } from 'react-redux'
|
||||||
|
import { FormattedMessage } from 'react-intl'
|
||||||
|
import slugify from '../utils/slugify'
|
||||||
|
import unslugify from '../utils/unslugify'
|
||||||
|
import { fetchGroupsByTag } from '../actions/groups'
|
||||||
|
import Block from '../components/block'
|
||||||
|
import ColumnIndicator from '../components/column_indicator'
|
||||||
|
import Heading from '../components/heading'
|
||||||
|
import GroupListItem from '../components/group_list_item'
|
||||||
|
|
||||||
|
class GroupTag extends ImmutablePureComponent {
|
||||||
|
|
||||||
|
state = {
|
||||||
|
tag: this.props.params.sluggedTag,
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate(prevProps) {
|
||||||
|
if (this.props.params.sluggedTag !== prevProps.params.sluggedTag) {
|
||||||
|
this.handleLoad(this.props.params.sluggedTag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.handleLoad(this.props.params.sluggedTag)
|
||||||
|
}
|
||||||
|
|
||||||
|
handleLoad = (sluggedTag) => {
|
||||||
|
const tag = unslugify(sluggedTag)
|
||||||
|
this.setState({ tag })
|
||||||
|
this.props.onFetchGroupsByTag(tag)
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {
|
||||||
|
isFetched,
|
||||||
|
isLoading,
|
||||||
|
groupIds,
|
||||||
|
} = this.props
|
||||||
|
const { tag } = this.state
|
||||||
|
|
||||||
|
let errorMessage
|
||||||
|
if (!groupIds || (isFetched && groupIds.size === 0)) {
|
||||||
|
errorMessage = <ColumnIndicator type='error' message={<FormattedMessage id='groups.empty' defaultMessage='There are no groups to display' />} />
|
||||||
|
} else if (isLoading && groupIds.size === 0) {
|
||||||
|
errorMessage = <ColumnIndicator type='loading' />
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Block>
|
||||||
|
<div className={[_s.d, _s.flexRow, _s.px15, _s.pt10].join(' ')}>
|
||||||
|
<div className={[_s.d, _s.overflowHidden].join(' ')}>
|
||||||
|
<Heading size='h2'>
|
||||||
|
Groups by tag: {tag}
|
||||||
|
</Heading>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={[_s.d, _s.py10, _s.w100PC].join(' ')}>
|
||||||
|
{
|
||||||
|
!errorMessage &&
|
||||||
|
groupIds.map((groupId, i) => (
|
||||||
|
<GroupListItem
|
||||||
|
isAddable
|
||||||
|
key={`group-collection-item-${i}`}
|
||||||
|
id={groupId}
|
||||||
|
isLast={groupIds.count() - 1 === i}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
{ !!errorMessage && errorMessage}
|
||||||
|
</div>
|
||||||
|
</Block>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapStateToProps = (state, { params: { sluggedTag } }) => {
|
||||||
|
const cleanSluggedTag = slugify(sluggedTag)
|
||||||
|
|
||||||
|
return {
|
||||||
|
groupIds: state.getIn(['group_lists', 'by_tag', cleanSluggedTag, 'items']),
|
||||||
|
isFetched: state.getIn(['group_lists', 'by_tag', cleanSluggedTag, 'isFetched']),
|
||||||
|
isLoading: state.getIn(['group_lists', 'by_tag', cleanSluggedTag, 'isLoading']),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
|
onFetchGroupsByTag: (tag) => dispatch(fetchGroupsByTag(tag)),
|
||||||
|
})
|
||||||
|
|
||||||
|
GroupTag.propTypes = {
|
||||||
|
groupIds: ImmutablePropTypes.list,
|
||||||
|
isFetched: PropTypes.bool.isRequired,
|
||||||
|
isLoading: PropTypes.bool.isRequired,
|
||||||
|
onFetchGroupsByTag: PropTypes.func.isRequired,
|
||||||
|
sluggedTag: PropTypes.string.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(GroupTag)
|
@ -42,10 +42,10 @@ class GroupsCollection extends ImmutablePureComponent {
|
|||||||
isFetched,
|
isFetched,
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
if (isLoading && groupIds.size === 0) {
|
if (!groupIds || (isFetched && groupIds.size === 0)) {
|
||||||
return <ColumnIndicator type='loading' />
|
|
||||||
} else if (isFetched && groupIds.size === 0) {
|
|
||||||
return <ColumnIndicator type='error' message={intl.formatMessage(messages.empty)} />
|
return <ColumnIndicator type='error' message={intl.formatMessage(messages.empty)} />
|
||||||
|
} else if (isLoading && groupIds.size === 0) {
|
||||||
|
return <ColumnIndicator type='loading' />
|
||||||
}
|
}
|
||||||
|
|
||||||
const isAddable = ['featured', 'new'].indexOf(activeTab) > -1
|
const isAddable = ['featured', 'new'].indexOf(activeTab) > -1
|
||||||
|
@ -70,6 +70,8 @@ import {
|
|||||||
GroupRemovedAccounts,
|
GroupRemovedAccounts,
|
||||||
GroupTimeline,
|
GroupTimeline,
|
||||||
GroupsCategories,
|
GroupsCategories,
|
||||||
|
GroupCategory,
|
||||||
|
GroupTag,
|
||||||
HashtagTimeline,
|
HashtagTimeline,
|
||||||
HomeTimeline,
|
HomeTimeline,
|
||||||
Investors,
|
Investors,
|
||||||
@ -197,6 +199,8 @@ class SwitchingArea extends React.PureComponent {
|
|||||||
<WrappedRoute path='/groups/browse/member' exact page={GroupsPage} component={GroupsCollection} content={children} componentParams={{ activeTab: 'member' }} />
|
<WrappedRoute path='/groups/browse/member' exact page={GroupsPage} component={GroupsCollection} content={children} componentParams={{ activeTab: 'member' }} />
|
||||||
<WrappedRoute path='/groups/browse/admin' exact page={GroupsPage} component={GroupsCollection} content={children} componentParams={{ activeTab: 'admin' }} />
|
<WrappedRoute path='/groups/browse/admin' exact page={GroupsPage} component={GroupsCollection} content={children} componentParams={{ activeTab: 'admin' }} />
|
||||||
<WrappedRoute path='/groups/browse/categories' exact page={GroupsPage} component={GroupsCategories} content={children} componentParams={{ activeTab: 'categories' }} />
|
<WrappedRoute path='/groups/browse/categories' exact page={GroupsPage} component={GroupsCategories} content={children} componentParams={{ activeTab: 'categories' }} />
|
||||||
|
<WrappedRoute path='/groups/browse/categories/:sluggedCategory' exact page={GroupsPage} component={GroupCategory} content={children} componentParams={{ activeTab: 'categories' }} />
|
||||||
|
<WrappedRoute path='/groups/browse/tags/:sluggedTag' exact page={GroupsPage} component={GroupTag} content={children} />
|
||||||
|
|
||||||
<WrappedRoute path='/groups/create' page={ModalPage} component={GroupCreate} content={children} componentParams={{ title: 'Create Group', page: 'create-group' }} />
|
<WrappedRoute path='/groups/create' page={ModalPage} component={GroupCreate} content={children} componentParams={{ title: 'Create Group', page: 'create-group' }} />
|
||||||
<WrappedRoute path='/groups/:id/members' page={GroupPage} component={GroupMembers} content={children} />
|
<WrappedRoute path='/groups/:id/members' page={GroupPage} component={GroupMembers} content={children} />
|
||||||
|
@ -47,8 +47,9 @@ export function GroupRemovedAccounts() { return import(/* webpackChunkName: "fea
|
|||||||
export function GroupTimeline() { return import(/* webpackChunkName: "features/group_timeline" */'../../group_timeline') }
|
export function GroupTimeline() { return import(/* webpackChunkName: "features/group_timeline" */'../../group_timeline') }
|
||||||
export function GroupTimelineSortOptionsPopover() { return import(/* webpackChunkName: "components/group_timeline_sort_options_popover" */'../../../components/popover/group_timeline_sort_options_popover') }
|
export function GroupTimelineSortOptionsPopover() { return import(/* webpackChunkName: "components/group_timeline_sort_options_popover" */'../../../components/popover/group_timeline_sort_options_popover') }
|
||||||
export function GroupTimelineSortTopOptionsPopover() { return import(/* webpackChunkName: "components/group_timeline_sort_top_options_popover" */'../../../components/popover/group_timeline_sort_top_options_popover') }
|
export function GroupTimelineSortTopOptionsPopover() { return import(/* webpackChunkName: "components/group_timeline_sort_top_options_popover" */'../../../components/popover/group_timeline_sort_top_options_popover') }
|
||||||
// export function GroupCategory() { return import(/* webpackChunkName: "features/group_category" */'../../group_category') }
|
|
||||||
export function GroupsCategories() { return import(/* webpackChunkName: "features/groups_categories" */'../../groups_categories') }
|
export function GroupsCategories() { return import(/* webpackChunkName: "features/groups_categories" */'../../groups_categories') }
|
||||||
|
export function GroupCategory() { return import(/* webpackChunkName: "features/group_category" */'../../group_category') }
|
||||||
|
export function GroupTag() { return import(/* webpackChunkName: "features/group_tag" */'../../group_tag') }
|
||||||
export function HashtagTimeline() { return import(/* webpackChunkName: "features/hashtag_timeline" */'../../hashtag_timeline') }
|
export function HashtagTimeline() { return import(/* webpackChunkName: "features/hashtag_timeline" */'../../hashtag_timeline') }
|
||||||
export function HashtagTimelineSettingsModal() { return import(/* webpackChunkName: "components/hashtag_timeline_settings_modal" */'../../../components/modal/hashtag_timeline_settings_modal') }
|
export function HashtagTimelineSettingsModal() { return import(/* webpackChunkName: "components/hashtag_timeline_settings_modal" */'../../../components/modal/hashtag_timeline_settings_modal') }
|
||||||
export function HomeTimeline() { return import(/* webpackChunkName: "features/home_timeline" */'../../home_timeline') }
|
export function HomeTimeline() { return import(/* webpackChunkName: "features/home_timeline" */'../../home_timeline') }
|
||||||
|
@ -10,12 +10,19 @@ import {
|
|||||||
GROUP_CHECK_PASSWORD_REQUEST,
|
GROUP_CHECK_PASSWORD_REQUEST,
|
||||||
GROUP_CHECK_PASSWORD_SUCCESS,
|
GROUP_CHECK_PASSWORD_SUCCESS,
|
||||||
GROUP_CHECK_PASSWORD_FAIL,
|
GROUP_CHECK_PASSWORD_FAIL,
|
||||||
|
GROUPS_BY_CATEGORY_FETCH_REQUEST,
|
||||||
|
GROUPS_BY_CATEGORY_FETCH_SUCCESS,
|
||||||
|
GROUPS_BY_CATEGORY_FETCH_FAIL,
|
||||||
|
GROUPS_BY_TAG_FETCH_REQUEST,
|
||||||
|
GROUPS_BY_TAG_FETCH_SUCCESS,
|
||||||
|
GROUPS_BY_TAG_FETCH_FAIL,
|
||||||
} from '../actions/groups'
|
} from '../actions/groups'
|
||||||
import {
|
import {
|
||||||
GROUP_TIMELINE_SORTING_TYPE_TOP,
|
GROUP_TIMELINE_SORTING_TYPE_TOP,
|
||||||
GROUP_TIMELINE_SORTING_TYPE_NEWEST,
|
GROUP_TIMELINE_SORTING_TYPE_NEWEST,
|
||||||
GROUP_TIMELINE_SORTING_TYPE_TOP_OPTION_TODAY,
|
GROUP_TIMELINE_SORTING_TYPE_TOP_OPTION_TODAY,
|
||||||
} from '../constants'
|
} from '../constants'
|
||||||
|
import slugify from '../utils/slugify'
|
||||||
|
|
||||||
const tabs = ['new', 'featured', 'member', 'admin']
|
const tabs = ['new', 'featured', 'member', 'admin']
|
||||||
|
|
||||||
@ -43,6 +50,8 @@ const initialState = ImmutableMap({
|
|||||||
isLoading: false,
|
isLoading: false,
|
||||||
items: ImmutableList(),
|
items: ImmutableList(),
|
||||||
}),
|
}),
|
||||||
|
by_category: ImmutableMap(),
|
||||||
|
by_tag: ImmutableMap(),
|
||||||
})
|
})
|
||||||
|
|
||||||
export default function groupLists(state = initialState, action) {
|
export default function groupLists(state = initialState, action) {
|
||||||
@ -111,7 +120,33 @@ export default function groupLists(state = initialState, action) {
|
|||||||
mutable.setIn(['passwordCheck', 'isLoading'], false)
|
mutable.setIn(['passwordCheck', 'isLoading'], false)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
case GROUPS_BY_CATEGORY_FETCH_REQUEST:
|
||||||
|
return state.setIn(['by_category', slugify(action.category), 'isLoading'], true)
|
||||||
|
case GROUPS_BY_CATEGORY_FETCH_SUCCESS:
|
||||||
|
return state.setIn(['by_category', slugify(action.category)], ImmutableMap({
|
||||||
|
items: ImmutableList(action.groups.map(item => item.id)),
|
||||||
|
isLoading: false,
|
||||||
|
}))
|
||||||
|
case GROUPS_BY_CATEGORY_FETCH_FAIL:
|
||||||
|
return state.setIn(['by_category', slugify(action.category)], ImmutableMap({
|
||||||
|
items: ImmutableList(),
|
||||||
|
isLoading: false,
|
||||||
|
}))
|
||||||
|
|
||||||
|
case GROUPS_BY_TAG_FETCH_REQUEST:
|
||||||
|
return state.setIn(['by_tag', slugify(action.tag), 'isLoading'], true)
|
||||||
|
case GROUPS_BY_TAG_FETCH_SUCCESS:
|
||||||
|
return state.setIn(['by_tag', slugify(action.tag)], ImmutableMap({
|
||||||
|
items: ImmutableList(action.groups.map(item => item.id)),
|
||||||
|
isLoading: false,
|
||||||
|
}))
|
||||||
|
case GROUPS_BY_TAG_FETCH_FAIL:
|
||||||
|
return state.setIn(['by_tag', slugify(action.tag)], ImmutableMap({
|
||||||
|
items: ImmutableList(),
|
||||||
|
isLoading: false,
|
||||||
|
}))
|
||||||
default:
|
default:
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
7
app/javascript/gabsocial/utils/unslugify.js
Normal file
7
app/javascript/gabsocial/utils/unslugify.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
// https://github.com/danny-wood/unslugify/blob/master/index.js
|
||||||
|
export default function unslugify(text) {
|
||||||
|
const result = `${text}`.replace(/\-/g, " ");
|
||||||
|
return result.replace(/\w\S*/g, function (txt) {
|
||||||
|
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
|
||||||
|
});
|
||||||
|
}
|
@ -437,6 +437,9 @@ Rails.application.routes.draw do
|
|||||||
post '/statuses/:status_id/approve', to: 'groups#approve_status'
|
post '/statuses/:status_id/approve', to: 'groups#approve_status'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
get '/category/:category', to: 'groups#by_category'
|
||||||
|
get '/tag/:tag', to: 'groups#by_tag'
|
||||||
|
|
||||||
resources :relationships, only: :index, controller: 'groups/relationships'
|
resources :relationships, only: :index, controller: 'groups/relationships'
|
||||||
resource :accounts, only: [:show, :create, :update, :destroy], controller: 'groups/accounts'
|
resource :accounts, only: [:show, :create, :update, :destroy], controller: 'groups/accounts'
|
||||||
resource :removed_accounts, only: [:show, :create, :destroy], controller: 'groups/removed_accounts'
|
resource :removed_accounts, only: [:show, :create, :destroy], controller: 'groups/removed_accounts'
|
||||||
|
Loading…
Reference in New Issue
Block a user