Open DerekHung opened 7 years ago
提供 mobile-web 胤廷有經過重新設計的 action
import * as GroupApi from './group_api';
import {loadListDataCenter, initialEntity} from 'src/client/actions/general';
import {isWrong} from 'src/util/checkTools';
const domain = 'group';
/**
* 當group要取得到非PageModel的資料使用的
* 目前用於
* - 請求取得所有Group的類別queryGroupCategoryList()
* - 取得自己的社團的初始資料getMyGroupInitData()(有五大類)
*
* @param {object} {domain, key, ...option} - 內涵domain, key, 其餘的會被放入option中
*/
export const REQUEST_GROUP_DATA = 'REQUEST_GROUP_DATA';
export const requestGroupData = ({domain, key, ...option}) => ({
type: REQUEST_GROUP_DATA,
payload: {domain, key, ...option},
});
/**
* 當group接收到非PageModel的資料使用的
* 目前用於
* - 請求取得所有Group的類別queryGroupCategoryList()
* - 取得自己的社團的初始資料getMyGroupInitData()(有五大類)
*
* @param {object} {domain, key, ...option} - 內涵domain, key, 其餘的會被放入option中
*/
export const RECEIVE_GROUP_DATA = 'RECEIVE_GROUP_DATA';
export const receiveGroupData = ({domain, key, ...option}) => ({
type: RECEIVE_GROUP_DATA,
payload: {domain, key, ...option},
});
/**
* 當group接收非PageModel資料發生錯誤時使用的
* 目前用於
* - 請求取得所有Group的類別queryGroupCategoryList()
* - 取得自己的社團的初始資料getMyGroupInitData()(有五大類)
* @param {object} {domain, key, ...option} - 內涵domain, key, 其餘的會被放入option中
*/
export const RECEIVE_GROUP_DATA_FAIL = 'RECEIVE_GROUP_DATA_FAIL';
export function receiveGroupDataFail({domain, key, option}) {
return (dispatch) => {
dispatch({
type: RECEIVE_GROUP_DATA_FAIL,
payload: {domain, key, option},
});
return Promise.reject(`FAIL [${domain}-${key}]`);
};
}
/**
* 切換group的tab
* 1. 發出切換group tab的action
* 2. 判斷此分頁(社團類別)是否有載入資料了
* -若無則去撈資料,subDomain為all or activity or member需要多設定option,dispatch(loadListDataCenter({...}))
*
* @param {string|number} tab - 要切換的分頁名,為Group類別的子項目
* @param {string} subDomain - 要切換的分頁類別,為'all' 或 'self' 或 'currentChannel'
* @param {number} channelId - 要切換的社團首頁的channelId
*/
export const CHANGE_GROUP_TAB = 'CHANGE_GROUP_TAB';
export const changeGroupTab = (tab, subDomain, channelId) => (dispatch, getState) => {
dispatch({
type: CHANGE_GROUP_TAB,
payload: {tab, subDomain, channelId},
});
/**
* A. 當subDomain === 'currentChannel'表示在社團獨立頁,須帶channelId
* 此時的tab會為activity(文章頁)、member(成員頁)
*
* B. 當subDomain為all或是self表示在列表頁
* 此時的tab會為社團分類如'知識技術','品味生活','joined', 'managed'...
*
* 要檢查切過去的分頁有沒有撈過資料,沒有的話要去打Api
*/
if (subDomain === 'currentChannel') {
if (!getState().entities.channels[channelId][tab].hasLoaded) {
return dispatch(loadListDataCenter({
domain: 'group',
key: tab,
channelId,
}));
}
} else if (!getState().group[subDomain].byGroup[tab].hasLoaded) {
return dispatch(loadListDataCenter({
domain: 'group',
key: tab,
}));
}
return Promise.resolve('done');
};
/**
* 進入公開社團時要觸發的action
* 1. 判斷是否載入過社團列表頁了 Object.keys(getState().group.all.byGroup).length > 0
* -無,打GroupApi.queryGroupCategoryList()取得所有Group的類別(目前預設有四大類)
* [TODO] 若此API失敗的處理
* 2. 切換分頁state.group.tab.all到第一個類別
*/
export const initGroupPage = () => (dispatch, getState) => {
dispatch({type: 'INIT_GROUP_PAGE'});
const key = 'initGroupPage';
let dummyPromise;
if (!Object.keys(getState().group.all.byGroup).length) {
dummyPromise = () => {
dispatch(requestGroupData({domain, key}));
return dispatch(GroupApi.queryGroupCategoryList()).then(({response}) => {
if (isWrong(response)) {
return dispatch(receiveGroupDataFail({domain, key}));
}
return dispatch(receiveGroupData({domain, key, response}));
});
};
} else {
dummyPromise = () => Promise.resolve();
}
return dummyPromise()
.then(() => {
const firstGroupName = Object.keys(getState().group.all.byGroup)[0];
return dispatch(changeGroupTab(firstGroupName, 'all'));
})
.catch((reason) => { console.info(reason); });
};
/**
* 進入我的社團時要觸發的action
* 1. 判斷是否載入過我的社團列表頁了 state.group.self.length > 0
* -無,打GroupApi.getMyGroupInitData()取得自己的社團的初始資料(有五大類)
* 2. 切換分頁state.group.tab.all到第一個類別
*/
export const initMyGroupPage = () => (dispatch, getState) => {
dispatch({type: 'INIT_MY_GROUP_PAGE'});
const key = 'initMyGroupPage';
let dummyPromise;
if (!Object.keys(getState().group.self.byGroup).length) {
dummyPromise = () => {
dispatch(requestGroupData({domain, key}));
return dispatch(GroupApi.getMyGroupInitData()).then(({response}) => {
if (isWrong(response)) {
return dispatch(receiveGroupDataFail({domain, key}));
}
return dispatch(receiveGroupData({domain, key, response}));
});
};
} else {
dummyPromise = () => Promise.resolve();
}
return dummyPromise().then(() => {
const firstGroupName = Object.keys(getState().group.self.byGroup)[0];
return dispatch(changeGroupTab(firstGroupName, 'self'));
});
};
/**
* 進入社團首頁時觸發的action
* 1. 進入initSingleGroupInfo這個function,去看entities納的channels是否存在此channelId的資料了
* 2. 切換group的分頁
*
* @param {number} channelId - 要進入的社團的channelId
*/
export const initGroupMainPage = channelId => (dispatch, getState) => {
dispatch({type: 'INIT_GROUP_MAIN_PAGE'});
return initSingleGroupInfo(dispatch, getState, channelId)
.then(() => dispatch(changeGroupTab('activity', 'currentChannel', channelId)));
};
/**
* 進入社團首頁的成員列表時觸發的action
* 1. 進入initSingleGroupInfo這個function,去看entities納的channels是否存在此channelId的資料了
* 2. 切換group的分頁
*
* @param {number} channelId - 要進入的社團的channelId
*/
export const initGroupMemberPage = channelId => (dispatch, getState) => {
dispatch({type: 'INIT_GROUP_Group_PAGE'});
return initSingleGroupInfo(dispatch, getState, channelId)
.then(() => dispatch(changeGroupTab('member', 'currentChannel', channelId)));
};
/**
* 判斷entities內的channels是否已經有此channel的資料
* 目前只用在initGroupMemberPage與initGroupMainPage
*
* @param {function} dispatch - store的dispatch
* @param {function} getState - store的getState
* @param {number} channelId - 要進入的社團的channelId
*/
function initSingleGroupInfo(dispatch, getState, channelId) {
const key = 'initSingleGroup';
const entity = getState().entities.channels[channelId];
// 若不存在於entities中或沒載入過,去取得groupInfo並且新增於entities.channels[channelId]
const dummyPromise = !entity || entity.hasLoaded
? () => dispatch(GroupApi.getGroupInfo({channelId}))
.then((res) => {
const source = isWrong(res.response) ? {} : res.response;
dispatch(initialEntity({
toEntity: 'channels',
domain,
key,
channelId,
source,
}));
})
: () => Promise.resolve();
return dummyPromise();
}
*修改已有的機制 1.input、output,有被定義過,類似 data schema
*可以更好的地方:
1.呼叫 api 方法,可以再抽出公用方法 2.錯誤處理流程,統一回傳幾種 type 3.邏輯判斷,另外用方法抽離
以下表列幾種code中的action 寫法 action 撰寫的方式不一致之外,有些寫法會造成大量的side effect 再來相似的action 在get / post 的時候沒有固定的流程跟驗證