Add reset password & UI change

This commit is contained in:
Qolzam
2017-11-12 15:31:54 +07:00
parent 9ffd6a1e40
commit 55789967eb
22 changed files with 731 additions and 374 deletions

2
.gitignore vendored
View File

@@ -1,5 +1,5 @@
node_modules/ node_modules/
public/bundle.js public/bundle*.js
config/ config/
.vscode/ .vscode/
src/data/awsClient src/data/awsClient

View File

@@ -5,7 +5,9 @@
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"test": "NODE_ENV=test karma start", "test": "NODE_ENV=test karma start",
"build": "webpack", "build": "NODE_ENV=production webpack -p",
"watch": "webpack -w",
"deploy:firebase": "npm run build && firebase deploy",
"start": "npm run build && node server.js" "start": "npm run build && node server.js"
}, },
"author": "Amir Movahedi", "author": "Amir Movahedi",

View File

@@ -25,7 +25,6 @@
height: 40px; height: 40px;
position: relative; position: relative;
text-align: center; text-align: center;
-webkit-animation: sk-rotate 2.0s infinite linear; -webkit-animation: sk-rotate 2.0s infinite linear;
animation: sk-rotate 2.0s infinite linear; animation: sk-rotate 2.0s infinite linear;
} }
@@ -39,7 +38,6 @@
top: 0; top: 0;
background-color: #333; background-color: #333;
border-radius: 100%; border-radius: 100%;
-webkit-animation: sk-bounce 2.0s infinite ease-in-out; -webkit-animation: sk-bounce 2.0s infinite ease-in-out;
animation: sk-bounce 2.0s infinite ease-in-out; animation: sk-bounce 2.0s infinite ease-in-out;
} }
@@ -100,7 +98,6 @@
-moz-background-clip: text; -moz-background-clip: text;
background-clip: text; background-clip: text;
color: transparent; color: transparent;
font-weight: 100; font-weight: 100;
} }
@@ -125,7 +122,7 @@
</div> </div>
</div> </div>
<script src="/bundle.js"></script> <script src="/bundle-v0.1.js"></script>
</body> </body>
</html> </html>

View File

