From 3aae90a78c0f16e047b6c7e465ff4740eaf8cf3a Mon Sep 17 00:00:00 2001
From: NGUYEN DINH Quoc-Huy <quochuy@gmail.com>
Date: Mon, 15 Mar 2021 21:58:20 +1100
Subject: [PATCH] Closes #123 - move loading indicator into search result
 container - update list of communities even when no results is being returned
 - clean up code

---
 src/app/components/pages/CommunitiesIndex.jsx | 113 +++++++---------
 src/app/redux/FetchDataSaga.js                | 122 ++++-------------
 src/app/redux/GlobalReducer.js                | 127 ++++++------------
 3 files changed, 114 insertions(+), 248 deletions(-)

diff --git a/src/app/components/pages/CommunitiesIndex.jsx b/src/app/components/pages/CommunitiesIndex.jsx
index 014f043b0..a1fc9e359 100644
--- a/src/app/components/pages/CommunitiesIndex.jsx
+++ b/src/app/components/pages/CommunitiesIndex.jsx
@@ -21,31 +21,26 @@ export default class CommunitiesIndex extends React.Component {
     }
 
     componentWillMount = () => {
-        this.props.performSearch(
-            this.props.username,
-            this.state.searchQuery,
-            this.state.searchOrder
-        );
+        const { performSearch, username, searchQuery, searchOrder } = this.props;
+        performSearch(username, searchQuery, searchOrder);
     };
