Start adding API selection modal and supporting code
This commit is contained in:
@@ -3,6 +3,8 @@ import io from "socket.io-client"
|
|||||||
import { AsyncStorage } from "react-native"
|
import { AsyncStorage } from "react-native"
|
||||||
|
|
||||||
const authTokenName = "AuthToken"
|
const authTokenName = "AuthToken"
|
||||||
|
const backendName = "backendName"
|
||||||
|
|
||||||
let baseURL = null
|
let baseURL = null
|
||||||
let apiPath = null
|
let apiPath = null
|
||||||
//
|
//
|
||||||
@@ -46,6 +48,15 @@ class API extends EventEmitter {
|
|||||||
super()
|
super()
|
||||||
this.user = { pending: true }
|
this.user = { pending: true }
|
||||||
|
|
||||||
|
AsyncStorage.getItem(backendName)
|
||||||
|
.then((backend) => {
|
||||||
|
this.backend = backend
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
this.backend = "normal"
|
||||||
|
AsyncStorage.setItem(backendName, this.backend)
|
||||||
|
})
|
||||||
|
|
||||||
AsyncStorage.getItem(authTokenName)
|
AsyncStorage.getItem(authTokenName)
|
||||||
.then((token) => {
|
.then((token) => {
|
||||||
if (!token) {
|
if (!token) {
|
||||||
@@ -105,8 +116,8 @@ class API extends EventEmitter {
|
|||||||
return this.user
|
return this.user
|
||||||
}
|
}
|
||||||
|
|
||||||
get apiURL() {
|
get backend() {
|
||||||
return baseURL + apiPath
|
return this.backend
|
||||||
}
|
}
|
||||||
|
|
||||||
makeImageUrl(id, size) {
|
makeImageUrl(id, size) {
|
||||||
|
|||||||
@@ -8,8 +8,9 @@ import {
|
|||||||
TextInput,
|
TextInput,
|
||||||
View,
|
View,
|
||||||
Button,
|
Button,
|
||||||
|
TouchableWithoutFeedback,
|
||||||
} from "react-native"
|
} from "react-native"
|
||||||
import { MessageModal } from "../Modal"
|
import { MessageModal, ApiModal } from "../Modal"
|
||||||
import logoImage from "./images/deighton.png"
|
import logoImage from "./images/deighton.png"
|
||||||
import { FormBinder } from "react-form-binder"
|
import { FormBinder } from "react-form-binder"
|
||||||
import { api } from "../API"
|
import { api } from "../API"
|
||||||
@@ -48,9 +49,6 @@ export class Login extends React.Component {
|
|||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
justifyContent: "center",
|
justifyContent: "center",
|
||||||
},
|
},
|
||||||
logo: {
|
|
||||||
width: "50%",
|
|
||||||
},
|
|
||||||
inputRow: {
|
inputRow: {
|
||||||
paddingTop: 10,
|
paddingTop: 10,
|
||||||
width: "60%",
|
width: "60%",
|
||||||
@@ -79,6 +77,7 @@ export class Login extends React.Component {
|
|||||||
this.state = {
|
this.state = {
|
||||||
binder: new FormBinder({ email: "john@lyon-smith.org" }, Login.bindings),
|
binder: new FormBinder({ email: "john@lyon-smith.org" }, Login.bindings),
|
||||||
messageModal: null,
|
messageModal: null,
|
||||||
|
apiModal: null,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,16 +109,28 @@ export class Login extends React.Component {
|
|||||||
this.setState({ messageModal: null })
|
this.setState({ messageModal: null })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
handleApiDismiss() {
|
||||||
|
this.setState({ apiModal: null })
|
||||||
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
handleApiPress() {
|
||||||
|
this.setState({ apiModal: {} })
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { messageModal } = this.state
|
const { messageModal, apiModal } = this.state
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={Login.styles.page} behavior="padding">
|
<View style={Login.styles.page} behavior="padding">
|
||||||
<Image
|
<TouchableWithoutFeedback onPress={this.handleApiPress}>
|
||||||
style={Login.styles.logo}
|
<Image
|
||||||
source={logoImage}
|
style={{ width: "50%" }}
|
||||||
resizeMode="contain"
|
source={logoImage}
|
||||||
/>
|
resizeMode="contain"
|
||||||
|
/>
|
||||||
|
</TouchableWithoutFeedback>
|
||||||
<View style={Login.styles.inputRow}>
|
<View style={Login.styles.inputRow}>
|
||||||
<BoundInput
|
<BoundInput
|
||||||
name="email"
|
name="email"
|
||||||
@@ -172,6 +183,10 @@ export class Login extends React.Component {
|
|||||||
detail={messageModal ? messageModal.detail : ""}
|
detail={messageModal ? messageModal.detail : ""}
|
||||||
onDismiss={messageModal && this.handleMessageDismiss}
|
onDismiss={messageModal && this.handleMessageDismiss}
|
||||||
/>
|
/>
|
||||||
|
<ApiModal
|
||||||
|
open={!!apiModal}
|
||||||
|
onDismiss={apiModal && this.handleApiDismiss}
|
||||||
|
/>
|
||||||
{Platform.OS === "ios" && <KeyboardSpacer />}
|
{Platform.OS === "ios" && <KeyboardSpacer />}
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -55,6 +55,17 @@ export class Home extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
handleMarkerPress(e, sectionIndex) {
|
||||||
|
if (this.sectionList) {
|
||||||
|
this.sectionList.scrollToLocation({
|
||||||
|
sectionIndex,
|
||||||
|
itemIndex: 0,
|
||||||
|
viewOffset: 45,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@autobind
|
@autobind
|
||||||
handleWorkItemsListPress() {
|
handleWorkItemsListPress() {
|
||||||
this.props.history.push("/workitemlist")
|
this.props.history.push("/workitemlist")
|
||||||
@@ -116,14 +127,19 @@ export class Home extends React.Component {
|
|||||||
latitudeDelta: 0.0922,
|
latitudeDelta: 0.0922,
|
||||||
longitudeDelta: 0.0922,
|
longitudeDelta: 0.0922,
|
||||||
}}>
|
}}>
|
||||||
{sections.map((section, index) => (
|
{sections.map((workItem, index) => (
|
||||||
<Marker
|
<Marker
|
||||||
key={index}
|
key={index}
|
||||||
coordinate={section.coordinate}
|
coordinate={workItem.coordinate}
|
||||||
title={workItemTypeText[section.workItemType]}
|
title={
|
||||||
description={section.address}
|
pad(workItem.ticketNumber, 4) +
|
||||||
|
": " +
|
||||||
|
workItemTypeText[workItem.workItemType]
|
||||||
|
}
|
||||||
|
description={workItem.address}
|
||||||
image={pinImage}
|
image={pinImage}
|
||||||
anchor={{ x: 0.5, y: 1.0 }}
|
anchor={{ x: 0.5, y: 1.0 }}
|
||||||
|
onPress={(e) => this.handleMarkerPress(e, index)}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</MapView>
|
</MapView>
|
||||||
@@ -152,8 +168,10 @@ export class Home extends React.Component {
|
|||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
<SectionList
|
<SectionList
|
||||||
|
ref={(ref) => (this.sectionList = ref)}
|
||||||
style={{ width: "100%", flexGrow: 1 }}
|
style={{ width: "100%", flexGrow: 1 }}
|
||||||
sections={sections}
|
sections={sections}
|
||||||
|
stickySectionHeadersEnabled={true}
|
||||||
renderSectionHeader={({ section: workItem }) => (
|
renderSectionHeader={({ section: workItem }) => (
|
||||||
<View
|
<View
|
||||||
key={workItem._id}
|
key={workItem._id}
|
||||||
@@ -169,10 +187,10 @@ export class Home extends React.Component {
|
|||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
|
keyExtractor={(item) => item._id}
|
||||||
renderItem={({ item: activity, section }) => {
|
renderItem={({ item: activity, section }) => {
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
key={activity._id}
|
|
||||||
style={{
|
style={{
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
height: 50,
|
height: 50,
|
||||||
|
|||||||
77
mobile/src/Modal/ApiModal.js
Normal file
77
mobile/src/Modal/ApiModal.js
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
import React, { Component } from "react"
|
||||||
|
import Modal from "react-native-modal"
|
||||||
|
import PropTypes from "prop-types"
|
||||||
|
import { View, Text, TouchableOpacity } from "react-native"
|
||||||
|
import { Icon, OptionStrip } from "../ui"
|
||||||
|
import autobind from "autobind-decorator"
|
||||||
|
|
||||||
|
export class ApiModal extends Component {
|
||||||
|
static propTypes = {
|
||||||
|
open: PropTypes.bool,
|
||||||
|
onDismiss: PropTypes.func,
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props)
|
||||||
|
this.state = {
|
||||||
|
value: null,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
handleButtonPress() {
|
||||||
|
const { onDismiss } = this.props
|
||||||
|
|
||||||
|
if (onDismiss) {
|
||||||
|
onDismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
handleValueChanged(newValue) {
|
||||||
|
this.setState({ value: newValue })
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { open, icon, message, detail } = this.props
|
||||||
|
const { value } = this.state
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal isVisible={open}>
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flexDirection: "column",
|
||||||
|
justifyContent: "center",
|
||||||
|
width: "100%",
|
||||||
|
backgroundColor: "#FFFFFF",
|
||||||
|
padding: 10,
|
||||||
|
}}>
|
||||||
|
<OptionStrip
|
||||||
|
options={[
|
||||||
|
{ value: "normal", text: "Normal" },
|
||||||
|
{ value: "test", text: "Test" },
|
||||||
|
{ value: "local", text: "Local" },
|
||||||
|
]}
|
||||||
|
value={value}
|
||||||
|
onValueChanged={this.handleValueChanged}
|
||||||
|
/>
|
||||||
|
<TouchableOpacity
|
||||||
|
onPress={this.handleButtonPress}
|
||||||
|
style={{
|
||||||
|
alignSelf: "center",
|
||||||
|
backgroundColor: "blue",
|
||||||
|
marginTop: 30,
|
||||||
|
marginBottom: 10,
|
||||||
|
justifyContent: "center",
|
||||||
|
paddingHorizontal: 10,
|
||||||
|
height: 40,
|
||||||
|
width: 100,
|
||||||
|
backgroundColor: "#3BB0FD",
|
||||||
|
}}>
|
||||||
|
<Text style={{ alignSelf: "center", color: "black" }}>OK</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
</Modal>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
import React, { Component } from 'react'
|
import React, { Component } from "react"
|
||||||
import Modal from 'react-native-modal'
|
import Modal from "react-native-modal"
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from "prop-types"
|
||||||
import { View, Text, TouchableOpacity } from 'react-native'
|
import { View, Text, TouchableOpacity } from "react-native"
|
||||||
import { Icon } from '../ui'
|
import { Icon } from "../ui"
|
||||||
import autobind from 'autobind-decorator'
|
import autobind from "autobind-decorator"
|
||||||
|
|
||||||
export class MessageModal extends Component {
|
export class MessageModal extends Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
@@ -11,7 +11,7 @@ export class MessageModal extends Component {
|
|||||||
icon: PropTypes.string.isRequired,
|
icon: PropTypes.string.isRequired,
|
||||||
message: PropTypes.string.isRequired,
|
message: PropTypes.string.isRequired,
|
||||||
detail: PropTypes.string,
|
detail: PropTypes.string,
|
||||||
onDismiss: PropTypes.func
|
onDismiss: PropTypes.func,
|
||||||
}
|
}
|
||||||
|
|
||||||
@autobind
|
@autobind
|
||||||
@@ -23,40 +23,48 @@ export class MessageModal extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(props) {
|
|
||||||
super(props)
|
|
||||||
this.state = {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { open, icon, message, detail } = this.props
|
const { open, icon, message, detail } = this.props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal isVisible={open}>
|
<Modal isVisible={open}>
|
||||||
<View style={{ flexDirection: 'row', width: '100%', padding: 5, backgroundColor: '#FFFFFF' }}>
|
<View
|
||||||
|
style={{
|
||||||
|
flexDirection: "row",
|
||||||
|
width: "100%",
|
||||||
|
padding: 5,
|
||||||
|
backgroundColor: "#FFFFFF",
|
||||||
|
}}>
|
||||||
<Icon name={icon} size={100} margin={3} />
|
<Icon name={icon} size={100} margin={3} />
|
||||||
<View style={{ flexGrow: 1, flexBasis: 0, flexDirection: 'column', flexWrap: 'wrap', marginLeft: 20, marginRight: 20}}>
|
<View
|
||||||
|
style={{
|
||||||
|
flexGrow: 1,
|
||||||
|
flexBasis: 0,
|
||||||
|
flexDirection: "column",
|
||||||
|
flexWrap: "wrap",
|
||||||
|
marginLeft: 20,
|
||||||
|
marginRight: 20,
|
||||||
|
}}>
|
||||||
<Text style={{ marginTop: 5, fontSize: 18 }}>{message}</Text>
|
<Text style={{ marginTop: 5, fontSize: 18 }}>{message}</Text>
|
||||||
<Text style={{ marginTop: 20 }}>{detail}</Text>
|
<Text style={{ marginTop: 20 }}>{detail}</Text>
|
||||||
<TouchableOpacity onPress={this.handleButtonPress}
|
<TouchableOpacity
|
||||||
|
onPress={this.handleButtonPress}
|
||||||
style={{
|
style={{
|
||||||
alignSelf: 'flex-end',
|
alignSelf: "flex-end",
|
||||||
backgroundColor: 'blue',
|
backgroundColor: "blue",
|
||||||
marginTop: 20,
|
marginTop: 20,
|
||||||
marginBottom: 10,
|
marginBottom: 10,
|
||||||
justifyContent: 'center',
|
justifyContent: "center",
|
||||||
paddingHorizontal: 10,
|
paddingHorizontal: 10,
|
||||||
height: 40,
|
height: 40,
|
||||||
width: 100,
|
width: 100,
|
||||||
backgroundColor: '#3BB0FD'
|
backgroundColor: "#3BB0FD",
|
||||||
}}>
|
}}>
|
||||||
<Text style={{ alignSelf: 'center', color: 'black' }}>OK</Text>
|
<Text style={{ alignSelf: "center", color: "black" }}>OK</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</Modal>
|
</Modal>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
export { MessageModal } from './MessageModal'
|
export { MessageModal } from "./MessageModal"
|
||||||
|
export { ApiModal } from "./ApiModal"
|
||||||
|
|||||||
Reference in New Issue
Block a user