Start adding API selection modal and supporting code

This commit is contained in:
John Lyon-Smith
2018-04-08 20:53:01 -07:00
parent 7891bb71c9
commit d674f5e7eb
6 changed files with 171 additions and 41 deletions

View File

@@ -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) {

View File

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

View File

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

View 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>
)
}
}

View File

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

View File

@@ -1 +1,2 @@
export { MessageModal } from './MessageModal' export { MessageModal } from "./MessageModal"
export { ApiModal } from "./ApiModal"