-    componentDidUpdate = (prevProps, prevState) => {
-        if (prevProps.username !== this.props.username) {
-            this.props.performSearch(
-                this.props.username,
-                this.state.searchQuery,
-                this.state.searchOrder
-            );
+
+    componentDidUpdate = prevProps => {
+        const { performSearch, username, searchQuery, searchOrder } = this.props;
+
+        if (prevProps.username !== username) {
+            performSearch(username, searchQuery, searchOrder);
         }
     };
 
     render() {
-        const {
-            communities,
-            communities_idx,
-            username,
-            walletUrl,
-            performSearch,
-        } = this.props;
-        const ordered = communities_idx.map(name => communities.get(name));
+        const { communities, communities_idx, username, walletUrl, performSearch } = this.props;
+        const ordered =
+            communities_idx !== null
+                ? communities_idx.map(name => {
+                      return communities.get(name);
+                  })
+                : [];
 
         const sortOptions = [
             {
@@ -62,31 +57,18 @@ export default class CommunitiesIndex extends React.Component {
             },
         ];
 
-        if (communities_idx.size === 0) {
+        const role = comm => {
             return (
-                <center>
-                    <LoadingIndicator
-                        style={{ marginBottom: '2rem' }}
-                        type="circle"
-                    />
-                </center>
-            );
-        }
-
-        const role = comm =>
-            comm.context &&
-            comm.context.role !== 'guest' && (
-                <span className="user_role">{comm.context.role}</span>
+                comm.context && comm.context.role !== 'guest' && <span className="user_role">{comm.context.role}</span>
             );
+        };
 
         const communityAdmins = admins => {
-            if (!admins || admins.length === 0) return;
+            if (!admins || admins.length === 0) return null;
 
             return (
                 <div>
-                    {admins.length === 1
-                        ? `${tt('g.administrator')}: `
-                        : `${tt('g.administrators')}: `}
+                    {admins.length === 1 ? `${tt('g.administrator')}: ` : `${tt('g.administrators')}: `}
                     <UserNames names={admins} />
                 </div>
             );
@@ -104,9 +86,8 @@ export default class CommunitiesIndex extends React.Component {
                         <br />
                         {comm.about}
                         <small>
-                            {comm.subscribers} subscribers &bull;{' '}
-                            {comm.num_authors} posters &bull; {comm.num_pending}{' '}
-                            posts
+                            {comm.subscribers}
+                            subscribers &bull; {comm.num_authors} posters &bull; {comm.num_pending} posts
                             {admins}
                         </small>
                     </th>
@@ -117,18 +98,14 @@ export default class CommunitiesIndex extends React.Component {
             );
         };
 
+        const { searchQuery, searchOrder } = this.state;
+
         return (
-            <PostsIndexLayout
-                category={null}
-                enableAds={false}
-                blogmode={false}
-            >
+            <PostsIndexLayout category={null} enableAds={false} blogmode={false}>
                 <div className="CommunitiesIndex c-sidebar__module">
                     {username && (
                         <div style={{ float: 'right' }}>
-                            <a href={`${walletUrl}/@${username}/communities`}>
-                                Create a Community
-                            </a>
+                            <a href={`${walletUrl}/@${username}/communities`}>Create a Community</a>
                         </div>
                     )}
 
@@ -139,16 +116,12 @@ export default class CommunitiesIndex extends React.Component {
                     <div className="articles__header row">
                         <div className="small-8 medium-7 large-8 column">
                             <ElasticSearchInput
-                                expanded={true}
+                                expanded
                                 handleSubmit={q => {
                                     this.setState({
                                         searchQuery: q,
                                     });
-                                    performSearch(
-                                        username,
-                                        q,
-                                        this.state.searchOrder
-                                    );
+                                    performSearch(username, q, searchOrder);
                                 }}
                                 redirect={false}
                             />
@@ -156,24 +129,33 @@ export default class CommunitiesIndex extends React.Component {
                         <div className="small-4 medium-3 large-4 column">
                             <NativeSelect
                                 options={sortOptions}
-                                currentlySelected={this.state.searchOrder}
+                                currentlySelected={searchOrder}
                                 onChange={opt => {
                                     this.setState({
                                         searchOrder: opt.value,
                                     });
-                                    performSearch(
-                                        username,
-                                        this.state.searchQuery,
-                                        opt.value
-                                    );
+                                    performSearch(username, searchQuery, opt.value);
                                 }}
                             />
                         </div>
                     </div>
-                    <hr />
-                    <table>
-                        <tbody>{ordered.map(comm => row(comm.toJS()))}</tbody>
-                    </table>
+                    {ordered && (
+                        <div>
+                            <hr />
+                            <table>
+                                <tbody>
+                                    {ordered.map(comm => {
+                                        return row(comm.toJS());
+                                    })}
+                                </tbody>
+                            </table>
+                        </div>
+                    )}
+                    {communities === null && (
+                        <center>
+                            <LoadingIndicator style={{ marginBottom: '2rem' }} type="circle" />
+                        </center>
+                    )}
                 </div>
             </PostsIndexLayout>
         );
@@ -195,6 +177,7 @@ module.exports = {
         dispatch => {
             return {
                 performSearch: (observer, query, sort = 'rank') => {
+                    console.log('search', query);
                     dispatch(
                         fetchDataSagaActions.listCommunities({
                             observer,
diff --git a/src/app/redux/FetchDataSaga.js b/src/app/redux/FetchDataSaga.js
index 83c3f4762..39a1c805b 100644
--- a/src/app/redux/FetchDataSaga.js
+++ b/src/app/redux/FetchDataSaga.js
@@ -1,11 +1,4 @@
-import {
-    call,
-    put,
-    select,
-    fork,
-    takeLatest,
-    takeEvery,
-} from 'redux-saga/effects';
+import { call, put, select, fork, takeLatest, takeEvery } from 'redux-saga/effects';
 import { api } from '@hiveio/hive-js';
 import { loadFollows } from 'app/redux/FollowSaga';
 import * as globalActions from './GlobalReducer';
@@ -14,10 +7,7 @@ import * as transactionActions from './TransactionReducer';
 import constants from './constants';
 import { fromJS, Map, Set } from 'immutable';
 import { getStateAsync, callBridge } from 'app/utils/steemApi';
-import {
-    fetchCrossPosts,
-    augmentContentWithCrossPost,
-} from 'app/utils/CrossPosts';
+import { fetchCrossPosts, augmentContentWithCrossPost } from 'app/utils/CrossPosts';
 
 const REQUEST_DATA = 'fetchDataSaga/REQUEST_DATA';
 const FETCH_STATE = 'fetchDataSaga/FETCH_STATE';
@@ -26,8 +16,7 @@ const GET_COMMUNITY = 'fetchDataSaga/GET_COMMUNITY';
 const LIST_COMMUNITIES = 'fetchDataSaga/LIST_COMMUNITIES';
 const GET_SUBSCRIPTIONS = 'fetchDataSaga/GET_SUBSCRIPTIONS';
 const GET_ACCOUNT_NOTIFICATIONS = 'fetchDataSaga/GET_ACCOUNT_NOTIFICATIONS';
-const GET_UNREAD_ACCOUNT_NOTIFICATIONS =
-    'fetchDataSaga/GET_UNREAD_ACCOUNT_NOTIFICATIONS';
+const GET_UNREAD_ACCOUNT_NOTIFICATIONS = 'fetchDataSaga/GET_UNREAD_ACCOUNT_NOTIFICATIONS';
 const MARK_NOTIFICATIONS_AS_READ = 'fetchDataSaga/MARK_NOTIFICATIONS_AS_READ';
 const GET_REWARDS_DATA = 'fetchDataSaga/GET_REWARDS_DATA';
 
@@ -41,10 +30,7 @@ export const fetchDataWatches = [
     takeLatest(GET_SUBSCRIPTIONS, getSubscriptions),
     takeEvery(LIST_COMMUNITIES, listCommunities),
     takeEvery(GET_ACCOUNT_NOTIFICATIONS, getAccountNotifications),
-    takeEvery(
-        GET_UNREAD_ACCOUNT_NOTIFICATIONS,
-        getUnreadAccountNotificationsSaga
-    ),
+    takeEvery(GET_UNREAD_ACCOUNT_NOTIFICATIONS, getUnreadAccountNotificationsSaga),
     takeEvery(GET_REWARDS_DATA, getRewardsDataSaga),
     takeEvery(MARK_NOTIFICATIONS_AS_READ, markNotificationsAsReadSaga),
 ];
@@ -68,21 +54,14 @@ export function* fetchState(location_change_action) {
 
     // `ignore_fetch` case should only trigger on initial page load. No need to call
     // fetchState immediately after loading fresh state from the server. Details: #593
-    const server_location = yield select(state =>
-        state.offchain.get('server_location')
-    );
+    const server_location = yield select(state => state.offchain.get('server_location'));
     const ignore_fetch = pathname === server_location && is_initial_state;
 
     if (ignore_fetch) {
         return;
     }
     is_initial_state = false;
-    if (
-        process.env.BROWSER &&
-        window &&
-        window.optimize &&
-        window.optimize.isInitialized
-    ) {
+    if (process.env.BROWSER && window && window.optimize && window.optimize.isInitialized) {
         window.optimize.refreshAll({ refresh: false });
     }
     const url = pathname;
@@ -91,9 +70,7 @@ export function* fetchState(location_change_action) {
     try {
         let username = null;
         if (process.env.BROWSER) {
-            [username] = yield select(state => [
-                state.user.getIn(['current', 'username']),
-            ]);
+            [username] = yield select(state => [state.user.getIn(['current', 'username'])]);
         }
         const state = yield call(getStateAsync, url, username, false);
         yield put(globalActions.receiveState(state));
@@ -111,26 +88,18 @@ function* syncSpecialPosts() {
     if (!process.env.BROWSER) return null;
 
     // Get special posts from the store.
-    const specialPosts = yield select(state =>
-        state.offchain.get('special_posts')
-    );
+    const specialPosts = yield select(state => state.offchain.get('special_posts'));
 
     // Mark seen featured posts.
     const seenFeaturedPosts = specialPosts.get('featured_posts').map(post => {
         const id = `${post.get('author')}/${post.get('permlink')}`;
-        return post.set(
-            'seen',
-            localStorage.getItem(`featured-post-seen:${id}`) === 'true'
-        );
+        return post.set('seen', localStorage.getItem(`featured-post-seen:${id}`) === 'true');
     });
 
     // Mark seen promoted posts.
     const seenPromotedPosts = specialPosts.get('promoted_posts').map(post => {
         const id = `${post.get('author')}/${post.get('permlink')}`;
-        return post.set(
-            'seen',
-            localStorage.getItem(`promoted-post-seen:${id}`) === 'true'
-        );
+        return post.set('seen', localStorage.getItem(`promoted-post-seen:${id}`) === 'true');
     });
 
     // Look up seen post URLs.
@@ -173,14 +142,13 @@ function* getAccounts(usernames) {
 export function* listCommunities(action) {
     const { observer, query, sort } = action.payload;
     try {
+        yield put(globalActions.receiveCommunities(null));
         const communities = yield call(callBridge, 'list_communities', {
             observer,
-            query,
+            query: query !== '' ? query : null,
             sort,
         });
-        if (communities.length > 0) {
-            yield put(globalActions.receiveCommunities(communities));
-        }
+        yield put(globalActions.receiveCommunities(communities));
     } catch (error) {
         console.log('Error requesting communities:', error);
     }
@@ -245,17 +213,10 @@ export function* getAccountNotifications(action) {
     if (!action.payload) throw 'no account specified';
     yield put(globalActions.notificationsLoading(true));
     try {
-        const notifications = yield call(
-            callBridge,
-            'account_notifications',
-            action.payload
-        );
+        const notifications = yield call(callBridge, 'account_notifications', action.payload);
 
         if (notifications && notifications.error) {
-            console.error(
-                '~~ Saga getAccountNotifications error ~~>',
-                notifications.error
-            );
+            console.error('~~ Saga getAccountNotifications error ~~>', notifications.error);
             yield put(appActions.steemApiError(notifications.error.message));
         } else {
             const limit = action.payload.limit ? action.payload.limit : 100;
@@ -285,19 +246,10 @@ export function* getUnreadAccountNotificationsSaga(action) {
     if (!action.payload) throw 'no account specified';
     yield put(globalActions.notificationsLoading(true));
     try {
-        const unreadNotifications = yield call(
-            callBridge,
-            'unread_notifications',
-            action.payload
-        );
+        const unreadNotifications = yield call(callBridge, 'unread_notifications', action.payload);
         if (unreadNotifications && unreadNotifications.error) {
-            console.error(
-                '~~ Saga getUnreadAccountNotifications error ~~>',
-                unreadNotifications.error
-            );
-            yield put(
-                appActions.steemApiError(unreadNotifications.error.message)
-            );
+            console.error('~~ Saga getUnreadAccountNotifications error ~~>', unreadNotifications.error);
+            yield put(appActions.steemApiError(unreadNotifications.error.message));
         } else {
             yield put(
                 globalActions.receiveUnreadNotifications({
@@ -330,9 +282,7 @@ export function* markNotificationsAsReadSaga(action) {
                     successCallback(username, timeNow);
                 },
                 errorCallback: () => {
-                    console.log(
-                        'There was an error marking notifications as read!'
-                    );
+                    console.log('There was an error marking notifications as read!');
                     globalActions.notificationsLoading(false);
                 },
             })
@@ -396,16 +346,8 @@ export function* fetchData(action) {
                         const contentKey = keys[ki];
                         let post = content[contentKey];
 
-                        if (
-                            Object.prototype.hasOwnProperty.call(
-                                post,
-                                'cross_post_key'
-                            )
-                        ) {
-                            post = augmentContentWithCrossPost(
-                                post,
-                                crossPosts[post.cross_post_key]
-                            );
+                        if (Object.prototype.hasOwnProperty.call(post, 'cross_post_key')) {
+                            post = augmentContentWithCrossPost(post, crossPosts[post.cross_post_key]);
                         }
 
                         data.push(post);
@@ -428,14 +370,9 @@ export function* fetchData(action) {
 
             // Still return all data but only count ones matching the filter.
             // Rely on UI to actually hide the posts.
-            fetched += postFilter
-                ? data.filter(postFilter).length
-                : data.length;
+            fetched += postFilter ? data.filter(postFilter).length : data.length;
 
-            fetchDone =
-                endOfData ||
-                fetchLimitReached ||
-                fetched >= constants.FETCH_DATA_BATCH_SIZE;
+            fetchDone = endOfData || fetchLimitReached || fetched >= constants.FETCH_DATA_BATCH_SIZE;
 
             yield put(
                 globalActions.receiveData({
@@ -460,9 +397,7 @@ export function* fetchData(action) {
     @arg {string} url
     @arg {object} body (for JSON.stringify)
 */
-function* fetchJson({
-    payload: { id, url, body, successCallback, skipLoading = false },
-}) {
+function* fetchJson({ payload: { id, url, body, successCallback, skipLoading = false } }) {
     try {
         const payload = {
             method: body ? 'POST' : 'GET',
@@ -472,9 +407,7 @@ function* fetchJson({
             },
             body: body ? JSON.stringify(body) : undefined,
         };
-        let result = yield skipLoading
-            ? fetch(url, payload)
-            : call(fetch, url, payload);
+        let result = yield skipLoading ? fetch(url, payload) : call(fetch, url, payload);
         result = yield result.json();
         if (successCallback) result = successCallback(result);
         yield put(globalActions.fetchJsonResult({ id, result }));
@@ -488,10 +421,7 @@ export function* getRewardsDataSaga(action) {
     try {
         const rewards = yield call(callBridge, 'get_payout_stats', {});
         if (rewards && rewards.error) {
-            console.error(
-                '~~ Saga getRewardsDataSaga error ~~>',
-                rewards.error
-            );
+            console.error('~~ Saga getRewardsDataSaga error ~~>', rewards.error);
             yield put(appActions.steemApiError(rewards.error.message));
         } else {
             yield put(globalActions.receiveRewards({ rewards }));
diff --git a/src/app/redux/GlobalReducer.js b/src/app/redux/GlobalReducer.js
index eda56b32d..df00797dc 100644
--- a/src/app/redux/GlobalReducer.js
+++ b/src/app/redux/GlobalReducer.js
@@ -61,9 +61,7 @@ const transformAccount = account =>
  */
 
 const mergeAccounts = (state, account) => {
-    return state.updateIn(['accounts', account.get('name')], Map(), a =>
-        a.mergeDeep(account)
-    );
+    return state.updateIn(['accounts', account.get('name')], Map(), a => a.mergeDeep(account));
 };
 
 export default function reducer(state = defaultState, action = {}) {
@@ -72,9 +70,7 @@ export default function reducer(state = defaultState, action = {}) {
     switch (action.type) {
         case SET_COLLAPSED: {
             return state.withMutations(map => {
-                map.updateIn(['content', payload.post], value =>
-                    value.merge(Map({ collapsed: payload.collapsed }))
-                );
+                map.updateIn(['content', payload.post], value => value.merge(Map({ collapsed: payload.collapsed })));
             });
         }
 
@@ -92,15 +88,10 @@ export default function reducer(state = defaultState, action = {}) {
                     flag_weight: 0,
                 },
             };
-            return state.updateIn(['content', key], Map(), c =>
-                c.mergeDeep(update)
-            );
+            return state.updateIn(['content', key], Map(), c => c.mergeDeep(update));
 
         case RECEIVE_STATE: {
-            console.log(
-                'Merging state',
-                state.mergeDeep(fromJS(payload)).toJS()
-            );
+            console.log('Merging state', state.mergeDeep(fromJS(payload)).toJS());
             return state.mergeDeep(fromJS(payload));
         }
 
@@ -109,9 +100,7 @@ export default function reducer(state = defaultState, action = {}) {
             return state.updateIn(['notifications', payload.name], Map(), n =>
                 n.withMutations(nmut =>
                     nmut
-                        .update('notifications', List(), a =>
-                            a.concat(fromJS(payload.notifications))
-                        )
+                        .update('notifications', List(), a => a.concat(fromJS(payload.notifications)))
                         .set('isLastPage', payload.isLastPage)
                 )
             );
@@ -141,20 +130,22 @@ export default function reducer(state = defaultState, action = {}) {
         }
 
         case RECEIVE_POST_HEADER: {
-            return state.update('headers', Map(), a =>
-                a.mergeDeep(fromJS(payload))
-            );
+            return state.update('headers', Map(), a => a.mergeDeep(fromJS(payload)));
         }
 
         case RECEIVE_COMMUNITIES: {
-            const map = Map(payload.map(c => [c.name, fromJS(c)]));
-            const idx = List(payload.map(c => c.name));
-            if (map.length <= 0) {
-                debugger;
+            let map = null;
+            let idx = null;
+
+            if (payload !== null) {
+                map = Map(payload.map(c => [c.name, fromJS(c)]));
+                idx = List(payload.map(c => c.name));
+                if (map.length <= 0) {
+                    debugger;
+                }
             }
-            return state
-                .setIn(['community'], map)
-                .setIn(['community_idx'], idx);
+
+            return state.setIn(['community'], map).setIn(['community_idx'], idx);
         }
 
         case RECEIVE_COMMUNITY: {
@@ -166,10 +157,7 @@ export default function reducer(state = defaultState, action = {}) {
         }
 
         case RECEIVE_SUBSCRIPTIONS: {
-            return state.setIn(
-                ['subscriptions', payload.username],
-                fromJS(payload.subscriptions)
-            );
+            return state.setIn(['subscriptions', payload.username], fromJS(payload.subscriptions));
         }
         case RECEIVE_REWARDS: {
             return state.set('rewards', fromJS(payload.rewards));
@@ -177,17 +165,11 @@ export default function reducer(state = defaultState, action = {}) {
 
         // Interleave special posts into the map of posts.
         case SYNC_SPECIAL_POSTS: {
-            return payload.featuredPosts
-                .concat(payload.promotedPosts)
-                .reduce((acc, specialPost) => {
-                    const author = specialPost.get('author');
-                    const permlink = specialPost.get('permlink');
-                    return acc.updateIn(
-                        ['content', `${author}/${permlink}`],
-                        Map(),
-                        p => p.mergeDeep(specialPost)
-                    );
-                }, state);
+            return payload.featuredPosts.concat(payload.promotedPosts).reduce((acc, specialPost) => {
+                const author = specialPost.get('author');
+                const permlink = specialPost.get('permlink');
+                return acc.updateIn(['content', `${author}/${permlink}`], Map(), p => p.mergeDeep(specialPost));
+            }, state);
         }
 
         case RECEIVE_CONTENT: {
@@ -196,9 +178,7 @@ export default function reducer(state = defaultState, action = {}) {
             console.log('received content...', payload.content);
 
             // merge content object into map
-            let new_state = state.updateIn(['content', key], Map(), c =>
-                c.mergeDeep(content)
-            );
+            let new_state = state.updateIn(['content', key], Map(), c => c.mergeDeep(content));
 
             // merge vote info taking pending votes into account
             let votes_key = ['content', key, 'active_votes'];
@@ -219,12 +199,7 @@ export default function reducer(state = defaultState, action = {}) {
         }
 
         case LINK_REPLY: {
-            const {
-                author,
-                permlink,
-                parent_author = '',
-                parent_permlink = '',
-            } = payload;
+            const { author, permlink, parent_author = '', parent_permlink = '' } = payload;
             const parent_key = postKey(parent_author, parent_permlink);
             if (!parent_key) return state;
             const key = author + '/' + permlink;
@@ -234,15 +209,8 @@ export default function reducer(state = defaultState, action = {}) {
                 List(),
                 l => (l.findIndex(i => i === key) === -1 ? l.push(key) : l)
             );
-            const children = updatedState.getIn(
-                ['content', parent_key, 'replies'],
-                List()
-            ).size;
-            updatedState = updatedState.updateIn(
-                ['content', parent_key, 'children'],
-                0,
-                () => children
-            );
+            const children = updatedState.getIn(['content', parent_key, 'replies'], List()).size;
+            updatedState = updatedState.updateIn(['content', parent_key, 'children'], 0, () => children);
             return updatedState;
         }
 
@@ -250,16 +218,11 @@ export default function reducer(state = defaultState, action = {}) {
             const { author, permlink } = payload;
             const key = author + '/' + permlink;
             const content = state.getIn(['content', key]);
-            const parent_key = postKey(
-                content.get('parent_author'),
-                content.get('parent_permlink')
-            );
+            const parent_key = postKey(content.get('parent_author'), content.get('parent_permlink'));
             let updatedState = state.deleteIn(['content', key]);
             if (parent_key) {
-                updatedState = updatedState.updateIn(
-                    ['content', parent_key, 'replies'],
-                    List(),
-                    r => r.filter(i => i !== key)
+                updatedState = updatedState.updateIn(['content', parent_key, 'replies'], List(), r =>
+                    r.filter(i => i !== key)
                 );
             }
             return updatedState;
@@ -281,12 +244,9 @@ export default function reducer(state = defaultState, action = {}) {
 
         case FETCHING_DATA: {
             const { order, category } = payload;
-            const new_state = state.updateIn(
-                ['status', category || '', order],
-                () => {
-                    return { fetching: true };
-                }
-            );
+            const new_state = state.updateIn(['status', category || '', order], () => {
+                return { fetching: true };
+            });
             return new_state;
         }
 
@@ -316,15 +276,12 @@ export default function reducer(state = defaultState, action = {}) {
             });
 
             // update status
-            new_state = new_state.updateIn(
-                ['status', category || '', order],
-                () => {
-                    if (endOfData) {
-                        return { fetching, last_fetch: new Date() };
-                    }
-                    return { fetching };
+            new_state = new_state.updateIn(['status', category || '', order], () => {
+                if (endOfData) {
+                    return { fetching, last_fetch: new Date() };
                 }
-            );
+                return { fetching };
+            });
             return new_state;
         }
 
@@ -335,9 +292,7 @@ export default function reducer(state = defaultState, action = {}) {
         }
 
         case REMOVE: {
-            const key = Array.isArray(payload.key)
-                ? payload.key
-                : [payload.key];
+            const key = Array.isArray(payload.key) ? payload.key : [payload.key];
             return state.removeIn(key);
         }
 
@@ -357,9 +312,7 @@ export default function reducer(state = defaultState, action = {}) {
 
         case SHOW_DIALOG: {
             const { name, params = {} } = payload;
-            return state.update('active_dialogs', Map(), d =>
-                d.set(name, fromJS({ params }))
-            );
+            return state.update('active_dialogs', Map(), d => d.set(name, fromJS({ params })));
         }
 
         case HIDE_DIALOG: {
-- 
GitLab