@@ -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 _____________ */ /* _____________ CRUD State _____________ */
/** /**

View File

@@ -107,7 +107,7 @@ export const dbUpdateComment = (id: string, postId: string, text: string) => {
userId: uid userId: uid
} }
return commentService.updateComment(uid,postId,updatedComment) return commentService.updateComment(id,postId,updatedComment)
.then(() => { .then(() => {
dispatch(updateComment( id, postId, text)) dispatch(updateComment( id, postId, text))
dispatch(globalActions.hideTopLoading()) dispatch(globalActions.hideTopLoading())

View File

@@ -7,6 +7,9 @@ import Paper from 'material-ui/Paper'
import TextField from 'material-ui/TextField' import TextField from 'material-ui/TextField'
import RaisedButton from 'material-ui/RaisedButton' import RaisedButton from 'material-ui/RaisedButton'
import FlatButton from 'material-ui/FlatButton' 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 actions
import * as authorizeActions from 'actions/authorizeActions' import * as authorizeActions from 'actions/authorizeActions'
@@ -16,6 +19,24 @@ import { ILoginComponentState } from './ILoginComponentState'
// - Create Login component class // - Create Login component class
export class LoginComponent extends Component<ILoginComponentProps,ILoginComponentState> { export class LoginComponent extends Component<ILoginComponentProps,ILoginComponentState> {
styles = {
singinOptions: {
paddingBottom: 10
},
divider: {
marginBottom: 10,
marginTop: 15
},
restPassword: {
lineHeight: 6,
fontWeight: 100,
fontSize: 'small'
},
restPasswordLink: {
color: '#0095ff'
}
}
/** /**
* Component constructor * Component constructor
* @param {object} props is an object properties of component * @param {object} props is an object properties of component
@@ -30,6 +51,7 @@ export class LoginComponent extends Component<ILoginComponentProps,ILoginCompone
passwordInputError: '', passwordInputError: '',
confirmInputError: '' confirmInputError: ''
} }
// Binding function to `this` // Binding function to `this`
this.handleForm = this.handleForm.bind(this) this.handleForm = this.handleForm.bind(this)
@@ -136,9 +158,21 @@ export class LoginComponent extends Component<ILoginComponentProps,ILoginCompone
fontWeight: 400, fontWeight: 400,
lineHeight: '32px', lineHeight: '32px',
margin: 0 margin: 0
}}>Sign in</h2> }} className='zoomOutLCorner animated'>Sign in</h2>
</div> </div>
<div style={this.styles.singinOptions}>
<FlatButton
icon={<div className='icon-fb icon'></div>}
/>
<FlatButton
icon={<div className='icon-google icon'></div>}
/>
<FlatButton
icon={<div className='icon-github icon'></div>}
/>
</div>
<Divider style={this.styles.divider} />
<TextField <TextField
onChange={this.handleInputChange} onChange={this.handleInputChange}
errorText={this.state.emailInputError} errorText={this.state.emailInputError}
@@ -167,7 +201,7 @@ export class LoginComponent extends Component<ILoginComponentProps,ILoginCompone
<RaisedButton label='Login' primary={true} onClick={this.handleForm} tabIndex={3} /> <RaisedButton label='Login' primary={true} onClick={this.handleForm} tabIndex={3} />
</div> </div>
</div> </div>
<span style={this.styles.restPassword as any}>Have you forgot your password? <NavLink to='/resetPassword' style={this.styles.restPasswordLink}>reset your password</NavLink></span>
</div> </div>
</Paper> </Paper>
</div> </div>

View File

@@ -11,6 +11,7 @@ import LinearProgress from 'material-ui/LinearProgress'
import Home from 'components/home' import Home from 'components/home'
import Signup from 'components/signup' import Signup from 'components/signup'
import Login from 'components/login' import Login from 'components/login'
import ResetPassword from 'components/resetPassword'
import Setting from 'components/setting' import Setting from 'components/setting'
import MasterLoading from 'components/masterLoading' import MasterLoading from 'components/masterLoading'
import { IMasterComponentProps } from './IMasterComponentProps' import { IMasterComponentProps } from './IMasterComponentProps'
@@ -133,6 +134,7 @@ export class MasterComponent extends Component<IMasterComponentProps, IMasterCom
? (<Switch> ? (<Switch>
<Route path='/signup' component={Signup} /> <Route path='/signup' component={Signup} />
<Route path='/settings' component={Setting} /> <Route path='/settings' component={Setting} />
<Route path='/resetPassword' component={ResetPassword} />
<Route path='/login' render={() => { <Route path='/login' render={() => {
console.log('this.props.authed: ', this.props.authed, 'this.props: ', this.props) console.log('this.props.authed: ', this.props.authed, 'this.props: ', this.props)
return ( return (

View File

@@ -0,0 +1,16 @@
export interface IRestPasswordComponentProps {
/**
* Reset password
*
* @memberof IRestPasswordComponentProps
*/
resetPassword: (email: string) => any
/**
* Redirect to login page
*
* @memberof IRestPasswordComponentProps
*/
loginPage: () => void
}

View File

@@ -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
}

View File

@@ -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<IRestPasswordComponentProps,IRestPasswordComponentState> {
/**
* 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 (
<div>
<h1 style={{
textAlign: 'center',
padding: '20px',
fontSize: '30px',
fontWeight: 500,
lineHeight: '32px',
margin: 'auto',
color: 'rgba(138, 148, 138, 0.2)'
}}>Green</h1>
<div className='animate-bottom'>
<Paper style={paperStyle} zDepth={1} rounded={false} >
<div style={{ padding: '48px 40px 36px' }}>
<div style={{
paddingLeft: '40px',
paddingRight: '40px'
}}>
<h2 style={{
textAlign: 'left',
paddingTop: '16px',
fontSize: '24px',
fontWeight: 400,
lineHeight: '32px',
margin: 0
}} className='zoomOutLCorner animated'>Reset Password</h2>
</div>
<TextField
onChange={this.handleInputChange}
errorText={this.state.emailInputError}
name='emailInput'
floatingLabelStyle={{ fontSize: '15px' }}
floatingLabelText='Email'
type='email'
/><br />
<br />
<br />
<div className='settings__button-box'>
<div>
<FlatButton label='Back' onClick={this.props.loginPage} />
</div>
<div>
<RaisedButton label='Reset password' primary={true} onClick={this.handleForm} />
</div>
</div>
</div>
</Paper>
</div>
</div>
)
}
}
/**
* 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))

View File

@@ -0,0 +1,2 @@
import RestPasswordComponent from './RestPasswordComponent'
export default RestPasswordComponent

View File

@@ -193,7 +193,7 @@ export class SignupComponent extends Component<ISignupComponentProps,ISignupComp
fontSize: '24px', fontSize: '24px',
fontWeight: 400, fontWeight: 400,
lineHeight: '32px', lineHeight: '32px',
margin: 0}}>Sign up</h2> margin: 0}} className='zoomOutLCorner animated'>Sign up</h2>
</div> </div>
<TextField <TextField

View File

@@ -40,5 +40,12 @@ export interface IAuthorizeService {
* *
* @memberof IAuthorizeService * @memberof IAuthorizeService
*/ */
onAuthStateChanged: (callBack: (user: User) => void) onAuthStateChanged: (callBack: (user: User) => void) => void
/**
* Reset user password
*
* @memberof IAuthorizeService
*/
resetPassword: (email: string) => Promise<void>
} }

