Bug fixing
@@ -390,14 +390,18 @@ class API extends EventEmitter {
|
||||
method: "GET",
|
||||
mode: "no-cors",
|
||||
}
|
||||
let headers = new Headers()
|
||||
|
||||
fetch(
|
||||
headers.set("Referer", config.refererURL)
|
||||
fetchOptions.headers = headers
|
||||
|
||||
const path =
|
||||
config.googleGeocodeURL +
|
||||
`?latlng=${coord.latitude},${coord.longitude}&key=${
|
||||
config.googleAPIKey
|
||||
}`,
|
||||
fetchOptions
|
||||
)
|
||||
`?latlng=${coord.latitude},${coord.longitude}&key=${
|
||||
config.googleGeocodeAPIKey
|
||||
}`
|
||||
|
||||
fetch(path, fetchOptions)
|
||||
.then((res) => {
|
||||
return Promise.all([Promise.resolve(res), res.json()])
|
||||
})
|
||||
@@ -407,7 +411,7 @@ class API extends EventEmitter {
|
||||
if (res.ok) {
|
||||
let address = ""
|
||||
|
||||
if (responseBody.results && responseBody.result.length > 0) {
|
||||
if (responseBody.results && responseBody.results.length > 0) {
|
||||
address = responseBody.results[0].formatted_address
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
import autobind from "autobind-decorator"
|
||||
import backImage from "./images/back.png"
|
||||
import { config } from "../config"
|
||||
import "url-search-params-polyfill"
|
||||
|
||||
const shapes = {
|
||||
order: {
|
||||
|
||||
@@ -27,6 +27,7 @@ import KeyboardSpacer from "react-native-keyboard-spacer"
|
||||
import { isIphoneX } from "react-native-iphone-x-helper"
|
||||
import { api } from "../API"
|
||||
import { formatLatLng, parseLatLng } from "../util"
|
||||
import "url-search-params-polyfill"
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
@@ -189,7 +190,7 @@ export class Activity extends React.Component {
|
||||
<BoundHeader
|
||||
binder={binder}
|
||||
name="header"
|
||||
title="Work Item"
|
||||
title="Activity"
|
||||
leftButton={{ icon: "back", onPress: this.handleBackPress }}
|
||||
rightButton={{ icon: "done", onPress: this.handleDonePress }}
|
||||
/>
|
||||
@@ -220,31 +221,33 @@ export class Activity extends React.Component {
|
||||
label="Date & Time:"
|
||||
/>
|
||||
<BoundInput binder={binder} name="location" label="Location:" />
|
||||
<MapView
|
||||
style={{
|
||||
flexDirection: "column",
|
||||
justifyContent: "center",
|
||||
width: "100%",
|
||||
height: 400,
|
||||
marginTop: 10,
|
||||
}}
|
||||
zoomControlEnabled={false}
|
||||
zoomEnabled={false}
|
||||
scrollEnabled={false}
|
||||
rotateEnabled={false}
|
||||
pitchEnabled={false}
|
||||
showsIndoors={false}
|
||||
showsTraffic={false}
|
||||
showsCompass={false}
|
||||
showsScale={false}
|
||||
showsUserLocation
|
||||
cacheEnabled
|
||||
initialRegion={{
|
||||
latitude: 43.653908,
|
||||
longitude: -79.384293,
|
||||
latitudeDelta: 0.0922,
|
||||
longitudeDelta: 0.0421,
|
||||
}}>
|
||||
<View style={{ flexDirection: "column", justifyContent: "center" }}>
|
||||
<MapView
|
||||
style={{
|
||||
flexDirection: "column",
|
||||
justifyContent: "center",
|
||||
width: "100%",
|
||||
height: 400,
|
||||
marginTop: 10,
|
||||
}}
|
||||
zoomControlEnabled={false}
|
||||
zoomEnabled={false}
|
||||
scrollEnabled={false}
|
||||
rotateEnabled={false}
|
||||
pitchEnabled={false}
|
||||
showsIndoors={false}
|
||||
showsTraffic={false}
|
||||
showsCompass={false}
|
||||
showsScale={false}
|
||||
showsUserLocation
|
||||
cacheEnabled
|
||||
initialRegion={{
|
||||
latitude: 43.653908,
|
||||
longitude: -79.384293,
|
||||
latitudeDelta: 0.0922,
|
||||
longitudeDelta: 0.0421,
|
||||
}}
|
||||
/>
|
||||
<Icon
|
||||
name="target"
|
||||
size={24}
|
||||
@@ -254,7 +257,7 @@ export class Activity extends React.Component {
|
||||
alignSelf: "center",
|
||||
}}
|
||||
/>
|
||||
</MapView>
|
||||
</View>
|
||||
</View>
|
||||
<View style={styles.panel}>
|
||||
<PhotoPanel />
|
||||
|
||||
@@ -3,5 +3,5 @@ import { Route, Redirect } from "react-router-native"
|
||||
|
||||
export const DefaultRoute = () => {
|
||||
// NOTE: When working on the app, change this to the page you are working on
|
||||
return <Route render={() => <Redirect to={"/activity"} />} />
|
||||
return <Route render={() => <Redirect to={"/workItem"} />} />
|
||||
}
|
||||
|
||||
@@ -125,7 +125,7 @@ export class Login extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { messageModal, apiModal } = this.state
|
||||
const { messageModal, apiModal, waitModal } = this.state
|
||||
|
||||
return (
|
||||
<View style={Login.styles.page} behavior="padding">
|
||||
|
||||
@@ -27,9 +27,9 @@ import { ensurePermissions } from "../App"
|
||||
import { versionInfo } from "../version"
|
||||
import { config } from "../config"
|
||||
import KeyboardSpacer from "react-native-keyboard-spacer"
|
||||
import hardhatPinImage from "./images/hardhat.png"
|
||||
import clipboardPinImage from "./images/clipboard.png"
|
||||
import questionPinImage from "./images/question.png"
|
||||
import hardhatPinImage from "./images/hardhat-pin.png"
|
||||
import clipboardPinImage from "./images/clipboard-pin.png"
|
||||
import questionPinImage from "./images/question-pin.png"
|
||||
|
||||
const neverAskForLocationPermissionKeyName = "NeverAskForLocationPermission"
|
||||
const neverAskForCameraKeyName = "NeverAskForCameraPermission"
|
||||
@@ -141,7 +141,7 @@ export class Home extends React.Component {
|
||||
|
||||
if (this.state.positionInfo) {
|
||||
const coords = this.state.positionInfo.coords
|
||||
const workItem = sections[sectionIndex]
|
||||
const workItem = this.sections[sectionIndex]
|
||||
const [lng, lat] = workItem.location.coordinates
|
||||
|
||||
this.setState({
|
||||
@@ -159,16 +159,16 @@ export class Home extends React.Component {
|
||||
@autobind
|
||||
handleWorkItemsListPress() {
|
||||
const { positionInfo } = this.state
|
||||
this.props.history.push(
|
||||
`/workItemList${
|
||||
positionInfo
|
||||
? "?latLng=" +
|
||||
coords.latitude.toString() +
|
||||
"," +
|
||||
coords.longitude.toString()
|
||||
: ""
|
||||
}`
|
||||
)
|
||||
|
||||
if (positionInfo) {
|
||||
const { coords } = positionInfo
|
||||
|
||||
this.props.history.push(
|
||||
`/workItemList?latLng=${coords.latitude},${coords.longitude}`
|
||||
)
|
||||
} else {
|
||||
this.props.history.push("/workItemList")
|
||||
}
|
||||
}
|
||||
|
||||
@autobind
|
||||
@@ -184,8 +184,8 @@ export class Home extends React.Component {
|
||||
@autobind
|
||||
handleGlassesPress() {
|
||||
const { lat: lat1, lng: lng1 } = this.state.positionInfo.coords
|
||||
const closestWorkItem = null
|
||||
const shortestDistance = config.minDistanceToItem
|
||||
let closestWorkItem = null
|
||||
let shortestDistance = config.minDistanceToItem
|
||||
|
||||
this.state.sections.forEach((workItem) => {
|
||||
const [lng2, lat2] = workItem.location.coordinates
|
||||
@@ -270,7 +270,7 @@ export class Home extends React.Component {
|
||||
showsBuildings={false}
|
||||
showsTraffic={false}
|
||||
showsIndoors={false}
|
||||
zoomControlEnabled
|
||||
zoomControlEnabled={false}
|
||||
region={region}>
|
||||
{sections.map((workItem, index) => (
|
||||
<Marker
|
||||
|
||||
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 1.4 KiB |
BIN
mobile/src/Home/images/clipboard-pin@1x.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 8.8 KiB After Width: | Height: | Size: 4.5 KiB |
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 1.6 KiB |
BIN
mobile/src/Home/images/hardhat-pin@1x.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 5.1 KiB |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 1.7 KiB |
BIN
mobile/src/Home/images/question-pin@1x.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 5.1 KiB |
@@ -1,7 +1,7 @@
|
||||
import React, { Component } from "react"
|
||||
import Modal from "react-native-modal"
|
||||
import PropTypes from "prop-types"
|
||||
import { View, ActivityIndicator } from "react-native"
|
||||
import { View, Text, ActivityIndicator } from "react-native"
|
||||
|
||||
export class WaitModal extends Component {
|
||||
static propTypes = {
|
||||
@@ -18,10 +18,18 @@ export class WaitModal extends Component {
|
||||
style={{
|
||||
flexDirection: "column",
|
||||
justifyContent: "center",
|
||||
backgroundColor: "#FFFFFF",
|
||||
backgroundColor: "transparent",
|
||||
}}>
|
||||
<ActivityIndicator size="large" color="#0000FF" />
|
||||
<Text style={{ marginTop: 5, fontSize: 18 }}>{message}</Text>
|
||||
<Text
|
||||
style={{
|
||||
marginTop: 15,
|
||||
fontSize: 18,
|
||||
alignSelf: "center",
|
||||
color: "#FFFFFF",
|
||||
}}>
|
||||
{message}
|
||||
</Text>
|
||||
</View>
|
||||
</Modal>
|
||||
)
|
||||
|
||||
@@ -28,6 +28,7 @@ import { ifIphoneX, isIphoneX } from "react-native-iphone-x-helper"
|
||||
import KeyboardSpacer from "react-native-keyboard-spacer"
|
||||
import { api } from "../API"
|
||||
import "url-search-params-polyfill"
|
||||
import { config } from "../config"
|
||||
import { workItemTypeEnum, formatLatLng, parseLatLng } from "../util"
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
@@ -58,6 +59,7 @@ export class WorkItem extends React.Component {
|
||||
location: {
|
||||
isValid: (r, v) => v !== "",
|
||||
isReadOnly: true,
|
||||
alwaysGet: true,
|
||||
},
|
||||
address: {
|
||||
isValid: true,
|
||||
@@ -74,15 +76,18 @@ export class WorkItem extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
||||
region = {
|
||||
latitude: 43.653908,
|
||||
longitude: -79.384293,
|
||||
latitudeDelta: 0.0922,
|
||||
longitudeDelta: 0.0421,
|
||||
}
|
||||
|
||||
this.state = {
|
||||
binder: new FormBinder({}, WorkItem.bindings),
|
||||
messageModal: null,
|
||||
region: {
|
||||
latitude: 43.653908,
|
||||
longitude: -79.384293,
|
||||
latitudeDelta: 0.0922,
|
||||
longitudeDelta: 0.0421,
|
||||
},
|
||||
region,
|
||||
}
|
||||
|
||||
const { search } = this.props.location
|
||||
@@ -96,15 +101,17 @@ export class WorkItem extends React.Component {
|
||||
.then((workItem) => {
|
||||
if (workItem) {
|
||||
const [lng, lat] = workItem.location.coordinates
|
||||
const region = {
|
||||
latitude: lat,
|
||||
longitude: lng,
|
||||
latitudeDelta: 0.01,
|
||||
longitudeDelta: 0.01,
|
||||
}
|
||||
|
||||
workItem.location = formatLatLng(lat, lng)
|
||||
this.setState({
|
||||
binder: new FormBinder(workItem, WorkItem.bindings),
|
||||
region: {
|
||||
latitude: lat,
|
||||
longitude: lng,
|
||||
latitudeDelta: 0.01,
|
||||
longitudeDelta: 0.01,
|
||||
},
|
||||
region,
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -198,6 +205,7 @@ export class WorkItem extends React.Component {
|
||||
|
||||
if (this.geoCodeTimer) {
|
||||
clearTimeout(this.geoCodeTimer)
|
||||
this.geoCodeTimer = null
|
||||
}
|
||||
|
||||
this.geoCodeTimer = setTimeout(
|
||||
@@ -209,12 +217,16 @@ export class WorkItem extends React.Component {
|
||||
@autobind
|
||||
handleStartAddressLookup(latLng) {
|
||||
api
|
||||
.addressLookup(latLng)
|
||||
.getAddress(latLng)
|
||||
.then((address) => {
|
||||
this.setState({ address })
|
||||
if (this.addressInput) {
|
||||
this.addressInput.handleChangeText(address)
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.setState({ address: "" })
|
||||
if (this.addressInput) {
|
||||
this.addressInput.handleChangeText("")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -252,6 +264,7 @@ export class WorkItem extends React.Component {
|
||||
<View style={styles.panel}>
|
||||
<View style={{ flexDirection: "column", justifyContent: "center" }}>
|
||||
<MapView
|
||||
ref={(ref) => (this.mapView = ref)}
|
||||
style={{
|
||||
flexDirection: "column",
|
||||
justifyContent: "center",
|
||||
@@ -262,7 +275,7 @@ export class WorkItem extends React.Component {
|
||||
showsBuildings={false}
|
||||
showsTraffic={false}
|
||||
showsIndoors={false}
|
||||
zoomControlEnabled
|
||||
zoomControlEnabled={false}
|
||||
rotateEnabled={false}
|
||||
region={region}
|
||||
onRegionChange={this.handleRegionChange}
|
||||
|
||||
@@ -20,7 +20,9 @@ import {
|
||||
parseLatLng,
|
||||
pad,
|
||||
geoDistance,
|
||||
dotify,
|
||||
} from "../util"
|
||||
import "url-search-params-polyfill"
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
@@ -179,7 +181,7 @@ export class WorkItemList extends React.Component {
|
||||
{workItemTypeText[item.workItemType]}
|
||||
</Text>
|
||||
<Text style={{ fontSize: 14, color: "gray" }}>
|
||||
{`${item.address || "..."} | ${
|
||||
{`${dotify(item.address) || "..."} | ${
|
||||
this.position
|
||||
? geoDistance(
|
||||
this.position.latitude,
|
||||
|
||||
@@ -4,11 +4,9 @@ import { Platform } from "react-native"
|
||||
export const config = {
|
||||
localIPAddr: "192.168.1.175",
|
||||
viroAPIKey: "06F37B6A-74DA-4A83-965A-7DE2209A5C46",
|
||||
googleAPIKey:
|
||||
Platform.os === "ios"
|
||||
? "AIzaSyDN4E_vzO4cKjKHkMg_49hX1GBnU34kx4U"
|
||||
: "AIzaSyAC7r1GjMFL1atZdbEcFSdCaXDrPnISqTc",
|
||||
googleGeocodeAPIKey: "AIzaSyCs4JVT6gysnY5dAJ7KjVJYeykLv_xz1GI",
|
||||
googleGeocodeURL: "https://maps.googleapis.com/maps/api/geocode/json",
|
||||
refererURL: "https://dar.kss.us.com",
|
||||
defaultUser: "john@lyon-smith.org",
|
||||
//defaultUser: "",
|
||||
//minGPSAccuracy: 20,
|
||||
|
||||
@@ -54,7 +54,12 @@ export class BoundInput extends React.Component {
|
||||
|
||||
return (
|
||||
<View style={{ width: "100%" }}>
|
||||
<Text style={{ color: "black", fontSize: 14, marginBottom: 5 }}>
|
||||
<Text
|
||||
style={{
|
||||
color: "black",
|
||||
fontSize: 14,
|
||||
marginBottom: 5,
|
||||
}}>
|
||||
{label}
|
||||
</Text>
|
||||
<TextInput
|
||||
@@ -68,6 +73,7 @@ export class BoundInput extends React.Component {
|
||||
paddingTop: 7,
|
||||
paddingBottom: Platform.OS === "ios" ? 7 : 0,
|
||||
textAlignVertical: "top",
|
||||
marginBottom: 5,
|
||||
}}
|
||||
multiline={lines > 1}
|
||||
numberOfLines={lines}
|
||||
|
||||
@@ -56,6 +56,14 @@ export const pad = (num, size) => {
|
||||
return s
|
||||
}
|
||||
|
||||
export const dotify = (s) => {
|
||||
if (s.length < 30) {
|
||||
return s
|
||||
} else {
|
||||
return s.substring(0, 26) + "..."
|
||||
}
|
||||
}
|
||||
|
||||
export const regionContainingPoints = (points, inset) => {
|
||||
let minX,
|
||||
maxX,
|
||||
|
||||
@@ -143,75 +143,6 @@ export class Teams extends Component {
|
||||
})
|
||||
}
|
||||
|
||||
@autobind
|
||||
handleResendEmail() {
|
||||
this.setState({
|
||||
waitModal: { message: "Resending Email..." },
|
||||
})
|
||||
api
|
||||
.sendConfirmEmail({ existingEmail: this.state.selectedTeam.email })
|
||||
.then(() => {
|
||||
this.setState({
|
||||
waitModal: null,
|
||||
messageModal: {
|
||||
icon: "thumb",
|
||||
message: `An email has been sent to '${
|
||||
this.state.selectedTeam.email
|
||||
}' with further instructions.`,
|
||||
},
|
||||
})
|
||||
})
|
||||
.catch((error) => {
|
||||
this.setState({
|
||||
error: true,
|
||||
waitModal: null,
|
||||
messageModal: {
|
||||
icon: "hand",
|
||||
message: "Unable to request email change.",
|
||||
detail: error.message,
|
||||
},
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@autobind
|
||||
handleChangeEmailDismiss(newEmail) {
|
||||
this.setState({ changeEmailModal: null })
|
||||
if (!newEmail) {
|
||||
return
|
||||
}
|
||||
this.setState({
|
||||
waitModal: { message: "Requesting Email Change..." },
|
||||
})
|
||||
if (this.state.selectedTeam) {
|
||||
api
|
||||
.sendConfirmEmail({
|
||||
existingEmail: this.state.selectedTeam.email,
|
||||
newEmail,
|
||||
})
|
||||
.then(() => {
|
||||
this.setState({
|
||||
waitModal: null,
|
||||
messageModal: {
|
||||
icon: "hand",
|
||||
message: `An email has been sent to '${newEmail}' to confirm this email.`,
|
||||
},
|
||||
})
|
||||
})
|
||||
.catch((error) => {
|
||||
this.setState({
|
||||
error: true,
|
||||
waitModal: null,
|
||||
messageModal: {
|
||||
icon: "hand",
|
||||
message: "Unable to request email change.",
|
||||
detail: error.message,
|
||||
},
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@autobind
|
||||
handleRemove() {
|
||||
this.setState({
|
||||
|
||||