[Enhancement] Apply immutable js. (#49)
This commit is contained in:
11
package.json
11
package.json
@@ -18,9 +18,11 @@
|
|||||||
"author": "Amir Movahedi",
|
"author": "Amir Movahedi",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@types/react-helmet": "^5.0.5",
|
||||||
"@types/redux-devtools": "^3.0.43",
|
"@types/redux-devtools": "^3.0.43",
|
||||||
"@types/redux-devtools-dock-monitor": "^1.1.32",
|
"@types/redux-devtools-dock-monitor": "^1.1.32",
|
||||||
"@types/redux-devtools-log-monitor": "^1.0.33",
|
"@types/redux-devtools-log-monitor": "^1.0.33",
|
||||||
|
"@types/redux-immutable": "^3.0.38",
|
||||||
"amazon-cognito-identity-js": "^1.21.0",
|
"amazon-cognito-identity-js": "^1.21.0",
|
||||||
"aws-sdk": "^2.132.0",
|
"aws-sdk": "^2.132.0",
|
||||||
"axios": "^0.16.2",
|
"axios": "^0.16.2",
|
||||||
@@ -29,6 +31,7 @@
|
|||||||
"crypto-js": "^3.1.9-1",
|
"crypto-js": "^3.1.9-1",
|
||||||
"faker": "^4.1.0",
|
"faker": "^4.1.0",
|
||||||
"firebase": "^4.11.0",
|
"firebase": "^4.11.0",
|
||||||
|
"immutable": "^3.8.2",
|
||||||
"install": "^0.10.2",
|
"install": "^0.10.2",
|
||||||
"inversify": "^4.6.0",
|
"inversify": "^4.6.0",
|
||||||
"jss-rtl": "^0.2.1",
|
"jss-rtl": "^0.2.1",
|
||||||
@@ -48,9 +51,11 @@
|
|||||||
"react-day-picker": "^7.0.7",
|
"react-day-picker": "^7.0.7",
|
||||||
"react-dom": "^16.2.0",
|
"react-dom": "^16.2.0",
|
||||||
"react-event-listener": "^0.5.1",
|
"react-event-listener": "^0.5.1",
|
||||||
|
"react-helmet": "^5.2.0",
|
||||||
"react-infinite-scroller": "^1.1.2",
|
"react-infinite-scroller": "^1.1.2",
|
||||||
"react-linkify": "^0.2.1",
|
"react-linkify": "^0.2.1",
|
||||||
"react-localize-redux": "^2.15.1",
|
"react-loadable": "^5.3.1",
|
||||||
|
"react-localize-redux": "^2.16.0",
|
||||||
"react-parallax": "^1.6.1",
|
"react-parallax": "^1.6.1",
|
||||||
"react-redux": "^5.0.6",
|
"react-redux": "^5.0.6",
|
||||||
"react-router": "^4.1.1 ",
|
"react-router": "^4.1.1 ",
|
||||||
@@ -62,10 +67,12 @@
|
|||||||
"react-tap-event-plugin": "^3.0.2",
|
"react-tap-event-plugin": "^3.0.2",
|
||||||
"redux": "^3.7.2",
|
"redux": "^3.7.2",
|
||||||
"redux-actions": "^2.0.3",
|
"redux-actions": "^2.0.3",
|
||||||
"redux-saga": "^0.16.0",
|
|
||||||
"redux-devtools": "^3.4.1",
|
"redux-devtools": "^3.4.1",
|
||||||
"redux-devtools-dock-monitor": "^1.1.3",
|
"redux-devtools-dock-monitor": "^1.1.3",
|
||||||
|
"redux-devtools-extension": "^2.13.2",
|
||||||
"redux-devtools-log-monitor": "^1.4.0",
|
"redux-devtools-log-monitor": "^1.4.0",
|
||||||
|
"redux-immutable": "^4.0.0",
|
||||||
|
"redux-saga": "^0.16.0",
|
||||||
"redux-thunk": "^2.2.0",
|
"redux-thunk": "^2.2.0",
|
||||||
"reflect-metadata": "^0.1.10",
|
"reflect-metadata": "^0.1.10",
|
||||||
"save": "^2.3.0",
|
"save": "^2.3.0",
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ const sortCommentsByDate = (sortedObjects: comments) => {
|
|||||||
.sort((a: any, b: any) => parseInt(b[1].creationDate, 10) - parseInt(a[1].creationDate, 10)).slice(0, 3))
|
.sort((a: any, b: any) => parseInt(b[1].creationDate, 10) - parseInt(a[1].creationDate, 10)).slice(0, 3))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
return sortedObjects
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|||||||
@@ -4,11 +4,14 @@ import * as moment from 'moment/moment'
|
|||||||
* @param title log title
|
* @param title log title
|
||||||
* @param data log data object
|
* @param data log data object
|
||||||
*/
|
*/
|
||||||
const logger = (title: string, data: any) => {
|
const logger = (title: string, ...data: any[]) => {
|
||||||
const randomColor = getRandomColor()
|
const randomColor = getRandomColor()
|
||||||
|
|
||||||
console.log(`\n\n%c ======= ${title} ======= %c${moment().format('HH:mm:ss SSS')} \n`, `color:${randomColor};font-size:15`
|
window['console']['log'](`\n\n%c ======= ${title} ======= %c${moment().format('HH:mm:ss SSS')} \n`, `color:${randomColor};font-size:15`
|
||||||
, `color:${getRandomColor()};font-size:15`, data,`\n\n =========================================`)
|
, `color:${getRandomColor()};font-size:15`)
|
||||||
|
window['console']['log'](``)
|
||||||
|
window['console']['log'](` `, data)
|
||||||
|
window['console']['log'](`\n =========================================`)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,8 +34,11 @@ const updateObject = (oldObject: any, updatedProperties: any) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getStateSlice = (state: any) => state.toJS()['locale']
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
logger,
|
logger,
|
||||||
getRandomColor,
|
getRandomColor,
|
||||||
updateObject
|
updateObject,
|
||||||
|
getStateSlice
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import {List} from 'immutable'
|
||||||
|
|
||||||
// Get tags from post content
|
// Get tags from post content
|
||||||
export const detectTags: (content: string, character: string) => string[] = (content: string, character: string) => {
|
export const detectTags: (content: string, character: string) => string[] = (content: string, character: string) => {
|
||||||
@@ -27,3 +28,15 @@ export const sortObjectsDate = (objects: any) => {
|
|||||||
|
|
||||||
return sortedObjects
|
return sortedObjects
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const sortImuObjectsDate = (objects: List<Map<string, any>>) => {
|
||||||
|
let sortedObjects = objects
|
||||||
|
|
||||||
|
// Sort posts with creation date
|
||||||
|
return sortedObjects.sort((a: any, b: any) => {
|
||||||
|
return parseInt(b.get('creationDate'),10) - parseInt(a.get('creationDate'),10)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
// return sortedObjects
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,6 +2,9 @@
|
|||||||
import React, { Component } from 'react'
|
import React, { Component } from 'react'
|
||||||
import { connect } from 'react-redux'
|
import { connect } from 'react-redux'
|
||||||
import { push } from 'react-router-redux'
|
import { push } from 'react-router-redux'
|
||||||
|
import {Map, List as ImuList} from 'immutable'
|
||||||
|
|
||||||
|
// - Material UI
|
||||||
import List, {
|
import List, {
|
||||||
ListItem,
|
ListItem,
|
||||||
ListItemIcon,
|
ListItemIcon,
|
||||||
@@ -119,7 +122,7 @@ export class CircleComponent extends Component<ICircleComponentProps, ICircleCom
|
|||||||
/**
|
/**
|
||||||
* Circle name on change
|
* Circle name on change
|
||||||
*/
|
*/
|
||||||
circleName: this.props.circle.name,
|
circleName: this.props.circle.get('name', ''),
|
||||||
/**
|
/**
|
||||||
* Save operation will be disable if user doesn't meet requirement
|
* Save operation will be disable if user doesn't meet requirement
|
||||||
*/
|
*/
|
||||||
@@ -210,9 +213,9 @@ export class CircleComponent extends Component<ICircleComponentProps, ICircleCom
|
|||||||
let usersParsed: any = []
|
let usersParsed: any = []
|
||||||
|
|
||||||
if (usersOfCircle) {
|
if (usersOfCircle) {
|
||||||
Object.keys(usersOfCircle).forEach((userId, index) => {
|
usersOfCircle.forEach((user: Map<string, any>, userId) => {
|
||||||
const { fullName } = usersOfCircle[userId]
|
const fullName = user.get('fullName')
|
||||||
let avatar = usersOfCircle && usersOfCircle[userId] ? usersOfCircle[userId].avatar || '' : ''
|
let avatar = user.get('avatar', '')
|
||||||
usersParsed.push(
|
usersParsed.push(
|
||||||
<ListItem
|
<ListItem
|
||||||
button
|
button
|
||||||
@@ -303,9 +306,9 @@ export class CircleComponent extends Component<ICircleComponentProps, ICircleCom
|
|||||||
<ListItemIcon className={classes.icon}>
|
<ListItemIcon className={classes.icon}>
|
||||||
<SvgGroup />
|
<SvgGroup />
|
||||||
</ListItemIcon>
|
</ListItemIcon>
|
||||||
<ListItemText inset primary={<span style={this.styles}>{this.props.circle.name}</span>} />
|
<ListItemText inset primary={<span style={this.styles}>{this.props.circle.get('name')}</span>} />
|
||||||
<ListItemSecondaryAction>
|
<ListItemSecondaryAction>
|
||||||
{circle.isSystem ? null : rightIconMenu}
|
{circle.get('isSystem') ? null : rightIconMenu}
|
||||||
</ListItemSecondaryAction>
|
</ListItemSecondaryAction>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<Collapse component='li' in={this.state.open} timeout='auto' unmountOnExit>
|
<Collapse component='li' in={this.state.open} timeout='auto' unmountOnExit>
|
||||||
@@ -363,27 +366,24 @@ const mapDispatchToProps = (dispatch: any, ownProps: ICircleComponentProps) => {
|
|||||||
* @param {object} ownProps is the props belong to component
|
* @param {object} ownProps is the props belong to component
|
||||||
* @return {object} props of component
|
* @return {object} props of component
|
||||||
*/
|
*/
|
||||||
const mapStateToProps = (state: any, ownProps: ICircleComponentProps) => {
|
const mapStateToProps = (state: Map<string, any>, ownProps: ICircleComponentProps) => {
|
||||||
const { circle, authorize, server } = state
|
const userTies: Map<string, any> = state.getIn(['circle', 'userTies'])
|
||||||
const { userTies } = circle
|
const uid = state.getIn(['authorize', 'uid'])
|
||||||
const { uid } = state.authorize
|
const circles: Map<string, Map<string, any>> = state.getIn(['circle', 'circleList'], {})
|
||||||
const circles: { [circleId: string]: Circle } = circle ? (circle.circleList || {}) : {}
|
const currentCircle: Map<string, any> = circles.get(ownProps.id, Map({}))
|
||||||
const currentCircle = (circles ? circles[ownProps.id] : {}) as Circle
|
const circleId = ownProps.circle.get('id')
|
||||||
const circleId = ownProps.circle.id!
|
let usersOfCircle: Map<string, any> = Map({})
|
||||||
let usersOfCircle: { [userId: string]: UserTie } = {}
|
userTies.forEach((userTie , userTieId) => {
|
||||||
Object.keys(userTies).forEach((userTieId) => {
|
const theUserTie: Map<string, any> = userTie
|
||||||
const theUserTie = userTies[userTieId] as UserTie
|
const circleList: ImuList<string> = theUserTie.getIn(['circleIdList'])
|
||||||
if (theUserTie.circleIdList!.indexOf(ownProps.id) > -1) {
|
if ( circleList.indexOf(ownProps.id) > -1) {
|
||||||
usersOfCircle = {
|
usersOfCircle = usersOfCircle.set(userTieId!, theUserTie)
|
||||||
...usersOfCircle,
|
|
||||||
[userTieId]: theUserTie
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return {
|
return {
|
||||||
usersOfCircle,
|
usersOfCircle,
|
||||||
openSetting: (state.circle && state.circle.openSetting && state.circle.openSetting[circleId]) ? state.circle.openSetting[circleId] : false,
|
openSetting: state.getIn(['circle', 'openSetting', circleId], false),
|
||||||
userInfo: state.user.info
|
userInfo: state.getIn(['user', 'info'])
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,81 +1,57 @@
|
|||||||
import { Comment } from 'core/domain/comments'
|
import { Comment } from 'core/domain/comments'
|
||||||
import { Profile } from 'core/domain/users'
|
import { Profile } from 'core/domain/users'
|
||||||
import { Circle, UserTie } from 'core/domain/circles'
|
import { Circle, UserTie } from 'core/domain/circles'
|
||||||
|
import {Map} from 'immutable'
|
||||||
|
|
||||||
export interface ICircleComponentProps {
|
export interface ICircleComponentProps {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Circle
|
||||||
*
|
|
||||||
* @type {Circle}
|
|
||||||
* @memberof ICircleComponentProps
|
|
||||||
*/
|
*/
|
||||||
circle: Circle
|
circle: Map<string, any>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Circle identifier
|
* Circle identifier
|
||||||
*
|
|
||||||
* @type {string}
|
|
||||||
* @memberof ICircleComponentProps
|
|
||||||
*/
|
*/
|
||||||
id: string
|
id: string
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User identifier
|
* User identifier
|
||||||
*
|
|
||||||
* @type {string}
|
|
||||||
* @memberof ICircleComponentProps
|
|
||||||
*/
|
*/
|
||||||
uid: string
|
uid: string
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Update circle
|
||||||
*
|
|
||||||
* @type {Function}
|
|
||||||
* @memberof ICircleComponentProps
|
|
||||||
*/
|
*/
|
||||||
updateCircle?: Function
|
updateCircle?: Function
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Delete circle
|
||||||
*
|
|
||||||
* @type {Function}
|
|
||||||
* @memberof ICircleComponentProps
|
|
||||||
*/
|
*/
|
||||||
deleteCircle?: Function
|
deleteCircle?: Function
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Users of current circle
|
* Users of current circle
|
||||||
*/
|
*/
|
||||||
usersOfCircle?: {[userId: string]: UserTie}
|
usersOfCircle?: Map<string, any>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Close setting box of circle
|
* Close setting box of circle
|
||||||
*
|
|
||||||
* @type {Function}
|
|
||||||
* @memberof ICircleComponentProps
|
|
||||||
*/
|
*/
|
||||||
closeCircleSettings?: any
|
closeCircleSettings?: any
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Circle setting dialog is open {true} or not {false}
|
* Circle setting dialog is open {true} or not {false}
|
||||||
*
|
|
||||||
* @type {Function}
|
|
||||||
* @memberof ICircleComponentProps
|
|
||||||
*/
|
*/
|
||||||
openSetting?: boolean
|
openSetting?: boolean
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Change route location
|
* Change route location
|
||||||
*
|
|
||||||
* @memberof ICircleComponentProps
|
|
||||||
*/
|
*/
|
||||||
goTo?: (url: string) => void
|
goTo?: (url: string) => void
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open setting box for a circle
|
* Open setting box for a circle
|
||||||
*
|
|
||||||
* @memberof ICircleComponentProps
|
|
||||||
*/
|
*/
|
||||||
openCircleSettings?: () => any
|
openCircleSettings?: () => any
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import moment from 'moment/moment'
|
|||||||
import Linkify from 'react-linkify'
|
import Linkify from 'react-linkify'
|
||||||
import Popover from 'material-ui/Popover'
|
import Popover from 'material-ui/Popover'
|
||||||
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
|
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
|
||||||
|
import {Map} from 'immutable'
|
||||||
|
|
||||||
import { Comment } from 'core/domain/comments'
|
import { Comment } from 'core/domain/comments'
|
||||||
|
|
||||||
@@ -285,8 +286,8 @@ export class CommentComponent extends Component<ICommentComponentProps, IComment
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentWillMount () {
|
componentWillMount () {
|
||||||
const { userId } = this.props.comment
|
const { commentOwner } = this.props
|
||||||
if (!this.props.isCommentOwner && !this.props.info![userId!]) {
|
if (!this.props.isCommentOwner && !commentOwner) {
|
||||||
this.props.getUserInfo!()
|
this.props.getUserInfo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -432,15 +433,16 @@ const mapDispatchToProps = (dispatch: any, ownProps: ICommentComponentProps) =>
|
|||||||
* @param {object} ownProps is the props belong to component
|
* @param {object} ownProps is the props belong to component
|
||||||
* @return {object} props of component
|
* @return {object} props of component
|
||||||
*/
|
*/
|
||||||
const mapStateToProps = (state: any, ownProps: any) => {
|
const mapStateToProps = (state: any, ownProps: ICommentComponentProps) => {
|
||||||
const { uid } = state.authorize
|
const commentOwnerId = ownProps.comment.userId
|
||||||
const avatar = state.user.info && state.user.info[ownProps.comment.userId] ? state.user.info[ownProps.comment.userId].avatar || '' : ''
|
const uid = state.getIn(['authorize', 'uid'])
|
||||||
const fullName = state.user.info && state.user.info[ownProps.comment.userId] ? state.user.info[ownProps.comment.userId].fullName || '' : ''
|
const avatar = ownProps.comment.userAvatar
|
||||||
|
const fullName = ownProps.comment.userDisplayName
|
||||||
return {
|
return {
|
||||||
translate: getTranslate(state.locale),
|
translate: getTranslate(state.get('locale')),
|
||||||
uid: uid,
|
uid: uid,
|
||||||
isCommentOwner: (uid === ownProps.comment.userId),
|
isCommentOwner: (uid === commentOwnerId),
|
||||||
info: state.user.info,
|
commentOwner: state.getIn(['user', 'info', commentOwnerId]),
|
||||||
avatar,
|
avatar,
|
||||||
fullName
|
fullName
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,11 @@ export interface ICommentComponentProps {
|
|||||||
*/
|
*/
|
||||||
comment: Comment
|
comment: Comment
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Comment owner
|
||||||
|
*/
|
||||||
|
commentOwner?: Profile
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open profile editor
|
* Open profile editor
|
||||||
*
|
*
|
||||||
@@ -63,14 +68,6 @@ export interface ICommentComponentProps {
|
|||||||
*/
|
*/
|
||||||
getUserInfo?: () => void
|
getUserInfo?: () => void
|
||||||
|
|
||||||
/**
|
|
||||||
* User profile
|
|
||||||
*
|
|
||||||
* @type {{[userId: string]: Profile}}
|
|
||||||
* @memberof ICommentComponentProps
|
|
||||||
*/
|
|
||||||
info?: {[userId: string]: Profile}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User full name
|
* User full name
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { NavLink } from 'react-router-dom'
|
|||||||
import { connect } from 'react-redux'
|
import { connect } from 'react-redux'
|
||||||
import moment from 'moment/moment'
|
import moment from 'moment/moment'
|
||||||
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
|
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
|
||||||
|
import { Map } from 'immutable'
|
||||||
|
|
||||||
import Paper from 'material-ui/Paper'
|
import Paper from 'material-ui/Paper'
|
||||||
import Button from 'material-ui/Button'
|
import Button from 'material-ui/Button'
|
||||||
@@ -30,11 +31,12 @@ import UserAvatar from 'components/userAvatar'
|
|||||||
|
|
||||||
import { ICommentGroupComponentProps } from './ICommentGroupComponentProps'
|
import { ICommentGroupComponentProps } from './ICommentGroupComponentProps'
|
||||||
import { ICommentGroupComponentState } from './ICommentGroupComponentState'
|
import { ICommentGroupComponentState } from './ICommentGroupComponentState'
|
||||||
import { Comment } from 'core/domain/comments/comment'
|
import { Comment } from 'core/domain/comments'
|
||||||
import { ServerRequestModel } from 'models/server'
|
import { ServerRequestModel } from 'models/server'
|
||||||
import StringAPI from 'api/StringAPI'
|
import StringAPI from 'api/StringAPI'
|
||||||
import { ServerRequestType } from 'constants/serverRequestType'
|
import { ServerRequestType } from 'constants/serverRequestType'
|
||||||
import { ServerRequestStatusType } from 'store/actions/serverRequestStatusType'
|
import { ServerRequestStatusType } from 'store/actions/serverRequestStatusType'
|
||||||
|
import { Profile } from 'core/domain/users'
|
||||||
|
|
||||||
const styles = (theme: any) => ({
|
const styles = (theme: any) => ({
|
||||||
textField: {
|
textField: {
|
||||||
@@ -210,8 +212,8 @@ export class CommentGroupComponent extends Component<ICommentGroupComponentProps
|
|||||||
* @return {DOM} list of comments' DOM
|
* @return {DOM} list of comments' DOM
|
||||||
*/
|
*/
|
||||||
commentList = () => {
|
commentList = () => {
|
||||||
const {classes} = this.props
|
const {classes, postId} = this.props
|
||||||
let comments = this.props.commentSlides
|
let comments = Map(this.props.commentSlides!).toJS()
|
||||||
if (comments) {
|
if (comments) {
|
||||||
comments = _.fromPairs(_.toPairs(comments)
|
comments = _.fromPairs(_.toPairs(comments)
|
||||||
.sort((a: any, b: any) => parseInt(b[1].creationDate, 10) - parseInt(a[1].creationDate, 10)))
|
.sort((a: any, b: any) => parseInt(b[1].creationDate, 10) - parseInt(a[1].creationDate, 10)))
|
||||||
@@ -229,10 +231,8 @@ export class CommentGroupComponent extends Component<ICommentGroupComponentProps
|
|||||||
parsedComments.push(parsedComments[0])
|
parsedComments.push(parsedComments[0])
|
||||||
}
|
}
|
||||||
return parsedComments.map((comment, index) => {
|
return parsedComments.map((comment, index) => {
|
||||||
const { userInfo } = this.props
|
const commentAvatar = comment.userAvatar
|
||||||
|
const commentFullName = comment.userDisplayName
|
||||||
const commentAvatar = userInfo && userInfo[comment.userId!] ? userInfo[comment.userId!].avatar || '' : ''
|
|
||||||
const commentFullName = userInfo && userInfo[comment.userId!] ? userInfo[comment.userId!].fullName || '' : ''
|
|
||||||
|
|
||||||
const commentBody = (
|
const commentBody = (
|
||||||
<div style={{ outline: 'none', flex: 'auto', flexGrow: 1 }}>
|
<div style={{ outline: 'none', flex: 'auto', flexGrow: 1 }}>
|
||||||
@@ -274,8 +274,8 @@ export class CommentGroupComponent extends Component<ICommentGroupComponentProps
|
|||||||
* @return {react element} return the DOM which rendered by component
|
* @return {react element} return the DOM which rendered by component
|
||||||
*/
|
*/
|
||||||
render () {
|
render () {
|
||||||
const { comments, classes, postId, fullName, avatar, getCommentsRequest, open, commentSlides, translate } = this.props
|
const { classes, postId, fullName, avatar, commentsRequestStatus, open, commentSlides, translate } = this.props
|
||||||
|
const comments: Map<string, Comment> = this.props.comments || Map({})
|
||||||
/**
|
/**
|
||||||
* Comment list box
|
* Comment list box
|
||||||
*/
|
*/
|
||||||
@@ -314,20 +314,20 @@ export class CommentGroupComponent extends Component<ICommentGroupComponentProps
|
|||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
||||||
const showComments = ( comments && Object.keys(comments).length > 0
|
const showComments = ( !comments.isEmpty()
|
||||||
? (
|
? (
|
||||||
<Paper elevation={0} style={open ? { display: 'block', padding: '0px 0px' } : { display: 'none', padding: '12px 16px' }}>
|
<Paper elevation={0} style={open ? { display: 'block', padding: '0px 0px' } : { display: 'none', padding: '12px 16px' }}>
|
||||||
<CommentListComponent comments={comments!} isPostOwner={this.props.isPostOwner} disableComments={this.props.disableComments} postId={postId}/>
|
<CommentListComponent comments={comments!} isPostOwner={this.props.isPostOwner} disableComments={this.props.disableComments} postId={postId}/>
|
||||||
</Paper>)
|
</Paper>)
|
||||||
: '')
|
: '')
|
||||||
const loadComments = (( getCommentsRequest === undefined || (getCommentsRequest && getCommentsRequest!.status !== ServerRequestStatusType.OK)) ? <LinearProgress style={this.styles.progressbar} variant='indeterminate' /> : showComments)
|
const loadComments = ((commentsRequestStatus === ServerRequestStatusType.OK) || !comments.isEmpty() ? showComments : <LinearProgress style={this.styles.progressbar} variant='indeterminate' />)
|
||||||
/**
|
/**
|
||||||
* Return Elements
|
* Return Elements
|
||||||
*/
|
*/
|
||||||
return (
|
return (
|
||||||
<div key={postId + '-comments'}>
|
<div key={postId + '-comments-group'}>
|
||||||
<div style={commentSlides && Object.keys(commentSlides).length > 0 ? { display: 'block' } : { display: 'none' }}>
|
|
||||||
<Divider />
|
<Divider />
|
||||||
|
<div style={commentSlides && !commentSlides.isEmpty() ? { display: 'block' } : { display: 'none' }}>
|
||||||
<Paper elevation={0} className='animate-top' style={!open ? { display: 'block' } : { display: 'none' }}>
|
<Paper elevation={0} className='animate-top' style={!open ? { display: 'block' } : { display: 'none' }}>
|
||||||
|
|
||||||
<div style={{ position: 'relative', height: '60px' }} >
|
<div style={{ position: 'relative', height: '60px' }} >
|
||||||
@@ -339,11 +339,11 @@ export class CommentGroupComponent extends Component<ICommentGroupComponentProps
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Paper>
|
</Paper>
|
||||||
|
|
||||||
|
</div>
|
||||||
{
|
{
|
||||||
open ? loadComments : ''
|
open ? loadComments : ''
|
||||||
}
|
}
|
||||||
|
|
||||||
</div>
|
|
||||||
{
|
{
|
||||||
(!this.props.disableComments && open )
|
(!this.props.disableComments && open )
|
||||||
? commentWriteBox
|
? commentWriteBox
|
||||||
@@ -377,19 +377,20 @@ const mapDispatchToProps = (dispatch: any, ownProps: ICommentGroupComponentProps
|
|||||||
* @param {object} ownProps is the props belong to component
|
* @param {object} ownProps is the props belong to component
|
||||||
* @return {object} props of component
|
* @return {object} props of component
|
||||||
*/
|
*/
|
||||||
const mapStateToProps = (state: any, ownProps: ICommentGroupComponentProps) => {
|
const mapStateToProps = (state: Map<string, any>, ownProps: ICommentGroupComponentProps) => {
|
||||||
const { post, user, authorize, server } = state
|
|
||||||
const {request} = server
|
|
||||||
const { ownerPostUserId, postId } = ownProps
|
const { ownerPostUserId, postId } = ownProps
|
||||||
const commentSlides = post.userPosts[ownerPostUserId] && post.userPosts[ownerPostUserId][postId] ? post.userPosts[ownerPostUserId][postId].comments : {}
|
const uid = state.getIn(['authorize', 'uid'], 0)
|
||||||
const getCommentsRequest: ServerRequestModel = request ? request[StringAPI.createServerRequestId(ServerRequestType.CommentGetComments, postId)] : null
|
const requestId = StringAPI.createServerRequestId(ServerRequestType.CommentGetComments, postId)
|
||||||
|
const commentsRequestStatus = state.getIn(['server', 'request', requestId])
|
||||||
|
const commentSlides = state.getIn(['post', 'userPosts', ownerPostUserId, postId, 'comments'])
|
||||||
|
const user = state.getIn(['user', 'info', uid])
|
||||||
return {
|
return {
|
||||||
translate: getTranslate(state.locale),
|
translate: getTranslate(state.get('locale')),
|
||||||
getCommentsRequest,
|
commentsRequestStatus : commentsRequestStatus ? commentsRequestStatus.status : ServerRequestStatusType.NoAction,
|
||||||
commentSlides,
|
commentSlides,
|
||||||
avatar: user.info && user.info[state.authorize.uid] ? user.info[authorize.uid].avatar || '' : '',
|
avatar: user.avatar || '',
|
||||||
fullName: user.info && user.info[state.authorize.uid] ? user.info[authorize.uid].fullName || '' : '',
|
fullName: user.fullName || '',
|
||||||
userInfo: user.info
|
userInfo: state.getIn(['user', 'info'])
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import { Profile } from 'core/domain/users'
|
import { Profile } from 'core/domain/users'
|
||||||
import { Comment } from 'core/domain/comments'
|
import { Comment } from 'core/domain/comments'
|
||||||
import { ServerRequestModel } from 'models/server'
|
import { ServerRequestModel } from 'models/server'
|
||||||
|
import { ServerRequestStatusType } from 'store/actions/serverRequestStatusType'
|
||||||
|
import {Map} from 'immutable'
|
||||||
export interface ICommentGroupComponentProps {
|
export interface ICommentGroupComponentProps {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -9,15 +11,12 @@ export interface ICommentGroupComponentProps {
|
|||||||
* @type {{[commentId: string]: Comment}}
|
* @type {{[commentId: string]: Comment}}
|
||||||
* @memberof ICommentGroupComponentProps
|
* @memberof ICommentGroupComponentProps
|
||||||
*/
|
*/
|
||||||
comments?: {[commentId: string]: Comment}
|
comments?: Map<string, Comment>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Commnets show on slide preview
|
* Commnets show on slide preview
|
||||||
*
|
|
||||||
* @type {{[commentId: string]: Comment}}
|
|
||||||
* @memberof ICommentGroupComponentProps
|
|
||||||
*/
|
*/
|
||||||
commentSlides?: {[commentId: string]: Comment}
|
commentSlides?: Map<string, Comment>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The post identifier which comment belong to
|
* The post identifier which comment belong to
|
||||||
@@ -33,7 +32,7 @@ export interface ICommentGroupComponentProps {
|
|||||||
* @type {{[userId: string]: Profile}}
|
* @type {{[userId: string]: Profile}}
|
||||||
* @memberof ICommentGroupComponentProps
|
* @memberof ICommentGroupComponentProps
|
||||||
*/
|
*/
|
||||||
userInfo?: {[userId: string]: Profile}
|
userInfo?: Map<string, Profile>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Comment group is open {true} or not {false}
|
* Comment group is open {true} or not {false}
|
||||||
@@ -102,7 +101,7 @@ export interface ICommentGroupComponentProps {
|
|||||||
/**
|
/**
|
||||||
* Get post comments request payload
|
* Get post comments request payload
|
||||||
*/
|
*/
|
||||||
getCommentsRequest?: ServerRequestModel
|
commentsRequestStatus?: ServerRequestStatusType
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Styles
|
* Styles
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
import React, { Component } from 'react'
|
import React, { Component } from 'react'
|
||||||
import { connect } from 'react-redux'
|
import { connect } from 'react-redux'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
|
import {Map} from 'immutable'
|
||||||
|
|
||||||
// - Material UI
|
// - Material UI
|
||||||
import { withStyles } from 'material-ui/styles'
|
import { withStyles } from 'material-ui/styles'
|
||||||
@@ -66,14 +67,15 @@ export class CommentListComponent extends Component<ICommentListComponentProps,
|
|||||||
* @return {DOM} list of comments' DOM
|
* @return {DOM} list of comments' DOM
|
||||||
*/
|
*/
|
||||||
commentList = () => {
|
commentList = () => {
|
||||||
let {comments, commentsEditorStatus} = this.props
|
let comments = Map<string, Comment>(this.props.comments)
|
||||||
if (comments) {
|
let commentsEditorStatus = Map<string, boolean>(this.props.commentsEditorStatus!)
|
||||||
|
if (!comments.isEmpty()) {
|
||||||
|
|
||||||
let parsedComments: Comment[] = []
|
let parsedComments: Comment[] = []
|
||||||
Object.keys(comments).forEach((commentId) => {
|
comments.forEach((comment, commentId) => {
|
||||||
parsedComments.push({
|
parsedComments.push({
|
||||||
id: commentId,
|
id: commentId,
|
||||||
...comments[commentId]
|
...Map(comment!).toJS()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
let sortedComments = PostAPI.sortObjectsDate(parsedComments)
|
let sortedComments = PostAPI.sortObjectsDate(parsedComments)
|
||||||
@@ -86,7 +88,7 @@ export class CommentListComponent extends Component<ICommentListComponentProps,
|
|||||||
comment={comment}
|
comment={comment}
|
||||||
isPostOwner={this.props.isPostOwner}
|
isPostOwner={this.props.isPostOwner}
|
||||||
disableComments={this.props.disableComments}
|
disableComments={this.props.disableComments}
|
||||||
editorStatus={(commentsEditorStatus![comment.id!]) || false}
|
editorStatus={(commentsEditorStatus.get(comment.id!, false))}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -100,11 +102,11 @@ export class CommentListComponent extends Component<ICommentListComponentProps,
|
|||||||
* @return {react element} return the DOM which rendered by component
|
* @return {react element} return the DOM which rendered by component
|
||||||
*/
|
*/
|
||||||
render () {
|
render () {
|
||||||
const {classes} = this.props
|
const {classes, postId} = this.props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
||||||
<List className={classes.list}>
|
<List key={`comment-list-${postId}`} className={classes.list}>
|
||||||
|
|
||||||
{this.commentList()}
|
{this.commentList()}
|
||||||
</List>
|
</List>
|
||||||
@@ -130,9 +132,8 @@ const mapDispatchToProps = (dispatch: any, ownProps: ICommentListComponentProps)
|
|||||||
* @param {object} ownProps is the props belong to component
|
* @param {object} ownProps is the props belong to component
|
||||||
* @return {object} props of component
|
* @return {object} props of component
|
||||||
*/
|
*/
|
||||||
const mapStateToProps = (state: any, ownProps: ICommentListComponentProps) => {
|
const mapStateToProps = (state: Map<string, any>, ownProps: ICommentListComponentProps) => {
|
||||||
const { comment } = state
|
const commentsEditorStatus = state.getIn(['comment', 'editorStatus', ownProps.postId ], {})
|
||||||
const commentsEditorStatus: { [commentId: string]: Comment } = comment.editorStatus[ownProps.postId] || {}
|
|
||||||
return {
|
return {
|
||||||
commentsEditorStatus
|
commentsEditorStatus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Comment } from 'core/domain/comments'
|
import { Comment } from 'core/domain/comments'
|
||||||
|
import {Map} from 'immutable'
|
||||||
|
|
||||||
export interface ICommentListComponentProps {
|
export interface ICommentListComponentProps {
|
||||||
|
|
||||||
@@ -8,7 +9,7 @@ export interface ICommentListComponentProps {
|
|||||||
* @type {{[commentId: string]: Comment}}
|
* @type {{[commentId: string]: Comment}}
|
||||||
* @memberof ICommentListComponentProps
|
* @memberof ICommentListComponentProps
|
||||||
*/
|
*/
|
||||||
comments: {[commentId: string]: Comment}
|
comments: Map<string, Comment>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Comments editor status
|
* Comments editor status
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import MomentLocaleUtils, {
|
|||||||
formatDate,
|
formatDate,
|
||||||
parseDate,
|
parseDate,
|
||||||
} from 'react-day-picker/moment'
|
} from 'react-day-picker/moment'
|
||||||
|
import {Map} from 'immutable'
|
||||||
|
|
||||||
import { grey } from 'material-ui/colors'
|
import { grey } from 'material-ui/colors'
|
||||||
import IconButton from 'material-ui/IconButton'
|
import IconButton from 'material-ui/IconButton'
|
||||||
@@ -294,9 +295,9 @@ export class EditProfileComponent extends Component<IEditProfileComponentProps,
|
|||||||
*/
|
*/
|
||||||
handleUpdate = () => {
|
handleUpdate = () => {
|
||||||
const { fullNameInput, tagLineInput, avatar, banner, selectedBirthday, companyName, webUrl, twitterId } = this.state
|
const { fullNameInput, tagLineInput, avatar, banner, selectedBirthday, companyName, webUrl, twitterId } = this.state
|
||||||
const { info } = this.props
|
const { info, update } = this.props
|
||||||
|
|
||||||
if (this.state.fullNameInput.trim() === '') {
|
if (fullNameInput.trim() === '') {
|
||||||
this.setState({
|
this.setState({
|
||||||
fullNameInputError: 'This field is required'
|
fullNameInputError: 'This field is required'
|
||||||
})
|
})
|
||||||
@@ -305,7 +306,7 @@ export class EditProfileComponent extends Component<IEditProfileComponentProps,
|
|||||||
fullNameInputError: ''
|
fullNameInputError: ''
|
||||||
})
|
})
|
||||||
|
|
||||||
this.props.update!({
|
update!({
|
||||||
fullName: fullNameInput,
|
fullName: fullNameInput,
|
||||||
tagLine: tagLineInput,
|
tagLine: tagLineInput,
|
||||||
avatar: avatar,
|
avatar: avatar,
|
||||||
@@ -562,13 +563,14 @@ const mapDispatchToProps = (dispatch: any, ownProps: IEditProfileComponentProps)
|
|||||||
* @param {object} ownProps is the props belong to component
|
* @param {object} ownProps is the props belong to component
|
||||||
* @return {object} props of component
|
* @return {object} props of component
|
||||||
*/
|
*/
|
||||||
const mapStateToProps = (state: any, ownProps: IEditProfileComponentProps) => {
|
const mapStateToProps = (state: Map<string, any>, ownProps: IEditProfileComponentProps) => {
|
||||||
|
const uid = state.getIn(['authorize', 'uid'])
|
||||||
return {
|
return {
|
||||||
currentLanguage: getActiveLanguage(state.locale).code,
|
currentLanguage: getActiveLanguage(state.get('locale')).code,
|
||||||
translate: getTranslate(state.locale),
|
translate: getTranslate(state.get('locale')),
|
||||||
open: state.user.openEditProfile,
|
open: state.getIn(['user', 'openEditProfile'], false),
|
||||||
info: state.user.info[state.authorize.uid],
|
info: state.getIn(['user', 'info', uid]),
|
||||||
avatarURL: state.imageGallery.imageURLList
|
avatarURL: state.getIn(['imageGallery', 'imageURLList'])
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import PropTypes from 'prop-types'
|
|||||||
import Paper from 'material-ui/Paper'
|
import Paper from 'material-ui/Paper'
|
||||||
import InfiniteScroll from 'react-infinite-scroller'
|
import InfiniteScroll from 'react-infinite-scroller'
|
||||||
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
|
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
|
||||||
|
import {Map} from 'immutable'
|
||||||
|
|
||||||
// - Import app components
|
// - Import app components
|
||||||
import UserBoxList from 'components/userBoxList'
|
import UserBoxList from 'components/userBoxList'
|
||||||
@@ -16,6 +17,7 @@ import LoadMoreProgressComponent from 'layouts/loadMoreProgress'
|
|||||||
import * as userActions from 'store/actions/userActions'
|
import * as userActions from 'store/actions/userActions'
|
||||||
import { IFindPeopleComponentProps } from './IFindPeopleComponentProps'
|
import { IFindPeopleComponentProps } from './IFindPeopleComponentProps'
|
||||||
import { IFindPeopleComponentState } from './IFindPeopleComponentState'
|
import { IFindPeopleComponentState } from './IFindPeopleComponentState'
|
||||||
|
import { UserTie } from 'core/domain/circles/userTie'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create component class
|
* Create component class
|
||||||
@@ -50,7 +52,7 @@ export class FindPeopleComponent extends Component<IFindPeopleComponentProps, IF
|
|||||||
*/
|
*/
|
||||||
render () {
|
render () {
|
||||||
const {hasMorePeople, translate} = this.props
|
const {hasMorePeople, translate} = this.props
|
||||||
|
const peopleInfo = Map<string, UserTie>(this.props.peopleInfo!)
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<InfiniteScroll
|
<InfiniteScroll
|
||||||
@@ -63,11 +65,11 @@ export class FindPeopleComponent extends Component<IFindPeopleComponentProps, IF
|
|||||||
|
|
||||||
<div className='tracks'>
|
<div className='tracks'>
|
||||||
|
|
||||||
{this.props.peopleInfo && Object.keys(this.props.peopleInfo).length !== 0 ? (<div>
|
{peopleInfo && peopleInfo.count() > 0 ? (<div>
|
||||||
<div className='profile__title'>
|
<div className='profile__title'>
|
||||||
{translate!('people.suggestionsForYouLabel')}
|
{translate!('people.suggestionsForYouLabel')}
|
||||||
</div>
|
</div>
|
||||||
<UserBoxList users={this.props.peopleInfo}/>
|
<UserBoxList users={peopleInfo}/>
|
||||||
<div style={{ height: '24px' }}></div>
|
<div style={{ height: '24px' }}></div>
|
||||||
</div>) : (<div className='g__title-center'>
|
</div>) : (<div className='g__title-center'>
|
||||||
{translate!('people.nothingToShowLabel')}
|
{translate!('people.nothingToShowLabel')}
|
||||||
@@ -98,11 +100,13 @@ const mapDispatchToProps = (dispatch: any, ownProps: IFindPeopleComponentProps)
|
|||||||
* @return {object} props of component
|
* @return {object} props of component
|
||||||
*/
|
*/
|
||||||
const mapStateToProps = (state: any, ownProps: IFindPeopleComponentProps) => {
|
const mapStateToProps = (state: any, ownProps: IFindPeopleComponentProps) => {
|
||||||
const {people, info} = state.user
|
const people = state.getIn(['user', 'people'])
|
||||||
|
const hasMorePeople = state.getIn(['user', 'people', 'hasMoreData' ], true)
|
||||||
|
const info: Map<string, UserTie> = state.getIn(['user', 'info'])
|
||||||
return {
|
return {
|
||||||
translate: getTranslate(state.locale),
|
translate: getTranslate(state.get('locale')),
|
||||||
peopleInfo: info,
|
peopleInfo: info,
|
||||||
hasMorePeople: people.hasMoreData
|
hasMorePeople
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Profile } from 'core/domain/users/profile'
|
import { Profile } from 'core/domain/users/profile'
|
||||||
|
import { UserTie } from 'core/domain/circles'
|
||||||
|
|
||||||
export interface IFindPeopleComponentProps {
|
export interface IFindPeopleComponentProps {
|
||||||
|
|
||||||
@@ -11,11 +12,8 @@ export interface IFindPeopleComponentProps {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Users' profile
|
* Users' profile
|
||||||
*
|
|
||||||
* @type {{[userId: string]: Profile}}
|
|
||||||
* @memberof IFindPeopleComponentProps
|
|
||||||
*/
|
*/
|
||||||
peopleInfo?: {[userId: string]: Profile}
|
peopleInfo?: Map<string, UserTie>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If there are more people {true} or not {false}
|
* If there are more people {true} or not {false}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import React, { Component } from 'react'
|
|||||||
import { connect } from 'react-redux'
|
import { connect } from 'react-redux'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
|
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
|
||||||
|
import {Map} from 'immutable'
|
||||||
|
|
||||||
// - Import app components
|
// - Import app components
|
||||||
import UserBoxList from 'components/userBoxList'
|
import UserBoxList from 'components/userBoxList'
|
||||||
@@ -46,13 +47,14 @@ export class FollowersComponent extends Component<IFollowersComponentProps,IFoll
|
|||||||
*/
|
*/
|
||||||
render () {
|
render () {
|
||||||
const {translate} = this.props
|
const {translate} = this.props
|
||||||
|
const followers = this.props.followers!
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{(this.props.followers && Object.keys(this.props.followers).length !== 0) ? (<div>
|
{(followers && followers.keySeq().count() !== 0) ? (<div>
|
||||||
<div className='profile__title'>
|
<div className='profile__title'>
|
||||||
{translate!('people.followersLabel')}
|
{translate!('people.followersLabel')}
|
||||||
</div>
|
</div>
|
||||||
<UserBoxList users={this.props.followers} />
|
<UserBoxList users={followers} />
|
||||||
<div style={{ height: '24px' }}></div>
|
<div style={{ height: '24px' }}></div>
|
||||||
</div>)
|
</div>)
|
||||||
: (<div className='g__title-center'>
|
: (<div className='g__title-center'>
|
||||||
@@ -81,13 +83,13 @@ const mapDispatchToProps = (dispatch: any,ownProps: IFollowersComponentProps) =>
|
|||||||
* @param {object} ownProps is the props belong to component
|
* @param {object} ownProps is the props belong to component
|
||||||
* @return {object} props of component
|
* @return {object} props of component
|
||||||
*/
|
*/
|
||||||
const mapStateToProps = (state: any,ownProps: IFollowersComponentProps) => {
|
const mapStateToProps = (state: Map<string, any>,ownProps: IFollowersComponentProps) => {
|
||||||
const {circle, authorize, server} = state
|
|
||||||
const { uid } = state.authorize
|
const uid = state.getIn(['authorize', 'uid'], 0)
|
||||||
const circles: { [circleId: string]: Circle } = circle ? (circle.circleList || {}) : {}
|
const circles: { [circleId: string]: Circle } = state.getIn(['circle', 'circleList'], {})
|
||||||
const followers = circle ? circle.userTieds : {}
|
const followers = state.getIn(['circle', 'userTieds'], {})
|
||||||
return{
|
return{
|
||||||
translate: getTranslate(state.locale),
|
translate: getTranslate(state.get('locale')),
|
||||||
followers
|
followers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
import { UserTie } from 'core/domain/circles'
|
import { UserTie } from 'core/domain/circles'
|
||||||
|
import {Map} from 'immutable'
|
||||||
|
|
||||||
export interface IFollowersComponentProps {
|
export interface IFollowersComponentProps {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User followers info
|
* User followers info
|
||||||
*
|
|
||||||
* @type {{[userId: string]: UserTie}}
|
|
||||||
* @memberof IFindPeopleComponentProps
|
|
||||||
*/
|
*/
|
||||||
followers?: {[userId: string]: UserTie}
|
followers?: Map<string, UserTie>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Translate to locale string
|
* Translate to locale string
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import React, { Component } from 'react'
|
|||||||
import { connect } from 'react-redux'
|
import { connect } from 'react-redux'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
|
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
|
||||||
|
import {Map} from 'immutable'
|
||||||
|
|
||||||
// - Import app components
|
// - Import app components
|
||||||
import UserBoxList from 'components/userBoxList'
|
import UserBoxList from 'components/userBoxList'
|
||||||
@@ -46,13 +47,14 @@ export class FollowingComponent extends Component<IFollowingComponentProps,IFoll
|
|||||||
*/
|
*/
|
||||||
render () {
|
render () {
|
||||||
const {translate} = this.props
|
const {translate} = this.props
|
||||||
|
const followingUsers = Map(this.props.followingUsers!)
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{(this.props.followingUsers && Object.keys(this.props.followingUsers).length !== 0 ) ? (<div>
|
{(followingUsers && followingUsers.keySeq().count() !== 0 ) ? (<div>
|
||||||
<div className='profile__title'>
|
<div className='profile__title'>
|
||||||
{translate!('people.followingLabel')}
|
{translate!('people.followingLabel')}
|
||||||
</div>
|
</div>
|
||||||
<UserBoxList users={this.props.followingUsers} />
|
<UserBoxList users={followingUsers} />
|
||||||
<div style={{ height: '24px' }}></div>
|
<div style={{ height: '24px' }}></div>
|
||||||
|
|
||||||
</div>) : (<div className='g__title-center'>
|
</div>) : (<div className='g__title-center'>
|
||||||
@@ -81,13 +83,13 @@ const mapDispatchToProps = (dispatch: any,ownProp: IFollowingComponentProps) =>
|
|||||||
* @param {object} ownProps is the props belong to component
|
* @param {object} ownProps is the props belong to component
|
||||||
* @return {object} props of component
|
* @return {object} props of component
|
||||||
*/
|
*/
|
||||||
const mapStateToProps = (state: any,ownProps: IFollowingComponentProps) => {
|
const mapStateToProps = (state: Map<string, any>,ownProps: IFollowingComponentProps) => {
|
||||||
const {circle, authorize, server} = state
|
|
||||||
const { uid } = state.authorize
|
const uid = state.getIn(['authorize', 'uid'], 0)
|
||||||
const circles: { [circleId: string]: Circle } = circle ? (circle.circleList || {}) : {}
|
const circles: { [circleId: string]: Circle } = state.getIn(['circle', 'circleList'], {})
|
||||||
const followingUsers = circle ? circle.userTies : {}
|
const followingUsers = state.getIn(['circle', 'userTies'], {})
|
||||||
return {
|
return {
|
||||||
translate: getTranslate(state.locale),
|
translate: getTranslate(state.get('locale')),
|
||||||
uid,
|
uid,
|
||||||
circles,
|
circles,
|
||||||
followingUsers
|
followingUsers
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import { UserTie } from 'core/domain/circles'
|
import { UserTie } from 'core/domain/circles'
|
||||||
|
import {Map} from 'immutable'
|
||||||
|
|
||||||
export interface IFollowingComponentProps {
|
export interface IFollowingComponentProps {
|
||||||
|
|
||||||
followingUsers?: {[userId: string]: UserTie}
|
followingUsers?: Map<string, UserTie>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Translate to locale string
|
* Translate to locale string
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import React, { Component } from 'react'
|
|||||||
import { NavLink } from 'react-router-dom'
|
import { NavLink } from 'react-router-dom'
|
||||||
import { connect } from 'react-redux'
|
import { connect } from 'react-redux'
|
||||||
import classNames from 'classnames'
|
import classNames from 'classnames'
|
||||||
|
import { Map } from 'immutable'
|
||||||
|
|
||||||
// - Material UI
|
// - Material UI
|
||||||
import SvgDehaze from 'material-ui-icons/Dehaze'
|
import SvgDehaze from 'material-ui-icons/Dehaze'
|
||||||
@@ -256,18 +257,20 @@ const mapDispatchToProps = (dispatch: Function, ownProps: IHomeHeaderComponentPr
|
|||||||
}
|
}
|
||||||
|
|
||||||
// - Map state to props
|
// - Map state to props
|
||||||
const mapStateToProps = (state: any, ownProps: IHomeHeaderComponentProps) => {
|
const mapStateToProps = (state: Map<string,any>, ownProps: IHomeHeaderComponentProps) => {
|
||||||
|
|
||||||
let notifyCount = state.notify.userNotifies
|
const uid = state.getIn(['authorize', 'uid'], 0)
|
||||||
? Object
|
const userNotifies: Map<string, any> = state.getIn(['notify','userNotifies'])
|
||||||
.keys(state.notify.userNotifies)
|
let notifyCount = userNotifies
|
||||||
.filter((key) => !state.notify.userNotifies[key].isSeen).length
|
? userNotifies
|
||||||
|
.filter((notification) => !notification.get('isSeen', false)).count()
|
||||||
: 0
|
: 0
|
||||||
|
const user = state.getIn(['user', 'info', uid], {})
|
||||||
return {
|
return {
|
||||||
translate: getTranslate(state.locale),
|
translate: getTranslate(state.get('locale')),
|
||||||
avatar: state.user.info && state.user.info[state.authorize.uid] ? state.user.info[state.authorize.uid].avatar : '',
|
avatar: user.avatar || '',
|
||||||
fullName: state.user.info && state.user.info[state.authorize.uid] ? state.user.info[state.authorize.uid].fullName : '',
|
fullName: user.fullName || '',
|
||||||
title: state.global.headerTitle,
|
title: state.getIn(['global', 'headerTitle'], ''),
|
||||||
notifyCount
|
notifyCount
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Image } from 'core/domain/imageGallery'
|
import { Image } from 'core/domain/imageGallery'
|
||||||
|
import {Map, Collection, List} from 'immutable'
|
||||||
|
|
||||||
export interface IImageGalleryComponentProps {
|
export interface IImageGalleryComponentProps {
|
||||||
|
|
||||||
@@ -33,11 +34,8 @@ export interface IImageGalleryComponentProps {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* List of image in image gallery
|
* List of image in image gallery
|
||||||
*
|
|
||||||
* @type {Image[]}
|
|
||||||
* @memberof IImageGalleryComponentProps
|
|
||||||
*/
|
*/
|
||||||
images?: Image[]
|
images?: List<Image>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Styles
|
* Styles
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import { grey } from 'material-ui/colors'
|
|||||||
import { withStyles } from 'material-ui/styles'
|
import { withStyles } from 'material-ui/styles'
|
||||||
import uuid from 'uuid'
|
import uuid from 'uuid'
|
||||||
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
|
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
|
||||||
|
import {Map} from 'immutable'
|
||||||
|
|
||||||
// - Import actions
|
// - Import actions
|
||||||
import * as imageGalleryActions from 'store/actions/imageGalleryActions'
|
import * as imageGalleryActions from 'store/actions/imageGalleryActions'
|
||||||
@@ -161,7 +162,6 @@ export class ImageGalleryComponent extends Component<IImageGalleryComponentProps
|
|||||||
}
|
}
|
||||||
|
|
||||||
imageList = () => {
|
imageList = () => {
|
||||||
|
|
||||||
return this.props.images!.map((image: Image, index) => {
|
return this.props.images!.map((image: Image, index) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -254,11 +254,13 @@ const mapDispatchToProps = (dispatch: any, ownProps: IImageGalleryComponentProps
|
|||||||
* @param {object} ownProps is the props belong to component
|
* @param {object} ownProps is the props belong to component
|
||||||
* @return {object} props of component
|
* @return {object} props of component
|
||||||
*/
|
*/
|
||||||
const mapStateToProps = (state: any) => {
|
const mapStateToProps = (state: Map<string, any>) => {
|
||||||
|
const uid = state.getIn(['authorize', 'uid'])
|
||||||
|
const currentUser = state.getIn(['user', 'info', uid])
|
||||||
return {
|
return {
|
||||||
translate: getTranslate(state.locale),
|
translate: getTranslate(state.get('locale')),
|
||||||
images: state.imageGallery.images,
|
images: state.getIn(['imageGallery', 'images']),
|
||||||
avatar: state.user.info && state.user.info[state.authorize.uid] ? state.user.info[state.authorize.uid].avatar : ''
|
avatar: currentUser ? currentUser.avatar : ''
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { connect } from 'react-redux'
|
|||||||
import SvgImage from 'material-ui-icons/Image'
|
import SvgImage from 'material-ui-icons/Image'
|
||||||
import { withStyles } from 'material-ui/styles'
|
import { withStyles } from 'material-ui/styles'
|
||||||
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
|
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
|
||||||
|
import { Map } from 'immutable'
|
||||||
|
|
||||||
// - Import app components
|
// - Import app components
|
||||||
|
|
||||||
@@ -121,11 +122,11 @@ const mapDispatchToProps = (dispatch: any, ownProps: IImgComponentProps) => {
|
|||||||
* @param {object} ownProps is the props belong to component
|
* @param {object} ownProps is the props belong to component
|
||||||
* @return {object} props of component
|
* @return {object} props of component
|
||||||
*/
|
*/
|
||||||
const mapStateToProps = (state: any, ownProps: IImgComponentProps) => {
|
const mapStateToProps = (state: Map<string, any>, ownProps: IImgComponentProps) => {
|
||||||
return {
|
return {
|
||||||
translate: getTranslate(state.locale),
|
translate: getTranslate(state.get('locale')),
|
||||||
avatarURL: state.imageGallery.imageURLList,
|
avatarURL: state.getIn(['imageGallery', 'imageURLList']),
|
||||||
imageRequests: state.imageGallery.imageRequests
|
imageRequests: state.getIn(['imageGallery', 'imageRequests'])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import PropTypes from 'prop-types'
|
|||||||
import { connect } from 'react-redux'
|
import { connect } from 'react-redux'
|
||||||
import SvgImage from 'material-ui-icons/Image'
|
import SvgImage from 'material-ui-icons/Image'
|
||||||
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
|
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
|
||||||
|
import {Map} from 'immutable'
|
||||||
|
|
||||||
// - Import app components
|
// - Import app components
|
||||||
|
|
||||||
@@ -153,9 +154,7 @@ const mapDispatchToProps = (dispatch: any, ownProps: IImgCoverComponentProps) =>
|
|||||||
*/
|
*/
|
||||||
const mapStateToProps = (state: any, ownProps: IImgCoverComponentProps) => {
|
const mapStateToProps = (state: any, ownProps: IImgCoverComponentProps) => {
|
||||||
return {
|
return {
|
||||||
translate: getTranslate(state.locale),
|
translate: getTranslate(state.get('locale'))
|
||||||
avatarURL: state.imageGallery.imageURLList,
|
|
||||||
imageRequests: state.imageGallery.imageRequests
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,5 @@
|
|||||||
export interface IMasterLoadingComponentProps {
|
export interface IMasterLoadingComponentProps {
|
||||||
|
error?: boolean
|
||||||
/**
|
timedOut?: boolean
|
||||||
* Loading is active {true} or not {false}
|
pastDelay?: boolean
|
||||||
*
|
|
||||||
* @type {boolean}
|
|
||||||
* @memberof IMasterLoadingComponentProps
|
|
||||||
*/
|
|
||||||
activeLoading: boolean
|
|
||||||
|
|
||||||
handleLoading: (status: boolean) => void
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,11 @@
|
|||||||
import React, { Component } from 'react'
|
import React, { Component } from 'react'
|
||||||
import { CircularProgress } from 'material-ui/Progress'
|
import { CircularProgress } from 'material-ui/Progress'
|
||||||
import Dialog from 'material-ui/Dialog'
|
import Dialog from 'material-ui/Dialog'
|
||||||
|
import red from 'material-ui/colors/red'
|
||||||
import { IMasterLoadingComponentProps } from './IMasterLoadingComponentProps'
|
import { IMasterLoadingComponentProps } from './IMasterLoadingComponentProps'
|
||||||
import { IMasterLoadingComponentState } from './IMasterLoadingComponentState'
|
import { IMasterLoadingComponentState } from './IMasterLoadingComponentState'
|
||||||
|
import Grid from 'material-ui/Grid/Grid'
|
||||||
|
import { Typography } from 'material-ui'
|
||||||
|
|
||||||
// - Import app components
|
// - Import app components
|
||||||
|
|
||||||
@@ -11,26 +14,78 @@ import { IMasterLoadingComponentState } from './IMasterLoadingComponentState'
|
|||||||
export default class MasterLoadingComponent extends Component<IMasterLoadingComponentProps, IMasterLoadingComponentState> {
|
export default class MasterLoadingComponent extends Component<IMasterLoadingComponentProps, IMasterLoadingComponentState> {
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
constructor (props: IMasterLoadingComponentProps) {
|
constructor(props: IMasterLoadingComponentProps) {
|
||||||
super(props)
|
super(props)
|
||||||
// Binding functions to `this`
|
// Binding functions to `this`
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loadProgress() {
|
||||||
|
const { error, timedOut, pastDelay } = this.props
|
||||||
|
if (error) {
|
||||||
|
return (
|
||||||
|
<Grid container>
|
||||||
|
<Grid item>
|
||||||
|
<CircularProgress style={{ color: red[500] }} size={50} />
|
||||||
|
</Grid>
|
||||||
|
<Grid item>
|
||||||
|
<Typography variant='title' color='primary' style={{ marginLeft: '15px' }} >
|
||||||
|
Unexpected Error Happened ...
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
)
|
||||||
|
} else if (timedOut) {
|
||||||
|
return (
|
||||||
|
<Grid container>
|
||||||
|
<Grid item>
|
||||||
|
<CircularProgress style={{ color: red[500] }} size={50} />
|
||||||
|
</Grid>
|
||||||
|
<Grid item>
|
||||||
|
<Typography variant='title' color='primary' style={{ marginLeft: '15px' }} >
|
||||||
|
It takes long time ...
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
)
|
||||||
|
} else if (pastDelay) {
|
||||||
|
return (
|
||||||
|
<Grid container>
|
||||||
|
<Grid item>
|
||||||
|
<CircularProgress size={50} />
|
||||||
|
</Grid>
|
||||||
|
<Grid item>
|
||||||
|
<Typography variant='title' color='primary' style={{ marginLeft: '15px' }} >
|
||||||
|
Loading...
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<Grid container>
|
||||||
|
<Grid item>
|
||||||
|
<CircularProgress size={50} />
|
||||||
|
</Grid>
|
||||||
|
<Grid item>
|
||||||
|
<Typography variant='title' color='primary' style={{ marginLeft: '15px' }} >
|
||||||
|
Loading...
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Render app DOM component
|
// Render app DOM component
|
||||||
render () {
|
render() {
|
||||||
const {activeLoading} = this.props
|
|
||||||
return (
|
return (
|
||||||
|
|
||||||
<div className='mLoading__loading' style={{ display: (activeLoading ? 'flex' : 'none') }}>
|
<div className='mLoading__loading'>
|
||||||
<CircularProgress
|
{
|
||||||
color='secondary'
|
this.loadProgress()
|
||||||
size={50}
|
}
|
||||||
variant='determinate'
|
|
||||||
value={25}
|
|
||||||
min={0}
|
|
||||||
max={50}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,44 +1,30 @@
|
|||||||
import { Profile } from 'core/domain/users'
|
import { Profile } from 'core/domain/users'
|
||||||
import { Notification } from 'core/domain/notifications'
|
import { Notification } from 'core/domain/notifications'
|
||||||
|
import {Map} from 'immutable'
|
||||||
export interface INotifyComponentProps {
|
export interface INotifyComponentProps {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notifications
|
* Notifications
|
||||||
*
|
|
||||||
* @type {{[notificationId: string]: Notification}}
|
|
||||||
* @memberof INotifyComponentProps
|
|
||||||
*/
|
*/
|
||||||
notifications?: {[notificationId: string]: Notification}
|
notifications?: Map<string, any>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Users' profile
|
* Users' profile
|
||||||
*
|
|
||||||
* @type {{[userId: string]: Profile}}
|
|
||||||
* @memberof INotifyComponentProps
|
|
||||||
*/
|
*/
|
||||||
info?: {[userId: string]: Profile}
|
info?: Map<string, Profile>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Close notification
|
* Close notification
|
||||||
*
|
|
||||||
* @memberof INotifyComponentProps
|
|
||||||
*/
|
*/
|
||||||
onRequestClose: () => void
|
onRequestClose: () => void
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User notifications popover is opem {true} or not {false}
|
* User notifications popover is opem {true} or not {false}
|
||||||
*
|
|
||||||
* @type {boolean}
|
|
||||||
* @memberof INotifyComponentProps
|
|
||||||
*/
|
*/
|
||||||
open: boolean
|
open: boolean
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Keep element
|
* Keep element
|
||||||
*
|
|
||||||
* @type {*}
|
|
||||||
* @memberof INotifyComponentProps
|
|
||||||
*/
|
*/
|
||||||
anchorEl?: any
|
anchorEl?: any
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { withStyles } from 'material-ui/styles'
|
|||||||
import Typography from 'material-ui/Typography'
|
import Typography from 'material-ui/Typography'
|
||||||
import Paper from 'material-ui/Paper'
|
import Paper from 'material-ui/Paper'
|
||||||
import List, { ListItem, ListItemSecondaryAction, ListItemText } from 'material-ui/List'
|
import List, { ListItem, ListItemSecondaryAction, ListItemText } from 'material-ui/List'
|
||||||
|
import { Map } from 'immutable'
|
||||||
|
|
||||||
// - Import app components
|
// - Import app components
|
||||||
import NotifyItem from 'components/notifyItem'
|
import NotifyItem from 'components/notifyItem'
|
||||||
@@ -52,7 +53,8 @@ const styles = (theme: any) => ({
|
|||||||
},
|
},
|
||||||
list: {
|
list: {
|
||||||
maxHeight: 380,
|
maxHeight: 380,
|
||||||
overflowY: 'auto'
|
overflowY: 'auto',
|
||||||
|
width: '98%'
|
||||||
|
|
||||||
},
|
},
|
||||||
fullPageXs: {
|
fullPageXs: {
|
||||||
@@ -106,20 +108,22 @@ export class NotifyComponent extends Component<INotifyComponentProps, INotifyCom
|
|||||||
}
|
}
|
||||||
|
|
||||||
notifyItemList = () => {
|
notifyItemList = () => {
|
||||||
let { notifications, info, onRequestClose } = this.props
|
let { info, onRequestClose } = this.props
|
||||||
|
let notifications: Map<string, Map<string, any>> = this.props.notifications!
|
||||||
let parsedDOM: any[] = []
|
let parsedDOM: any[] = []
|
||||||
if (notifications) {
|
if (notifications) {
|
||||||
Object.keys(notifications).forEach((key) => {
|
notifications.forEach((notification, key) => {
|
||||||
const { notifierUserId } = notifications![key]
|
const notifierUserId = notification!.get('notifierUserId')
|
||||||
|
const userInfo = info!.get(notifierUserId)
|
||||||
parsedDOM.push(
|
parsedDOM.push(
|
||||||
<NotifyItem
|
<NotifyItem
|
||||||
key={key}
|
key={key}
|
||||||
description={(notifications![key] ? notifications![key].description || '' : '')}
|
description={notification!.get('description', '')}
|
||||||
fullName={(info![notifierUserId] ? info![notifierUserId].fullName || '' : '')}
|
fullName={(userInfo ? userInfo.fullName || '' : '')}
|
||||||
avatar={(info![notifierUserId] ? info![notifierUserId].avatar || '' : '')}
|
avatar={(userInfo ? userInfo.avatar || '' : '')}
|
||||||
id={key}
|
id={key!}
|
||||||
isSeen={(notifications![key] ? notifications![key].isSeen || false : false)}
|
isSeen={notification!.get('isSeen', false)}
|
||||||
url={(notifications![key] ? notifications![key].url || '' : '')}
|
url={notification!.get('url')}
|
||||||
notifierUserId={notifierUserId}
|
notifierUserId={notifierUserId}
|
||||||
closeNotify={onRequestClose}
|
closeNotify={onRequestClose}
|
||||||
/>
|
/>
|
||||||
@@ -179,10 +183,10 @@ const mapDispatchToProps = (dispatch: any, ownProps: INotifyComponentProps) => {
|
|||||||
* @param {object} ownProps is the props belong to component
|
* @param {object} ownProps is the props belong to component
|
||||||
* @return {object} props of component
|
* @return {object} props of component
|
||||||
*/
|
*/
|
||||||
const mapStateToProps = (state: any, ownProps: INotifyComponentProps) => {
|
const mapStateToProps = (state: Map<string, any>, ownProps: INotifyComponentProps) => {
|
||||||
return {
|
return {
|
||||||
notifications: state.notify.userNotifies,
|
notifications: state.getIn(['notify', 'userNotifies']),
|
||||||
info: state.user.info
|
info: state.getIn(['user', 'info'])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,12 @@
|
|||||||
import { Comment } from 'core/domain/comments'
|
import { Comment } from 'core/domain/comments'
|
||||||
import { Post } from 'core/domain/posts/post'
|
import { Post } from 'core/domain/posts/post'
|
||||||
|
import {Map} from 'immutable'
|
||||||
export interface IPostComponentProps {
|
export interface IPostComponentProps {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Post object
|
* Post object
|
||||||
*
|
|
||||||
* @type {Post}
|
|
||||||
* @memberof IPostComponentProps
|
|
||||||
*/
|
*/
|
||||||
post: Post
|
post: Map<string, any>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Owner's post avatar
|
* Owner's post avatar
|
||||||
@@ -113,7 +110,7 @@ export interface IPostComponentProps {
|
|||||||
* @type {{[commentId: string]: Comment}}
|
* @type {{[commentId: string]: Comment}}
|
||||||
* @memberof ICommentGroupComponentProps
|
* @memberof ICommentGroupComponentProps
|
||||||
*/
|
*/
|
||||||
commentList?: {[commentId: string]: Comment}
|
commentList?: Map<string, Comment>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Styles
|
* Styles
|
||||||
|
|||||||
@@ -8,9 +8,11 @@ import moment from 'moment/moment'
|
|||||||
import Linkify from 'react-linkify'
|
import Linkify from 'react-linkify'
|
||||||
import copy from 'copy-to-clipboard'
|
import copy from 'copy-to-clipboard'
|
||||||
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
|
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
|
||||||
|
import { Map } from 'immutable'
|
||||||
|
|
||||||
// - Material UI
|
// - Material UI
|
||||||
import { Card, CardActions, CardHeader, CardMedia, CardContent } from 'material-ui'
|
import Card, { CardActions, CardHeader, CardMedia, CardContent } from 'material-ui/Card'
|
||||||
|
import { LinearProgress } from 'material-ui/Progress'
|
||||||
import Typography from 'material-ui/Typography'
|
import Typography from 'material-ui/Typography'
|
||||||
import SvgShare from 'material-ui-icons/Share'
|
import SvgShare from 'material-ui-icons/Share'
|
||||||
import SvgComment from 'material-ui-icons/Comment'
|
import SvgComment from 'material-ui-icons/Comment'
|
||||||
@@ -65,7 +67,8 @@ const styles = (theme: any) => ({
|
|||||||
color: 'rgb(134, 129, 129)',
|
color: 'rgb(134, 129, 129)',
|
||||||
fontSize: 10,
|
fontSize: 10,
|
||||||
fontWeight: 400,
|
fontWeight: 400,
|
||||||
padding: 2
|
padding: 2,
|
||||||
|
zIndex: 1
|
||||||
},
|
},
|
||||||
commentCounter: {
|
commentCounter: {
|
||||||
color: 'rgb(134, 129, 129)',
|
color: 'rgb(134, 129, 129)',
|
||||||
@@ -125,7 +128,7 @@ export class PostComponent extends Component<IPostComponentProps, IPostComponent
|
|||||||
/**
|
/**
|
||||||
* Post text
|
* Post text
|
||||||
*/
|
*/
|
||||||
text: post.body ? post.body : '',
|
text: post.get('body', ''),
|
||||||
/**
|
/**
|
||||||
* It's true if whole the text post is visible
|
* It's true if whole the text post is visible
|
||||||
*/
|
*/
|
||||||
@@ -141,11 +144,11 @@ export class PostComponent extends Component<IPostComponentProps, IPostComponent
|
|||||||
/**
|
/**
|
||||||
* If it's true comment will be disabled on post
|
* If it's true comment will be disabled on post
|
||||||
*/
|
*/
|
||||||
disableComments: post.disableComments!,
|
disableComments: post.get('disableComments', false),
|
||||||
/**
|
/**
|
||||||
* If it's true share will be disabled on post
|
* If it's true share will be disabled on post
|
||||||
*/
|
*/
|
||||||
disableSharing: post.disableSharing!,
|
disableSharing: post.get('disableSharing', false),
|
||||||
/**
|
/**
|
||||||
* Title of share post
|
* Title of share post
|
||||||
*/
|
*/
|
||||||
@@ -187,7 +190,8 @@ export class PostComponent extends Component<IPostComponentProps, IPostComponent
|
|||||||
*/
|
*/
|
||||||
handleOpenComments = () => {
|
handleOpenComments = () => {
|
||||||
const { getPostComments, commentList, post } = this.props
|
const { getPostComments, commentList, post } = this.props
|
||||||
const { id, ownerUserId } = post
|
const id = post.get('id')
|
||||||
|
const ownerUserId = post.get('ownerUserId')
|
||||||
if (!commentList) {
|
if (!commentList) {
|
||||||
getPostComments!(ownerUserId!, id!)
|
getPostComments!(ownerUserId!, id!)
|
||||||
}
|
}
|
||||||
@@ -228,14 +232,13 @@ export class PostComponent extends Component<IPostComponentProps, IPostComponent
|
|||||||
*/
|
*/
|
||||||
handleDelete = () => {
|
handleDelete = () => {
|
||||||
const { post } = this.props
|
const { post } = this.props
|
||||||
this.props.delete!(post.id!)
|
this.props.delete!(post.get('id'))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open post menu
|
* Open post menu
|
||||||
*/
|
*/
|
||||||
openPostMenu = (event: any) => {
|
openPostMenu = (event: any) => {
|
||||||
console.log(event.currentTarget)
|
|
||||||
this.setState({
|
this.setState({
|
||||||
postMenuAnchorEl: event.currentTarget,
|
postMenuAnchorEl: event.currentTarget,
|
||||||
isPostMenuOpen: true
|
isPostMenuOpen: true
|
||||||
@@ -274,7 +277,7 @@ export class PostComponent extends Component<IPostComponentProps, IPostComponent
|
|||||||
*/
|
*/
|
||||||
handleOpenShare = () => {
|
handleOpenShare = () => {
|
||||||
const {post} = this.props
|
const {post} = this.props
|
||||||
copy(`${location.origin}/${post.ownerUserId}/posts/${post.id}`)
|
copy(`${location.origin}/${post.get('ownerUserId')}/posts/${post.get('id')}`)
|
||||||
this.setState({
|
this.setState({
|
||||||
shareOpen: true
|
shareOpen: true
|
||||||
})
|
})
|
||||||
@@ -360,12 +363,12 @@ export class PostComponent extends Component<IPostComponentProps, IPostComponent
|
|||||||
<MenuItem onClick={this.handleOpenPostWrite} > {translate!('post.edit')} </MenuItem>
|
<MenuItem onClick={this.handleOpenPostWrite} > {translate!('post.edit')} </MenuItem>
|
||||||
<MenuItem onClick={this.handleDelete} > {translate!('post.delete')} </MenuItem>
|
<MenuItem onClick={this.handleDelete} > {translate!('post.delete')} </MenuItem>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
onClick={() => this.props.toggleDisableComments!(!post.disableComments)} >
|
onClick={() => this.props.toggleDisableComments!(!post.get('disableComments'))} >
|
||||||
{post.disableComments ? translate!('post.enableComments') : translate!('post.disableComments')}
|
{post.get('disableComments') ? translate!('post.enableComments') : translate!('post.disableComments')}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
onClick={() => this.props.toggleSharingComments!(!post.disableSharing)} >
|
onClick={() => this.props.toggleSharingComments!(!post.get('disableSharing'))} >
|
||||||
{post.disableSharing ? translate!('post.enableSharing') : translate!('post.disableSharing')}
|
{post.get('disableSharing') ? translate!('post.enableSharing') : translate!('post.disableSharing')}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
</MenuList>
|
</MenuList>
|
||||||
</Paper>
|
</Paper>
|
||||||
@@ -375,13 +378,23 @@ export class PostComponent extends Component<IPostComponentProps, IPostComponent
|
|||||||
</Manager>
|
</Manager>
|
||||||
)
|
)
|
||||||
|
|
||||||
const { ownerUserId, ownerDisplayName, creationDate, image, body } = post
|
const {
|
||||||
|
ownerUserId,
|
||||||
|
ownerDisplayName,
|
||||||
|
creationDate,
|
||||||
|
image,
|
||||||
|
body,
|
||||||
|
id,
|
||||||
|
disableComments,
|
||||||
|
commentCounter,
|
||||||
|
disableSharing ,
|
||||||
|
} = post.toJS()
|
||||||
// Define variables
|
// Define variables
|
||||||
return (
|
return (
|
||||||
<Card>
|
<Card key={`post-component-${id}`}>
|
||||||
<CardHeader
|
<CardHeader
|
||||||
title={<NavLink to={`/${ownerUserId}`}>{ownerDisplayName}</NavLink>}
|
title={<NavLink to={`/${ownerUserId}`}>{ownerDisplayName}</NavLink>}
|
||||||
subheader={moment.unix(creationDate!).fromNow() + ' | ' + translate!('post.public')}
|
subheader={creationDate ? moment.unix(creationDate!).fromNow() + ' | ' + translate!('post.public') : <LinearProgress color='primary' />}
|
||||||
avatar={<NavLink to={`/${ownerUserId}`}><UserAvatar fullName={fullName!} fileName={avatar!} size={36} /></NavLink>}
|
avatar={<NavLink to={`/${ownerUserId}`}><UserAvatar fullName={fullName!} fileName={avatar!} size={36} /></NavLink>}
|
||||||
action={isPostOwner ? rightIconMenu : ''}
|
action={isPostOwner ? rightIconMenu : ''}
|
||||||
>
|
>
|
||||||
@@ -426,16 +439,16 @@ export class PostComponent extends Component<IPostComponentProps, IPostComponent
|
|||||||
<div className={classes.voteCounter}> {this.props.voteCount! > 0 ? this.props.voteCount : ''} </div>
|
<div className={classes.voteCounter}> {this.props.voteCount! > 0 ? this.props.voteCount : ''} </div>
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</div>
|
</div>
|
||||||
{!post.disableComments ?
|
{!disableComments ?
|
||||||
(<div style={{ display: 'inherit' }}><IconButton
|
(<div style={{ display: 'inherit' }}><IconButton
|
||||||
className={classes.iconButton}
|
className={classes.iconButton}
|
||||||
onClick={this.handleOpenComments}
|
onClick={this.handleOpenComments}
|
||||||
aria-label='Comment'>
|
aria-label='Comment'>
|
||||||
<SvgComment />
|
<SvgComment />
|
||||||
<div className={classes.commentCounter}>{post.commentCounter! > 0 ? post.commentCounter : ''} </div>
|
<div className={classes.commentCounter}>{commentCounter! > 0 ? commentCounter : ''} </div>
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</div>) : ''}
|
</div>) : ''}
|
||||||
{!post.disableSharing ? (<IconButton
|
{!disableSharing ? (<IconButton
|
||||||
className={classes.iconButton}
|
className={classes.iconButton}
|
||||||
onClick={this.handleOpenShare}
|
onClick={this.handleOpenShare}
|
||||||
aria-label='Comment'>
|
aria-label='Comment'>
|
||||||
@@ -444,7 +457,7 @@ export class PostComponent extends Component<IPostComponentProps, IPostComponent
|
|||||||
|
|
||||||
</CardActions>
|
</CardActions>
|
||||||
|
|
||||||
<CommentGroup open={this.state.openComments} comments={commentList} ownerPostUserId={post.ownerUserId!} onToggleRequest={this.handleOpenComments} isPostOwner={this.props.isPostOwner!} disableComments={post.disableComments!} postId={post.id!} />
|
<CommentGroup open={this.state.openComments} comments={commentList} ownerPostUserId={ownerUserId!} onToggleRequest={this.handleOpenComments} isPostOwner={this.props.isPostOwner!} disableComments={disableComments!} postId={id} />
|
||||||
|
|
||||||
<ShareDialog
|
<ShareDialog
|
||||||
onClose={this.handleCloseShare}
|
onClose={this.handleCloseShare}
|
||||||
@@ -477,16 +490,14 @@ export class PostComponent extends Component<IPostComponentProps, IPostComponent
|
|||||||
const mapDispatchToProps = (dispatch: any, ownProps: IPostComponentProps) => {
|
const mapDispatchToProps = (dispatch: any, ownProps: IPostComponentProps) => {
|
||||||
const { post } = ownProps
|
const { post } = ownProps
|
||||||
return {
|
return {
|
||||||
vote: () => dispatch(voteActions.dbAddVote(post.id!, post.ownerUserId!)),
|
vote: () => dispatch(voteActions.dbAddVote(post.get('id'), post.get('ownerUserId'))),
|
||||||
unvote: () => dispatch(voteActions.dbDeleteVote(post.id!, post.ownerUserId!)),
|
unvote: () => dispatch(voteActions.dbDeleteVote(post.get('id'), post.get('ownerUserId'))),
|
||||||
delete: (id: string) => dispatch(postActions.dbDeletePost(id)),
|
delete: (id: string) => dispatch(postActions.dbDeletePost(id)),
|
||||||
toggleDisableComments: (status: boolean) => {
|
toggleDisableComments: (status: boolean) => {
|
||||||
post.disableComments = status
|
dispatch(postActions.dbUpdatePost(post.set('disableComments', status), (x: any) => x))
|
||||||
dispatch(postActions.dbUpdatePost(post, (x: any) => x))
|
|
||||||
},
|
},
|
||||||
toggleSharingComments: (status: boolean) => {
|
toggleSharingComments: (status: boolean) => {
|
||||||
post.disableSharing = status
|
dispatch(postActions.dbUpdatePost(post.set('disableSharing', status), (x: any) => x))
|
||||||
dispatch(postActions.dbUpdatePost(post, (x: any) => x))
|
|
||||||
},
|
},
|
||||||
goTo: (url: string) => dispatch(push(url)),
|
goTo: (url: string) => dispatch(push(url)),
|
||||||
setHomeTitle: (title: string) => dispatch(globalActions.setHeaderTitle(title || '')),
|
setHomeTitle: (title: string) => dispatch(globalActions.setHeaderTitle(title || '')),
|
||||||
@@ -501,21 +512,21 @@ const mapDispatchToProps = (dispatch: any, ownProps: IPostComponentProps) => {
|
|||||||
* @param {object} ownProps is the props belong to component
|
* @param {object} ownProps is the props belong to component
|
||||||
* @return {object} props of component
|
* @return {object} props of component
|
||||||
*/
|
*/
|
||||||
const mapStateToProps = (state: any, ownProps: IPostComponentProps) => {
|
const mapStateToProps = (state: Map<string, any>, ownProps: IPostComponentProps) => {
|
||||||
const { post, vote, authorize, comment } = state
|
|
||||||
const { uid } = authorize
|
const uid = state.getIn(['authorize', 'uid'])
|
||||||
let currentUserVote = ownProps.post.votes ? ownProps.post.votes[uid] : false
|
let currentUserVote = ownProps.post.getIn(['votes', uid], false)
|
||||||
const postModel = post.userPosts[ownProps.post.ownerUserId!][ownProps.post.id!]
|
const voteCount = state.getIn(['post', 'userPosts', ownProps.post.get('ownerUserId'), ownProps.post.get('id'), 'score'], 0)
|
||||||
const postOwner = (post.userPosts[uid] ? Object.keys(post.userPosts[uid]).filter((key) => { return ownProps.post.id === key }).length : 0)
|
const commentList: { [commentId: string]: Comment } = state.getIn(['comment', 'postComments', ownProps.post.get('id')])
|
||||||
const commentList: { [commentId: string]: Comment } = comment.postComments[ownProps.post.id!]
|
const user = state.getIn(['user', 'info', ownProps.post.get('ownerUserId')])
|
||||||
return {
|
return {
|
||||||
translate: getTranslate(state.locale),
|
translate: getTranslate(state.get('locale')),
|
||||||
commentList,
|
commentList,
|
||||||
avatar: state.user.info && state.user.info[ownProps.post.ownerUserId!] ? state.user.info[ownProps.post.ownerUserId!].avatar || '' : '',
|
avatar: user ? user.avatar : '',
|
||||||
fullName: state.user.info && state.user.info[ownProps.post.ownerUserId!] ? state.user.info[ownProps.post.ownerUserId!].fullName || '' : '',
|
fullName: user ? user.fullName : '',
|
||||||
voteCount: postModel.score,
|
voteCount,
|
||||||
currentUserVote,
|
currentUserVote,
|
||||||
isPostOwner: postOwner > 0
|
isPostOwner: uid === ownProps.post.get('ownerUserId')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Post } from 'core/domain/posts'
|
import { Post } from 'core/domain/posts'
|
||||||
|
import {Map} from 'immutable'
|
||||||
export interface IPostWriteComponentProps {
|
export interface IPostWriteComponentProps {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -55,7 +55,7 @@ export interface IPostWriteComponentProps {
|
|||||||
/**
|
/**
|
||||||
* Post model
|
* Post model
|
||||||
*/
|
*/
|
||||||
postModel?: Post
|
postModel?: Map<string, any>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save a post
|
* Save a post
|
||||||
@@ -69,7 +69,7 @@ export interface IPostWriteComponentProps {
|
|||||||
*
|
*
|
||||||
* @memberof IPostWriteComponentProps
|
* @memberof IPostWriteComponentProps
|
||||||
*/
|
*/
|
||||||
update?: (post: Post, callback: Function) => any
|
update?: (post: Map<string, any>, callback: Function) => any
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Styles
|
* Styles
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import React, { Component } from 'react'
|
|||||||
import { connect } from 'react-redux'
|
import { connect } from 'react-redux'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
|
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
|
||||||
|
import { Map } from 'immutable'
|
||||||
|
|
||||||
import { Card, CardActions, CardHeader, CardMedia, CardContent } from 'material-ui'
|
import { Card, CardActions, CardHeader, CardMedia, CardContent } from 'material-ui'
|
||||||
import List, {
|
import List, {
|
||||||
@@ -108,15 +109,15 @@ export class PostWriteComponent extends Component<IPostWriteComponentProps, IPos
|
|||||||
/**
|
/**
|
||||||
* Post text
|
* Post text
|
||||||
*/
|
*/
|
||||||
postText: this.props.edit && postModel ? (postModel.body ? postModel.body! : '') : '',
|
postText: this.props.edit && postModel ? postModel.get('body', '') : '',
|
||||||
/**
|
/**
|
||||||
* The URL image of the post
|
* The URL image of the post
|
||||||
*/
|
*/
|
||||||
image: this.props.edit && postModel ? (postModel.image ? postModel.image! : '') : '',
|
image: this.props.edit && postModel ? postModel.get('image', '') : '',
|
||||||
/**
|
/**
|
||||||
* The path identifier of image on the server
|
* The path identifier of image on the server
|
||||||
*/
|
*/
|
||||||
imageFullPath: this.props.edit && postModel ? (postModel.imageFullPath ? postModel.imageFullPath! : '') : '',
|
imageFullPath: this.props.edit && postModel ? postModel.get('imageFullPath', '') : '',
|
||||||
/**
|
/**
|
||||||
* If it's true gallery will be open
|
* If it's true gallery will be open
|
||||||
*/
|
*/
|
||||||
@@ -132,11 +133,11 @@ export class PostWriteComponent extends Component<IPostWriteComponentProps, IPos
|
|||||||
/**
|
/**
|
||||||
* If it's true comment will be disabled on post
|
* If it's true comment will be disabled on post
|
||||||
*/
|
*/
|
||||||
disableComments: this.props.edit && postModel ? postModel.disableComments! : false,
|
disableComments: this.props.edit && postModel ? postModel.get('disableComments') : false,
|
||||||
/**
|
/**
|
||||||
* If it's true share will be disabled on post
|
* If it's true share will be disabled on post
|
||||||
*/
|
*/
|
||||||
disableSharing: this.props.edit && postModel ? postModel.disableSharing! : false
|
disableSharing: this.props.edit && postModel ? postModel.get('disableSharing') : false
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -253,14 +254,14 @@ export class PostWriteComponent extends Component<IPostWriteComponentProps, IPos
|
|||||||
}, onRequestClose)
|
}, onRequestClose)
|
||||||
}
|
}
|
||||||
} else { // In edit status we pass post to update functions
|
} else { // In edit status we pass post to update functions
|
||||||
postModel!.body = postText
|
const updatedPost = postModel!.set('body', postText)
|
||||||
postModel!.tags = tags
|
.set('tags', tags)
|
||||||
postModel!.image = image
|
.set('image', image)
|
||||||
postModel!.imageFullPath = imageFullPath
|
.set('imageFullPath', imageFullPath)
|
||||||
postModel!.disableComments = disableComments
|
.set('disableComments', disableComments)
|
||||||
postModel!.disableSharing = disableSharing
|
.set('disableSharing', disableSharing)
|
||||||
|
|
||||||
update!(postModel!, onRequestClose)
|
update!(updatedPost, onRequestClose)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -337,34 +338,38 @@ export class PostWriteComponent extends Component<IPostWriteComponentProps, IPos
|
|||||||
if (!nextProps.open) {
|
if (!nextProps.open) {
|
||||||
const { postModel } = this.props
|
const { postModel } = this.props
|
||||||
this.setState({
|
this.setState({
|
||||||
/**
|
/**
|
||||||
* Post text
|
* Post text
|
||||||
*/
|
*/
|
||||||
postText: this.props.edit && postModel ? (postModel.body ? postModel.body! : '') : '',
|
postText: this.props.edit && postModel ? postModel.get('body', '') : '',
|
||||||
/**
|
/**
|
||||||
* The URL image of the post
|
* The URL image of the post
|
||||||
*/
|
*/
|
||||||
image: this.props.edit && postModel ? (postModel.image ? postModel.image! : '') : '',
|
image: this.props.edit && postModel ? postModel.get('image', '') : '',
|
||||||
/**
|
/**
|
||||||
* The path identifier of image on the server
|
* The path identifier of image on the server
|
||||||
*/
|
*/
|
||||||
imageFullPath: this.props.edit && postModel ? (postModel.imageFullPath ? postModel.imageFullPath! : '') : '',
|
imageFullPath: this.props.edit && postModel ? postModel.get('imageFullPath', '') : '',
|
||||||
/**
|
/**
|
||||||
* If it's true gallery will be open
|
* If it's true gallery will be open
|
||||||
*/
|
*/
|
||||||
galleryOpen: false,
|
galleryOpen: false,
|
||||||
/**
|
/**
|
||||||
* If it's true post button will be disabled
|
* Whether menu is open
|
||||||
*/
|
*/
|
||||||
disabledPost: true,
|
menuOpen: false,
|
||||||
/**
|
/**
|
||||||
* If it's true comment will be disabled on post
|
* If it's true post button will be disabled
|
||||||
*/
|
*/
|
||||||
disableComments: this.props.edit && postModel ? postModel.disableComments! : false,
|
disabledPost: true,
|
||||||
/**
|
/**
|
||||||
* If it's true share will be disabled on post
|
* If it's true comment will be disabled on post
|
||||||
*/
|
*/
|
||||||
disableSharing: this.props.edit && postModel ? postModel.disableSharing! : false
|
disableComments: this.props.edit && postModel ? postModel.get('disableComments') : false,
|
||||||
|
/**
|
||||||
|
* If it's true share will be disabled on post
|
||||||
|
*/
|
||||||
|
disableSharing: this.props.edit && postModel ? postModel.get('disableSharing') : false
|
||||||
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -576,7 +581,7 @@ export class PostWriteComponent extends Component<IPostWriteComponentProps, IPos
|
|||||||
const mapDispatchToProps = (dispatch: any, ownProps: IPostWriteComponentProps) => {
|
const mapDispatchToProps = (dispatch: any, ownProps: IPostWriteComponentProps) => {
|
||||||
return {
|
return {
|
||||||
post: (post: Post, callBack: Function) => dispatch(postActions.dbAddImagePost(post, callBack)),
|
post: (post: Post, callBack: Function) => dispatch(postActions.dbAddImagePost(post, callBack)),
|
||||||
update: (post: Post, callBack: Function) => dispatch(postActions.dbUpdatePost(post, callBack))
|
update: (post: Map<string, any>, callBack: Function) => dispatch(postActions.dbUpdatePost(post, callBack))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -586,12 +591,14 @@ const mapDispatchToProps = (dispatch: any, ownProps: IPostWriteComponentProps) =
|
|||||||
* @param {object} ownProps is the props belong to component
|
* @param {object} ownProps is the props belong to component
|
||||||
* @return {object} props of component
|
* @return {object} props of component
|
||||||
*/
|
*/
|
||||||
const mapStateToProps = (state: any, ownProps: IPostWriteComponentProps) => {
|
const mapStateToProps = (state: Map<string, any>, ownProps: IPostWriteComponentProps) => {
|
||||||
|
const uid = state.getIn(['authorize', 'uid'])
|
||||||
|
const user = state.getIn(['user', 'info', uid], {})
|
||||||
return {
|
return {
|
||||||
translate: getTranslate(state.locale),
|
translate: getTranslate(state.get('locale')),
|
||||||
postImageState: state.imageGallery.status,
|
postImageState: state.getIn(['imageGallery', 'status']),
|
||||||
ownerAvatar: state.user.info && state.user.info[state.authorize.uid] ? state.user.info[state.authorize.uid].avatar : '',
|
ownerAvatar: user.avatar || '',
|
||||||
ownerDisplayName: state.user.info && state.user.info[state.authorize.uid] ? state.user.info[state.authorize.uid].fullName : ''
|
ownerDisplayName: user.fullName || ''
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
// - Import react components
|
// - Import react components
|
||||||
import React, { Component } from 'react'
|
import React, { Component } from 'react'
|
||||||
import { connect } from 'react-redux'
|
import { connect } from 'react-redux'
|
||||||
import PropTypes from 'prop-types'
|
|
||||||
import config from 'src/config'
|
import config from 'src/config'
|
||||||
|
import {Map} from 'immutable'
|
||||||
|
|
||||||
// - Material UI
|
// - Material UI
|
||||||
import { grey } from 'material-ui/colors'
|
import { grey } from 'material-ui/colors'
|
||||||
@@ -33,39 +33,6 @@ import { IProfileHeaderComponentState } from './IProfileHeaderComponentState'
|
|||||||
*/
|
*/
|
||||||
export class ProfileHeaderComponent extends Component<IProfileHeaderComponentProps, IProfileHeaderComponentState> {
|
export class ProfileHeaderComponent extends Component<IProfileHeaderComponentProps, IProfileHeaderComponentState> {
|
||||||
|
|
||||||
static propTypes = {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* User avatar address
|
|
||||||
*/
|
|
||||||
avatar: PropTypes.string,
|
|
||||||
/**
|
|
||||||
* User banner address
|
|
||||||
*/
|
|
||||||
banner: PropTypes.string,
|
|
||||||
/**
|
|
||||||
* User tagline
|
|
||||||
*/
|
|
||||||
tagLine: PropTypes.string,
|
|
||||||
/**
|
|
||||||
* User full name
|
|
||||||
*/
|
|
||||||
fullName: PropTypes.string.isRequired,
|
|
||||||
/**
|
|
||||||
* The number of followers
|
|
||||||
*/
|
|
||||||
followerCount: PropTypes.number,
|
|
||||||
/**
|
|
||||||
* User identifier
|
|
||||||
*/
|
|
||||||
userId: PropTypes.string,
|
|
||||||
/**
|
|
||||||
* If the user profile identifier of param is equal to the user authed identifier
|
|
||||||
*/
|
|
||||||
isAuthedUser: PropTypes.bool
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component constructor
|
* Component constructor
|
||||||
* @param {object} props is an object properties of component
|
* @param {object} props is an object properties of component
|
||||||
@@ -186,7 +153,7 @@ export class ProfileHeaderComponent extends Component<IProfileHeaderComponentPro
|
|||||||
/>
|
/>
|
||||||
<div className='left'>
|
<div className='left'>
|
||||||
{/* User avatar*/}
|
{/* User avatar*/}
|
||||||
<div style={{ display: 'flex', justifyContent: 'center' }}><UserAvatar fullName={this.props.fullName} fileName={this.props.avatar} size={60} style={styles.avatar} /></div>
|
<div style={{ display: 'flex', justifyContent: 'center' }}><UserAvatar fullName={this.props.fullName || ' '} fileName={this.props.avatar} size={60} style={styles.avatar} /></div>
|
||||||
<div className='info'>
|
<div className='info'>
|
||||||
<div className='fullName'>
|
<div className='fullName'>
|
||||||
{this.props.fullName}
|
{this.props.fullName}
|
||||||
@@ -235,11 +202,11 @@ const mapDispatchToProps = (dispatch: any, ownProps: IProfileHeaderComponentProp
|
|||||||
* @param {object} ownProps is the props belong to component
|
* @param {object} ownProps is the props belong to component
|
||||||
* @return {object} props of component
|
* @return {object} props of component
|
||||||
*/
|
*/
|
||||||
const mapStateToProps = (state: any, ownProps: IProfileHeaderComponentProps) => {
|
const mapStateToProps = (state: Map<string, any>, ownProps: IProfileHeaderComponentProps) => {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
translate: getTranslate(state.locale),
|
translate: getTranslate(state.get('locale')),
|
||||||
editProfileOpen: state.user.openEditProfile
|
editProfileOpen: state.getIn(['user', 'openEditProfile'])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { Feed } from 'core/domain/common/feed'
|
import { Feed } from 'core/domain/common/feed'
|
||||||
import { ServerRequestModel } from 'models/server/serverRequestModel'
|
import { ServerRequestModel } from 'models/server/serverRequestModel'
|
||||||
import { Profile } from 'core/domain/users'
|
import { Profile } from 'core/domain/users'
|
||||||
|
import { ServerRequestStatusType } from 'store/actions/serverRequestStatusType'
|
||||||
|
|
||||||
export interface ISendFeedbackComponentProps {
|
export interface ISendFeedbackComponentProps {
|
||||||
/**
|
/**
|
||||||
@@ -21,7 +22,7 @@ export interface ISendFeedbackComponentProps {
|
|||||||
/**
|
/**
|
||||||
* The server request of send feedback
|
* The server request of send feedback
|
||||||
*/
|
*/
|
||||||
sendFeedbackRequest?: ServerRequestModel
|
sendFeedbackRequestType?: ServerRequestStatusType
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Current user profile
|
* Current user profile
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import React, { Component } from 'react'
|
|||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import { connect } from 'react-redux'
|
import { connect } from 'react-redux'
|
||||||
import classNames from 'classnames'
|
import classNames from 'classnames'
|
||||||
|
import {Map} from 'immutable'
|
||||||
|
|
||||||
// - Material UI
|
// - Material UI
|
||||||
import Paper from 'material-ui/Paper'
|
import Paper from 'material-ui/Paper'
|
||||||
@@ -89,7 +90,7 @@ export class SendFeedbackComponent extends Component<ISendFeedbackComponentProps
|
|||||||
}
|
}
|
||||||
|
|
||||||
mainForm = () => {
|
mainForm = () => {
|
||||||
const { sendFeedbackStatus, hideFeedback, sendFeed, sendFeedbackRequest, translate } = this.props
|
const { sendFeedbackStatus, hideFeedback, sendFeed, sendFeedbackRequestType, translate } = this.props
|
||||||
const { feedText } = this.state
|
const { feedText } = this.state
|
||||||
return (
|
return (
|
||||||
<div className='main-box'>
|
<div className='main-box'>
|
||||||
@@ -168,11 +169,11 @@ export class SendFeedbackComponent extends Component<ISendFeedbackComponentProps
|
|||||||
}
|
}
|
||||||
|
|
||||||
getFeedbackForm = () => {
|
getFeedbackForm = () => {
|
||||||
const { sendFeedbackStatus, hideFeedback, sendFeed, sendFeedbackRequest } = this.props
|
const { sendFeedbackStatus, hideFeedback, sendFeed, sendFeedbackRequestType } = this.props
|
||||||
const { feedText } = this.state
|
const { feedText } = this.state
|
||||||
|
|
||||||
if (sendFeedbackRequest) {
|
if (sendFeedbackRequestType) {
|
||||||
switch (sendFeedbackRequest.status) {
|
switch (sendFeedbackRequestType) {
|
||||||
case ServerRequestStatusType.Sent:
|
case ServerRequestStatusType.Sent:
|
||||||
return this.loadingForm()
|
return this.loadingForm()
|
||||||
|
|
||||||
@@ -195,7 +196,7 @@ export class SendFeedbackComponent extends Component<ISendFeedbackComponentProps
|
|||||||
* @return {react element} return the DOM which rendered by component
|
* @return {react element} return the DOM which rendered by component
|
||||||
*/
|
*/
|
||||||
render () {
|
render () {
|
||||||
const { sendFeedbackStatus, hideFeedback, sendFeed, sendFeedbackRequest, classes } = this.props
|
const { sendFeedbackStatus, hideFeedback, sendFeed, sendFeedbackRequestType, classes } = this.props
|
||||||
const { feedText } = this.state
|
const { feedText } = this.state
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -237,19 +238,19 @@ const mapDispatchToProps = (dispatch: Function, ownProps: ISendFeedbackComponent
|
|||||||
* @param {object} ownProps is the props belong to component
|
* @param {object} ownProps is the props belong to component
|
||||||
* @return {object} props of component
|
* @return {object} props of component
|
||||||
*/
|
*/
|
||||||
const mapStateToProps = (state: any, ownProps: ISendFeedbackComponentProps) => {
|
const mapStateToProps = (state: Map<string, any>, ownProps: ISendFeedbackComponentProps) => {
|
||||||
|
|
||||||
const { server, global, authorize, user } = state
|
const request = state.getIn(['server', 'request'])
|
||||||
const { request } = server
|
const uid = state.getIn(['authorize', 'uid'])
|
||||||
const { uid } = authorize
|
const requestId = StringAPI.createServerRequestId(ServerRequestType.CommonSendFeedback, uid)
|
||||||
const currentUser: User = user.info && user.info[uid] ? { ...user.info[uid], userId: uid } : {}
|
const currentUser: User = { ...state.getIn(['user', 'info', uid], {}), userId: uid }
|
||||||
const { sendFeedbackStatus } = global
|
const sendFeedbackStatus = state.getIn(['global', 'sendFeedbackStatus'])
|
||||||
const sendFeedbackRequest: ServerRequestModel = request ? request[StringAPI.createServerRequestId(ServerRequestType.CommonSendFeedback, uid)] : null
|
const sendFeedbackRequestType = state.getIn(['server', 'request', requestId])
|
||||||
|
|
||||||
return {
|
return {
|
||||||
translate: getTranslate(state.locale),
|
translate: getTranslate(state.get('locale')),
|
||||||
sendFeedbackStatus,
|
sendFeedbackStatus,
|
||||||
sendFeedbackRequest,
|
sendFeedbackRequestType: sendFeedbackRequestType ? sendFeedbackRequestType.status : ServerRequestStatusType.NoAction,
|
||||||
currentUser
|
currentUser
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Post } from 'core/domain/posts'
|
import { Post } from 'core/domain/posts'
|
||||||
|
import {Map} from 'immutable'
|
||||||
|
|
||||||
export interface IShareDialogComponentProps {
|
export interface IShareDialogComponentProps {
|
||||||
|
|
||||||
@@ -25,7 +26,7 @@ export interface IShareDialogComponentProps {
|
|||||||
/**
|
/**
|
||||||
* The post object for sharing
|
* The post object for sharing
|
||||||
*/
|
*/
|
||||||
post: Post
|
post: Map<string, any>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Styles
|
* Styles
|
||||||
|
|||||||
@@ -105,9 +105,9 @@ export class ShareDialogComponent extends Component<IShareDialogComponentProps,
|
|||||||
<div>
|
<div>
|
||||||
<FacebookShareButton
|
<FacebookShareButton
|
||||||
onShareWindowClose={onClose}
|
onShareWindowClose={onClose}
|
||||||
url={`${location.origin}/${post.ownerUserId}/posts/${post.id}`}
|
url={`${location.origin}/${post.get('ownerUserId')}/posts/${post.get('id')}`}
|
||||||
quote={post.body}
|
quote={post.get('body')}
|
||||||
hashtag={`#${post.tags![0]}`}>
|
hashtag={`#${post.getIn(['tags', 0], '')}`}>
|
||||||
<MenuItem >
|
<MenuItem >
|
||||||
<ListItemIcon classes={{ root: classes.networkShare }}>
|
<ListItemIcon classes={{ root: classes.networkShare }}>
|
||||||
<FacebookIcon
|
<FacebookIcon
|
||||||
@@ -121,9 +121,9 @@ export class ShareDialogComponent extends Component<IShareDialogComponentProps,
|
|||||||
<div>
|
<div>
|
||||||
<TwitterShareButton
|
<TwitterShareButton
|
||||||
onShareWindowClose={onClose}
|
onShareWindowClose={onClose}
|
||||||
url={`${location.origin}/${post.ownerUserId}/posts/${post.id}`}
|
url={`${location.origin}/${post.get('ownerUserId')}/posts/${post.get('id')}`}
|
||||||
quote={post.body}
|
quote={post.get('body')}
|
||||||
hashtag={`#${post.tags![0]}`}>
|
hashtag={`#${post.getIn(['tags', 0], '')}`}>
|
||||||
<MenuItem >
|
<MenuItem >
|
||||||
<ListItemIcon classes={{ root: classes.networkShare }}>
|
<ListItemIcon classes={{ root: classes.networkShare }}>
|
||||||
<TwitterIcon
|
<TwitterIcon
|
||||||
@@ -137,9 +137,9 @@ export class ShareDialogComponent extends Component<IShareDialogComponentProps,
|
|||||||
<div>
|
<div>
|
||||||
<LinkedinShareButton
|
<LinkedinShareButton
|
||||||
onShareWindowClose={onClose}
|
onShareWindowClose={onClose}
|
||||||
url={`${location.origin}/${post.ownerUserId}/posts/${post.id}`}
|
url={`${location.origin}/${post.get('ownerUserId')}/posts/${post.get('id')}`}
|
||||||
quote={post.body}
|
quote={post.get('body')}
|
||||||
hashtag={`#${post.tags![0]}`}>
|
hashtag={`#${post.getIn(['tags', 0], '')}`}>
|
||||||
<MenuItem >
|
<MenuItem >
|
||||||
<ListItemIcon classes={{ root: classes.networkShare }}>
|
<ListItemIcon classes={{ root: classes.networkShare }}>
|
||||||
<LinkedinIcon
|
<LinkedinIcon
|
||||||
@@ -153,9 +153,9 @@ export class ShareDialogComponent extends Component<IShareDialogComponentProps,
|
|||||||
<div>
|
<div>
|
||||||
<GooglePlusShareButton
|
<GooglePlusShareButton
|
||||||
onShareWindowClose={onClose}
|
onShareWindowClose={onClose}
|
||||||
url={`${location.origin}/${post.ownerUserId}/posts/${post.id}`}
|
url={`${location.origin}/${post.get('ownerUserId')}/posts/${post.get('id')}`}
|
||||||
quote={post.body}
|
quote={post.get('body')}
|
||||||
hashtag={`#${post.tags![0]}`}>
|
hashtag={`#${post.getIn(['tags', 0], '')}`}>
|
||||||
<MenuItem >
|
<MenuItem >
|
||||||
<ListItemIcon classes={{ root: classes.networkShare }}>
|
<ListItemIcon classes={{ root: classes.networkShare }}>
|
||||||
<GooglePlusIcon
|
<GooglePlusIcon
|
||||||
@@ -174,7 +174,7 @@ export class ShareDialogComponent extends Component<IShareDialogComponentProps,
|
|||||||
</MenuItem>
|
</MenuItem>
|
||||||
</MenuList>)
|
</MenuList>)
|
||||||
: <div>
|
: <div>
|
||||||
<TextField autoFocus fullWidth={true} id='text-field-default' defaultValue={`${location.origin}/${post.ownerUserId}/posts/${post.id}`} />
|
<TextField autoFocus fullWidth={true} id='text-field-default' defaultValue={`${location.origin}/${post.get('ownerUserId')}/posts/${post.get('id')}`} />
|
||||||
<Typography className={classNames('animate-top', classes.clipboard)} variant='headline' component='h2'>
|
<Typography className={classNames('animate-top', classes.clipboard)} variant='headline' component='h2'>
|
||||||
Link has been copied to clipboard ...
|
Link has been copied to clipboard ...
|
||||||
</Typography>
|
</Typography>
|
||||||
@@ -205,7 +205,7 @@ const mapDispatchToProps = (dispatch: any, ownProps: IShareDialogComponentProps)
|
|||||||
*/
|
*/
|
||||||
const mapStateToProps = (state: any, ownProps: IShareDialogComponentProps) => {
|
const mapStateToProps = (state: any, ownProps: IShareDialogComponentProps) => {
|
||||||
return {
|
return {
|
||||||
translate: getTranslate(state.locale)
|
translate: getTranslate(state.get('locale'))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import React, { Component } from 'react'
|
|||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import { connect } from 'react-redux'
|
import { connect } from 'react-redux'
|
||||||
import Avatar from 'material-ui/Avatar'
|
import Avatar from 'material-ui/Avatar'
|
||||||
|
import { Map } from 'immutable'
|
||||||
|
|
||||||
// - Import app components
|
// - Import app components
|
||||||
|
|
||||||
@@ -95,8 +96,8 @@ const mapDispatchToProps = (dispatch: Function, ownProps: IUserAvatarComponentPr
|
|||||||
*/
|
*/
|
||||||
const mapStateToProps = (state: any, ownProps: IUserAvatarComponentProps) => {
|
const mapStateToProps = (state: any, ownProps: IUserAvatarComponentProps) => {
|
||||||
return {
|
return {
|
||||||
avatarURL: state.imageGallery.imageURLList,
|
avatarURL: state.getIn(['imageGallery', 'imageURLList']),
|
||||||
imageRequests: state.imageGallery.imageRequests
|
imageRequests: state.getIn(['imageGallery', 'imageRequests'])
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,40 +3,28 @@ import { Circle } from 'core/domain/circles/circle'
|
|||||||
import { UserTie } from 'core/domain/circles'
|
import { UserTie } from 'core/domain/circles'
|
||||||
import { ServerRequestStatusType } from 'store/actions/serverRequestStatusType'
|
import { ServerRequestStatusType } from 'store/actions/serverRequestStatusType'
|
||||||
import { ServerRequestModel } from 'models/server/serverRequestModel'
|
import { ServerRequestModel } from 'models/server/serverRequestModel'
|
||||||
|
import {Map, List} from 'immutable'
|
||||||
export interface IUserBoxComponentProps {
|
export interface IUserBoxComponentProps {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User identifier
|
* User identifier
|
||||||
*
|
|
||||||
* @type {string}
|
|
||||||
* @memberof IUserBoxComponentProps
|
|
||||||
*/
|
*/
|
||||||
userId: string
|
userId: string
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User
|
* User
|
||||||
*
|
|
||||||
* @type {User}
|
|
||||||
* @memberof IUserBoxComponentProps
|
|
||||||
*/
|
*/
|
||||||
user: UserTie
|
user: UserTie
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Circles
|
* Circles
|
||||||
*
|
|
||||||
* @type {{[circleId: string]: Circle}}
|
|
||||||
* @memberof IUserBoxComponentProps
|
|
||||||
*/
|
*/
|
||||||
circles?: {[circleId: string]: Circle}
|
circles?: Map<string, Map<string, any>>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of circles' id
|
* List of circles' id
|
||||||
*
|
|
||||||
* @type {string[]}
|
|
||||||
* @memberof IUserBoxComponentProps
|
|
||||||
*/
|
*/
|
||||||
userBelongCircles?: string[]
|
userBelongCircles?: List<string>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether current user followed this user
|
* Whether current user followed this user
|
||||||
@@ -45,54 +33,38 @@ export interface IUserBoxComponentProps {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The number of circles
|
* The number of circles
|
||||||
*
|
|
||||||
* @type {number}
|
|
||||||
* @memberof IUserBoxComponentProps
|
|
||||||
*/
|
*/
|
||||||
belongCirclesCount?: number
|
belongCirclesCount?: number
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The first circle
|
* The first circle
|
||||||
*
|
|
||||||
* @type {User}
|
|
||||||
* @memberof IUserBoxComponentProps
|
|
||||||
*/
|
*/
|
||||||
firstBelongCircle?: Circle
|
firstBelongCircle?: Map<string, any>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Avatar address
|
* Avatar address
|
||||||
*
|
|
||||||
* @type {string}
|
|
||||||
* @memberof IUserBoxComponentProps
|
|
||||||
*/
|
*/
|
||||||
avatar?: string
|
avatar?: string
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User full name
|
* User full name
|
||||||
*
|
|
||||||
* @type {string}
|
|
||||||
* @memberof IUserBoxComponentProps
|
|
||||||
*/
|
*/
|
||||||
fullName?: string
|
fullName?: string
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `Following` circle identifier of current user
|
* The `Following` circle identifier of current user
|
||||||
*/
|
*/
|
||||||
followingCircleId?: string
|
followingCircle?: Map<string, any>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a circle
|
* Create a circle
|
||||||
*
|
|
||||||
* @memberof IUserBoxComponentProps
|
|
||||||
*/
|
*/
|
||||||
createCircle?: (name: string) => any
|
createCircle?: (name: string) => any
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a user in a circle
|
* Add a user in a circle
|
||||||
*
|
|
||||||
* @memberof IUserBoxComponentProps
|
|
||||||
*/
|
*/
|
||||||
addUserToCircle?: (circleIds: string[],user: UserTie) => any
|
addUserToCircle?: (circleIds: List<string>,user: UserTie) => any
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add referer user to the `Following` circle of current user
|
* Add referer user to the `Following` circle of current user
|
||||||
@@ -107,12 +79,12 @@ export interface IUserBoxComponentProps {
|
|||||||
/**
|
/**
|
||||||
* Set current user selected circles for referer user
|
* Set current user selected circles for referer user
|
||||||
*/
|
*/
|
||||||
setSelectedCircles?: (userId: string, circleList: string[]) => any
|
setSelectedCircles?: (userId: string, circleList: List<string>) => any
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove current user selected circles for referer user
|
* Remove current user selected circles for referer user
|
||||||
*/
|
*/
|
||||||
removeSelectedCircles?: (userId: string, circleList: string[]) => any
|
removeSelectedCircles?: (userId: string, circleList: List<string>) => any
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open select circle box
|
* Open select circle box
|
||||||
@@ -126,8 +98,6 @@ export interface IUserBoxComponentProps {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Redirect page to [url]
|
* Redirect page to [url]
|
||||||
*
|
|
||||||
* @memberof IUserBoxComponentProps
|
|
||||||
*/
|
*/
|
||||||
goTo?: (url: string) => any
|
goTo?: (url: string) => any
|
||||||
|
|
||||||
@@ -149,7 +119,7 @@ export interface IUserBoxComponentProps {
|
|||||||
/**
|
/**
|
||||||
* Keep selected circles for refere user
|
* Keep selected circles for refere user
|
||||||
*/
|
*/
|
||||||
selectedCircles?: string[]
|
selectedCircles?: List<string>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the select circles box for referer user is open
|
* Whether the select circles box for referer user is open
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import PropTypes from 'prop-types'
|
|||||||
import { push } from 'react-router-redux'
|
import { push } from 'react-router-redux'
|
||||||
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
|
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
|
||||||
import classNames from 'classnames'
|
import classNames from 'classnames'
|
||||||
|
import {Map, List as ImuList} from 'immutable'
|
||||||
|
|
||||||
// - Material UI
|
// - Material UI
|
||||||
import Paper from 'material-ui/Paper'
|
import Paper from 'material-ui/Paper'
|
||||||
@@ -112,7 +113,6 @@ export class UserBoxComponent extends Component<IUserBoxComponentProps, IUserBox
|
|||||||
borderRadius: '4px'
|
borderRadius: '4px'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
selectedCircles: string[]
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component constructor
|
* Component constructor
|
||||||
@@ -140,7 +140,6 @@ export class UserBoxComponent extends Component<IUserBoxComponentProps, IUserBox
|
|||||||
*/
|
*/
|
||||||
disabledDoneCircles: true
|
disabledDoneCircles: true
|
||||||
}
|
}
|
||||||
this.selectedCircles = userBelongCircles!.slice()
|
|
||||||
// Binding functions to `this`
|
// Binding functions to `this`
|
||||||
this.handleChangeName = this.handleChangeName.bind(this)
|
this.handleChangeName = this.handleChangeName.bind(this)
|
||||||
this.onCreateCircle = this.onCreateCircle.bind(this)
|
this.onCreateCircle = this.onCreateCircle.bind(this)
|
||||||
@@ -153,11 +152,10 @@ export class UserBoxComponent extends Component<IUserBoxComponentProps, IUserBox
|
|||||||
* Handle follow user
|
* Handle follow user
|
||||||
*/
|
*/
|
||||||
handleDoneAddCircle = () => {
|
handleDoneAddCircle = () => {
|
||||||
const { userId, user, addUserToCircle, selectedCircles, deleteFollowingUser } = this.props
|
const { userId, user, addUserToCircle, selectedCircles, deleteFollowingUser, avatar, fullName } = this.props
|
||||||
const { avatar, fullName } = user
|
|
||||||
const { disabledDoneCircles } = this.state
|
const { disabledDoneCircles } = this.state
|
||||||
if (!disabledDoneCircles) {
|
if (!disabledDoneCircles) {
|
||||||
if (selectedCircles!.length > 0) {
|
if (selectedCircles!.count() > 0) {
|
||||||
addUserToCircle!(selectedCircles!, { avatar, userId, fullName })
|
addUserToCircle!(selectedCircles!, { avatar, userId, fullName })
|
||||||
} else {
|
} else {
|
||||||
deleteFollowingUser!(userId)
|
deleteFollowingUser!(userId)
|
||||||
@@ -171,14 +169,13 @@ export class UserBoxComponent extends Component<IUserBoxComponentProps, IUserBox
|
|||||||
onFollowUser = (event: any) => {
|
onFollowUser = (event: any) => {
|
||||||
// This prevents ghost click
|
// This prevents ghost click
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
const { isFollowed, followUser, followingCircleId, userId, user, followRequest } = this.props
|
const { isFollowed, followUser, followingCircle, userId, user, followRequest, avatar, fullName } = this.props
|
||||||
|
|
||||||
if (followRequest && followRequest.status === ServerRequestStatusType.Sent) {
|
if (followRequest && followRequest.status === ServerRequestStatusType.Sent) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const { avatar, fullName } = user
|
|
||||||
if (!isFollowed) {
|
if (!isFollowed) {
|
||||||
followUser!(followingCircleId!, { avatar, userId, fullName })
|
followUser!(followingCircle!.get('id'), { avatar, userId, fullName })
|
||||||
} else {
|
} else {
|
||||||
this.onRequestOpenAddCircle()
|
this.onRequestOpenAddCircle()
|
||||||
}
|
}
|
||||||
@@ -234,17 +231,13 @@ export class UserBoxComponent extends Component<IUserBoxComponentProps, IUserBox
|
|||||||
|
|
||||||
handleSelectCircle = (event: object, isInputChecked: boolean, circleId: string) => {
|
handleSelectCircle = (event: object, isInputChecked: boolean, circleId: string) => {
|
||||||
const { userBelongCircles, circles, setSelectedCircles, selectedCircles, userId } = this.props
|
const { userBelongCircles, circles, setSelectedCircles, selectedCircles, userId } = this.props
|
||||||
let newSelectedCircles = selectedCircles!.slice()
|
let newSelectedCircles = selectedCircles!
|
||||||
if (isInputChecked) {
|
if (isInputChecked) {
|
||||||
|
newSelectedCircles = selectedCircles!.push(circleId)
|
||||||
newSelectedCircles = [
|
|
||||||
...selectedCircles!,
|
|
||||||
circleId
|
|
||||||
]
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
const circleIndex = selectedCircles!.indexOf(circleId)
|
const circleIndex = selectedCircles!.indexOf(circleId)
|
||||||
newSelectedCircles.splice(circleIndex, 1)
|
newSelectedCircles = newSelectedCircles.remove(circleIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
setSelectedCircles!(userId, newSelectedCircles)
|
setSelectedCircles!(userId, newSelectedCircles)
|
||||||
@@ -258,39 +251,39 @@ export class UserBoxComponent extends Component<IUserBoxComponentProps, IUserBox
|
|||||||
*/
|
*/
|
||||||
circleList = () => {
|
circleList = () => {
|
||||||
let { circles, userId, userBelongCircles, selectedCircles, classes } = this.props
|
let { circles, userId, userBelongCircles, selectedCircles, classes } = this.props
|
||||||
|
const circleDomList: any[] = []
|
||||||
if (circles) {
|
if (circles) {
|
||||||
|
|
||||||
const parsedDate = Object.keys(circles).map((circleId, index) => {
|
circles.forEach((circle, circleId) => {
|
||||||
let isBelong = selectedCircles ? selectedCircles!.indexOf(circleId) > -1 : false
|
let isBelong = selectedCircles ? selectedCircles!.indexOf(circleId!) > -1 : false
|
||||||
|
|
||||||
// Create checkbox for selected/unselected circle
|
// Create checkbox for selected/unselected circle
|
||||||
return (
|
circleDomList.push(
|
||||||
<ListItem key={`${circleId}-${userId}`} dense className={classes.listItem}>
|
<ListItem key={`${circleId}-${userId}`} dense className={classes.listItem}>
|
||||||
<ListItemText className={classes.circleName} primary={circles![circleId].name} />
|
<ListItemText className={classes.circleName} primary={circle!.get('name')} />
|
||||||
<ListItemSecondaryAction>
|
<ListItemSecondaryAction>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
onChange={(event: object, isInputChecked: boolean) => this.handleSelectCircle(event, isInputChecked, circleId)}
|
onChange={(event: object, isInputChecked: boolean) => this.handleSelectCircle(event, isInputChecked, circleId!)}
|
||||||
checked={isBelong}
|
checked={isBelong}
|
||||||
/>
|
/>
|
||||||
</ListItemSecondaryAction>
|
</ListItemSecondaryAction>
|
||||||
</ListItem>)
|
</ListItem>)
|
||||||
})
|
})
|
||||||
|
|
||||||
return parsedDate
|
return circleDomList
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the the selected circles changed
|
* Check if the the selected circles changed
|
||||||
*/
|
*/
|
||||||
selectedCircleChange = (selectedCircles: string[]) => {
|
selectedCircleChange = (selectedCircles: ImuList<string>) => {
|
||||||
let isChanged = false
|
let isChanged = false
|
||||||
const { userBelongCircles, circles } = this.props
|
const { userBelongCircles, circles } = this.props
|
||||||
|
|
||||||
if (selectedCircles.length === userBelongCircles!.length) {
|
if (selectedCircles.count() === userBelongCircles!.count()) {
|
||||||
for (let circleIndex: number = 0; circleIndex < selectedCircles.length; circleIndex++) {
|
for (let circleIndex: number = 0; circleIndex < selectedCircles.count(); circleIndex++) {
|
||||||
const selectedCircleId = selectedCircles[circleIndex]
|
const selectedCircleId = selectedCircles.get(circleIndex)
|
||||||
if (!(userBelongCircles!.indexOf(selectedCircleId) > -1)) {
|
if (!(userBelongCircles!.indexOf(selectedCircleId) > -1)) {
|
||||||
isChanged = true
|
isChanged = true
|
||||||
break
|
break
|
||||||
@@ -308,7 +301,18 @@ export class UserBoxComponent extends Component<IUserBoxComponentProps, IUserBox
|
|||||||
*/
|
*/
|
||||||
render () {
|
render () {
|
||||||
const { disabledDoneCircles } = this.state
|
const { disabledDoneCircles } = this.state
|
||||||
const { isFollowed, followRequest, userId, isSelecteCirclesOpen, addToCircleRequest, deleteFollowingUserRequest, classes, translate } = this.props
|
const {
|
||||||
|
isFollowed,
|
||||||
|
firstBelongCircle,
|
||||||
|
belongCirclesCount,
|
||||||
|
followRequest,
|
||||||
|
userId,
|
||||||
|
isSelecteCirclesOpen,
|
||||||
|
addToCircleRequest,
|
||||||
|
deleteFollowingUserRequest,
|
||||||
|
classes,
|
||||||
|
translate
|
||||||
|
} = this.props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Paper key={userId} elevation={1} className={classNames('grid-cell', classes.paper)}>
|
<Paper key={userId} elevation={1} className={classNames('grid-cell', classes.paper)}>
|
||||||
@@ -331,7 +335,7 @@ export class UserBoxComponent extends Component<IUserBoxComponentProps, IUserBox
|
|||||||
</div>
|
</div>
|
||||||
<div onClick={() => this.props.goTo!(`/${this.props.userId}`)} className='people__name' style={{ cursor: 'pointer' }}>
|
<div onClick={() => this.props.goTo!(`/${this.props.userId}`)} className='people__name' style={{ cursor: 'pointer' }}>
|
||||||
<div>
|
<div>
|
||||||
{this.props.user.fullName}
|
{this.props.fullName}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style={this.styles.followButton as any}>
|
<div style={this.styles.followButton as any}>
|
||||||
@@ -344,7 +348,7 @@ export class UserBoxComponent extends Component<IUserBoxComponentProps, IUserBox
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
{!isFollowed ? translate!('userBox.followButton')
|
{!isFollowed ? translate!('userBox.followButton')
|
||||||
: (this.props.belongCirclesCount! > 1 ? translate!('userBox.numberOfCircleButton', {circlesCount: this.props.belongCirclesCount}) : ((this.props.firstBelongCircle) ? this.props.firstBelongCircle.name : translate!('userBox.followButton')))}
|
: (belongCirclesCount! > 1 ? translate!('userBox.numberOfCircleButton', {circlesCount: belongCirclesCount}) : ((firstBelongCircle) ? firstBelongCircle.get('name', 'Followed') : translate!('userBox.followButton')))}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -414,7 +418,7 @@ export class UserBoxComponent extends Component<IUserBoxComponentProps, IUserBox
|
|||||||
const mapDispatchToProps = (dispatch: Function, ownProps: IUserBoxComponentProps) => {
|
const mapDispatchToProps = (dispatch: Function, ownProps: IUserBoxComponentProps) => {
|
||||||
return {
|
return {
|
||||||
createCircle: (name: string) => dispatch(circleActions.dbAddCircle(name)),
|
createCircle: (name: string) => dispatch(circleActions.dbAddCircle(name)),
|
||||||
addUserToCircle: (circleIds: string[], user: UserTie) => dispatch(circleActions.dbUpdateUserInCircles(circleIds, user)),
|
addUserToCircle: (circleIds: ImuList<string>, user: UserTie) => dispatch(circleActions.dbUpdateUserInCircles(circleIds, user)),
|
||||||
followUser: (circleId: string, userFollowing: UserTie) => dispatch(circleActions.dbFollowUser(circleId, userFollowing)),
|
followUser: (circleId: string, userFollowing: UserTie) => dispatch(circleActions.dbFollowUser(circleId, userFollowing)),
|
||||||
deleteFollowingUser: (followingId: string) => dispatch(circleActions.dbDeleteFollowingUser(followingId)),
|
deleteFollowingUser: (followingId: string) => dispatch(circleActions.dbDeleteFollowingUser(followingId)),
|
||||||
setSelectedCircles: (userId: string, circleList: string[]) => dispatch(circleActions.setSelectedCircles(userId, circleList)),
|
setSelectedCircles: (userId: string, circleList: string[]) => dispatch(circleActions.setSelectedCircles(userId, circleList)),
|
||||||
@@ -432,36 +436,41 @@ const mapDispatchToProps = (dispatch: Function, ownProps: IUserBoxComponentProps
|
|||||||
* @param {object} ownProps is the props belong to component
|
* @param {object} ownProps is the props belong to component
|
||||||
* @return {object} props of component
|
* @return {object} props of component
|
||||||
*/
|
*/
|
||||||
const mapStateToProps = (state: any, ownProps: IUserBoxComponentProps) => {
|
const mapStateToProps = (state: Map<string, any>, ownProps: IUserBoxComponentProps) => {
|
||||||
|
|
||||||
const { circle, authorize, server } = state
|
const uid = state.getIn(['authorize', 'uid'])
|
||||||
const { uid } = authorize
|
const request = state.getIn(['server', 'request'])
|
||||||
const { request } = server
|
|
||||||
|
|
||||||
const circles: { [circleId: string]: Circle } = circle ? (circle.circleList || {}) : {}
|
const circles: Map<string, Map<string, any>> = state.getIn(['circle', 'circleList'], {})
|
||||||
const userBelongCircles = circle ? (circle.userTies[ownProps.userId] ? circle.userTies[ownProps.userId].circleIdList : []) : []
|
const userBelongCircles: ImuList<any> = state.getIn(['circle', 'userTies', ownProps.userId, 'circleIdList'], ImuList())
|
||||||
const isFollowed = userBelongCircles.length > 0
|
const isFollowed = userBelongCircles.count() > 0
|
||||||
const followingCircleId = circles ? Object.keys(circles)
|
const followingCircle = circles
|
||||||
.filter((circleId) => circles[circleId].isSystem && circles[circleId].name === `Following`)[0] : ''
|
.filter((followingCircle) => followingCircle!.get('isSystem', false) && followingCircle!.get('name') === `Following`)
|
||||||
const followRequest: ServerRequestModel = request ? request[StringAPI.createServerRequestId(ServerRequestType.CircleFollowUser, ownProps.userId)] : null
|
.toArray()[0]
|
||||||
const addToCircleRequest: ServerRequestModel = request ? request[StringAPI.createServerRequestId(ServerRequestType.CircleAddToCircle, ownProps.userId)] : null
|
const followRequestId = StringAPI.createServerRequestId(ServerRequestType.CircleFollowUser, ownProps.userId)
|
||||||
const deleteFollowingUserRequest: ServerRequestModel = request ? request[StringAPI.createServerRequestId(ServerRequestType.CircleDeleteFollowingUser, ownProps.userId)] : null
|
const followRequest = state.getIn(['server', 'request', followRequestId])
|
||||||
const selectedCircles = circle.selectedCircles ? circle.selectedCircles[ownProps.userId] : []
|
const addToCircleRequestId = StringAPI.createServerRequestId(ServerRequestType.CircleAddToCircle, ownProps.userId)
|
||||||
const isSelecteCirclesOpen = circle.openSelecteCircles ? circle.openSelecteCircles[ownProps.userId] : []
|
const addToCircleRequest = state.getIn(['server', 'request', addToCircleRequestId])
|
||||||
|
const deleteFollowingUserRequestId = StringAPI.createServerRequestId(ServerRequestType.CircleDeleteFollowingUser, ownProps.userId)
|
||||||
|
const deleteFollowingUserRequest = state.getIn(['server', 'request', deleteFollowingUserRequestId])
|
||||||
|
const selectedCircles = state.getIn(['circle', 'selectedCircles', ownProps.userId], [])
|
||||||
|
|
||||||
|
const isSelecteCirclesOpen = state.getIn(['circle', 'openSelecteCircles', ownProps.userId], [])
|
||||||
|
const userBox = state.getIn(['user', 'info', ownProps.userId])
|
||||||
|
|
||||||
return {
|
return {
|
||||||
translate: getTranslate(state.locale),
|
translate: getTranslate(state.get('locale')),
|
||||||
isSelecteCirclesOpen,
|
isSelecteCirclesOpen,
|
||||||
isFollowed,
|
isFollowed,
|
||||||
selectedCircles,
|
selectedCircles,
|
||||||
circles,
|
circles,
|
||||||
followingCircleId,
|
followingCircle,
|
||||||
userBelongCircles,
|
userBelongCircles,
|
||||||
followRequest,
|
followRequest,
|
||||||
belongCirclesCount: userBelongCircles.length || 0,
|
belongCirclesCount: userBelongCircles.count() || 0,
|
||||||
firstBelongCircle: userBelongCircles ? (circles ? circles[userBelongCircles[0]] : {}) : {},
|
firstBelongCircle: userBelongCircles ? circles.get(userBelongCircles.get(0), Map({})) : Map({}),
|
||||||
avatar: state.user.info && state.user.info[ownProps.userId] ? state.user.info[ownProps.userId].avatar || '' : '',
|
avatar: userBox.avatar || '' ,
|
||||||
fullName: state.user.info && state.user.info[ownProps.userId] ? state.user.info[ownProps.userId].fullName || '' : ''
|
fullName: userBox.fullName || ''
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { User } from 'core/domain/users'
|
import { User } from 'core/domain/users'
|
||||||
import { UserTie } from 'core/domain/circles'
|
import { UserTie } from 'core/domain/circles'
|
||||||
|
import {Map} from 'immutable'
|
||||||
|
|
||||||
export interface IUserBoxListComponentProps {
|
export interface IUserBoxListComponentProps {
|
||||||
|
|
||||||
@@ -9,7 +10,7 @@ export interface IUserBoxListComponentProps {
|
|||||||
* @type {{[userId: string]: User}}
|
* @type {{[userId: string]: User}}
|
||||||
* @memberof IUserBoxListComponentProps
|
* @memberof IUserBoxListComponentProps
|
||||||
*/
|
*/
|
||||||
users: {[userId: string]: UserTie}
|
users: Map<string, UserTie>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User identifier
|
* User identifier
|
||||||
|
|||||||
@@ -2,12 +2,14 @@
|
|||||||
import React, { Component } from 'react'
|
import React, { Component } from 'react'
|
||||||
import { connect } from 'react-redux'
|
import { connect } from 'react-redux'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
|
import {Map} from 'immutable'
|
||||||
|
|
||||||
// - Import app components
|
// - Import app components
|
||||||
import UserBox from 'components/userBox'
|
import UserBox from 'components/userBox'
|
||||||
|
|
||||||
import { IUserBoxListComponentProps } from './IUserBoxListComponentProps'
|
import { IUserBoxListComponentProps } from './IUserBoxListComponentProps'
|
||||||
import { IUserBoxListComponentState } from './IUserBoxListComponentState'
|
import { IUserBoxListComponentState } from './IUserBoxListComponentState'
|
||||||
|
import { UserTie } from 'core/domain/circles/userTie'
|
||||||
|
|
||||||
// - Import API
|
// - Import API
|
||||||
|
|
||||||
@@ -42,15 +44,17 @@ export class UserBoxListComponent extends Component<IUserBoxListComponentProps,I
|
|||||||
}
|
}
|
||||||
|
|
||||||
userList = () => {
|
userList = () => {
|
||||||
let { users, uid } = this.props
|
let { uid } = this.props
|
||||||
|
const users = this.props.users
|
||||||
|
const userBoxList: any[] = []
|
||||||
if (users) {
|
if (users) {
|
||||||
return Object.keys(users).map((key, index) => {
|
users.forEach((user: UserTie, key: string) => {
|
||||||
if (uid !== key) {
|
if (uid !== key) {
|
||||||
return <UserBox key={key} userId={key} user={users[key]}/>
|
userBoxList.push(<UserBox key={key} userId={key} user={user}/>)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
return userBoxList
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -92,7 +96,7 @@ const mapDispatchToProps = (dispatch: Function, ownProps: IUserBoxListComponentP
|
|||||||
* @return {object} props of component
|
* @return {object} props of component
|
||||||
*/
|
*/
|
||||||
const mapStateToProps = (state: any, ownProps: IUserBoxListComponentProps) => {
|
const mapStateToProps = (state: any, ownProps: IUserBoxListComponentProps) => {
|
||||||
const {uid} = state.authorize
|
const uid = state.getIn(['authorize', 'uid'], 0)
|
||||||
return {
|
return {
|
||||||
uid
|
uid
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,14 @@
|
|||||||
import { Circle } from 'core/domain/circles'
|
import { Circle } from 'core/domain/circles'
|
||||||
|
import {Map} from 'immutable'
|
||||||
export interface IYourCirclesComponentProps {
|
export interface IYourCirclesComponentProps {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Circles
|
* Circles
|
||||||
*
|
|
||||||
* @type {{[circleId: string]: Circle}}
|
|
||||||
* @memberof IYourCirclesComponentProps
|
|
||||||
*/
|
*/
|
||||||
circles?: {[circleId: string]: Circle}
|
circles?: Map<string, Map<string, any>>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User identifier
|
* User identifier
|
||||||
*
|
|
||||||
* @type {string}
|
|
||||||
* @memberof IYourCirclesComponentProps
|
|
||||||
*/
|
*/
|
||||||
uid?: string
|
uid?: string
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
import React, { Component } from 'react'
|
import React, { Component } from 'react'
|
||||||
import { connect } from 'react-redux'
|
import { connect } from 'react-redux'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
|
import {Map} from 'immutable'
|
||||||
|
|
||||||
import List from 'material-ui/List'
|
import List from 'material-ui/List'
|
||||||
|
|
||||||
// - Import app components
|
// - Import app components
|
||||||
@@ -44,8 +46,8 @@ export class YourCirclesComponent extends Component<IYourCirclesComponentProps,I
|
|||||||
let parsedCircles: any[] = []
|
let parsedCircles: any[] = []
|
||||||
|
|
||||||
if (circles) {
|
if (circles) {
|
||||||
Object.keys(circles).map((key, index) => {
|
circles.map((circle, key) => {
|
||||||
parsedCircles.push(<CircleComponent key={key} circle={circles![key]} id={key} uid={uid!} />)
|
parsedCircles.push(<CircleComponent key={key} circle={circle!} id={key!} uid={uid!} />)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return parsedCircles
|
return parsedCircles
|
||||||
@@ -95,10 +97,9 @@ const mapDispatchToProps = (dispatch: Function, ownProps: IYourCirclesComponentP
|
|||||||
* @param {object} ownProps is the props belong to component
|
* @param {object} ownProps is the props belong to component
|
||||||
* @return {object} props of component
|
* @return {object} props of component
|
||||||
*/
|
*/
|
||||||
const mapStateToProps = (state: any, ownProps: IYourCirclesComponentProps) => {
|
const mapStateToProps = (state: Map<string, any>, ownProps: IYourCirclesComponentProps) => {
|
||||||
const {circle, authorize, server} = state
|
const uid = state.getIn(['authorize', 'uid'])
|
||||||
const { uid } = state.authorize
|
const circles: Map<string, Map<string, any>> = state.getIn(['circle', 'circleList'], {})
|
||||||
const circles: { [circleId: string]: Circle } = circle ? (circle.circleList || {}) : {}
|
|
||||||
return {
|
return {
|
||||||
uid,
|
uid,
|
||||||
circles
|
circles
|
||||||
|
|||||||
@@ -12,6 +12,8 @@
|
|||||||
ADD_VIDEO_POST = 'ADD_VIDEO_POST',
|
ADD_VIDEO_POST = 'ADD_VIDEO_POST',
|
||||||
ADD_POST = 'ADD_POST',
|
ADD_POST = 'ADD_POST',
|
||||||
UPDATE_POST = 'UPDATE_POST',
|
UPDATE_POST = 'UPDATE_POST',
|
||||||
|
UPDATE_POST_COMMENTS = 'UPDATE_POST_COMMENTS',
|
||||||
|
UPDATE_POST_VOTES = 'UPDATE_POST_VOTES',
|
||||||
DELETE_POST = 'DELETE_POST',
|
DELETE_POST = 'DELETE_POST',
|
||||||
ADD_LIST_POST = 'ADD_LIST_POST',
|
ADD_LIST_POST = 'ADD_LIST_POST',
|
||||||
CLEAR_ALL_DATA_POST = 'CLEAR_ALL_DATA_POST'
|
CLEAR_ALL_DATA_POST = 'CLEAR_ALL_DATA_POST'
|
||||||
|
|||||||
@@ -144,7 +144,7 @@ const mapDispatchToProps = (dispatch: Function, ownProps: IEmailVerificationComp
|
|||||||
*/
|
*/
|
||||||
const mapStateToProps = (state: any, ownProps: IEmailVerificationComponentProps) => {
|
const mapStateToProps = (state: any, ownProps: IEmailVerificationComponentProps) => {
|
||||||
return {
|
return {
|
||||||
translate: getTranslate(state.locale)
|
translate: getTranslate(state.get('locale'))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
// - Import react components
|
// - Import react components
|
||||||
import { HomeRouter } from 'routes'
|
import { HomeRouter } from 'routes'
|
||||||
|
import { Map } from 'immutable'
|
||||||
import React, { Component } from 'react'
|
import React, { Component } from 'react'
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
import { Route, Switch, withRouter, Redirect, NavLink } from 'react-router-dom'
|
import { Route, Switch, withRouter, Redirect, NavLink } from 'react-router-dom'
|
||||||
@@ -172,7 +173,7 @@ export class HomeComponent extends Component<IHomeComponentProps, IHomeComponent
|
|||||||
if (!isVerifide) {
|
if (!isVerifide) {
|
||||||
goTo!('/emailVerification')
|
goTo!('/emailVerification')
|
||||||
|
|
||||||
} else if (!global.defaultLoadDataStatus) {
|
} else if (!global.get('defaultLoadDataStatus')) {
|
||||||
|
|
||||||
clearData!()
|
clearData!()
|
||||||
loadData!()
|
loadData!()
|
||||||
@@ -188,7 +189,7 @@ export class HomeComponent extends Component<IHomeComponentProps, IHomeComponent
|
|||||||
* @memberof Home
|
* @memberof Home
|
||||||
*/
|
*/
|
||||||
render() {
|
render() {
|
||||||
const HR = HomeRouter as any
|
const HR = HomeRouter
|
||||||
const { loaded, authed, loadDataStream, mergedPosts, hasMorePosts, showSendFeedback, translate, classes, theme } = this.props
|
const { loaded, authed, loadDataStream, mergedPosts, hasMorePosts, showSendFeedback, translate, classes, theme } = this.props
|
||||||
const { drawerOpen } = this.state
|
const { drawerOpen } = this.state
|
||||||
const drawer = (
|
const drawer = (
|
||||||
@@ -337,29 +338,28 @@ const mapDispatchToProps = (dispatch: any, ownProps: IHomeComponentProps) => {
|
|||||||
* @param {object} ownProps is the props belong to component
|
* @param {object} ownProps is the props belong to component
|
||||||
* @return {object} props of component
|
* @return {object} props of component
|
||||||
*/
|
*/
|
||||||
const mapStateToProps = (state: any, ownProps: IHomeComponentProps) => {
|
const mapStateToProps = (state: Map<string, any>, ownProps: IHomeComponentProps) => {
|
||||||
const { authorize, global, user, post, imageGallery, notify, circle } = state
|
const uid = state.getIn(['authorize', 'uid'], {})
|
||||||
const { uid } = authorize
|
const global = state.get('global', {})
|
||||||
let mergedPosts = {}
|
let mergedPosts = Map({})
|
||||||
const circles = circle ? (circle.circleList || {}) : {}
|
const circles = state.getIn(['circle', 'circleList'], {})
|
||||||
const followingUsers = circle ? circle.userTies : {}
|
const followingUsers: Map<string, any> = state.getIn(['circle', 'userTies'], {})
|
||||||
const posts = post.userPosts ? post.userPosts[authorize.uid] : {}
|
const posts = state.getIn(['post', 'userPosts', uid ], {})
|
||||||
const hasMorePosts = post.stream.hasMoreData
|
const hasMorePosts = state.getIn(['post', 'stream', 'hasMoreData' ], true)
|
||||||
Object.keys(followingUsers).forEach((userId) => {
|
followingUsers.forEach((user, userId) => {
|
||||||
let newPosts = post.userPosts ? post.userPosts[userId] : {}
|
let newPosts = state.getIn(['post', 'userPosts', userId], {})
|
||||||
_.merge(mergedPosts, newPosts)
|
mergedPosts = mergedPosts.merge(newPosts)
|
||||||
})
|
})
|
||||||
_.merge(mergedPosts, posts)
|
mergedPosts = mergedPosts.merge(posts)
|
||||||
return {
|
return {
|
||||||
authed: authorize.authed,
|
authed: state.getIn(['authorize', 'authed'], false),
|
||||||
isVerifide: authorize.isVerifide,
|
isVerifide: state.getIn(['authorize', 'isVerifide'], false),
|
||||||
mainStyle: global.sidebarMainStyle,
|
translate: getTranslate(state.get('locale')),
|
||||||
translate: getTranslate(state.locale),
|
currentLanguage: getActiveLanguage(state.get('locale')).code,
|
||||||
currentLanguage: getActiveLanguage(state.locale).code,
|
|
||||||
mergedPosts,
|
mergedPosts,
|
||||||
global,
|
global,
|
||||||
hasMorePosts,
|
hasMorePosts,
|
||||||
loaded: user.loaded && imageGallery.loaded && notify.loaded && circle.loaded
|
loaded: state.getIn(['user', 'loaded']) && state.getIn(['imageGallery', 'loaded']) && state.getIn(['notify', 'loaded']) && state.getIn(['circle', 'loaded'])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import Divider from 'material-ui/Divider'
|
|||||||
import ActionAndroid from 'material-ui-icons/Android'
|
import ActionAndroid from 'material-ui-icons/Android'
|
||||||
import { withStyles } from 'material-ui/styles'
|
import { withStyles } from 'material-ui/styles'
|
||||||
import config from 'src/config'
|
import config from 'src/config'
|
||||||
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
|
import { localize } from 'react-localize-redux'
|
||||||
|
|
||||||
// - Import actions
|
// - Import actions
|
||||||
import * as authorizeActions from 'src/store/actions/authorizeActions'
|
import * as authorizeActions from 'src/store/actions/authorizeActions'
|
||||||
@@ -20,6 +20,7 @@ import { ILoginComponentProps } from './ILoginComponentProps'
|
|||||||
import { ILoginComponentState } from './ILoginComponentState'
|
import { ILoginComponentState } from './ILoginComponentState'
|
||||||
import { OAuthType } from 'src/core/domain/authorize'
|
import { OAuthType } from 'src/core/domain/authorize'
|
||||||
import Grid from 'material-ui/Grid/Grid'
|
import Grid from 'material-ui/Grid/Grid'
|
||||||
|
import CommonAPI from 'api/CommonAPI'
|
||||||
|
|
||||||
const styles = (theme: any) => ({
|
const styles = (theme: any) => ({
|
||||||
textField: {
|
textField: {
|
||||||
@@ -253,9 +254,8 @@ const mapDispatchToProps = (dispatch: any, ownProps: ILoginComponentProps) => {
|
|||||||
*/
|
*/
|
||||||
const mapStateToProps = (state: any, ownProps: ILoginComponentProps) => {
|
const mapStateToProps = (state: any, ownProps: ILoginComponentProps) => {
|
||||||
return {
|
return {
|
||||||
translate: getTranslate(state.locale)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// - Connect component to redux store
|
// - Connect component to redux store
|
||||||
export default withRouter<any>(connect(mapStateToProps, mapDispatchToProps)(withStyles(styles)(LoginComponent as any) as any)) as typeof LoginComponent
|
export default withRouter<any>(connect(mapStateToProps, mapDispatchToProps)(withStyles(styles)(localize(LoginComponent, 'locale', CommonAPI.getStateSlice) as any) as any)) as typeof LoginComponent
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import { Route, Switch, NavLink, withRouter, Redirect } from 'react-router-dom'
|
|||||||
import { push } from 'react-router-redux'
|
import { push } from 'react-router-redux'
|
||||||
import Snackbar from 'material-ui/Snackbar'
|
import Snackbar from 'material-ui/Snackbar'
|
||||||
import { LinearProgress } from 'material-ui/Progress'
|
import { LinearProgress } from 'material-ui/Progress'
|
||||||
|
import {Helmet} from 'react-helmet'
|
||||||
|
import {Map} from 'immutable'
|
||||||
|
|
||||||
// - Import components
|
// - Import components
|
||||||
|
|
||||||
@@ -53,7 +55,6 @@ export class MasterComponent extends Component<IMasterComponentProps, IMasterCom
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Binding functions to `this`
|
// Binding functions to `this`
|
||||||
this.handleLoading = this.handleLoading.bind(this)
|
|
||||||
this.handleMessage = this.handleMessage.bind(this)
|
this.handleMessage = this.handleMessage.bind(this)
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -63,14 +64,6 @@ export class MasterComponent extends Component<IMasterComponentProps, IMasterCom
|
|||||||
this.props.closeMessage()
|
this.props.closeMessage()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle loading
|
|
||||||
handleLoading = (status: boolean) => {
|
|
||||||
this.setState({
|
|
||||||
loading: status,
|
|
||||||
authed: false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidCatch (error: any, info: any) {
|
componentDidCatch (error: any, info: any) {
|
||||||
console.log('===========Catched by React componentDidCatch==============')
|
console.log('===========Catched by React componentDidCatch==============')
|
||||||
console.log(error, info)
|
console.log(error, info)
|
||||||
@@ -130,6 +123,11 @@ export class MasterComponent extends Component<IMasterComponentProps, IMasterCom
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div id='master'>
|
<div id='master'>
|
||||||
|
<Helmet>
|
||||||
|
<meta charSet='utf-8' />
|
||||||
|
<title>React Social Network</title>
|
||||||
|
<link rel='canonical' href='https://github.com/Qolzam/react-social-network' />
|
||||||
|
</Helmet>
|
||||||
{sendFeedbackStatus ? <SendFeedback /> : ''}
|
{sendFeedbackStatus ? <SendFeedback /> : ''}
|
||||||
<div className='master__progress' style={{ display: (progress.visible ? 'block' : 'none') }}>
|
<div className='master__progress' style={{ display: (progress.visible ? 'block' : 'none') }}>
|
||||||
<LinearProgress variant='determinate' value={progress.percent} />
|
<LinearProgress variant='determinate' value={progress.percent} />
|
||||||
@@ -137,7 +135,7 @@ export class MasterComponent extends Component<IMasterComponentProps, IMasterCom
|
|||||||
<div className='master__loading animate-fading2' style={{ display: (global.showTopLoading ? 'flex' : 'none') }}>
|
<div className='master__loading animate-fading2' style={{ display: (global.showTopLoading ? 'flex' : 'none') }}>
|
||||||
<div className='title'>Loading ... </div>
|
<div className='title'>Loading ... </div>
|
||||||
</div>
|
</div>
|
||||||
<MasterLoading activeLoading={global.showMasterLoading} handleLoading={this.handleLoading} />
|
{progress.visible ? <MasterLoading /> : ''}
|
||||||
<MasterRouter enabled={!loading} data={{uid}} />
|
<MasterRouter enabled={!loading} data={{uid}} />
|
||||||
<Snackbar
|
<Snackbar
|
||||||
open={this.props.global.messageOpen}
|
open={this.props.global.messageOpen}
|
||||||
@@ -196,15 +194,16 @@ const mapDispatchToProps = (dispatch: any, ownProps: IMasterComponentProps) => {
|
|||||||
* Map state to props
|
* Map state to props
|
||||||
* @param {object} state
|
* @param {object} state
|
||||||
*/
|
*/
|
||||||
const mapStateToProps = (state: any) => {
|
const mapStateToProps = (state: Map<string, any>) => {
|
||||||
const { authorize, global, user, post, comment, imageGallery, vote, notify, circle } = state
|
const authorize = Map(state.get('authorize', {})).toJS()
|
||||||
const { sendFeedbackStatus } = global
|
const global = Map(state.get('global', {})).toJS()
|
||||||
|
const { sendFeedbackStatus, progress } = global
|
||||||
return {
|
return {
|
||||||
sendFeedbackStatus,
|
sendFeedbackStatus,
|
||||||
|
progress,
|
||||||
guest: authorize.guest,
|
guest: authorize.guest,
|
||||||
uid: authorize.uid,
|
uid: authorize.uid,
|
||||||
authed: authorize.authed,
|
authed: authorize.authed,
|
||||||
progress: global.progress,
|
|
||||||
global: global
|
global: global
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { push } from 'react-router-redux'
|
|||||||
import AppBar from 'material-ui/AppBar'
|
import AppBar from 'material-ui/AppBar'
|
||||||
import Typography from 'material-ui/Typography'
|
import Typography from 'material-ui/Typography'
|
||||||
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
|
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
|
||||||
|
import {Map} from 'immutable'
|
||||||
|
|
||||||
// - Import app components
|
// - Import app components
|
||||||
import FindPeople from 'src/components/findPeople'
|
import FindPeople from 'src/components/findPeople'
|
||||||
@@ -187,12 +188,12 @@ const mapDispatchToProps = (dispatch: any, ownProps: IPeopleComponentProps) => {
|
|||||||
* @param {object} ownProps is the props belong to component
|
* @param {object} ownProps is the props belong to component
|
||||||
* @return {object} props of component
|
* @return {object} props of component
|
||||||
*/
|
*/
|
||||||
const mapStateToProps = (state: any, ownProps: IPeopleComponentProps) => {
|
const mapStateToProps = (state: Map<string, any>, ownProps: IPeopleComponentProps) => {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
translate: getTranslate(state.locale),
|
translate: getTranslate(state.get('locale')),
|
||||||
uid: state.authorize.uid,
|
uid: state.getIn(['authorize', 'uid'], 0),
|
||||||
circlesLoaded: state.circle.loaded
|
circlesLoaded: state.getIn(['circle', 'loaded'])
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
import React, { Component } from 'react'
|
import React, { Component } from 'react'
|
||||||
import { connect } from 'react-redux'
|
import { connect } from 'react-redux'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
|
import {Map} from 'immutable'
|
||||||
|
|
||||||
// - Import app components
|
// - Import app components
|
||||||
import Stream from 'containers/stream'
|
import Stream from 'containers/stream'
|
||||||
@@ -76,12 +77,15 @@ const mapDispatchToProps = (dispatch: any,ownProps: IPostPageComponentProps) =>
|
|||||||
* @param {object} ownProps is the props belong to component
|
* @param {object} ownProps is the props belong to component
|
||||||
* @return {object} props of component
|
* @return {object} props of component
|
||||||
*/
|
*/
|
||||||
const mapStateToProps = (state: any,ownProps: IPostPageComponentProps) => {
|
const mapStateToProps = (state: Map<string, any>,ownProps: IPostPageComponentProps) => {
|
||||||
const {userId,postId} = ownProps.match.params
|
const {userId,postId} = ownProps.match.params
|
||||||
|
const userInfo = state.getIn(['state', 'user', 'info', userId])
|
||||||
|
let posts: Map<string, Map<string, any>> = Map({})
|
||||||
|
posts = posts.set(postId, state.getIn(['post', 'userPosts', userId, postId], Map({})))
|
||||||
return{
|
return{
|
||||||
avatar: state.user.info && state.user.info[userId] ? state.user.info[userId].avatar : '',
|
avatar: userInfo ? userInfo.avatar : '',
|
||||||
name: state.user.info && state.user.info[userId] ? state.user.info[userId].fullName : '',
|
name: userInfo ? userInfo.fullName : '',
|
||||||
posts: state.post.userPosts && state.post.userPosts[userId] ? {[postId] : { ...state.post.userPosts[userId][postId]}} : {}
|
posts
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import Dialog from 'material-ui/Dialog'
|
|||||||
import Button from 'material-ui/Button'
|
import Button from 'material-ui/Button'
|
||||||
import RaisedButton from 'material-ui/Button'
|
import RaisedButton from 'material-ui/Button'
|
||||||
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
|
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
|
||||||
|
import {Map} from 'immutable'
|
||||||
|
|
||||||
// - Import app components
|
// - Import app components
|
||||||
import ProfileHeader from 'src/components/profileHeader'
|
import ProfileHeader from 'src/components/profileHeader'
|
||||||
@@ -19,6 +20,7 @@ import * as userActions from 'src/store/actions/userActions'
|
|||||||
import * as globalActions from 'src/store/actions/globalActions'
|
import * as globalActions from 'src/store/actions/globalActions'
|
||||||
import { IProfileComponentProps } from './IProfileComponentProps'
|
import { IProfileComponentProps } from './IProfileComponentProps'
|
||||||
import { IProfileComponentState } from './IProfileComponentState'
|
import { IProfileComponentState } from './IProfileComponentState'
|
||||||
|
import { Profile } from 'core/domain/users'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create component class
|
* Create component class
|
||||||
@@ -78,13 +80,13 @@ export class ProfileComponent extends Component<IProfileComponentProps,IProfileC
|
|||||||
}
|
}
|
||||||
const {loadPosts, hasMorePosts, translate} = this.props
|
const {loadPosts, hasMorePosts, translate} = this.props
|
||||||
const St = StreamComponent as any
|
const St = StreamComponent as any
|
||||||
|
const posts = Map(this.props.posts)
|
||||||
return (
|
return (
|
||||||
<div style={styles.profile}>
|
<div style={styles.profile}>
|
||||||
<div style={styles.header}>
|
<div style={styles.header}>
|
||||||
|
|
||||||
<ProfileHeader tagLine={this.props.tagLine} avatar={this.props.avatar} isAuthedUser={this.props.isAuthedUser} banner={this.props.banner} fullName={this.props.name} followerCount={0} userId={this.props.userId}/>
|
<ProfileHeader tagLine={this.props.tagLine} avatar={this.props.avatar} isAuthedUser={this.props.isAuthedUser} banner={this.props.banner} fullName={this.props.name} followerCount={0} userId={this.props.userId}/>
|
||||||
</div>
|
</div>
|
||||||
{this.props.posts && Object.keys(this.props.posts).length !== 0
|
{posts
|
||||||
? (<div style={styles.content}>
|
? (<div style={styles.content}>
|
||||||
<div className='profile__title'>
|
<div className='profile__title'>
|
||||||
{translate!('profile.headPostsLabel', {userName: this.props.name})}
|
{translate!('profile.headPostsLabel', {userName: this.props.name})}
|
||||||
@@ -92,7 +94,7 @@ export class ProfileComponent extends Component<IProfileComponentProps,IProfileC
|
|||||||
<div style={{ height: '24px' }}></div>
|
<div style={{ height: '24px' }}></div>
|
||||||
|
|
||||||
<St
|
<St
|
||||||
posts={this.props.posts}
|
posts={posts}
|
||||||
loadStream={loadPosts}
|
loadStream={loadPosts}
|
||||||
hasMorePosts={hasMorePosts}
|
hasMorePosts={hasMorePosts}
|
||||||
displayWriting={false} />
|
displayWriting={false} />
|
||||||
@@ -128,17 +130,18 @@ const mapDispatchToProps = (dispatch: any, ownProps: IProfileComponentProps) =>
|
|||||||
* @param {object} ownProps is the props belong to component
|
* @param {object} ownProps is the props belong to component
|
||||||
* @return {object} props of component
|
* @return {object} props of component
|
||||||
*/
|
*/
|
||||||
const mapStateToProps = (state: any, ownProps: IProfileComponentProps) => {
|
const mapStateToProps = (state: Map<string, any>, ownProps: IProfileComponentProps) => {
|
||||||
const { userId } = ownProps.match.params
|
const { userId } = ownProps.match.params
|
||||||
const {uid} = state.authorize
|
const uid = state.getIn(['authorize', 'uid'], 0)
|
||||||
const hasMorePosts = state.post.profile.hasMoreData
|
const hasMorePosts = state.getIn(['post', 'profile', 'hasMoreData'])
|
||||||
const posts = state.post.userPosts ? state.post.userPosts[userId] : {}
|
const posts = state.getIn(['post', 'userPosts', userId])
|
||||||
|
const userProfile = state.getIn(['user', 'info', userId], {}) as Profile
|
||||||
return {
|
return {
|
||||||
translate: getTranslate(state.locale),
|
translate: getTranslate(state.get('locale')),
|
||||||
avatar: state.user.info && state.user.info[userId] ? state.user.info[userId].avatar || '' : '',
|
avatar: userProfile.avatar,
|
||||||
name: state.user.info && state.user.info[userId] ? state.user.info[userId].fullName || '' : '',
|
name: userProfile.fullName,
|
||||||
banner: state.user.info && state.user.info[userId] ? state.user.info[userId].banner || '' : '',
|
banner: userProfile.banner,
|
||||||
tagLine: state.user.info && state.user.info[userId] ? state.user.info[userId].tagLine || '' : '',
|
tagLine: userProfile.tagLine,
|
||||||
isAuthedUser: userId === uid,
|
isAuthedUser: userId === uid,
|
||||||
userId,
|
userId,
|
||||||
posts,
|
posts,
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ const mapDispatchToProps = (dispatch: Function, ownProps: IResetPasswordComponen
|
|||||||
*/
|
*/
|
||||||
const mapStateToProps = (state: any, ownProps: IResetPasswordComponentProps) => {
|
const mapStateToProps = (state: any, ownProps: IResetPasswordComponentProps) => {
|
||||||
return {
|
return {
|
||||||
translate: getTranslate(state.locale),
|
translate: getTranslate(state.get('locale')),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -225,7 +225,7 @@ const mapDispatchToProps = (dispatch: any, ownProps: ISettingComponentProps) =>
|
|||||||
*/
|
*/
|
||||||
const mapStateToProps = (state: any, ownProps: ISettingComponentProps) => {
|
const mapStateToProps = (state: any, ownProps: ISettingComponentProps) => {
|
||||||
return {
|
return {
|
||||||
translate: getTranslate(state.locale)
|
translate: getTranslate(state.get('locale'))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -287,7 +287,7 @@ const mapDispatchToProps = (dispatch: any, ownProps: ISignupComponentProps) => {
|
|||||||
*/
|
*/
|
||||||
const mapStateToProps = (state: any, ownProps: ISignupComponentProps) => {
|
const mapStateToProps = (state: any, ownProps: ISignupComponentProps) => {
|
||||||
return {
|
return {
|
||||||
translate: getTranslate(state.locale),
|
translate: getTranslate(state.get('locale')),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Post } from 'src/core/domain/posts'
|
import { Post } from 'src/core/domain/posts'
|
||||||
|
import {Map} from 'immutable'
|
||||||
|
|
||||||
export interface IStreamComponentProps {
|
export interface IStreamComponentProps {
|
||||||
|
|
||||||
@@ -82,7 +83,7 @@ export interface IStreamComponentProps {
|
|||||||
* @type {{[postId: string]: Post}}
|
* @type {{[postId: string]: Post}}
|
||||||
* @memberof IStreamComponentProps
|
* @memberof IStreamComponentProps
|
||||||
*/
|
*/
|
||||||
posts: {[postId: string]: Post}
|
posts: Map<string, Map<string, any>>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Router match property
|
* Router match property
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import Paper from 'material-ui/Paper'
|
|||||||
import List, { ListItem, ListItemIcon, ListItemText } from 'material-ui/List'
|
import List, { ListItem, ListItemIcon, ListItemText } from 'material-ui/List'
|
||||||
import InfiniteScroll from 'react-infinite-scroller'
|
import InfiniteScroll from 'react-infinite-scroller'
|
||||||
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
|
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
|
||||||
|
import { Map, List as ImuList } from 'immutable'
|
||||||
|
|
||||||
// - Import app components
|
// - Import app components
|
||||||
import PostComponent from 'src/components/post'
|
import PostComponent from 'src/components/post'
|
||||||
@@ -128,9 +129,10 @@ export class StreamComponent extends Component<IStreamComponentProps, IStreamCom
|
|||||||
*/
|
*/
|
||||||
postLoad = () => {
|
postLoad = () => {
|
||||||
|
|
||||||
let { posts, match } = this.props
|
let { match } = this.props
|
||||||
|
let posts: Map<string, Map<string, any>> = this.props.posts
|
||||||
let { tag } = match.params
|
let { tag } = match.params
|
||||||
if (posts === undefined || !(Object.keys(posts).length > 0)) {
|
if (posts === undefined || !(posts.keySeq().count() > 0)) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
||||||
@@ -138,37 +140,37 @@ export class StreamComponent extends Component<IStreamComponentProps, IStreamCom
|
|||||||
'Nothing has shared.'
|
'Nothing has shared.'
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
let postBack = { divided: false, oddPostList: [], evenPostList: [] }
|
let postBack = { divided: false, oddPostList: [], evenPostList: [] }
|
||||||
let parsedPosts: any = []
|
let parsedPosts: ImuList<any> = ImuList()
|
||||||
Object.keys(posts).forEach((postId) => {
|
posts.forEach((post: Map<string, any>) => {
|
||||||
if (tag) {
|
if (tag) {
|
||||||
let regex = new RegExp('#' + tag, 'g')
|
let regex = new RegExp('#' + tag, 'g')
|
||||||
let postMatch = posts[postId].body!.match(regex)
|
let postMatch = String(post.get('body', '')).match(regex)
|
||||||
if (postMatch !== null) {
|
if (postMatch !== null) {
|
||||||
parsedPosts.push({ ...posts[postId] })
|
parsedPosts = parsedPosts.push(post)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
parsedPosts.push({ ...posts[postId] })
|
parsedPosts = parsedPosts.push(post)
|
||||||
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
const sortedPosts = PostAPI.sortObjectsDate(parsedPosts)
|
const sortedPosts = PostAPI.sortImuObjectsDate(parsedPosts)
|
||||||
if (sortedPosts.length > 6) {
|
if (sortedPosts.count() > 6) {
|
||||||
postBack.divided = true
|
postBack.divided = true
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
postBack.divided = false
|
postBack.divided = false
|
||||||
}
|
}
|
||||||
sortedPosts.forEach((post: Post, index: any) => {
|
let index = 0
|
||||||
|
sortedPosts.forEach((post) => {
|
||||||
|
|
||||||
let newPost: any = (
|
let newPost: any = (
|
||||||
<div key={`${post.id!}-stream-div`}>
|
<div key={`${post!.get('id')!}-stream-div`}>
|
||||||
|
|
||||||
{index > 1 || (!postBack.divided && index > 0) ? <div style={{ height: '16px' }}></div> : ''}
|
{index > 1 || (!postBack.divided && index > 0) ? <div style={{ height: '16px' }}></div> : ''}
|
||||||
<PostComponent key={`${post.id!}-stream-div-post`} post={post} />
|
<PostComponent key={`${post!.get('id')}-stream-div-post`} post={post! as any} />
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
@@ -178,6 +180,7 @@ export class StreamComponent extends Component<IStreamComponentProps, IStreamCom
|
|||||||
} else {
|
} else {
|
||||||
postBack.evenPostList.push(newPost as never)
|
postBack.evenPostList.push(newPost as never)
|
||||||
}
|
}
|
||||||
|
++index
|
||||||
})
|
})
|
||||||
return postBack
|
return postBack
|
||||||
}
|
}
|
||||||
@@ -276,14 +279,15 @@ const mapDispatchToProps = (dispatch: any, ownProps: IStreamComponentProps) => {
|
|||||||
* @param {object} ownProps is the props belong to component
|
* @param {object} ownProps is the props belong to component
|
||||||
* @return {object} props of component
|
* @return {object} props of component
|
||||||
*/
|
*/
|
||||||
const mapStateToProps = (state: any, ownProps: IStreamComponentProps) => {
|
const mapStateToProps = (state: Map<string, any>, ownProps: IStreamComponentProps) => {
|
||||||
const { post } = state
|
const uid = state.getIn(['authorize', 'uid'])
|
||||||
|
const user = state.getIn(['user', 'info', uid])
|
||||||
return {
|
return {
|
||||||
translate: getTranslate(state.locale),
|
translate: getTranslate(state.get('locale')),
|
||||||
avatar: state.user.info && state.user.info[state.authorize.uid] ? state.user.info[state.authorize.uid].avatar : '',
|
avatar: user.avatar || '',
|
||||||
fullName: state.user.info && state.user.info[state.authorize.uid] ? state.user.info[state.authorize.uid].fullName : ''
|
fullName: user.fullName || ''
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// - Connect component to redux store
|
// - Connect component to redux store
|
||||||
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(StreamComponent as any) as any)
|
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(StreamComponent as any) as any) as typeof StreamComponent
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
import React, { Component } from 'react'
|
|
||||||
|
|
||||||
const asyncComponent = (importComponent: any) => {
|
|
||||||
return class extends Component {
|
|
||||||
state = {
|
|
||||||
component: null
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount () {
|
|
||||||
importComponent()
|
|
||||||
.then((cmp: any) => {
|
|
||||||
this.setState({component: cmp.default})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
render () {
|
|
||||||
const C: any = this.state.component
|
|
||||||
|
|
||||||
return C ? <C {...this.props} /> : null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default asyncComponent
|
|
||||||
@@ -1,29 +1,31 @@
|
|||||||
// - Import react components
|
// - Import react components
|
||||||
import PrivateRoute from './PrivateRoute'
|
import PrivateRoute from './PrivateRoute'
|
||||||
import React, { Component } from 'react'
|
import React, { Component } from 'react'
|
||||||
import PropTypes from 'prop-types'
|
|
||||||
import { connect } from 'react-redux'
|
import { connect } from 'react-redux'
|
||||||
import { Route, Switch, withRouter, Redirect, NavLink } from 'react-router-dom'
|
import { Route, Switch, withRouter, Redirect, NavLink } from 'react-router-dom'
|
||||||
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
|
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
|
||||||
|
import Loadable from 'react-loadable'
|
||||||
|
import { Map } from 'immutable'
|
||||||
|
|
||||||
import asyncComponent from 'hoc/asyncComponent/asyncComponent'
|
|
||||||
import { IRouterProps } from './IRouterProps'
|
import { IRouterProps } from './IRouterProps'
|
||||||
|
import MasterLoadingComponent from 'components/masterLoading/MasterLoadingComponent'
|
||||||
|
|
||||||
// - Async Components
|
// - Async Components
|
||||||
const AsyncStream = asyncComponent(() => {
|
const AsyncStream = Loadable({
|
||||||
return import('containers/stream')
|
loader: () => import('containers/stream'),
|
||||||
|
loading: MasterLoadingComponent,
|
||||||
})
|
})
|
||||||
|
const AsyncProfile = Loadable({
|
||||||
const AsyncProfile = asyncComponent(() => {
|
loader: () => import('containers/profile'),
|
||||||
return import('containers/profile')
|
loading: MasterLoadingComponent,
|
||||||
})
|
})
|
||||||
|
const AsyncPostPage = Loadable({
|
||||||
const AsyncPostPage = asyncComponent(() => {
|
loader: () => import('containers/postPage'),
|
||||||
return import('containers/postPage')
|
loading: MasterLoadingComponent,
|
||||||
})
|
})
|
||||||
|
const AsyncPeople = Loadable({
|
||||||
const AsyncPeople = asyncComponent(() => {
|
loader: () => import('containers/people'),
|
||||||
return import('containers/people')
|
loading: MasterLoadingComponent,
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -32,7 +34,7 @@ const AsyncPeople = asyncComponent(() => {
|
|||||||
export class HomeRouter extends Component<IRouterProps, any> {
|
export class HomeRouter extends Component<IRouterProps, any> {
|
||||||
render () {
|
render () {
|
||||||
const { enabled, match, data, translate } = this.props
|
const { enabled, match, data, translate } = this.props
|
||||||
const St = AsyncStream as any
|
const St = AsyncStream
|
||||||
return (
|
return (
|
||||||
enabled ? (
|
enabled ? (
|
||||||
<Switch>
|
<Switch>
|
||||||
@@ -71,10 +73,10 @@ const mapDispatchToProps = (dispatch: any, ownProps: IRouterProps) => {
|
|||||||
/**
|
/**
|
||||||
* Map state to props
|
* Map state to props
|
||||||
*/
|
*/
|
||||||
const mapStateToProps = (state: any, ownProps: IRouterProps) => {
|
const mapStateToProps = (state: Map<string, any>, ownProps: IRouterProps) => {
|
||||||
return {
|
return {
|
||||||
translate: getTranslate(state.locale),
|
translate: getTranslate(state.get('locale')),
|
||||||
currentLanguage: getActiveLanguage(state.locale).code,
|
currentLanguage: getActiveLanguage(state.get('locale')).code,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,33 +5,35 @@ import React, { Component } from 'react'
|
|||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import { connect } from 'react-redux'
|
import { connect } from 'react-redux'
|
||||||
import { Route, Switch, withRouter, Redirect, NavLink } from 'react-router-dom'
|
import { Route, Switch, withRouter, Redirect, NavLink } from 'react-router-dom'
|
||||||
|
import Loadable from 'react-loadable'
|
||||||
|
|
||||||
import asyncComponent from 'hoc/asyncComponent/asyncComponent'
|
|
||||||
import { IRouterProps } from './IRouterProps'
|
import { IRouterProps } from './IRouterProps'
|
||||||
|
import MasterLoadingComponent from 'components/masterLoading/MasterLoadingComponent'
|
||||||
|
|
||||||
// - Async Components
|
// - Async Components
|
||||||
const AsyncHome: any = asyncComponent(() => {
|
const AsyncHome: any = Loadable({
|
||||||
return import('containers/home')
|
loader: () => import('containers/home'),
|
||||||
|
loading: MasterLoadingComponent,
|
||||||
})
|
})
|
||||||
|
const AsyncSignup = Loadable({
|
||||||
const AsyncSignup = asyncComponent(() => {
|
loader: () => import('containers/signup'),
|
||||||
return import('containers/signup')
|
loading: MasterLoadingComponent,
|
||||||
})
|
})
|
||||||
|
const AsyncEmailVerification = Loadable({
|
||||||
const AsyncEmailVerification = asyncComponent(() => {
|
loader: () => import('containers/emailVerification'),
|
||||||
return import('containers/emailVerification')
|
loading: MasterLoadingComponent,
|
||||||
})
|
})
|
||||||
|
const AsyncResetPassword = Loadable({
|
||||||
const AsyncResetPassword = asyncComponent(() => {
|
loader: () => import('containers/resetPassword'),
|
||||||
return import('containers/resetPassword')
|
loading: MasterLoadingComponent,
|
||||||
})
|
})
|
||||||
|
const AsyncLogin = Loadable({
|
||||||
const AsyncLogin = asyncComponent(() => {
|
loader: () => import('containers/login'),
|
||||||
return import('containers/login')
|
loading: MasterLoadingComponent,
|
||||||
})
|
})
|
||||||
|
const AsyncSetting = Loadable({
|
||||||
const AsyncSetting = asyncComponent(() => {
|
loader: () => import('containers/setting'),
|
||||||
return import('containers/setting')
|
loading: MasterLoadingComponent,
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import React, { Component } from 'react'
|
|||||||
import { connect } from 'react-redux'
|
import { connect } from 'react-redux'
|
||||||
import { Route, Redirect } from 'react-router-dom'
|
import { Route, Redirect } from 'react-router-dom'
|
||||||
import { IRoute } from './IRoute'
|
import { IRoute } from './IRoute'
|
||||||
|
import { Map } from 'immutable'
|
||||||
|
|
||||||
export class PrivateRoute extends Component<IRoute, any> {
|
export class PrivateRoute extends Component<IRoute, any> {
|
||||||
|
|
||||||
@@ -19,10 +20,10 @@ export class PrivateRoute extends Component<IRoute, any> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = (state: any, nexProps: IRoute) => {
|
const mapStateToProps = (state: Map<string, any>, nexProps: IRoute) => {
|
||||||
const { authorize } = state
|
|
||||||
return {
|
return {
|
||||||
authed: authorize.authed
|
authed: state.getIn(['authorize', 'authed'])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import React, { Component } from 'react'
|
|||||||
import { connect } from 'react-redux'
|
import { connect } from 'react-redux'
|
||||||
import { Route, Redirect } from 'react-router-dom'
|
import { Route, Redirect } from 'react-router-dom'
|
||||||
import { IRoute } from './IRoute'
|
import { IRoute } from './IRoute'
|
||||||
|
import {Map} from 'immutable'
|
||||||
|
|
||||||
export class PublicRoute extends Component<IRoute, any> {
|
export class PublicRoute extends Component<IRoute, any> {
|
||||||
|
|
||||||
@@ -19,10 +20,10 @@ export class PublicRoute extends Component<IRoute, any> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = (state: any, nexProps: IRoute) => {
|
const mapStateToProps = (state: Map<string, any>, nexProps: IRoute) => {
|
||||||
const { authorize } = state
|
|
||||||
return {
|
return {
|
||||||
authed: authorize.authed
|
authed: state.getIn(['authorize', 'authed', false])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import CommonAPI from 'api/CommonAPI'
|
|||||||
/**
|
/**
|
||||||
* Developer tools
|
* Developer tools
|
||||||
*/
|
*/
|
||||||
console.trace = CommonAPI.logger
|
window['console']['trace'] = CommonAPI.logger
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize container
|
* Initialize container
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { User } from 'src/core/domain/users'
|
|||||||
import { Circle, UserTie } from 'src/core/domain/circles'
|
import { Circle, UserTie } from 'src/core/domain/circles'
|
||||||
import { SocialError } from 'src/core/domain/common'
|
import { SocialError } from 'src/core/domain/common'
|
||||||
import * as moment from 'moment/moment'
|
import * as moment from 'moment/moment'
|
||||||
|
import { Map, List } from 'immutable'
|
||||||
|
|
||||||
// - Import action types
|
// - Import action types
|
||||||
import { CircleActionType } from 'constants/circleActionType'
|
import { CircleActionType } from 'constants/circleActionType'
|
||||||
@@ -37,7 +38,8 @@ const userTieService: IUserTieService = provider.get<IUserTieService>(SocialProv
|
|||||||
export let dbAddCircle = (circleName: string) => {
|
export let dbAddCircle = (circleName: string) => {
|
||||||
return (dispatch: any, getState: Function) => {
|
return (dispatch: any, getState: Function) => {
|
||||||
|
|
||||||
let uid: string = getState().authorize.uid
|
const state: Map<string, any> = getState()
|
||||||
|
let uid: string = state.getIn(['authorize', 'uid'])
|
||||||
let circle: Circle = {
|
let circle: Circle = {
|
||||||
creationDate: moment().unix(),
|
creationDate: moment().unix(),
|
||||||
name: circleName,
|
name: circleName,
|
||||||
@@ -47,7 +49,7 @@ export let dbAddCircle = (circleName: string) => {
|
|||||||
return circleService.addCircle(uid, circle).then((circleKey: string) => {
|
return circleService.addCircle(uid, circle).then((circleKey: string) => {
|
||||||
circle.id = circleKey
|
circle.id = circleKey
|
||||||
circle.ownerId = uid
|
circle.ownerId = uid
|
||||||
dispatch(addCircle(circle))
|
dispatch(addCircle(Map(circle)))
|
||||||
|
|
||||||
}, (error: SocialError) => dispatch(globalActions.showMessage(error.message)))
|
}, (error: SocialError) => dispatch(globalActions.showMessage(error.message)))
|
||||||
|
|
||||||
@@ -59,9 +61,9 @@ export let dbAddCircle = (circleName: string) => {
|
|||||||
*/
|
*/
|
||||||
export const dbFollowUser = (followingCircleId: string, userFollowing: UserTie) => {
|
export const dbFollowUser = (followingCircleId: string, userFollowing: UserTie) => {
|
||||||
return (dispatch: Function, getState: Function) => {
|
return (dispatch: Function, getState: Function) => {
|
||||||
const state = getState()
|
const state: Map<string, any> = getState()
|
||||||
let uid: string = state.authorize.uid
|
let uid: string = state.getIn(['authorize', 'uid'])
|
||||||
let user: User = { ...state.user.info[uid], userId: uid }
|
let user: User = { ...state.getIn(['user', 'info', uid]), userId: uid }
|
||||||
|
|
||||||
// Set server request status to {Sent} for following user
|
// Set server request status to {Sent} for following user
|
||||||
const followReqestModel = createFollowRequest(userFollowing.userId!)
|
const followReqestModel = createFollowRequest(userFollowing.userId!)
|
||||||
@@ -74,15 +76,16 @@ export const dbFollowUser = (followingCircleId: string, userFollowing: UserTie)
|
|||||||
[followingCircleId]
|
[followingCircleId]
|
||||||
)
|
)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
dispatch(addFollowingUser(
|
let userTie: Map<string, any> = Map(new UserTie(
|
||||||
new UserTie(
|
userFollowing.userId!,
|
||||||
userFollowing.userId!,
|
moment().unix(),
|
||||||
moment().unix(),
|
userFollowing.fullName,
|
||||||
userFollowing.fullName,
|
userFollowing.avatar,
|
||||||
userFollowing.avatar,
|
false,
|
||||||
false,
|
))
|
||||||
[followingCircleId]
|
userTie = userTie.set('circleIdList', List([followingCircleId]))
|
||||||
)))
|
|
||||||
|
dispatch(addFollowingUser(userTie))
|
||||||
|
|
||||||
// Set server request status to {OK} for following user
|
// Set server request status to {OK} for following user
|
||||||
followReqestModel.status = ServerRequestStatusType.OK
|
followReqestModel.status = ServerRequestStatusType.OK
|
||||||
@@ -111,11 +114,11 @@ export const dbFollowUser = (followingCircleId: string, userFollowing: UserTie)
|
|||||||
/**
|
/**
|
||||||
* Update user in circle/circles
|
* Update user in circle/circles
|
||||||
*/
|
*/
|
||||||
export let dbUpdateUserInCircles = (circleIdList: string[], userFollowing: UserTie) => {
|
export let dbUpdateUserInCircles = (circleIdList: List<string>, userFollowing: UserTie) => {
|
||||||
return (dispatch: any, getState: Function) => {
|
return (dispatch: any, getState: Function) => {
|
||||||
const state = getState()
|
const state: Map<string, any> = getState()
|
||||||
let uid: string = state.authorize.uid
|
let uid: string = state.getIn(['authorize', 'uid'])
|
||||||
let user: User = { ...state.user.info[uid], userId: uid }
|
let user: User = { ...state.getIn(['user', 'info', uid]), userId: uid }
|
||||||
|
|
||||||
// Set server request status to {Sent}
|
// Set server request status to {Sent}
|
||||||
const addToCircleRequest = createAddToCircleRequest(userFollowing.userId!)
|
const addToCircleRequest = createAddToCircleRequest(userFollowing.userId!)
|
||||||
@@ -127,18 +130,18 @@ export let dbUpdateUserInCircles = (circleIdList: string[], userFollowing: UserT
|
|||||||
return userTieService.updateUsersTie(
|
return userTieService.updateUsersTie(
|
||||||
{ userId: user.userId!, fullName: user.fullName, avatar: user.avatar, approved: false },
|
{ userId: user.userId!, fullName: user.fullName, avatar: user.avatar, approved: false },
|
||||||
{ userId: userFollowing.userId!, fullName: userFollowing.fullName, avatar: userFollowing.avatar, approved: false },
|
{ userId: userFollowing.userId!, fullName: userFollowing.fullName, avatar: userFollowing.avatar, approved: false },
|
||||||
circleIdList
|
circleIdList.toJS()
|
||||||
)
|
)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
dispatch(addFollowingUser(
|
let userTie: Map<string, any> = Map(new UserTie(
|
||||||
new UserTie(
|
userFollowing.userId!,
|
||||||
userFollowing.userId!,
|
moment().unix(),
|
||||||
moment().unix(),
|
userFollowing.fullName,
|
||||||
userFollowing.fullName,
|
userFollowing.avatar,
|
||||||
userFollowing.avatar,
|
false
|
||||||
false,
|
))
|
||||||
circleIdList
|
userTie = userTie.set('circleIdList', circleIdList)
|
||||||
)))
|
dispatch(addFollowingUser(userTie))
|
||||||
|
|
||||||
// Set server request status to {OK}
|
// Set server request status to {OK}
|
||||||
addToCircleRequest.status = ServerRequestStatusType.OK
|
addToCircleRequest.status = ServerRequestStatusType.OK
|
||||||
@@ -167,7 +170,8 @@ export let dbUpdateUserInCircles = (circleIdList: string[], userFollowing: UserT
|
|||||||
export let dbDeleteFollowingUser = (userFollowingId: string) => {
|
export let dbDeleteFollowingUser = (userFollowingId: string) => {
|
||||||
return (dispatch: any, getState: Function) => {
|
return (dispatch: any, getState: Function) => {
|
||||||
|
|
||||||
let uid: string = getState().authorize.uid
|
const state: Map<string, any> = getState()
|
||||||
|
let uid: string = state.getIn(['authorize', 'uid'])
|
||||||
|
|
||||||
// Set server request status to {Sent}
|
// Set server request status to {Sent}
|
||||||
const deleteFollowingUserRequest = createdeleteFollowingUserRequest(userFollowingId)
|
const deleteFollowingUserRequest = createdeleteFollowingUserRequest(userFollowingId)
|
||||||
@@ -208,16 +212,17 @@ export let dbDeleteFollowingUser = (userFollowingId: string) => {
|
|||||||
*/
|
*/
|
||||||
export const dbUpdateCircle = (newCircle: Circle) => {
|
export const dbUpdateCircle = (newCircle: Circle) => {
|
||||||
return (dispatch: any, getState: Function) => {
|
return (dispatch: any, getState: Function) => {
|
||||||
|
|
||||||
// Get current user id
|
// Get current user id
|
||||||
let uid: string = getState().authorize.uid
|
const state: Map<string, any> = getState()
|
||||||
|
let uid: string = state.getIn(['authorize', 'uid'])
|
||||||
|
|
||||||
// Write the new data simultaneously in the list
|
// Write the new data simultaneously in the list
|
||||||
let circle: Circle = {...getState().circle.circleList[newCircle.id!]}
|
let circle: Map<string, any> = state.getIn(['circle', 'circleList', newCircle.id!])
|
||||||
circle.name = newCircle.name
|
circle = circle.set('name', newCircle.name)
|
||||||
return circleService.updateCircle(uid, newCircle.id!, circle)
|
return circleService.updateCircle(uid, newCircle.id!, circle.toJS())
|
||||||
.then(() => {
|
.then(() => {
|
||||||
dispatch(updateCircle({ id: newCircle.id, ...circle }))
|
circle = circle.set('id', newCircle.id)
|
||||||
|
dispatch(updateCircle(circle))
|
||||||
}, (error: SocialError) => {
|
}, (error: SocialError) => {
|
||||||
dispatch(globalActions.showMessage(error.message))
|
dispatch(globalActions.showMessage(error.message))
|
||||||
})
|
})
|
||||||
@@ -232,7 +237,8 @@ export const dbDeleteCircle = (circleId: string) => {
|
|||||||
return (dispatch: any, getState: Function) => {
|
return (dispatch: any, getState: Function) => {
|
||||||
|
|
||||||
// Get current user id
|
// Get current user id
|
||||||
let uid: string = getState().authorize.uid
|
const state: Map<string, any> = getState()
|
||||||
|
let uid: string = state.getIn(['authorize', 'uid'])
|
||||||
|
|
||||||
return circleService.deleteCircle(uid, circleId)
|
return circleService.deleteCircle(uid, circleId)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
@@ -249,7 +255,8 @@ export const dbDeleteCircle = (circleId: string) => {
|
|||||||
*/
|
*/
|
||||||
export const dbGetCircles = () => {
|
export const dbGetCircles = () => {
|
||||||
return (dispatch: any, getState: Function) => {
|
return (dispatch: any, getState: Function) => {
|
||||||
let uid: string = getState().authorize.uid
|
const state: Map<string, any> = getState()
|
||||||
|
let uid: string = state.getIn(['authorize', 'uid'])
|
||||||
if (uid) {
|
if (uid) {
|
||||||
|
|
||||||
return circleService.getCircles(uid)
|
return circleService.getCircles(uid)
|
||||||
@@ -269,7 +276,8 @@ export const dbGetCircles = () => {
|
|||||||
*/
|
*/
|
||||||
export const dbGetUserTies = () => {
|
export const dbGetUserTies = () => {
|
||||||
return (dispatch: any, getState: Function) => {
|
return (dispatch: any, getState: Function) => {
|
||||||
let uid: string = getState().authorize.uid
|
const state: Map<string, any> = getState()
|
||||||
|
let uid: string = state.getIn(['authorize', 'uid'])
|
||||||
if (uid) {
|
if (uid) {
|
||||||
userTieService.getUserTies(uid).then((result) => {
|
userTieService.getUserTies(uid).then((result) => {
|
||||||
|
|
||||||
@@ -289,7 +297,8 @@ export const dbGetUserTies = () => {
|
|||||||
*/
|
*/
|
||||||
export const dbGetFollowers = () => {
|
export const dbGetFollowers = () => {
|
||||||
return (dispatch: any, getState: Function) => {
|
return (dispatch: any, getState: Function) => {
|
||||||
let uid: string = getState().authorize.uid
|
const state: Map<string, any> = getState()
|
||||||
|
let uid: string = state.getIn(['authorize', 'uid'])
|
||||||
if (uid) {
|
if (uid) {
|
||||||
userTieService.getUserTieSender(uid).then((result) => {
|
userTieService.getUserTieSender(uid).then((result) => {
|
||||||
|
|
||||||
@@ -367,7 +376,7 @@ const createdeleteFollowingUserRequest = (userFollowingId: string) => {
|
|||||||
/**
|
/**
|
||||||
* Add a circle
|
* Add a circle
|
||||||
*/
|
*/
|
||||||
export const addCircle = (circle: Circle) => {
|
export const addCircle = (circle: Map<string, any>) => {
|
||||||
return {
|
return {
|
||||||
type: CircleActionType.ADD_CIRCLE,
|
type: CircleActionType.ADD_CIRCLE,
|
||||||
payload: { circle }
|
payload: { circle }
|
||||||
@@ -377,7 +386,7 @@ export const addCircle = (circle: Circle) => {
|
|||||||
/**
|
/**
|
||||||
* Update a circle
|
* Update a circle
|
||||||
*/
|
*/
|
||||||
export const updateCircle = (circle: Circle) => {
|
export const updateCircle = (circle: Map<string, any>) => {
|
||||||
return {
|
return {
|
||||||
type: CircleActionType.UPDATE_CIRCLE,
|
type: CircleActionType.UPDATE_CIRCLE,
|
||||||
payload: { circle }
|
payload: { circle }
|
||||||
@@ -438,7 +447,7 @@ export const closeCircleSettings = (circleId: string) => {
|
|||||||
/**
|
/**
|
||||||
* Add following user
|
* Add following user
|
||||||
*/
|
*/
|
||||||
export const addFollowingUser = (userTie: UserTie) => {
|
export const addFollowingUser = (userTie: Map<string, any>) => {
|
||||||
return {
|
return {
|
||||||
type: CircleActionType.ADD_FOLLOWING_USER,
|
type: CircleActionType.ADD_FOLLOWING_USER,
|
||||||
payload: { userTie }
|
payload: { userTie }
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// - Import react components
|
// - Import react components
|
||||||
import moment from 'moment/moment'
|
import moment from 'moment/moment'
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
|
import {Map} from 'immutable'
|
||||||
|
|
||||||
// - Import domain
|
// - Import domain
|
||||||
import { Comment } from 'src/core/domain/comments'
|
import { Comment } from 'src/core/domain/comments'
|
||||||
@@ -40,14 +41,14 @@ export const dbAddComment = (ownerPostUserId: string, newComment: Comment, callB
|
|||||||
|
|
||||||
dispatch(globalActions.showTopLoading())
|
dispatch(globalActions.showTopLoading())
|
||||||
|
|
||||||
const state = getState()
|
const state: Map<string, any> = getState()
|
||||||
let uid: string = state.authorize.uid
|
let uid: string = state.getIn(['authorize', 'uid'])
|
||||||
|
const currentUser = state.getIn(['user', 'info', uid])
|
||||||
let comment: Comment = {
|
let comment: Comment = {
|
||||||
score: 0,
|
score: 0,
|
||||||
creationDate: moment().unix(),
|
creationDate: moment().unix(),
|
||||||
userDisplayName: state.user.info[uid].fullName,
|
userDisplayName: currentUser.fullName,
|
||||||
userAvatar: state.user.info[uid].avatar,
|
userAvatar: currentUser.avatar,
|
||||||
userId: uid,
|
userId: uid,
|
||||||
postId: newComment.postId,
|
postId: newComment.postId,
|
||||||
text: newComment.text
|
text: newComment.text
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// - Import image gallery action types
|
// - Import image gallery action types
|
||||||
import { GlobalActionType } from 'constants/globalActionType'
|
import { GlobalActionType } from 'constants/globalActionType'
|
||||||
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
|
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
|
||||||
|
import { Map } from 'immutable'
|
||||||
|
|
||||||
// - Import actions
|
// - Import actions
|
||||||
import * as serverActions from 'store/actions/serverActions'
|
import * as serverActions from 'store/actions/serverActions'
|
||||||
@@ -24,8 +25,8 @@ const commonService: ICommonService = provider.get<ICommonService>(SocialProvide
|
|||||||
*/
|
*/
|
||||||
export let dbSendFeed = (newFeed: Feed) => {
|
export let dbSendFeed = (newFeed: Feed) => {
|
||||||
return (dispatch: any, getState: Function) => {
|
return (dispatch: any, getState: Function) => {
|
||||||
|
const state: Map<string, any> = getState()
|
||||||
let uid: string = getState().authorize.uid
|
let uid: string = state.getIn(['authorize', 'uid'])
|
||||||
|
|
||||||
// Set server request status to {Sent}
|
// Set server request status to {Sent}
|
||||||
const feedbackRequest = createFeedbackRequest(uid)
|
const feedbackRequest = createFeedbackRequest(uid)
|
||||||
@@ -49,8 +50,8 @@ export let dbSendFeed = (newFeed: Feed) => {
|
|||||||
// - Show notification of request
|
// - Show notification of request
|
||||||
export const showNotificationRequest = () => {
|
export const showNotificationRequest = () => {
|
||||||
return (dispatch: Function, getState: Function) => {
|
return (dispatch: Function, getState: Function) => {
|
||||||
const state = getState()
|
const state: Map<string, any> = getState()
|
||||||
const translate = getTranslate(state.locale)
|
const translate = getTranslate(state.get('locale'))
|
||||||
return dispatch(showMessage(String(translate('common.sentRequestMessage'))))
|
return dispatch(showMessage(String(translate('common.sentRequestMessage'))))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -58,8 +59,8 @@ export const showNotificationRequest = () => {
|
|||||||
// - Show notification of success
|
// - Show notification of success
|
||||||
export const showNotificationSuccess = () => {
|
export const showNotificationSuccess = () => {
|
||||||
return (dispatch: Function, getState: Function) => {
|
return (dispatch: Function, getState: Function) => {
|
||||||
const state = getState()
|
const state: Map<string, any> = getState()
|
||||||
const translate = getTranslate(state.locale)
|
const translate = getTranslate(state.get('locale'))
|
||||||
return dispatch(showMessage(String(translate('common.successfulRequestMessage'))))
|
return dispatch(showMessage(String(translate('common.successfulRequestMessage'))))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
// - Import react componetns
|
// - Import react componetns
|
||||||
import moment from 'moment/moment'
|
import moment from 'moment/moment'
|
||||||
|
import { Map } from 'immutable'
|
||||||
|
|
||||||
// - Import domain
|
// - Import domain
|
||||||
import { Image } from 'src/core/domain/imageGallery'
|
import { Image } from 'src/core/domain/imageGallery'
|
||||||
@@ -28,7 +29,8 @@ const imageGalleryService: IImageGalleryService = provider.get<IImageGalleryServ
|
|||||||
*/
|
*/
|
||||||
export const dbGetImageGallery = () => {
|
export const dbGetImageGallery = () => {
|
||||||
return (dispatch: any, getState: Function) => {
|
return (dispatch: any, getState: Function) => {
|
||||||
let uid: string = getState().authorize.uid
|
const state: Map<string, any> = getState()
|
||||||
|
let uid: string = state.getIn(['authorize', 'uid'])
|
||||||
if (uid) {
|
if (uid) {
|
||||||
|
|
||||||
return imageGalleryService.getImageGallery(uid)
|
return imageGalleryService.getImageGallery(uid)
|
||||||
@@ -51,7 +53,8 @@ export const dbGetImageGallery = () => {
|
|||||||
export const dbSaveImage = (imageURL: string,imageFullPath: string) => {
|
export const dbSaveImage = (imageURL: string,imageFullPath: string) => {
|
||||||
return (dispatch: any, getState: Function) => {
|
return (dispatch: any, getState: Function) => {
|
||||||
|
|
||||||
let uid: string = getState().authorize.uid
|
const state: Map<string, any> = getState()
|
||||||
|
let uid: string = state.getIn(['authorize', 'uid'])
|
||||||
let image: Image = {
|
let image: Image = {
|
||||||
creationDate: moment().unix(),
|
creationDate: moment().unix(),
|
||||||
deleteDate: '',
|
deleteDate: '',
|
||||||
@@ -82,7 +85,8 @@ export const dbDeleteImage = (id: string) => {
|
|||||||
return (dispatch: any, getState: Function) => {
|
return (dispatch: any, getState: Function) => {
|
||||||
|
|
||||||
// Get current user id
|
// Get current user id
|
||||||
let uid: string = getState().authorize.uid
|
const state: Map<string, any> = getState()
|
||||||
|
let uid: string = state.getIn(['authorize', 'uid'])
|
||||||
|
|
||||||
return imageGalleryService.deleteImage(uid,id)
|
return imageGalleryService.deleteImage(uid,id)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
// - Import domain
|
// - Import domain
|
||||||
import { Notification } from 'src/core/domain/notifications'
|
import { Notification } from 'src/core/domain/notifications'
|
||||||
import { SocialError } from 'src/core/domain/common'
|
import { SocialError } from 'src/core/domain/common'
|
||||||
|
import { Map, fromJS } from 'immutable'
|
||||||
|
|
||||||
// - Import action types
|
// - Import action types
|
||||||
import { NotificationActionType } from 'constants/notificationActionType'
|
import { NotificationActionType } from 'constants/notificationActionType'
|
||||||
@@ -23,7 +24,6 @@ const notificationService: INotificationService = provider.get<INotificationServ
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Add notificaition to database
|
* Add notificaition to database
|
||||||
* @param {object} newNotify user notificaition
|
|
||||||
*/
|
*/
|
||||||
export const dbAddNotification = (newNotify: Notification) => {
|
export const dbAddNotification = (newNotify: Notification) => {
|
||||||
return (dispatch: any, getState: Function) => {
|
return (dispatch: any, getState: Function) => {
|
||||||
@@ -50,16 +50,17 @@ export const dbAddNotification = (newNotify: Notification) => {
|
|||||||
*/
|
*/
|
||||||
export const dbGetNotifications = () => {
|
export const dbGetNotifications = () => {
|
||||||
return (dispatch: Function , getState: Function) => {
|
return (dispatch: Function , getState: Function) => {
|
||||||
let uid: string = getState().authorize.uid
|
const state: Map<string, any> = getState()
|
||||||
|
let uid: string = state.getIn(['authorize', 'uid'])
|
||||||
if (uid) {
|
if (uid) {
|
||||||
return notificationService.getNotifications(uid,
|
return notificationService.getNotifications(uid,
|
||||||
(notifications: { [notifyId: string]: Notification} ) => {
|
(notifications: { [notifyId: string]: Notification} ) => {
|
||||||
Object.keys(notifications).forEach((key => {
|
Object.keys(notifications).forEach((key => {
|
||||||
if (!getState().user.info[notifications[key].notifierUserId]) {
|
if (!state.getIn(['user', 'info', 'notifications', 'key','notifierUserId'])) {
|
||||||
dispatch(userActions.dbGetUserInfoByUserId(notifications[key].notifierUserId,''))
|
dispatch(userActions.dbGetUserInfoByUserId(notifications[key].notifierUserId,''))
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
dispatch(addNotifyList(notifications))
|
dispatch(addNotifyList(fromJS(notifications)))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -73,7 +74,8 @@ export const dbDeleteNotification = (id: string) => {
|
|||||||
return (dispatch: any, getState: Function) => {
|
return (dispatch: any, getState: Function) => {
|
||||||
|
|
||||||
// Get current user id
|
// Get current user id
|
||||||
let uid: string = getState().authorize.uid
|
const state: Map<string, any> = getState()
|
||||||
|
let uid: string = state.getIn(['authorize', 'uid'])
|
||||||
|
|
||||||
return notificationService.deleteNotification(id,uid).then(() => {
|
return notificationService.deleteNotification(id,uid).then(() => {
|
||||||
dispatch(deleteNotify(id))
|
dispatch(deleteNotify(id))
|
||||||
@@ -90,14 +92,14 @@ export const dbDeleteNotification = (id: string) => {
|
|||||||
export const dbSeenNotification = (id: string) => {
|
export const dbSeenNotification = (id: string) => {
|
||||||
return (dispatch: any, getState: Function) => {
|
return (dispatch: any, getState: Function) => {
|
||||||
|
|
||||||
// Get current user id
|
const state: Map<string, any> = getState()
|
||||||
let uid: string = getState().authorize.uid
|
let uid: string = state.getIn(['authorize', 'uid'])
|
||||||
let notify: Notification = getState().notify.userNotifies[id]
|
let notify: Map<string, any> = state.getIn(['notify', 'userNotifies', id])
|
||||||
|
|
||||||
let updatedNotification: Notification = {
|
let updatedNotification: Notification = {
|
||||||
description: notify.description,
|
description: notify.get('description'),
|
||||||
url: notify.url,
|
url: notify.get('url'),
|
||||||
notifierUserId: notify.notifierUserId,
|
notifierUserId: notify.get('notifierUserId'),
|
||||||
notifyRecieverUserId: uid,
|
notifyRecieverUserId: uid,
|
||||||
isSeen: true
|
isSeen: true
|
||||||
}
|
}
|
||||||
@@ -127,7 +129,7 @@ export const addNotify = () => {
|
|||||||
* Add notificaition list
|
* Add notificaition list
|
||||||
* @param {[notifyId: string]: Notification} userNotifies an array of notificaitions
|
* @param {[notifyId: string]: Notification} userNotifies an array of notificaitions
|
||||||
*/
|
*/
|
||||||
export const addNotifyList = (userNotifies: {[notifyId: string]: Notification}) => {
|
export const addNotifyList = (userNotifies: Map<string, any>) => {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: NotificationActionType.ADD_NOTIFY_LIST,
|
type: NotificationActionType.ADD_NOTIFY_LIST,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// - Import domain
|
// - Import domain
|
||||||
import { Post } from 'src/core/domain/posts'
|
import { Post } from 'src/core/domain/posts'
|
||||||
import { SocialError } from 'src/core/domain/common'
|
import { SocialError } from 'src/core/domain/common'
|
||||||
|
import { Map } from 'immutable'
|
||||||
|
|
||||||
// - Import utility components
|
// - Import utility components
|
||||||
import moment from 'moment/moment'
|
import moment from 'moment/moment'
|
||||||
@@ -27,8 +28,8 @@ const postService: IPostService = provider.get<IPostService>(SocialProviderTypes
|
|||||||
*/
|
*/
|
||||||
export let dbAddPost = (newPost: Post, callBack: Function) => {
|
export let dbAddPost = (newPost: Post, callBack: Function) => {
|
||||||
return (dispatch: any, getState: Function) => {
|
return (dispatch: any, getState: Function) => {
|
||||||
|
const state: Map<string, any> = getState()
|
||||||
let uid: string = getState().authorize.uid
|
let uid: string = state.getIn(['authorize', 'uid'])
|
||||||
let post: Post = {
|
let post: Post = {
|
||||||
postTypeId: 0,
|
postTypeId: 0,
|
||||||
creationDate: moment().unix(),
|
creationDate: moment().unix(),
|
||||||
@@ -70,8 +71,8 @@ export const dbAddImagePost = (newPost: Post, callBack: Function) => {
|
|||||||
return (dispatch: any, getState: Function) => {
|
return (dispatch: any, getState: Function) => {
|
||||||
|
|
||||||
dispatch(globalActions.showTopLoading())
|
dispatch(globalActions.showTopLoading())
|
||||||
|
const state: Map<string, any> = getState()
|
||||||
let uid: string = getState().authorize.uid
|
let uid: string = state.getIn(['authorize', 'uid'])
|
||||||
let post: Post = {
|
let post: Post = {
|
||||||
postTypeId: 1,
|
postTypeId: 1,
|
||||||
creationDate: moment().unix(),
|
creationDate: moment().unix(),
|
||||||
@@ -111,12 +112,12 @@ export const dbAddImagePost = (newPost: Post, callBack: Function) => {
|
|||||||
/**
|
/**
|
||||||
* Update a post from database
|
* Update a post from database
|
||||||
*/
|
*/
|
||||||
export const dbUpdatePost = (updatedPost: Post, callBack: Function) => {
|
export const dbUpdatePost = (updatedPost: Map<string, any>, callBack: Function) => {
|
||||||
return (dispatch: any, getState: Function) => {
|
return (dispatch: any, getState: Function) => {
|
||||||
console.trace('update post ', updatedPost)
|
|
||||||
dispatch(globalActions.showTopLoading())
|
dispatch(globalActions.showTopLoading())
|
||||||
|
|
||||||
return postService.updatePost(updatedPost).then(() => {
|
return postService.updatePost(updatedPost.toJS()).then(() => {
|
||||||
|
|
||||||
dispatch(updatePost(updatedPost))
|
dispatch(updatePost(updatedPost))
|
||||||
callBack()
|
callBack()
|
||||||
@@ -141,8 +142,9 @@ export const dbDeletePost = (id: string) => {
|
|||||||
|
|
||||||
dispatch(globalActions.showTopLoading())
|
dispatch(globalActions.showTopLoading())
|
||||||
|
|
||||||
|
const state: Map<string, any> = getState()
|
||||||
// Get current user id
|
// Get current user id
|
||||||
let uid: string = getState().authorize.uid
|
let uid: string = state.getIn(['authorize', 'uid'])
|
||||||
|
|
||||||
return postService.deletePost(id).then(() => {
|
return postService.deletePost(id).then(() => {
|
||||||
dispatch(deletePost(uid, id))
|
dispatch(deletePost(uid, id))
|
||||||
@@ -162,12 +164,12 @@ export const dbDeletePost = (id: string) => {
|
|||||||
*/
|
*/
|
||||||
export const dbGetPosts = (page: number = 0, limit: number = 10) => {
|
export const dbGetPosts = (page: number = 0, limit: number = 10) => {
|
||||||
return (dispatch: any, getState: Function) => {
|
return (dispatch: any, getState: Function) => {
|
||||||
const state = getState()
|
const state: Map<string, any> = getState()
|
||||||
const {stream} = state.post
|
const stream: Map<string, any> = state.getIn(['post', 'stream'])
|
||||||
const lastPageRequest = stream.lastPageRequest
|
const lastPageRequest = stream.get('lastPageRequest')
|
||||||
const lastPostId = stream.lastPostId
|
const lastPostId = stream.get('lastPostId')
|
||||||
|
|
||||||
let uid: string = state.authorize.uid
|
let uid: string = state.getIn(['authorize', 'uid'])
|
||||||
if (uid && lastPageRequest !== page) {
|
if (uid && lastPageRequest !== page) {
|
||||||
return postService.getPosts(uid, lastPostId, page, limit).then((result) => {
|
return postService.getPosts(uid, lastPostId, page, limit).then((result) => {
|
||||||
if (!result.posts || !(result.posts.length > 0)) {
|
if (!result.posts || !(result.posts.length > 0)) {
|
||||||
@@ -207,12 +209,12 @@ export const dbGetPosts = (page: number = 0, limit: number = 10) => {
|
|||||||
*/
|
*/
|
||||||
export const dbGetPostsByUserId = (userId: string, page: number = 0, limit: number = 10) => {
|
export const dbGetPostsByUserId = (userId: string, page: number = 0, limit: number = 10) => {
|
||||||
return (dispatch: any, getState: Function) => {
|
return (dispatch: any, getState: Function) => {
|
||||||
const state = getState()
|
const state: Map<string, any> = getState()
|
||||||
const {profile} = state.post
|
const {profile} = state.get('post')
|
||||||
const lastPageRequest = profile[userId] ? profile[userId].lastPageRequest : -1
|
const lastPageRequest = state.getIn(['post','profile', userId, 'lastPageRequest'], -1 )
|
||||||
const lastPostId = profile[userId] ? profile[userId].lastPostId : ''
|
const lastPostId = state.getIn(['post','profile', userId, 'lastPostId'], '' )
|
||||||
|
|
||||||
let uid: string = state.authorize.uid
|
let uid: string = state.getIn(['authorize', 'uid'])
|
||||||
|
|
||||||
if (uid && lastPageRequest !== page) {
|
if (uid && lastPageRequest !== page) {
|
||||||
|
|
||||||
@@ -282,13 +284,33 @@ export const addPost = (uid: string, post: Post) => {
|
|||||||
/**
|
/**
|
||||||
* Update a post
|
* Update a post
|
||||||
*/
|
*/
|
||||||
export const updatePost = (post: Post) => {
|
export const updatePost = (post: Map<string, any>) => {
|
||||||
return {
|
return {
|
||||||
type: PostActionType.UPDATE_POST,
|
type: PostActionType.UPDATE_POST,
|
||||||
payload: { post }
|
payload: { post }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the comments of post
|
||||||
|
*/
|
||||||
|
export const updatePostComments = (comments: Map<string, any>) => {
|
||||||
|
return {
|
||||||
|
type: PostActionType.UPDATE_POST,
|
||||||
|
payload: comments
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the votes of post
|
||||||
|
*/
|
||||||
|
export const updatePostVotes = (votes: Map<string, any>) => {
|
||||||
|
return {
|
||||||
|
type: PostActionType.UPDATE_POST,
|
||||||
|
payload: votes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete a post
|
* Delete a post
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
export enum ServerRequestStatusType {
|
export enum ServerRequestStatusType {
|
||||||
Sent = 'Sent',
|
Sent = 'Sent',
|
||||||
|
NoAction = 'NoAction',
|
||||||
OK = 'OK',
|
OK = 'OK',
|
||||||
Error = 'Error'
|
Error = 'Error'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
// - Import react components
|
// - Import react components
|
||||||
import { provider } from 'src/socialEngine'
|
import { provider } from 'src/socialEngine'
|
||||||
|
import { Map } from 'immutable'
|
||||||
|
|
||||||
// - Import domain
|
// - Import domain
|
||||||
import { Profile } from 'src/core/domain/users'
|
import { Profile } from 'src/core/domain/users'
|
||||||
import { SocialError } from 'src/core/domain/common'
|
import { SocialError } from 'src/core/domain/common'
|
||||||
@@ -25,7 +27,8 @@ const userService: IUserService = provider.get<IUserService>(SocialProviderTypes
|
|||||||
*/
|
*/
|
||||||
export const dbGetUserInfo = () => {
|
export const dbGetUserInfo = () => {
|
||||||
return (dispatch: any, getState: Function) => {
|
return (dispatch: any, getState: Function) => {
|
||||||
let uid: string = getState().authorize.uid
|
const state: Map<string, any> = getState()
|
||||||
|
let uid: string = state.getIn(['authorize', 'uid'])
|
||||||
if (uid) {
|
if (uid) {
|
||||||
return userService.getUserProfile(uid).then((userProfile: Profile) => {
|
return userService.getUserProfile(uid).then((userProfile: Profile) => {
|
||||||
dispatch(addUserInfo(uid, {
|
dispatch(addUserInfo(uid, {
|
||||||
@@ -54,7 +57,8 @@ export const dbGetUserInfoByUserId = (uid: string, callerKey: string) => {
|
|||||||
return (dispatch: Function, getState: Function) => {
|
return (dispatch: Function, getState: Function) => {
|
||||||
if (uid) {
|
if (uid) {
|
||||||
|
|
||||||
let caller = getState().global.temp.caller
|
const state: Map<string, any> = getState()
|
||||||
|
let caller = state.getIn(['global', 'temp', 'caller'])
|
||||||
if ( caller && caller.indexOf(`dbGetUserInfoByUserId-${uid}`) > -1) {
|
if ( caller && caller.indexOf(`dbGetUserInfoByUserId-${uid}`) > -1) {
|
||||||
return undefined
|
return undefined
|
||||||
}
|
}
|
||||||
@@ -95,11 +99,10 @@ export const dbGetUserInfoByUserId = (uid: string, callerKey: string) => {
|
|||||||
*/
|
*/
|
||||||
export const dbUpdateUserInfo = (newProfile: Profile) => {
|
export const dbUpdateUserInfo = (newProfile: Profile) => {
|
||||||
return (dispatch: any, getState: Function) => {
|
return (dispatch: any, getState: Function) => {
|
||||||
console.trace('newProfile', newProfile)
|
const state: Map<string, any> = getState()
|
||||||
// Get current user id
|
let uid: string = state.getIn(['authorize', 'uid'])
|
||||||
let uid: string = getState().authorize.uid
|
|
||||||
|
|
||||||
let profile: Profile = getState().user.info[uid]
|
let profile: Profile = state.getIn(['user', 'info', uid])
|
||||||
let updatedProfile: Profile = {
|
let updatedProfile: Profile = {
|
||||||
avatar: newProfile.avatar || profile.avatar || '',
|
avatar: newProfile.avatar || profile.avatar || '',
|
||||||
banner: newProfile.banner || profile.banner || 'https://firebasestorage.googleapis.com/v0/b/open-social-33d92.appspot.com/o/images%2F751145a1-9488-46fd-a97e-04018665a6d3.JPG?alt=media&token=1a1d5e21-5101-450e-9054-ea4a20e06c57',
|
banner: newProfile.banner || profile.banner || 'https://firebasestorage.googleapis.com/v0/b/open-social-33d92.appspot.com/o/images%2F751145a1-9488-46fd-a97e-04018665a6d3.JPG?alt=media&token=1a1d5e21-5101-450e-9054-ea4a20e06c57',
|
||||||
@@ -126,33 +129,27 @@ export const dbUpdateUserInfo = (newProfile: Profile) => {
|
|||||||
// - Get people info from database
|
// - Get people info from database
|
||||||
export const dbGetPeopleInfo = (page: number, limit: number) => {
|
export const dbGetPeopleInfo = (page: number, limit: number) => {
|
||||||
return (dispatch: any, getState: Function) => {
|
return (dispatch: any, getState: Function) => {
|
||||||
const state = getState()
|
const state: Map<string, any> = getState()
|
||||||
const {people} = state.user
|
const people: Map<string, any> = state.getIn(['user', 'people'])
|
||||||
const lastPageRequest = people.lastPageRequest
|
const lastPageRequest = people.get('lastPageRequest')
|
||||||
const lastUserId = people.lastUserId
|
const lastUserId = people.get('lastUserId')
|
||||||
|
|
||||||
let uid: string = state.authorize.uid
|
let uid: string = state.getIn(['authorize', 'uid'])
|
||||||
|
|
||||||
if (uid && lastPageRequest !== page) {
|
if (uid && lastPageRequest !== page) {
|
||||||
|
|
||||||
return userService.getUsersProfile(uid, lastUserId, page, limit).then((result) => {
|
return userService.getUsersProfile(uid, lastUserId, page, limit).then((result) => {
|
||||||
|
|
||||||
if (!result.users || !(result.users.length > 0)) {
|
if (!result.users || !(result.users.length > 0)) {
|
||||||
return dispatch(notMoreDataPeople())
|
return dispatch(notMoreDataPeople())
|
||||||
}
|
}
|
||||||
// Store last user Id
|
// Store last user Id
|
||||||
dispatch(lastUserPeople(result.newLastUserId))
|
dispatch(lastUserPeople(result.newLastUserId))
|
||||||
|
|
||||||
let parsedData: {[userId: string]: Profile} = {}
|
let parsedData: Map<string, Profile> = Map({})
|
||||||
result.users.forEach((post) => {
|
result.users.forEach((user) => {
|
||||||
const userId = Object.keys(post)[0]
|
const userId = Object.keys(user)[0]
|
||||||
const postData = post[userId]
|
const userData = user[userId]
|
||||||
parsedData = {
|
parsedData = parsedData.set(userId, userData)
|
||||||
...parsedData,
|
|
||||||
[userId]: {
|
|
||||||
...postData
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
dispatch(addPeopleInfo(parsedData))
|
dispatch(addPeopleInfo(parsedData))
|
||||||
})
|
})
|
||||||
@@ -176,9 +173,8 @@ export const addUserInfo = (uid: string, info: Profile) => {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Add people information
|
* Add people information
|
||||||
* @param {[userId: string]: Profile} infoList is the lst of information about users
|
|
||||||
*/
|
*/
|
||||||
export const addPeopleInfo = (infoList: {[userId: string]: Profile}) => {
|
export const addPeopleInfo = (infoList: Map<string, Profile>) => {
|
||||||
return {
|
return {
|
||||||
type: UserActionType.ADD_PEOPLE_INFO,
|
type: UserActionType.ADD_PEOPLE_INFO,
|
||||||
payload: infoList
|
payload: infoList
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import moment from 'moment/moment'
|
import moment from 'moment/moment'
|
||||||
|
import {Map} from 'immutable'
|
||||||
|
|
||||||
// - Import action types
|
// - Import action types
|
||||||
import { VoteActionType } from 'constants/voteActionType'
|
import { VoteActionType } from 'constants/voteActionType'
|
||||||
@@ -31,20 +32,22 @@ const voteService: IVoteService = provider.get<IVoteService>(SocialProviderTypes
|
|||||||
export const dbAddVote = (postId: string,ownerPostUserId: string) => {
|
export const dbAddVote = (postId: string,ownerPostUserId: string) => {
|
||||||
return (dispatch: any, getState: Function) => {
|
return (dispatch: any, getState: Function) => {
|
||||||
|
|
||||||
const state = getState()
|
const state: Map<string, any> = getState()
|
||||||
let uid: string = state.authorize.uid
|
let uid: string = state.getIn(['authorize', 'uid'])
|
||||||
|
const currentUser = state.getIn(['user', 'info', uid])
|
||||||
let vote: Vote = {
|
let vote: Vote = {
|
||||||
postId: postId,
|
postId: postId,
|
||||||
creationDate: moment().unix(),
|
creationDate: moment().unix(),
|
||||||
userDisplayName: getState().user.info[uid].fullName,
|
userDisplayName: currentUser.fullName,
|
||||||
userAvatar: getState().user.info[uid].avatar,
|
userAvatar: currentUser.avatar,
|
||||||
userId: uid
|
userId: uid
|
||||||
}
|
}
|
||||||
const post: Post = state.post.userPosts[ownerPostUserId][postId]
|
const post: Map<string, any> = state.getIn(['post', 'userPosts', ownerPostUserId, postId])
|
||||||
|
const score = Number(post.get('score', 0)) + 1
|
||||||
post.score! += 1
|
const votedPost = post
|
||||||
post.votes = { ...post.votes!, [uid]: true}
|
.set('score', score)
|
||||||
dispatch(postActions.updatePost(post))
|
.setIn(['votes',uid], true)
|
||||||
|
dispatch(postActions.updatePost(votedPost))
|
||||||
|
|
||||||
return voteService.addVote(vote).then((voteKey: string) => {
|
return voteService.addVote(vote).then((voteKey: string) => {
|
||||||
if (uid !== ownerPostUserId) {
|
if (uid !== ownerPostUserId) {
|
||||||
@@ -59,9 +62,11 @@ export const dbAddVote = (postId: string,ownerPostUserId: string) => {
|
|||||||
|
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
post.score! -= 1
|
const score = post.get('score', 0) - 1
|
||||||
post.votes = { ...post.votes!, [uid]: false}
|
const votedPost = post
|
||||||
dispatch(postActions.updatePost(post))
|
.set('score', score)
|
||||||
|
.setIn(['votes',uid], false)
|
||||||
|
dispatch(postActions.updatePost(votedPost))
|
||||||
dispatch(globalActions.showMessage(error.message))
|
dispatch(globalActions.showMessage(error.message))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -72,15 +77,15 @@ export const dbAddVote = (postId: string,ownerPostUserId: string) => {
|
|||||||
*/
|
*/
|
||||||
export const dbGetVotes = (userId: string, postId: string) => {
|
export const dbGetVotes = (userId: string, postId: string) => {
|
||||||
return (dispatch: any, getState: Function) => {
|
return (dispatch: any, getState: Function) => {
|
||||||
let uid: string = getState().authorize.uid
|
const state: Map<string, any> = getState()
|
||||||
|
let uid: string = state.getIn(['authorize', 'uid'])
|
||||||
if (uid) {
|
if (uid) {
|
||||||
|
|
||||||
return voteService
|
return voteService
|
||||||
.getVotes(postId)
|
.getVotes(postId)
|
||||||
.then((postVotes: { [postId: string]: { [voteId: string]: Vote } }) => {
|
.then((postVotes: { [postId: string]: { [voteId: string]: Vote } }) => {
|
||||||
dispatch(addVoteList(postVotes))
|
dispatch(addVoteList(postVotes))
|
||||||
const state = getState()
|
const post: Post = state.getIn(['post', 'userPosts', userId, postId])
|
||||||
const post: Post = state.post.userPosts[userId][postId]
|
|
||||||
if (!post) {
|
if (!post) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -101,18 +106,21 @@ export const dbGetVotes = (userId: string, postId: string) => {
|
|||||||
*/
|
*/
|
||||||
export const dbDeleteVote = (postId: string, ownerPostUserId: string) => {
|
export const dbDeleteVote = (postId: string, ownerPostUserId: string) => {
|
||||||
return (dispatch: any, getState: Function) => {
|
return (dispatch: any, getState: Function) => {
|
||||||
const state = getState()
|
const state: Map<string, any> = getState()
|
||||||
// Get current user id
|
let uid: string = state.getIn(['authorize', 'uid'])
|
||||||
let uid: string = state.authorize.uid
|
const post: Map<string, any> = state.getIn(['post', 'userPosts', ownerPostUserId, postId])
|
||||||
const post: Post = state.post.userPosts[ownerPostUserId][postId]
|
const score = post.get('score', 0) - 1
|
||||||
post.score! -= 1
|
const votedPost = post
|
||||||
post.votes = { ...post.votes!, [uid]: false}
|
.set('score', score)
|
||||||
dispatch(postActions.updatePost(post))
|
.setIn(['votes',uid], false)
|
||||||
|
dispatch(postActions.updatePost(votedPost))
|
||||||
return voteService.deleteVote(uid, postId).then(x => x)
|
return voteService.deleteVote(uid, postId).then(x => x)
|
||||||
.catch((error: any) => {
|
.catch((error: any) => {
|
||||||
post.score! += 1
|
const score = post.get('score', 0) + 1
|
||||||
post.votes = { ...post.votes!, [uid]: true}
|
const votedPost = post
|
||||||
dispatch(postActions.updatePost(post))
|
.set('score', score)
|
||||||
|
.setIn(['votes',uid], true)
|
||||||
|
dispatch(postActions.updatePost(votedPost))
|
||||||
dispatch(globalActions.showMessage(error.message))
|
dispatch(globalActions.showMessage(error.message))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,25 @@
|
|||||||
// - Import external components
|
// - Import external components
|
||||||
import * as redux from 'redux'
|
import { createStore, applyMiddleware, compose, Store } from 'redux'
|
||||||
|
import { composeWithDevTools } from 'redux-devtools-extension'
|
||||||
import thunk from 'redux-thunk'
|
import thunk from 'redux-thunk'
|
||||||
import { routerMiddleware } from 'react-router-redux'
|
import { routerMiddleware } from 'react-router-redux'
|
||||||
import createHistory from 'history/createBrowserHistory'
|
import createHistory from 'history/createBrowserHistory'
|
||||||
import createSagaMiddleware, { END } from 'redux-saga'
|
import createSagaMiddleware, { END } from 'redux-saga'
|
||||||
import { createLogger } from 'redux-logger'
|
import { createLogger } from 'redux-logger'
|
||||||
import { rootReducer } from 'store/reducers'
|
import { rootReducer } from 'store/reducers'
|
||||||
|
import { fromJS, Iterable, Map } from 'immutable'
|
||||||
import DevTools from './devTools'
|
import DevTools from './devTools'
|
||||||
// Create a history of your choosing (we're using a browser history in this case)
|
// Create a history of your choosing (we're using a browser history in this case)
|
||||||
export const history = createHistory()
|
export const history = createHistory()
|
||||||
|
|
||||||
// - Build the middleware for intercepting and dispatching navigation actions
|
// Logger option for transforming immutable js
|
||||||
const logger = createLogger()
|
const logger = createLogger({
|
||||||
|
stateTransformer: (state: Map<string, any>) => {
|
||||||
|
|
||||||
|
return state.toJS()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
const sagaMiddleware = createSagaMiddleware()
|
const sagaMiddleware = createSagaMiddleware()
|
||||||
// - initial state
|
// - initial state
|
||||||
let initialState = {
|
let initialState = {
|
||||||
@@ -19,9 +27,11 @@ let initialState = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// - Config and create store of redux
|
// - Config and create store of redux
|
||||||
let store: redux.Store<any> = redux.createStore(rootReducer, initialState, redux.compose(
|
const composeEnhancers = composeWithDevTools({
|
||||||
redux.applyMiddleware(logger,thunk, routerMiddleware(history), sagaMiddleware),
|
// Specify extension’s options like name, actionsBlacklist, actionsCreators, serialize...
|
||||||
DevTools.instrument()
|
})
|
||||||
|
let store: Store<any> = createStore(rootReducer, fromJS(initialState), composeEnhancers(
|
||||||
|
applyMiddleware(logger,thunk, routerMiddleware(history), sagaMiddleware)
|
||||||
))
|
))
|
||||||
|
|
||||||
export default {store, runSaga: sagaMiddleware.run, close: () => store.dispatch(END), history}
|
export default {store, runSaga: sagaMiddleware.run, close: () => store.dispatch(END), history}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { routerMiddleware } from 'react-router-redux'
|
|||||||
import createHistory from 'history/createBrowserHistory'
|
import createHistory from 'history/createBrowserHistory'
|
||||||
import createSagaMiddleware, { END } from 'redux-saga'
|
import createSagaMiddleware, { END } from 'redux-saga'
|
||||||
import { rootReducer } from 'store/reducers'
|
import { rootReducer } from 'store/reducers'
|
||||||
|
import { fromJS } from 'immutable'
|
||||||
// Create a history of your choosing (we're using a browser history in this case)
|
// Create a history of your choosing (we're using a browser history in this case)
|
||||||
export const history = createHistory()
|
export const history = createHistory()
|
||||||
|
|
||||||
@@ -16,7 +17,7 @@ let initialState = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// - Config and create store of redux
|
// - Config and create store of redux
|
||||||
let store: redux.Store<any> = redux.createStore(rootReducer, initialState, redux.compose(
|
let store: redux.Store<any> = redux.createStore(rootReducer, fromJS(initialState), redux.compose(
|
||||||
redux.applyMiddleware(thunk, routerMiddleware(history), sagaMiddleware)
|
redux.applyMiddleware(thunk, routerMiddleware(history), sagaMiddleware)
|
||||||
))
|
))
|
||||||
|
|
||||||
|
|||||||
@@ -6,41 +6,35 @@ import { AuthorizeActionType } from 'constants/authorizeActionType'
|
|||||||
|
|
||||||
import { IAuthorizeAction } from './IAuthorizeAction'
|
import { IAuthorizeAction } from './IAuthorizeAction'
|
||||||
import { AuthorizeState } from './AuthorizeState'
|
import { AuthorizeState } from './AuthorizeState'
|
||||||
|
import { Map } from 'immutable'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Authorize reducer
|
* Authorize reducer
|
||||||
* @param {object} state
|
* @param {object} state
|
||||||
* @param {object} action
|
* @param {object} action
|
||||||
*/
|
*/
|
||||||
export let authorizeReducer = (state: AuthorizeState = new AuthorizeState(), action: IAuthorizeAction) => {
|
export let authorizeReducer = (state = Map(new AuthorizeState()), action: IAuthorizeAction) => {
|
||||||
const { payload } = action
|
const { payload } = action
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case AuthorizeActionType.LOGIN:
|
case AuthorizeActionType.LOGIN:
|
||||||
return{
|
return state
|
||||||
...state,
|
.set('uid', payload.uid)
|
||||||
uid: payload.uid,
|
.set('authed', true)
|
||||||
authed: true,
|
.set('guest', false)
|
||||||
guest: false,
|
.set('isVerifide', payload.isVerifide)
|
||||||
isVerifide: payload.isVerifide
|
|
||||||
}
|
|
||||||
case AuthorizeActionType.LOGOUT:
|
|
||||||
return{
|
|
||||||
...state,
|
|
||||||
uid: 0,
|
|
||||||
authed: false,
|
|
||||||
guest: true
|
|
||||||
}
|
|
||||||
|
|
||||||
|
case AuthorizeActionType.LOGOUT:
|
||||||
|
return state
|
||||||
|
.set('uid', 0)
|
||||||
|
.set('authed', false)
|
||||||
|
.set('guest', true)
|
||||||
|
.set('isVerifide', false)
|
||||||
case AuthorizeActionType.SIGNUP:
|
case AuthorizeActionType.SIGNUP:
|
||||||
return{
|
return state
|
||||||
...state,
|
.set('uid', payload.userId)
|
||||||
uid: payload.userId
|
|
||||||
}
|
|
||||||
case AuthorizeActionType.UPDATE_PASSWORD:
|
case AuthorizeActionType.UPDATE_PASSWORD:
|
||||||
return{
|
return state
|
||||||
...state,
|
.set('updatePassword', payload.updatePassword)
|
||||||
updatePassword: payload.updatePassword
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
return state
|
return state
|
||||||
|
|
||||||
|
|||||||
@@ -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 = {
|
export const authorizeSelector = {
|
||||||
getCurrentUser
|
getCurrentUser
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Circle, UserTie } from 'src/core/domain/circles'
|
import { Circle, UserTie } from 'src/core/domain/circles'
|
||||||
|
import {Map} from 'immutable'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Circle state
|
* Circle state
|
||||||
@@ -12,19 +13,19 @@ export class CircleState {
|
|||||||
*
|
*
|
||||||
* @memberof CircleState
|
* @memberof CircleState
|
||||||
*/
|
*/
|
||||||
userTies: { [userId: string]: UserTie } = {}
|
userTies: Map<string, UserTie> = Map({})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The list of users belong to users circle
|
* The list of users belong to users circle
|
||||||
*
|
*
|
||||||
* @memberof CircleState
|
* @memberof CircleState
|
||||||
*/
|
*/
|
||||||
userTieds: { [userId: string]: UserTie } = {}
|
userTieds: Map<string, UserTie> = Map({})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The list of circle of current user
|
* 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
|
* Whether select circle box is open for the selected user
|
||||||
@@ -39,7 +40,7 @@ export class CircleState {
|
|||||||
/**
|
/**
|
||||||
* Keep selected circles for refere user
|
* 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
|
* Whether the select circles box for referer user is open
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// - Import react components
|
// - Import react components
|
||||||
import moment from 'moment/moment'
|
import moment from 'moment/moment'
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
|
import { Map, List } from 'immutable'
|
||||||
|
|
||||||
// - Import domain
|
// - Import domain
|
||||||
import { User } from 'src/core/domain/users'
|
import { User } from 'src/core/domain/users'
|
||||||
@@ -12,245 +13,120 @@ import { CircleActionType } from 'constants/circleActionType'
|
|||||||
import { CircleState } from './CircleState'
|
import { CircleState } from './CircleState'
|
||||||
import { ICircleAction } from './ICircleAction'
|
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
|
* Circle reducer
|
||||||
* @param state
|
* @param state
|
||||||
* @param action
|
* @param action
|
||||||
*/
|
*/
|
||||||
export let circleReducer = (state: CircleState = new CircleState(), action: ICircleAction) => {
|
export let circleReducer = (state = Map(new CircleState()), action: ICircleAction) => {
|
||||||
const { payload } = action
|
const { payload } = action
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case CircleActionType.CLEAR_ALL_CIRCLES:
|
case CircleActionType.CLEAR_ALL_CIRCLES:
|
||||||
return new CircleState()
|
return Map(new CircleState())
|
||||||
|
|
||||||
case CircleActionType.ADD_CIRCLE:
|
case CircleActionType.ADD_CIRCLE: return addCircle(state, payload)
|
||||||
return {
|
case CircleActionType.UPDATE_CIRCLE: return updateCircle(state, payload)
|
||||||
...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.DELETE_CIRCLE:
|
case CircleActionType.DELETE_CIRCLE:
|
||||||
let filteredDeleteCircles = {}
|
return state
|
||||||
Object.keys(state.circleList).map((key) => {
|
.deleteIn(['circleList', payload.circleId])
|
||||||
if (key !== payload.circleId) {
|
|
||||||
return _.merge(filteredDeleteCircles, { [key]: { ...state.circleList![key] } })
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
circleList: {
|
|
||||||
...state.circleList,
|
|
||||||
...filteredDeleteCircles
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case CircleActionType.ADD_LIST_CIRCLE:
|
case CircleActionType.ADD_LIST_CIRCLE:
|
||||||
return {
|
return state
|
||||||
...state,
|
.set('loaded', true)
|
||||||
circleList: {
|
.mergeIn(['circleList'], payload.circleList)
|
||||||
...state.circleList,
|
|
||||||
...payload.circleList
|
|
||||||
},
|
|
||||||
loaded: true
|
|
||||||
}
|
|
||||||
|
|
||||||
case CircleActionType.ADD_FOLLOWING_USER:
|
case CircleActionType.ADD_FOLLOWING_USER:
|
||||||
return {
|
const userTie: Map<string, any> = payload.userTie
|
||||||
...state,
|
return state
|
||||||
userTies: {
|
.setIn(['userTies', userTie.get('userId')], payload.userTie)
|
||||||
...state.userTies,
|
.setIn(['selectedCircles', userTie.get('userId')], userTie.get('circleIdList'))
|
||||||
[payload.userTie.userId]: {
|
|
||||||
...payload.userTie
|
|
||||||
}
|
|
||||||
},
|
|
||||||
selectedCircles: {
|
|
||||||
...state.selectedCircles,
|
|
||||||
[payload.userTie.userId]: payload.userTie.circleIdList
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case CircleActionType.UPDATE_USER_TIE:
|
case CircleActionType.UPDATE_USER_TIE:
|
||||||
return {
|
return state
|
||||||
...state,
|
.setIn(['userTies', payload.userTie.user.userId], payload.userTie)
|
||||||
userTies: {
|
|
||||||
...state.userTies,
|
|
||||||
[payload.userTie.user.userId]: {
|
|
||||||
...payload.userTie
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case CircleActionType.ADD_USER_TIE_LIST:
|
case CircleActionType.ADD_USER_TIE_LIST:
|
||||||
return {
|
return state
|
||||||
...state,
|
.mergeIn(['userTies'], payload.userTies)
|
||||||
userTies: {
|
.set('selectedCircles', getSelectedCircles(payload.userTies))
|
||||||
...state.userTies,
|
|
||||||
...payload.userTies
|
|
||||||
},
|
|
||||||
selectedCircles : getSelectedCircles(payload.userTies)
|
|
||||||
}
|
|
||||||
|
|
||||||
case CircleActionType.ADD_USER_TIED_LIST:
|
case CircleActionType.ADD_USER_TIED_LIST:
|
||||||
return {
|
return state
|
||||||
...state,
|
.mergeIn(['userTieds'], payload.userTieds)
|
||||||
userTieds: {
|
|
||||||
...state.userTieds,
|
|
||||||
...payload.userTieds
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case CircleActionType.DELETE_USER_FROM_CIRCLE:
|
case CircleActionType.DELETE_USER_FROM_CIRCLE:
|
||||||
let filteredCircles: string[] = []
|
return state
|
||||||
Object.keys(state.userTies[payload.userId].circleIdList!).forEach((circleId) => {
|
.deleteIn(['userTies', payload.userTie.user.userId, 'circleIdList', payload.circleId])
|
||||||
if (circleId !== payload.circleId) {
|
|
||||||
filteredCircles.push(circleId)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
userTies: {
|
|
||||||
...state.userTies,
|
|
||||||
[payload.userTie.user.userId]: {
|
|
||||||
...payload.userTie,
|
|
||||||
circleIdList: filteredCircles
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case CircleActionType.DELETE_FOLLOWING_USER:
|
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) {
|
* User interface stuffs
|
||||||
return _.merge(filteredUserTies, { [userId]: { ...state.userTies[userId] } })
|
*/
|
||||||
}
|
|
||||||
})
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
userTies: {
|
|
||||||
...filteredUserTies
|
|
||||||
},
|
|
||||||
selectedCircles : getSelectedCircles(filteredUserTies)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* User interface stuffs
|
|
||||||
*/
|
|
||||||
|
|
||||||
case CircleActionType.CLOSE_CIRCLE_SETTINGS:
|
case CircleActionType.CLOSE_CIRCLE_SETTINGS:
|
||||||
return {
|
return state
|
||||||
...state,
|
.setIn(['openSetting', payload.circleId], false)
|
||||||
openSetting: {
|
|
||||||
...state.openSetting,
|
|
||||||
[payload.circleId]: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case CircleActionType.OPEN_CIRCLE_SETTINGS:
|
case CircleActionType.OPEN_CIRCLE_SETTINGS:
|
||||||
return {
|
return state
|
||||||
...state,
|
.setIn(['openSetting', payload.circleId], true)
|
||||||
openSetting: {
|
|
||||||
...state.openSetting,
|
|
||||||
[payload.circleId]: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case CircleActionType.SHOW_SELECT_CIRCLE_BOX:
|
case CircleActionType.SHOW_SELECT_CIRCLE_BOX:
|
||||||
return {
|
return state
|
||||||
...state,
|
.setIn(['selectCircleStatus', payload.userId], true)
|
||||||
selectCircleStatus: {
|
|
||||||
...state.selectCircleStatus,
|
|
||||||
[payload.userId]: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case CircleActionType.HIDE_SELECT_CIRCLE_BOX:
|
case CircleActionType.HIDE_SELECT_CIRCLE_BOX:
|
||||||
return {
|
return state
|
||||||
...state,
|
.setIn(['selectCircleStatus', payload.userId], false)
|
||||||
selectCircleStatus: {
|
|
||||||
...state.selectCircleStatus,
|
|
||||||
[payload.userId]: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case CircleActionType.SHOW_FOLLOWING_USER_LOADING:
|
case CircleActionType.SHOW_FOLLOWING_USER_LOADING:
|
||||||
return {
|
return state
|
||||||
...state,
|
.setIn(['followingLoadingStatus', payload.userId], true)
|
||||||
followingLoadingStatus: {
|
|
||||||
...state.followingLoadingStatus,
|
|
||||||
[payload.userId]: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case CircleActionType.HIDE_FOLLOWING_USER_LOADING:
|
case CircleActionType.HIDE_FOLLOWING_USER_LOADING:
|
||||||
return {
|
return state
|
||||||
...state,
|
.setIn(['followingLoadingStatus', payload.userId], false)
|
||||||
followingLoadingStatus: {
|
|
||||||
...state.followingLoadingStatus,
|
|
||||||
[payload.userId]: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* User box component
|
|
||||||
*/
|
|
||||||
case CircleActionType.SET_SELECTED_CIRCLES_USER_BOX_COMPONENT:
|
case CircleActionType.SET_SELECTED_CIRCLES_USER_BOX_COMPONENT:
|
||||||
return {
|
return state
|
||||||
...state,
|
.setIn(['selectedCircles', payload.userId], payload.circleList)
|
||||||
selectedCircles: {
|
|
||||||
...state.selectedCircles,
|
|
||||||
[payload.userId]: payload.circleList
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* User box component
|
|
||||||
*/
|
|
||||||
case CircleActionType.REMOVE_SELECTED_CIRCLES_USER_BOX_COMPONENT:
|
case CircleActionType.REMOVE_SELECTED_CIRCLES_USER_BOX_COMPONENT:
|
||||||
return {
|
return state
|
||||||
...state,
|
.setIn(['selectedCircles', payload.userId], [])
|
||||||
selectedCircles: {
|
|
||||||
...state.selectedCircles,
|
|
||||||
[payload.userId]: []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* User box component
|
|
||||||
*/
|
|
||||||
case CircleActionType.OPEN_SELECT_CIRCLES_USER_BOX_COMPONENT:
|
case CircleActionType.OPEN_SELECT_CIRCLES_USER_BOX_COMPONENT:
|
||||||
return {
|
return state
|
||||||
...state,
|
.setIn(['openSelecteCircles', payload.userId], true)
|
||||||
openSelecteCircles: {
|
|
||||||
...state.openSelecteCircles,
|
|
||||||
[payload.userId]: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case CircleActionType.CLOSE_SELECT_CIRCLES_USER_BOX_COMPONENT:
|
case CircleActionType.CLOSE_SELECT_CIRCLES_USER_BOX_COMPONENT:
|
||||||
return {
|
return state
|
||||||
...state,
|
.setIn(['openSelecteCircles', payload.userId], false)
|
||||||
openSelecteCircles: {
|
|
||||||
...state.openSelecteCircles,
|
|
||||||
[payload.userId]: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
return state
|
return state
|
||||||
|
|
||||||
@@ -260,14 +136,11 @@ export let circleReducer = (state: CircleState = new CircleState(), action: ICir
|
|||||||
/**
|
/**
|
||||||
* Map user ties selected to selected circles
|
* Map user ties selected to selected circles
|
||||||
*/
|
*/
|
||||||
const getSelectedCircles = (userTies: {[userId: string]: UserTie }) => {
|
const getSelectedCircles = (userTies: { [userId: string]: UserTie }) => {
|
||||||
let selectedCircles: {[userId: string]: string[]} = {}
|
let selectedCircles: Map<string, List<string>> = Map({})
|
||||||
Object.keys(userTies).forEach((userId: string) => {
|
Object.keys(userTies).forEach((userId: string) => {
|
||||||
const userTie = (userTies as {[userId: string]: UserTie })[userId]
|
const userTie = (userTies as { [userId: string]: UserTie })[userId]
|
||||||
selectedCircles = {
|
selectedCircles = selectedCircles.set(userTie.userId!, List(userTie.circleIdList!))
|
||||||
...selectedCircles,
|
|
||||||
[userTie.userId!]: userTie.circleIdList!
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return selectedCircles
|
return selectedCircles
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
import { Comment } from 'src/core/domain/comments'
|
import { Comment } from 'src/core/domain/comments'
|
||||||
|
import {Map} from 'immutable'
|
||||||
/**
|
/**
|
||||||
* Comment state
|
* Comment state
|
||||||
*
|
*
|
||||||
@@ -11,22 +11,16 @@ export class CommentState {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The list of comments on the posts
|
* 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
|
* 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}
|
* If the comments are loaded {true} or not {false}
|
||||||
*
|
|
||||||
* @type {Boolean}
|
|
||||||
* @memberof CommentState
|
|
||||||
*/
|
*/
|
||||||
loaded: Boolean = false
|
loaded: Boolean = false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// - Import react components
|
// - Import react components
|
||||||
import moment from 'moment/moment'
|
import moment from 'moment/moment'
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
|
import { Map } from 'immutable'
|
||||||
|
|
||||||
// - Import domain
|
// - Import domain
|
||||||
import { User } from 'src/core/domain/users'
|
import { User } from 'src/core/domain/users'
|
||||||
@@ -17,96 +18,38 @@ import { ICommentAction } from './ICommentAction'
|
|||||||
* @param state
|
* @param state
|
||||||
* @param action
|
* @param action
|
||||||
*/
|
*/
|
||||||
export let commentReducer = (state: CommentState = new CommentState(), action: ICommentAction) => {
|
export let commentReducer = (state = Map(new CommentState()), action: ICommentAction) => {
|
||||||
let { payload } = action
|
let { payload } = action
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
|
|
||||||
/* _____________ CRUD _____________ */
|
/* _____________ CRUD _____________ */
|
||||||
case CommentActionType.ADD_COMMENT:
|
case CommentActionType.ADD_COMMENT:
|
||||||
return {
|
return state
|
||||||
...state,
|
.setIn(['postComments', payload.postId, payload.id], payload)
|
||||||
postComments: {
|
|
||||||
...state.postComments,
|
|
||||||
[payload.postId]: {
|
|
||||||
...state.postComments![payload.postId],
|
|
||||||
[payload.id]: {
|
|
||||||
...payload,
|
|
||||||
editorStatus: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case CommentActionType.ADD_COMMENT_LIST:
|
case CommentActionType.ADD_COMMENT_LIST:
|
||||||
return {
|
return state
|
||||||
...state,
|
.mergeIn(['postComments'], payload)
|
||||||
postComments: {
|
.set('loaded', true)
|
||||||
...state.postComments,
|
|
||||||
...payload
|
case CommentActionType.UPDATE_COMMENT:
|
||||||
},
|
const { comment } = payload
|
||||||
loaded: true
|
return state
|
||||||
}
|
.updateIn(['postComments', comment.postId, comment.id, 'text'], (text: string) => comment.text)
|
||||||
case CommentActionType.UPDATE_COMMENT:
|
|
||||||
const {comment} = payload
|
case CommentActionType.DELETE_COMMENT:
|
||||||
return {
|
return state.deleteIn(['postComments', payload.postId, payload.id])
|
||||||
...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,
|
|
||||||
postComments: {
|
|
||||||
...state.postComments,
|
|
||||||
[payload.postId]: {
|
|
||||||
...parsedComments
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case CommentActionType.CLOSE_COMMENT_EDITOR:
|
case CommentActionType.CLOSE_COMMENT_EDITOR:
|
||||||
return {
|
return state
|
||||||
...state,
|
.setIn(['editorStatus', payload.postId, payload.id], false)
|
||||||
editorStatus: {
|
|
||||||
...state.editorStatus,
|
|
||||||
[payload.postId]: {
|
|
||||||
...state.editorStatus![payload.postId],
|
|
||||||
[payload.id]: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case CommentActionType.OPEN_COMMENT_EDITOR:
|
case CommentActionType.OPEN_COMMENT_EDITOR:
|
||||||
return {
|
return state
|
||||||
...state,
|
.setIn(['editorStatus', payload.postId, payload.id], true)
|
||||||
editorStatus: {
|
|
||||||
...state.editorStatus,
|
|
||||||
[payload.postId]: {
|
|
||||||
...state.editorStatus![payload.postId],
|
|
||||||
[payload.id]: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case CommentActionType.CLEAR_ALL_DATA_COMMENT:
|
case CommentActionType.CLEAR_ALL_DATA_COMMENT:
|
||||||
return new CommentState()
|
return Map(new CommentState())
|
||||||
default:
|
default:
|
||||||
return state
|
return state
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { Map, fromJS, List } from 'immutable'
|
||||||
/**
|
/**
|
||||||
* Global state
|
* Global state
|
||||||
*
|
*
|
||||||
@@ -15,13 +16,10 @@ export class GlobalState {
|
|||||||
* }}
|
* }}
|
||||||
* @memberof IGlobalState
|
* @memberof IGlobalState
|
||||||
*/
|
*/
|
||||||
progress: {
|
progress = Map({
|
||||||
percent: number
|
|
||||||
visible: boolean
|
|
||||||
} = {
|
|
||||||
percent: 0,
|
percent: 0,
|
||||||
visible: false
|
visible: false
|
||||||
}
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If loading is enabled {true} or not false
|
* If loading is enabled {true} or not false
|
||||||
@@ -122,7 +120,7 @@ export class GlobalState {
|
|||||||
* @type {*}
|
* @type {*}
|
||||||
* @memberof IGlobalState
|
* @memberof IGlobalState
|
||||||
*/
|
*/
|
||||||
temp: any = {
|
temp: any = Map({
|
||||||
caller: []
|
caller: List()
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,112 +3,86 @@ import { GlobalActionType } from 'constants/globalActionType'
|
|||||||
|
|
||||||
import { GlobalState } from './GlobalState'
|
import { GlobalState } from './GlobalState'
|
||||||
import { IGlobalAction } from './IGlobalAction'
|
import { IGlobalAction } from './IGlobalAction'
|
||||||
|
import { Map, fromJS } from 'immutable'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Global reducer
|
* Global reducer
|
||||||
* @param {object} state
|
* @param {object} state
|
||||||
* @param {object} action
|
* @param {object} action
|
||||||
*/
|
*/
|
||||||
export const globalReducer = (state: GlobalState = new GlobalState(), action: IGlobalAction) => {
|
export const globalReducer = (state = Map(new GlobalState()), action: IGlobalAction) => {
|
||||||
const { payload } = action
|
const { payload } = action
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case GlobalActionType.PROGRESS_CHANGE:
|
case GlobalActionType.PROGRESS_CHANGE:
|
||||||
return {
|
return state
|
||||||
...state,
|
.setIn(['progress', 'percent'], payload.percent)
|
||||||
progress: {
|
.setIn(['progress', 'visible'], payload.visible)
|
||||||
...state.progress,
|
|
||||||
percent: payload.percent,
|
|
||||||
visible: payload.visible
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case GlobalActionType.DEFAULT_DATA_DISABLE:
|
case GlobalActionType.DEFAULT_DATA_DISABLE:
|
||||||
return {
|
return state
|
||||||
...state,
|
.set('defaultLoadDataStatus', false)
|
||||||
defaultLoadDataStatus: false
|
|
||||||
}
|
|
||||||
case GlobalActionType.DEFAULT_DATA_ENABLE:
|
case GlobalActionType.DEFAULT_DATA_ENABLE:
|
||||||
return {
|
return state
|
||||||
...state,
|
.set('defaultLoadDataStatus', true)
|
||||||
defaultLoadDataStatus: true
|
|
||||||
}
|
|
||||||
case GlobalActionType.SHOW_MESSAGE_GLOBAL:
|
case GlobalActionType.SHOW_MESSAGE_GLOBAL:
|
||||||
return {
|
return state
|
||||||
...state,
|
.set('message', action.payload)
|
||||||
message: action.payload,
|
.set('messageOpen', true)
|
||||||
messageOpen: true
|
|
||||||
}
|
|
||||||
case GlobalActionType.SHOW_NORMAL_MESSAGE_GLOBAL:
|
case GlobalActionType.SHOW_NORMAL_MESSAGE_GLOBAL:
|
||||||
return {
|
return state
|
||||||
...state,
|
.set('message', action.payload)
|
||||||
message: action.payload,
|
.set('messageOpen', true)
|
||||||
messageOpen: true
|
|
||||||
}
|
|
||||||
case GlobalActionType.HIDE_MESSAGE_GLOBAL:
|
case GlobalActionType.HIDE_MESSAGE_GLOBAL:
|
||||||
return {
|
return state
|
||||||
...state,
|
.set('message', action.payload)
|
||||||
message: '',
|
.set('messageOpen', false)
|
||||||
messageOpen: false,
|
.set('messageColor', '')
|
||||||
messageColor: ''
|
|
||||||
}
|
|
||||||
case GlobalActionType.SET_HEADER_TITLE:
|
case GlobalActionType.SET_HEADER_TITLE:
|
||||||
return {
|
return state
|
||||||
...state,
|
.set('headerTitle', action.payload)
|
||||||
headerTitle: action.payload
|
|
||||||
}
|
|
||||||
case GlobalActionType.SHOW_SEND_FEEDBACK:
|
case GlobalActionType.SHOW_SEND_FEEDBACK:
|
||||||
return {
|
return state
|
||||||
...state,
|
.set('sendFeedbackStatus', true)
|
||||||
sendFeedbackStatus: true
|
|
||||||
}
|
|
||||||
case GlobalActionType.HIDE_SEND_FEEDBACK:
|
case GlobalActionType.HIDE_SEND_FEEDBACK:
|
||||||
return {
|
return state
|
||||||
...state,
|
.set('sendFeedbackStatus', false)
|
||||||
sendFeedbackStatus: false
|
|
||||||
}
|
|
||||||
case GlobalActionType.HIDE_TOP_LOADING:
|
case GlobalActionType.HIDE_TOP_LOADING:
|
||||||
const queueTopLoading = state.topLoadingQueue > 0 ? (state.topLoadingQueue - 1) : 0
|
const queueTopLoading = Number(state.get('topLoadingQueue')) > 0 ? (Number(state.get('topLoadingQueue')) - 1) : 0
|
||||||
return {
|
return state
|
||||||
...state,
|
.set('topLoadingQueue', queueTopLoading)
|
||||||
topLoadingQueue: queueTopLoading,
|
.set('showTopLoading', (queueTopLoading > 0 ? true : false))
|
||||||
showTopLoading: (queueTopLoading > 0 ? true : false)
|
|
||||||
|
|
||||||
}
|
|
||||||
case GlobalActionType.SHOW_TOP_LOADING:
|
case GlobalActionType.SHOW_TOP_LOADING:
|
||||||
return {
|
return state
|
||||||
...state,
|
.set('topLoadingQueue', (Number(state.get('topLoadingQueue')) + 1))
|
||||||
topLoadingQueue: (state.topLoadingQueue + 1),
|
.set('showTopLoading', true)
|
||||||
showTopLoading: true
|
|
||||||
}
|
case GlobalActionType.HIDE_MASTER_LOADING:
|
||||||
case GlobalActionType.HIDE_MASTER_LOADING:
|
const queueMasterLoading = Number(state.get('masterLoadingQueue')) > 0 ? (Number(state.get('masterLoadingQueue')) - 1) : 0
|
||||||
const queueMasterLoading = state.masterLoadingQueue > 0 ? (state.masterLoadingQueue - 1) : 0
|
return state
|
||||||
return {
|
.set('masterLoadingQueue', queueMasterLoading)
|
||||||
...state,
|
.set('showMasterLoading', (queueMasterLoading > 0 ? true : false))
|
||||||
masterLoadingQueue: queueMasterLoading,
|
|
||||||
showMasterLoading: (queueMasterLoading > 0 ? true : false)
|
|
||||||
|
|
||||||
}
|
|
||||||
case GlobalActionType.SHOW_MASTER_LOADING:
|
case GlobalActionType.SHOW_MASTER_LOADING:
|
||||||
return {
|
return state
|
||||||
...state,
|
.set('masterLoadingQueue', Number(state.get('masterLoadingQueue')) + 1)
|
||||||
masterLoadingQueue: (state.masterLoadingQueue + 1),
|
.set('showMasterLoading', true)
|
||||||
showMasterLoading: true
|
|
||||||
}
|
|
||||||
case GlobalActionType.TEMP:
|
case GlobalActionType.TEMP:
|
||||||
return {
|
return state
|
||||||
...state,
|
.mergeIn(['temp', 'caller'], fromJS([payload.caller]))
|
||||||
temp: {
|
|
||||||
...state.temp,
|
case GlobalActionType.CLEAR_ALL_GLOBAL:
|
||||||
caller: [
|
return state
|
||||||
...state.temp.caller,
|
.set('sendFeedbackStatus', false)
|
||||||
payload.caller
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case GlobalActionType.CLEAR_ALL_GLOBAL:
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
sendFeedbackStatus: false,
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return state
|
return state
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Image } from 'src/core/domain/imageGallery'
|
import { Image } from 'src/core/domain/imageGallery'
|
||||||
|
import {Map, Collection, List} from 'immutable'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ImageGallery state
|
* ImageGallery state
|
||||||
@@ -18,49 +19,31 @@ export class ImageGalleryState {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The list of image
|
* The list of image
|
||||||
*
|
|
||||||
* @type {(Image[] | null)}
|
|
||||||
* @memberof ImageGalleryState
|
|
||||||
*/
|
*/
|
||||||
images: Image[] = []
|
images: List<Image> = List()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Selected image name
|
* Selected image name
|
||||||
*
|
|
||||||
* @type {string}
|
|
||||||
* @memberof ImageGalleryState
|
|
||||||
*/
|
*/
|
||||||
selectImage: string = ''
|
selectImage: string = ''
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Selected image address
|
* Selected image address
|
||||||
*
|
|
||||||
* @type {string}
|
|
||||||
* @memberof ImageGalleryState
|
|
||||||
*/
|
*/
|
||||||
selectURL: string = ''
|
selectURL: string = ''
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If image gallery is loaded {true} or not false
|
* If image gallery is loaded {true} or not false
|
||||||
*
|
|
||||||
* @type {Boolean}
|
|
||||||
* @memberof ImageGalleryState
|
|
||||||
*/
|
*/
|
||||||
loaded: Boolean = false
|
loaded: Boolean = false
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Images address list
|
* Images address list
|
||||||
*
|
|
||||||
* @type {*}
|
|
||||||
* @memberof ImageGalleryState
|
|
||||||
*/
|
*/
|
||||||
imageURLList: any = {}
|
imageURLList: any = {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Store image requested
|
* Store image requested
|
||||||
*
|
|
||||||
* @type {*}
|
|
||||||
* @memberof ImageGalleryState
|
|
||||||
*/
|
*/
|
||||||
imageRequests: any = {}
|
imageRequests: any = {}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
// - Import react components
|
// - Import react components
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
|
import { Map, List } from 'immutable'
|
||||||
|
|
||||||
// - Import domain
|
// - Import domain
|
||||||
import { User } from 'src/core/domain/users'
|
import { User } from 'src/core/domain/users'
|
||||||
@@ -14,52 +15,36 @@ import { ImageGalleryState } from './ImageGalleryState'
|
|||||||
/**
|
/**
|
||||||
* Image gallery reducer
|
* Image gallery reducer
|
||||||
*/
|
*/
|
||||||
export let imageGalleryReducer = (state: ImageGalleryState = new ImageGalleryState(), action: IImageGalleryAction) => {
|
export let imageGalleryReducer = (state = Map(new ImageGalleryState()), action: IImageGalleryAction) => {
|
||||||
const { payload } = action
|
const { payload } = action
|
||||||
|
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
/* ----------------- CRUD ----------------- */
|
/* ----------------- CRUD ----------------- */
|
||||||
case ImageGalleryActionType.ADD_IMAGE_GALLERY:
|
case ImageGalleryActionType.ADD_IMAGE_GALLERY:
|
||||||
return {
|
return state
|
||||||
...state,
|
.mergeIn(['images'], List([payload]))
|
||||||
images: [...state.images!, payload]
|
|
||||||
}
|
|
||||||
case ImageGalleryActionType.ADD_IMAGE_LIST_GALLERY:
|
case ImageGalleryActionType.ADD_IMAGE_LIST_GALLERY:
|
||||||
return {
|
return state
|
||||||
...state,
|
.set('images', List(payload))
|
||||||
images: [...payload],
|
.set('loaded', true)
|
||||||
loaded: true
|
|
||||||
}
|
|
||||||
|
|
||||||
case ImageGalleryActionType.DELETE_IMAGE:
|
case ImageGalleryActionType.DELETE_IMAGE:
|
||||||
return {
|
return state
|
||||||
...state,
|
.update('images', (images: List<Image>) => {
|
||||||
images: [
|
return images.filter((image) => image!.id !== payload)
|
||||||
...state.images!.filter((item: Image) => {
|
})
|
||||||
return item.id !== payload
|
|
||||||
})
|
|
||||||
]
|
|
||||||
}
|
|
||||||
case ImageGalleryActionType.SET_IMAGE_URL:
|
case ImageGalleryActionType.SET_IMAGE_URL:
|
||||||
return {
|
return state
|
||||||
...state,
|
.setIn(['imageURLList', payload.name], payload.url)
|
||||||
imageURLList: {
|
|
||||||
...state.imageURLList,
|
|
||||||
[payload.name]: payload.url
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case ImageGalleryActionType.SEND_IMAGE_REQUEST:
|
case ImageGalleryActionType.SEND_IMAGE_REQUEST:
|
||||||
return {
|
return state
|
||||||
...state,
|
.mergeIn(['imageRequests'], payload)
|
||||||
imageRequests: [
|
|
||||||
...state.imageRequests,
|
|
||||||
payload
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
case ImageGalleryActionType.CLEAT_ALL_DATA_IMAGE_GALLERY:
|
case ImageGalleryActionType.CLEAT_ALL_DATA_IMAGE_GALLERY:
|
||||||
return new ImageGalleryState()
|
return Map(new ImageGalleryState())
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return state
|
return state
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Notification } from 'src/core/domain/notifications'
|
import { Notification } from 'src/core/domain/notifications'
|
||||||
|
import {Map} from 'immutable'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notification state
|
* Notification state
|
||||||
@@ -10,17 +11,11 @@ export class NotificationState {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The list of users notification
|
* 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}
|
* If user notifications are loaded {true} or not {false}
|
||||||
*
|
|
||||||
* @type {Boolean}
|
|
||||||
* @memberof NotificationState
|
|
||||||
*/
|
*/
|
||||||
loaded: Boolean = false
|
loaded: Boolean = false
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
// - Import react components
|
// - Import react components
|
||||||
import moment from 'moment/moment'
|
import moment from 'moment/moment'
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
|
import { Map } from 'immutable'
|
||||||
|
|
||||||
// - Import domain
|
// - Import domain
|
||||||
import { Notification } from 'src/core/domain/notifications'
|
import { Notification } from 'src/core/domain/notifications'
|
||||||
@@ -16,7 +17,7 @@ import { INotificationAction } from './INotificationAction'
|
|||||||
* @param {object} state
|
* @param {object} state
|
||||||
* @param {object} action
|
* @param {object} action
|
||||||
*/
|
*/
|
||||||
export let notificationReducer = (state: NotificationState = new NotificationState(), action: INotificationAction) => {
|
export let notificationReducer = (state = Map(new NotificationState()), action: INotificationAction) => {
|
||||||
let { payload } = action
|
let { payload } = action
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
|
|
||||||
@@ -25,44 +26,21 @@ export let notificationReducer = (state: NotificationState = new NotificationSta
|
|||||||
return state
|
return state
|
||||||
|
|
||||||
case NotificationActionType.ADD_NOTIFY_LIST:
|
case NotificationActionType.ADD_NOTIFY_LIST:
|
||||||
return {
|
return state
|
||||||
...state,
|
.set('userNotifies', payload)
|
||||||
userNotifies: {
|
.set('loaded', true)
|
||||||
...payload
|
|
||||||
},
|
|
||||||
loaded: true
|
|
||||||
}
|
|
||||||
|
|
||||||
case NotificationActionType.SEEN_NOTIFY:
|
case NotificationActionType.SEEN_NOTIFY:
|
||||||
return {
|
return state
|
||||||
...state,
|
.setIn(['userNotifies', payload, 'isSeen'], true)
|
||||||
userNotifies: {
|
.set('loaded', true)
|
||||||
...state.userNotifies,
|
|
||||||
[payload]: {
|
|
||||||
...state.userNotifies![payload],
|
|
||||||
isSeen: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
loaded: true
|
|
||||||
}
|
|
||||||
|
|
||||||
case NotificationActionType.DELETE_NOTIFY:
|
case NotificationActionType.DELETE_NOTIFY:
|
||||||
let parsedNotifies = {}
|
return state
|
||||||
Object.keys(state.userNotifies!).map((id) => {
|
.deleteIn(['userNotifies', payload])
|
||||||
if (id !== payload) {
|
|
||||||
_.merge(parsedNotifies, { [id]: { ...state.userNotifies![id] } })
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
userNotifies: {
|
|
||||||
...parsedNotifies
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case NotificationActionType.CLEAR_ALL_DATA_NOTIFY:
|
case NotificationActionType.CLEAR_ALL_DATA_NOTIFY:
|
||||||
return new NotificationState()
|
return Map(new NotificationState())
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return state
|
return state
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Post } from 'src/core/domain/posts'
|
import { Post } from 'src/core/domain/posts'
|
||||||
|
import { Map, fromJS, List } from 'immutable'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Post state
|
* Post state
|
||||||
@@ -14,7 +15,7 @@ export class PostState {
|
|||||||
* @type {*}
|
* @type {*}
|
||||||
* @memberof PostState
|
* @memberof PostState
|
||||||
*/
|
*/
|
||||||
userPosts: any = {}
|
userPosts = Map({})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If user posts are loaded {true} or not {false}
|
* If user posts are loaded {true} or not {false}
|
||||||
@@ -27,12 +28,12 @@ export class PostState {
|
|||||||
/**
|
/**
|
||||||
* Stream data storage
|
* Stream data storage
|
||||||
*/
|
*/
|
||||||
stream?: {hasMoreData: boolean, lastPageRequest: number, lastPostId: string} =
|
stream?: Map<string,any> =
|
||||||
{hasMoreData: true, lastPageRequest: -1, lastPostId: ''}
|
Map({hasMoreData: true, lastPageRequest: -1, lastPostId: ''})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Profile posts data storage
|
* Profile posts data storage
|
||||||
*/
|
*/
|
||||||
profile?: {[userId: string]: {hasMoreData: boolean, lastPageRequest: number, lastPostId: string}} =
|
profile?: Map<string, any> =
|
||||||
{}
|
Map({})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
import moment from 'moment/moment'
|
import moment from 'moment/moment'
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
import { Reducer, Action } from 'redux'
|
import { Reducer, Action } from 'redux'
|
||||||
|
import { Map } from 'immutable'
|
||||||
|
|
||||||
// - Import action types
|
// - Import action types
|
||||||
import { PostActionType } from 'constants/postActionType'
|
import { PostActionType } from 'constants/postActionType'
|
||||||
@@ -11,167 +12,94 @@ import { IPostAction } from './IPostAction'
|
|||||||
import { Post } from 'src/core/domain/posts/post'
|
import { Post } from 'src/core/domain/posts/post'
|
||||||
import CommonAPI from 'src/api/CommonAPI'
|
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
|
* Post reducer
|
||||||
* @param {object} state
|
* @param {object} state
|
||||||
* @param {object} action
|
* @param {object} action
|
||||||
*/
|
*/
|
||||||
export let postReducer = (state: PostState = new PostState(), action: IPostAction) => {
|
export let postReducer = (state = Map(new PostState()), action: IPostAction) => {
|
||||||
const { payload } = action
|
const { payload } = action
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case PostActionType.CLEAR_ALL_DATA_POST:
|
case PostActionType.CLEAR_ALL_DATA_POST:
|
||||||
return new PostState()
|
return Map(new PostState())
|
||||||
|
|
||||||
case PostActionType.ADD_IMAGE_POST:
|
case PostActionType.ADD_IMAGE_POST:
|
||||||
return {
|
return state
|
||||||
...state,
|
.setIn(['userPosts', payload.uid, payload.post.id], Map(payload.post))
|
||||||
userPosts: {
|
|
||||||
...state.userPosts,
|
|
||||||
[payload.uid]: {
|
|
||||||
...state.userPosts[payload.uid],
|
|
||||||
[payload.post.id]: { ...payload.post }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case PostActionType.ADD_POST:
|
case PostActionType.ADD_POST:
|
||||||
return {
|
return state
|
||||||
...state,
|
.setIn(['userPosts', payload.uid, payload.post.id], Map(payload.post))
|
||||||
userPosts: {
|
|
||||||
...state.userPosts,
|
|
||||||
[payload.uid]: {
|
|
||||||
...state.userPosts[payload.uid],
|
|
||||||
[payload.post.id]: { ...payload.post }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case PostActionType.UPDATE_POST:
|
case PostActionType.UPDATE_POST: return updatePost(state, payload)
|
||||||
const post: Post = payload.post
|
case PostActionType.UPDATE_POST_COMMENTS: return updatePostComments(state, payload)
|
||||||
return {
|
case PostActionType.UPDATE_POST_VOTES: return updatePostVotes(state, payload)
|
||||||
...state,
|
|
||||||
userPosts: {
|
|
||||||
...state.userPosts,
|
|
||||||
[post.ownerUserId!]: {
|
|
||||||
...state.userPosts[post.ownerUserId!],
|
|
||||||
[payload.post.id]: {
|
|
||||||
...payload.post,
|
|
||||||
comments: post.comments,
|
|
||||||
votes: post.votes
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case PostActionType.DELETE_POST:
|
case PostActionType.DELETE_POST:
|
||||||
let filteredPosts = {}
|
return state
|
||||||
Object.keys(state.userPosts[payload.uid]).map((key) => {
|
.deleteIn(['userPosts', payload.uid, payload.id])
|
||||||
if (key !== payload.id) {
|
|
||||||
return _.merge(filteredPosts, { [key]: { ...state.userPosts[payload.uid][key] } })
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
userPosts: {
|
|
||||||
...state.userPosts,
|
|
||||||
[payload.uid]: {
|
|
||||||
...filteredPosts
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case PostActionType.ADD_LIST_POST:
|
case PostActionType.ADD_LIST_POST:
|
||||||
const newUserPosts = payload.userPosts as { [userId: string]: { [postId: string]: Post } }
|
return state
|
||||||
const mergedObject = _.merge(state.userPosts, newUserPosts)
|
.mergeDeepIn(['userPosts'], payload.userPosts)
|
||||||
return {
|
.set('loaded', true)
|
||||||
...state,
|
|
||||||
userPosts: {
|
|
||||||
...mergedObject
|
|
||||||
},
|
|
||||||
loaded: true
|
|
||||||
|
|
||||||
}
|
|
||||||
case PostActionType.HAS_MORE_DATA_STREAM:
|
case PostActionType.HAS_MORE_DATA_STREAM:
|
||||||
return {
|
return state
|
||||||
...state,
|
.setIn(['stream', 'hasMoreData'], true)
|
||||||
stream: {
|
|
||||||
...state.stream,
|
|
||||||
hasMoreData: true
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
case PostActionType.NOT_MORE_DATA_STREAM:
|
case PostActionType.NOT_MORE_DATA_STREAM:
|
||||||
return {
|
return state
|
||||||
...state,
|
.setIn(['stream', 'hasMoreData'], false)
|
||||||
stream: {
|
|
||||||
...state.stream,
|
|
||||||
hasMoreData: false
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
case PostActionType.REQUEST_PAGE_STREAM:
|
case PostActionType.REQUEST_PAGE_STREAM:
|
||||||
return {
|
return state
|
||||||
...state,
|
.setIn(['stream', 'lastPageRequest'], payload.page)
|
||||||
stream: {
|
|
||||||
...state.stream,
|
|
||||||
lastPageRequest: payload.page
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case PostActionType.LAST_POST_STREAM:
|
case PostActionType.LAST_POST_STREAM:
|
||||||
return {
|
return state
|
||||||
...state,
|
.setIn(['stream', 'lastPostId'], payload.lastPostId)
|
||||||
stream: {
|
|
||||||
...state.stream,
|
|
||||||
lastPostId: payload.lastPostId
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case PostActionType.HAS_MORE_DATA_PROFILE:
|
case PostActionType.HAS_MORE_DATA_PROFILE:
|
||||||
return {
|
return state
|
||||||
...state,
|
.setIn(['profile', 'hasMoreData'], true)
|
||||||
profile: {
|
|
||||||
...state.profile,
|
|
||||||
hasMoreData: true
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
case PostActionType.NOT_MORE_DATA_PROFILE:
|
case PostActionType.NOT_MORE_DATA_PROFILE:
|
||||||
return {
|
return state
|
||||||
...state,
|
.setIn(['profile', payload.userId, 'hasMoreData'], false)
|
||||||
profile: {
|
|
||||||
...state.profile,
|
|
||||||
[payload.userId]: {
|
|
||||||
...state.profile![payload.userId],
|
|
||||||
hasMoreData: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
case PostActionType.REQUEST_PAGE_PROFILE:
|
case PostActionType.REQUEST_PAGE_PROFILE:
|
||||||
return {
|
return state
|
||||||
...state,
|
.setIn(['profile', payload.userId, 'lastPageRequest'], payload.page)
|
||||||
profile: {
|
|
||||||
...state.profile,
|
|
||||||
[payload.userId]: {
|
|
||||||
...state.profile![payload.userId],
|
|
||||||
lastPageRequest: payload.page
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case PostActionType.LAST_POST_PROFILE:
|
case PostActionType.LAST_POST_PROFILE:
|
||||||
return {
|
return state
|
||||||
...state,
|
.setIn(['profile', payload.userId, 'lastPostId'], payload.lastPostId)
|
||||||
profile: {
|
|
||||||
...state.profile,
|
|
||||||
[payload.userId]: {
|
|
||||||
...state.profile![payload.userId],
|
|
||||||
lastPostId: payload.lastPostId
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
return state
|
return state
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
const getPost = (state: any, userId: string, postId: string) => {
|
import {Map} from 'immutable'
|
||||||
return (state.post.userPosts && state.post.userPosts[userId] && state.post.userPosts[userId][postId])
|
|
||||||
? state.post.userPosts[userId][postId]
|
const getPost = (state: Map<string, any>, userId: string, postId: string) => {
|
||||||
: null
|
return state.getIn(['post', 'userPosts', userId, postId])
|
||||||
}
|
}
|
||||||
|
|
||||||
export const postSelector = {
|
export const postSelector = {
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import * as redux from 'redux'
|
|
||||||
import { localeReducer as locale } from 'react-localize-redux'
|
import { localeReducer as locale } from 'react-localize-redux'
|
||||||
|
import {
|
||||||
|
combineReducers
|
||||||
|
} from 'redux-immutable'
|
||||||
|
|
||||||
// - Import reducers
|
// - Import reducers
|
||||||
import { authorizeReducer } from './authorize'
|
import { authorizeReducer } from './authorize'
|
||||||
@@ -15,7 +17,7 @@ import { serverReducer } from './server'
|
|||||||
import { routerReducer, routerMiddleware } from 'react-router-redux'
|
import { routerReducer, routerMiddleware } from 'react-router-redux'
|
||||||
|
|
||||||
// - Reducers
|
// - Reducers
|
||||||
export const rootReducer = redux.combineReducers({
|
export const rootReducer = combineReducers({
|
||||||
locale,
|
locale,
|
||||||
imageGallery: imageGalleryReducer,
|
imageGallery: imageGalleryReducer,
|
||||||
post: postReducer,
|
post: postReducer,
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { ServerRequestModel } from 'src/models/server'
|
import { ServerRequestModel } from 'src/models/server'
|
||||||
|
import {Map} from 'immutable'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Server state
|
* Server state
|
||||||
@@ -12,5 +13,5 @@ export class ServerState {
|
|||||||
* The list of posts server
|
* The list of posts server
|
||||||
* @memberof ServerState
|
* @memberof ServerState
|
||||||
*/
|
*/
|
||||||
request: {[requestId: string]: ServerRequestModel} | null = {}
|
request: Map<string, ServerRequestModel> = Map({})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
// - Import react components
|
// - Import react components
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
|
import { Map } from 'immutable'
|
||||||
|
|
||||||
// - Import action types
|
// - Import action types
|
||||||
import { ServerActionType } from 'constants/serverActionType'
|
import { ServerActionType } from 'constants/serverActionType'
|
||||||
@@ -16,61 +17,30 @@ import { ServerRequestStatusType } from 'store/actions/serverRequestStatusType'
|
|||||||
* @param {object} state
|
* @param {object} state
|
||||||
* @param {object} action
|
* @param {object} action
|
||||||
*/
|
*/
|
||||||
export let serverReducer = (state: ServerState = new ServerState(), action: IServerAction) => {
|
export let serverReducer = (state = Map(new ServerState()), action: IServerAction) => {
|
||||||
let { payload } = action
|
let { payload } = action
|
||||||
const request = (payload ? payload.request : {}) as ServerRequestModel
|
const request = (payload ? payload.request : {}) as ServerRequestModel
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
|
|
||||||
/* _____________ CRUD _____________ */
|
/* _____________ CRUD _____________ */
|
||||||
case ServerActionType.ADD_REQUEST:
|
case ServerActionType.ADD_REQUEST:
|
||||||
return {
|
return state
|
||||||
...state,
|
.setIn(['request', request.id], request)
|
||||||
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] } })
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
case ServerActionType.DELETE_REQUEST:
|
||||||
return {
|
return state
|
||||||
...state,
|
.deleteIn(['request', request.id])
|
||||||
request: parsedRequests
|
|
||||||
}
|
|
||||||
|
|
||||||
case ServerActionType.ERROR_REQUEST:
|
case ServerActionType.ERROR_REQUEST:
|
||||||
return {
|
return state
|
||||||
...state,
|
.setIn(['request', request.id, 'status'], ServerRequestStatusType.Error)
|
||||||
request: {
|
|
||||||
...state.request,
|
|
||||||
[request.id]: {
|
|
||||||
...state.request![request.id],
|
|
||||||
status: ServerRequestStatusType.Error
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case ServerActionType.OK_REQUEST:
|
case ServerActionType.OK_REQUEST:
|
||||||
return {
|
return state
|
||||||
...state,
|
.setIn(['request', request.id, 'status'], ServerRequestStatusType.OK)
|
||||||
request: {
|
|
||||||
...state.request,
|
|
||||||
[request.id]: {
|
|
||||||
...state.request![request.id],
|
|
||||||
status: ServerRequestStatusType.OK
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case ServerActionType.CLEAR_ALL_DATA_REQUEST:
|
case ServerActionType.CLEAR_ALL_DATA_REQUEST:
|
||||||
return new ServerState()
|
return Map(new ServerState())
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return state
|
return state
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { User,Profile } from 'src/core/domain/users'
|
import { User,Profile } from 'src/core/domain/users'
|
||||||
|
import { Map, fromJS, List } from 'immutable'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User state
|
* User state
|
||||||
@@ -9,31 +10,21 @@ import { User,Profile } from 'src/core/domain/users'
|
|||||||
export class UserState {
|
export class UserState {
|
||||||
/**
|
/**
|
||||||
* The list of users information
|
* 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
|
* If users profile are loaded
|
||||||
*
|
|
||||||
* @type {Boolean}
|
|
||||||
* @memberof UserState
|
|
||||||
*/
|
*/
|
||||||
loaded: Boolean = false
|
loaded: Boolean = false
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If edit profile is open {true} or not {false}
|
* If edit profile is open {true} or not {false}
|
||||||
*
|
|
||||||
* @type {Boolean}
|
|
||||||
* @memberof UserState
|
|
||||||
*/
|
*/
|
||||||
openEditProfile: Boolean = false
|
openEditProfile: Boolean = false
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* People data storage
|
* People data storage
|
||||||
*/
|
*/
|
||||||
people?: {hasMoreData: boolean, lastPageRequest: number, lastUserId: string} =
|
people?: Map<string, any> = Map({hasMoreData: true, lastPageRequest: -1, lastUserId: ''})
|
||||||
{hasMoreData: true, lastPageRequest: -1, lastUserId: ''}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
// - Import action types
|
// - Import action types
|
||||||
import { UserActionType } from 'constants/userActionType'
|
import { UserActionType } from 'constants/userActionType'
|
||||||
|
import { Map } from 'immutable'
|
||||||
|
|
||||||
// - Import domain
|
// - Import domain
|
||||||
import { User,Profile } from 'src/core/domain/users'
|
import { User, Profile } from 'src/core/domain/users'
|
||||||
|
|
||||||
import { UserState } from './UserState'
|
import { UserState } from './UserState'
|
||||||
import { IUserAction } from './IUserAction'
|
import { IUserAction } from './IUserAction'
|
||||||
@@ -10,101 +11,52 @@ import { IUserAction } from './IUserAction'
|
|||||||
/**
|
/**
|
||||||
* User reducer
|
* User reducer
|
||||||
*/
|
*/
|
||||||
export let userReducer = (state: UserState = new UserState(), action: IUserAction) => {
|
export let userReducer = (state = Map(new UserState()), action: IUserAction) => {
|
||||||
const { payload } = action
|
const { payload } = action
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case UserActionType.USER_INFO:
|
case UserActionType.USER_INFO:
|
||||||
return {
|
return state
|
||||||
...state,
|
.setIn(['info', payload.uid], payload.info)
|
||||||
info: {
|
|
||||||
...state.info,
|
|
||||||
[payload.uid]: {
|
|
||||||
...payload.info
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case UserActionType.ADD_USER_INFO:
|
case UserActionType.ADD_USER_INFO:
|
||||||
return {
|
return state
|
||||||
...state,
|
.setIn(['info', payload.uid], payload.info)
|
||||||
info: {
|
.set('loaded', true)
|
||||||
...state.info,
|
|
||||||
[payload.uid]: {
|
|
||||||
...payload.info
|
|
||||||
}
|
|
||||||
},
|
|
||||||
loaded: true
|
|
||||||
}
|
|
||||||
case UserActionType.ADD_PEOPLE_INFO:
|
case UserActionType.ADD_PEOPLE_INFO:
|
||||||
return {
|
return state
|
||||||
...state,
|
.mergeIn(['info'], payload)
|
||||||
info: {
|
|
||||||
...state.info,
|
|
||||||
...payload
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case UserActionType.UPDATE_USER_INFO:
|
case UserActionType.UPDATE_USER_INFO:
|
||||||
return {
|
return state
|
||||||
...state,
|
.mergeIn(['info', payload.uid], payload.info)
|
||||||
info: {
|
|
||||||
...state.info,
|
|
||||||
[payload.uid]: {
|
|
||||||
...state.info![payload.uid],
|
|
||||||
...payload.info
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case UserActionType.CLEAR_ALL_DATA_USER:
|
case UserActionType.CLEAR_ALL_DATA_USER:
|
||||||
return new UserState()
|
return Map(new UserState())
|
||||||
|
|
||||||
case UserActionType.CLOSE_EDIT_PROFILE:
|
case UserActionType.CLOSE_EDIT_PROFILE:
|
||||||
return {
|
return state
|
||||||
...state,
|
.set('openEditProfile', false)
|
||||||
openEditProfile: false
|
|
||||||
}
|
|
||||||
|
|
||||||
case UserActionType.OPEN_EDIT_PROFILE:
|
case UserActionType.OPEN_EDIT_PROFILE:
|
||||||
return {
|
return state
|
||||||
...state,
|
.set('openEditProfile', true)
|
||||||
openEditProfile: true
|
|
||||||
}
|
case UserActionType.HAS_MORE_DATA_PEOPLE:
|
||||||
case UserActionType.HAS_MORE_DATA_PEOPLE:
|
return state
|
||||||
return {
|
.setIn(['people', 'hasMoreData'], true)
|
||||||
...state,
|
|
||||||
people: {
|
|
||||||
...state.people,
|
|
||||||
hasMoreData: true
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
case UserActionType.NOT_MORE_DATA_PEOPLE:
|
case UserActionType.NOT_MORE_DATA_PEOPLE:
|
||||||
return {
|
return state
|
||||||
...state,
|
.setIn(['people', 'hasMoreData'], false)
|
||||||
people: {
|
|
||||||
...state.people,
|
|
||||||
hasMoreData: false
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
case UserActionType.REQUEST_PAGE_PEOPLE:
|
case UserActionType.REQUEST_PAGE_PEOPLE:
|
||||||
return {
|
return state
|
||||||
...state,
|
.setIn(['people', 'lastPageRequest'], payload.page)
|
||||||
people: {
|
|
||||||
...state.people,
|
|
||||||
lastPageRequest: payload.page
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case UserActionType.LAST_USER_PEOPLE:
|
case UserActionType.LAST_USER_PEOPLE:
|
||||||
return {
|
return state
|
||||||
...state,
|
.setIn(['people', 'lastUserId'], payload.lastUserId)
|
||||||
people: {
|
|
||||||
...state.people,
|
|
||||||
lastUserId: payload.lastUserId
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return state
|
return state
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// - Import react components
|
// - Import react components
|
||||||
import moment from 'moment/moment'
|
import moment from 'moment/moment'
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
|
import { Map } from 'immutable'
|
||||||
|
|
||||||
// - Import action types
|
// - Import action types
|
||||||
import { VoteActionType } from 'constants/voteActionType'
|
import { VoteActionType } from 'constants/voteActionType'
|
||||||
@@ -16,56 +17,26 @@ import { IVoteAction } from './IVoteAction'
|
|||||||
* @param {object} state
|
* @param {object} state
|
||||||
* @param {object} action
|
* @param {object} action
|
||||||
*/
|
*/
|
||||||
export let voteReducer = (state: VoteState = new VoteState(), action: IVoteAction) => {
|
export let voteReducer = (state = Map(new VoteState()), action: IVoteAction) => {
|
||||||
let { payload } = action
|
let { payload } = action
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
|
|
||||||
/* _____________ CRUD _____________ */
|
/* _____________ CRUD _____________ */
|
||||||
case VoteActionType.ADD_VOTE:
|
case VoteActionType.ADD_VOTE:
|
||||||
return {
|
return state
|
||||||
...state,
|
.setIn(['postVotes', payload.postId, payload.userId], payload)
|
||||||
postVotes: {
|
|
||||||
...state.postVotes,
|
|
||||||
[payload.postId]: {
|
|
||||||
...state.postVotes![payload.postId],
|
|
||||||
[payload.userId]: {
|
|
||||||
...payload
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case VoteActionType.ADD_VOTE_LIST:
|
case VoteActionType.ADD_VOTE_LIST:
|
||||||
return {
|
return state
|
||||||
...state,
|
.set('postVotes', payload)
|
||||||
postVotes: {
|
.set('loaded', true)
|
||||||
...payload
|
|
||||||
},
|
|
||||||
loaded: true
|
|
||||||
}
|
|
||||||
|
|
||||||
case VoteActionType.DELETE_VOTE:
|
case VoteActionType.DELETE_VOTE:
|
||||||
let parsedVotes = {}
|
return state
|
||||||
if (state.postVotes![payload.postId]) {
|
.deleteIn(['postVotes', payload.postId, payload.userId])
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case VoteActionType.CLEAR_ALL_DATA_VOTE:
|
case VoteActionType.CLEAR_ALL_DATA_VOTE:
|
||||||
return new VoteState()
|
return Map(new VoteState())
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return state
|
return state
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import { eventChannel, Channel } from 'redux-saga'
|
|||||||
import { ServerRequestStatusType } from 'store/actions/serverRequestStatusType'
|
import { ServerRequestStatusType } from 'store/actions/serverRequestStatusType'
|
||||||
import { Post } from 'core/domain/posts'
|
import { Post } from 'core/domain/posts'
|
||||||
import { postSelector } from 'store/reducers/posts/postSelector'
|
import { postSelector } from 'store/reducers/posts/postSelector'
|
||||||
|
import {Map} from 'immutable'
|
||||||
/**
|
/**
|
||||||
* Get service providers
|
* Get service providers
|
||||||
*/
|
*/
|
||||||
@@ -40,15 +41,15 @@ function* setComments(ownerId: string, postId: string, comments: postComments) {
|
|||||||
*/
|
*/
|
||||||
yield put(commentActions.addCommentList(comments))
|
yield put(commentActions.addCommentList(comments))
|
||||||
let commentsCount: number
|
let commentsCount: number
|
||||||
const post: Post = yield select(postSelector.getPost, ownerId, postId)
|
const post: Map<string, any> = yield select(postSelector.getPost, ownerId, postId)
|
||||||
if (post) {
|
if (post) {
|
||||||
const desiredComments = comments[postId]
|
const desiredComments = comments[postId]
|
||||||
if (desiredComments) {
|
if (desiredComments) {
|
||||||
commentsCount = Object.keys(desiredComments).length
|
commentsCount = Object.keys(desiredComments).length
|
||||||
let sortedObjects = yield CommentAPI.sortCommentsByDate(desiredComments)
|
let sortedObjects = yield CommentAPI.sortCommentsByDate(desiredComments)
|
||||||
post.comments = sortedObjects
|
const updatedPost = post.set('comments', Map(sortedObjects))
|
||||||
post.commentCounter = commentsCount
|
.set('commentCounter', commentsCount)
|
||||||
yield put(postActions.updatePost(post))
|
yield put(postActions.updatePost(updatedPost))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -72,10 +73,8 @@ function* dbFetchComments(ownerId: string, postId: string) {
|
|||||||
yield call(setComments, ownerId, postId, comments)
|
yield call(setComments, ownerId, postId, comments)
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
console.trace('FiNALLY')
|
|
||||||
if (yield cancelled()) {
|
if (yield cancelled()) {
|
||||||
channelSubscription.close()
|
channelSubscription.close()
|
||||||
console.trace('comments cancelled')
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
1
src/typings/react-loadable.d.ts
vendored
Normal file
1
src/typings/react-loadable.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
declare module 'react-loadable'
|
||||||
63
yarn.lock
63
yarn.lock
@@ -141,6 +141,12 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@types/react" "*"
|
"@types/react" "*"
|
||||||
|
|
||||||
|
"@types/react-helmet@^5.0.5":
|
||||||
|
version "5.0.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/react-helmet/-/react-helmet-5.0.5.tgz#30a12b0431732a20882f0fa9b75bf56ff91700d3"
|
||||||
|
dependencies:
|
||||||
|
"@types/react" "*"
|
||||||
|
|
||||||
"@types/react-infinite-scroller@^1.0.4":
|
"@types/react-infinite-scroller@^1.0.4":
|
||||||
version "1.0.6"
|
version "1.0.6"
|
||||||
resolved "https://registry.yarnpkg.com/@types/react-infinite-scroller/-/react-infinite-scroller-1.0.6.tgz#ab36d95ce25712b70ccff439f2a3204bb15476d9"
|
resolved "https://registry.yarnpkg.com/@types/react-infinite-scroller/-/react-infinite-scroller-1.0.6.tgz#ab36d95ce25712b70ccff439f2a3204bb15476d9"
|
||||||
@@ -211,6 +217,13 @@
|
|||||||
"@types/react" "*"
|
"@types/react" "*"
|
||||||
redux "^3.6.0"
|
redux "^3.6.0"
|
||||||
|
|
||||||
|
"@types/redux-immutable@^3.0.38":
|
||||||
|
version "3.0.38"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/redux-immutable/-/redux-immutable-3.0.38.tgz#9e2fcce4a9c64e60f13de2165d2765f7af85d487"
|
||||||
|
dependencies:
|
||||||
|
immutable "^3.8.1"
|
||||||
|
redux "^3.6.0"
|
||||||
|
|
||||||
"@types/redux-logger@^3.0.4":
|
"@types/redux-logger@^3.0.4":
|
||||||
version "3.0.5"
|
version "3.0.5"
|
||||||
resolved "https://registry.yarnpkg.com/@types/redux-logger/-/redux-logger-3.0.5.tgz#d1a02758f90845899cd304aa0912daeba2028eb6"
|
resolved "https://registry.yarnpkg.com/@types/redux-logger/-/redux-logger-3.0.5.tgz#d1a02758f90845899cd304aa0912daeba2028eb6"
|
||||||
@@ -2250,6 +2263,10 @@ execa@^0.7.0:
|
|||||||
signal-exit "^3.0.0"
|
signal-exit "^3.0.0"
|
||||||
strip-eof "^1.0.0"
|
strip-eof "^1.0.0"
|
||||||
|
|
||||||
|
exenv@^1.2.1:
|
||||||
|
version "1.2.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/exenv/-/exenv-1.2.2.tgz#2ae78e85d9894158670b03d47bec1f03bd91bb9d"
|
||||||
|
|
||||||
expand-brackets@^0.1.4:
|
expand-brackets@^0.1.4:
|
||||||
version "0.1.5"
|
version "0.1.5"
|
||||||
resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b"
|
resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b"
|
||||||
@@ -3175,6 +3192,10 @@ ignore-walk@^3.0.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
minimatch "^3.0.4"
|
minimatch "^3.0.4"
|
||||||
|
|
||||||
|
immutable@^3.8.1, immutable@^3.8.2:
|
||||||
|
version "3.8.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/immutable/-/immutable-3.8.2.tgz#c2439951455bb39913daf281376f1530e104adf3"
|
||||||
|
|
||||||
import-lazy@^2.1.0:
|
import-lazy@^2.1.0:
|
||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43"
|
resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43"
|
||||||
@@ -5846,7 +5867,7 @@ promzard@^0.3.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
read "1"
|
read "1"
|
||||||
|
|
||||||
prop-types@^15.0.0, prop-types@^15.5.7:
|
prop-types@^15.0.0, prop-types@^15.5.0, prop-types@^15.5.7:
|
||||||
version "15.6.1"
|
version "15.6.1"
|
||||||
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.1.tgz#36644453564255ddda391191fb3a125cbdf654ca"
|
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.1.tgz#36644453564255ddda391191fb3a125cbdf654ca"
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -6133,6 +6154,15 @@ react-event-listener@^0.5.1:
|
|||||||
prop-types "^15.6.0"
|
prop-types "^15.6.0"
|
||||||
warning "^3.0.0"
|
warning "^3.0.0"
|
||||||
|
|
||||||
|
react-helmet@^5.2.0:
|
||||||
|
version "5.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-helmet/-/react-helmet-5.2.0.tgz#a81811df21313a6d55c5f058c4aeba5d6f3d97a7"
|
||||||
|
dependencies:
|
||||||
|
deep-equal "^1.0.1"
|
||||||
|
object-assign "^4.1.1"
|
||||||
|
prop-types "^15.5.4"
|
||||||
|
react-side-effect "^1.1.0"
|
||||||
|
|
||||||
react-infinite-scroller@^1.1.2:
|
react-infinite-scroller@^1.1.2:
|
||||||
version "1.1.3"
|
version "1.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/react-infinite-scroller/-/react-infinite-scroller-1.1.3.tgz#c4230024bc237ce876c76b2e38d77dc1f6aabb26"
|
resolved "https://registry.yarnpkg.com/react-infinite-scroller/-/react-infinite-scroller-1.1.3.tgz#c4230024bc237ce876c76b2e38d77dc1f6aabb26"
|
||||||
@@ -6169,9 +6199,15 @@ react-linkify@^0.2.1:
|
|||||||
prop-types "^15.5.8"
|
prop-types "^15.5.8"
|
||||||
tlds "^1.57.0"
|
tlds "^1.57.0"
|
||||||
|
|
||||||
react-localize-redux@^2.15.1:
|
react-loadable@^5.3.1:
|
||||||
version "2.15.1"
|
version "5.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/react-localize-redux/-/react-localize-redux-2.15.1.tgz#b32969eae191bcbcca2f0ffdc20802768fec0601"
|
resolved "https://registry.yarnpkg.com/react-loadable/-/react-loadable-5.3.1.tgz#9699e9a08fed49bacd69caaa282034b62a76bcdd"
|
||||||
|
dependencies:
|
||||||
|
prop-types "^15.5.0"
|
||||||
|
|
||||||
|
react-localize-redux@^2.16.0:
|
||||||
|
version "2.16.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-localize-redux/-/react-localize-redux-2.16.0.tgz#9e4b1c4703984decfb33fcf8f9ab51454af5211e"
|
||||||
dependencies:
|
dependencies:
|
||||||
flat "^2.0.1"
|
flat "^2.0.1"
|
||||||
reselect "^3.0.1"
|
reselect "^3.0.1"
|
||||||
@@ -6290,6 +6326,13 @@ react-share@^2.0.0:
|
|||||||
jsonp "^0.2.1"
|
jsonp "^0.2.1"
|
||||||
prop-types "^15.5.8"
|
prop-types "^15.5.8"
|
||||||
|
|
||||||
|
react-side-effect@^1.1.0:
|
||||||
|
version "1.1.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-side-effect/-/react-side-effect-1.1.5.tgz#f26059e50ed9c626d91d661b9f3c8bb38cd0ff2d"
|
||||||
|
dependencies:
|
||||||
|
exenv "^1.2.1"
|
||||||
|
shallowequal "^1.0.1"
|
||||||
|
|
||||||
react-string-replace@^0.4.0:
|
react-string-replace@^0.4.0:
|
||||||
version "0.4.1"
|
version "0.4.1"
|
||||||
resolved "https://registry.yarnpkg.com/react-string-replace/-/react-string-replace-0.4.1.tgz#024c6ac0a91163ecae439a1b197d3e1660c98c0d"
|
resolved "https://registry.yarnpkg.com/react-string-replace/-/react-string-replace-0.4.1.tgz#024c6ac0a91163ecae439a1b197d3e1660c98c0d"
|
||||||
@@ -6513,6 +6556,10 @@ redux-devtools-dock-monitor@^1.1.3:
|
|||||||
react-dock "^0.2.4"
|
react-dock "^0.2.4"
|
||||||
react-pure-render "^1.0.2"
|
react-pure-render "^1.0.2"
|
||||||
|
|
||||||
|
redux-devtools-extension@^2.13.2:
|
||||||
|
version "2.13.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/redux-devtools-extension/-/redux-devtools-extension-2.13.2.tgz#e0f9a8e8dfca7c17be92c7124958a3b94eb2911d"
|
||||||
|
|
||||||
redux-devtools-instrument@^1.0.1:
|
redux-devtools-instrument@^1.0.1:
|
||||||
version "1.8.3"
|
version "1.8.3"
|
||||||
resolved "https://registry.yarnpkg.com/redux-devtools-instrument/-/redux-devtools-instrument-1.8.3.tgz#c510d67ab4e5e4525acd6e410c25ab46b85aca7c"
|
resolved "https://registry.yarnpkg.com/redux-devtools-instrument/-/redux-devtools-instrument-1.8.3.tgz#c510d67ab4e5e4525acd6e410c25ab46b85aca7c"
|
||||||
@@ -6544,6 +6591,10 @@ redux-devtools@^3.4.1:
|
|||||||
prop-types "^15.5.7"
|
prop-types "^15.5.7"
|
||||||
redux-devtools-instrument "^1.0.1"
|
redux-devtools-instrument "^1.0.1"
|
||||||
|
|
||||||
|
redux-immutable@^4.0.0:
|
||||||
|
version "4.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/redux-immutable/-/redux-immutable-4.0.0.tgz#3a1a32df66366462b63691f0e1dc35e472bbc9f3"
|
||||||
|
|
||||||
redux-logger@^3.0.1:
|
redux-logger@^3.0.1:
|
||||||
version "3.0.6"
|
version "3.0.6"
|
||||||
resolved "https://registry.yarnpkg.com/redux-logger/-/redux-logger-3.0.6.tgz#f7555966f3098f3c88604c449cf0baf5778274bf"
|
resolved "https://registry.yarnpkg.com/redux-logger/-/redux-logger-3.0.6.tgz#f7555966f3098f3c88604c449cf0baf5778274bf"
|
||||||
@@ -7006,6 +7057,10 @@ sha@~2.0.1:
|
|||||||
graceful-fs "^4.1.2"
|
graceful-fs "^4.1.2"
|
||||||
readable-stream "^2.0.2"
|
readable-stream "^2.0.2"
|
||||||
|
|
||||||
|
shallowequal@^1.0.1:
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.0.2.tgz#1561dbdefb8c01408100319085764da3fcf83f8f"
|
||||||
|
|
||||||
shebang-command@^1.2.0:
|
shebang-command@^1.2.0:
|
||||||
version "1.2.0"
|
version "1.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
|
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
|
||||||
|
|||||||
Reference in New Issue
Block a user