View File

@@ -12,7 +12,7 @@ export interface ICommentService {
addComment: (postId: string, comment: Comment) => Promise<string> addComment: (postId: string, comment: Comment) => Promise<string>
getComments: (callback: (resultComments: { [postId: string]: { [commentId: string]: Comment } }) => void) => void getComments: (callback: (resultComments: { [postId: string]: { [commentId: string]: Comment } }) => void) => void
updateComment: (userId: string, postId: string, comment: Comment) => Promise<void> updateComment: (commentId: string, postId: string, comment: Comment) => Promise<void>
deleteComment: (commentId: string, postId: string) => Promise<void> deleteComment: (commentId: string, postId: string) => Promise<void>
} }

View File

@@ -12,6 +12,7 @@ try {
messagingSenderId: process.env.MESSAGING_SENDER_ID messagingSenderId: process.env.MESSAGING_SENDER_ID
} }
console.log(firebase)
firebase.initializeApp(config) firebase.initializeApp(config)
} catch (error) { } catch (error) {
console.log('=========Firebase initializer==============') console.log('=========Firebase initializer==============')

View File

@@ -108,8 +108,25 @@ export class AuthorizeService implements IAuthorizeService {
* *
* @memberof IAuthorizeService * @memberof IAuthorizeService
*/ */
onAuthStateChanged: (callBack: (user: User) => void) => any = (callBack) => { public onAuthStateChanged: (callBack: (user: User) => void) => any = (callBack) => {
firebaseAuth().onAuthStateChanged(callBack) firebaseAuth().onAuthStateChanged(callBack)
} }
/**
* Reset user password
*
* @memberof AuthorizeService
*/
public resetPassword: (email: string) => Promise<void> = (email) => {
return new Promise<void>((resolve,reject) => {
let auth = firebaseAuth()
auth.sendPasswordResetEmail(email).then(function () {
resolve()
}).catch((error: any) => {
// An error happened.
reject(new SocialError(error.code, error.message))
})
})
}
} }

View File

