[Enhancement] Apply immutable js. (#49)

This commit is contained in:
Qolzam
2018-04-04 10:33:15 +07:00
parent b94d2a0124
commit 9cd2672395
98 changed files with 1294 additions and 1633 deletions

View File

@@ -6,41 +6,35 @@ import { AuthorizeActionType } from 'constants/authorizeActionType'
import { IAuthorizeAction } from './IAuthorizeAction'
import { AuthorizeState } from './AuthorizeState'
import { Map } from 'immutable'
/**
* Authorize reducer
* @param {object} state
* @param {object} action
*/
export let authorizeReducer = (state: AuthorizeState = new AuthorizeState(), action: IAuthorizeAction) => {
export let authorizeReducer = (state = Map(new AuthorizeState()), action: IAuthorizeAction) => {
const { payload } = action
switch (action.type) {
case AuthorizeActionType.LOGIN:
return{
...state,
uid: payload.uid,
authed: true,
guest: false,
isVerifide: payload.isVerifide
}
case AuthorizeActionType.LOGOUT:
return{
...state,
uid: 0,
authed: false,
guest: true
}
return state
.set('uid', payload.uid)
.set('authed', true)
.set('guest', false)
.set('isVerifide', payload.isVerifide)
case AuthorizeActionType.LOGOUT:
return state
.set('uid', 0)
.set('authed', false)
.set('guest', true)
.set('isVerifide', false)
case AuthorizeActionType.SIGNUP:
return{
...state,
uid: payload.userId
}
return state
.set('uid', payload.userId)
case AuthorizeActionType.UPDATE_PASSWORD:
return{
...state,
updatePassword: payload.updatePassword
}
return state
.set('updatePassword', payload.updatePassword)
default:
return state

View File

@@ -1,4 +1,8 @@
const getCurrentUser = (state: any) => (state.user.info && state.authorize.uid) ? state.user.info[state.authorize.uid] : null
import {Map} from 'immutable'
const getCurrentUser = (state: Map<any, string>) => {
const uid = state.getIn(['authorize', 'uid'])
return state.getIn(['user', 'info', uid])
}
export const authorizeSelector = {
getCurrentUser

View File

@@ -1,4 +1,5 @@
import { Circle, UserTie } from 'src/core/domain/circles'
import {Map} from 'immutable'
/**
* Circle state
@@ -12,19 +13,19 @@ export class CircleState {
*
* @memberof CircleState
*/
userTies: { [userId: string]: UserTie } = {}
userTies: Map<string, UserTie> = Map({})
/**
* The list of users belong to users circle
*
* @memberof CircleState
*/
userTieds: { [userId: string]: UserTie } = {}
userTieds: Map<string, UserTie> = Map({})
/**
* The list of circle of current user
*/
circleList: { [circleId: string]: Circle }
circleList: Map<string, Circle> = Map({})
/**
* Whether select circle box is open for the selected user
@@ -39,7 +40,7 @@ export class CircleState {
/**
* Keep selected circles for refere user
*/
selectedCircles: { [userId: string]: string[] }
selectedCircles: Map<string, string[]> = Map({})
/**
* Whether the select circles box for referer user is open

View File

@@ -1,6 +1,7 @@
// - Import react components
import moment from 'moment/moment'
import _ from 'lodash'
import { Map, List } from 'immutable'
// - Import domain
import { User } from 'src/core/domain/users'
@@ -12,245 +13,120 @@ import { CircleActionType } from 'constants/circleActionType'
import { CircleState } from './CircleState'
import { ICircleAction } from './ICircleAction'
/**
* Add circle
*/
const addCircle = (state: any , payload: any) => {
const circle: Map<string, any> = payload.circle
return state
.setIn(['circleList', circle.get('id')], payload.circle)
}
/**
* Update circle
*/
const updateCircle = (state: any , payload: any) => {
const circle: Map<string, any> = payload.circle
return state
.setIn(['openSetting', circle.get('id')], false)
.setIn(['circleList', circle.get('id')], payload.circle)
}
/**
* Circle reducer
* @param state
* @param action
*/
export let circleReducer = (state: CircleState = new CircleState(), action: ICircleAction) => {
export let circleReducer = (state = Map(new CircleState()), action: ICircleAction) => {
const { payload } = action
switch (action.type) {
case CircleActionType.CLEAR_ALL_CIRCLES:
return new CircleState()
return Map(new CircleState())
case CircleActionType.ADD_CIRCLE:
return {
...state,
circleList: {
...state.circleList,
[payload.circle.id]: {
...payload.circle
}
}
}
case CircleActionType.UPDATE_CIRCLE:
return {
...state,
openSetting: {
...state.openSetting,
[payload.circle.id]: false
},
circleList: {
...state.circleList,
[payload.circle.id]: {
...payload.circle
}
}
}
case CircleActionType.ADD_CIRCLE: return addCircle(state, payload)
case CircleActionType.UPDATE_CIRCLE: return updateCircle(state, payload)
case CircleActionType.DELETE_CIRCLE:
let filteredDeleteCircles = {}
Object.keys(state.circleList).map((key) => {
if (key !== payload.circleId) {
return _.merge(filteredDeleteCircles, { [key]: { ...state.circleList![key] } })
}
})
return {
...state,
circleList: {
...state.circleList,
...filteredDeleteCircles
}
}
return state
.deleteIn(['circleList', payload.circleId])
case CircleActionType.ADD_LIST_CIRCLE:
return {
...state,
circleList: {
...state.circleList,
...payload.circleList
},
loaded: true
}
return state
.set('loaded', true)
.mergeIn(['circleList'], payload.circleList)
case CircleActionType.ADD_FOLLOWING_USER:
return {
...state,
userTies: {
...state.userTies,
[payload.userTie.userId]: {
...payload.userTie
}
},
selectedCircles: {
...state.selectedCircles,
[payload.userTie.userId]: payload.userTie.circleIdList
}
}
const userTie: Map<string, any> = payload.userTie
return state
.setIn(['userTies', userTie.get('userId')], payload.userTie)
.setIn(['selectedCircles', userTie.get('userId')], userTie.get('circleIdList'))
case CircleActionType.UPDATE_USER_TIE:
return {
...state,
userTies: {
...state.userTies,
[payload.userTie.user.userId]: {
...payload.userTie
}
}
}
return state
.setIn(['userTies', payload.userTie.user.userId], payload.userTie)
case CircleActionType.ADD_USER_TIE_LIST:
return {
...state,
userTies: {
...state.userTies,
...payload.userTies
},
selectedCircles : getSelectedCircles(payload.userTies)
}
return state
.mergeIn(['userTies'], payload.userTies)
.set('selectedCircles', getSelectedCircles(payload.userTies))
case CircleActionType.ADD_USER_TIED_LIST:
return {
...state,
userTieds: {
...state.userTieds,
...payload.userTieds
}
}
return state
.mergeIn(['userTieds'], payload.userTieds)
case CircleActionType.DELETE_USER_FROM_CIRCLE:
let filteredCircles: string[] = []
Object.keys(state.userTies[payload.userId].circleIdList!).forEach((circleId) => {
if (circleId !== payload.circleId) {
filteredCircles.push(circleId)
}
})
return {
...state,
userTies: {
...state.userTies,
[payload.userTie.user.userId]: {
...payload.userTie,
circleIdList: filteredCircles
}
}
}
return state
.deleteIn(['userTies', payload.userTie.user.userId, 'circleIdList', payload.circleId])
case CircleActionType.DELETE_FOLLOWING_USER:
let filteredUserTies: {[userId: string]: UserTie } = {}
return state
.deleteIn(['userTies', payload.userId])
.deleteIn(['selectedCircles', payload.userId])
Object.keys(state.userTies).forEach((userId) => {
if (userId !== payload.userId) {
return _.merge(filteredUserTies, { [userId]: { ...state.userTies[userId] } })
}
})
return {
...state,
userTies: {
...filteredUserTies
},
selectedCircles : getSelectedCircles(filteredUserTies)
}
/**
* User interface stuffs
*/
/**
* User interface stuffs
*/
case CircleActionType.CLOSE_CIRCLE_SETTINGS:
return {
...state,
openSetting: {
...state.openSetting,
[payload.circleId]: false
}
}
return state
.setIn(['openSetting', payload.circleId], false)
case CircleActionType.OPEN_CIRCLE_SETTINGS:
return {
...state,
openSetting: {
...state.openSetting,
[payload.circleId]: true
}
}
return state
.setIn(['openSetting', payload.circleId], true)
case CircleActionType.SHOW_SELECT_CIRCLE_BOX:
return {
...state,
selectCircleStatus: {
...state.selectCircleStatus,
[payload.userId]: true
}
}
return state
.setIn(['selectCircleStatus', payload.userId], true)
case CircleActionType.HIDE_SELECT_CIRCLE_BOX:
return {
...state,
selectCircleStatus: {
...state.selectCircleStatus,
[payload.userId]: false
}
}
return state
.setIn(['selectCircleStatus', payload.userId], false)
case CircleActionType.SHOW_FOLLOWING_USER_LOADING:
return {
...state,
followingLoadingStatus: {
...state.followingLoadingStatus,
[payload.userId]: true
}
}
return state
.setIn(['followingLoadingStatus', payload.userId], true)
case CircleActionType.HIDE_FOLLOWING_USER_LOADING:
return {
...state,
followingLoadingStatus: {
...state.followingLoadingStatus,
[payload.userId]: false
}
}
return state
.setIn(['followingLoadingStatus', payload.userId], false)
/**
* User box component
*/
case CircleActionType.SET_SELECTED_CIRCLES_USER_BOX_COMPONENT:
return {
...state,
selectedCircles: {
...state.selectedCircles,
[payload.userId]: payload.circleList
}
}
/**
* User box component
*/
return state
.setIn(['selectedCircles', payload.userId], payload.circleList)
case CircleActionType.REMOVE_SELECTED_CIRCLES_USER_BOX_COMPONENT:
return {
...state,
selectedCircles: {
...state.selectedCircles,
[payload.userId]: []
}
}
/**
* User box component
*/
return state
.setIn(['selectedCircles', payload.userId], [])
case CircleActionType.OPEN_SELECT_CIRCLES_USER_BOX_COMPONENT:
return {
...state,
openSelecteCircles: {
...state.openSelecteCircles,
[payload.userId]: true
}
}
return state
.setIn(['openSelecteCircles', payload.userId], true)
case CircleActionType.CLOSE_SELECT_CIRCLES_USER_BOX_COMPONENT:
return {
...state,
openSelecteCircles: {
...state.openSelecteCircles,
[payload.userId]: false
}
}
return state
.setIn(['openSelecteCircles', payload.userId], false)
default:
return state
@@ -260,14 +136,11 @@ export let circleReducer = (state: CircleState = new CircleState(), action: ICir
/**
* Map user ties selected to selected circles
*/
const getSelectedCircles = (userTies: {[userId: string]: UserTie }) => {
let selectedCircles: {[userId: string]: string[]} = {}
const getSelectedCircles = (userTies: { [userId: string]: UserTie }) => {
let selectedCircles: Map<string, List<string>> = Map({})
Object.keys(userTies).forEach((userId: string) => {
const userTie = (userTies as {[userId: string]: UserTie })[userId]
selectedCircles = {
...selectedCircles,
[userTie.userId!]: userTie.circleIdList!
}
const userTie = (userTies as { [userId: string]: UserTie })[userId]
selectedCircles = selectedCircles.set(userTie.userId!, List(userTie.circleIdList!))
})
return selectedCircles

View File

@@ -1,6 +1,6 @@
import { Comment } from 'src/core/domain/comments'
import {Map} from 'immutable'
/**
* Comment state
*
@@ -11,22 +11,16 @@ export class CommentState {
/**
* The list of comments on the posts
*
* @type {({[postId: string]: {[commentId: string]: Comment}} | null)}
* @memberof CommentState
*/
postComments: {[postId: string]: {[commentId: string]: Comment}} = {}
postComments: Map<string, {[commentId: string]: Comment}> = Map({})
/**
* Whether comment editor is open
*/
editorStatus: {[postId: string]: {[commentId: string]: boolean}} = {}
editorStatus: Map<string, {[commentId: string]: boolean}> = Map({})
/**
* If the comments are loaded {true} or not {false}
*
* @type {Boolean}
* @memberof CommentState
*/
loaded: Boolean = false
}

View File

@@ -1,6 +1,7 @@
// - Import react components
import moment from 'moment/moment'
import _ from 'lodash'
import { Map } from 'immutable'
// - Import domain
import { User } from 'src/core/domain/users'
@@ -17,96 +18,38 @@ import { ICommentAction } from './ICommentAction'
* @param state
* @param action
*/
export let commentReducer = (state: CommentState = new CommentState(), action: ICommentAction) => {
export let commentReducer = (state = Map(new CommentState()), action: ICommentAction) => {
let { payload } = action
switch (action.type) {
/* _____________ CRUD _____________ */
case CommentActionType.ADD_COMMENT:
return {
...state,
postComments: {
...state.postComments,
[payload.postId]: {
...state.postComments![payload.postId],
[payload.id]: {
...payload,
editorStatus: false
}
}
return state
.setIn(['postComments', payload.postId, payload.id], payload)
}
}
case CommentActionType.ADD_COMMENT_LIST:
return {
...state,
postComments: {
...state.postComments,
...payload
},
loaded: true
}
case CommentActionType.UPDATE_COMMENT:
const {comment} = payload
return {
...state,
postComments: {
...state.postComments,
[comment.postId]: {
...state.postComments![comment.postId],
[comment.id]: {
...state.postComments![comment.postId][comment.id],
text: comment.text,
editorStatus: false
}
}
}
}
case CommentActionType.DELETE_COMMENT:
if (!state.postComments![payload.postId]) {
return state
}
let parsedComments = {}
Object.keys(state.postComments![payload.postId]).map((id) => {
if (id !== payload.id) {
_.merge(parsedComments, { [id]: { ...state.postComments![payload.postId][id] } })
}
return state
.mergeIn(['postComments'], payload)
.set('loaded', true)
case CommentActionType.UPDATE_COMMENT:
const { comment } = payload
return state
.updateIn(['postComments', comment.postId, comment.id, 'text'], (text: string) => comment.text)
case CommentActionType.DELETE_COMMENT:
return state.deleteIn(['postComments', payload.postId, payload.id])
})
return {
...state,
postComments: {
...state.postComments,
[payload.postId]: {
...parsedComments
}
}
}
case CommentActionType.CLOSE_COMMENT_EDITOR:
return {
...state,
editorStatus: {
...state.editorStatus,
[payload.postId]: {
...state.editorStatus![payload.postId],
[payload.id]: false
}
}
}
return state
.setIn(['editorStatus', payload.postId, payload.id], false)
case CommentActionType.OPEN_COMMENT_EDITOR:
return {
...state,
editorStatus: {
...state.editorStatus,
[payload.postId]: {
...state.editorStatus![payload.postId],
[payload.id]: true
}
}
}
return state
.setIn(['editorStatus', payload.postId, payload.id], true)
case CommentActionType.CLEAR_ALL_DATA_COMMENT:
return new CommentState()
return Map(new CommentState())
default:
return state

View File

@@ -1,3 +1,4 @@
import { Map, fromJS, List } from 'immutable'
/**
* Global state
*
@@ -15,13 +16,10 @@ export class GlobalState {
* }}
* @memberof IGlobalState
*/
progress: {
percent: number
visible: boolean
} = {
progress = Map({
percent: 0,
visible: false
}
})
/**
* If loading is enabled {true} or not false
@@ -122,7 +120,7 @@ export class GlobalState {
* @type {*}
* @memberof IGlobalState
*/
temp: any = {
caller: []
}
temp: any = Map({
caller: List()
})
}

View File

@@ -3,112 +3,86 @@ import { GlobalActionType } from 'constants/globalActionType'
import { GlobalState } from './GlobalState'
import { IGlobalAction } from './IGlobalAction'
import { Map, fromJS } from 'immutable'
/**
* Global reducer
* @param {object} state
* @param {object} action
*/
export const globalReducer = (state: GlobalState = new GlobalState(), action: IGlobalAction) => {
export const globalReducer = (state = Map(new GlobalState()), action: IGlobalAction) => {
const { payload } = action
switch (action.type) {
case GlobalActionType.PROGRESS_CHANGE:
return {
...state,
progress: {
...state.progress,
percent: payload.percent,
visible: payload.visible
}
}
return state
.setIn(['progress', 'percent'], payload.percent)
.setIn(['progress', 'visible'], payload.visible)
case GlobalActionType.DEFAULT_DATA_DISABLE:
return {
...state,
defaultLoadDataStatus: false
}
return state
.set('defaultLoadDataStatus', false)
case GlobalActionType.DEFAULT_DATA_ENABLE:
return {
...state,
defaultLoadDataStatus: true
}
return state
.set('defaultLoadDataStatus', true)
case GlobalActionType.SHOW_MESSAGE_GLOBAL:
return {
...state,
message: action.payload,
messageOpen: true
}
return state
.set('message', action.payload)
.set('messageOpen', true)
case GlobalActionType.SHOW_NORMAL_MESSAGE_GLOBAL:
return {
...state,
message: action.payload,
messageOpen: true
}
return state
.set('message', action.payload)
.set('messageOpen', true)
case GlobalActionType.HIDE_MESSAGE_GLOBAL:
return {
...state,
message: '',
messageOpen: false,
messageColor: ''
}
return state
.set('message', action.payload)
.set('messageOpen', false)
.set('messageColor', '')
case GlobalActionType.SET_HEADER_TITLE:
return {
...state,
headerTitle: action.payload
}
return state
.set('headerTitle', action.payload)
case GlobalActionType.SHOW_SEND_FEEDBACK:
return {
...state,
sendFeedbackStatus: true
}
return state
.set('sendFeedbackStatus', true)
case GlobalActionType.HIDE_SEND_FEEDBACK:
return {
...state,
sendFeedbackStatus: false
}
return state
.set('sendFeedbackStatus', false)
case GlobalActionType.HIDE_TOP_LOADING:
const queueTopLoading = state.topLoadingQueue > 0 ? (state.topLoadingQueue - 1) : 0
return {
...state,
topLoadingQueue: queueTopLoading,
showTopLoading: (queueTopLoading > 0 ? true : false)
const queueTopLoading = Number(state.get('topLoadingQueue')) > 0 ? (Number(state.get('topLoadingQueue')) - 1) : 0
return state
.set('topLoadingQueue', queueTopLoading)
.set('showTopLoading', (queueTopLoading > 0 ? true : false))
}
case GlobalActionType.SHOW_TOP_LOADING:
return {
...state,
topLoadingQueue: (state.topLoadingQueue + 1),
showTopLoading: true
}
case GlobalActionType.HIDE_MASTER_LOADING:
const queueMasterLoading = state.masterLoadingQueue > 0 ? (state.masterLoadingQueue - 1) : 0
return {
...state,
masterLoadingQueue: queueMasterLoading,
showMasterLoading: (queueMasterLoading > 0 ? true : false)
return state
.set('topLoadingQueue', (Number(state.get('topLoadingQueue')) + 1))
.set('showTopLoading', true)
case GlobalActionType.HIDE_MASTER_LOADING:
const queueMasterLoading = Number(state.get('masterLoadingQueue')) > 0 ? (Number(state.get('masterLoadingQueue')) - 1) : 0
return state
.set('masterLoadingQueue', queueMasterLoading)
.set('showMasterLoading', (queueMasterLoading > 0 ? true : false))
}
case GlobalActionType.SHOW_MASTER_LOADING:
return {
...state,
masterLoadingQueue: (state.masterLoadingQueue + 1),
showMasterLoading: true
}
return state
.set('masterLoadingQueue', Number(state.get('masterLoadingQueue')) + 1)
.set('showMasterLoading', true)
case GlobalActionType.TEMP:
return {
...state,
temp: {
...state.temp,
caller: [
...state.temp.caller,
payload.caller
]
}
}
case GlobalActionType.CLEAR_ALL_GLOBAL:
return {
...state,
sendFeedbackStatus: false,
}
return state
.mergeIn(['temp', 'caller'], fromJS([payload.caller]))
case GlobalActionType.CLEAR_ALL_GLOBAL:
return state
.set('sendFeedbackStatus', false)
default:
return state

View File

@@ -1,4 +1,5 @@
import { Image } from 'src/core/domain/imageGallery'
import {Map, Collection, List} from 'immutable'
/**
* ImageGallery state
@@ -18,49 +19,31 @@ export class ImageGalleryState {
/**
* The list of image
*
* @type {(Image[] | null)}
* @memberof ImageGalleryState
*/
images: Image[] = []
images: List<Image> = List()
/**
* Selected image name
*
* @type {string}
* @memberof ImageGalleryState
*/
selectImage: string = ''
/**
* Selected image address
*
* @type {string}
* @memberof ImageGalleryState
*/
selectURL: string = ''
/**
* If image gallery is loaded {true} or not false
*
* @type {Boolean}
* @memberof ImageGalleryState
*/
loaded: Boolean = false
/**
* Images address list
*
* @type {*}
* @memberof ImageGalleryState
*/
imageURLList: any = {}
/**
* Store image requested
*
* @type {*}
* @memberof ImageGalleryState
*/
imageRequests: any = {}

View File

@@ -1,5 +1,6 @@
// - Import react components
import _ from 'lodash'
import { Map, List } from 'immutable'
// - Import domain
import { User } from 'src/core/domain/users'
@@ -14,52 +15,36 @@ import { ImageGalleryState } from './ImageGalleryState'
/**
* Image gallery reducer
*/
export let imageGalleryReducer = (state: ImageGalleryState = new ImageGalleryState(), action: IImageGalleryAction) => {
export let imageGalleryReducer = (state = Map(new ImageGalleryState()), action: IImageGalleryAction) => {
const { payload } = action
switch (action.type) {
/* ----------------- CRUD ----------------- */
case ImageGalleryActionType.ADD_IMAGE_GALLERY:
return {
...state,
images: [...state.images!, payload]
}
return state
.mergeIn(['images'], List([payload]))
case ImageGalleryActionType.ADD_IMAGE_LIST_GALLERY:
return {
...state,
images: [...payload],
loaded: true
}
return state
.set('images', List(payload))
.set('loaded', true)
case ImageGalleryActionType.DELETE_IMAGE:
return {
...state,
images: [
...state.images!.filter((item: Image) => {
return item.id !== payload
})
]
}
return state
.update('images', (images: List<Image>) => {
return images.filter((image) => image!.id !== payload)
})
case ImageGalleryActionType.SET_IMAGE_URL:
return {
...state,
imageURLList: {
...state.imageURLList,
[payload.name]: payload.url
}
}
return state
.setIn(['imageURLList', payload.name], payload.url)
case ImageGalleryActionType.SEND_IMAGE_REQUEST:
return {
...state,
imageRequests: [
...state.imageRequests,
payload
]
}
return state
.mergeIn(['imageRequests'], payload)
case ImageGalleryActionType.CLEAT_ALL_DATA_IMAGE_GALLERY:
return new ImageGalleryState()
return Map(new ImageGalleryState())
default:
return state

View File

@@ -1,4 +1,5 @@
import { Notification } from 'src/core/domain/notifications'
import {Map} from 'immutable'
/**
* Notification state
@@ -10,17 +11,11 @@ export class NotificationState {
/**
* The list of users notification
*
* @type {({[userId: string]: {[notificationId: string]: Notification}} | null)}
* @memberof NotificationState
*/
userNotifies: {[userId: string]: {[notificationId: string]: Notification}} = {}
userNotifies: Map<string, Map<string, any>> = Map({})
/**
* If user notifications are loaded {true} or not {false}
*
* @type {Boolean}
* @memberof NotificationState
*/
loaded: Boolean = false
}

View File

@@ -1,6 +1,7 @@
// - Import react components
import moment from 'moment/moment'
import _ from 'lodash'
import { Map } from 'immutable'
// - Import domain
import { Notification } from 'src/core/domain/notifications'
@@ -16,7 +17,7 @@ import { INotificationAction } from './INotificationAction'
* @param {object} state
* @param {object} action
*/
export let notificationReducer = (state: NotificationState = new NotificationState(), action: INotificationAction) => {
export let notificationReducer = (state = Map(new NotificationState()), action: INotificationAction) => {
let { payload } = action
switch (action.type) {
@@ -25,44 +26,21 @@ export let notificationReducer = (state: NotificationState = new NotificationSta
return state
case NotificationActionType.ADD_NOTIFY_LIST:
return {
...state,
userNotifies: {
...payload
},
loaded: true
}
return state
.set('userNotifies', payload)
.set('loaded', true)
case NotificationActionType.SEEN_NOTIFY:
return {
...state,
userNotifies: {
...state.userNotifies,
[payload]: {
...state.userNotifies![payload],
isSeen: true
}
},
loaded: true
}
return state
.setIn(['userNotifies', payload, 'isSeen'], true)
.set('loaded', true)
case NotificationActionType.DELETE_NOTIFY:
let parsedNotifies = {}
Object.keys(state.userNotifies!).map((id) => {
if (id !== payload) {
_.merge(parsedNotifies, { [id]: { ...state.userNotifies![id] } })
}
})
return {
...state,
userNotifies: {
...parsedNotifies
}
}
return state
.deleteIn(['userNotifies', payload])
case NotificationActionType.CLEAR_ALL_DATA_NOTIFY:
return new NotificationState()
return Map(new NotificationState())
default:
return state

View File

@@ -1,4 +1,5 @@
import { Post } from 'src/core/domain/posts'
import { Map, fromJS, List } from 'immutable'
/**
* Post state
@@ -14,7 +15,7 @@ export class PostState {
* @type {*}
* @memberof PostState
*/
userPosts: any = {}
userPosts = Map({})
/**
* If user posts are loaded {true} or not {false}
@@ -27,12 +28,12 @@ export class PostState {
/**
* Stream data storage
*/
stream?: {hasMoreData: boolean, lastPageRequest: number, lastPostId: string} =
{hasMoreData: true, lastPageRequest: -1, lastPostId: ''}
stream?: Map<string,any> =
Map({hasMoreData: true, lastPageRequest: -1, lastPostId: ''})
/**
* Profile posts data storage
*/
profile?: {[userId: string]: {hasMoreData: boolean, lastPageRequest: number, lastPostId: string}} =
{}
profile?: Map<string, any> =
Map({})
}

View File

@@ -2,6 +2,7 @@
import moment from 'moment/moment'
import _ from 'lodash'
import { Reducer, Action } from 'redux'
import { Map } from 'immutable'
// - Import action types
import { PostActionType } from 'constants/postActionType'
@@ -11,167 +12,94 @@ import { IPostAction } from './IPostAction'
import { Post } from 'src/core/domain/posts/post'
import CommonAPI from 'src/api/CommonAPI'
const updatePost = (state: any, payload: any) => {
const post: Map<string, any> = payload.post
const updatePostOwnerId = post.get('ownerUserId')
const updatePostId = post.get('id')
return state
.setIn(['userPosts', updatePostOwnerId, updatePostId], Map(post))
}
const updatePostComments = (state: any, payload: any) => {
const post: Map<string, any> = payload.post
const updatePostOwnerId = post.get('ownerUserId')
const updatePostId = post.get('id')
return state
.setIn(['userPosts', updatePostOwnerId, updatePostId, 'comments'], post.get('comments'))
}
const updatePostVotes = (state: any, payload: any) => {
const post: Map<string, any> = payload.post
const updatePostOwnerId = post.get('ownerUserId')
const updatePostId = post.get('id')
return state
.setIn(['userPosts', updatePostOwnerId, updatePostId, 'votes'], post.get('votes'))
}
/**
* Post reducer
* @param {object} state
* @param {object} action
*/
export let postReducer = (state: PostState = new PostState(), action: IPostAction) => {
export let postReducer = (state = Map(new PostState()), action: IPostAction) => {
const { payload } = action
switch (action.type) {
case PostActionType.CLEAR_ALL_DATA_POST:
return new PostState()
return Map(new PostState())
case PostActionType.ADD_IMAGE_POST:
return {
...state,
userPosts: {
...state.userPosts,
[payload.uid]: {
...state.userPosts[payload.uid],
[payload.post.id]: { ...payload.post }
}
}
}
return state
.setIn(['userPosts', payload.uid, payload.post.id], Map(payload.post))
case PostActionType.ADD_POST:
return {
...state,
userPosts: {
...state.userPosts,
[payload.uid]: {
...state.userPosts[payload.uid],
[payload.post.id]: { ...payload.post }
}
}
}
return state
.setIn(['userPosts', payload.uid, payload.post.id], Map(payload.post))
case PostActionType.UPDATE_POST:
const post: Post = payload.post
return {
...state,
userPosts: {
...state.userPosts,
[post.ownerUserId!]: {
...state.userPosts[post.ownerUserId!],
[payload.post.id]: {
...payload.post,
comments: post.comments,
votes: post.votes
}
}
}
}
case PostActionType.UPDATE_POST: return updatePost(state, payload)
case PostActionType.UPDATE_POST_COMMENTS: return updatePostComments(state, payload)
case PostActionType.UPDATE_POST_VOTES: return updatePostVotes(state, payload)
case PostActionType.DELETE_POST:
let filteredPosts = {}
Object.keys(state.userPosts[payload.uid]).map((key) => {
if (key !== payload.id) {
return _.merge(filteredPosts, { [key]: { ...state.userPosts[payload.uid][key] } })
}
})
return {
...state,
userPosts: {
...state.userPosts,
[payload.uid]: {
...filteredPosts
}
}
}
return state
.deleteIn(['userPosts', payload.uid, payload.id])
case PostActionType.ADD_LIST_POST:
const newUserPosts = payload.userPosts as { [userId: string]: { [postId: string]: Post } }
const mergedObject = _.merge(state.userPosts, newUserPosts)
return {
...state,
userPosts: {
...mergedObject
},
loaded: true
return state
.mergeDeepIn(['userPosts'], payload.userPosts)
.set('loaded', true)
}
case PostActionType.HAS_MORE_DATA_STREAM:
return {
...state,
stream: {
...state.stream,
hasMoreData: true
}
return state
.setIn(['stream', 'hasMoreData'], true)
}
case PostActionType.NOT_MORE_DATA_STREAM:
return {
...state,
stream: {
...state.stream,
hasMoreData: false
}
}
return state
.setIn(['stream', 'hasMoreData'], false)
case PostActionType.REQUEST_PAGE_STREAM:
return {
...state,
stream: {
...state.stream,
lastPageRequest: payload.page
}
}
return state
.setIn(['stream', 'lastPageRequest'], payload.page)
case PostActionType.LAST_POST_STREAM:
return {
...state,
stream: {
...state.stream,
lastPostId: payload.lastPostId
}
}
return state
.setIn(['stream', 'lastPostId'], payload.lastPostId)
case PostActionType.HAS_MORE_DATA_PROFILE:
return {
...state,
profile: {
...state.profile,
hasMoreData: true
}
return state
.setIn(['profile', 'hasMoreData'], true)
}
case PostActionType.NOT_MORE_DATA_PROFILE:
return {
...state,
profile: {
...state.profile,
[payload.userId]: {
...state.profile![payload.userId],
hasMoreData: false
}
}
}
return state
.setIn(['profile', payload.userId, 'hasMoreData'], false)
case PostActionType.REQUEST_PAGE_PROFILE:
return {
...state,
profile: {
...state.profile,
[payload.userId]: {
...state.profile![payload.userId],
lastPageRequest: payload.page
}
}
}
return state
.setIn(['profile', payload.userId, 'lastPageRequest'], payload.page)
case PostActionType.LAST_POST_PROFILE:
return {
...state,
profile: {
...state.profile,
[payload.userId]: {
...state.profile![payload.userId],
lastPostId: payload.lastPostId
}
}
}
return state
.setIn(['profile', payload.userId, 'lastPostId'], payload.lastPostId)
default:
return state

View File

@@ -1,7 +1,7 @@
const getPost = (state: any, userId: string, postId: string) => {
return (state.post.userPosts && state.post.userPosts[userId] && state.post.userPosts[userId][postId])
? state.post.userPosts[userId][postId]
: null
import {Map} from 'immutable'
const getPost = (state: Map<string, any>, userId: string, postId: string) => {
return state.getIn(['post', 'userPosts', userId, postId])
}
export const postSelector = {

View File

@@ -1,5 +1,7 @@
import * as redux from 'redux'
import { localeReducer as locale } from 'react-localize-redux'
import {
combineReducers
} from 'redux-immutable'
// - Import reducers
import { authorizeReducer } from './authorize'
@@ -15,7 +17,7 @@ import { serverReducer } from './server'
import { routerReducer, routerMiddleware } from 'react-router-redux'
// - Reducers
export const rootReducer = redux.combineReducers({
export const rootReducer = combineReducers({
locale,
imageGallery: imageGalleryReducer,
post: postReducer,

View File

@@ -1,4 +1,5 @@
import { ServerRequestModel } from 'src/models/server'
import {Map} from 'immutable'
/**
* Server state
@@ -12,5 +13,5 @@ export class ServerState {
* The list of posts server
* @memberof ServerState
*/
request: {[requestId: string]: ServerRequestModel} | null = {}
request: Map<string, ServerRequestModel> = Map({})
}

View File

@@ -1,5 +1,6 @@
// - Import react components
import _ from 'lodash'
import { Map } from 'immutable'
// - Import action types
import { ServerActionType } from 'constants/serverActionType'
@@ -16,61 +17,30 @@ import { ServerRequestStatusType } from 'store/actions/serverRequestStatusType'
* @param {object} state
* @param {object} action
*/
export let serverReducer = (state: ServerState = new ServerState(), action: IServerAction) => {
export let serverReducer = (state = Map(new ServerState()), action: IServerAction) => {
let { payload } = action
const request = (payload ? payload.request : {}) as ServerRequestModel
switch (action.type) {
/* _____________ CRUD _____________ */
case ServerActionType.ADD_REQUEST:
return {
...state,
request: {
...state.request,
[request.id]: {
...request
}
}
}
case ServerActionType.DELETE_REQUEST:
let parsedRequests = {}
Object.keys(state.request!).forEach((id) => {
if (id !== request.id) {
_.merge(parsedRequests, { [id]: { ...state.request![id] } })
}
return state
.setIn(['request', request.id], request)
})
return {
...state,
request: parsedRequests
}
case ServerActionType.DELETE_REQUEST:
return state
.deleteIn(['request', request.id])
case ServerActionType.ERROR_REQUEST:
return {
...state,
request: {
...state.request,
[request.id]: {
...state.request![request.id],
status: ServerRequestStatusType.Error
}
}
}
return state
.setIn(['request', request.id, 'status'], ServerRequestStatusType.Error)
case ServerActionType.OK_REQUEST:
return {
...state,
request: {
...state.request,
[request.id]: {
...state.request![request.id],
status: ServerRequestStatusType.OK
}
}
}
return state
.setIn(['request', request.id, 'status'], ServerRequestStatusType.OK)
case ServerActionType.CLEAR_ALL_DATA_REQUEST:
return new ServerState()
return Map(new ServerState())
default:
return state

View File

@@ -1,4 +1,5 @@
import { User,Profile } from 'src/core/domain/users'
import { Map, fromJS, List } from 'immutable'
/**
* User state
@@ -9,31 +10,21 @@ import { User,Profile } from 'src/core/domain/users'
export class UserState {
/**
* The list of users information
*
* @type {({[userId: string]: Profile} | null)}
* @memberof UserState
*/
info: {[userId: string]: Profile} = {}
info: Map<string, Profile> = Map({})
/**
* If users profile are loaded
*
* @type {Boolean}
* @memberof UserState
*/
loaded: Boolean = false
/**
* If edit profile is open {true} or not {false}
*
* @type {Boolean}
* @memberof UserState
*/
openEditProfile: Boolean = false
/**
* People data storage
*/
people?: {hasMoreData: boolean, lastPageRequest: number, lastUserId: string} =
{hasMoreData: true, lastPageRequest: -1, lastUserId: ''}
people?: Map<string, any> = Map({hasMoreData: true, lastPageRequest: -1, lastUserId: ''})
}

View File

@@ -1,8 +1,9 @@
// - Import action types
import { UserActionType } from 'constants/userActionType'
import { Map } from 'immutable'
// - Import domain
import { User,Profile } from 'src/core/domain/users'
import { User, Profile } from 'src/core/domain/users'
import { UserState } from './UserState'
import { IUserAction } from './IUserAction'
@@ -10,101 +11,52 @@ import { IUserAction } from './IUserAction'
/**
* User reducer
*/
export let userReducer = (state: UserState = new UserState(), action: IUserAction) => {
export let userReducer = (state = Map(new UserState()), action: IUserAction) => {
const { payload } = action
switch (action.type) {
case UserActionType.USER_INFO:
return {
...state,
info: {
...state.info,
[payload.uid]: {
...payload.info
}
}
}
return state
.setIn(['info', payload.uid], payload.info)
case UserActionType.ADD_USER_INFO:
return {
...state,
info: {
...state.info,
[payload.uid]: {
...payload.info
}
},
loaded: true
}
return state
.setIn(['info', payload.uid], payload.info)
.set('loaded', true)
case UserActionType.ADD_PEOPLE_INFO:
return {
...state,
info: {
...state.info,
...payload
}
}
return state
.mergeIn(['info'], payload)
case UserActionType.UPDATE_USER_INFO:
return {
...state,
info: {
...state.info,
[payload.uid]: {
...state.info![payload.uid],
...payload.info
}
}
}
return state
.mergeIn(['info', payload.uid], payload.info)
case UserActionType.CLEAR_ALL_DATA_USER:
return new UserState()
return Map(new UserState())
case UserActionType.CLOSE_EDIT_PROFILE:
return {
...state,
openEditProfile: false
}
return state
.set('openEditProfile', false)
case UserActionType.OPEN_EDIT_PROFILE:
return {
...state,
openEditProfile: true
}
case UserActionType.HAS_MORE_DATA_PEOPLE:
return {
...state,
people: {
...state.people,
hasMoreData: true
}
return state
.set('openEditProfile', true)
case UserActionType.HAS_MORE_DATA_PEOPLE:
return state
.setIn(['people', 'hasMoreData'], true)
}
case UserActionType.NOT_MORE_DATA_PEOPLE:
return {
...state,
people: {
...state.people,
hasMoreData: false
}
}
return state
.setIn(['people', 'hasMoreData'], false)
case UserActionType.REQUEST_PAGE_PEOPLE:
return {
...state,
people: {
...state.people,
lastPageRequest: payload.page
}
}
return state
.setIn(['people', 'lastPageRequest'], payload.page)
case UserActionType.LAST_USER_PEOPLE:
return {
...state,
people: {
...state.people,
lastUserId: payload.lastUserId
}
}
return state
.setIn(['people', 'lastUserId'], payload.lastUserId)
default:
return state

View File

@@ -1,6 +1,7 @@
// - Import react components
import moment from 'moment/moment'
import _ from 'lodash'
import { Map } from 'immutable'
// - Import action types
import { VoteActionType } from 'constants/voteActionType'
@@ -16,56 +17,26 @@ import { IVoteAction } from './IVoteAction'
* @param {object} state
* @param {object} action
*/
export let voteReducer = (state: VoteState = new VoteState(), action: IVoteAction) => {
export let voteReducer = (state = Map(new VoteState()), action: IVoteAction) => {
let { payload } = action
switch (action.type) {
/* _____________ CRUD _____________ */
case VoteActionType.ADD_VOTE:
return {
...state,
postVotes: {
...state.postVotes,
[payload.postId]: {
...state.postVotes![payload.postId],
[payload.userId]: {
...payload
}
}
return state
.setIn(['postVotes', payload.postId, payload.userId], payload)
}
}
case VoteActionType.ADD_VOTE_LIST:
return {
...state,
postVotes: {
...payload
},
loaded: true
}
return state
.set('postVotes', payload)
.set('loaded', true)
case VoteActionType.DELETE_VOTE:
let parsedVotes = {}
if (state.postVotes![payload.postId]) {
Object.keys(state.postVotes![payload.postId]).map((id) => {
if (id !== payload.userId) {
_.merge(parsedVotes, { [id]: { ...state.postVotes![payload.postId][id] } })
}
})
}
return {
...state,
postVotes: {
...state.postVotes,
[payload.postId]: {
...parsedVotes
}
}
}
return state
.deleteIn(['postVotes', payload.postId, payload.userId])
case VoteActionType.CLEAR_ALL_DATA_VOTE:
return new VoteState()
return Map(new VoteState())
default:
return state