add user settings page
parent
0fcafdc711
commit
8a0c56644c
|
@ -115,6 +115,8 @@ module.exports = {
|
|||
}
|
||||
|
||||
passportHelper.callback(req, res, function (err, user, info, status) {
|
||||
// console.log(err)
|
||||
// console.log(user)
|
||||
if (err || !user) {
|
||||
sails.log.warn(user, err, info, status)
|
||||
if (!err && info) {
|
||||
|
@ -126,6 +128,7 @@ module.exports = {
|
|||
req.login(user, function (err) {
|
||||
if (err) {
|
||||
sails.log.warn(err)
|
||||
// console.log(err)
|
||||
return negotiateError(err)
|
||||
}
|
||||
|
||||
|
@ -135,7 +138,7 @@ module.exports = {
|
|||
if (req.query.next) {
|
||||
res.status(302).set('Location', req.query.next)
|
||||
} else if (req.query.code) { // if came from oauth callback
|
||||
res.status(302).set('Location', '/app')
|
||||
res.status(302).set('Location', '/targets')
|
||||
}
|
||||
|
||||
sails.log.info('user', user, 'authenticated successfully')
|
||||
|
|
|
@ -3,7 +3,7 @@ const HttpError = require('../errors/HttpError')
|
|||
|
||||
module.exports = {
|
||||
show: function (req, res) {
|
||||
res.view('pages/targets', {
|
||||
res.view('pages/app', {
|
||||
email: req.user.email
|
||||
})
|
||||
},
|
||||
|
|
|
@ -17,12 +17,11 @@ module.exports = {
|
|||
error: err.toString()
|
||||
})
|
||||
}
|
||||
|
||||
res.json(user)
|
||||
})
|
||||
},
|
||||
|
||||
update: async function (req, res, next) {
|
||||
edit: async function (req, res, next) {
|
||||
const passportHelper = await sails.helpers.passport()
|
||||
passportHelper.protocols.local.update(req.body, function (err, user) {
|
||||
if (err) {
|
||||
|
@ -30,7 +29,6 @@ module.exports = {
|
|||
error: err.toString()
|
||||
})
|
||||
}
|
||||
|
||||
res.json(user)
|
||||
})
|
||||
},
|
||||
|
|
|
@ -126,3 +126,31 @@ export const setUrl = (value) => async (dispatch, getState) => {
|
|||
dispatch(setWorking(false))
|
||||
}
|
||||
}
|
||||
|
||||
export const editUser = (user) => async (dispatch, getState) => {
|
||||
dispatch(setWorking(true))
|
||||
|
||||
try {
|
||||
if (!user.currentPassword) throw new Error('Please enter your current password.')
|
||||
await Ajax.patch({
|
||||
url: '/api/me',
|
||||
data: {
|
||||
id: user.id,
|
||||
email: user.email,
|
||||
password: user.password,
|
||||
currentPassword: user.currentPassword
|
||||
}
|
||||
})
|
||||
dispatch({
|
||||
type: ACTIONS.error,
|
||||
data: null
|
||||
})
|
||||
} catch (e) {
|
||||
dispatch({
|
||||
type: ACTIONS.error,
|
||||
data: e
|
||||
})
|
||||
} finally {
|
||||
dispatch(setWorking(false))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ export const clearError = () => ({
|
|||
|
||||
export const setLoggedIn = (data) => (dispatch, getState) => {
|
||||
window.localStorage.setItem('roe-token', JSON.stringify(data))
|
||||
window.location.href = '/app'
|
||||
window.location.href = '/targets'
|
||||
}
|
||||
|
||||
export const checkEmail = email => async (dispatch, getState) => {
|
||||
|
|
|
@ -2,10 +2,12 @@
|
|||
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import { BrowserRouter as Router, Route, NavLink, Switch, Redirect } from 'react-router-dom'
|
||||
import Progress from './components/Progress'
|
||||
import UriListItem from './containers/UriListItem'
|
||||
import reducer from './reducers'
|
||||
import { fetchData, createNewUrl, setEditing } from './actions'
|
||||
import { fetchData, createNewUrl, setEditing, editUser } from './actions'
|
||||
import UnderlineInput from './components/UnderlineInput'
|
||||
import '../styles/index.scss'
|
||||
|
||||
class App extends React.Component {
|
||||
|
@ -14,8 +16,10 @@ class App extends React.Component {
|
|||
this.state = {
|
||||
error: '',
|
||||
user: {
|
||||
id: '',
|
||||
email: '',
|
||||
password: ''
|
||||
password: '',
|
||||
currentPassword: ''
|
||||
},
|
||||
urls: [],
|
||||
editingUrl: null,
|
||||
|
@ -24,6 +28,8 @@ class App extends React.Component {
|
|||
|
||||
this.dispatch = this.dispatch.bind(this)
|
||||
this.getRegisteredUris = this.getRegisteredUris.bind(this)
|
||||
this.setUserValue = this.setUserValue.bind(this)
|
||||
this.saveUser = this.saveUser.bind(this)
|
||||
}
|
||||
dispatch (action) {
|
||||
if (!action) throw new Error('dispatch: missing action')
|
||||
|
@ -49,33 +55,97 @@ class App extends React.Component {
|
|||
editing={this.state.editingUrl === item.id} />)
|
||||
})
|
||||
}
|
||||
setUserValue (which, e) {
|
||||
this.setState({
|
||||
user: {
|
||||
...this.state.user,
|
||||
[which]: e.target.value
|
||||
}
|
||||
})
|
||||
}
|
||||
saveUser () {
|
||||
this.dispatch(editUser(this.state.user))
|
||||
this.setState({
|
||||
user: {
|
||||
...this.state.user,
|
||||
email: this.state.user.email,
|
||||
password: '',
|
||||
currentPassword: ''
|
||||
}
|
||||
})
|
||||
}
|
||||
render () {
|
||||
return (
|
||||
<div className='root-container flex-container' onClick={() => this.dispatch(setEditing(null))}>
|
||||
<aside className='nav nav-left'>
|
||||
<header>
|
||||
<h1>River of Ebooks</h1>
|
||||
<h2 className='flex-container'>
|
||||
<span className='flex'>{this.state.user.email}</span>
|
||||
<a href='/logout'>Log out</a>
|
||||
</h2>
|
||||
</header>
|
||||
</aside>
|
||||
<section className={'content flex' + (this.state.working ? ' working' : '')}>
|
||||
<Progress bound />
|
||||
{this.state.error && <div className='error-box'>{this.state.error}</div>}
|
||||
<header className='flex-container'>
|
||||
<div className='flex'>
|
||||
<h1>Push URIs</h1>
|
||||
<h2>Newly published books will be sent to these addresses.</h2>
|
||||
</div>
|
||||
<button className='btn' onClick={() => this.dispatch(createNewUrl())}>New address</button>
|
||||
</header>
|
||||
<ul className='list'>
|
||||
{this.getRegisteredUris()}
|
||||
</ul>
|
||||
</section>
|
||||
</div>
|
||||
<Router>
|
||||
<div className='root-container flex-container' onClick={() => this.dispatch(setEditing(null))}>
|
||||
<aside className='nav nav-left'>
|
||||
<header>
|
||||
<h1>River of Ebooks</h1>
|
||||
<h2 className='flex-container'>
|
||||
<span className='flex'>{this.state.user.email}</span>
|
||||
<a href='/logout'>Log out</a>
|
||||
</h2>
|
||||
</header>
|
||||
<ul>
|
||||
<li><NavLink to='/targets'>Push URIs</NavLink></li>
|
||||
<li><NavLink to='/account'>My account</NavLink></li>
|
||||
</ul>
|
||||
</aside>
|
||||
<section className={'content flex' + (this.state.working ? ' working' : '')}>
|
||||
<Progress bound />
|
||||
{this.state.error && <div className='error-box'>{this.state.error}</div>}
|
||||
<Switch>
|
||||
<Route path='/targets' exact children={props => (
|
||||
<div>
|
||||
<header className='flex-container'>
|
||||
<div className='flex'>
|
||||
<h1>Push URIs</h1>
|
||||
<h2>Newly published books will be sent to these addresses.</h2>
|
||||
</div>
|
||||
<button className='btn' onClick={() => this.dispatch(createNewUrl())}>New address</button>
|
||||
</header>
|
||||
<ul className='list'>
|
||||
{this.getRegisteredUris()}
|
||||
</ul>
|
||||
</div>
|
||||
)} />
|
||||
|
||||
<Route path='/account' exact children={props => (
|
||||
<div>
|
||||
<header className='flex-container'>
|
||||
<div className='flex'>
|
||||
<h1>My account</h1>
|
||||
<h2>User account settings</h2>
|
||||
</div>
|
||||
</header>
|
||||
<section className='inputs'>
|
||||
<UnderlineInput
|
||||
placeholder='Email address'
|
||||
value={this.state.user.email}
|
||||
pattern={/^([a-zA-Z0-9_\-.]+)@([a-zA-Z0-9_\-.]+)\.([a-zA-Z]{2,5})$/}
|
||||
onChange={(e) => this.setUserValue('email', e)} />
|
||||
<UnderlineInput
|
||||
placeholder='Password'
|
||||
type='password'
|
||||
value={this.state.user.password}
|
||||
onChange={(e) => this.setUserValue('password', e)} />
|
||||
<UnderlineInput
|
||||
placeholder='Current password'
|
||||
type='password'
|
||||
value={this.state.user.currentPassword}
|
||||
onChange={(e) => this.setUserValue('currentPassword', e)} />
|
||||
<div className='buttons'>
|
||||
<button className='btn' onClick={this.saveUser}>Save</button>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
)} />
|
||||
|
||||
<Route path='/' render={() => <Redirect to='/targets' />} />
|
||||
</Switch>
|
||||
</section>
|
||||
</div>
|
||||
</Router>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -108,8 +108,8 @@ class App extends React.Component {
|
|||
error={this.state.passwordError}
|
||||
button='Sign in'
|
||||
onButtonClick={() => this.dispatch(checkPassword(this.state.user.email, this.state.user.password))}
|
||||
smallButton='Forgot password?'
|
||||
onSmallButtonClick={() => this.dispatch(setCarousel(3))} />
|
||||
comment={null/*smallButton='Forgot password?'
|
||||
onSmallButtonClick={() => this.dispatch(setCarousel(3))}*/} />
|
||||
|
||||
<CarouselItem
|
||||
header='Password recovery'
|
||||
|
|
|
@ -43,7 +43,7 @@ const reducer = (state = {}, action) => {
|
|||
}
|
||||
case Actions.error:
|
||||
return {
|
||||
error: data.message
|
||||
error: (data || {}).message || ''
|
||||
}
|
||||
default: return {}
|
||||
}
|
||||
|
|
|
@ -13,9 +13,10 @@
|
|||
padding: 0 14px;
|
||||
margin: -14px 0 8px 0;
|
||||
}
|
||||
& > header {
|
||||
padding: 0 14px;
|
||||
|
||||
& > div {
|
||||
& > header {
|
||||
padding: 0 14px;
|
||||
}
|
||||
h1 {
|
||||
text-shadow: 1px 1px 2px $black-3;
|
||||
}
|
||||
|
@ -35,6 +36,14 @@
|
|||
list-style: none;
|
||||
// overflow: hidden;
|
||||
}
|
||||
.inputs {
|
||||
padding: 20px 14px;
|
||||
|
||||
.buttons {
|
||||
margin-top: 14px;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
&.working {
|
||||
& > .progress {
|
||||
top: 0;
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
box-shadow: $shadow-1;
|
||||
|
||||
header {
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
padding: 0 14px;
|
||||
|
||||
|
|
|
@ -66,7 +66,48 @@ module.exports.protocols = {
|
|||
}
|
||||
},
|
||||
update: async function (user, next) {
|
||||
throw new Error('not implemented')
|
||||
try {
|
||||
const dbUser = await User.findOne({
|
||||
id: user.id
|
||||
})
|
||||
if (!dbUser) throw new Error('an account with that id was not found')
|
||||
|
||||
const passport = await Passport.findOne({
|
||||
protocol: 'local',
|
||||
user: user.id
|
||||
})
|
||||
if (!user.currentPassword && passport) throw new Error('Missing current password')
|
||||
if (passport) {
|
||||
const res = await Passport.validatePassword(user.currentPassword, passport)
|
||||
if (!res) throw new Error('incorrect password')
|
||||
|
||||
await User.update({ id: user.id }, {
|
||||
email: user.email
|
||||
})
|
||||
if (user.password && user.password.length) {
|
||||
await Passport.update({ id: passport.id }, {
|
||||
password: user.password
|
||||
})
|
||||
}
|
||||
} else { // no password yet, add one
|
||||
await User.update({ id: user.id }, {
|
||||
email: user.email
|
||||
})
|
||||
if (user.password && user.password.length) {
|
||||
const token = generateToken()
|
||||
await Passport.create({
|
||||
protocol: 'local',
|
||||
password: user.password,
|
||||
user: dbUser.id,
|
||||
accesstoken: token
|
||||
})
|
||||
}
|
||||
}
|
||||
delete dbUser.password
|
||||
next(null, dbUser)
|
||||
} catch (e) {
|
||||
return next(e)
|
||||
}
|
||||
},
|
||||
connect: async function (req, res, next) {
|
||||
try {
|
||||
|
|
|
@ -31,7 +31,9 @@ module.exports.routes = {
|
|||
'GET /register': {
|
||||
view: 'pages/login'
|
||||
},
|
||||
'GET /app': 'TargetController.show',
|
||||
// figure out why proper clientside routing breaks the backend session
|
||||
'GET /account': 'TargetController.show',
|
||||
'GET /targets': 'TargetController.show',
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
|
@ -55,6 +57,8 @@ module.exports.routes = {
|
|||
'POST /auth/email_available': 'AuthController.emailAvailable',
|
||||
// 'POST /auth/local': 'AuthController.callback',
|
||||
// 'POST /auth/local/:action': 'AuthController.callback',
|
||||
'GET /api/me': 'UserController.me',
|
||||
'PATCH /api/me': 'UserController.edit',
|
||||
|
||||
'POST /auth/:provider': 'AuthController.callback',
|
||||
'POST /auth/:provider/:action': 'AuthController.callback',
|
||||
|
@ -64,9 +68,7 @@ module.exports.routes = {
|
|||
'GET /auth/:provider/:action': 'AuthController.callback',
|
||||
|
||||
'POST /api/publish': 'BooksController.publish',
|
||||
|
||||
'GET /api/books': 'BooksController.list',
|
||||
'GET /api/me': 'UserController.me',
|
||||
|
||||
'POST /api/targets': 'TargetController.create',
|
||||
'PATCH /api/targets/:id': 'TargetController.edit',
|
||||
|
|
|
@ -62,6 +62,7 @@
|
|||
"mocha": "^5.2.0",
|
||||
"node-sass": "^4.9.4",
|
||||
"npm-run-all": "^4.1.3",
|
||||
"react-router-dom": "^4.3.1",
|
||||
"rimraf": "^2.6.2",
|
||||
"sass-loader": "^7.1.0",
|
||||
"standard": "^12.0.1",
|
||||
|
|
104
shrinkwrap.yaml
104
shrinkwrap.yaml
|
@ -1,5 +1,7 @@
|
|||
dependencies:
|
||||
request: 2.88.0
|
||||
devDependencies:
|
||||
react-router-dom: 4.3.1
|
||||
packages:
|
||||
/ajv/6.8.1:
|
||||
dependencies:
|
||||
|
@ -136,6 +138,20 @@ packages:
|
|||
node: '>=6'
|
||||
resolution:
|
||||
integrity: sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==
|
||||
/history/4.7.2:
|
||||
dependencies:
|
||||
invariant: 2.2.4
|
||||
loose-envify: 1.4.0
|
||||
resolve-pathname: 2.2.0
|
||||
value-equal: 0.4.0
|
||||
warning: 3.0.0
|
||||
dev: true
|
||||
resolution:
|
||||
integrity: sha512-1zkBRWW6XweO0NBcjiphtVJVsIQ+SXF29z9DVkceeaSLVMFXHool+fdCZD4spDCfZJCILPILc3bm7Bc+HRi0nA==
|
||||
/hoist-non-react-statics/2.5.5:
|
||||
dev: true
|
||||
resolution:
|
||||
integrity: sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw==
|
||||
/http-signature/1.2.0:
|
||||
dependencies:
|
||||
assert-plus: 1.0.0
|
||||
|
@ -147,14 +163,28 @@ packages:
|
|||
npm: '>=1.3.7'
|
||||
resolution:
|
||||
integrity: sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=
|
||||
/invariant/2.2.4:
|
||||
dependencies:
|
||||
loose-envify: 1.4.0
|
||||
dev: true
|
||||
resolution:
|
||||
integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==
|
||||
/is-typedarray/1.0.0:
|
||||
dev: false
|
||||
resolution:
|
||||
integrity: sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=
|
||||
/isarray/0.0.1:
|
||||
dev: true
|
||||
resolution:
|
||||
integrity: sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=
|
||||
/isstream/0.1.2:
|
||||
dev: false
|
||||
resolution:
|
||||
integrity: sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=
|
||||
/js-tokens/4.0.0:
|
||||
dev: true
|
||||
resolution:
|
||||
integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
|
||||
/jsbn/0.1.1:
|
||||
dev: false
|
||||
resolution:
|
||||
|
@ -182,6 +212,13 @@ packages:
|
|||
'0': node >=0.6.0
|
||||
resolution:
|
||||
integrity: sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=
|
||||
/loose-envify/1.4.0:
|
||||
dependencies:
|
||||
js-tokens: 4.0.0
|
||||
dev: true
|
||||
hasBin: true
|
||||
resolution:
|
||||
integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
|
||||
/mime-db/1.37.0:
|
||||
dev: false
|
||||
engines:
|
||||
|
@ -200,10 +237,29 @@ packages:
|
|||
dev: false
|
||||
resolution:
|
||||
integrity: sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
|
||||
/object-assign/4.1.1:
|
||||
dev: true
|
||||
engines:
|
||||
node: '>=0.10.0'
|
||||
resolution:
|
||||
integrity: sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
|
||||
/path-to-regexp/1.7.0:
|
||||
dependencies:
|
||||
isarray: 0.0.1
|
||||
dev: true
|
||||
resolution:
|
||||
integrity: sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=
|
||||
/performance-now/2.1.0:
|
||||
dev: false
|
||||
resolution:
|
||||
integrity: sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
|
||||
/prop-types/15.6.2:
|
||||
dependencies:
|
||||
loose-envify: 1.4.0
|
||||
object-assign: 4.1.1
|
||||
dev: true
|
||||
resolution:
|
||||
integrity: sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ==
|
||||
/psl/1.1.31:
|
||||
dev: false
|
||||
resolution:
|
||||
|
@ -224,6 +280,33 @@ packages:
|
|||
node: '>=0.6'
|
||||
resolution:
|
||||
integrity: sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==
|
||||
/react-router-dom/4.3.1:
|
||||
dependencies:
|
||||
history: 4.7.2
|
||||
invariant: 2.2.4
|
||||
loose-envify: 1.4.0
|
||||
prop-types: 15.6.2
|
||||
react-router: 4.3.1
|
||||
warning: 4.0.2
|
||||
dev: true
|
||||
peerDependencies:
|
||||
react: '>=15'
|
||||
resolution:
|
||||
integrity: sha512-c/MlywfxDdCp7EnB7YfPMOfMD3tOtIjrQlj/CKfNMBxdmpJP8xcz5P/UAFn3JbnQCNUxsHyVVqllF9LhgVyFCA==
|
||||
/react-router/4.3.1:
|
||||
dependencies:
|
||||
history: 4.7.2
|
||||
hoist-non-react-statics: 2.5.5
|
||||
invariant: 2.2.4
|
||||
loose-envify: 1.4.0
|
||||
path-to-regexp: 1.7.0
|
||||
prop-types: 15.6.2
|
||||
warning: 4.0.2
|
||||
dev: true
|
||||
peerDependencies:
|
||||
react: '>=15'
|
||||
resolution:
|
||||
integrity: sha512-yrvL8AogDh2X42Dt9iknk4wF4V8bWREPirFfS9gLU1huk6qK41sg7Z/1S81jjTrGHxa3B8R3J6xIkDAA6CVarg==
|
||||
/request/2.88.0:
|
||||
dependencies:
|
||||
aws-sign2: 0.7.0
|
||||
|
@ -251,6 +334,10 @@ packages:
|
|||
node: '>= 4'
|
||||
resolution:
|
||||
integrity: sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==
|
||||
/resolve-pathname/2.2.0:
|
||||
dev: true
|
||||
resolution:
|
||||
integrity: sha512-bAFz9ld18RzJfddgrO2e/0S2O81710++chRMUxHjXOYKF6jTAMrUNZrEZ1PvV0zlhfjidm08iRPdTLPno1FuRg==
|
||||
/safe-buffer/5.1.2:
|
||||
dev: false
|
||||
resolution:
|
||||
|
@ -306,6 +393,10 @@ packages:
|
|||
hasBin: true
|
||||
resolution:
|
||||
integrity: sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==
|
||||
/value-equal/0.4.0:
|
||||
dev: true
|
||||
resolution:
|
||||
integrity: sha512-x+cYdNnaA3CxvMaTX0INdTCN8m8aF2uY9BvEqmxuYp8bL09cs/kWVQPVGcA35fMktdOsP69IgU7wFj/61dJHEw==
|
||||
/verror/1.10.0:
|
||||
dependencies:
|
||||
assert-plus: 1.0.0
|
||||
|
@ -316,8 +407,21 @@ packages:
|
|||
'0': node >=0.6.0
|
||||
resolution:
|
||||
integrity: sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=
|
||||
/warning/3.0.0:
|
||||
dependencies:
|
||||
loose-envify: 1.4.0
|
||||
dev: true
|
||||
resolution:
|
||||
integrity: sha1-MuU3fLVy3kqwR1O9+IIcAe1gW3w=
|
||||
/warning/4.0.2:
|
||||
dependencies:
|
||||
loose-envify: 1.4.0
|
||||
dev: true
|
||||
resolution:
|
||||
integrity: sha512-wbTp09q/9C+jJn4KKJfJfoS6VleK/Dti0yqWSm6KMvJ4MRCXFQNapHuJXutJIrWV0Cf4AhTdeIe4qdKHR1+Hug==
|
||||
registry: 'https://registry.npmjs.org/'
|
||||
shrinkwrapMinorVersion: 9
|
||||
shrinkwrapVersion: 3
|
||||
specifiers:
|
||||
react-router-dom: ^4.3.1
|
||||
request: ^2.88.0
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
<%- partial('../../.tmp/public/index.html') %>
|
|
@ -1 +0,0 @@
|
|||
<%- partial('../../.tmp/public/targets.html') %>
|
Loading…
Reference in New Issue