From 051cfa6f073db85ad95dab658bc0a079b7286f0d Mon Sep 17 00:00:00 2001
From: Qolzam
Date: Sun, 14 Jan 2018 15:10:00 +0700
Subject: [PATCH] [Next Version] Realat to #5 #6 #9 #15 #17 #20 #23 #24 #27 #35
#36 #42
---
README.md | 119 +++++----
docs/README.md | 119 +++++----
docs/layers/api.md | 16 --
package.json | 3 +-
src/actions/circleActions.ts | 210 ++++++++++++++--
src/actions/commentActions.ts | 2 +-
src/actions/globalActions.ts | 169 ++++++++++---
.../{serveActions.ts => serverActions.ts} | 2 +-
src/api/CircleAPI.ts | 47 ----
src/api/CommonAPI.ts | 14 +-
src/assets/fonts/Flaticon.eot | Bin 0 -> 2902 bytes
src/assets/fonts/Flaticon.ttf | Bin 0 -> 2724 bytes
src/assets/fonts/Flaticon.woff | Bin 0 -> 1608 bytes
src/assets/images/Flaticon.svg | 65 +++++
src/components/circle/CircleComponent.tsx | 36 ++-
.../circle/ICircleComponentProps.ts | 9 +-
.../findPeople/IFindPeopleComponentProps.ts | 2 +-
.../followers/FollowersComponent.tsx | 3 +-
.../following/FollowingComponent.tsx | 4 +-
src/components/home/HomeComponent.tsx | 13 +-
src/components/home/IHomeComponentProps.ts | 10 +
.../master/IMasterComponentProps.ts | 13 +-
src/components/master/MasterComponent.tsx | 23 +-
.../masterLoading/MasterLoadingComponent.tsx | 29 +--
.../ISendFeedbackComponentProps.ts | 30 +++
.../ISendFeedbackComponentState.ts | 7 +
.../sendFeedback/SendFeedbackComponent.tsx | 232 ++++++++++++++++++
src/components/sendFeedback/index.ts | 2 +
src/components/signup/SignupComponent.tsx | 2 +-
.../userBox/IUserBoxComponentProps.ts | 65 ++++-
.../userBox/IUserBoxComponentState.ts | 12 -
src/components/userBox/UserBoxComponent.tsx | 154 +++++++-----
.../yourCircles/YourCirclesComponent.tsx | 2 -
src/constants/circleActionType.ts | 4 +
src/constants/globalActionType.ts | 4 +
src/constants/serverRequestType.ts | 4 +-
src/core/domain/circles/circle.ts | 4 +-
src/core/domain/common/feed.ts | 34 +++
src/core/domain/common/feedType.ts | 8 +
src/core/domain/common/index.ts | 6 +-
src/core/services/circles/IUserTieService.ts | 6 +
src/core/services/common/ICommonService.ts | 5 +
.../services/circles/UserTieService.ts | 30 ++-
.../services/common/CommonService.ts | 20 +-
.../services/graphs/GraphService.ts | 33 +--
.../services/posts/PostService.ts | 2 +-
.../services/users/UserService.ts | 12 +-
src/reducers/circles/CircleState.ts | 50 ++--
src/reducers/circles/circleReducer.ts | 70 +++++-
src/reducers/global/GlobalState.ts | 169 +++++++------
src/reducers/global/globalReducer.ts | 32 ++-
src/reducers/server/serverReducer.ts | 2 +-
src/socialEngine.ts | 2 +-
src/styles/app.scss | 2 +
src/styles/base/_flaticon.scss | 52 ++++
src/styles/base/_icon.scss | 10 +
src/styles/components/_homeHeader.scss | 11 +-
src/styles/components/_masterLoading.scss | 42 +++-
src/styles/components/_sendFeedback.scss | 37 +++
59 files changed, 1570 insertions(+), 495 deletions(-)
rename src/actions/{serveActions.ts => serverActions.ts} (94%)
delete mode 100644 src/api/CircleAPI.ts
create mode 100644 src/assets/fonts/Flaticon.eot
create mode 100644 src/assets/fonts/Flaticon.ttf
create mode 100644 src/assets/fonts/Flaticon.woff
create mode 100644 src/assets/images/Flaticon.svg
create mode 100644 src/components/sendFeedback/ISendFeedbackComponentProps.ts
create mode 100644 src/components/sendFeedback/ISendFeedbackComponentState.ts
create mode 100644 src/components/sendFeedback/SendFeedbackComponent.tsx
create mode 100644 src/components/sendFeedback/index.ts
create mode 100644 src/core/domain/common/feed.ts
create mode 100644 src/core/domain/common/feedType.ts
create mode 100644 src/styles/base/_flaticon.scss
create mode 100644 src/styles/components/_sendFeedback.scss
diff --git a/README.md b/README.md
index 51c0db8..de84b1d 100644
--- a/README.md
+++ b/README.md
@@ -6,12 +6,13 @@
[](https://gitter.im/react-social-network/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
-The React Social Network is an open source project relying on [React](https://facebook.github.io/react/docs/hello-world.html) a powerful javascript library for building the user interface. In this project, I tried to show some features of react/react components as a social network.
+The React Social Network is an open source project relying on [React](https://facebook.github.io/react/docs/hello-world.html) a powerful javascript library for building the user interface. In this project, I tried to show some features of react/react components as a social network.
+The structure of this project give the ability to devoloper to develop their project on thier own idea and environment.
@@ -27,9 +28,9 @@ For those who prefer writing code by typescript, now React Social Network suppor
This project adheres to the Contributor Covenant [code of conduct](https://github.com/Qolzam/react-social-network/blob/master/CODE_OF_CONDUCT.md).
By participating, you are expected to uphold this code. Please report unacceptable behavior to amir.gholzam@live.com.
-## DEMO
+## Example
- [Green Open Social](http://greensocial.herokuapp.com)
+ [Love Open Social](https://love-social.firebaseapp.com)
## Required Knowledge
@@ -39,44 +40,37 @@ I recommend that you get to know React before using React Social Network. React
## Document
- Use [Documentation](https://qolzam.gitbooks.io/react-social-network/) to find out more details about this project.
-
-## Features
-
- * [TypeScript](https://www.typescriptlang.org/) TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
- * [React](https://facebook.github.io/react/docs/hello-world.html) A javascript library for building user interfaces.
- * [Redux](http://redux.js.org/) is a predictable state container for JavaScript apps.
- * [Material-UI](http://www.material-ui.com/#/) A Set of React Components that Implement Google's Material Design.
- * [react-redux](https://github.com/reactjs/react-redux) Official React bindings for Redux.
- * [Firebase](https://firebase.google.com/) products like Analytics, Realtime Database, Messaging, and Crash Reporting let you move quickly and focus on your users.
- * [redux-thunk](https://github.com/gaearon/redux-thunk) Redux Thunk middleware allows you to write action creators that return a function instead of an action. The thunk can be used to delay the dispatch of an action, or to dispatch only if a certain condition is met. The inner function receives the store methods dispatch and getState as parameters.
- * [Express](https://expressjs.com/) Express is a minimal and flexible Node.js web application framework that provides a robust set of features for web and mobile applications.
- * [React Router V4](https://github.com/ReactTraining/react-router) for routing website location
- * [Sass](http://sass-lang.com/) CSS with superpowers. Sass boasts more features and abilities than any other CSS extension language out there.
- * [Webpack](https://webpack.js.org/) for bundling code
-
-## In my todo list
-
- * Documentation
- * Testing
- * Security issues
- * Performance
- * Add some features and solving bugs
- * Sharing post in social itself and other socials
- * Add link feature to post
- * Add vido post
- * Add image gallery post
- * Search post and people
- ...
+ Comming soon :) ...
-# Prerequisites
+## Road map
+ 1. Support Firebase/Firestore -> on developing
+ 2. Support AWS -> on developing
+ 3. Support Azure
+ 4. Support ASP.NET -> on developing
+
+## Getting Started
+
+These instructions will get you a copy of the project up and running on your local machine for development and testing purposes. See deployment for notes on how to deploy the project on a live system.
+
+### Prerequisites
Install [NodeJs](https://nodejs.org/en/)
+
+#### Note
-# Installing
+ - If you're using Windows you should install all node-gyp dependencies with following commands:
-[](https://www.youtube.com/watch?v=E12PNKKjzqA)
+`$ npm install --global --production windows-build-tools`
+and then install the package
+
+`$ npm install --global node-gyp`
+
+
+### Installing
+
+## Install back-end server/serverless
+ Comming soon :) ...
1. Fork the [react-social-network](https://github.com/Qolzam/react-social-network) repository on Github
2. Clone your fork to your local machine `git clone git@github.com:/react-social-network.git`
@@ -101,31 +95,56 @@ I recommend that you get to know React before using React Social Network. React
5. Installing all nodejs modules:
`npm install`
- 6. Rub webpack to build bundle file
- `webpack`
- 5. Running server:
- `node server.js`
+ 6. Go ahead ;)
+ `npm start`
-# Warning
- - If you're using Windows you should install all node-gyp dependencies with following commands:
-`$ npm install --global --production windows-build-tools`
-and then install the package
-`$ npm install --global node-gyp`
+## Deployment
+Follow [firebase instruction](https://firebase.google.com/docs/hosting/deploying)
+`firebase deploy`
-## Contribute
+## Built With
-[React Social Network](http://greensocial.herokuapp.com/) has been made by love. I planed to build a back-end for this project and improve the performance as I process all procedures on the front-end side. If you'd like to help,
+ * [TypeScript](https://www.typescriptlang.org/) TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
+ * [JSX/TSX](https://jsx.github.io/) This project support both *.jsx and *.tsx files. JSX is a statically-typed, object-oriented programming language designed to run on modern web browsers. Being developed at DeNA as a research project, the language has following characteristics.
+ * [React](https://facebook.github.io/react/docs/hello-world.html) A javascript library for building user interfaces.
+ * [Redux](http://redux.js.org/) is a predictable state container for JavaScript apps.
+ * [Material-UI](http://www.material-ui.com/#/) A Set of React Components that Implement Google's Material Design.
+ * [react-redux](https://github.com/reactjs/react-redux) Official React bindings for Redux.
+ * [Firebase](https://firebase.google.com/) products like Analytics, Realtime Database, Messaging, and Crash Reporting let you move quickly and focus on your users.
+ * [redux-thunk](https://github.com/gaearon/redux-thunk) Redux Thunk middleware allows you to write action creators that return a function instead of an action. The thunk can be used to delay the dispatch of an action, or to dispatch only if a certain condition is met. The inner function receives the store methods dispatch and getState as parameters.
+ * [Express](https://expressjs.com/) Express is a minimal and flexible Node.js web application framework that provides a robust set of features for web and mobile applications.
+ * [React Router V4](https://github.com/ReactTraining/react-router) for routing website location
+ * [Sass](http://sass-lang.com/) CSS with superpowers. Sass boasts more features and abilities than any other CSS extension language out there.
+ * [Webpack](https://webpack.js.org/) for bundling code
+
+## Contributing
+
+[React Social Network](https://love-social.firebaseapp.com) has been made by love. I planed to build a back-end for this project and improve the performance as I process all procedures on the front-end side. If you'd like to help,
check out the [document](https://qolzam.gitbooks.io/react-social-network/).
I'd greatly appreciate any [contribution](https://github.com/Qolzam/react-social-network/blob/master/CONTRIBUTING.md)
-you make. :)
- # Authors
+## Versioning
+
+We use [SemVer](http://semver.org/) for versioning. For the versions available, see the [tags on this repository](https://github.com/Qolzam/react-social-network/tags).
+
+## Authors
- Amir Movahedi
+ - See also the list of [contributors](https://github.com/Qolzam/react-social-network/contributors) who participated in this project.
-# License
+## License
This project is licensed under the MIT License - see the [LICENSE](https://github.com/Qolzam/react-social-network/blob/master/LICENSE) file for details
+
+
+## Acknowledgments
+
+* React
+* Firebase
+* JavaScript
+* TypeScript
+
+
diff --git a/docs/README.md b/docs/README.md
index 51c0db8..de84b1d 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -6,12 +6,13 @@
[](https://gitter.im/react-social-network/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
-The React Social Network is an open source project relying on [React](https://facebook.github.io/react/docs/hello-world.html) a powerful javascript library for building the user interface. In this project, I tried to show some features of react/react components as a social network.
+The React Social Network is an open source project relying on [React](https://facebook.github.io/react/docs/hello-world.html) a powerful javascript library for building the user interface. In this project, I tried to show some features of react/react components as a social network.
+The structure of this project give the ability to devoloper to develop their project on thier own idea and environment.
@@ -27,9 +28,9 @@ For those who prefer writing code by typescript, now React Social Network suppor
This project adheres to the Contributor Covenant [code of conduct](https://github.com/Qolzam/react-social-network/blob/master/CODE_OF_CONDUCT.md).
By participating, you are expected to uphold this code. Please report unacceptable behavior to amir.gholzam@live.com.
-## DEMO
+## Example
- [Green Open Social](http://greensocial.herokuapp.com)
+ [Love Open Social](https://love-social.firebaseapp.com)
## Required Knowledge
@@ -39,44 +40,37 @@ I recommend that you get to know React before using React Social Network. React
## Document
- Use [Documentation](https://qolzam.gitbooks.io/react-social-network/) to find out more details about this project.
-
-## Features
-
- * [TypeScript](https://www.typescriptlang.org/) TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
- * [React](https://facebook.github.io/react/docs/hello-world.html) A javascript library for building user interfaces.
- * [Redux](http://redux.js.org/) is a predictable state container for JavaScript apps.
- * [Material-UI](http://www.material-ui.com/#/) A Set of React Components that Implement Google's Material Design.
- * [react-redux](https://github.com/reactjs/react-redux) Official React bindings for Redux.
- * [Firebase](https://firebase.google.com/) products like Analytics, Realtime Database, Messaging, and Crash Reporting let you move quickly and focus on your users.
- * [redux-thunk](https://github.com/gaearon/redux-thunk) Redux Thunk middleware allows you to write action creators that return a function instead of an action. The thunk can be used to delay the dispatch of an action, or to dispatch only if a certain condition is met. The inner function receives the store methods dispatch and getState as parameters.
- * [Express](https://expressjs.com/) Express is a minimal and flexible Node.js web application framework that provides a robust set of features for web and mobile applications.
- * [React Router V4](https://github.com/ReactTraining/react-router) for routing website location
- * [Sass](http://sass-lang.com/) CSS with superpowers. Sass boasts more features and abilities than any other CSS extension language out there.
- * [Webpack](https://webpack.js.org/) for bundling code
-
-## In my todo list
-
- * Documentation
- * Testing
- * Security issues
- * Performance
- * Add some features and solving bugs
- * Sharing post in social itself and other socials
- * Add link feature to post
- * Add vido post
- * Add image gallery post
- * Search post and people
- ...
+ Comming soon :) ...
-# Prerequisites
+## Road map
+ 1. Support Firebase/Firestore -> on developing
+ 2. Support AWS -> on developing
+ 3. Support Azure
+ 4. Support ASP.NET -> on developing
+
+## Getting Started
+
+These instructions will get you a copy of the project up and running on your local machine for development and testing purposes. See deployment for notes on how to deploy the project on a live system.
+
+### Prerequisites
Install [NodeJs](https://nodejs.org/en/)
+
+#### Note
-# Installing
+ - If you're using Windows you should install all node-gyp dependencies with following commands:
-[](https://www.youtube.com/watch?v=E12PNKKjzqA)
+`$ npm install --global --production windows-build-tools`
+and then install the package
+
+`$ npm install --global node-gyp`
+
+
+### Installing
+
+## Install back-end server/serverless
+ Comming soon :) ...
1. Fork the [react-social-network](https://github.com/Qolzam/react-social-network) repository on Github
2. Clone your fork to your local machine `git clone git@github.com:/react-social-network.git`
@@ -101,31 +95,56 @@ I recommend that you get to know React before using React Social Network. React
5. Installing all nodejs modules:
`npm install`
- 6. Rub webpack to build bundle file
- `webpack`
- 5. Running server:
- `node server.js`
+ 6. Go ahead ;)
+ `npm start`
-# Warning
- - If you're using Windows you should install all node-gyp dependencies with following commands:
-`$ npm install --global --production windows-build-tools`
-and then install the package
-`$ npm install --global node-gyp`
+## Deployment
+Follow [firebase instruction](https://firebase.google.com/docs/hosting/deploying)
+`firebase deploy`
-## Contribute
+## Built With
-[React Social Network](http://greensocial.herokuapp.com/) has been made by love. I planed to build a back-end for this project and improve the performance as I process all procedures on the front-end side. If you'd like to help,
+ * [TypeScript](https://www.typescriptlang.org/) TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
+ * [JSX/TSX](https://jsx.github.io/) This project support both *.jsx and *.tsx files. JSX is a statically-typed, object-oriented programming language designed to run on modern web browsers. Being developed at DeNA as a research project, the language has following characteristics.
+ * [React](https://facebook.github.io/react/docs/hello-world.html) A javascript library for building user interfaces.
+ * [Redux](http://redux.js.org/) is a predictable state container for JavaScript apps.
+ * [Material-UI](http://www.material-ui.com/#/) A Set of React Components that Implement Google's Material Design.
+ * [react-redux](https://github.com/reactjs/react-redux) Official React bindings for Redux.
+ * [Firebase](https://firebase.google.com/) products like Analytics, Realtime Database, Messaging, and Crash Reporting let you move quickly and focus on your users.
+ * [redux-thunk](https://github.com/gaearon/redux-thunk) Redux Thunk middleware allows you to write action creators that return a function instead of an action. The thunk can be used to delay the dispatch of an action, or to dispatch only if a certain condition is met. The inner function receives the store methods dispatch and getState as parameters.
+ * [Express](https://expressjs.com/) Express is a minimal and flexible Node.js web application framework that provides a robust set of features for web and mobile applications.
+ * [React Router V4](https://github.com/ReactTraining/react-router) for routing website location
+ * [Sass](http://sass-lang.com/) CSS with superpowers. Sass boasts more features and abilities than any other CSS extension language out there.
+ * [Webpack](https://webpack.js.org/) for bundling code
+
+## Contributing
+
+[React Social Network](https://love-social.firebaseapp.com) has been made by love. I planed to build a back-end for this project and improve the performance as I process all procedures on the front-end side. If you'd like to help,
check out the [document](https://qolzam.gitbooks.io/react-social-network/).
I'd greatly appreciate any [contribution](https://github.com/Qolzam/react-social-network/blob/master/CONTRIBUTING.md)
-you make. :)
- # Authors
+## Versioning
+
+We use [SemVer](http://semver.org/) for versioning. For the versions available, see the [tags on this repository](https://github.com/Qolzam/react-social-network/tags).
+
+## Authors
- Amir Movahedi
+ - See also the list of [contributors](https://github.com/Qolzam/react-social-network/contributors) who participated in this project.
-# License
+## License
This project is licensed under the MIT License - see the [LICENSE](https://github.com/Qolzam/react-social-network/blob/master/LICENSE) file for details
+
+
+## Acknowledgments
+
+* React
+* Firebase
+* JavaScript
+* TypeScript
+
+
diff --git a/docs/layers/api.md b/docs/layers/api.md
index 9906a4a..24a654e 100644
--- a/docs/layers/api.md
+++ b/docs/layers/api.md
@@ -2,22 +2,6 @@
Is a decoupled layer of interfaces to data and/or functionality of one or more components.
-## CircleAPI.jsx
-
-We provided some functions for doing some procedures on user circles.
-
-```javascript
-getUserBelongCircles = (circles,followingId) => {}
-```
-
-To get circles which the user is added in. `circles` is the parameter that we want to know if user is exist in any of them or not. `followingId` is the parameter that show the use identifier who we are looking for in `circles` parameter.
-
-```javascript
-getFollowingUsers = (circles) => {}
-```
-
-Get the user who are in circles. `circles` is the paramater that we get users from.
-
## FileAPI.jsx
A set of functions for working with files.
diff --git a/package.json b/package.json
index 320f465..39beb80 100644
--- a/package.json
+++ b/package.json
@@ -39,7 +39,7 @@
"node-sass": "^4.5.2",
"npm": "^5.6.0",
"prop-types": "^15.6.0",
- "react": "^16.0.0",
+ "react": "^16.2.0",
"react-addons-test-utils": "^15.6.2",
"react-avatar-editor": "^10.3.0",
"react-dom": "^16.0.0",
@@ -68,6 +68,7 @@
"devDependencies": {
"@types/lodash": "^4.14.77",
"@types/material-ui": "^0.18.2",
+ "@types/moment": "^2.13.0",
"@types/node": "^8.0.33",
"@types/prop-types": "^15.5.2",
"@types/react": "^16.0.10",
diff --git a/src/actions/circleActions.ts b/src/actions/circleActions.ts
index 0bf901a..58e959c 100644
--- a/src/actions/circleActions.ts
+++ b/src/actions/circleActions.ts
@@ -14,12 +14,17 @@ import * as globalActions from 'actions/globalActions'
import * as postActions from 'actions/postActions'
import * as userActions from 'actions/userActions'
import * as notifyActions from 'actions/notifyActions'
+import * as serverActions from 'actions/serverActions'
import { IServiceProvider, ServiceProvide } from 'core/factories'
import { ICircleService } from 'core/services/circles'
import { SocialProviderTypes } from 'core/socialProviderTypes'
import { provider } from '../socialEngine'
import { IUserTieService } from 'core/services/circles'
+import StringAPI from 'api/StringAPI'
+import { ServerRequestStatusType } from 'actions/serverRequestStatusType'
+import { ServerRequestType } from 'constants/serverRequestType'
+import { ServerRequestModel } from 'models/server/serverRequestModel'
/**
* Get service providers
@@ -39,7 +44,9 @@ export let dbAddCircle = (circleName: string) => {
let uid: string = getState().authorize.uid
let circle: Circle = {
creationDate: moment().unix(),
- name: circleName
+ name: circleName,
+ isSystem : false,
+ ownerId: uid
}
return circleService.addCircle(uid, circle).then((circleKey: string) => {
circle.id = circleKey
@@ -51,6 +58,60 @@ export let dbAddCircle = (circleName: string) => {
}
}
+/**
+ * Add referer user to the `Following` circle of current user
+ */
+export const dbFollowUser = (followingCircleId: string, userFollowing: UserTie) => {
+ return (dispatch: Function, getState: Function) => {
+ const state = getState()
+ let uid: string = state.authorize.uid
+ let user: User = { ...state.user.info[uid], userId: uid }
+
+ // Set server request status to {Sent} for following user
+ const followReqestModel = createFollowRequest(userFollowing.userId!)
+ dispatch(serverActions.sendRequest(followReqestModel))
+
+ // Call server API
+ return userTieService.tieUseres(
+ { userId: user.userId!, fullName: user.fullName, avatar: user.avatar, approved: false },
+ { userId: userFollowing.userId!, fullName: userFollowing.fullName, avatar: userFollowing.avatar, approved: false },
+ [followingCircleId]
+ )
+ .then(() => {
+ dispatch(addFollowingUser(
+ new UserTie(
+ userFollowing.userId!,
+ moment().unix(),
+ userFollowing.fullName,
+ userFollowing.avatar,
+ false,
+ [followingCircleId]
+ )))
+
+ // Set server request status to {OK} for following user
+ followReqestModel.status = ServerRequestStatusType.OK
+ dispatch(serverActions.sendRequest(followReqestModel))
+
+ // Send notification
+ dispatch(notifyActions.dbAddNotification(
+ {
+ description: `${user.fullName} follow you.`,
+ url: `/${uid}`,
+ notifyRecieverUserId: userFollowing.userId as string,
+ notifierUserId: uid,
+ isSeen: false
+ }))
+
+ }, (error: SocialError) => {
+ dispatch(globalActions.showErrorMessage(error.message))
+
+ // Set server request status to {Error} for following user
+ followReqestModel.status = ServerRequestStatusType.Error
+ dispatch(serverActions.sendRequest(followReqestModel))
+ })
+ }
+}
+
/**
* Update user in circle/circles
*/
@@ -60,7 +121,14 @@ export let dbUpdateUserInCircles = (circleIdList: string[], userFollowing: UserT
let uid: string = state.authorize.uid
let user: User = { ...state.user.info[uid], userId: uid }
- return userTieService.tieUseres(
+ // Set server request status to {Sent}
+ const addToCircleRequest = createAddToCircleRequest(userFollowing.userId!)
+ dispatch(serverActions.sendRequest(addToCircleRequest))
+
+ dispatch(globalActions.showMasterLoading())
+
+ // Call server API
+ return userTieService.updateUsersTie(
{ userId: user.userId!, fullName: user.fullName, avatar: user.avatar, approved: false },
{ userId: userFollowing.userId!, fullName: userFollowing.fullName, avatar: userFollowing.avatar, approved: false },
circleIdList
@@ -76,17 +144,23 @@ export let dbUpdateUserInCircles = (circleIdList: string[], userFollowing: UserT
circleIdList
)))
- dispatch(notifyActions.dbAddNotification(
- {
- description: `${user.fullName} follow you.`,
- url: `/${uid}`,
- notifyRecieverUserId: userFollowing.userId as string,
- notifierUserId: uid,
- isSeen: false
- }))
+ // Set server request status to {OK}
+ addToCircleRequest.status = ServerRequestStatusType.OK
+ dispatch(serverActions.sendRequest(addToCircleRequest))
+
+ dispatch(globalActions.hideMasterLoading())
+
+ // Close select circle box
+ dispatch(closeSelectCircleBox(userFollowing.userId!))
}, (error: SocialError) => {
dispatch(globalActions.showErrorMessage(error.message))
+
+ dispatch(globalActions.hideMasterLoading())
+
+ // Set server request status to {Error}
+ addToCircleRequest.status = ServerRequestStatusType.Error
+ dispatch(serverActions.sendRequest(addToCircleRequest))
})
}
}
@@ -99,11 +173,36 @@ export let dbDeleteFollowingUser = (userFollowingId: string) => {
let uid: string = getState().authorize.uid
+ // Set server request status to {Sent}
+ const deleteFollowingUserRequest = createdeleteFollowingUserRequest(userFollowingId)
+ dispatch(serverActions.sendRequest(deleteFollowingUserRequest))
+
+ dispatch(globalActions.showMasterLoading())
+
+ // Call server API
return userTieService.removeUsersTie(uid, userFollowingId)
.then(() => {
dispatch(deleteFollowingUser(userFollowingId))
+
+ dispatch(globalActions.hideMasterLoading())
+
+ // Close select circle box
+ dispatch(closeSelectCircleBox(userFollowingId))
+
+ // Set server request status to {OK}
+ deleteFollowingUserRequest.status = ServerRequestStatusType.OK
+ dispatch(serverActions.sendRequest(deleteFollowingUserRequest))
}, (error: SocialError) => {
dispatch(globalActions.showErrorMessage(error.message))
+
+ dispatch(globalActions.hideMasterLoading())
+
+ // Close select circle box
+ dispatch(closeSelectCircleBox(userFollowingId))
+
+ // Set server request status to {Error}
+ deleteFollowingUserRequest.status = ServerRequestStatusType.Error
+ dispatch(serverActions.sendRequest(deleteFollowingUserRequest))
})
}
}
@@ -120,7 +219,8 @@ export const dbUpdateCircle = (newCircle: Circle) => {
// Write the new data simultaneously in the list
let circle: Circle = getState().circle.userTies[uid][newCircle.id!]
let updatedCircle: Circle = {
- name: newCircle.name || circle.name
+ name: newCircle.name || circle.name,
+ isSystem : false
}
return circleService.updateCircle(uid, newCircle.id!, circle)
.then(() => {
@@ -198,10 +298,10 @@ export const dbGetFollowers = () => {
return (dispatch: any, getState: Function) => {
let uid: string = getState().authorize.uid
if (uid) {
- userTieService.getUserTies(uid).then((result) => {
+ userTieService.getUserTieSender(uid).then((result) => {
dispatch(userActions.addPeopleInfo(result as any))
- dispatch(addUserTies(result))
+ dispatch(addUserTieds(result))
})
.catch((error: SocialError) => {
@@ -230,6 +330,45 @@ export const dbGetCirclesByUserId = (uid: string) => {
}
}
+/**
+ * Create follow user serevr request model
+ */
+const createFollowRequest = (userFollowingId: string) => {
+ const requestId = StringAPI.createServerRequestId(ServerRequestType.CircleFollowUser, userFollowingId)
+ return new ServerRequestModel(
+ ServerRequestType.CircleFollowUser,
+ requestId,
+ '',
+ ServerRequestStatusType.Sent
+ )
+}
+
+/**
+ * Create add referer user to circle serevr request model
+ */
+const createAddToCircleRequest = (userFollowingId: string) => {
+ const requestId = StringAPI.createServerRequestId(ServerRequestType.CircleAddToCircle, userFollowingId)
+ return new ServerRequestModel(
+ ServerRequestType.CircleAddToCircle,
+ requestId,
+ '',
+ ServerRequestStatusType.Sent
+ )
+}
+
+/**
+ * Create delete referer user serevr request model
+ */
+const createdeleteFollowingUserRequest = (userFollowingId: string) => {
+ const requestId = StringAPI.createServerRequestId(ServerRequestType.CircleDeleteFollowingUser, userFollowingId)
+ return new ServerRequestModel(
+ ServerRequestType.CircleDeleteFollowingUser,
+ requestId,
+ '',
+ ServerRequestStatusType.Sent
+ )
+}
+
/* _____________ CRUD State _____________ */
/**
@@ -396,6 +535,49 @@ export const showFollowingUserLoading = (userId: string) => {
}
+/**
+ * Set current user selected circles for referer user
+ */
+export const setSelectedCircles = (userId: string, circleList: string[]) => {
+ return {
+ type: CircleActionType.SET_SELECTED_CIRCLES_USER_BOX_COMPONENT,
+ payload: { userId, circleList }
+ }
+
+}
+
+/**
+ * Remove current user selected circles for referer user
+ */
+export const removeSelectedCircles = (userId: string) => {
+ return {
+ type: CircleActionType.REMOVE_SELECTED_CIRCLES_USER_BOX_COMPONENT,
+ payload: { userId }
+ }
+}
+
+/**
+ * Open select circle box
+ */
+export const openSelectCircleBox = (userId: string) => {
+ return {
+ type: CircleActionType.OPEN_SELECT_CIRCLES_USER_BOX_COMPONENT,
+ payload: { userId}
+ }
+
+}
+
+/**
+ * Close select circle box
+ */
+export const closeSelectCircleBox = (userId: string) => {
+ return {
+ type: CircleActionType.CLOSE_SELECT_CIRCLES_USER_BOX_COMPONENT,
+ payload: { userId}
+ }
+
+}
+
/**
* Hide loading on following user
*/
@@ -405,4 +587,4 @@ export const hideFollowingUserLoading = (userId: string) => {
payload: { userId }
}
-}
\ No newline at end of file
+}
diff --git a/src/actions/commentActions.ts b/src/actions/commentActions.ts
index 671f26b..ede2d8a 100644
--- a/src/actions/commentActions.ts
+++ b/src/actions/commentActions.ts
@@ -97,7 +97,7 @@ export const dbGetComments = (ownerUserId: string, postId: string) => {
}
const desiredComments = comments[postId]
- if (desiredComments && Object.keys(desiredComments).length > 0) {
+ if (desiredComments) {
commentsCount = Object.keys(desiredComments).length
let sortedObjects = desiredComments as any
// Sort posts with creation date
diff --git a/src/actions/globalActions.ts b/src/actions/globalActions.ts
index c28a04f..7a9f7b0 100644
--- a/src/actions/globalActions.ts
+++ b/src/actions/globalActions.ts
@@ -5,6 +5,50 @@ import { GlobalActionType } from 'constants/globalActionType'
import * as postActions from 'actions/postActions'
import * as commentActions from 'actions/commentActions'
import * as userActions from 'actions/userActions'
+import * as serverActions from 'actions/serverActions'
+
+import { ICommonService } from 'core/services/common/ICommonService'
+import { provider } from 'src/socialEngine'
+import { SocialProviderTypes } from 'core/socialProviderTypes'
+import { Feed, SocialError } from 'core/domain/common'
+import { ServerRequestType } from 'constants/serverRequestType'
+import StringAPI from 'api/StringAPI'
+import { ServerRequestModel } from 'models/server'
+import { ServerRequestStatusType } from 'actions/serverRequestStatusType'
+
+/**
+ * Get service providers
+ */
+const commonService: ICommonService = provider.get(SocialProviderTypes.CommonService)
+
+/**
+ * Add a normal feed
+ * @param {any} newFeed
+ * @param {Function} callBack
+ */
+export let dbSendFeed = (newFeed: Feed) => {
+ return (dispatch: any, getState: Function) => {
+
+ let uid: string = getState().authorize.uid
+
+ // Set server request status to {Sent}
+ const feedbackRequest = createFeedbackRequest(uid)
+ dispatch(serverActions.sendRequest(feedbackRequest))
+
+ return commonService.addFeed(newFeed).then(() => {
+ // Set server request status to {OK}
+ feedbackRequest.status = ServerRequestStatusType.OK
+ dispatch(serverActions.sendRequest(feedbackRequest))
+ })
+ .catch((error: SocialError) => {
+ dispatch(showErrorMessage(error.message))
+
+ // Set server request status to {Error}
+ feedbackRequest.status = ServerRequestStatusType.Error
+ dispatch(serverActions.sendRequest(feedbackRequest))
+ })
+ }
+}
/**
* Progress change
@@ -14,7 +58,7 @@ import * as userActions from 'actions/userActions'
export const progressChange = (percent: number, visible: Boolean) => {
return {
type: GlobalActionType.PROGRESS_CHANGE,
- payload: {percent, visible}
+ payload: { percent, visible }
}
}
@@ -23,7 +67,7 @@ export const progressChange = (percent: number, visible: Boolean) => {
* Default data loaded status will be true
*/
export const defaultDataEnable = () => {
- return{
+ return {
type: GlobalActionType.DEFAULT_DATA_ENABLE
}
}
@@ -33,21 +77,21 @@ export const defaultDataEnable = () => {
* @param {boolean} status
*/
export const defaultDataDisable = () => {
- return{
+ return {
type: GlobalActionType.DEFAULT_DATA_DISABLE
}
}
// - Show notification of request
export const showNotificationRequest = () => {
- return{
+ return {
type: GlobalActionType.SHOW_SEND_REQUEST_MESSAGE_GLOBAL
}
}
// - Show notification of success
export const showNotificationSuccess = () => {
- return{
+ return {
type: GlobalActionType.SHOW_REQUEST_SUCCESS_MESSAGE_GLOBAL
}
}
@@ -57,7 +101,7 @@ export const showNotificationSuccess = () => {
*/
export const hideMessage = () => {
hideTopLoading()
- return{
+ return {
type: GlobalActionType.HIDE_MESSAGE_GLOBAL
}
@@ -68,23 +112,6 @@ export const hideMessage = () => {
* @param {string} message
*/
export const showErrorMessage = (message: string) => {
- const appElement = document.getElementById('app')
- const masterElement = document.getElementById('master')
- const container = document.createElement('div')
- const div = document.createElement('div')
- div.innerHTML = message
- container.style.position = '100000'
- container.style.position = 'fixed'
- container.style.backgroundColor = '#32c3e4b8'
- container.style.width = '100%'
- container.style.height = '100%'
- container.style.display = 'flex'
- container.style.alignItems = 'center'
- container.style.alignItems = 'center'
- container.style.flexDirection = 'row'
- container.appendChild(div)
-
- appElement!.insertBefore(container, masterElement)
return {
type: GlobalActionType.SHOW_ERROR_MESSAGE_GLOBAL,
payload: message
@@ -95,8 +122,8 @@ export const showErrorMessage = (message: string) => {
/**
* Set header title
*/
-export const setHeaderTitleOpt = (callerKey: string,payload: any) => {
- return (dispatch: any,getState: Function) => {
+export const setHeaderTitleOpt = (callerKey: string, payload: any) => {
+ return (dispatch: any, getState: Function) => {
switch (callerKey) {
case 'profile':
const userName = getState().user.info && getState().user.info[payload] ? getState().user.info[payload].fullName : ''
@@ -114,7 +141,7 @@ export const setHeaderTitleOpt = (callerKey: string,payload: any) => {
* Set header title
*/
export const setHeaderTitle = (text: string) => {
- return{
+ return {
type: GlobalActionType.SET_HEADER_TITLE,
payload: text
}
@@ -125,7 +152,7 @@ export const setHeaderTitle = (text: string) => {
* Open post write
*/
export const openPostWrite = () => {
- return{
+ return {
type: GlobalActionType.OPEN_POST_WRITE
}
@@ -135,7 +162,7 @@ export const openPostWrite = () => {
* Close post write
*/
export const closePostWrite = () => {
- return{
+ return {
type: GlobalActionType.CLOSE_POST_WRITE
}
@@ -145,7 +172,7 @@ export const closePostWrite = () => {
* Show top loading
*/
export const showTopLoading = () => {
- return{
+ return {
type: GlobalActionType.SHOW_TOP_LOADING
}
@@ -155,17 +182,57 @@ export const showTopLoading = () => {
* Hide top loading
*/
export const hideTopLoading = () => {
- return{
+ return {
type: GlobalActionType.HIDE_TOP_LOADING
}
}
+/**
+ * Show master loading
+ */
+export const showMasterLoading = () => {
+ return {
+ type: GlobalActionType.SHOW_MASTER_LOADING
+ }
+
+}
+
+/**
+ * Show send feedback
+ */
+export const showSendFeedback = () => {
+ return {
+ type: GlobalActionType.SHOW_SEND_FEEDBACK
+ }
+
+}
+
+/**
+ * Hide send feedback
+ */
+export const hideSendFeedback = () => {
+ return {
+ type: GlobalActionType.HIDE_SEND_FEEDBACK
+ }
+
+}
+
+/**
+ * Hide master loading
+ */
+export const hideMasterLoading = () => {
+ return {
+ type: GlobalActionType.HIDE_MASTER_LOADING
+ }
+
+}
+
/**
* Store temp data
*/
export const temp = (data: any) => {
- return{
+ return {
type: GlobalActionType.TEMP,
payload: data
}
@@ -176,7 +243,7 @@ export const temp = (data: any) => {
* Clear temp data
*/
export const clearTemp = () => {
- return{
+ return {
type: GlobalActionType.CLEAR_TEMP
}
@@ -185,7 +252,43 @@ export const clearTemp = () => {
// - Load data for guest
export const loadDataGuest = () => {
// tslint:disable-next-line:no-empty
- return (dispatch: any,getState: Function) => {
+ return (dispatch: any, getState: Function) => {
}
}
+
+/**
+ * Show error report dialog
+ */
+const showErrorReport = (message: string) => {
+ const appElement = document.getElementById('app')
+ const masterElement = document.getElementById('master')
+ const container = document.createElement('div')
+ const div = document.createElement('div')
+ div.innerHTML = message
+ container.style.position = '100000'
+ container.style.position = 'fixed'
+ container.style.backgroundColor = '#32c3e4b8'
+ container.style.width = '100%'
+ container.style.height = '100%'
+ container.style.display = 'flex'
+ container.style.alignItems = 'center'
+ container.style.alignItems = 'center'
+ container.style.flexDirection = 'row'
+ container.appendChild(div)
+
+ appElement!.insertBefore(container, masterElement)
+}
+
+/**
+ * Create send feedback serevr request model
+ */
+const createFeedbackRequest = (userId: string) => {
+ const requestId = StringAPI.createServerRequestId(ServerRequestType.CommonSendFeedback, userId)
+ return new ServerRequestModel(
+ ServerRequestType.CommonSendFeedback,
+ requestId,
+ '',
+ ServerRequestStatusType.Sent
+ )
+}
diff --git a/src/actions/serveActions.ts b/src/actions/serverActions.ts
similarity index 94%
rename from src/actions/serveActions.ts
rename to src/actions/serverActions.ts
index d650e19..818b6e0 100644
--- a/src/actions/serveActions.ts
+++ b/src/actions/serverActions.ts
@@ -15,7 +15,7 @@ import { SocialError } from 'core/domain/common/socialError'
* @param {Request} request
*/
export const sendRequest = (request: ServerRequestModel) => {
- return { type: ServerActionType.ADD_REQUEST, payload: request }
+ return { type: ServerActionType.ADD_REQUEST, payload: {request} }
}
diff --git a/src/api/CircleAPI.ts b/src/api/CircleAPI.ts
deleted file mode 100644
index 6c90ebc..0000000
--- a/src/api/CircleAPI.ts
+++ /dev/null
@@ -1,47 +0,0 @@
-import { Circle, UserTie } from 'core/domain/circles'
-
-/**
- * Get the circles' id which the specify users is in that circle
- * @param {object} circles
- * @param {string} followingId
- */
-export const getUserBelongCircles = (circles: {[circleId: string]: Circle},followingId: string) => {
- let userBelongCircles: string[] = []
- Object.keys(circles).forEach((cid) => {
- if (cid.trim() !== '-Followers' && circles[cid].users) {
- let isExist = Object.keys(circles[cid].users).indexOf(followingId) > -1
- if (isExist) {
- userBelongCircles.push(cid)
- }
- }
- })
-
- return userBelongCircles
-}
-
-/**
- * Get the following users
- * @param {object} circles
- */
-export const getFollowingUsers = (circles: {[circleId: string]: Circle}) => {
- let followingUsers: {[userId: string]: UserTie} = {}
- Object.keys(circles).forEach((cid) => {
- if (cid.trim() !== '-Followers' && circles[cid].users) {
- Object.keys(circles[cid].users).forEach((userId) => {
- let isExist = Object.keys(followingUsers).indexOf(userId) > -1
- if (!isExist) {
- followingUsers[userId] = {
- ...circles[cid].users[userId]
- }
- }
- })
-
- }
- })
- return followingUsers
-}
-
-export default {
- getUserBelongCircles,
- getFollowingUsers
-}
diff --git a/src/api/CommonAPI.ts b/src/api/CommonAPI.ts
index 4db139f..ceb31dc 100644
--- a/src/api/CommonAPI.ts
+++ b/src/api/CommonAPI.ts
@@ -1,17 +1,15 @@
+import * as moment from 'moment'
/**
* Log the data
* @param title log title
* @param data log data object
*/
-const logger = (title: string, data: any, trace?: boolean) => {
+const logger = (title: string, data: any) => {
const randomColor = getRandomColor()
- if (trace) {
- console.trace()
- }
- console.log(`\n\n\n%c ${title} :\n`, `color:${getRandomColor()};font-size:15`)
- console.log('%c =========================================', `color:${randomColor}`)
- console.log(data)
- console.log('%c =========================================', `color:${randomColor}`)
+
+ console.log(`\n\n%c ======= ${title} ======= %c${moment().format('HH:mm:ss SSS')} \n`, `color:${getRandomColor()};font-size:15`
+ , `color:${getRandomColor()};font-size:15`, data,`\n\n =========================================`)
+
}
/**
diff --git a/src/assets/fonts/Flaticon.eot b/src/assets/fonts/Flaticon.eot
new file mode 100644
index 0000000000000000000000000000000000000000..32ec59033fcf2c720ec29153f28bca6ec562af75
GIT binary patch
literal 2902
zcmds3Uu;uV82?W1?Y&z!%I(tKJLtf>Zmb=!uD$Krg)9PL>kNWJaD<>iYw6mNt!=gr
zhk>LICK8``af!T{5KSP#uqT5rdoTux`k+LVpot;jjYMPcfhhHN?!D{34Se^sC*R+D
zzTf@6bME<$w-H@&5ixQQ9}aQ~CIihS#<@dBOhTksdhTnDvAYg^O;@7|C25vYRH7M5
zQ-Sg@x#=inC`*f`WgZ%xjzcp~3-IDTI)(9zP{^cV$UNZsm7wO~H&K}cI+9GjcDTG#
zZ6|VFgtmL~*pM;#*Bcc$oq+sSdM;J`?MWw>f5JSNK3mes!^Vh&KG?-D=2A;Vym}G#5pK_?<}&|0_|}I|B696278XkW{K*Bx=h-cq?}qo&9e2mx
z+&uc2+N`SlSbl#IcCu(?)j@0(VvAigERX+cWtBo}RWw)PkE{)+scECV>k(s)E
zNID-P`#ZAn=keKXKRX7AuhLB-@q9|4e4`=~sz#txsZ<_p=309&sTP>=5Y1uW$wU0l
zhq=dTr~P}EZnLc{&u%&Vj<=B!UWbp^6cQm*=mw*q(G^*wN5&1wd4F_8aDb&70#`e^
zdPSDl-=ix?=OZKPiFyK2Pp{|VJJZu_>ghEPi()nG8hcl^qgsB%9VXi0?~la|wbSbs
zdi^0b9E(Sd?LwzlQVmt>iFX*PSAt825s&rv`rWM4%T6kqrmLdd+J4j3;Zha3%_WQ4
z_7fAz(w3?85*V^djoqfFxSm
zl|a2gf{{+GH^lss+#CO-4%Luxr!M$k3);%DsAEwJrLvIo*CE*yZze
z;j>oDEyo|sya4=zcJ+VCb$U`=nGBop8>fHbOunemz%NIV|L;$
z?xO94`?L?JdL*D~KGq4GC{5nWaL#158yHaAUmB`^!RL#|eUq3zUzDHV*Bi_IfobPH
zK3txBxaoTJtG^Ye#kv6)?!>gsJMeWoZ}S51eP{C`wJ_^8;5qZ_-9f&(?^8&qud(rX{;q#}>J4t75o0qWuemZ~_r%30}?#!SG%AqyVQRg&H
zxsDym+ny2H4SqkoQqbqn8qtA5@!b4OHdoSv=>gpcM@Dw*`-`b`4z_iDQF1m_nn@SX
zYc(}mM>E;Q*%Ugiq}gVbOgaw~88bF-w{+Tr*}SBsjUW$$z&BXMNy$RKlq}3=GrAE9
z>wEOI&|o96!N?#-`dozn+4vpL%rDFo@_INN35CO9{kf}EZ+LV+TTrw01060Z>>zm`#UmitjQpbRWF0U_96l19A_i^*!3Zvxv(U
literal 0
HcmV?d00001
diff --git a/src/assets/fonts/Flaticon.ttf b/src/assets/fonts/Flaticon.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..83df41ba3805753a765cc7a3aba6e26557a54d39
GIT binary patch
literal 2724
zcmds3&u&V#+IKajUu>*-?uN^x=Q2~)S6)g>g1|eF}y2i1C65Dbd
z8Y+-{s8rNbFO5`gm8w<(iHe*mddZ=xC~A9XQGXy>sY2q0)T*Kf)W-d0z1V9L_yaoD
z_`P}W&Ae~FH?yoD#Aa`{rS{l=HGkY
z`jAQ_a=40xrLsSNY607!4PAHqH2M10iHFqTfPv`8%Dc-ASzUJ!TgSMKYHo85
zTd%HDsAj-FU&-E_rlo`SlhZWwKxWzwP{_21>=*Vv_p%q+94yn8d`R2q9iSyAc(NMf
za38m$b5m!iLi(Rl4Fj+pfX|LV$LI^r6WSH@n|!?|8egCHUTf|oMtqfC5{dIEK{8B4
zCRB|esambx+sdt0V^SkA<0)FxAhPiok7xbwq`AjwkM(<-Zn5nw&u%*WjyJ&wufvCI
z7DUJty3S~HVoet5fpJ}O-kn$z98l@Hz|Br>UXvyE&%_$&d|*U9QBNT1>GxcEYi^Fs
zZd~=SC|1L+v36xAs^v%CF{0i6!C2f-yS;9q-ydRQv3S(jDRg@!)ljv*c$cAiC4_Vt
z@z`L$-_5$c?3AKux+==;oi|)vE>)2`T(YR`JUOjwJW|?kudd!+y?SM3Wp?~@;*P4T
zsv>o^w+RSURH3cCQ&Q9;Mli@Sh+DnA@%74;mBi`sSv$TCJpB&ZO<|%$06#6E$(kIf
zL8|GpX&-zN-Uq%$8>nIWtzq%qXu`J+PcIq|cnP4sH#I)$?fvZO_*~SD^EO0rA`k@b
zSbsA|+E}zZ;FWBQ);S)GVcn^7Q)lZWRW4UFrNQLI8n=?7vGvun$>k{
zFu_fmKzFske+uLZ&>29x#?Q{t-l?orFH`_+=*#Rci`=I!O{ib
z`_9ruYGbwAkUxjQ!j@fv{W!mI#CEJ7L$B$K6nfdx9mu<2=>k2Ed$ATHBIYkkcaqNB
zmM&ragLH@rxZBTDiRLLwIVzKmI;U~Ub?neEMQEIcp&vw43icdjhz=Es=S%b1Tv-pM
zhjb$x86VaU7E|dQd`W;vVVQXZ7bp+ILaIEUE-c&H3A++fN!LZlahseIaw%WGrAE9>-+S_si8(nFfq*l>k?@~RbRtt)nlI$_a5xeQhr_V6g0nqu{f5Wa&oeuzP+ArulISM{l4$o``b^7FN*~b02h%B
z)K~8+7gzWHTP#+P57cdiIeiEN5kptaH_*Zo0HhMeo)D<-*9ZkSo|6aw4u-%B=Dfxi
zbrjqq$u!9AfgIsGv=BD|Ckg6^bQmkILZJY7L0lRi>S7>*p|rbSWTX|t<6y836Kb|W
z*l5sv1u>9>913Ft2s(Zi>4}L?PKDegj42Q_!cRaeE`bYmIKLkpg>aKdisz)lzDOqI
zHm>SG07w*a;(4%NC*(Ily~^@i88tB>DH#Bz38-;~NHh|LC8dsVQ4B>vv{J*zZFB$F
zMCr9uP@KoYTr;+0uVjhx#dDyzuM7M_1ey^laIznIhgk*4G1SH@15Xw)s8a>_mEqcc
z3tC>o9O
z_#%Xb5DCicBp*%;>NhX#NgY!lM8_Vyng-39?M0?g5XX(G=iu?c>*4<
zjc33YIg4{yodHGpB2D&E$v7ca;BV+
z7ihOHbQe{&i-v5P0!J^IxxDWl(Ci``iOmA(gaF%J$sA{AB7^5P?N&!6;jV7*vpmwP
zV*DWpF{UcO&*IzosYte6-{3+=$mK^*W;CK}kxuic__gFKr!}9Ba!oYkQ|!H&!ZVjB
z=O40F`tlncg0auH9a)@LLk_aJ9o`u$$tmlJy!L(@7bMsd)jHVJY0D`iQOA32au$OY
zM?)ALyK5|zlv3I#>>=}=ZT)&x_IIgq@`2KU*9OsvOxlNv$IBJr`%Pjj
zU$)P+NL=U!@16fhDtotEct}t8(=*P751Psg+e&nlOSHef3p#w#d%nK*qgMGh*|UZ!
zR`bX^%N0{bhE%Xp6nEh8RcV^I%5{xd1lLZLUhUlB#tf$it5-BfFC^Gqvvp`i7p(17
z!(XIduYMKao5nQEa=GXEs*Xc`<<4J!U$Ons)s3lk*htX{uJ>HI@$Q1LHm%7;+=`tP
z&+^bSX}cpGu-Z&hbq~#9IG6eFn;1S@-zg;f->jb%UNA2d^OoG%S#oBkyhUIoVR?IR7>GFlnWE&bE)mBf~>x1O=gleRWo7#{0p
zo&V;;Vc)8}k$4E#$K4+}@>0V%r!nPOfd8(UbAOXE9wY4q594Bj3DiQ?mu$6zDH_c48&US6y2fgo#j9MBf#a%L
h{;&iBy&3nPS70E!@7L*5w8d4=D
+
+
+
+
+Created by FontForge 20160405 at Sun Jan 14 05:05:09 2018
+ By Apache
+Copyright (c) 2018, Apache
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/circle/CircleComponent.tsx b/src/components/circle/CircleComponent.tsx
index 3d2bd24..f13079d 100644
--- a/src/components/circle/CircleComponent.tsx
+++ b/src/components/circle/CircleComponent.tsx
@@ -29,7 +29,7 @@ import * as circleActions from 'actions/circleActions'
import { ICircleComponentProps } from './ICircleComponentProps'
import { ICircleComponentState } from './ICircleComponentState'
-import { Circle } from 'core/domain/circles'
+import { Circle, UserTie } from 'core/domain/circles'
import { Profile } from 'core/domain/users/profile'
/**
@@ -135,21 +135,21 @@ export class CircleComponent extends Component {
- const { users } = this.props.circle
- const { userInfo } = this.props
+ const { usersOfCircle } = this.props
let usersParsed: any = []
- if (users) {
- Object.keys(users).forEach((key, index) => {
- const { fullName } = users[key]
- let avatar = userInfo && userInfo[key] ? userInfo[key].avatar || '' : ''
+ if (usersOfCircle) {
+ console.trace('usersOfCircle',usersOfCircle)
+ Object.keys(usersOfCircle).forEach((userId, index) => {
+ const { fullName } = usersOfCircle[userId]
+ let avatar = usersOfCircle && usersOfCircle[userId] ? usersOfCircle[userId].avatar || '' : ''
usersParsed.push( }
- onClick={() => this.props.goTo!(`/${key}`)}
+ leftAvatar={ }
+ onClick={() => this.props.goTo!(`/${userId}`)}
/>)
})
@@ -176,6 +176,7 @@ export class CircleComponent extends Component
@@ -203,7 +204,7 @@ export class CircleComponent extends Component
{this.props.circle.name}}
leftIcon={ }
- rightIconButton={this.rightIconMenu}
+ rightIconButton={!circle.isSystem ? this.rightIconMenu : null}
initiallyOpen={false}
onClick={this.handleToggleCircle}
open={this.state.open}
@@ -259,10 +260,23 @@ const mapDispatchToProps = (dispatch: any, ownProps: ICircleComponentProps) => {
*/
const mapStateToProps = (state: any, ownProps: ICircleComponentProps) => {
const {circle, authorize, server} = state
+ const {userTies} = circle
const { uid } = state.authorize
const circles: { [circleId: string]: Circle } = circle ? (circle.circleList || {}) : {}
const currentCircle = (circles ? circles[ownProps.id] : {}) as Circle
+
+ let usersOfCircle: {[userId: string]: UserTie} = {}
+ Object.keys(userTies).forEach((userTieId) => {
+ const theUserTie = userTies[userTieId] as UserTie
+ if (theUserTie.circleIdList!.indexOf(ownProps.id) > -1) {
+ usersOfCircle = {
+ ...usersOfCircle,
+ [userTieId]: theUserTie
+ }
+ }
+ })
return {
+ usersOfCircle,
openSetting: state.circle ? (currentCircle ? (currentCircle.openCircleSettings || false) : false) : false,
userInfo: state.user.info
diff --git a/src/components/circle/ICircleComponentProps.ts b/src/components/circle/ICircleComponentProps.ts
index 1618ad3..b48e234 100644
--- a/src/components/circle/ICircleComponentProps.ts
+++ b/src/components/circle/ICircleComponentProps.ts
@@ -1,6 +1,6 @@
import { Comment } from 'core/domain/comments'
import { Profile } from 'core/domain/users'
-import { Circle } from 'core/domain/circles'
+import { Circle, UserTie } from 'core/domain/circles'
export interface ICircleComponentProps {
@@ -45,12 +45,9 @@ export interface ICircleComponentProps {
deleteCircle?: Function
/**
- * Users profile
- *
- * @type {{[userId: string]: Profile}}
- * @memberof ICircleComponentProps
+ * Users of current circle
*/
- userInfo?: {[userId: string]: Profile}
+ usersOfCircle?: {[userId: string]: UserTie}
/**
* Close setting box of circle
diff --git a/src/components/findPeople/IFindPeopleComponentProps.ts b/src/components/findPeople/IFindPeopleComponentProps.ts
index e00b554..c14902a 100644
--- a/src/components/findPeople/IFindPeopleComponentProps.ts
+++ b/src/components/findPeople/IFindPeopleComponentProps.ts
@@ -20,6 +20,6 @@ export interface IFindPeopleComponentProps {
/**
* If there are more people {true} or not {false}
*/
- hasMorePeople: boolean
+ hasMorePeople?: boolean
}
diff --git a/src/components/followers/FollowersComponent.tsx b/src/components/followers/FollowersComponent.tsx
index c1eac4c..07a0b59 100644
--- a/src/components/followers/FollowersComponent.tsx
+++ b/src/components/followers/FollowersComponent.tsx
@@ -83,8 +83,9 @@ const mapStateToProps = (state: any,ownProps: IFollowersComponentProps) => {
const {circle, authorize, server} = state
const { uid } = state.authorize
const circles: { [circleId: string]: Circle } = circle ? (circle.circleList || {}) : {}
+ const followers = circle ? circle.userTieds : {}
return{
- followers: circles ? circles.userTieds : {}
+ followers
}
}
diff --git a/src/components/following/FollowingComponent.tsx b/src/components/following/FollowingComponent.tsx
index 053cf29..e122891 100644
--- a/src/components/following/FollowingComponent.tsx
+++ b/src/components/following/FollowingComponent.tsx
@@ -6,11 +6,11 @@ import PropTypes from 'prop-types'
// - Import app components
import UserBoxList from 'components/userBoxList'
+import { Circle } from 'core/domain/circles'
+
// - Import API
-import CircleAPI from 'api/CircleAPI'
import { IFollowingComponentProps } from './IFollowingComponentProps'
import { IFollowingComponentState } from './IFollowingComponentState'
-import { Circle } from 'core/domain/circles';
// - Import actions
diff --git a/src/components/home/HomeComponent.tsx b/src/components/home/HomeComponent.tsx
index 06c3550..b85ba61 100644
--- a/src/components/home/HomeComponent.tsx
+++ b/src/components/home/HomeComponent.tsx
@@ -26,7 +26,6 @@ import PostPage from 'components/postPage'
import People from 'components/people'
// - Import API
-import CircleAPI from 'api/CircleAPI'
// - Import actions
// - Import actions
@@ -130,7 +129,7 @@ export class HomeComponent extends Component
@@ -147,7 +146,7 @@ export class HomeComponent extends Component } />
} />
- } />
+ showSendFeedback()} style={{ color: 'rgb(117, 117, 117)' }} leftIcon={ } />
@@ -175,6 +174,7 @@ const mapDispatchToProps = (dispatch: any, ownProps: IHomeComponentProps) => {
dispatch(notifyActions.dbGetNotifications())
dispatch(circleActions.dbGetCircles())
dispatch(circleActions.dbGetUserTies())
+ dispatch(circleActions.dbGetFollowers())
},
clearData: () => {
@@ -192,7 +192,10 @@ const mapDispatchToProps = (dispatch: any, ownProps: IHomeComponentProps) => {
defaultDataEnable: () => {
dispatch(globalActions.defaultDataEnable())
},
- goTo: (url: string) => dispatch(push(url))
+ goTo: (url: string) => dispatch(push(url)),
+ showSendFeedback: () => dispatch(globalActions.showSendFeedback()),
+ hideSendFeedback: () => dispatch(globalActions.hideSendFeedback())
+
}
}
@@ -223,7 +226,7 @@ const mapStateToProps = (state: any, ownProps: IHomeComponentProps) => {
mergedPosts,
global,
hasMorePosts,
- loaded: user.loaded && post.loaded && imageGallery.loaded && notify.loaded && circle.loaded
+ loaded: user.loaded && imageGallery.loaded && notify.loaded && circle.loaded
}
}
diff --git a/src/components/home/IHomeComponentProps.ts b/src/components/home/IHomeComponentProps.ts
index 736ad85..cb4367c 100644
--- a/src/components/home/IHomeComponentProps.ts
+++ b/src/components/home/IHomeComponentProps.ts
@@ -98,4 +98,14 @@ export interface IHomeComponentProps {
*/
loaded?: boolean
+ /**
+ * Show send feedback form
+ */
+ showSendFeedback: () => any
+
+ /**
+ * Hide send feedback form
+ */
+ hideSendFeedback: () => any
+
}
diff --git a/src/components/master/IMasterComponentProps.ts b/src/components/master/IMasterComponentProps.ts
index 63e37eb..ad15a0f 100644
--- a/src/components/master/IMasterComponentProps.ts
+++ b/src/components/master/IMasterComponentProps.ts
@@ -1,4 +1,4 @@
-import { User } from 'core/domain/users';
+import { User } from 'core/domain/users'
export interface IMasterComponentProps {
/**
* Close gloal message
@@ -98,4 +98,15 @@ export interface IMasterComponentProps {
* @memberof IMasterProps
*/
uid: string
+
+ /**
+ * Show master loading
+ */
+ showMasterLoading?: () => any
+
+ /**
+ * Hide master loading
+ */
+ hideMasterLoading?: () => any
+
}
diff --git a/src/components/master/MasterComponent.tsx b/src/components/master/MasterComponent.tsx
index 4d356aa..6214e3d 100644
--- a/src/components/master/MasterComponent.tsx
+++ b/src/components/master/MasterComponent.tsx
@@ -10,6 +10,7 @@ import LinearProgress from 'material-ui/LinearProgress'
// - Import components
import MasterLoading from 'components/masterLoading'
+import SendFeedback from 'components/sendFeedback'
import MasterRouter from 'routes/MasterRouter'
import { IMasterComponentProps } from './IMasterComponentProps'
import { IMasterComponentState } from './IMasterComponentState'
@@ -79,9 +80,20 @@ export class MasterComponent extends Component {
- const {global, clearData, loadDataGuest, defaultDataDisable, defaultDataEnable, login, logout } = this.props
+ const {
+ global,
+ clearData,
+ loadDataGuest,
+ defaultDataDisable,
+ defaultDataEnable,
+ login,
+ logout,
+ showMasterLoading,
+ hideMasterLoading
+ } = this.props
if (user) {
login(user.uid,isVerifide)
+ hideMasterLoading!()
this.setState({
loading: false,
isVerifide: true
@@ -89,6 +101,7 @@ export class MasterComponent extends Component
-
+
-
+
{
},
loadDataGuest: () => {
dispatch(globalActions.loadDataGuest())
- }
+ },
+ showMasterLoading: () => dispatch(globalActions.showMasterLoading()),
+ hideMasterLoading: () => dispatch(globalActions.hideMasterLoading())
}
}
diff --git a/src/components/masterLoading/MasterLoadingComponent.tsx b/src/components/masterLoading/MasterLoadingComponent.tsx
index f3f9529..324b690 100644
--- a/src/components/masterLoading/MasterLoadingComponent.tsx
+++ b/src/components/masterLoading/MasterLoadingComponent.tsx
@@ -2,13 +2,14 @@
import React, { Component } from 'react'
import CircularProgress from 'material-ui/CircularProgress'
import Dialog from 'material-ui/Dialog'
+import RefreshIndicator from 'material-ui/RefreshIndicator'
import { IMasterLoadingComponentProps } from './IMasterLoadingComponentProps'
import { IMasterLoadingComponentState } from './IMasterLoadingComponentState'
// - Import app components
// - Create MasterLoading component class
-export default class MasterLoadingComponent extends Component {
+export default class MasterLoadingComponent extends Component {
// Constructor
constructor (props: IMasterLoadingComponentProps) {
@@ -19,27 +20,19 @@ export default class MasterLoadingComponent extends Component
-
-
-
-
+
)
}
diff --git a/src/components/sendFeedback/ISendFeedbackComponentProps.ts b/src/components/sendFeedback/ISendFeedbackComponentProps.ts
new file mode 100644
index 0000000..77f34e0
--- /dev/null
+++ b/src/components/sendFeedback/ISendFeedbackComponentProps.ts
@@ -0,0 +1,30 @@
+import { Feed } from 'core/domain/common/feed'
+import { ServerRequestModel } from 'models/server/serverRequestModel'
+import { Profile } from 'core/domain/users'
+
+export interface ISendFeedbackComponentProps {
+ /**
+ * Whether send feedback is diplayed
+ */
+ sendFeedbackStatus?: boolean
+
+ /**
+ * Send feedback
+ */
+ sendFeed?: (feed: Feed) => any
+
+ /**
+ * Hide feedback form
+ */
+ hideFeedback: () => any
+
+ /**
+ * The server request of send feedback
+ */
+ sendFeedbackRequest: ServerRequestModel
+
+ /**
+ * Current user profile
+ */
+ currentUser: Profile
+}
diff --git a/src/components/sendFeedback/ISendFeedbackComponentState.ts b/src/components/sendFeedback/ISendFeedbackComponentState.ts
new file mode 100644
index 0000000..77d1311
--- /dev/null
+++ b/src/components/sendFeedback/ISendFeedbackComponentState.ts
@@ -0,0 +1,7 @@
+
+export interface ISendFeedbackComponentState {
+ /**
+ * Feedback text
+ */
+ feedText: string
+}
diff --git a/src/components/sendFeedback/SendFeedbackComponent.tsx b/src/components/sendFeedback/SendFeedbackComponent.tsx
new file mode 100644
index 0000000..4ce20e4
--- /dev/null
+++ b/src/components/sendFeedback/SendFeedbackComponent.tsx
@@ -0,0 +1,232 @@
+// - Import react components
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
+import { connect } from 'react-redux'
+import Paper from 'material-ui/Paper'
+import TextField from 'material-ui/TextField'
+import IconButton from 'material-ui/IconButton'
+import SvgHappy from 'material-ui/svg-icons/image/tag-faces'
+import SvgSad from 'material-ui/svg-icons/action/face'
+import SvgClose from 'material-ui/svg-icons/content/clear'
+import RefreshIndicator from 'material-ui/RefreshIndicator'
+
+// - Import app components
+
+// - Import API
+
+// - Import actions
+import { globalActions } from 'actions'
+
+import { Feed } from 'core/domain/common'
+import { ISendFeedbackComponentProps } from './ISendFeedbackComponentProps'
+import { ISendFeedbackComponentState } from './ISendFeedbackComponentState'
+import { FeedType } from 'core/domain/common/feedType'
+import { ServerRequestModel } from 'models/server'
+import { Profile } from 'core/domain/users'
+import StringAPI from 'api/StringAPI'
+import { ServerRequestType } from 'constants/serverRequestType'
+import { User } from 'core/domain/users'
+import { ServerRequestStatusType } from 'actions/serverRequestStatusType'
+
+/**
+ * Create component class
+ */
+export class SendFeedbackComponent extends Component
{
+
+ /**
+ * Component constructor
+ * @param {object} props is an object properties of component
+ */
+ constructor(props: ISendFeedbackComponentProps) {
+ super(props)
+
+ // Defaul state
+ this.state = {
+ feedText: ''
+ }
+
+ // Binding functions to `this`
+ this.handleFeedText = this.handleFeedText.bind(this)
+ this.getFeedbackForm = this.getFeedbackForm.bind(this)
+ this.mainForm = this.mainForm.bind(this)
+ this.loadingForm = this.loadingForm.bind(this)
+ this.successForm = this.successForm.bind(this)
+ this.errorForm = this.errorForm.bind(this)
+ }
+
+ handleFeedText = (event: any) => {
+ const target = event ? event.target : {}
+ const value = target ? target.value : ''
+ if (value) {
+ this.setState({
+ feedText: value
+ })
+
+ }
+ }
+
+ handleSendFeed = (feedType: FeedType) => {
+ const { sendFeed, currentUser } = this.props
+ const { feedText } = this.state
+ sendFeed!(new Feed('', feedText, feedType, currentUser))
+ }
+
+ mainForm = () => {
+ const { sendFeedbackStatus, hideFeedback, sendFeed, sendFeedbackRequest } = this.props
+ const { feedText } = this.state
+ return (
+
+
+
+ this.handleSendFeed(FeedType.Sad)}
+ >
+
+ this.handleSendFeed(FeedType.Acceptable)}
+ >
+
+ this.handleSendFeed(FeedType.Happy)}
+ >
+
+ this.handleSendFeed(FeedType.Awesome)}
+ >
+
+
+
+
)
+ }
+
+ loadingForm = () => {
+ return (
+
+ Your feedback is sending!
+
+
+
+
+
+
)
+ }
+
+ successForm = () => {
+ return (We appreciate your kind support as always ;)
)
+ }
+
+ errorForm = () => {
+ return (Error in sending feedback :(
)
+ }
+
+ getFeedbackForm = () => {
+ const { sendFeedbackStatus, hideFeedback, sendFeed, sendFeedbackRequest } = this.props
+ const { feedText } = this.state
+
+ if (sendFeedbackRequest) {
+ switch (sendFeedbackRequest.status) {
+ case ServerRequestStatusType.Sent:
+ return this.loadingForm()
+
+ case ServerRequestStatusType.OK:
+ return this.successForm()
+
+ case ServerRequestStatusType.Error:
+ return this.errorForm()
+
+ default:
+ return this.mainForm()
+ }
+ } else {
+ return this.mainForm()
+ }
+ }
+
+ /**
+ * Reneder component DOM
+ * @return {react element} return the DOM which rendered by component
+ */
+ render() {
+ const { sendFeedbackStatus, hideFeedback, sendFeed, sendFeedbackRequest } = this.props
+ const { feedText } = this.state
+
+ return (
+
+
+
+ hideFeedback()}
+ >
+
+
+
+ {this.getFeedbackForm()}
+
+
+
+ )
+ }
+}
+
+/**
+ * Map dispatch to props
+ * @param {func} dispatch is the function to dispatch action to reducers
+ * @param {object} ownProps is the props belong to component
+ * @return {object} props of component
+ */
+const mapDispatchToProps = (dispatch: Function, ownProps: ISendFeedbackComponentProps) => {
+ return {
+ sendFeed: (feed: Feed) => (dispatch(globalActions.dbSendFeed(feed))),
+ hideFeedback: () => dispatch(globalActions.hideSendFeedback())
+ }
+}
+
+/**
+ * Map state to props
+ * @param {object} state is the obeject from redux store
+ * @param {object} ownProps is the props belong to component
+ * @return {object} props of component
+ */
+const mapStateToProps = (state: any, ownProps: ISendFeedbackComponentProps) => {
+
+ const { server, global, authorize, user } = state
+ const { request } = server
+ const { uid } = authorize
+ const currentUser: User = user.info && user.info[uid] ? { ...user.info[uid], userId: uid } : {}
+ const { sendFeedbackStatus } = global
+ const sendFeedbackRequest: ServerRequestModel = request ? request[StringAPI.createServerRequestId(ServerRequestType.CommonSendFeedback, uid)] : null
+
+ return {
+ sendFeedbackStatus,
+ sendFeedbackRequest,
+ currentUser
+ }
+}
+
+// - Connect component to redux store
+export default connect(mapStateToProps, mapDispatchToProps)(SendFeedbackComponent as any)
diff --git a/src/components/sendFeedback/index.ts b/src/components/sendFeedback/index.ts
new file mode 100644
index 0000000..3b51954
--- /dev/null
+++ b/src/components/sendFeedback/index.ts
@@ -0,0 +1,2 @@
+import SendFeedbackComponent from './SendFeedbackComponent'
+export default SendFeedbackComponent
diff --git a/src/components/signup/SignupComponent.tsx b/src/components/signup/SignupComponent.tsx
index 4d2e771..cde6261 100644
--- a/src/components/signup/SignupComponent.tsx
+++ b/src/components/signup/SignupComponent.tsx
@@ -281,4 +281,4 @@ const mapStateToProps = (state: any,ownProps: ISignupComponentProps) => {
}
// - Connect component to redux store
-export default withRouter(connect(mapStateToProps,mapDispatchToProps)(SignupComponent as any))
+export default withRouter(connect(mapStateToProps,mapDispatchToProps)(SignupComponent as any) as any)
diff --git a/src/components/userBox/IUserBoxComponentProps.ts b/src/components/userBox/IUserBoxComponentProps.ts
index 486f9c9..2e9b470 100644
--- a/src/components/userBox/IUserBoxComponentProps.ts
+++ b/src/components/userBox/IUserBoxComponentProps.ts
@@ -1,6 +1,8 @@
import { User } from 'core/domain/users'
import { Circle } from 'core/domain/circles/circle'
import { UserTie } from 'core/domain/circles'
+import { ServerRequestStatusType } from 'actions/serverRequestStatusType'
+import { ServerRequestModel } from 'models/server/serverRequestModel'
export interface IUserBoxComponentProps {
@@ -73,6 +75,11 @@ export interface IUserBoxComponentProps {
*/
fullName?: string
+ /**
+ * The `Following` circle identifier of current user
+ */
+ followingCircleId?: string
+
/**
* Create a circle
*
@@ -85,14 +92,37 @@ export interface IUserBoxComponentProps {
*
* @memberof IUserBoxComponentProps
*/
- addFollowingUser?: (cid: string,user: UserTie) => any
+ addUserToCircle?: (circleIds: string[],user: UserTie) => any
/**
- * Delete
- *
- * @memberof IUserBoxComponentProps
+ * Add referer user to the `Following` circle of current user
*/
- deleteFollowingUser?: (cid: string ,followingId: string) => any
+ followUser?: (circleId: string, userFollowing: UserTie) => any
+
+ /**
+ * Delete following user
+ */
+ deleteFollowingUser?: (followingId: string) => any
+
+ /**
+ * Set current user selected circles for referer user
+ */
+ setSelectedCircles?: (userId: string, circleList: string[]) => any
+
+ /**
+ * Remove current user selected circles for referer user
+ */
+ removeSelectedCircles?: (userId: string, circleList: string[]) => any
+
+ /**
+ * Open select circle box
+ */
+ openSelectCircles?: (userId: string) => any
+
+ /**
+ * Close select circle box
+ */
+ closeSelectCircles?: (userId: string) => any
/**
* Redirect page to [url]
@@ -100,4 +130,29 @@ export interface IUserBoxComponentProps {
* @memberof IUserBoxComponentProps
*/
goTo?: (url: string) => any
+
+ /**
+ * The status of following user server request
+ */
+ followRequest?: ServerRequestModel
+
+ /**
+ * The status of add to circle user server request
+ */
+ addToCircleRequest?: ServerRequestModel
+
+ /**
+ * The status of deleting following user server request
+ */
+ deleteFollowingUserRequest?: ServerRequestModel
+
+ /**
+ * Keep selected circles for refere user
+ */
+ selectedCircles?: string[]
+
+ /**
+ * Whether the select circles box for referer user is open
+ */
+ isSelecteCirclesOpen?: boolean
}
diff --git a/src/components/userBox/IUserBoxComponentState.ts b/src/components/userBox/IUserBoxComponentState.ts
index 7a6cbf2..045cdbe 100644
--- a/src/components/userBox/IUserBoxComponentState.ts
+++ b/src/components/userBox/IUserBoxComponentState.ts
@@ -33,22 +33,10 @@ export interface IUserBoxComponentState {
*/
anchorEl?: any
- /**
- * Circle list popover is open {true} or not {false}
- *
- * @type {boolean}
- * @memberof IUserBoxComponentState
- */
- open: boolean
-
/**
* Whether current user changed the selected circles for referer user
*
*/
disabledDoneCircles: boolean
- /**
- * Keep selected circles for refere user
- */
- selectedCircles: string[]
}
diff --git a/src/components/userBox/UserBoxComponent.tsx b/src/components/userBox/UserBoxComponent.tsx
index 686d2e5..e2155bd 100644
--- a/src/components/userBox/UserBoxComponent.tsx
+++ b/src/components/userBox/UserBoxComponent.tsx
@@ -1,5 +1,6 @@
// - Import react components
import React, { Component } from 'react'
+import moment from 'moment'
import { connect } from 'react-redux'
import PropTypes from 'prop-types'
import { push } from 'react-router-redux'
@@ -20,7 +21,6 @@ import { grey400, grey800, darkBlack, lightBlack } from 'material-ui/styles/colo
import UserAvatar from 'components/userAvatar'
// - Import API
-import CircleAPI from 'api/CircleAPI'
import StringAPI from 'api/StringAPI'
// - Import actions
@@ -31,12 +31,16 @@ import { IUserBoxComponentState } from './IUserBoxComponentState'
import { User } from 'core/domain/users'
import { UserTie, Circle } from 'core/domain/circles'
import { ServerRequestType } from 'constants/serverRequestType'
+import { ServerRequestStatusType } from 'actions/serverRequestStatusType'
+import { ServerRequestModel } from 'models/server'
/**
* Create component class
*/
export class UserBoxComponent extends Component {
-
+ /**
+ * Fields
+ */
static propTypes = {
/**
* User identifier
@@ -69,6 +73,7 @@ export class UserBoxComponent extends Component {
- const { userId, user } = this.props
+ handleDoneAddCircle = () => {
+ const { userId, user , addUserToCircle, selectedCircles, deleteFollowingUser} = this.props
const { avatar, fullName } = user
- if (checked) {
- this.props.addFollowingUser!(cid, { avatar, userId, fullName })
+ const {disabledDoneCircles} = this.state
+ if (!disabledDoneCircles) {
+ if (selectedCircles!.length > 0) {
+ addUserToCircle!(selectedCircles!, { avatar, userId, fullName })
+ } else {
+ deleteFollowingUser!(userId)
+ }
+ }
+ }
+
+ /**
+ * Handle follow user
+ */
+ onFollowUser = (event: any) => {
+ // This prevents ghost click
+ event.preventDefault()
+ const {isFollowed, followUser, followingCircleId, userId, user, followRequest } = this.props
+
+ if (followRequest && followRequest.status === ServerRequestStatusType.Sent) {
+ return
+ }
+ const { avatar, fullName } = user
+ if (!isFollowed) {
+ followUser!(followingCircleId!, { avatar, userId, fullName })
} else {
- this.props.deleteFollowingUser!(cid, userId)
+ this.onRequestOpenAddCircle()
}
}
@@ -130,8 +149,14 @@ export class UserBoxComponent extends Component {
+ const {setSelectedCircles, userId, userBelongCircles, closeSelectCircles} = this.props
+ setSelectedCircles!(userId, userBelongCircles!)
+ closeSelectCircles!(userId)
this.setState({
- open: false
+ circleName: ``,
+ disabledCreateCircle: true,
+ disabledAddToCircle: true,
+ disabledDoneCircles: true
})
}
@@ -139,9 +164,8 @@ export class UserBoxComponent extends Component {
- this.setState({
- open: true
- })
+ const { openSelectCircles, userId} = this.props
+ openSelectCircles!(userId)
}
/**
@@ -170,54 +194,40 @@ export class UserBoxComponent extends Component {
- const { userBelongCircles, circles } = this.props
- let selectedCircles = this.state.selectedCircles
+ const { userBelongCircles, circles, setSelectedCircles, selectedCircles, userId } = this.props
+ let newSelectedCircles = selectedCircles!.slice()
if (isInputChecked) {
- selectedCircles = [
- ...selectedCircles,
+
+ newSelectedCircles = [
+ ...selectedCircles!,
circleId
]
} else {
- const circleIndex = selectedCircles.indexOf(circleId)
- selectedCircles.splice(circleIndex, 1)
+ const circleIndex = selectedCircles!.indexOf(circleId)
+ newSelectedCircles.splice(circleIndex, 1)
}
+
+ setSelectedCircles!(userId, newSelectedCircles)
this.setState({
- selectedCircles: selectedCircles,
- disabledDoneCircles: !this.selectedCircleChange(selectedCircles)
+ disabledDoneCircles: !this.selectedCircleChange(newSelectedCircles)
})
}
- /**
- * Handle follow user
- */
- onFollowUser = (event: any) => {
- // This prevents ghost click
- event.preventDefault()
- this.onRequestOpenAddCircle()
- }
-
- /**
- * Add user to the circle/circles
- */
- onAddToCircle = () => {
-
- }
-
/**
* Create a circle list of user which belong to
*/
circleList = () => {
- let { circles, userId, userBelongCircles } = this.props
+ let { circles, userId, userBelongCircles, selectedCircles } = this.props
if (circles) {
- return Object.keys(circles).map((circleId, index) => {
- const {selectedCircles} = this.state
- let isBelong = selectedCircles!.indexOf(circleId) > -1
+ const parsedDate = Object.keys(circles).map((circleId, index) => {
+ let isBelong = selectedCircles ? selectedCircles!.indexOf(circleId) > -1 : false
+
// Create checkbox for selected/unselected circle
return
})
+
+ return parsedDate
}
}
@@ -260,6 +272,7 @@ export class UserBoxComponent extends Component
]
- const { isFollowed } = this.props
return (
-
+
1 ? `${this.props.belongCirclesCount} Circles` : ((this.props.firstBelongCircle) ? this.props.firstBelongCircle.name : 'Follow'))}
primary={true}
onTouchTap={this.onFollowUser}
+ disabled={
+ (followRequest ? followRequest.status === ServerRequestStatusType.Sent : false) ||
+ (deleteFollowingUserRequest ? deleteFollowingUserRequest.status === ServerRequestStatusType.Sent : false)
+ }
/>
@@ -316,7 +332,7 @@ export class UserBoxComponent extends Component {
return {
createCircle: (name: string) => dispatch(circleActions.dbAddCircle(name)),
- addFollowingUser: (circleIds: string[], user: UserTie) => dispatch(circleActions.dbUpdateUserInCircles(circleIds, user)),
- deleteFollowingUser: (cid: string, followingId: string) => dispatch(circleActions.dbDeleteFollowingUser(followingId)),
+ addUserToCircle: (circleIds: string[], user: UserTie) => dispatch(circleActions.dbUpdateUserInCircles(circleIds, user)),
+ followUser: (circleId: string, userFollowing: UserTie) => dispatch(circleActions.dbFollowUser(circleId, userFollowing)),
+ deleteFollowingUser: (followingId: string) => dispatch(circleActions.dbDeleteFollowingUser(followingId)),
+ setSelectedCircles: (userId: string, circleList: string[]) => dispatch(circleActions.setSelectedCircles(userId, circleList)),
+ removeSelectedCircles: (userId: string, circleList: string[]) => dispatch(circleActions.removeSelectedCircles(userId)),
+ openSelectCircles: (userId: string) => dispatch(circleActions.openSelectCircleBox(userId)),
+ closeSelectCircles: (userId: string) => dispatch(circleActions.closeSelectCircleBox(userId)),
goTo: (url: string) => dispatch(push(url))
}
@@ -381,13 +402,26 @@ const mapStateToProps = (state: any, ownProps: IUserBoxComponentProps) => {
const { circle, authorize, server } = state
const { uid } = authorize
const { request } = server
+
const circles: { [circleId: string]: Circle } = circle ? (circle.circleList || {}) : {}
const userBelongCircles = circle ? (circle.userTies[ownProps.userId] ? circle.userTies[ownProps.userId].circleIdList : []) : []
const isFollowed = userBelongCircles.length > 0
+ const followingCircleId = circles ? Object.keys(circles)
+ .filter((circleId) => circles[circleId].isSystem && circles[circleId].name === `Following`)[0] : ''
+ const followRequest: ServerRequestModel = request ? request[StringAPI.createServerRequestId(ServerRequestType.CircleFollowUser, ownProps.userId)] : null
+ const addToCircleRequest: ServerRequestModel = request ? request[StringAPI.createServerRequestId(ServerRequestType.CircleAddToCircle, ownProps.userId)] : null
+ const deleteFollowingUserRequest: ServerRequestModel = request ? request[StringAPI.createServerRequestId(ServerRequestType.CircleDeleteFollowingUser, ownProps.userId)] : null
+ const selectedCircles = circle.selectedCircles ? circle.selectedCircles[ownProps.userId] : []
+ const isSelecteCirclesOpen = circle.openSelecteCircles ? circle.openSelecteCircles[ownProps.userId] : []
+
return {
+ isSelecteCirclesOpen,
isFollowed,
+ selectedCircles,
circles,
+ followingCircleId,
userBelongCircles,
+ followRequest,
belongCirclesCount: userBelongCircles.length || 0,
firstBelongCircle: userBelongCircles ? (circles ? circles[userBelongCircles[0]] : {}) : {},
avatar: state.user.info && state.user.info[ownProps.userId] ? state.user.info[ownProps.userId].avatar || '' : '',
diff --git a/src/components/yourCircles/YourCirclesComponent.tsx b/src/components/yourCircles/YourCirclesComponent.tsx
index 7a9eb4a..d147c6c 100644
--- a/src/components/yourCircles/YourCirclesComponent.tsx
+++ b/src/components/yourCircles/YourCirclesComponent.tsx
@@ -45,9 +45,7 @@ export class YourCirclesComponent extends Component {
- if (key.trim() !== '-Followers') {
parsedCircles.push( )
- }
})
}
return parsedCircles
diff --git a/src/constants/circleActionType.ts b/src/constants/circleActionType.ts
index 6ad9cad..1854dd1 100644
--- a/src/constants/circleActionType.ts
+++ b/src/constants/circleActionType.ts
@@ -15,6 +15,10 @@ export enum CircleActionType {
DELETE_USER_FROM_CIRCLE = 'DELETE_USER_FROM_CIRCLE',
SHOW_SELECT_CIRCLE_BOX = 'SHOW_SELECT_CIRCLE_BOX',
HIDE_SELECT_CIRCLE_BOX = 'HIDE_SELECT_CIRCLE_BOX',
+ SET_SELECTED_CIRCLES_USER_BOX_COMPONENT = 'SET_SELECTED_CIRCLES_USER_BOX_COMPONENT',
+ REMOVE_SELECTED_CIRCLES_USER_BOX_COMPONENT = 'REMOVE_SELECTED_CIRCLES_USER_BOX_COMPONENT',
+ OPEN_SELECT_CIRCLES_USER_BOX_COMPONENT = 'OPEN_SELECT_CIRCLES_USER_BOX_COMPONENT',
+ CLOSE_SELECT_CIRCLES_USER_BOX_COMPONENT = 'CLOSE_SELECT_CIRCLES_USER_BOX_COMPONENT',
SHOW_FOLLOWING_USER_LOADING = 'SHOW_FOLLOWING_USER_LOADING',
HIDE_FOLLOWING_USER_LOADING = 'HIDE_FOLLOWING_USER_LOADING'
diff --git a/src/constants/globalActionType.ts b/src/constants/globalActionType.ts
index 437f73f..5216b84 100644
--- a/src/constants/globalActionType.ts
+++ b/src/constants/globalActionType.ts
@@ -12,6 +12,10 @@ export enum GlobalActionType {
SET_HEADER_TITLE = 'SET_HEADER_TITLE',
SHOW_TOP_LOADING = 'SHOW_TOP_LOADING',
HIDE_TOP_LOADING = 'HIDE_TOP_LOADING',
+ SHOW_MASTER_LOADING = 'SHOW_MASTER_LOADING',
+ HIDE_MASTER_LOADING = 'HIDE_MASTER_LOADING',
+ SHOW_SEND_FEEDBACK = 'SHOW_SEND_FEEDBACK',
+ HIDE_SEND_FEEDBACK = 'HIDE_SEND_FEEDBACK',
TEMP = 'TEMP',
CLEAR_TEMP = 'CLEAR_TEMP',
OPEN_POST_WRITE = 'OPEN_POST_WRITE',
diff --git a/src/constants/serverRequestType.ts b/src/constants/serverRequestType.ts
index ac36989..19cdb87 100644
--- a/src/constants/serverRequestType.ts
+++ b/src/constants/serverRequestType.ts
@@ -1,6 +1,8 @@
export enum ServerRequestType {
CircleAddToCircle = 'CircleAddToCircle',
CircleFollowUser = 'CircleFollowUser',
- CircleCreateTieUser = 'CircleCreateTieUser'
+ CircleCreateTieUser = 'CircleCreateTieUser',
+ CircleDeleteFollowingUser = 'CircleDeleteFollowingUser',
+ CommonSendFeedback = 'CommonSendFeedback'
}
diff --git a/src/core/domain/circles/circle.ts b/src/core/domain/circles/circle.ts
index 029c316..a5016c6 100644
--- a/src/core/domain/circles/circle.ts
+++ b/src/core/domain/circles/circle.ts
@@ -35,8 +35,8 @@ export class Circle extends BaseDomain {
public name: string
/**
- * Whether circle setting is open
+ * Whether it's configured by system
*/
- public openCircleSettings?: boolean
+ public isSystem: boolean
}
diff --git a/src/core/domain/common/feed.ts b/src/core/domain/common/feed.ts
new file mode 100644
index 0000000..3f555df
--- /dev/null
+++ b/src/core/domain/common/feed.ts
@@ -0,0 +1,34 @@
+import { BaseDomain } from 'core/domain/common'
+import { FeedType } from './feedType'
+import { User } from 'core/domain/users'
+
+export class Feed {
+
+ /**
+ * Constructor
+ */
+ constructor (
+ /**
+ * Feed identifier
+ */
+ public id?: string,
+
+ /**
+ * Feed text
+ */
+ public text?: string,
+
+ /**
+ * Feed type
+ */
+ public feedType?: FeedType,
+
+ /**
+ * The user who send the feedback
+ */
+ public user?: User
+
+ ) {
+ }
+
+}
diff --git a/src/core/domain/common/feedType.ts b/src/core/domain/common/feedType.ts
new file mode 100644
index 0000000..1d4c529
--- /dev/null
+++ b/src/core/domain/common/feedType.ts
@@ -0,0 +1,8 @@
+export enum FeedType {
+ Awesome = 'Awesome',
+ Happy = 'Happey',
+ Acceptable = 'Acceptable',
+ Sad = 'Sad',
+ Bug = 'Bug'
+
+}
diff --git a/src/core/domain/common/index.ts b/src/core/domain/common/index.ts
index bfbbe3c..4ac9b5d 100644
--- a/src/core/domain/common/index.ts
+++ b/src/core/domain/common/index.ts
@@ -1,7 +1,9 @@
import { SocialError } from './socialError'
import { BaseDomain } from './baseDomain'
+import { Feed } from './feed'
export {
SocialError,
- BaseDomain
-}
\ No newline at end of file
+ BaseDomain,
+ Feed
+}
diff --git a/src/core/services/circles/IUserTieService.ts b/src/core/services/circles/IUserTieService.ts
index 1dd5813..5578f4e 100644
--- a/src/core/services/circles/IUserTieService.ts
+++ b/src/core/services/circles/IUserTieService.ts
@@ -15,6 +15,12 @@ export interface IUserTieService {
tieUseres: (userTieSenderInfo: UserTie, userTieReceiveInfo: UserTie, circleIds: string[])
=> Promise
+ /**
+ * Update users tie
+ */
+ updateUsersTie: (userTieSenderInfo: UserTie, userTieReceiveInfo: UserTie, circleIds: string[])
+ => Promise
+
/**
* Remove users' tie
*/
diff --git a/src/core/services/common/ICommonService.ts b/src/core/services/common/ICommonService.ts
index 2a9f8b9..8b4cb78 100644
--- a/src/core/services/common/ICommonService.ts
+++ b/src/core/services/common/ICommonService.ts
@@ -1,4 +1,5 @@
import { User } from 'core/domain/users'
+import { Feed } from 'core/domain/common';
/**
* Common service interface
@@ -8,4 +9,8 @@ import { User } from 'core/domain/users'
*/
export interface ICommonService {
+ /**
+ * Post feedback
+ */
+ addFeed: (feed: Feed) => Promise
}
diff --git a/src/data/firestoreClient/services/circles/UserTieService.ts b/src/data/firestoreClient/services/circles/UserTieService.ts
index 956f67e..ead95d6 100644
--- a/src/data/firestoreClient/services/circles/UserTieService.ts
+++ b/src/data/firestoreClient/services/circles/UserTieService.ts
@@ -53,6 +53,32 @@ export class UserTieService implements IUserTieService {
})
}
+ /**
+ * Update users tie
+ */
+ public updateUsersTie: (userTieSenderInfo: UserTie, userTieReceiveInfo: UserTie, circleIds: string[])
+ => Promise = (userTieSenderInfo, userTieReceiveInfo, circleIds) => {
+ return new Promise((resolve, reject) => {
+
+ this._graphService
+ .updateGraph(
+ new Graph(
+ userTieSenderInfo.userId!,
+ 'TIE',
+ userTieReceiveInfo.userId!,
+ {...userTieSenderInfo},
+ {...userTieReceiveInfo},
+ {creationDate: Date.now(), circleIds}
+ )
+ ,'users'
+ ).then(() => {
+ resolve()
+
+ })
+ .catch((error: any) => reject(new SocialError(error.code, 'firestore/updateUsersTie :' + error.message)))
+ })
+ }
+
/**
* Remove users' tie
*/
@@ -89,7 +115,7 @@ export class UserTieService implements IUserTieService {
parsedData = {
...parsedData,
[rightUserInfo.userId!] : {
- ...node.rightMetadata,
+ ...rightUserInfo,
circleIdList: metadata ? metadata.circleIds : []
}
}
@@ -123,7 +149,7 @@ export class UserTieService implements IUserTieService {
parsedData = {
...parsedData,
[leftUserInfo.userId!] : {
- ...parsedData[leftUserInfo.userId!],
+ ...leftUserInfo,
circleIdList: []
}
}
diff --git a/src/data/firestoreClient/services/common/CommonService.ts b/src/data/firestoreClient/services/common/CommonService.ts
index 6de5cdd..4fdea8d 100644
--- a/src/data/firestoreClient/services/common/CommonService.ts
+++ b/src/data/firestoreClient/services/common/CommonService.ts
@@ -1,7 +1,7 @@
// - Import react components
-import { firebaseRef, firebaseAuth } from 'data/firebaseClient'
+import { firebaseRef, firebaseAuth, db } from 'data/firestoreClient'
-import { SocialError } from 'core/domain/common'
+import { SocialError, Feed } from 'core/domain/common'
import { ICommonService } from 'core/services/common'
import { injectable } from 'inversify'
@@ -15,4 +15,20 @@ import { injectable } from 'inversify'
@injectable()
export class CommonService implements ICommonService {
+ /**
+ * Post feedback
+ */
+ public addFeed: (feed: Feed)
+ => Promise = (feed) => {
+ return new Promise((resolve, reject) => {
+ let feedRef = db.collection(`feeds`).doc()
+ feedRef.set({ ...feed, id: feedRef.id })
+ .then(() => {
+ resolve(feedRef.id)
+ })
+ .catch((error: any) => {
+ reject(new SocialError(error.code, error.message))
+ })
+ })
+ }
}
diff --git a/src/data/firestoreClient/services/graphs/GraphService.ts b/src/data/firestoreClient/services/graphs/GraphService.ts
index 1e7dae4..1e6db68 100644
--- a/src/data/firestoreClient/services/graphs/GraphService.ts
+++ b/src/data/firestoreClient/services/graphs/GraphService.ts
@@ -34,17 +34,19 @@ export class GraphService implements IGraphService {
}
/**
- * Add graph
+ * Update graph
*/
public updateGraph: (graph: Graph, collection: string)
=> Promise = (graph, collection) => {
return new Promise((resolve,reject) => {
-
- let graphRef = db.collection(`graphs:${collection}`).doc()
- .set({...graph}).then((result) => {
- resolve()
- })
- .catch((error: any) => {
+ const graphData = this.getGraphs(collection, graph.leftNode, graph.edgeType, graph.rightNode)
+ .then((result) => {
+ graph.nodeId = result[0].nodeId
+ let graphRef = db.collection(`graphs:${collection}`).doc(result[0].nodeId)
+ .set({...graph}).then((result) => {
+ resolve()
+ })
+ }).catch((error: any) => {
reject(new SocialError(error.code,error.message))
})
})
@@ -114,19 +116,22 @@ export class GraphService implements IGraphService {
=> Promise = (collection, leftNode, edgeType, rightNode) => {
return new Promise((resolve,reject) => {
let graphsRef = db.collection(`graphs:${collection}`)
- let query
- if (leftNode) {
- query = graphsRef.where('leftNode', '==', leftNode)
+
+ if (leftNode != null) {
+ graphsRef = graphsRef.where('leftNode', '==', leftNode)
}
if (rightNode && rightNode != null) {
- query = graphsRef.where('rightNode', '==', rightNode)
+ console.trace('getGraphsQuery', {collection, leftNode, edgeType, rightNode})
+
+ graphsRef = graphsRef.where('rightNode', '==', rightNode)
}
if (edgeType) {
- query = graphsRef.where('edgeType', '==', edgeType)
+ graphsRef = graphsRef.where('edgeType', '==', edgeType)
}
- if (query) {
- query.get().then((result) => {
+ if (graphsRef) {
+ graphsRef.get().then((result) => {
+
resolve(result)
}).catch((error) => reject(error))
} else {
diff --git a/src/data/firestoreClient/services/posts/PostService.ts b/src/data/firestoreClient/services/posts/PostService.ts
index 35d6626..81811d2 100644
--- a/src/data/firestoreClient/services/posts/PostService.ts
+++ b/src/data/firestoreClient/services/posts/PostService.ts
@@ -195,7 +195,7 @@ export class PostService implements IPostService {
// a = current item in array
// b = next item in array
return b[bKey].creationDate! - a[aKey].creationDate!
- });
+ })
if (lastPostId && lastPostId !== '') {
const lastPostIndex = sortedObjects.findIndex((arg) => {
return Object.keys(arg)[0] === lastPostId
diff --git a/src/data/firestoreClient/services/users/UserService.ts b/src/data/firestoreClient/services/users/UserService.ts
index 7e21145..c824ecb 100644
--- a/src/data/firestoreClient/services/users/UserService.ts
+++ b/src/data/firestoreClient/services/users/UserService.ts
@@ -91,7 +91,7 @@ export class UserService implements IUserService {
}
]
- });
+ })
resolve({ users: parsedData, newLastUserId })
})
.catch((error: any) => {
@@ -107,11 +107,15 @@ export class UserService implements IUserService {
return new Promise((resolve,reject) => {
let userProviderRef = db.doc(`userProviderInfo/${userId}`)
userProviderRef.get().then((snapshot) => {
- let userProvider: UserProvider = snapshot.data() as UserProvider || {}
- resolve(userProvider)
+ if (snapshot.exists) {
+ let userProvider: UserProvider = snapshot.data() as UserProvider || {}
+ resolve(userProvider)
+ } else {
+ throw new SocialError(`firestore/getUserProviderData/notExist `, `document of userProviderRef is not exist `)
+ }
})
.catch((error: any) => {
- reject(new SocialError(error.code, 'firestore/getUserProviderData' + error.message))
+ reject(new SocialError(error.code, 'firestore/getUserProviderData ' + error.message))
})
})
diff --git a/src/reducers/circles/CircleState.ts b/src/reducers/circles/CircleState.ts
index f207a1b..e0c5967 100644
--- a/src/reducers/circles/CircleState.ts
+++ b/src/reducers/circles/CircleState.ts
@@ -7,39 +7,49 @@ import { Circle, UserTie } from 'core/domain/circles'
* @class CircleState
*/
export class CircleState {
- /**
- * The list of users belong to users circle
- *
- * @memberof CircleState
- */
- userTies: {[userId: string]: UserTie }= {}
+ /**
+ * The list of users belong to users circle
+ *
+ * @memberof CircleState
+ */
+ userTies: { [userId: string]: UserTie } = {}
- /**
- * The list of users belong to users circle
- *
- * @memberof CircleState
- */
- userTieds: {[userId: string]: UserTie }= {}
+ /**
+ * The list of users belong to users circle
+ *
+ * @memberof CircleState
+ */
+ userTieds: { [userId: string]: UserTie } = {}
/**
* The list of circle of current user
*/
- circleList: {[circleId: string]: Circle}
+ circleList: { [circleId: string]: Circle }
/**
* Whether select circle box is open for the selected user
*/
- selectCircleStatus: {[userId: string]: boolean}
+ selectCircleStatus: { [userId: string]: boolean }
/**
* Whether following loading is shown for the selected user
*/
- followingLoadingStatus: {[userId: string]: boolean}
+ followingLoadingStatus: { [userId: string]: boolean }
- /**
- * If user circles are loaded {true} or not {false}
- *
- * @memberof CircleState
- */
+ /**
+ * Keep selected circles for refere user
+ */
+ selectedCircles: { [userId: string]: string[] }
+
+ /**
+ * Whether the select circles box for referer user is open
+ */
+ openSelecteCircles: { [userId: string]: boolean }
+
+ /**
+ * If user circles are loaded {true} or not {false}
+ *
+ * @memberof CircleState
+ */
loaded: boolean = false
}
diff --git a/src/reducers/circles/circleReducer.ts b/src/reducers/circles/circleReducer.ts
index 2aeca22..f9d92e1 100644
--- a/src/reducers/circles/circleReducer.ts
+++ b/src/reducers/circles/circleReducer.ts
@@ -75,9 +75,13 @@ export let circleReducer = (state: CircleState = new CircleState(), action: ICir
...state,
userTies: {
...state.userTies,
- [payload.userTie.user.userId]: {
+ [payload.userTie.userId]: {
...payload.userTie
}
+ },
+ selectedCircles: {
+ ...state.selectedCircles,
+ [payload.userTie.userId]: payload.userTie.circleIdList
}
}
@@ -98,7 +102,8 @@ export let circleReducer = (state: CircleState = new CircleState(), action: ICir
userTies: {
...state.userTies,
...payload.userTies
- }
+ },
+ selectedCircles : getSelectedCircles(payload.userTies)
}
case CircleActionType.ADD_USER_TIED_LIST:
@@ -139,9 +144,9 @@ export let circleReducer = (state: CircleState = new CircleState(), action: ICir
return {
...state,
userTies: {
- ...state.userTies,
...filteredUserTies
- }
+ },
+ selectedCircles : getSelectedCircles(filteredUserTies)
}
/**
@@ -208,8 +213,65 @@ export let circleReducer = (state: CircleState = new CircleState(), action: ICir
}
}
+ /**
+ * User box component
+ */
+ case CircleActionType.SET_SELECTED_CIRCLES_USER_BOX_COMPONENT:
+ return {
+ ...state,
+ selectedCircles: {
+ ...state.selectedCircles,
+ [payload.userId]: payload.circleList
+ }
+ }
+ /**
+ * User box component
+ */
+ case CircleActionType.REMOVE_SELECTED_CIRCLES_USER_BOX_COMPONENT:
+ return {
+ ...state,
+ selectedCircles: {
+ ...state.selectedCircles,
+ [payload.userId]: []
+ }
+ }
+ /**
+ * User box component
+ */
+ case CircleActionType.OPEN_SELECT_CIRCLES_USER_BOX_COMPONENT:
+ return {
+ ...state,
+ openSelecteCircles: {
+ ...state.openSelecteCircles,
+ [payload.userId]: true
+ }
+ }
+ case CircleActionType.CLOSE_SELECT_CIRCLES_USER_BOX_COMPONENT:
+ return {
+ ...state,
+ openSelecteCircles: {
+ ...state.openSelecteCircles,
+ [payload.userId]: false
+ }
+ }
default:
return state
}
}
+
+/**
+ * Map user ties selected to selected circles
+ */
+const getSelectedCircles = (userTies: {[userId: string]: UserTie }) => {
+ let selectedCircles: {[userId: string]: string[]} = {}
+ Object.keys(userTies).forEach((userId: string) => {
+ const userTie = (userTies as {[userId: string]: UserTie })[userId]
+ selectedCircles = {
+ ...selectedCircles,
+ [userTie.userId!]: userTie.circleIdList!
+ }
+ })
+
+ return selectedCircles
+}
\ No newline at end of file
diff --git a/src/reducers/global/GlobalState.ts b/src/reducers/global/GlobalState.ts
index 659163e..bab07e1 100644
--- a/src/reducers/global/GlobalState.ts
+++ b/src/reducers/global/GlobalState.ts
@@ -6,101 +6,122 @@
*/
export class GlobalState {
- /**
- * Set percent of loading progress and visibility for Master component
- *
- * @type {{
- * percent: number,
- * visible: Boolean
- * }}
- * @memberof IGlobalState
- */
+ /**
+ * Set percent of loading progress and visibility for Master component
+ *
+ * @type {{
+ * percent: number,
+ * visible: boolean
+ * }}
+ * @memberof IGlobalState
+ */
progress: {
percent: number
- visible: Boolean
+ visible: boolean
} = {
percent: 0,
visible: false
}
- /**
- * If loading is enabled {true} or not false
- *
- * @type {Boolean}
- * @memberof IGlobalState
- */
- loadingStatus: Boolean = true
+ /**
+ * If loading is enabled {true} or not false
+ *
+ * @type {boolean}
+ * @memberof IGlobalState
+ */
+ loadingStatus: boolean = true
- /**
- * If user date is loaded {true} or not {false}
- *
- * @type {Boolean}
- * @memberof IGlobalState
- */
- defaultLoadDataStatus: Boolean = false
+ /**
+ * Whether send feedback is diplayed
+ */
+ sendFeedbackStatus: boolean = false
- /**
- * If message popup is open {true} or not {false}
- *
- * @type {Boolean}
- * @memberof IGlobalState
- */
- messageOpen: Boolean = false
+ /**
+ * If user date is loaded {true} or not {false}
+ *
+ * @type {boolean}
+ * @memberof IGlobalState
+ */
+ defaultLoadDataStatus: boolean = false
- /**
- * The text of popup global message
- *
- * @type {string}
- * @memberof IGlobalState
- */
+ /**
+ * If message popup is open {true} or not {false}
+ *
+ * @type {boolean}
+ * @memberof IGlobalState
+ */
+ messageOpen: boolean = false
+
+ /**
+ * The text of popup global message
+ *
+ * @type {string}
+ * @memberof IGlobalState
+ */
message: string = ''
- /**
- * Window size
- *
- * @type {number}
- * @memberof IGlobalState
- */
+ /**
+ * Window size
+ *
+ * @type {number}
+ * @memberof IGlobalState
+ */
windowWidth: number = 0
- /**
- * Window height
- *
- * @type {number}
- * @memberof IGlobalState
- */
+ /**
+ * Window height
+ *
+ * @type {number}
+ * @memberof IGlobalState
+ */
windowHeight: number = 0
- /**
- * The text of website header
- *
- * @type {string}
- * @memberof IGlobalState
- */
+ /**
+ * The text of website header
+ *
+ * @type {string}
+ * @memberof IGlobalState
+ */
headerTitle: string = ''
- /**
- * Top loading is visible {true} or not {false}
- *
- * @type {Boolean}
- * @memberof IGlobalState
- */
- showTopLoading: Boolean = false
+ /**
+ * Top loading is visible {true} or not {false}
+ *
+ * @type {boolean}
+ * @memberof IGlobalState
+ */
+ showTopLoading: boolean = false
- /**
- * Top loading message queue
- *
- * @type {number}
- * @memberof IGlobalState
- */
+ /**
+ * Top loading message queue
+ *
+ * @type {number}
+ * @memberof IGlobalState
+ */
topLoadingQueue: number = 0
- /**
- * Temp date storage
- *
- * @type {*}
- * @memberof IGlobalState
- */
+ /**
+ * Master loading is visible {true} or not {false}
+ *
+ * @type {boolean}
+ * @memberof IGlobalState
+ */
+ showMasterLoading: boolean = true
+
+ /**
+ * Master loading message queue
+ *
+ * @type {number}
+ * @memberof IGlobalState
+ */
+ masterLoadingQueue: number = 0
+
+ /**
+ * Temp date storage
+ *
+ * @type {*}
+ * @memberof IGlobalState
+ */
temp: any = {
caller: []
}
diff --git a/src/reducers/global/globalReducer.ts b/src/reducers/global/globalReducer.ts
index 1e7ef9e..1ee8b85 100644
--- a/src/reducers/global/globalReducer.ts
+++ b/src/reducers/global/globalReducer.ts
@@ -67,12 +67,22 @@ export const globalReducer = (state: GlobalState = new GlobalState(), action: IG
...state,
headerTitle: action.payload
}
- case GlobalActionType.HIDE_TOP_LOADING:
- const queue = state.topLoadingQueue > 0 ? (state.topLoadingQueue - 1) : 0
+ case GlobalActionType.SHOW_SEND_FEEDBACK:
return {
...state,
- topLoadingQueue: queue,
- showTopLoading: (queue > 0 ? true : false)
+ sendFeedbackStatus: true
+ }
+ case GlobalActionType.HIDE_SEND_FEEDBACK:
+ return {
+ ...state,
+ sendFeedbackStatus: false
+ }
+ case GlobalActionType.HIDE_TOP_LOADING:
+ const queueTopLoading = state.topLoadingQueue > 0 ? (state.topLoadingQueue - 1) : 0
+ return {
+ ...state,
+ topLoadingQueue: queueTopLoading,
+ showTopLoading: (queueTopLoading > 0 ? true : false)
}
case GlobalActionType.SHOW_TOP_LOADING:
@@ -81,6 +91,20 @@ export const globalReducer = (state: GlobalState = new GlobalState(), action: IG
topLoadingQueue: (state.topLoadingQueue + 1),
showTopLoading: true
}
+ case GlobalActionType.HIDE_MASTER_LOADING:
+ const queueMasterLoading = state.masterLoadingQueue > 0 ? (state.masterLoadingQueue - 1) : 0
+ return {
+ ...state,
+ masterLoadingQueue: queueMasterLoading,
+ showMasterLoading: (queueMasterLoading > 0 ? true : false)
+
+ }
+ case GlobalActionType.SHOW_MASTER_LOADING:
+ return {
+ ...state,
+ masterLoadingQueue: (state.masterLoadingQueue + 1),
+ showMasterLoading: true
+ }
case GlobalActionType.TEMP:
return {
...state,
diff --git a/src/reducers/server/serverReducer.ts b/src/reducers/server/serverReducer.ts
index 97f14c1..30cd337 100644
--- a/src/reducers/server/serverReducer.ts
+++ b/src/reducers/server/serverReducer.ts
@@ -28,7 +28,7 @@ export let serverReducer = (state: ServerState = new ServerState(), action: ISer
request: {
...state.request,
[request.id]: {
- request
+ ...request
}
}
}
diff --git a/src/socialEngine.ts b/src/socialEngine.ts
index 58bbf61..98816b5 100644
--- a/src/socialEngine.ts
+++ b/src/socialEngine.ts
@@ -7,7 +7,7 @@ import CommonAPI from 'api/CommonAPI'
/**
* Developer tools
*/
-(window as any).logger = CommonAPI.logger
+console.trace = CommonAPI.logger
/**
* Initialize container
diff --git a/src/styles/app.scss b/src/styles/app.scss
index c1f60de..2f7e4f4 100644
--- a/src/styles/app.scss
+++ b/src/styles/app.scss
@@ -2,11 +2,13 @@
@import 'base/grid';
@import 'base/animate';
@import 'base/icon';
+@import 'base/flaticon';
// Component styles
@import 'components/global';
@import 'components/master';
@import 'components/post';
@import 'components/profile';
+@import 'components/sendFeedback';
@import 'components/userBox';
@import 'components/imageGallery';
@import 'components/postWrite';
diff --git a/src/styles/base/_flaticon.scss b/src/styles/base/_flaticon.scss
new file mode 100644
index 0000000..a476de6
--- /dev/null
+++ b/src/styles/base/_flaticon.scss
@@ -0,0 +1,52 @@
+ /*
+ Flaticon icon font: Flaticon
+ */
+
+ @font-face {
+ font-family: "Flaticon";
+ src: url("../assets/fonts/Flaticon.eot");
+ src: url("../assets/fonts/Flaticon.eot?#iefix") format("embedded-opentype"),
+ url("../assets/fonts/Flaticon.woff") format("woff"),
+ url("../assets/fonts/Flaticon.ttf") format("truetype"),
+ url("../assets/images/Flaticon.svg#Flaticon") format("svg");
+ font-weight: normal;
+ font-style: normal;
+ }
+
+ @media screen and (-webkit-min-device-pixel-ratio:0) {
+ @font-face {
+ font-family: "Flaticon";
+ src: url("../assets/images/Flaticon.svg#Flaticon") format("svg");
+ }
+ }
+
+ .fi:before{
+ display: inline-block;
+ font-family: "Flaticon";
+ font-style: normal;
+ font-weight: normal;
+ font-variant: normal;
+ line-height: 1;
+ text-decoration: inherit;
+ text-rendering: optimizeLegibility;
+ text-transform: none;
+ -moz-osx-font-smoothing: grayscale;
+ -webkit-font-smoothing: antialiased;
+ font-smoothing: antialiased;
+ }
+
+ .flaticon-sad-2:before { content: "\f100"; }
+ .flaticon-sad-1:before { content: "\f101"; }
+ .flaticon-neutral:before { content: "\f102"; }
+ .flaticon-happy-2:before { content: "\f103"; }
+ .flaticon-sad:before { content: "\f104"; }
+ .flaticon-happy-1:before { content: "\f105"; }
+ .flaticon-happy:before { content: "\f106"; }
+
+ $font-Flaticon-sad-2: "\f100";
+ $font-Flaticon-sad-1: "\f101";
+ $font-Flaticon-neutral: "\f102";
+ $font-Flaticon-happy-2: "\f103";
+ $font-Flaticon-sad: "\f104";
+ $font-Flaticon-happy-1: "\f105";
+ $font-Flaticon-happy: "\f106";
\ No newline at end of file
diff --git a/src/styles/base/_icon.scss b/src/styles/base/_icon.scss
index 9895dd5..6870593 100644
--- a/src/styles/base/_icon.scss
+++ b/src/styles/base/_icon.scss
@@ -35,4 +35,14 @@
background-image: icon(facebook, #4267b2);
}
+.icon__svg {
+ padding: 10px;
+ display: block;
+ font-family: "Flaticon";
+ font-size: 64px;
+ line-height: 1;
+ transform: translate(-10px, -9px);
+
+}
+
// .icon-dashstroke { background-image: icon(heart, red, black, 2, 'stroke-dasharray : 2px, 1px;'); }
\ No newline at end of file
diff --git a/src/styles/components/_homeHeader.scss b/src/styles/components/_homeHeader.scss
index 7f46a9f..bd0ce6b 100644
--- a/src/styles/components/_homeHeader.scss
+++ b/src/styles/components/_homeHeader.scss
@@ -65,8 +65,7 @@
outline: none !important;
box-shadow: 0 2px 10px rgba(0, 0, 0, .2) !important;
div.container {
- padding: 10px;
- padding: 10px;
+ padding: 10px 0px 10px 0px;
display: flex;
flex-direction: column;
width: 100%;
@@ -86,16 +85,18 @@
padding: 10px 0px;
div.item {
width: 100%;
- height: 68px;
+ height: 54px;
background-color: white;
margin-bottom: 10px;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2);
display: flex;
- padding: 10px;
+ padding: 10px 0px 10px 0px;
flex-direction: row;
align-items: center;
position: relative;
- div.avatar {}
+ div.avatar {
+ margin-left: 5px;
+ }
div.info {
margin-left: 10px;
height: 100%;
diff --git a/src/styles/components/_masterLoading.scss b/src/styles/components/_masterLoading.scss
index f81bc82..920a296 100644
--- a/src/styles/components/_masterLoading.scss
+++ b/src/styles/components/_masterLoading.scss
@@ -2,11 +2,37 @@
background-color: rgb(216, 216, 216);
}
-.mLoading__content {
- max-width: 338px !important;
-}
-
-.mLoading__context{
- display: flex;
- justify-content: space-around;
-}
\ No newline at end of file
+.mLoading__loading {
+ position: fixed;
+ z-index: 2001;
+ height: 2em;
+ width: 2em;
+ overflow: show;
+ margin: auto;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ right: 0;
+ }
+
+ /* Transparent Overlay */
+ .mLoading__loading:before {
+ content: '';
+ display: block;
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background-color: rgba(255, 255, 255, 0.65);
+ }
+
+ /* :not(:required) hides these rules from IE9 and below */
+ .mLoading__loading:not(:required) {
+ /* hide "mLoading__loading..." text */
+ font: 0/0 a;
+ color: transparent;
+ text-shadow: none;
+ background-color: transparent;
+ border: 0;
+ }
\ No newline at end of file
diff --git a/src/styles/components/_sendFeedback.scss b/src/styles/components/_sendFeedback.scss
new file mode 100644
index 0000000..e7e995f
--- /dev/null
+++ b/src/styles/components/_sendFeedback.scss
@@ -0,0 +1,37 @@
+.sendFeedback__content {
+
+ position: fixed;
+ right: 5px;
+ bottom: 5px;
+ z-index: 1;
+ .paper {
+ width: 350px;
+ height: 100%;
+ margin: 20px;
+ text-align: center;
+
+ }
+ .buttons {
+ position: relative;
+ }
+ .close {
+ position: absolute;
+ top: 13px;
+ right: 13px;
+ }
+ .success {
+ padding: 30px;
+ }
+ .error {
+ padding: 30px;
+ }
+ .loading{
+ padding: 18px 0px 0px 0px;
+ .icon {
+ justify-content: center;
+ align-items: center;
+ align-content: center;
+ align-self: center;
+ }
+ }
+}
\ No newline at end of file