Get app working against deployed service

This commit is contained in:
John Lyon-Smith
2018-04-08 21:25:17 -07:00
parent d674f5e7eb
commit ee836def93
9 changed files with 141 additions and 86 deletions

View File

@@ -21,7 +21,7 @@
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>????</string> <string>????</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>20180407.3</string> <string>20180408.0</string>
<key>LSRequiresIPhoneOS</key> <key>LSRequiresIPhoneOS</key>
<true/> <true/>
<key>NSAppTransportSecurity</key> <key>NSAppTransportSecurity</key>

View File

@@ -2,21 +2,14 @@ import EventEmitter from "eventemitter3"
import io from "socket.io-client" import io from "socket.io-client"
import { AsyncStorage } from "react-native" import { AsyncStorage } from "react-native"
const authTokenName = "AuthToken" const authTokenKeyName = "AuthToken"
const backendName = "backendName" const backendKeyName = "BackendName"
let baseURL = null // if (__DEV__) {
let apiPath = null // const localIPAddr = process.env.LOCAL_IP_ADDR
// // baseURL = `http://${localIPAddr || "localhost"}:3001`
if (__DEV__) { // apiPath = ""
const localIPAddr = process.env.LOCAL_IP_ADDR // }
baseURL = `http://${localIPAddr || "localhost"}:3001`
apiPath = ""
} else {
baseURL = "https://dar.kss.us.com"
apiPath = "/api"
}
class NetworkError extends Error { class NetworkError extends Error {
constructor(message) { constructor(message) {
@@ -48,16 +41,20 @@ class API extends EventEmitter {
super() super()
this.user = { pending: true } this.user = { pending: true }
AsyncStorage.getItem(backendName) // AsyncStorage.getItem(backendKeyName)
.then((backend) => { // .then((backend) => {
this.backend = backend // this.backend = backend
}) // })
.catch((err) => { // .catch((err) => {
this.backend = "normal" // this.backend = "normal"
AsyncStorage.setItem(backendName, this.backend) // AsyncStorage.setItem(backendKeyName, this.backend)
}) // })
AsyncStorage.getItem(authTokenName) this.backendName = "normal"
this.baseURL = "https://dar.kss.us.com"
this.apiPath = "/api"
AsyncStorage.getItem(authTokenKeyName)
.then((token) => { .then((token) => {
if (!token) { if (!token) {
return Promise.reject() return Promise.reject()
@@ -72,7 +69,7 @@ class API extends EventEmitter {
this.emit("login") this.emit("login")
}) })
.catch((err) => { .catch((err) => {
AsyncStorage.removeItem(authTokenName) AsyncStorage.removeItem(authTokenKeyName)
this.token = null this.token = null
this.user = {} this.user = {}
this.socket = null this.socket = null
@@ -81,8 +78,8 @@ class API extends EventEmitter {
} }
connectSocket() { connectSocket() {
this.socket = io(baseURL, { this.socket = io(this.baseURL, {
path: apiPath + "/socketio", path: this.apiPath + "/socketio",
query: { query: {
auth_token: this.token, auth_token: this.token,
}, },
@@ -117,14 +114,14 @@ class API extends EventEmitter {
} }
get backend() { get backend() {
return this.backend return this.backendName
} }
makeImageUrl(id, size) { makeImageUrl(id, size) {
if (id) { if (id) {
return apiPath + "/assets/" + id + "?access_token=" + this.token return this.apiPath + "/assets/" + id + "?access_token=" + this.token
} else if (size && size.width && size.height) { } else if (size && size.width && size.height) {
return `${apiPath}/placeholders/${size.width}x${ return `${this.apiPath}/placeholders/${size.width}x${
size.height size.height
}?access_token=${this.token}` }?access_token=${this.token}`
} else { } else {
@@ -133,7 +130,9 @@ class API extends EventEmitter {
} }
makeAssetUrl(id) { makeAssetUrl(id) {
return id ? apiPath + "/assets/" + id + "?access_token=" + this.token : null return id
? this.apiPath + "/assets/" + id + "?access_token=" + this.token
: null
} }
static makeParams(params) { static makeParams(params) {
@@ -169,7 +168,7 @@ class API extends EventEmitter {
} }
} }
fetchOptions.headers = headers fetchOptions.headers = headers
fetch(this.apiURL + path, fetchOptions) fetch(this.baseURL + this.apiPath + path, fetchOptions)
.then((res) => { .then((res) => {
return Promise.all([ return Promise.all([
Promise.resolve(res), Promise.resolve(res),
@@ -221,7 +220,7 @@ class API extends EventEmitter {
} }
if (remember) { if (remember) {
AsyncStorage.setItem(authTokenName, token) AsyncStorage.setItem(authTokenKeyName, token)
} }
this.token = token this.token = token
this.user = response.body this.user = response.body
@@ -237,7 +236,7 @@ class API extends EventEmitter {
logout() { logout() {
let cb = () => { let cb = () => {
// Regardless of response, always logout in the client // Regardless of response, always logout in the client
AsyncStorage.removeItem(authTokenName) AsyncStorage.removeItem(authTokenKeyName)
this.token = null this.token = null
this.user = {} this.user = {}
this.disconnectSocket() this.disconnectSocket()

View File

@@ -173,7 +173,7 @@ export class Login extends React.Component {
color: "lightgray", color: "lightgray",
fontSize: 10, fontSize: 10,
}}> }}>
{versionInfo.version} {versionInfo.fullVersion}
</Text> </Text>
</View> </View>
<MessageModal <MessageModal

View File

@@ -4,6 +4,7 @@ import PropTypes from "prop-types"
import { View, Text, TouchableOpacity } from "react-native" import { View, Text, TouchableOpacity } from "react-native"
import { Icon, OptionStrip } from "../ui" import { Icon, OptionStrip } from "../ui"
import autobind from "autobind-decorator" import autobind from "autobind-decorator"
import { api } from "../API"
export class ApiModal extends Component { export class ApiModal extends Component {
static propTypes = { static propTypes = {
@@ -14,7 +15,7 @@ export class ApiModal extends Component {
constructor(props) { constructor(props) {
super(props) super(props)
this.state = { this.state = {
value: null, value: api.backend,
} }
} }

View File

@@ -1,6 +1,6 @@
export const versionInfo = { export const versionInfo = {
version: '1.0.0', version: '1.0.0',
fullVersion: '1.0.0-20180407.3', fullVersion: '1.0.0-20180408.0',
title: 'Deighton AR System', title: 'Deighton AR System',
copyright: '© 2018, Kingston Software Solutions.', copyright: '© 2018, Kingston Software Solutions.',
supportEmail: 'support@kss.us.com', supportEmail: 'support@kss.us.com',

View File

@@ -15,8 +15,8 @@
major: 1, major: 1,
minor: 0, minor: 0,
patch: 0, patch: 0,
build: 20180407, build: 20180408,
revision: 3, revision: 0,
sequence: 1, sequence: 1,
tz: "America/Los_Angeles", tz: "America/Los_Angeles",
title: "Deighton AR System", title: "Deighton AR System",

View File

@@ -20,9 +20,10 @@
}, },
"rules": { "rules": {
"key-spacing": 0, "key-spacing": 0,
"jsx-quotes": [2, "prefer-single"],
"object-curly-spacing": [2, "always"], "object-curly-spacing": [2, "always"],
"space-before-function-paren": ["error", "never"], "space-before-function-paren": ["error", "never"],
"comma-dangle": ["error", "only-multiline"] "comma-dangle": ["error", "only-multiline"],
"jsx-quotes": "off",
"quotes": "off"
} }
} }

View File

@@ -1,18 +1,26 @@
import React, { Component, Fragment } from 'react' import React, { Component, Fragment } from "react"
import { Login, Logout, ResetPassword, ForgotPassword, ConfirmEmail, ProtectedRoute, DefaultRoute } from './Auth' import {
import { Home } from './Home' Login,
import { Profile } from './Profile' Logout,
import { Users } from './Users' ResetPassword,
import { Teams } from './Teams' ForgotPassword,
import { System } from './System' ConfirmEmail,
import { HeaderButton, HeaderText, Column, Row, Text, Box } from 'ui' ProtectedRoute,
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom' DefaultRoute,
import logoImage from 'images/logo.png' } from "./Auth"
import { versionInfo } from './version' import { Home } from "./Home"
import { sizeInfo, colorInfo } from 'ui/style' import { Profile } from "./Profile"
import { api } from 'src/API' import { Users } from "./Users"
import PropTypes from 'prop-types' import { Teams } from "./Teams"
import autobind from 'autobind-decorator' import { System } from "./System"
import { HeaderButton, HeaderText, Column, Row, Text, Box } from "ui"
import { BrowserRouter as Router, Route, Switch } from "react-router-dom"
import logoImage from "images/logo.png"
import { versionInfo } from "./version"
import { sizeInfo, colorInfo } from "ui/style"
import { api } from "src/API"
import PropTypes from "prop-types"
import autobind from "autobind-decorator"
export class App extends Component { export class App extends Component {
static propTypes = { static propTypes = {
@@ -22,18 +30,18 @@ export class App extends Component {
constructor(props) { constructor(props) {
super(props) super(props)
this.state = { this.state = {
loggedInUser: api.loggedInUser loggedInUser: api.loggedInUser,
} }
} }
componentDidMount() { componentDidMount() {
api.addListener('login', this.handleUpdate) api.addListener("login", this.handleUpdate)
api.addListener('logout', this.handleUpdate) api.addListener("logout", this.handleUpdate)
} }
componentWillUnmount() { componentWillUnmount() {
api.removeListener('login', this.handleUpdate) api.removeListener("login", this.handleUpdate)
api.removeListener('logout', this.handleUpdate) api.removeListener("logout", this.handleUpdate)
} }
@autobind @autobind
@@ -43,15 +51,15 @@ export class App extends Component {
handleLogout() { handleLogout() {
// We have to use window here because App does not have history in it's props // We have to use window here because App does not have history in it's props
window.location.replace('/logout') window.location.replace("/logout")
} }
handleHome() { handleHome() {
window.location.replace('/') window.location.replace("/")
} }
handleProfile() { handleProfile() {
window.location.replace('/profile') window.location.replace("/profile")
} }
@autobind @autobind
@@ -73,20 +81,25 @@ export class App extends Component {
) )
headerButtonsRight = ( headerButtonsRight = (
<Fragment> <Fragment>
<HeaderButton icon='profile' onClick={this.handleProfile} /> <HeaderButton icon="profile" onClick={this.handleProfile} />
<HeaderButton icon='logout' onClick={this.handleLogout} /> <HeaderButton icon="logout" onClick={this.handleLogout} />
</Fragment> </Fragment>
) )
} }
return ( return (
<Router basename='/'> <Router basename="/">
<Column minHeight='100vh'> <Column minHeight="100vh">
<Column.Item height={sizeInfo.headerHeight - sizeInfo.headerBorderWidth}> <Column.Item
<Box background={colorInfo.headerButtonBackground} height={sizeInfo.headerHeight - sizeInfo.headerBorderWidth}>
borderBottom={{ width: sizeInfo.headerBorderWidth, color: colorInfo.headerBorder }} <Box
style={{ boxSizing: 'content' }}> background={colorInfo.headerButtonBackground}
<Row minWidth='100vw'> borderBottom={{
width: sizeInfo.headerBorderWidth,
color: colorInfo.headerBorder,
}}
style={{ boxSizing: "content" }}>
<Row minWidth="100vw">
<Row.Item>{headerButtonsLeft}</Row.Item> <Row.Item>{headerButtonsLeft}</Row.Item>
<Row.Item grow /> <Row.Item grow />
<Row.Item>{headerButtonsRight}</Row.Item> <Row.Item>{headerButtonsRight}</Row.Item>
@@ -94,21 +107,62 @@ export class App extends Component {
</Box> </Box>
</Column.Item> </Column.Item>
<Switch> <Switch>
<Route exact path='/login' component={Login} /> <Route exact path="/login" component={Login} />
<Route exact path='/logout' component={Logout} /> <Route exact path="/logout" component={Logout} />
<Route exact path='/confirm-email' component={ConfirmEmail} /> <Route exact path="/confirm-email" component={ConfirmEmail} />
<Route exact path='/reset-password' component={ResetPassword} /> <Route exact path="/reset-password" component={ResetPassword} />
<Route exact path='/forgot-password' component={ForgotPassword} /> <Route exact path="/forgot-password" component={ForgotPassword} />
<ProtectedRoute exact path='/profile' render={props => (<Profile {...props} changeTitle={this.handleChangeTitle} />)} /> <ProtectedRoute
<ProtectedRoute exact admin path='/users' render={props => (<Users {...props} changeTitle={this.handleChangeTitle} />)} /> exact
<ProtectedRoute exact admin path='/teams' render={props => (<Teams {...props} changeTitle={this.handleChangeTitle} />)} /> path="/profile"
<ProtectedRoute exact admin path='/system' render={props => (<System {...props} changeTitle={this.handleChangeTitle} />)} /> render={(props) => (
<ProtectedRoute exact admin path='/home' render={props => (<Home {...props} changeTitle={this.handleChangeTitle} />)} /> <Profile {...props} changeTitle={this.handleChangeTitle} />
)}
/>
<ProtectedRoute
exact
admin
path="/users"
render={(props) => (
<Users {...props} changeTitle={this.handleChangeTitle} />
)}
/>
<ProtectedRoute
exact
admin
path="/teams"
render={(props) => (
<Teams {...props} changeTitle={this.handleChangeTitle} />
)}
/>
<ProtectedRoute
exact
admin
path="/system"
render={(props) => (
<System {...props} changeTitle={this.handleChangeTitle} />
)}
/>
<ProtectedRoute
exact
admin
path="/home"
render={(props) => (
<Home {...props} changeTitle={this.handleChangeTitle} />
)}
/>
<DefaultRoute /> <DefaultRoute />
</Switch> </Switch>
<Column.Item> <Column.Item>
<Box background={colorInfo.headerButtonBackground} borderTop={{ width: sizeInfo.headerBorderWidth, color: colorInfo.headerBorder }}> <Box
<Text color='dimmed' margin={sizeInfo.footerTextMargin}>{'v' + versionInfo.version} {versionInfo.copyright}</Text> background={colorInfo.headerButtonBackground}
borderTop={{
width: sizeInfo.headerBorderWidth,
color: colorInfo.headerBorder,
}}>
<Text color="dimmed" margin={sizeInfo.footerTextMargin}>
{"v" + versionInfo.fullVersion} {versionInfo.copyright}
</Text>
</Box> </Box>
</Column.Item> </Column.Item>
</Column> </Column>

View File

@@ -1,6 +1,6 @@
export const versionInfo = { export const versionInfo = {
version: '1.0.0', version: '1.0.0',
fullVersion: '1.0.0-20180407.3', fullVersion: '1.0.0-20180408.0',
title: 'Deighton AR System', title: 'Deighton AR System',
copyright: '© 2018, Kingston Software Solutions.', copyright: '© 2018, Kingston Software Solutions.',
supportEmail: 'support@kss.us.com', supportEmail: 'support@kss.us.com',