diff --git a/src/app/components/pages/CommunitiesIndex.jsx b/src/app/components/pages/CommunitiesIndex.jsx index 014f043b003d7bc6adf4cc93ed959577ed76f7d5..a1fc9e3597ad72ffcd0a864d4405e6c599d9c1d8 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 •{' '} - {comm.num_authors} posters • {comm.num_pending}{' '} - posts + {comm.subscribers} + subscribers • {comm.num_authors} posters • {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 83c3f4762a87cfd88cdb8efab4fc98de623493c6..39a1c805bae74ab5d0e3ebfcbeeb3e0fa6201d25 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 eda56b32d0cc1e1a41bffcfe09a354f30121f7d7..df00797dcc0c16a8b1aac4a2a7ab0b0b522d2ba8 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: {