Added image picker and cleaned up main and job list screens.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { useQuery } from "@apollo/client";
|
||||
import { Picker } from "native-base";
|
||||
import React from "react";
|
||||
import { View } from "react-native";
|
||||
import { Text, View } from "react-native";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { QUERY_ALL_ACTIVE_JOBS } from "../../graphql/jobs.queries";
|
||||
@@ -10,6 +10,7 @@ import { selectCurrentCameraJobId } from "../../redux/app/app.selectors";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import ErrorDisplay from "../error-display/error-display.component";
|
||||
import LoadingDisplay from "../loading-display/loading-display.component";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
@@ -27,17 +28,13 @@ export function CameraSelectJob({
|
||||
setCameraJobId,
|
||||
setCameraJob,
|
||||
}) {
|
||||
const { loading, error, data, refetch } = useQuery(QUERY_ALL_ACTIVE_JOBS, {
|
||||
const { loading, error, data } = useQuery(QUERY_ALL_ACTIVE_JOBS, {
|
||||
variables: {
|
||||
statuses: bodyshop.md_ro_statuses.active_statuses || ["Open", "Open*"],
|
||||
},
|
||||
skip: !bodyshop,
|
||||
});
|
||||
|
||||
const onRefresh = async () => {
|
||||
return refetch();
|
||||
};
|
||||
|
||||
const { t } = useTranslation();
|
||||
if (loading) return <LoadingDisplay />;
|
||||
if (error) return <ErrorDisplay errorMessage={error.message} />;
|
||||
|
||||
@@ -45,19 +42,14 @@ export function CameraSelectJob({
|
||||
return (
|
||||
<View
|
||||
style={{
|
||||
backgroundColor: "rgba(35,35,35, 0.4)",
|
||||
paddingTop: 30,
|
||||
//textShadow: "tomato 0px 0px 10px",
|
||||
fontColor: "black",
|
||||
fontSize: 20,
|
||||
fontWeight: "bold",
|
||||
}}
|
||||
>
|
||||
{!cameraJobId && <Text>{t("mediabrowser.labels.selectjob")}</Text>}
|
||||
<Picker
|
||||
note
|
||||
selectedValue={cameraJobId}
|
||||
onValueChange={(value, idx) => {
|
||||
console.log(value, idx);
|
||||
setCameraJobId(value);
|
||||
setCameraJob(data.jobs[idx]);
|
||||
}}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { DateTime } from "luxon";
|
||||
import { Input, Item, Label } from "native-base";
|
||||
import React from "react";
|
||||
import { StyleSheet } from "react-native";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { DateTime } from "luxon";
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
//currentUser: selectCurrentUser
|
||||
});
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
import { Container, Content, Thumbnail } from "native-base";
|
||||
import React, { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import {
|
||||
FlatList,
|
||||
SafeAreaView,
|
||||
RefreshControl,
|
||||
StyleSheet,
|
||||
Text,
|
||||
TouchableOpacity,
|
||||
View,
|
||||
RefreshControl,
|
||||
} from "react-native";
|
||||
import MediaCacheOverlay from "../media-cache-overlay/media-cache-overlay.component";
|
||||
|
||||
@@ -17,7 +14,6 @@ const REACT_APP_CLOUDINARY_IMAGE_ENDPOINT =
|
||||
const REACT_APP_CLOUDINARY_THUMB_TRANSFORMATIONS = "c_fill,f_auto,h_250,w_250";
|
||||
|
||||
export default function JobDocumentsComponent({ job, loading, refetch }) {
|
||||
const { t } = useTranslation();
|
||||
const [previewVisible, setPreviewVisible] = useState(false);
|
||||
const [imgIndex, setImgIndex] = useState(0);
|
||||
const onRefresh = async () => {
|
||||
|
||||
@@ -6,7 +6,7 @@ import Dinero from "dinero.js";
|
||||
|
||||
export default function JobLines({ job, loading, refetch }) {
|
||||
const { t } = useTranslation();
|
||||
if (!!!job) {
|
||||
if (!job) {
|
||||
<Card>
|
||||
<Text>Job is not defined.</Text>
|
||||
</Card>;
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { Ionicons } from "@expo/vector-icons";
|
||||
import { useNavigation } from "@react-navigation/native";
|
||||
import * as ImagePicker from "expo-image-picker";
|
||||
import { Body, H3, Icon, ListItem, Right } from "native-base";
|
||||
import React from "react";
|
||||
import React, { useEffect } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Text } from "react-native";
|
||||
import { Animated, Platform, Text } from "react-native";
|
||||
import { TouchableOpacity } from "react-native-gesture-handler";
|
||||
import Swipeable from "react-native-gesture-handler/Swipeable";
|
||||
import { connect } from "react-redux";
|
||||
@@ -23,9 +24,40 @@ export function JobListItem({ setCameraJob, setCameraJobId, item }) {
|
||||
const { t } = useTranslation();
|
||||
const navigation = useNavigation();
|
||||
|
||||
const RenderRightAction = () => {
|
||||
const navigation = useNavigation();
|
||||
const { t } = useTranslation();
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
if (Platform.OS !== "web") {
|
||||
const {
|
||||
status,
|
||||
} = await ImagePicker.requestMediaLibraryPermissionsAsync();
|
||||
if (status !== "granted") {
|
||||
alert("Sorry, we need camera roll permissions to make this work!");
|
||||
}
|
||||
}
|
||||
})();
|
||||
}, []);
|
||||
|
||||
const pickImage = async () => {
|
||||
let result = await ImagePicker.launchImageLibraryAsync({
|
||||
mediaTypes: ImagePicker.MediaTypeOptions.All,
|
||||
allowsEditing: true,
|
||||
aspect: [4, 3],
|
||||
quality: 1,
|
||||
});
|
||||
|
||||
console.log(result);
|
||||
|
||||
if (!result.cancelled) {
|
||||
// setImage(result.uri);
|
||||
}
|
||||
};
|
||||
|
||||
const RenderRightAction = (progress, dragX) => {
|
||||
const scale = dragX.interpolate({
|
||||
inputRange: [-100, 0],
|
||||
outputRange: [0.7, 0],
|
||||
});
|
||||
|
||||
return (
|
||||
<TouchableOpacity
|
||||
style={[styles.swipe_view, styles.swipe_view_blue]}
|
||||
@@ -35,10 +67,46 @@ export function JobListItem({ setCameraJob, setCameraJobId, item }) {
|
||||
navigation.navigate("CameraTab");
|
||||
}}
|
||||
>
|
||||
<Ionicons name="ios-camera" size={24} color="white" />
|
||||
{/* <Text style={styles.swipe_text}>
|
||||
{t("joblist.actions.swipecamera")}
|
||||
</Text> */}
|
||||
<Animated.View
|
||||
style={{
|
||||
// color: "white",
|
||||
// paddingHorizontal: 10,
|
||||
// fontWeight: "600",
|
||||
transform: [{ scale }],
|
||||
}}
|
||||
>
|
||||
<Ionicons name="ios-camera" size={24} color="white" />
|
||||
</Animated.View>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
};
|
||||
const RenderLeftAction = (progress, dragX) => {
|
||||
const scale = dragX.interpolate({
|
||||
inputRange: [0, 100],
|
||||
outputRange: [0, 1],
|
||||
extrapolate: "clamp",
|
||||
});
|
||||
|
||||
return (
|
||||
<TouchableOpacity
|
||||
style={[styles.swipe_view, styles.swipe_view_blue]}
|
||||
onPress={() => {
|
||||
setCameraJobId(item.id);
|
||||
setCameraJob(item);
|
||||
navigation.push("MediaBrowser");
|
||||
//pickImage(item.id);
|
||||
}}
|
||||
>
|
||||
<Animated.Text
|
||||
style={{
|
||||
// color: "white",
|
||||
// paddingHorizontal: 10,
|
||||
// fontWeight: "600",
|
||||
transform: [{ scale }],
|
||||
}}
|
||||
>
|
||||
Add
|
||||
</Animated.Text>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
};
|
||||
@@ -51,7 +119,10 @@ export function JobListItem({ setCameraJob, setCameraJobId, item }) {
|
||||
};
|
||||
|
||||
return (
|
||||
<Swipeable renderRightActions={() => <RenderRightAction />}>
|
||||
<Swipeable
|
||||
renderLeftActions={RenderLeftAction}
|
||||
renderRightActions={RenderRightAction}
|
||||
>
|
||||
<TouchableOpacity onPress={onPress}>
|
||||
<ListItem>
|
||||
<H3>{item.ro_number || t("general.labels.na")}</H3>
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
import { Ionicons } from "@expo/vector-icons";
|
||||
import { AntDesign, Ionicons } from "@expo/vector-icons";
|
||||
import { useNavigation } from "@react-navigation/native";
|
||||
import { Card, CardItem, Text, View, Row } from "native-base";
|
||||
import { DateTime } from "luxon";
|
||||
import { Card, CardItem, Text, View } from "native-base";
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { TouchableOpacity } from "react-native-gesture-handler";
|
||||
import Swipeable from "react-native-gesture-handler/Swipeable";
|
||||
import styles from "../styles";
|
||||
import { AntDesign } from "@expo/vector-icons";
|
||||
import { DateTime } from "luxon";
|
||||
export default function NoteListItem({ item }) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
export default function NoteListItem({ item }) {
|
||||
return (
|
||||
<Swipeable renderRightActions={() => <RenderRightAction />}>
|
||||
<Card>
|
||||
|
||||
@@ -6,7 +6,7 @@ import JobNotesItem from "../job-notes-item/job-notes-item.component";
|
||||
|
||||
export default function JobNotes({ job, loading, refetch }) {
|
||||
const { t } = useTranslation();
|
||||
if (!!!job) {
|
||||
if (!job) {
|
||||
<Card>
|
||||
<Text>Job is not defined.</Text>
|
||||
</Card>;
|
||||
|
||||
@@ -2,7 +2,7 @@ import { useFocusEffect } from "@react-navigation/native";
|
||||
import { Camera } from "expo-camera";
|
||||
import * as FileSystem from "expo-file-system";
|
||||
import React, { useEffect, useRef, useState } from "react";
|
||||
import { SafeAreaView, Text, View } from "react-native";
|
||||
import { Text, View } from "react-native";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import {
|
||||
@@ -45,10 +45,8 @@ export function ScreenCamera({ cameraJobId, addPhoto }) {
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
const { status: cameraStatus } = await Camera.requestPermissionsAsync();
|
||||
setHasPermission(cameraStatus === "granted");
|
||||
|
||||
console.log("Camera Perms:", await Camera.getPermissionsAsync());
|
||||
const { status } = await Camera.requestPermissionsAsync();
|
||||
setHasPermission(status === "granted");
|
||||
})();
|
||||
}, []);
|
||||
|
||||
@@ -77,13 +75,6 @@ export function ScreenCamera({ cameraJobId, addPhoto }) {
|
||||
to: newUri,
|
||||
});
|
||||
setState({ ...state, capturing: false });
|
||||
console.log("Add Photo Object", {
|
||||
...photo,
|
||||
id: filename,
|
||||
uri: newUri,
|
||||
jobId: cameraJobId,
|
||||
video: false,
|
||||
});
|
||||
addPhoto({
|
||||
...photo,
|
||||
id: filename,
|
||||
@@ -107,7 +98,13 @@ export function ScreenCamera({ cameraJobId, addPhoto }) {
|
||||
to: newUri,
|
||||
});
|
||||
setState({ ...state, capturing: false });
|
||||
|
||||
console.log("Adding Photo", {
|
||||
...video,
|
||||
id: filename,
|
||||
uri: newUri,
|
||||
jobId: cameraJobId,
|
||||
video: true,
|
||||
});
|
||||
addPhoto({
|
||||
...video,
|
||||
id: filename,
|
||||
@@ -129,34 +126,32 @@ export function ScreenCamera({ cameraJobId, addPhoto }) {
|
||||
const { flashMode, cameraType, capturing } = state;
|
||||
|
||||
return (
|
||||
<SafeAreaView style={{ display: "flex", flex: 1 }}>
|
||||
<Camera
|
||||
style={{ flex: 1, display: "flex" }}
|
||||
type={state.cameraType}
|
||||
ref={cameraRef}
|
||||
ratio={"16:9"}
|
||||
<Camera
|
||||
style={{ flex: 1, display: "flex" }}
|
||||
type={state.cameraType}
|
||||
ref={cameraRef}
|
||||
ratio={"16:9"}
|
||||
>
|
||||
<View
|
||||
style={{
|
||||
flex: 1,
|
||||
}}
|
||||
>
|
||||
<View
|
||||
style={{
|
||||
flex: 1,
|
||||
}}
|
||||
>
|
||||
<CameraSelectJob />
|
||||
<CameraSelectJob />
|
||||
|
||||
<CameraControls
|
||||
capturing={capturing}
|
||||
flashMode={flashMode}
|
||||
cameraType={cameraType}
|
||||
setFlashMode={setFlashMode}
|
||||
setCameraType={setCameraType}
|
||||
onCaptureIn={handleCaptureIn}
|
||||
onCaptureOut={handleCaptureOut}
|
||||
onLongCapture={handleLongCapture}
|
||||
onShortCapture={handleShortCapture}
|
||||
/>
|
||||
</View>
|
||||
</Camera>
|
||||
</SafeAreaView>
|
||||
<CameraControls
|
||||
capturing={capturing}
|
||||
flashMode={flashMode}
|
||||
cameraType={cameraType}
|
||||
setFlashMode={setFlashMode}
|
||||
setCameraType={setCameraType}
|
||||
onCaptureIn={handleCaptureIn}
|
||||
onCaptureOut={handleCaptureOut}
|
||||
onLongCapture={handleLongCapture}
|
||||
onShortCapture={handleShortCapture}
|
||||
/>
|
||||
</View>
|
||||
</Camera>
|
||||
);
|
||||
}
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(ScreenCamera);
|
||||
|
||||
@@ -25,6 +25,7 @@ import ScreenMessagingList from "../screen-messaging-list/screen-messaging-list.
|
||||
import ScreenSettingsComponent from "../screen-settings/screen-settings.component";
|
||||
import ScreenSignIn from "../screen-sign-in/screen-sign-in.component";
|
||||
import ScreenSplash from "../screen-splash/screen-splash.component";
|
||||
import ScreenMediaBrowser from "../screen-media-browser/screen-media-browser.component";
|
||||
|
||||
const JobStack = createStackNavigator();
|
||||
const CameraStack = createStackNavigator();
|
||||
@@ -63,6 +64,15 @@ const JobStackNavigator = () => (
|
||||
i18n.t("joblist.labels.detail"),
|
||||
})}
|
||||
/>
|
||||
<JobStack.Screen
|
||||
name="MediaBrowser"
|
||||
component={ScreenMediaBrowser}
|
||||
// options={({ route }) => ({
|
||||
// title:
|
||||
// (route.params && route.params.title) ||
|
||||
// i18n.t("joblist.labels.detail"),
|
||||
// })}
|
||||
/>
|
||||
</JobStack.Navigator>
|
||||
);
|
||||
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
import { Ionicons } from "@expo/vector-icons";
|
||||
import { AssetsSelector } from "expo-images-picker";
|
||||
import _ from "lodash";
|
||||
import React, { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { StyleSheet, Text, View } from "react-native";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import {
|
||||
selectCurrentCameraJobId,
|
||||
selectDeleteAfterUpload,
|
||||
} from "../../redux/app/app.selectors";
|
||||
import {
|
||||
selectBodyshop,
|
||||
selectCurrentUser,
|
||||
} from "../../redux/user/user.selectors";
|
||||
import { handleUpload } from "../../util/document-upload.utility";
|
||||
import CameraSelectJob from "../camera-select-job/camera-select-job.component";
|
||||
import UploadDeleteSwitch from "../upload-delete-switch/upload-delete-switch.component";
|
||||
import UploadProgress from "../upload-progress/upload-progress.component";
|
||||
import * as FileSystem from "expo-file-system";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
currentUser: selectCurrentUser,
|
||||
bodyshop: selectBodyshop,
|
||||
selectedCameraJobId: selectCurrentCameraJobId,
|
||||
deleteAfterUpload: selectDeleteAfterUpload,
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, null)(ImageBrowserScreen);
|
||||
export function ImageBrowserScreen({
|
||||
currentUser,
|
||||
bodyshop,
|
||||
selectedCameraJobId,
|
||||
deleteAfterUpload,
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const [uploads, setUploads] = useState({});
|
||||
|
||||
function handleOnProgress(uri, percent) {
|
||||
setUploads((prevUploads) => ({ ...prevUploads, [uri]: { percent } }));
|
||||
}
|
||||
function handleOnSuccess(uri) {
|
||||
console.log("onSucces!", uri);
|
||||
setTimeout(async function () {
|
||||
setUploads((prevUploads) => _.omit(prevUploads, uri));
|
||||
if (deleteAfterUpload) {
|
||||
await FileSystem.deleteAsync(uri);
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
const onDone = async (data) => {
|
||||
const actions = [];
|
||||
console.log("Assets :>> ", data);
|
||||
data.forEach(function (p) {
|
||||
const uri = p.uri.split("/").pop();
|
||||
actions.push(
|
||||
handleUpload(
|
||||
{
|
||||
uri: p.uri,
|
||||
onError: handleOnError,
|
||||
onProgress: ({ percent }) => handleOnProgress(uri, percent),
|
||||
onSuccess: () => handleOnSuccess(uri),
|
||||
},
|
||||
{
|
||||
bodyshop: bodyshop,
|
||||
jobId: selectedCameraJobId,
|
||||
uploaded_by: currentUser.email,
|
||||
photo: p,
|
||||
}
|
||||
)
|
||||
);
|
||||
});
|
||||
Promise.all(actions);
|
||||
};
|
||||
|
||||
return (
|
||||
<View style={[styles.flex, styles.container]}>
|
||||
<CameraSelectJob />
|
||||
<UploadDeleteSwitch />
|
||||
{selectedCameraJobId && (
|
||||
<AssetsSelector
|
||||
style={{ flex: 9 }}
|
||||
options={{
|
||||
// manipulate: {
|
||||
// //width: 512,
|
||||
// compress: 0.7,
|
||||
// base64: false,
|
||||
// saveTo: "jpeg",
|
||||
// },
|
||||
assetsType: ["photo", "video"],
|
||||
//maxSelections: 5,
|
||||
margin: 3,
|
||||
portraitCols: 4,
|
||||
landscapeCols: 5,
|
||||
widgetWidth: 100,
|
||||
widgetBgColor: "white",
|
||||
selectedBgColor: "#adadad",
|
||||
spinnerColor: "#c8c8c8",
|
||||
videoIcon: {
|
||||
Component: Ionicons,
|
||||
iconName: "ios-videocam",
|
||||
color: "white",
|
||||
size: 20,
|
||||
},
|
||||
selectedIcon: {
|
||||
Component: Ionicons,
|
||||
iconName: "ios-checkmark-circle-outline",
|
||||
color: "white",
|
||||
bg: "rgba(35,35,35, 0.75)",
|
||||
size: 32,
|
||||
},
|
||||
defaultTopNavigator: {
|
||||
continueText: t("mediabrowser.actions.upload"),
|
||||
//goBackText: "Back",
|
||||
buttonStyle: styles.buttonStyle,
|
||||
textStyle: styles.textStyle,
|
||||
|
||||
backFunction: (props) => {
|
||||
console.log("Back Function", props);
|
||||
},
|
||||
doneFunction: onDone,
|
||||
},
|
||||
noAssets: {
|
||||
Component: function NoAsset() {
|
||||
return (
|
||||
<View>
|
||||
<Text>Looks like nothing here</Text>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
},
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
<UploadProgress uploads={uploads} />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
flex: {
|
||||
flex: 1,
|
||||
},
|
||||
container: {
|
||||
display: "flex",
|
||||
// position: "relative",
|
||||
},
|
||||
buttonStyle: {
|
||||
//backgroundColor: "tomato",
|
||||
},
|
||||
// eslint-disable-next-line react-native/no-color-literals
|
||||
textStyle: {
|
||||
color: "dodgerblue",
|
||||
},
|
||||
});
|
||||
|
||||
function handleOnError(...props) {
|
||||
console.log("HandleOnError", props);
|
||||
}
|
||||
@@ -1,9 +1,11 @@
|
||||
import { Button, Container, Spinner, Text as NBText, View } from "native-base";
|
||||
import _ from "lodash";
|
||||
import { Button, Spinner, Text as NBText, View } from "native-base";
|
||||
import React, { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import {
|
||||
FlatList,
|
||||
Image,
|
||||
SafeAreaView,
|
||||
StyleSheet,
|
||||
Text,
|
||||
TouchableOpacity,
|
||||
@@ -38,24 +40,14 @@ export function ScreenMediaCache({
|
||||
const { t } = useTranslation();
|
||||
const [previewVisible, setPreviewVisible] = useState(false);
|
||||
const [imgIndex, setImgIndex] = useState(0);
|
||||
const [imagesInDir, setImagesInDir] = useState([]);
|
||||
|
||||
console.log("Photos", photos);
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<View style={styles.actions}>
|
||||
<Button onPress={() => removeAllPhotos()}>
|
||||
<NBText>{t("mediacache.actions.deleteall")}</NBText>
|
||||
</Button>
|
||||
<Button onPress={() => uploadAllphotos()}>
|
||||
<NBText>{t("mediacache.actions.uploadall")}</NBText>
|
||||
{uploadInProgress && <Spinner />}
|
||||
</Button>
|
||||
</View>
|
||||
const groupedPhotos = _.groupBy(photos, "jobId");
|
||||
|
||||
const RenderJobPictures = ({ jobId, jobPhotos }) => (
|
||||
<View>
|
||||
<Text>{jobId}</Text>
|
||||
<FlatList
|
||||
data={photos}
|
||||
data={jobPhotos}
|
||||
style={{ flex: 1 }}
|
||||
contentContainerStyle={styles.listContentContainer}
|
||||
keyExtractor={(item) => item.id}
|
||||
@@ -83,6 +75,32 @@ export function ScreenMediaCache({
|
||||
)
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
|
||||
return (
|
||||
<SafeAreaView style={styles.container}>
|
||||
<View style={styles.actions}>
|
||||
<Button onPress={() => removeAllPhotos()}>
|
||||
<NBText>{t("mediacache.actions.deleteall")}</NBText>
|
||||
</Button>
|
||||
<Button onPress={() => uploadAllphotos()}>
|
||||
<NBText>{t("mediacache.actions.uploadall")}</NBText>
|
||||
{uploadInProgress && <Spinner />}
|
||||
</Button>
|
||||
</View>
|
||||
<FlatList
|
||||
data={groupedPhotos ? Object.keys(groupedPhotos) : []}
|
||||
style={{ flex: 1 }}
|
||||
contentContainerStyle={styles.listContentContainer}
|
||||
keyExtractor={(item) => item}
|
||||
renderItem={(object) => (
|
||||
<RenderJobPictures
|
||||
jobPhotos={groupedPhotos[object.item]}
|
||||
jobId={object.item}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<MediaCacheOverlay
|
||||
imgIndex={imgIndex}
|
||||
setImgIndex={setImgIndex}
|
||||
@@ -90,7 +108,7 @@ export function ScreenMediaCache({
|
||||
setPreviewVisible={setPreviewVisible}
|
||||
/>
|
||||
<Text>{`${photos.length} Photos`}</Text>
|
||||
</Container>
|
||||
</SafeAreaView>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { Container, Content, H1 } from "native-base";
|
||||
import React from "react";
|
||||
import { StyleSheet, Image } from "react-native";
|
||||
import Logo from "../../assets/logo192.png";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { H1, Container, Content } from "native-base";
|
||||
import styles from "../styles";
|
||||
import { Image, StyleSheet } from "react-native";
|
||||
import { BarIndicator } from "react-native-indicators";
|
||||
import Logo from "../../assets/logo192.png";
|
||||
import styles from "../styles";
|
||||
|
||||
export default function ScreenSplash() {
|
||||
const { t } = useTranslation();
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { Text } from "native-base";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Container, Content, Text } from "native-base";
|
||||
import { View, StyleSheet } from "react-native";
|
||||
import { StyleSheet, View } from "react-native";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { selectSignInError } from "../../redux/user/user.selectors";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
signInError: selectSignInError,
|
||||
});
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { StyleSheet } from "react-native";
|
||||
import { Row } from "native-base";
|
||||
|
||||
export default StyleSheet.create({
|
||||
contentContainer__centered: {
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { StyleSheet, Switch, Text, View } from "react-native";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { toggleDeleteAfterUpload } from "../../redux/app/app.actions";
|
||||
import { selectDeleteAfterUpload } from "../../redux/app/app.selectors";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
//currentUser: selectCurrentUser
|
||||
deleteAfterUpload: selectDeleteAfterUpload,
|
||||
});
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
toggleDeleteAfterUpload: () => dispatch(toggleDeleteAfterUpload()),
|
||||
});
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(UploadDeleteSwitch);
|
||||
|
||||
export function UploadDeleteSwitch({
|
||||
deleteAfterUpload,
|
||||
toggleDeleteAfterUpload,
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Text style={styles.text}>
|
||||
{t("mediabrowser.labels.deleteafterupload")}
|
||||
</Text>
|
||||
<Switch
|
||||
trackColor={{ false: "#767577", true: "#81b0ff" }}
|
||||
thumbColor={deleteAfterUpload ? "#f5dd4b" : "#f4f3f4"}
|
||||
ios_backgroundColor="#3e3e3e"
|
||||
onValueChange={() => toggleDeleteAfterUpload()}
|
||||
value={deleteAfterUpload}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
},
|
||||
|
||||
text: {
|
||||
flex: 1,
|
||||
},
|
||||
});
|
||||
46
components/upload-progress/upload-progress.component.jsx
Normal file
46
components/upload-progress/upload-progress.component.jsx
Normal file
@@ -0,0 +1,46 @@
|
||||
import React from "react";
|
||||
import { ScrollView, StyleSheet, Text, View } from "react-native";
|
||||
import * as Progress from "react-native-progress";
|
||||
|
||||
export default function UploadProgress({ uploads }) {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<ScrollView>
|
||||
{Object.keys(uploads).map((key) => (
|
||||
<View key={key} style={styles.progressItem}>
|
||||
<Text style={styles.progressText}>{key}</Text>
|
||||
<View style={styles.progressBarContainer}>
|
||||
<Progress.Bar
|
||||
style={styles.progress}
|
||||
height={10}
|
||||
width={null}
|
||||
progress={uploads[key].percent}
|
||||
color={uploads[key].percent === 1 ? "green" : "blue"}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
))}
|
||||
</ScrollView>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
display: "flex",
|
||||
//flex: 1,
|
||||
},
|
||||
progressItem: {
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
marginBottom: 12,
|
||||
},
|
||||
progressText: {
|
||||
flex: 1,
|
||||
},
|
||||
progressBarContainer: {
|
||||
flex: 1,
|
||||
marginLeft: 12,
|
||||
marginRight: 12,
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user