diff --git a/app/javascript/gabsocial/actions/groups.js b/app/javascript/gabsocial/actions/groups.js
index 1c370ca6..8d27e8e7 100644
--- a/app/javascript/gabsocial/actions/groups.js
+++ b/app/javascript/gabsocial/actions/groups.js
@@ -133,20 +133,27 @@ export function fetchGroupRelationshipsFail(error) {
};
export const fetchGroups = (tab) => (dispatch, getState) => {
- if (!me) return;
+ if (!me) return
- dispatch(fetchGroupsRequest());
+ // Don't refetch or fetch when loading
+ const isLoading = getState().getIn(['group_lists', tab, 'loading'])
+ const isFetched = getState().getIn(['group_lists', tab, 'fetched'])
+
+ if (isLoading || isFetched) return
+
+ dispatch(fetchGroupsRequest(tab))
api(getState).get('/api/v1/groups?tab=' + tab)
.then(({ data }) => {
- dispatch(fetchGroupsSuccess(data, tab));
- dispatch(fetchGroupRelationships(data.map(item => item.id)));
+ dispatch(fetchGroupsSuccess(data, tab))
+ dispatch(fetchGroupRelationships(data.map(item => item.id)))
})
- .catch(err => dispatch(fetchGroupsFail(err)));
-};
+ .catch((err) => dispatch(fetchGroupsFail(err, tab)))
+}
-export const fetchGroupsRequest = () => ({
+export const fetchGroupsRequest = (tab) => ({
type: GROUPS_FETCH_REQUEST,
+ tab,
});
export const fetchGroupsSuccess = (groups, tab) => ({
@@ -155,9 +162,10 @@ export const fetchGroupsSuccess = (groups, tab) => ({
tab,
});
-export const fetchGroupsFail = error => ({
+export const fetchGroupsFail = (error, tab) => ({
type: GROUPS_FETCH_FAIL,
error,
+ tab,
});
export function joinGroup(id) {
diff --git a/app/javascript/gabsocial/components/panel/groups_panel.js b/app/javascript/gabsocial/components/panel/groups_panel.js
index b9c12054..f583a711 100644
--- a/app/javascript/gabsocial/components/panel/groups_panel.js
+++ b/app/javascript/gabsocial/components/panel/groups_panel.js
@@ -13,7 +13,7 @@ const messages = defineMessages({
})
const mapStateToProps = (state) => ({
- groupIds: state.getIn(['group_lists', 'member']),
+ groupIds: state.getIn(['group_lists', 'member', 'items']),
})
const mapDispatchToProps = (dispatch) => ({
diff --git a/app/javascript/gabsocial/features/groups_collection.js b/app/javascript/gabsocial/features/groups_collection.js
index 6a31d39d..1f2585a2 100644
--- a/app/javascript/gabsocial/features/groups_collection.js
+++ b/app/javascript/gabsocial/features/groups_collection.js
@@ -1,5 +1,6 @@
import ImmutablePropTypes from 'react-immutable-proptypes'
import ImmutablePureComponent from 'react-immutable-pure-component'
+import { FormattedMessage } from 'react-intl'
import { fetchGroups } from '../actions/groups'
import { BREAKPOINT_EXTRA_SMALL } from '../constants'
import Responsive from './ui/util/responsive_component'
@@ -8,7 +9,9 @@ import ScrollableList from '../components/scrollable_list'
import GroupCollectionItem from '../components/group_collection_item'
const mapStateToProps = (state, { activeTab }) => ({
- groupIds: state.getIn(['group_lists', activeTab]),
+ groupIds: state.getIn(['group_lists', activeTab, 'items']),
+ isFetched: state.getIn(['group_lists', activeTab, 'isFetched']),
+ isLoading: state.getIn(['group_lists', activeTab, 'isLoading']),
})
export default
@@ -19,6 +22,8 @@ class GroupsCollection extends ImmutablePureComponent {
activeTab: PropTypes.string.isRequired,
dispatch: PropTypes.func.isRequired,
groupIds: ImmutablePropTypes.list,
+ isFetched: PropTypes.bool.isRequired,
+ isLoading: PropTypes.bool.isRequired,
}
componentWillMount() {
@@ -32,10 +37,16 @@ class GroupsCollection extends ImmutablePureComponent {
}
render() {
- const { groupIds } = this.props
+ const {
+ groupIds,
+ isLoading,
+ isFetched,
+ } = this.props
- if (!groupIds) {
+ if (isLoading && groupIds.size === 0) {
return
+ } else if (isFetched && groupIds.size === 0) {
+ return } />
}
const halfCount = parseInt(groupIds.size / 2)
diff --git a/app/javascript/gabsocial/reducers/group_lists.js b/app/javascript/gabsocial/reducers/group_lists.js
index ae10fa92..a65e8c32 100644
--- a/app/javascript/gabsocial/reducers/group_lists.js
+++ b/app/javascript/gabsocial/reducers/group_lists.js
@@ -1,22 +1,55 @@
import { Map as ImmutableMap, List as ImmutableList } from 'immutable'
-import { GROUPS_FETCH_SUCCESS } from '../actions/groups'
+import {
+ GROUPS_FETCH_REQUEST,
+ GROUPS_FETCH_SUCCESS,
+ GROUPS_FETCH_FAIL,
+} from '../actions/groups'
+
+const tabs = ['new', 'featured', 'member', 'admin']
const initialState = ImmutableMap({
- new: ImmutableList(),
- featured: ImmutableList(),
- member: ImmutableList(),
- admin: ImmutableList(),
+ new: ImmutableMap({
+ fetched: false,
+ loading: false,
+ items: ImmutableList(),
+ }),
+ featured: ImmutableMap({
+ fetched: false,
+ loading: false,
+ items: ImmutableList(),
+ }),
+ member: ImmutableMap({
+ fetched: false,
+ loading: false,
+ items: ImmutableList(),
+ }),
+ admin: ImmutableMap({
+ fetched: false,
+ loading: false,
+ items: ImmutableList(),
+ }),
})
-const normalizeList = (state, type, id, groups) => {
- return state.set(type, ImmutableList(groups.map(item => item.id)))
-}
-
export default function groupLists(state = initialState, action) {
+ if (tabs.indexOf(action.tab) === -1) return state
+
switch(action.type) {
+ case GROUPS_FETCH_REQUEST:
+ return state.withMutations((mutable) => {
+ mutable.setIn([action.tab, 'loading'], true)
+ });
case GROUPS_FETCH_SUCCESS:
- if (!action.tab) return state
- return normalizeList(state, action.tab, action.id, action.groups)
+ return state.withMutations((mutable) => {
+ mutable.setIn([action.tab, 'items'], ImmutableList(action.groups.map(item => item.id)))
+ mutable.setIn([action.tab, 'loading'], false)
+ mutable.setIn([action.tab, 'fetched'], true)
+ })
+ case GROUPS_FETCH_FAIL:
+ return state.withMutations((mutable) => {
+ mutable.setIn([action.tab, 'items'], ImmutableList())
+ mutable.setIn([action.tab, 'loading'], false)
+ mutable.setIn([action.tab, 'fetched'], true)
+ })
default:
return state
}