@@ -18,7 +18,7 @@ export class CircleService implements ICircleService {
public addCircle: (userId: string, circle: Circle) public addCircle: (userId: string, circle: Circle)
=> Promise<string> = (userId, circle) => { => Promise<string> = (userId, circle) => {
return new Promise<string>((resolve,reject) => { return new Promise<string>((resolve,reject) => {
let circleRef = firebaseRef.child(`userCircles/${userId}/circles`).push(circle) let circleRef = firebaseRef.child(`users/${userId}/circles`).push(circle)
circleRef.then(() => { circleRef.then(() => {
resolve(circleRef.key as string) resolve(circleRef.key as string)
}) })
@@ -35,8 +35,8 @@ export class CircleService implements ICircleService {
return new Promise<void>((resolve,reject) => { return new Promise<void>((resolve,reject) => {
let updates: any = {} let updates: any = {}
updates[`userCircles/${userId}/circles/${circleId}/users/${userFollowingId}`] = userCircle updates[`users/${userId}/circles/${circleId}/users/${userFollowingId}`] = userCircle
updates[`userCircles/${userFollowingId}/circles/-Followers/users/${userId}`] = userFollower updates[`users/${userFollowingId}/circles/-Followers/users/${userId}`] = userFollower
firebaseRef.update(updates).then(() => { firebaseRef.update(updates).then(() => {
resolve() resolve()
@@ -52,8 +52,8 @@ export class CircleService implements ICircleService {
return new Promise<void>((resolve,reject) => { return new Promise<void>((resolve,reject) => {
let updates: any = {} let updates: any = {}
updates[`userCircles/${userId}/circles/${circleId}/users/${userFollowingId}`] = null updates[`users/${userId}/circles/${circleId}/users/${userFollowingId}`] = null
updates[`userCircles/${userFollowingId}/circles/-Followers/users/${userId}`] = null updates[`users/${userFollowingId}/circles/-Followers/users/${userId}`] = null
firebaseRef.update(updates).then(() => { firebaseRef.update(updates).then(() => {
resolve() resolve()
@@ -69,7 +69,7 @@ export class CircleService implements ICircleService {
return new Promise<void>((resolve,reject) => { return new Promise<void>((resolve,reject) => {
let updates: any = {} let updates: any = {}
updates[`userCircles/${userId}/circles/${circleId}`] = circle updates[`users/${userId}/circles/${circleId}`] = circle
firebaseRef.update(updates).then(() => { firebaseRef.update(updates).then(() => {
resolve() resolve()
}) })
@@ -85,7 +85,7 @@ export class CircleService implements ICircleService {
return new Promise<void>((resolve,reject) => { return new Promise<void>((resolve,reject) => {
let updates: any = {} let updates: any = {}
updates[`userCircles/${userId}/circles/${circleId}`] = null updates[`users/${userId}/circles/${circleId}`] = null
firebaseRef.update(updates).then(() => { firebaseRef.update(updates).then(() => {
resolve() resolve()
}) })
@@ -97,7 +97,7 @@ export class CircleService implements ICircleService {
} }
public getCircles: (userId: string) => Promise<{ [circleId: string]: Circle }> = (userId) => { public getCircles: (userId: string) => Promise<{ [circleId: string]: Circle }> = (userId) => {
return new Promise<{ [circleId: string]: Circle }>((resolve,reject) => { 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) => { circlesRef.once('value').then((snapshot: any) => {
let circles: any = snapshot.val() || {} let circles: any = snapshot.val() || {}

View File

@@ -35,12 +35,12 @@ export class CommentService implements ICommentService {
}) })
} }
public updateComment: (userId: string, postId: string, comment: Comment) public updateComment: (commentId: string, postId: string, comment: Comment)
=> Promise<void> = (userId, postId, comment) => { => Promise<void> = (commentId, postId, comment) => {
return new Promise<void>((resolve,reject) => { return new Promise<void>((resolve,reject) => {
let updates: any = {} let updates: any = {}
updates[`postComments/${postId}/${userId}`] = comment updates[`postComments/${postId}/${commentId}`] = comment
firebaseRef.update(updates) firebaseRef.update(updates)
.then(() => { .then(() => {
resolve() resolve()

View File

@@ -1,8 +1,7 @@
@import "base/variables"; @import "base/variables";
@import 'base/grid'; @import 'base/grid';
@import 'base/animate'; @import 'base/animate';
@import 'base/icon';
// Component styles // Component styles
@import 'components/global'; @import 'components/global';
@import 'components/master'; @import 'components/master';
@@ -20,4 +19,3 @@
@import 'components/signup'; @import 'components/signup';
@import 'components/masterLoading'; @import 'components/masterLoading';
@import 'components/settings'; @import 'components/settings';

View File

@@ -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;
}

View File

@@ -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;'); }

View File

@@ -55,10 +55,11 @@ module.exports = {
MESSAGING_SENDER_ID: JSON.stringify(process.env.MESSAGING_SENDER_ID), MESSAGING_SENDER_ID: JSON.stringify(process.env.MESSAGING_SENDER_ID),
HOST_URL: JSON.stringify(process.env.HOST_URL) HOST_URL: JSON.stringify(process.env.HOST_URL)
} }
})], })
],
output: { output: {
path: path.resolve(__dirname, './public'), path: path.resolve(__dirname, './public'),
filename: 'bundle.js', filename: 'bundle-v0.1.js',
}, },
resolve: { resolve: {
@@ -83,15 +84,13 @@ module.exports = {
actionTypes: 'src/constants/actionTypes.jsx' actionTypes: 'src/constants/actionTypes.jsx'
}, },
extensions: [' ', '.scss', ".ts", ".tsx", ".js", ".json", '.jsx'] extensions: [' ', '.scss', ".ts", ".tsx", ".js", '.jsx']
}, },
module: { module: {
rules: [ rules: [{
{
test: /\.ts(x?)$/, test: /\.ts(x?)$/,
exclude: /node_modules/, exclude: /node_modules/,
use: [ use: [{
{
loader: 'babel-loader', loader: 'babel-loader',
options: babelOptions options: babelOptions
}, },