diff --git a/.gitignore b/.gitignore
index d3325e4..ad9d66a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,5 @@
node_modules/
-public/bundle.js
+public/bundle*.js
config/
.vscode/
src/data/awsClient
diff --git a/package.json b/package.json
index 368b31c..df32d83 100644
--- a/package.json
+++ b/package.json
@@ -1,104 +1,106 @@
{
- "name": "react-social",
- "version": "1.0.0",
- "description": "Simple react socail app",
- "main": "index.js",
- "scripts": {
- "test": "NODE_ENV=test karma start",
- "build": "webpack",
- "start": "npm run build && node server.js"
- },
- "author": "Amir Movahedi",
- "license": "MIT",
- "dependencies": {
- "amazon-cognito-identity-js": "^1.21.0",
- "aws-sdk": "^2.132.0",
- "axios": "^0.16.1",
- "classnames": "^2.2.5",
- "crypto-js": "^3.1.9-1",
- "css-loader": "^0.28.0",
- "deep-freeze-strict": "^1.1.1",
- "expect": "^1.20.2",
- "express": "^4.15.2",
- "faker": "^4.1.0",
- "file-loader": "^0.11.1",
- "firebase": "^3.9.0",
- "inversify": "^4.3.0",
- "keycode": "^2.1.9",
- "lodash": "^4.17.4",
- "material-ui": "^0.19.4",
- "moment": "^2.18.1",
- "morgan": "^1.8.1",
- "node-env-file": "^0.1.8",
- "node-sass": "^4.5.2",
- "prop-types": "^15.6.0",
- "react": "^16.0.0",
- "react-addons-test-utils": "^15.6.2",
- "react-avatar-editor": "^10.3.0",
- "react-dom": "^16.0.0",
- "react-event-listener": "^0.5.1",
- "react-linkify": "^0.2.1",
- "react-parallax": "^1.4.4",
- "react-redux": "^5.0.6",
- "react-router": "^4.1.1 ",
- "react-router-dom": "^4.1.1",
- "react-router-redux": "^5.0.0-alpha.6",
- "react-string-replace": "^0.4.0",
- "react-tap-event-plugin": "^3.0.2",
- "redux": "^3.7.2",
- "redux-actions": "^2.0.3",
- "redux-thunk": "^2.2.0",
- "reflect-metadata": "^0.1.10",
- "sass-loader": "^6.0.3",
- "save": "^2.3.0",
- "script-loader": "^0.7.0",
- "style-loader": "^0.16.1",
- "url-loader": "^0.5.8",
- "uuid": "^3.0.1"
- },
- "devDependencies": {
- "@types/lodash": "^4.14.77",
- "@types/material-ui": "^0.18.2",
- "@types/node": "^8.0.33",
- "@types/prop-types": "^15.5.2",
- "@types/react": "^16.0.10",
- "@types/react-dom": "^16.0.1",
- "@types/react-event-listener": "^0.4.4",
- "@types/react-redux": "^5.0.10",
- "@types/react-router-dom": "^4.0.8",
- "@types/react-router-redux": "^5.0.8",
- "@types/react-tap-event-plugin": "0.0.30",
- "@types/redux-logger": "^3.0.4",
- "@types/uuid": "^3.4.3",
- "@types/webpack": "^3.0.13",
- "babel-core": "^6.24.1",
- "babel-loader": "^7.1.2",
- "babel-plugin-transform-decorators-legacy": "^1.3.4",
- "babel-polyfill": "^6.26.0",
- "babel-preset-env": "^1.6.0",
- "babel-preset-react": "^6.24.1",
- "babel-preset-stage-0": "^6.24.1",
- "css-loader": "^0.28.7",
- "eslint": "^4.9.0",
- "karma": "^1.6.0",
- "karma-chrome-launcher": "^2.0.0",
- "karma-mocha": "^1.3.0",
- "karma-mocha-reporter": "^2.2.3",
- "karma-sourcemap-loader": "^0.3.7",
- "karma-webpack": "^2.0.3",
- "mocha": "^3.2.0",
- "redux-logger": "^3.0.1",
- "redux-mock-store": "^1.2.3",
- "source-map-loader": "^0.2.2",
- "ts-loader": "^2.3.7",
- "ts-node": "^3.3.0",
- "tslint": "^5.7.0",
- "tslint-config-standard": "^6.0.1",
- "typescript": "^2.5.3",
- "webpack": "^3.6.0"
- },
- "engines": {
- "node": "7.3.0",
- "npm": "3.10.10"
- }
-}
+ "name": "react-social",
+ "version": "1.0.0",
+ "description": "Simple react socail app",
+ "main": "index.js",
+ "scripts": {
+ "test": "NODE_ENV=test karma start",
+ "build": "NODE_ENV=production webpack -p",
+ "watch": "webpack -w",
+ "deploy:firebase": "npm run build && firebase deploy",
+ "start": "npm run build && node server.js"
+ },
+ "author": "Amir Movahedi",
+ "license": "MIT",
+ "dependencies": {
+ "amazon-cognito-identity-js": "^1.21.0",
+ "aws-sdk": "^2.132.0",
+ "axios": "^0.16.1",
+ "classnames": "^2.2.5",
+ "crypto-js": "^3.1.9-1",
+ "css-loader": "^0.28.0",
+ "deep-freeze-strict": "^1.1.1",
+ "expect": "^1.20.2",
+ "express": "^4.15.2",
+ "faker": "^4.1.0",
+ "file-loader": "^0.11.1",
+ "firebase": "^3.9.0",
+ "inversify": "^4.3.0",
+ "keycode": "^2.1.9",
+ "lodash": "^4.17.4",
+ "material-ui": "^0.19.4",
+ "moment": "^2.18.1",
+ "morgan": "^1.8.1",
+ "node-env-file": "^0.1.8",
+ "node-sass": "^4.5.2",
+ "prop-types": "^15.6.0",
+ "react": "^16.0.0",
+ "react-addons-test-utils": "^15.6.2",
+ "react-avatar-editor": "^10.3.0",
+ "react-dom": "^16.0.0",
+ "react-event-listener": "^0.5.1",
+ "react-linkify": "^0.2.1",
+ "react-parallax": "^1.4.4",
+ "react-redux": "^5.0.6",
+ "react-router": "^4.1.1 ",
+ "react-router-dom": "^4.1.1",
+ "react-router-redux": "^5.0.0-alpha.6",
+ "react-string-replace": "^0.4.0",
+ "react-tap-event-plugin": "^3.0.2",
+ "redux": "^3.7.2",
+ "redux-actions": "^2.0.3",
+ "redux-thunk": "^2.2.0",
+ "reflect-metadata": "^0.1.10",
+ "sass-loader": "^6.0.3",
+ "save": "^2.3.0",
+ "script-loader": "^0.7.0",
+ "style-loader": "^0.16.1",
+ "url-loader": "^0.5.8",
+ "uuid": "^3.0.1"
+ },
+ "devDependencies": {
+ "@types/lodash": "^4.14.77",
+ "@types/material-ui": "^0.18.2",
+ "@types/node": "^8.0.33",
+ "@types/prop-types": "^15.5.2",
+ "@types/react": "^16.0.10",
+ "@types/react-dom": "^16.0.1",
+ "@types/react-event-listener": "^0.4.4",
+ "@types/react-redux": "^5.0.10",
+ "@types/react-router-dom": "^4.0.8",
+ "@types/react-router-redux": "^5.0.8",
+ "@types/react-tap-event-plugin": "0.0.30",
+ "@types/redux-logger": "^3.0.4",
+ "@types/uuid": "^3.4.3",
+ "@types/webpack": "^3.0.13",
+ "babel-core": "^6.24.1",
+ "babel-loader": "^7.1.2",
+ "babel-plugin-transform-decorators-legacy": "^1.3.4",
+ "babel-polyfill": "^6.26.0",
+ "babel-preset-env": "^1.6.0",
+ "babel-preset-react": "^6.24.1",
+ "babel-preset-stage-0": "^6.24.1",
+ "css-loader": "^0.28.7",
+ "eslint": "^4.9.0",
+ "karma": "^1.6.0",
+ "karma-chrome-launcher": "^2.0.0",
+ "karma-mocha": "^1.3.0",
+ "karma-mocha-reporter": "^2.2.3",
+ "karma-sourcemap-loader": "^0.3.7",
+ "karma-webpack": "^2.0.3",
+ "mocha": "^3.2.0",
+ "redux-logger": "^3.0.1",
+ "redux-mock-store": "^1.2.3",
+ "source-map-loader": "^0.2.2",
+ "ts-loader": "^2.3.7",
+ "ts-node": "^3.3.0",
+ "tslint": "^5.7.0",
+ "tslint-config-standard": "^6.0.1",
+ "typescript": "^2.5.3",
+ "webpack": "^3.6.0"
+ },
+ "engines": {
+ "node": "7.3.0",
+ "npm": "3.10.10"
+ }
+}
\ No newline at end of file
diff --git a/public/index.html b/public/index.html
index eab425a..d463c7c 100644
--- a/public/index.html
+++ b/public/index.html
@@ -2,130 +2,127 @@
-
-
-
-
+
+
+
+
-
-
-
-
Green Open Social
+
-
-
+
\ No newline at end of file
diff --git a/src/actions/authorizeActions.ts b/src/actions/authorizeActions.ts
index da639a2..dce0cff 100644
--- a/src/actions/authorizeActions.ts
+++ b/src/actions/authorizeActions.ts
@@ -107,6 +107,28 @@ export const dbUpdatePassword = (newPassword: string) => {
}
}
+ /**
+ * Reset user's password
+ * @param {string} newPassword
+ */
+export const dbResetPassword = (email: string) => {
+ return (dispatch: any, getState: any) => {
+ dispatch(globalActions.showNotificationRequest())
+
+ return authorizeService.resetPassword(email).then(() => {
+
+ // Reset password successful.
+ dispatch(globalActions.showNotificationSuccess())
+ dispatch(push('/login'))
+ })
+ .catch((error: SocialError) => {
+ // An error happened.
+ dispatch(globalActions.showErrorMessage(error.code))
+
+ })
+ }
+}
+
/* _____________ CRUD State _____________ */
/**
diff --git a/src/actions/commentActions.ts b/src/actions/commentActions.ts
index 5b4a5b9..0bc8513 100644
--- a/src/actions/commentActions.ts
+++ b/src/actions/commentActions.ts
@@ -107,7 +107,7 @@ export const dbUpdateComment = (id: string, postId: string, text: string) => {
userId: uid
}
- return commentService.updateComment(uid,postId,updatedComment)
+ return commentService.updateComment(id,postId,updatedComment)
.then(() => {
dispatch(updateComment( id, postId, text))
dispatch(globalActions.hideTopLoading())
diff --git a/src/components/login/LoginComponent.tsx b/src/components/login/LoginComponent.tsx
index 0dc9b12..7a53ba9 100644
--- a/src/components/login/LoginComponent.tsx
+++ b/src/components/login/LoginComponent.tsx
@@ -7,6 +7,9 @@ import Paper from 'material-ui/Paper'
import TextField from 'material-ui/TextField'
import RaisedButton from 'material-ui/RaisedButton'
import FlatButton from 'material-ui/FlatButton'
+import FontIcon from 'material-ui/FontIcon'
+import Divider from 'material-ui/Divider'
+import ActionAndroid from 'material-ui/svg-icons/action/android'
// - Import actions
import * as authorizeActions from 'actions/authorizeActions'
@@ -16,6 +19,24 @@ import { ILoginComponentState } from './ILoginComponentState'
// - Create Login component class
export class LoginComponent extends Component
{
+ styles = {
+ singinOptions: {
+ paddingBottom: 10
+ },
+ divider: {
+ marginBottom: 10,
+ marginTop: 15
+ },
+ restPassword: {
+ lineHeight: 6,
+ fontWeight: 100,
+ fontSize: 'small'
+ },
+ restPasswordLink: {
+ color: '#0095ff'
+ }
+ }
+
/**
* Component constructor
* @param {object} props is an object properties of component
@@ -30,6 +51,7 @@ export class LoginComponent extends ComponentSign in
+ }} className='zoomOutLCorner animated'>Sign in
+
+
}
+ />
+ }
+ />
+ }
+ />
+
+
-
+ Have you forgot your password? reset your password
diff --git a/src/components/master/MasterComponent.tsx b/src/components/master/MasterComponent.tsx
index b50e569..3e8d280 100644
--- a/src/components/master/MasterComponent.tsx
+++ b/src/components/master/MasterComponent.tsx
@@ -11,6 +11,7 @@ import LinearProgress from 'material-ui/LinearProgress'
import Home from 'components/home'
import Signup from 'components/signup'
import Login from 'components/login'
+import ResetPassword from 'components/resetPassword'
import Setting from 'components/setting'
import MasterLoading from 'components/masterLoading'
import { IMasterComponentProps } from './IMasterComponentProps'
@@ -133,6 +134,7 @@ export class MasterComponent extends Component
+
{
console.log('this.props.authed: ', this.props.authed, 'this.props: ', this.props)
return (
diff --git a/src/components/resetPassword/IRestPasswordComponentProps.ts b/src/components/resetPassword/IRestPasswordComponentProps.ts
new file mode 100644
index 0000000..4dec803
--- /dev/null
+++ b/src/components/resetPassword/IRestPasswordComponentProps.ts
@@ -0,0 +1,16 @@
+export interface IRestPasswordComponentProps {
+
+ /**
+ * Reset password
+ *
+ * @memberof IRestPasswordComponentProps
+ */
+ resetPassword: (email: string) => any
+
+ /**
+ * Redirect to login page
+ *
+ * @memberof IRestPasswordComponentProps
+ */
+ loginPage: () => void
+}
diff --git a/src/components/resetPassword/IRestPasswordComponentState.ts b/src/components/resetPassword/IRestPasswordComponentState.ts
new file mode 100644
index 0000000..694438e
--- /dev/null
+++ b/src/components/resetPassword/IRestPasswordComponentState.ts
@@ -0,0 +1,20 @@
+
+export interface IRestPasswordComponentState {
+
+ /**
+ * Email input value
+ *
+ * @type {string}
+ * @memberof IRestPasswordComponentState
+ */
+ emailInput: string
+
+ /**
+ * Email input error text
+ *
+ * @type {string}
+ * @memberof IRestPasswordComponentState
+ */
+ emailInputError: string
+
+}
diff --git a/src/components/resetPassword/RestPasswordComponent.tsx b/src/components/resetPassword/RestPasswordComponent.tsx
new file mode 100644
index 0000000..b7111ac
--- /dev/null
+++ b/src/components/resetPassword/RestPasswordComponent.tsx
@@ -0,0 +1,173 @@
+// - Import external components
+import React, { Component } from 'react'
+import { connect } from 'react-redux'
+import { NavLink, withRouter } from 'react-router-dom'
+import { push } from 'react-router-redux'
+import Paper from 'material-ui/Paper'
+import TextField from 'material-ui/TextField'
+import RaisedButton from 'material-ui/RaisedButton'
+import FlatButton from 'material-ui/FlatButton'
+import { firebaseRef, firebaseAuth } from 'data/firebaseClient'
+
+// - Import actions
+import * as authorizeActions from 'actions/authorizeActions'
+import { IRestPasswordComponentProps } from './IRestPasswordComponentProps'
+import { IRestPasswordComponentState } from './IRestPasswordComponentState'
+
+/**
+ * Create component class
+ *
+ * @export
+ * @class RestPasswordComponent
+ * @extends {Component}
+ */
+export class RestPasswordComponent extends Component {
+
+ /**
+ * Component constructor
+ * @param {object} props is an object properties of component
+ */
+ constructor (props: IRestPasswordComponentProps) {
+ super(props)
+
+ this.state = {
+ emailInput: '',
+ emailInputError: ''
+
+ }
+ // Binding function to `this`
+ this.handleForm = this.handleForm.bind(this)
+
+ }
+
+ /**
+ * Handle data on input change
+ * @param {event} evt is an event of inputs of element on change
+ */
+ handleInputChange = (event: any) => {
+ const target = event.target
+ const value = target.type === 'checkbox' ? target.checked : target.value
+ const name = target.name
+ this.setState({
+ [name]: value
+ })
+
+ }
+
+ /**
+ * Handle register form
+ */
+ handleForm = () => {
+
+ let error = false
+ if (this.state.emailInput === '') {
+ this.setState({
+ emailInputError: 'This field is required'
+ })
+
+ return
+ }
+
+ this.props.resetPassword(this.state.emailInput)
+ }
+
+ /**
+ * Reneder component DOM
+ * @return {react element} return the DOM which rendered by component
+ */
+ render () {
+
+ const paperStyle = {
+ minHeight: 370,
+ width: 450,
+ textAlign: 'center',
+ display: 'block',
+ margin: 'auto'
+ }
+ return (
+
+
+
Green
+
+
+
+
+
+
+
Reset Password
+
+
+
+
+
+
+
+
+
+
+
+ )
+ }
+}
+
+/**
+ * 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: IRestPasswordComponentProps) => {
+ return {
+ loginPage: () => {
+ dispatch(push('/login'))
+ },
+ resetPassword: (emailAddress: string) => dispatch(authorizeActions.dbResetPassword(emailAddress))
+ }
+}
+
+/**
+ * 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: IRestPasswordComponentProps) => {
+ return {
+
+ }
+}
+
+// - Connect component to redux store
+export default withRouter(connect(mapStateToProps, mapDispatchToProps)(RestPasswordComponent as any))
diff --git a/src/components/resetPassword/index.ts b/src/components/resetPassword/index.ts
new file mode 100644
index 0000000..cc9af07
--- /dev/null
+++ b/src/components/resetPassword/index.ts
@@ -0,0 +1,2 @@
+import RestPasswordComponent from './RestPasswordComponent'
+export default RestPasswordComponent
diff --git a/src/components/signup/SignupComponent.tsx b/src/components/signup/SignupComponent.tsx
index 780e0e3..4d2e771 100644
--- a/src/components/signup/SignupComponent.tsx
+++ b/src/components/signup/SignupComponent.tsx
@@ -193,7 +193,7 @@ export class SignupComponent extends ComponentSign up
+ margin: 0}} className='zoomOutLCorner animated'>Sign up
void)
+ onAuthStateChanged: (callBack: (user: User) => void) => void
+
+ /**
+ * Reset user password
+ *
+ * @memberof IAuthorizeService
+ */
+ resetPassword: (email: string) => Promise
}
diff --git a/src/core/services/comments/ICommentService.ts b/src/core/services/comments/ICommentService.ts
index da41927..cb9aff3 100644
--- a/src/core/services/comments/ICommentService.ts
+++ b/src/core/services/comments/ICommentService.ts
@@ -12,7 +12,7 @@ export interface ICommentService {
addComment: (postId: string, comment: Comment) => Promise
getComments: (callback: (resultComments: { [postId: string]: { [commentId: string]: Comment } }) => void) => void
- updateComment: (userId: string, postId: string, comment: Comment) => Promise
+ updateComment: (commentId: string, postId: string, comment: Comment) => Promise
deleteComment: (commentId: string, postId: string) => Promise
}
diff --git a/src/data/firebaseClient/index.ts b/src/data/firebaseClient/index.ts
index 3f53585..284178d 100644
--- a/src/data/firebaseClient/index.ts
+++ b/src/data/firebaseClient/index.ts
@@ -12,6 +12,7 @@ try {
messagingSenderId: process.env.MESSAGING_SENDER_ID
}
+ console.log(firebase)
firebase.initializeApp(config)
} catch (error) {
console.log('=========Firebase initializer==============')
diff --git a/src/data/firebaseClient/services/authorize/AuthorizeService.ts b/src/data/firebaseClient/services/authorize/AuthorizeService.ts
index d8bf76f..5f1e101 100644
--- a/src/data/firebaseClient/services/authorize/AuthorizeService.ts
+++ b/src/data/firebaseClient/services/authorize/AuthorizeService.ts
@@ -108,8 +108,25 @@ export class AuthorizeService implements IAuthorizeService {
*
* @memberof IAuthorizeService
*/
- onAuthStateChanged: (callBack: (user: User) => void) => any = (callBack) => {
+ public onAuthStateChanged: (callBack: (user: User) => void) => any = (callBack) => {
firebaseAuth().onAuthStateChanged(callBack)
}
+ /**
+ * Reset user password
+ *
+ * @memberof AuthorizeService
+ */
+ public resetPassword: (email: string) => Promise = (email) => {
+ return new Promise((resolve,reject) => {
+ let auth = firebaseAuth()
+
+ auth.sendPasswordResetEmail(email).then(function () {
+ resolve()
+ }).catch((error: any) => {
+ // An error happened.
+ reject(new SocialError(error.code, error.message))
+ })
+ })
+ }
}
diff --git a/src/data/firebaseClient/services/circles/CircleService.ts b/src/data/firebaseClient/services/circles/CircleService.ts
index 69ed598..c893b08 100644
--- a/src/data/firebaseClient/services/circles/CircleService.ts
+++ b/src/data/firebaseClient/services/circles/CircleService.ts
@@ -18,7 +18,7 @@ export class CircleService implements ICircleService {
public addCircle: (userId: string, circle: Circle)
=> Promise = (userId, circle) => {
return new Promise((resolve,reject) => {
- let circleRef = firebaseRef.child(`userCircles/${userId}/circles`).push(circle)
+ let circleRef = firebaseRef.child(`users/${userId}/circles`).push(circle)
circleRef.then(() => {
resolve(circleRef.key as string)
})
@@ -35,8 +35,8 @@ export class CircleService implements ICircleService {
return new Promise((resolve,reject) => {
let updates: any = {}
- updates[`userCircles/${userId}/circles/${circleId}/users/${userFollowingId}`] = userCircle
- updates[`userCircles/${userFollowingId}/circles/-Followers/users/${userId}`] = userFollower
+ updates[`users/${userId}/circles/${circleId}/users/${userFollowingId}`] = userCircle
+ updates[`users/${userFollowingId}/circles/-Followers/users/${userId}`] = userFollower
firebaseRef.update(updates).then(() => {
resolve()
@@ -52,8 +52,8 @@ export class CircleService implements ICircleService {
return new Promise((resolve,reject) => {
let updates: any = {}
- updates[`userCircles/${userId}/circles/${circleId}/users/${userFollowingId}`] = null
- updates[`userCircles/${userFollowingId}/circles/-Followers/users/${userId}`] = null
+ updates[`users/${userId}/circles/${circleId}/users/${userFollowingId}`] = null
+ updates[`users/${userFollowingId}/circles/-Followers/users/${userId}`] = null
firebaseRef.update(updates).then(() => {
resolve()
@@ -69,7 +69,7 @@ export class CircleService implements ICircleService {
return new Promise((resolve,reject) => {
let updates: any = {}
- updates[`userCircles/${userId}/circles/${circleId}`] = circle
+ updates[`users/${userId}/circles/${circleId}`] = circle
firebaseRef.update(updates).then(() => {
resolve()
})
@@ -85,7 +85,7 @@ export class CircleService implements ICircleService {
return new Promise((resolve,reject) => {
let updates: any = {}
- updates[`userCircles/${userId}/circles/${circleId}`] = null
+ updates[`users/${userId}/circles/${circleId}`] = null
firebaseRef.update(updates).then(() => {
resolve()
})
@@ -97,7 +97,7 @@ export class CircleService implements ICircleService {
}
public getCircles: (userId: string) => Promise<{ [circleId: string]: Circle }> = (userId) => {
return new Promise<{ [circleId: string]: Circle }>((resolve,reject) => {
- let circlesRef: any = firebaseRef.child(`userCircles/${userId}/circles`)
+ let circlesRef: any = firebaseRef.child(`users/${userId}/circles`)
circlesRef.once('value').then((snapshot: any) => {
let circles: any = snapshot.val() || {}
diff --git a/src/data/firebaseClient/services/comments/CommentService.ts b/src/data/firebaseClient/services/comments/CommentService.ts
index 64a8a19..5be106f 100644
--- a/src/data/firebaseClient/services/comments/CommentService.ts
+++ b/src/data/firebaseClient/services/comments/CommentService.ts
@@ -35,12 +35,12 @@ export class CommentService implements ICommentService {
})
}
- public updateComment: (userId: string, postId: string, comment: Comment)
- => Promise = (userId, postId, comment) => {
+ public updateComment: (commentId: string, postId: string, comment: Comment)
+ => Promise = (commentId, postId, comment) => {
return new Promise((resolve,reject) => {
let updates: any = {}
- updates[`postComments/${postId}/${userId}`] = comment
+ updates[`postComments/${postId}/${commentId}`] = comment
firebaseRef.update(updates)
.then(() => {
resolve()
diff --git a/src/styles/app.scss b/src/styles/app.scss
index 6269a1a..72a4735 100644
--- a/src/styles/app.scss
+++ b/src/styles/app.scss
@@ -1,8 +1,7 @@
@import "base/variables";
@import 'base/grid';
@import 'base/animate';
-
-
+@import 'base/icon';
// Component styles
@import 'components/global';
@import 'components/master';
@@ -19,5 +18,4 @@
@import 'components/login';
@import 'components/signup';
@import 'components/masterLoading';
-@import 'components/settings';
-
+@import 'components/settings';
\ No newline at end of file
diff --git a/src/styles/base/_animate.scss b/src/styles/base/_animate.scss
index aa1a982..53d67d8 100644
--- a/src/styles/base/_animate.scss
+++ b/src/styles/base/_animate.scss
@@ -165,3 +165,32 @@
}
}
+.animated {
+ animation-duration: .5s;
+ animation-fill-mode: both;
+}
+
+.animated.infinite {
+ animation-iteration-count: infinite;
+}
+
+.animated.hinge {
+ animation-duration: 2s;
+}
+
+@keyframes zoomOutUp {
+ 40% {
+ opacity: 1;
+ transform: scale3d(1, 1, 1) translate3d(0, 0px, 0);
+ animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
+ }
+ to {
+ transform: scale3d(.8, .8, .8) translate3d(-80px, -40px, 0);
+ transform-origin: center bottom;
+ animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
+ }
+}
+
+.zoomOutLCorner {
+ animation-name: zoomOutUp;
+}
\ No newline at end of file
diff --git a/src/styles/base/_icon.scss b/src/styles/base/_icon.scss
new file mode 100644
index 0000000..9895dd5
--- /dev/null
+++ b/src/styles/base/_icon.scss
@@ -0,0 +1,38 @@
+// https://codepen.io/noahblon/pen/xGbXdV
+@function _buildIcon($icon) {
+ $icon: '%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20width%3D%2224%22%20height%3D%2224%22%3E#{$icon}%3C%2Fsvg%3E';
+ @return $icon;
+}
+
+@function _buildPath($path, $parameters) {
+ $icon: '%3Cpath%20fill%3D%22#{map-get($parameters, color)}%22%20stroke%3D%22#{map-get($parameters, stroke-color)}%22%20stroke-width%3D%22#{map-get($parameters, stroke-width)}%22%20style%3D%22#{map-get($parameters, css)}%22%20d%3D%22#{$path}%22%20%2F%3E';
+ @return $icon;
+}
+
+@function icon( $icon-name, $color, $stroke-color: transparent, $stroke-width: 0, $css: '' // arbitrary css
+) {
+ $parameters: ( 'color': $color, 'stroke-color': $stroke-color, 'stroke-width': $stroke-width, 'css': $css);
+ $icons: ( github: _buildPath('M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12', $parameters), google: _buildPath('M7.635 10.909v2.619h4.335c-.173 1.125-1.31 3.295-4.331 3.295-2.604 0-4.731-2.16-4.731-4.823 0-2.662 2.122-4.822 4.728-4.822 1.485 0 2.479.633 3.045 1.178l2.073-1.994c-1.33-1.245-3.056-1.995-5.115-1.995C3.412 4.365 0 7.785 0 12s3.414 7.635 7.635 7.635c4.41 0 7.332-3.098 7.332-7.461 0-.501-.054-.885-.12-1.265H7.635zm16.365 0h-2.183V8.726h-2.183v2.183h-2.182v2.181h2.184v2.184h2.189V13.09H24', $parameters), facebook: _buildPath('M22.676 0H1.324C.593 0 0 .593 0 1.324v21.352C0 23.408.593 24 1.324 24h11.494v-9.294H9.689v-3.621h3.129V8.41c0-3.099 1.894-4.785 4.659-4.785 1.325 0 2.464.097 2.796.141v3.24h-1.921c-1.5 0-1.792.721-1.792 1.771v2.311h3.584l-.465 3.63H16.56V24h6.115c.733 0 1.325-.592 1.325-1.324V1.324C24 .593 23.408 0 22.676 0', $parameters));
+ $icon: _buildIcon(map-get($icons, $icon-name));
+ @return url("data:image/svg+xml;charset=utf8,#{$icon}");
+}
+
+.icon {
+ width: 24px;
+ height: 24px;
+ display: inline-block;
+}
+
+.icon-github {
+ background-image: icon(github, #24292e);
+}
+
+.icon-google {
+ background-image: icon(google, #db4437);
+}
+
+.icon-fb {
+ background-image: icon(facebook, #4267b2);
+}
+
+// .icon-dashstroke { background-image: icon(heart, red, black, 2, 'stroke-dasharray : 2px, 1px;'); }
\ No newline at end of file
diff --git a/webpack.config.js b/webpack.config.js
index c28dd0e..9c3e027 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -7,147 +7,146 @@ process.env.NODE_ENV = process.env.NODE_ENV || 'development';
console.log(process.env.NODE_ENV);
try {
- envFile(path.join(__dirname, 'config/' + process.env.NODE_ENV + '.env'));
+ envFile(path.join(__dirname, 'config/' + process.env.NODE_ENV + '.env'));
} catch (e) {
}
var babelOptions = {
- plugins: ['transform-decorators-legacy'],
- presets: ['babel-polyfill','react', 'env', 'stage-0']
+ plugins: ['transform-decorators-legacy'],
+ presets: ['babel-polyfill', 'react', 'env', 'stage-0']
};
module.exports = {
- entry: [
- './src/index.tsx'
- ],
- externals: {
- jquery: 'jQuery'
- },
- plugins: (process.env.NODE_ENV === 'production') ? [
- new webpack.optimize.UglifyJsPlugin({
- minimize: true,
- compressor: {
- warnings: false
- }
- }),
- new webpack.DefinePlugin({
- 'process.env': {
- NODE_ENV: JSON.stringify(process.env.NODE_ENV),
- API_KEY: JSON.stringify(process.env.API_KEY),
- AUTH_DOMAIN: JSON.stringify(process.env.AUTH_DOMAIN),
- DATABASE_URL: JSON.stringify(process.env.DATABASE_URL),
- STORAGE_BUCKET: JSON.stringify(process.env.STORAGE_BUCKET),
- PROJECT_ID: JSON.stringify(process.env.PROJECT_ID),
- MESSAGING_SENDER_ID: JSON.stringify(process.env.MESSAGING_SENDER_ID),
- HOST_URL: JSON.stringify(process.env.HOST_URL)
- }
- })
- ] : [
- new webpack.DefinePlugin({
- 'process.env': {
- NODE_ENV: JSON.stringify(process.env.NODE_ENV),
- API_KEY: JSON.stringify(process.env.API_KEY),
- AUTH_DOMAIN: JSON.stringify(process.env.AUTH_DOMAIN),
- DATABASE_URL: JSON.stringify(process.env.DATABASE_URL),
- STORAGE_BUCKET: JSON.stringify(process.env.STORAGE_BUCKET),
- PROJECT_ID: JSON.stringify(process.env.PROJECT_ID),
- MESSAGING_SENDER_ID: JSON.stringify(process.env.MESSAGING_SENDER_ID),
- HOST_URL: JSON.stringify(process.env.HOST_URL)
- }
- })],
- output: {
- path: path.resolve(__dirname, './public'),
- filename: 'bundle.js',
-
- },
- resolve: {
-
- modules: [
- __dirname,
- path.resolve(__dirname, 'node_modules')
+ entry: [
+ './src/index.tsx'
],
- alias: {
- src: 'src',
- components: 'src/components',
- reducers: 'src/reducers',
- constants: 'src/constants',
- core: 'src/core',
- data: 'src/data',
- api: 'src/api',
- layouts: 'src/layouts',
- models: 'src/models',
- store: 'src/store',
- applicationStyles: 'src/styles/app.scss',
- actions: 'src/actions',
- actionTypes: 'src/constants/actionTypes.jsx'
+ externals: {
+ jquery: 'jQuery'
+ },
+ plugins: (process.env.NODE_ENV === 'production') ? [
+ new webpack.optimize.UglifyJsPlugin({
+ minimize: true,
+ compressor: {
+ warnings: false
+ }
+ }),
+ new webpack.DefinePlugin({
+ 'process.env': {
+ NODE_ENV: JSON.stringify(process.env.NODE_ENV),
+ API_KEY: JSON.stringify(process.env.API_KEY),
+ AUTH_DOMAIN: JSON.stringify(process.env.AUTH_DOMAIN),
+ DATABASE_URL: JSON.stringify(process.env.DATABASE_URL),
+ STORAGE_BUCKET: JSON.stringify(process.env.STORAGE_BUCKET),
+ PROJECT_ID: JSON.stringify(process.env.PROJECT_ID),
+ MESSAGING_SENDER_ID: JSON.stringify(process.env.MESSAGING_SENDER_ID),
+ HOST_URL: JSON.stringify(process.env.HOST_URL)
+ }
+ })
+ ] : [
+ new webpack.DefinePlugin({
+ 'process.env': {
+ NODE_ENV: JSON.stringify(process.env.NODE_ENV),
+ API_KEY: JSON.stringify(process.env.API_KEY),
+ AUTH_DOMAIN: JSON.stringify(process.env.AUTH_DOMAIN),
+ DATABASE_URL: JSON.stringify(process.env.DATABASE_URL),
+ STORAGE_BUCKET: JSON.stringify(process.env.STORAGE_BUCKET),
+ PROJECT_ID: JSON.stringify(process.env.PROJECT_ID),
+ MESSAGING_SENDER_ID: JSON.stringify(process.env.MESSAGING_SENDER_ID),
+ HOST_URL: JSON.stringify(process.env.HOST_URL)
+ }
+ })
+ ],
+ output: {
+ path: path.resolve(__dirname, './public'),
+ filename: 'bundle-v0.1.js',
},
- extensions: [' ', '.scss', ".ts", ".tsx", ".js", ".json", '.jsx']
- },
- module: {
- rules: [
- {
- test: /\.ts(x?)$/,
- exclude: /node_modules/,
- use: [
- {
- loader: 'babel-loader',
- options: babelOptions
- },
- {
- loader: 'ts-loader',
- options: { transpileOnly: true }
- }
+ resolve: {
+
+ modules: [
+ __dirname,
+ path.resolve(__dirname, 'node_modules')
+ ],
+ alias: {
+ src: 'src',
+ components: 'src/components',
+ reducers: 'src/reducers',
+ constants: 'src/constants',
+ core: 'src/core',
+ data: 'src/data',
+ api: 'src/api',
+ layouts: 'src/layouts',
+ models: 'src/models',
+ store: 'src/store',
+ applicationStyles: 'src/styles/app.scss',
+ actions: 'src/actions',
+ actionTypes: 'src/constants/actionTypes.jsx'
+
+ },
+ extensions: [' ', '.scss', ".ts", ".tsx", ".js", '.jsx']
+ },
+ module: {
+ rules: [{
+ test: /\.ts(x?)$/,
+ exclude: /node_modules/,
+ use: [{
+ loader: 'babel-loader',
+ options: babelOptions
+ },
+ {
+ loader: 'ts-loader',
+ options: { transpileOnly: true }
+ }
+ ]
+ },
+ {
+ enforce: "pre",
+ test: /\.js$/,
+ loader: "source-map-loader"
+ },
+ {
+ test: /\.js(x?)$/,
+ exclude: /(node_modules|bower_components)/,
+ use: {
+ loader: 'babel-loader',
+ options: babelOptions
+ }
+ },
+ {
+ test: /\.scss$/,
+ use: [{
+ loader: "style-loader"
+ }, {
+ loader: "css-loader"
+ }, {
+ loader: "sass-loader",
+ options: {
+ includePaths: [
+
+ ]
+ }
+ }]
+ },
+ {
+ test: /\.css$/,
+ use: [{
+ loader: "style-loader"
+ }, {
+ loader: "css-loader"
+
+ }]
+ },
+ {
+ test: /\.(woff|woff2|eot|ttf|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
+ loader: 'url-loader'
+ }, {
+ test: /\.(jpe?g|png|webp|gif|cur)$/,
+ loader: 'file-loader?name=/images/[name].[ext]'
+ }
+
+
]
- },
- {
- enforce: "pre",
- test: /\.js$/,
- loader: "source-map-loader"
- },
- {
- test: /\.js(x?)$/,
- exclude: /(node_modules|bower_components)/,
- use: {
- loader: 'babel-loader',
- options: babelOptions
- }
- },
- {
- test: /\.scss$/,
- use: [{
- loader: "style-loader"
- }, {
- loader: "css-loader"
- }, {
- loader: "sass-loader",
- options: {
- includePaths: [
-
- ]
- }
- }]
- },
- {
- test: /\.css$/,
- use: [{
- loader: "style-loader"
- }, {
- loader: "css-loader"
-
- }]
- },
- {
- test: /\.(woff|woff2|eot|ttf|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
- loader: 'url-loader'
- }, {
- test: /\.(jpe?g|png|webp|gif|cur)$/,
- loader: 'file-loader?name=/images/[name].[ext]'
- }
-
-
- ]
- },
- devtool: process.env.NODE_ENV === 'production' ? undefined : 'cheap-module-eval-source-map'
-};
+ },
+ devtool: process.env.NODE_ENV === 'production' ? undefined : 'cheap-module-eval-source-map'
+};
\ No newline at end of file