Adding work item details to activity
This commit is contained in:
@@ -31,7 +31,7 @@ import { formatLatLng, workItemTypeEnum } from "../util"
|
||||
import moment from "moment"
|
||||
import "url-search-params-polyfill"
|
||||
import { config } from "../config"
|
||||
import { FormStaticOptionStrip } from "../ui/FormStaticOptionStrip"
|
||||
import { FormStaticOptionStrip, FormStaticPhotoPanel } from "../ui"
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
@@ -127,6 +127,7 @@ export class Activity extends React.Component {
|
||||
dateTime: moment().format(),
|
||||
details: workItem.details,
|
||||
workItemType: workItem.workItemType,
|
||||
workItemPhotos: workItem.photos,
|
||||
})
|
||||
|
||||
this.region = {
|
||||
@@ -294,6 +295,7 @@ export class Activity extends React.Component {
|
||||
details,
|
||||
workItemType,
|
||||
uploadPercent,
|
||||
workItemPhotos,
|
||||
} = this.state
|
||||
|
||||
return (
|
||||
@@ -347,6 +349,10 @@ export class Activity extends React.Component {
|
||||
value={workItemType}
|
||||
/>
|
||||
<FormStaticInput label="Details:" value={details} />
|
||||
<FormStaticPhotoPanel
|
||||
label="Work Item Photos:"
|
||||
value={workItemPhotos}
|
||||
/>
|
||||
<FormStaticInput label="Location:" value={location} />
|
||||
<View style={{ flexDirection: "column", justifyContent: "center" }}>
|
||||
<MapView
|
||||
|
||||
@@ -55,7 +55,7 @@ export default class App extends React.Component {
|
||||
<Switch>
|
||||
<Route exact path="/login" component={Login} />
|
||||
<Route exact path="/logout" component={Logout} />
|
||||
{/* <ProtectedRoute exact path="/home" component={Home} /> */}
|
||||
<ProtectedRoute exact path="/home" component={Home} />
|
||||
<ProtectedRoute
|
||||
exact
|
||||
path="/arviewer"
|
||||
@@ -69,8 +69,7 @@ export default class App extends React.Component {
|
||||
path="/workItemList"
|
||||
component={WorkItemList}
|
||||
/>
|
||||
{/* <DefaultRoute redirect="/home" /> */}
|
||||
<DefaultRoute redirect="/activity?workItemId=5b0c85995ebbed31c323cdf6" />
|
||||
<DefaultRoute redirect="/home" />
|
||||
</Switch>
|
||||
</View>
|
||||
</NativeRouter>
|
||||
|
||||
@@ -14,17 +14,7 @@ import ImagePicker from "react-native-image-picker"
|
||||
import ImageResizer from "react-native-image-resizer"
|
||||
import { reactAutoBind } from "auto-bind2"
|
||||
import { api } from "../API"
|
||||
|
||||
const getScreenPortraitDimensions = () => {
|
||||
const { width, height } = Dimensions.get("window")
|
||||
|
||||
return {
|
||||
screenWidth: Math.min(width, height),
|
||||
screenHeight: Math.max(width, height),
|
||||
}
|
||||
}
|
||||
|
||||
const photoSpacing = 10
|
||||
import { PhotoPanel } from "."
|
||||
|
||||
export class BoundPhotoPanel extends Component {
|
||||
static propTypes = {
|
||||
@@ -95,56 +85,15 @@ export class BoundPhotoPanel extends Component {
|
||||
)
|
||||
}
|
||||
|
||||
handleLayout(e) {
|
||||
if (!this.state.photoSize) {
|
||||
const { layout } = e.nativeEvent
|
||||
const ratio = 3 / 4
|
||||
const width = (layout.width - photoSpacing) / 2
|
||||
const height = width / ratio
|
||||
|
||||
this.setState({ photoSize: { width, height } })
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { photoSize, value: assetIds } = this.state
|
||||
|
||||
const renderPhoto = (index) => {
|
||||
const assetId = assetIds[index]
|
||||
|
||||
return (
|
||||
<TouchableOpacity
|
||||
key={assetId || "blank" + index.toString()}
|
||||
style={{
|
||||
width: photoSize.width,
|
||||
height: photoSize.height,
|
||||
borderWidth: 2,
|
||||
borderColor: "gray",
|
||||
borderRadius: 4,
|
||||
justifyContent: "center",
|
||||
}}
|
||||
onPress={() => this.handlePhotoPress(index)}>
|
||||
{!assetId && (
|
||||
<Icon name="add" size={24} style={{ alignSelf: "center" }} />
|
||||
)}
|
||||
{assetId && (
|
||||
<Image
|
||||
source={{ uri: api.makeImageUrl(assetId) }}
|
||||
style={{ width: "100%", height: "100%" }}
|
||||
resizeMode="contain"
|
||||
/>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
)
|
||||
}
|
||||
const { photoSize, value } = this.state
|
||||
|
||||
return (
|
||||
<View
|
||||
style={{
|
||||
flexDirection: "column",
|
||||
justifyContent: "space-between",
|
||||
}}
|
||||
onLayout={this.handleLayout}>
|
||||
}}>
|
||||
<Text
|
||||
style={{
|
||||
fontSize: 14,
|
||||
@@ -152,18 +101,7 @@ export class BoundPhotoPanel extends Component {
|
||||
}}>
|
||||
Pictures:
|
||||
</Text>
|
||||
{photoSize && (
|
||||
<View style={styles.photoRow}>
|
||||
{renderPhoto(0)}
|
||||
{renderPhoto(1)}
|
||||
</View>
|
||||
)}
|
||||
{photoSize && (
|
||||
<View style={styles.photoRow}>
|
||||
{renderPhoto(2)}
|
||||
{renderPhoto(3)}
|
||||
</View>
|
||||
)}
|
||||
<PhotoPanel onPhotoPress={this.handlePhotoPress} value={value} />
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
30
mobile/src/ui/FormStaticPhotoPanel.js
Normal file
30
mobile/src/ui/FormStaticPhotoPanel.js
Normal file
@@ -0,0 +1,30 @@
|
||||
import React from "react"
|
||||
import PropTypes from "prop-types"
|
||||
import { Text, View, Platform } from "react-native"
|
||||
import { PhotoPanel } from "."
|
||||
|
||||
export class FormStaticPhotoPanel extends React.Component {
|
||||
static propTypes = {
|
||||
label: PropTypes.string,
|
||||
value: PropTypes.arrayOf(PropTypes.string),
|
||||
}
|
||||
|
||||
render() {
|
||||
const { label, value, options } = this.props
|
||||
|
||||
return (
|
||||
<View style={{ width: "100%" }}>
|
||||
<Text
|
||||
style={{
|
||||
color: "black",
|
||||
fontSize: 14,
|
||||
marginBottom: 5,
|
||||
}}>
|
||||
{label}
|
||||
</Text>
|
||||
<PhotoPanel value={value} readOnly />
|
||||
<Text> </Text>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
}
|
||||
108
mobile/src/ui/PhotoPanel.js
Normal file
108
mobile/src/ui/PhotoPanel.js
Normal file
@@ -0,0 +1,108 @@
|
||||
import React, { Component } from "react"
|
||||
import PropTypes from "prop-types"
|
||||
import {
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
Image,
|
||||
TouchableOpacity,
|
||||
Dimensions,
|
||||
ActivityIndicator,
|
||||
} from "react-native"
|
||||
import { Icon } from "."
|
||||
import { reactAutoBind } from "auto-bind2"
|
||||
import { api } from "../API"
|
||||
|
||||
const photoSpacing = 10
|
||||
|
||||
export class PhotoPanel extends Component {
|
||||
static propTypes = {
|
||||
onPhotoPress: PropTypes.func,
|
||||
readOnly: PropTypes.bool,
|
||||
value: PropTypes.arrayOf(PropTypes.string),
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props)
|
||||
reactAutoBind(this)
|
||||
this.state = {
|
||||
photoSize: null,
|
||||
}
|
||||
}
|
||||
|
||||
handleLayout(e) {
|
||||
if (!this.state.photoSize) {
|
||||
const { layout } = e.nativeEvent
|
||||
const ratio = 3 / 4
|
||||
const width = (layout.width - photoSpacing) / 2
|
||||
const height = width / ratio
|
||||
|
||||
this.setState({ photoSize: { width, height } })
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { photoSize } = this.state
|
||||
const { value: assetIds, readOnly, onPhotoPress } = this.props
|
||||
const renderPhoto = (index) => {
|
||||
const assetId = assetIds && assetIds[index]
|
||||
|
||||
return (
|
||||
<TouchableOpacity
|
||||
key={assetId || "blank" + index.toString()}
|
||||
disabled={readOnly}
|
||||
style={{
|
||||
width: photoSize.width,
|
||||
height: photoSize.height,
|
||||
borderWidth: 2,
|
||||
borderColor: "gray",
|
||||
borderRadius: 4,
|
||||
justifyContent: "center",
|
||||
}}
|
||||
onPress={() => onPhotoPress(index)}>
|
||||
{!assetId && (
|
||||
<Icon
|
||||
name={!readOnly ? "add" : "blank"}
|
||||
size={24}
|
||||
style={{ alignSelf: "center" }}
|
||||
/>
|
||||
)}
|
||||
{assetId && (
|
||||
<Image
|
||||
source={{ uri: api.makeImageUrl(assetId) }}
|
||||
style={{ width: "100%", height: "100%" }}
|
||||
resizeMode="contain"
|
||||
/>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<View onLayout={this.handleLayout}>
|
||||
{photoSize && (
|
||||
<View style={styles.photoRow}>
|
||||
{renderPhoto(0)}
|
||||
{renderPhoto(1)}
|
||||
</View>
|
||||
)}
|
||||
{photoSize && (
|
||||
<View style={styles.photoRow}>
|
||||
{renderPhoto(2)}
|
||||
{renderPhoto(3)}
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
photoRow: {
|
||||
flexDirection: "row",
|
||||
justifyContent: "space-between",
|
||||
width: "100%",
|
||||
paddingTop: 5,
|
||||
paddingBottom: 5,
|
||||
},
|
||||
})
|
||||
@@ -3,10 +3,12 @@ export { Header } from "./Header"
|
||||
export { OptionStrip } from "./OptionStrip"
|
||||
export { BubbleLoader } from "./BubbleLoader"
|
||||
export { ProgressBar } from "./ProgressBar"
|
||||
export { PhotoPanel } from "./PhotoPanel"
|
||||
export { Geolocation } from "./Geolocation"
|
||||
export { BoundSwitch } from "./BoundSwitch"
|
||||
export { BoundInput } from "./BoundInput"
|
||||
export { FormStaticInput } from "./FormStaticInput"
|
||||
export { FormStaticPhotoPanel } from "./FormStaticPhotoPanel"
|
||||
export { FormStaticOptionStrip } from "./FormStaticOptionStrip"
|
||||
export { BoundButton } from "./BoundButton"
|
||||
export { BoundOptionStrip } from "./BoundOptionStrip"
|
||||
|
||||
Reference in New Issue
Block a user