- Merge client update into test-beta
Signed-off-by: Dave Richer <dave@imexsystems.ca>
This commit is contained in:
@@ -1,26 +1,26 @@
|
||||
import { DetermineFileType } from "../documents-upload/documents-upload.utility";
|
||||
import {DetermineFileType} from "../documents-upload/documents-upload.utility";
|
||||
|
||||
export const GenerateSrcUrl = (value) => {
|
||||
let extension = value.extension;
|
||||
if (extension && extension.toLowerCase().includes("heic")) extension = "jpg";
|
||||
let extension = value.extension;
|
||||
if (extension && extension.toLowerCase().includes("heic")) extension = "jpg";
|
||||
|
||||
return `${process.env.REACT_APP_CLOUDINARY_ENDPOINT}/${DetermineFileType(
|
||||
value.type
|
||||
)}/upload/${value.key}${extension ? `.${extension}` : ""}`;
|
||||
return `${process.env.REACT_APP_CLOUDINARY_ENDPOINT}/${DetermineFileType(
|
||||
value.type
|
||||
)}/upload/${value.key}${extension ? `.${extension}` : ""}`;
|
||||
};
|
||||
|
||||
export const GenerateThumbUrl = (value) => {
|
||||
let extension = value.extension;
|
||||
if (extension && extension.toLowerCase().includes("heic")) extension = "jpg";
|
||||
else if (
|
||||
DetermineFileType(value.type) !== "image" ||
|
||||
(value.type && value.type.includes("application"))
|
||||
)
|
||||
extension = "jpg";
|
||||
let extension = value.extension;
|
||||
if (extension && extension.toLowerCase().includes("heic")) extension = "jpg";
|
||||
else if (
|
||||
DetermineFileType(value.type) !== "image" ||
|
||||
(value.type && value.type.includes("application"))
|
||||
)
|
||||
extension = "jpg";
|
||||
|
||||
return `${process.env.REACT_APP_CLOUDINARY_ENDPOINT}/${DetermineFileType(
|
||||
value.type
|
||||
)}/upload/${process.env.REACT_APP_CLOUDINARY_THUMB_TRANSFORMATIONS}/${
|
||||
value.key
|
||||
}${extension ? `.${extension}` : ""}`;
|
||||
return `${process.env.REACT_APP_CLOUDINARY_ENDPOINT}/${DetermineFileType(
|
||||
value.type
|
||||
)}/upload/${process.env.REACT_APP_CLOUDINARY_THUMB_TRANSFORMATIONS}/${
|
||||
value.key
|
||||
}${extension ? `.${extension}` : ""}`;
|
||||
};
|
||||
|
||||
@@ -1,145 +1,145 @@
|
||||
import { Button, Space } from "antd";
|
||||
import {Button, Space} from "antd";
|
||||
import axios from "axios";
|
||||
import React, { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { logImEXEvent } from "../../firebase/firebase.utils";
|
||||
import React, {useState} from "react";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import {logImEXEvent} from "../../firebase/firebase.utils";
|
||||
import cleanAxios from "../../utils/CleanAxios";
|
||||
import formatBytes from "../../utils/formatbytes";
|
||||
//import yauzl from "yauzl";
|
||||
import { useTreatments } from "@splitsoftware/splitio-react";
|
||||
import {useSplitTreatments} from "@splitsoftware/splitio-react";
|
||||
|
||||
import {connect} from "react-redux";
|
||||
import {createStructuredSelector} from "reselect";
|
||||
import {selectBodyshop} from "../../redux/user/user.selectors";
|
||||
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
bodyshop: selectBodyshop,
|
||||
});
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
||||
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
||||
});
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(JobsDocumentsDownloadButton);
|
||||
|
||||
export function JobsDocumentsDownloadButton({
|
||||
bodyshop,
|
||||
galleryImages,
|
||||
identifier,
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const [download, setDownload] = useState(null);
|
||||
const { Direct_Media_Download } = useTreatments(
|
||||
["Direct_Media_Download"],
|
||||
{},
|
||||
bodyshop.imexshopid
|
||||
);
|
||||
const imagesToDownload = [
|
||||
...galleryImages.images.filter((image) => image.isSelected),
|
||||
...galleryImages.other.filter((image) => image.isSelected),
|
||||
];
|
||||
export function JobsDocumentsDownloadButton({bodyshop, galleryImages, identifier}) {
|
||||
|
||||
function downloadProgress(progressEvent) {
|
||||
setDownload((currentDownloadState) => {
|
||||
return {
|
||||
downloaded: progressEvent.loaded || 0,
|
||||
speed:
|
||||
(progressEvent.loaded || 0) -
|
||||
((currentDownloadState && currentDownloadState.downloaded) || 0),
|
||||
};
|
||||
});
|
||||
}
|
||||
const {t} = useTranslation();
|
||||
const [download, setDownload] = useState(null);
|
||||
|
||||
const handleDownload = async () => {
|
||||
logImEXEvent("jobs_documents_download");
|
||||
|
||||
const zipUrl = await axios({
|
||||
url: "/media/download",
|
||||
method: "POST",
|
||||
//responseType: "arraybuffer", // Important
|
||||
data: { ids: imagesToDownload.map((_) => _.key) },
|
||||
const {treatments: {Direct_Media_Download}} = useSplitTreatments({
|
||||
attributes: {},
|
||||
names: ["Direct_Media_Download"],
|
||||
splitKey: bodyshop.imexshopid,
|
||||
});
|
||||
|
||||
const theDownloadedZip = await cleanAxios({
|
||||
url: zipUrl.data,
|
||||
method: "GET",
|
||||
responseType: "arraybuffer",
|
||||
onDownloadProgress: downloadProgress,
|
||||
});
|
||||
setDownload(null);
|
||||
if (Direct_Media_Download.treatment === "on") {
|
||||
try {
|
||||
// const parentDir = await window.showDirectoryPicker({
|
||||
// id: "media",
|
||||
// startIn: "downloads",
|
||||
// });
|
||||
const imagesToDownload = [
|
||||
...galleryImages.images.filter((image) => image.isSelected),
|
||||
...galleryImages.other.filter((image) => image.isSelected),
|
||||
];
|
||||
|
||||
// const directory = await parentDir.getDirectoryHandle(identifier, {
|
||||
// create: true,
|
||||
// });
|
||||
|
||||
// yauzl.fromBuffer(
|
||||
// Buffer.from(theDownloadedZip.data),
|
||||
// {},
|
||||
// (err, zipFile) => {
|
||||
// if (err) throw err;
|
||||
// zipFile.on("entry", (entry) => {
|
||||
// zipFile.openReadStream(entry, async (readErr, readStream) => {
|
||||
// if (readErr) {
|
||||
// zipFile.close();
|
||||
// throw readErr;
|
||||
// }
|
||||
// if (err) throw err;
|
||||
// let fileSystemHandle = await directory.getFileHandle(
|
||||
// entry.fileName,
|
||||
// {
|
||||
// create: true,
|
||||
// }
|
||||
// );
|
||||
// const writable = await fileSystemHandle.createWritable();
|
||||
// readStream.on("data", async function (chunk) {
|
||||
// await writable.write(chunk);
|
||||
// });
|
||||
// readStream.on("end", async function () {
|
||||
// await writable.close();
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
// }
|
||||
// );
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
standardMediaDownload(theDownloadedZip.data);
|
||||
}
|
||||
} else {
|
||||
standardMediaDownload(theDownloadedZip.data);
|
||||
function downloadProgress(progressEvent) {
|
||||
setDownload((currentDownloadState) => {
|
||||
return {
|
||||
downloaded: progressEvent.loaded || 0,
|
||||
speed:
|
||||
(progressEvent.loaded || 0) -
|
||||
((currentDownloadState && currentDownloadState.downloaded) || 0),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function standardMediaDownload(bufferData) {
|
||||
const a = document.createElement("a");
|
||||
const url = window.URL.createObjectURL(new Blob([bufferData]));
|
||||
a.href = url;
|
||||
a.download = `${identifier || "documents"}.zip`;
|
||||
a.click();
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
loading={!!download}
|
||||
disabled={imagesToDownload.length < 1}
|
||||
onClick={handleDownload}
|
||||
>
|
||||
<Space>
|
||||
<span>{t("documents.actions.download")}</span>
|
||||
{download && (
|
||||
<span>{`(${formatBytes(download.downloaded)} @ ${formatBytes(
|
||||
download.speed
|
||||
)} / second)`}</span>
|
||||
)}
|
||||
</Space>
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
const handleDownload = async () => {
|
||||
logImEXEvent("jobs_documents_download");
|
||||
|
||||
const zipUrl = await axios({
|
||||
url: "/media/download",
|
||||
method: "POST",
|
||||
//responseType: "arraybuffer", // Important
|
||||
data: {ids: imagesToDownload.map((_) => _.key)},
|
||||
});
|
||||
|
||||
const theDownloadedZip = await cleanAxios({
|
||||
url: zipUrl.data,
|
||||
method: "GET",
|
||||
responseType: "arraybuffer",
|
||||
onDownloadProgress: downloadProgress,
|
||||
});
|
||||
setDownload(null);
|
||||
if (Direct_Media_Download.treatment === "on") {
|
||||
try {
|
||||
// const parentDir = await window.showDirectoryPicker({
|
||||
// id: "media",
|
||||
// startIn: "downloads",
|
||||
// });
|
||||
|
||||
// const directory = await parentDir.getDirectoryHandle(identifier, {
|
||||
// create: true,
|
||||
// });
|
||||
|
||||
// yauzl.fromBuffer(
|
||||
// Buffer.from(theDownloadedZip.data),
|
||||
// {},
|
||||
// (err, zipFile) => {
|
||||
// if (err) throw err;
|
||||
// zipFile.on("entry", (entry) => {
|
||||
// zipFile.openReadStream(entry, async (readErr, readStream) => {
|
||||
// if (readErr) {
|
||||
// zipFile.close();
|
||||
// throw readErr;
|
||||
// }
|
||||
// if (err) throw err;
|
||||
// let fileSystemHandle = await directory.getFileHandle(
|
||||
// entry.fileName,
|
||||
// {
|
||||
// create: true,
|
||||
// }
|
||||
// );
|
||||
// const writable = await fileSystemHandle.createWritable();
|
||||
// readStream.on("data", async function (chunk) {
|
||||
// await writable.write(chunk);
|
||||
// });
|
||||
// readStream.on("end", async function () {
|
||||
// await writable.close();
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
// }
|
||||
// );
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
standardMediaDownload(theDownloadedZip.data);
|
||||
}
|
||||
} else {
|
||||
standardMediaDownload(theDownloadedZip.data);
|
||||
}
|
||||
|
||||
function standardMediaDownload(bufferData) {
|
||||
const a = document.createElement("a");
|
||||
const url = window.URL.createObjectURL(new Blob([bufferData]));
|
||||
a.href = url;
|
||||
a.download = `${identifier || "documents"}.zip`;
|
||||
a.click();
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
loading={!!download}
|
||||
disabled={imagesToDownload.length < 1}
|
||||
onClick={handleDownload}
|
||||
>
|
||||
<Space>
|
||||
<span>{t("documents.actions.download")}</span>
|
||||
{download && (
|
||||
<span>{`(${formatBytes(download.downloaded)} @ ${formatBytes(
|
||||
download.speed
|
||||
)} / second)`}</span>
|
||||
)}
|
||||
</Space>
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,172 +1,172 @@
|
||||
import { useApolloClient } from "@apollo/client";
|
||||
import { Button, Form, notification, Popover, Space } from "antd";
|
||||
import {useApolloClient} from "@apollo/client";
|
||||
import {Button, Form, notification, Popover, Space} from "antd";
|
||||
import axios from "axios";
|
||||
import React, { useMemo, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { GET_DOC_SIZE_BY_JOB } from "../../graphql/documents.queries";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import React, {useMemo, useState} from "react";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import {connect} from "react-redux";
|
||||
import {createStructuredSelector} from "reselect";
|
||||
import {GET_DOC_SIZE_BY_JOB} from "../../graphql/documents.queries";
|
||||
import {selectBodyshop} from "../../redux/user/user.selectors";
|
||||
import JobSearchSelect from "../job-search-select/job-search-select.component";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
bodyshop: selectBodyshop,
|
||||
});
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
||||
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
||||
});
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(JobsDocumentsGalleryReassign);
|
||||
|
||||
export function JobsDocumentsGalleryReassign({
|
||||
bodyshop,
|
||||
galleryImages,
|
||||
callback,
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const [form] = Form.useForm();
|
||||
bodyshop,
|
||||
galleryImages,
|
||||
callback,
|
||||
}) {
|
||||
const {t} = useTranslation();
|
||||
const [form] = Form.useForm();
|
||||
|
||||
const selectedImages = useMemo(() => {
|
||||
return [
|
||||
...galleryImages.images.filter((image) => image.isSelected),
|
||||
...galleryImages.other.filter((image) => image.isSelected),
|
||||
];
|
||||
}, [galleryImages]);
|
||||
const client = useApolloClient();
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const selectedImages = useMemo(() => {
|
||||
return [
|
||||
...galleryImages.images.filter((image) => image.isSelected),
|
||||
...galleryImages.other.filter((image) => image.isSelected),
|
||||
];
|
||||
}, [galleryImages]);
|
||||
const client = useApolloClient();
|
||||
const [open, setOpen] = useState(false);
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
// const updateImage = async (i, jobid) => {
|
||||
// //Move the cloudinary image
|
||||
// const updateImage = async (i, jobid) => {
|
||||
// //Move the cloudinary image
|
||||
|
||||
// //Update it in the database.
|
||||
// const result = await updateDocument({
|
||||
// variables: {
|
||||
// id: i.id,
|
||||
// document: {
|
||||
// key: i.public_id,
|
||||
// jobid: jobid,
|
||||
// },
|
||||
// },
|
||||
// });
|
||||
// //Update it in the database.
|
||||
// const result = await updateDocument({
|
||||
// variables: {
|
||||
// id: i.id,
|
||||
// document: {
|
||||
// key: i.public_id,
|
||||
// jobid: jobid,
|
||||
// },
|
||||
// },
|
||||
// });
|
||||
|
||||
// if (!!result.errors) {
|
||||
// notification["error"]({
|
||||
// message: t("documents.errors.updating", {
|
||||
// message: JSON.stringify(result.errors),
|
||||
// }),
|
||||
// });
|
||||
// } else {
|
||||
// notification["success"]({
|
||||
// message: t("documents.successes.updated"),
|
||||
// });
|
||||
// }
|
||||
// };
|
||||
// if (!!result.errors) {
|
||||
// notification["error"]({
|
||||
// message: t("documents.errors.updating", {
|
||||
// message: JSON.stringify(result.errors),
|
||||
// }),
|
||||
// });
|
||||
// } else {
|
||||
// notification["success"]({
|
||||
// message: t("documents.successes.updated"),
|
||||
// });
|
||||
// }
|
||||
// };
|
||||
|
||||
const handleFinish = async ({ jobid }) => {
|
||||
setLoading(true);
|
||||
const handleFinish = async ({jobid}) => {
|
||||
setLoading(true);
|
||||
|
||||
//Check to see if the space remaining on the new job is sufficient. If it isn't cancel this.
|
||||
const newJobData = await client.query({
|
||||
query: GET_DOC_SIZE_BY_JOB,
|
||||
variables: { jobId: jobid },
|
||||
});
|
||||
//Check to see if the space remaining on the new job is sufficient. If it isn't cancel this.
|
||||
const newJobData = await client.query({
|
||||
query: GET_DOC_SIZE_BY_JOB,
|
||||
variables: {jobId: jobid},
|
||||
});
|
||||
|
||||
const transferedDocSizeTotal = selectedImages.reduce(
|
||||
(acc, val) => acc + val.size,
|
||||
0
|
||||
const transferedDocSizeTotal = selectedImages.reduce(
|
||||
(acc, val) => acc + val.size,
|
||||
0
|
||||
);
|
||||
|
||||
const shouldPreventTransfer =
|
||||
bodyshop.jobsizelimit -
|
||||
newJobData.data.documents_aggregate.aggregate.sum.size <
|
||||
transferedDocSizeTotal;
|
||||
|
||||
if (shouldPreventTransfer) {
|
||||
notification.open({
|
||||
key: "cannotuploaddocuments",
|
||||
type: "error",
|
||||
message: t("documents.labels.reassign_limitexceeded_title"),
|
||||
description: t("documents.labels.reassign_limitexceeded"),
|
||||
});
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const res = await axios.post("/media/rename", {
|
||||
tojobid: jobid,
|
||||
documents: selectedImages.map((i) => {
|
||||
//Need to check if the current key folder is null, or another job.
|
||||
const currentKeys = i.key.split("/");
|
||||
currentKeys[1] = jobid;
|
||||
currentKeys.join("/");
|
||||
return {
|
||||
id: i.id,
|
||||
from: i.key,
|
||||
to: currentKeys.join("/"),
|
||||
extension: i.extension,
|
||||
type: i.type,
|
||||
};
|
||||
}),
|
||||
});
|
||||
//Add in confirmation & errors.
|
||||
if (callback) callback();
|
||||
|
||||
if (res.errors) {
|
||||
notification["error"]({
|
||||
message: t("documents.errors.updating", {
|
||||
message: JSON.stringify(res.errors),
|
||||
}),
|
||||
});
|
||||
}
|
||||
if (!res.mutationResult?.errors) {
|
||||
notification["success"]({
|
||||
message: t("documents.successes.updated"),
|
||||
});
|
||||
}
|
||||
setOpen(false);
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
const popContent = (
|
||||
<div>
|
||||
<Form onFinish={handleFinish} layout="vertical" form={form}>
|
||||
<Form.Item
|
||||
label={t("documents.labels.newjobid")}
|
||||
style={{width: "20rem"}}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
//message: t("general.validation.required"),
|
||||
},
|
||||
]}
|
||||
name={"jobid"}
|
||||
>
|
||||
<JobSearchSelect/>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
<Space>
|
||||
<Button type="primary" onClick={() => form.submit()}>
|
||||
{t("general.actions.submit")}
|
||||
</Button>
|
||||
<Button onClick={() => setOpen(false)}>
|
||||
{t("general.actions.cancel")}
|
||||
</Button>
|
||||
</Space>
|
||||
</div>
|
||||
);
|
||||
|
||||
const shouldPreventTransfer =
|
||||
bodyshop.jobsizelimit -
|
||||
newJobData.data.documents_aggregate.aggregate.sum.size <
|
||||
transferedDocSizeTotal;
|
||||
|
||||
if (shouldPreventTransfer) {
|
||||
notification.open({
|
||||
key: "cannotuploaddocuments",
|
||||
type: "error",
|
||||
message: t("documents.labels.reassign_limitexceeded_title"),
|
||||
description: t("documents.labels.reassign_limitexceeded"),
|
||||
});
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const res = await axios.post("/media/rename", {
|
||||
tojobid: jobid,
|
||||
documents: selectedImages.map((i) => {
|
||||
//Need to check if the current key folder is null, or another job.
|
||||
const currentKeys = i.key.split("/");
|
||||
currentKeys[1] = jobid;
|
||||
currentKeys.join("/");
|
||||
return {
|
||||
id: i.id,
|
||||
from: i.key,
|
||||
to: currentKeys.join("/"),
|
||||
extension: i.extension,
|
||||
type: i.type,
|
||||
};
|
||||
}),
|
||||
});
|
||||
//Add in confirmation & errors.
|
||||
if (callback) callback();
|
||||
|
||||
if (res.errors) {
|
||||
notification["error"]({
|
||||
message: t("documents.errors.updating", {
|
||||
message: JSON.stringify(res.errors),
|
||||
}),
|
||||
});
|
||||
}
|
||||
if (!res.mutationResult?.errors) {
|
||||
notification["success"]({
|
||||
message: t("documents.successes.updated"),
|
||||
});
|
||||
}
|
||||
setVisible(false);
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
const popContent = (
|
||||
<div>
|
||||
<Form onFinish={handleFinish} layout="vertical" form={form}>
|
||||
<Form.Item
|
||||
label={t("documents.labels.newjobid")}
|
||||
style={{ width: "20rem" }}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
//message: t("general.validation.required"),
|
||||
},
|
||||
]}
|
||||
name={"jobid"}
|
||||
>
|
||||
<JobSearchSelect />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
<Space>
|
||||
<Button type="primary" onClick={() => form.submit()}>
|
||||
{t("general.actions.submit")}
|
||||
</Button>
|
||||
<Button onClick={() => setVisible(false)}>
|
||||
{t("general.actions.cancel")}
|
||||
</Button>
|
||||
</Space>
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<Popover content={popContent} visible={visible}>
|
||||
<Button
|
||||
disabled={selectedImages.length < 1}
|
||||
onClick={() => setVisible(true)}
|
||||
loading={loading}
|
||||
>
|
||||
{t("documents.actions.reassign")}
|
||||
</Button>
|
||||
</Popover>
|
||||
);
|
||||
return (
|
||||
<Popover content={popContent} open={open}>
|
||||
<Button
|
||||
disabled={selectedImages.length < 1}
|
||||
onClick={() => setOpen(true)}
|
||||
loading={loading}
|
||||
>
|
||||
{t("documents.actions.reassign")}
|
||||
</Button>
|
||||
</Popover>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { EditFilled, FileExcelFilled, SyncOutlined } from "@ant-design/icons";
|
||||
import { Button, Card, Col, Row, Space } from "antd";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { Gallery } from "react-grid-gallery";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import {EditFilled, FileExcelFilled, SyncOutlined} from "@ant-design/icons";
|
||||
import {Button, Card, Col, Row, Space} from "antd";
|
||||
import React, {useEffect, useState} from "react";
|
||||
import {Gallery} from "react-grid-gallery";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import DocumentsUploadComponent from "../documents-upload/documents-upload.component";
|
||||
import { DetermineFileType } from "../documents-upload/documents-upload.utility";
|
||||
import { GenerateSrcUrl, GenerateThumbUrl } from "./job-documents.utility";
|
||||
import {DetermineFileType} from "../documents-upload/documents-upload.utility";
|
||||
import {GenerateSrcUrl, GenerateThumbUrl} from "./job-documents.utility";
|
||||
import JobsDocumentsDownloadButton from "./jobs-document-gallery.download.component";
|
||||
import JobsDocumentsGalleryReassign from "./jobs-document-gallery.reassign.component";
|
||||
import JobsDocumentsDeleteButton from "./jobs-documents-gallery.delete.component";
|
||||
@@ -15,237 +15,238 @@ import Lightbox from "react-image-lightbox";
|
||||
import "react-image-lightbox/style.css";
|
||||
|
||||
function JobsDocumentsComponent({
|
||||
data,
|
||||
jobId,
|
||||
refetch,
|
||||
billId,
|
||||
billsCallback,
|
||||
totalSize,
|
||||
downloadIdentifier,
|
||||
ignoreSizeLimit,
|
||||
}) {
|
||||
const [galleryImages, setgalleryImages] = useState({ images: [], other: [] });
|
||||
const { t } = useTranslation();
|
||||
const [modalState, setModalState] = useState({ open: false, index: 0 });
|
||||
data,
|
||||
jobId,
|
||||
refetch,
|
||||
billId,
|
||||
billsCallback,
|
||||
totalSize,
|
||||
downloadIdentifier,
|
||||
ignoreSizeLimit,
|
||||
}) {
|
||||
const [galleryImages, setgalleryImages] = useState({images: [], other: []});
|
||||
const {t} = useTranslation();
|
||||
const [modalState, setModalState] = useState({open: false, index: 0});
|
||||
|
||||
useEffect(() => {
|
||||
let documents = data.reduce(
|
||||
(acc, value) => {
|
||||
const fileType = DetermineFileType(value.type);
|
||||
if (value.type.startsWith("image")) {
|
||||
acc.images.push({
|
||||
// src: GenerateSrcUrl(value),
|
||||
src: GenerateThumbUrl(value),
|
||||
// src: GenerateSrcUrl(value),
|
||||
// thumbnail: GenerateThumbUrl(value),
|
||||
fullsize: GenerateSrcUrl(value),
|
||||
height: 225,
|
||||
width: 225,
|
||||
isSelected: false,
|
||||
key: value.key,
|
||||
extension: value.extension,
|
||||
id: value.id,
|
||||
type: value.type,
|
||||
size: value.size,
|
||||
tags: [{ value: value.type, title: value.type }],
|
||||
});
|
||||
} else {
|
||||
let thumb;
|
||||
switch (fileType) {
|
||||
case "raw":
|
||||
thumb = `${window.location.origin}/file.png`;
|
||||
break;
|
||||
default:
|
||||
thumb = GenerateThumbUrl(value);
|
||||
break;
|
||||
}
|
||||
useEffect(() => {
|
||||
let documents = data.reduce(
|
||||
(acc, value) => {
|
||||
const fileType = DetermineFileType(value.type);
|
||||
if (value.type.startsWith("image")) {
|
||||
acc.images.push({
|
||||
// src: GenerateSrcUrl(value),
|
||||
src: GenerateThumbUrl(value),
|
||||
// src: GenerateSrcUrl(value),
|
||||
// thumbnail: GenerateThumbUrl(value),
|
||||
fullsize: GenerateSrcUrl(value),
|
||||
height: 225,
|
||||
width: 225,
|
||||
isSelected: false,
|
||||
key: value.key,
|
||||
extension: value.extension,
|
||||
id: value.id,
|
||||
type: value.type,
|
||||
size: value.size,
|
||||
tags: [{value: value.type, title: value.type}],
|
||||
});
|
||||
} else {
|
||||
let thumb;
|
||||
switch (fileType) {
|
||||
case "raw":
|
||||
thumb = `${window.location.origin}/file.png`;
|
||||
break;
|
||||
default:
|
||||
thumb = GenerateThumbUrl(value);
|
||||
break;
|
||||
}
|
||||
|
||||
const fileName = value.key.split("/").pop();
|
||||
acc.other.push({
|
||||
source: GenerateSrcUrl(value),
|
||||
src: thumb,
|
||||
thumbnail: thumb,
|
||||
tags: [
|
||||
{
|
||||
value: fileName,
|
||||
title: fileName,
|
||||
},
|
||||
const fileName = value.key.split("/").pop();
|
||||
acc.other.push({
|
||||
source: GenerateSrcUrl(value),
|
||||
src: thumb,
|
||||
thumbnail: thumb,
|
||||
tags: [
|
||||
{
|
||||
value: fileName,
|
||||
title: fileName,
|
||||
},
|
||||
|
||||
{ value: value.type, title: value.type },
|
||||
...(value.bill
|
||||
? [
|
||||
{
|
||||
value: value.bill.vendor.name,
|
||||
title: t("vendors.fields.name"),
|
||||
},
|
||||
{ value: value.bill.date, title: t("bills.fields.date") },
|
||||
{
|
||||
value: value.bill.invoice_number,
|
||||
title: t("bills.fields.invoice_number"),
|
||||
},
|
||||
]
|
||||
: []),
|
||||
],
|
||||
height: 225,
|
||||
width: 225,
|
||||
isSelected: false,
|
||||
extension: value.extension,
|
||||
key: value.key,
|
||||
id: value.id,
|
||||
type: value.type,
|
||||
size: value.size,
|
||||
});
|
||||
}
|
||||
{value: value.type, title: value.type},
|
||||
...(value.bill
|
||||
? [
|
||||
{
|
||||
value: value.bill.vendor.name,
|
||||
title: t("vendors.fields.name"),
|
||||
},
|
||||
{value: value.bill.date, title: t("bills.fields.date")},
|
||||
{
|
||||
value: value.bill.invoice_number,
|
||||
title: t("bills.fields.invoice_number"),
|
||||
},
|
||||
]
|
||||
: []),
|
||||
],
|
||||
height: 225,
|
||||
width: 225,
|
||||
isSelected: false,
|
||||
extension: value.extension,
|
||||
key: value.key,
|
||||
id: value.id,
|
||||
type: value.type,
|
||||
size: value.size,
|
||||
});
|
||||
}
|
||||
|
||||
return acc;
|
||||
},
|
||||
{ images: [], other: [] }
|
||||
return acc;
|
||||
},
|
||||
{images: [], other: []}
|
||||
);
|
||||
setgalleryImages(documents);
|
||||
}, [data, setgalleryImages, t]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Row gutter={[16, 16]}>
|
||||
<Col span={24}>
|
||||
<Space wrap>
|
||||
<Button onClick={() => refetch && refetch()}>
|
||||
<SyncOutlined/>
|
||||
</Button>
|
||||
<JobsDocumentsGallerySelectAllComponent
|
||||
galleryImages={galleryImages}
|
||||
setGalleryImages={setgalleryImages}
|
||||
/>
|
||||
<JobsDocumentsDownloadButton
|
||||
galleryImages={galleryImages}
|
||||
identifier={downloadIdentifier}
|
||||
/>
|
||||
<JobsDocumentsDeleteButton
|
||||
galleryImages={galleryImages}
|
||||
deletionCallback={billsCallback || refetch}
|
||||
/>
|
||||
{!billId && (
|
||||
<JobsDocumentsGalleryReassign
|
||||
galleryImages={galleryImages}
|
||||
callback={refetch}
|
||||
/>
|
||||
)}
|
||||
</Space>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<Card>
|
||||
<DocumentsUploadComponent
|
||||
jobId={jobId}
|
||||
totalSize={totalSize}
|
||||
billId={billId}
|
||||
callbackAfterUpload={billsCallback || refetch}
|
||||
ignoreSizeLimit={ignoreSizeLimit}
|
||||
/>
|
||||
</Card>
|
||||
</Col>
|
||||
|
||||
<Col span={24}>
|
||||
<Card title={t("jobs.labels.documents-images")}>
|
||||
<Gallery
|
||||
images={galleryImages.images}
|
||||
onClick={(index, item) => {
|
||||
setModalState({open: true, index: index});
|
||||
// window.open(
|
||||
// item.fullsize,
|
||||
// "_blank",
|
||||
// "toolbar=0,location=0,menubar=0"
|
||||
// );
|
||||
}}
|
||||
onSelect={(index, image) => {
|
||||
setgalleryImages({
|
||||
...galleryImages,
|
||||
images: galleryImages.images.map((g, idx) =>
|
||||
index === idx ? {...g, isSelected: !g.isSelected} : g
|
||||
),
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</Card>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<Card title={t("jobs.labels.documents-other")}>
|
||||
<Gallery
|
||||
images={galleryImages.other}
|
||||
thumbnailStyle={() => {
|
||||
return {
|
||||
backgroundImage: <FileExcelFilled/>,
|
||||
height: "100%",
|
||||
width: "100%",
|
||||
cursor: "pointer",
|
||||
};
|
||||
}}
|
||||
onClick={(index) => {
|
||||
window.open(
|
||||
galleryImages.other[index].source,
|
||||
"_blank",
|
||||
"toolbar=0,location=0,menubar=0"
|
||||
);
|
||||
}}
|
||||
onSelect={(index) => {
|
||||
setgalleryImages({
|
||||
...galleryImages,
|
||||
other: galleryImages.other.map((g, idx) =>
|
||||
index === idx ? {...g, isSelected: !g.isSelected} : g
|
||||
),
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</Card>
|
||||
</Col>
|
||||
{modalState.open && (
|
||||
<Lightbox
|
||||
toolbarButtons={[
|
||||
<EditFilled
|
||||
onClick={() => {
|
||||
const newWindow = window.open(
|
||||
`${window.location.protocol}//${
|
||||
window.location.host
|
||||
}/edit?documentId=${
|
||||
galleryImages.images[modalState.index].id
|
||||
}`,
|
||||
"_blank",
|
||||
"noopener,noreferrer"
|
||||
);
|
||||
if (newWindow) newWindow.opener = null;
|
||||
}}
|
||||
/>,
|
||||
]}
|
||||
mainSrc={galleryImages.images[modalState.index].fullsize}
|
||||
nextSrc={
|
||||
galleryImages.images[
|
||||
(modalState.index + 1) % galleryImages.images.length
|
||||
].fullsize
|
||||
}
|
||||
prevSrc={
|
||||
galleryImages.images[
|
||||
(modalState.index + galleryImages.images.length - 1) %
|
||||
galleryImages.images.length
|
||||
].fullsize
|
||||
}
|
||||
onCloseRequest={() => setModalState({open: false, index: 0})}
|
||||
onMovePrevRequest={() =>
|
||||
setModalState({
|
||||
...modalState,
|
||||
index:
|
||||
(modalState.index + galleryImages.images.length - 1) %
|
||||
galleryImages.images.length,
|
||||
})
|
||||
}
|
||||
onMoveNextRequest={() =>
|
||||
setModalState({
|
||||
...modalState,
|
||||
index: (modalState.index + 1) % galleryImages.images.length,
|
||||
})
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
setgalleryImages(documents);
|
||||
}, [data, setgalleryImages, t]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Row gutter={[16, 16]}>
|
||||
<Col span={24}>
|
||||
<Space wrap>
|
||||
<Button onClick={() => refetch && refetch()}>
|
||||
<SyncOutlined />
|
||||
</Button>
|
||||
<JobsDocumentsGallerySelectAllComponent
|
||||
galleryImages={galleryImages}
|
||||
setGalleryImages={setgalleryImages}
|
||||
/>
|
||||
<JobsDocumentsDownloadButton
|
||||
galleryImages={galleryImages}
|
||||
identifier={downloadIdentifier}
|
||||
/>
|
||||
<JobsDocumentsDeleteButton
|
||||
galleryImages={galleryImages}
|
||||
deletionCallback={billsCallback || refetch}
|
||||
/>
|
||||
{!billId && (
|
||||
<JobsDocumentsGalleryReassign
|
||||
galleryImages={galleryImages}
|
||||
callback={refetch}
|
||||
/>
|
||||
)}
|
||||
</Space>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<Card>
|
||||
<DocumentsUploadComponent
|
||||
jobId={jobId}
|
||||
totalSize={totalSize}
|
||||
billId={billId}
|
||||
callbackAfterUpload={billsCallback || refetch}
|
||||
ignoreSizeLimit={ignoreSizeLimit}
|
||||
/>
|
||||
</Card>
|
||||
</Col>
|
||||
|
||||
<Col span={24}>
|
||||
<Card title={t("jobs.labels.documents-images")}>
|
||||
<Gallery
|
||||
images={galleryImages.images}
|
||||
onClick={(index, item) => {
|
||||
setModalState({ open: true, index: index });
|
||||
// window.open(
|
||||
// item.fullsize,
|
||||
// "_blank",
|
||||
// "toolbar=0,location=0,menubar=0"
|
||||
// );
|
||||
}}
|
||||
onSelect={(index, image) => {
|
||||
setgalleryImages({
|
||||
...galleryImages,
|
||||
images: galleryImages.images.map((g, idx) =>
|
||||
index === idx ? { ...g, isSelected: !g.isSelected } : g
|
||||
),
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</Card>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<Card title={t("jobs.labels.documents-other")}>
|
||||
<Gallery
|
||||
images={galleryImages.other}
|
||||
thumbnailStyle={() => {
|
||||
return {
|
||||
backgroundImage: <FileExcelFilled />,
|
||||
height: "100%",
|
||||
width: "100%",
|
||||
cursor: "pointer",
|
||||
};
|
||||
}}
|
||||
onClick={(index) => {
|
||||
window.open(
|
||||
galleryImages.other[index].source,
|
||||
"_blank",
|
||||
"toolbar=0,location=0,menubar=0"
|
||||
);
|
||||
}}
|
||||
onSelect={(index) => {
|
||||
setgalleryImages({
|
||||
...galleryImages,
|
||||
other: galleryImages.other.map((g, idx) =>
|
||||
index === idx ? { ...g, isSelected: !g.isSelected } : g
|
||||
),
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</Card>
|
||||
</Col>
|
||||
{modalState.open && (
|
||||
<Lightbox
|
||||
toolbarButtons={[
|
||||
<EditFilled
|
||||
onClick={() => {
|
||||
const newWindow = window.open(
|
||||
`${window.location.protocol}//${
|
||||
window.location.host
|
||||
}/edit?documentId=${
|
||||
galleryImages.images[modalState.index].id
|
||||
}`,
|
||||
"_blank",
|
||||
"noopener,noreferrer"
|
||||
);
|
||||
if (newWindow) newWindow.opener = null;
|
||||
}}
|
||||
/>,
|
||||
]}
|
||||
mainSrc={galleryImages.images[modalState.index].fullsize}
|
||||
nextSrc={
|
||||
galleryImages.images[
|
||||
(modalState.index + 1) % galleryImages.images.length
|
||||
].fullsize
|
||||
}
|
||||
prevSrc={
|
||||
galleryImages.images[
|
||||
(modalState.index + galleryImages.images.length - 1) %
|
||||
galleryImages.images.length
|
||||
].fullsize
|
||||
}
|
||||
onCloseRequest={() => setModalState({ open: false, index: 0 })}
|
||||
onMovePrevRequest={() =>
|
||||
setModalState({
|
||||
...modalState,
|
||||
index:
|
||||
(modalState.index + galleryImages.images.length - 1) %
|
||||
galleryImages.images.length,
|
||||
})
|
||||
}
|
||||
onMoveNextRequest={() =>
|
||||
setModalState({
|
||||
...modalState,
|
||||
index: (modalState.index + 1) % galleryImages.images.length,
|
||||
})
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default JobsDocumentsComponent;
|
||||
|
||||
@@ -1,35 +1,35 @@
|
||||
import { useQuery } from "@apollo/client";
|
||||
import {useQuery} from "@apollo/client";
|
||||
import React from "react";
|
||||
import { GET_DOCUMENTS_BY_JOB } from "../../graphql/documents.queries";
|
||||
import {GET_DOCUMENTS_BY_JOB} from "../../graphql/documents.queries";
|
||||
import AlertComponent from "../alert/alert.component";
|
||||
import LoadingSpinner from "../loading-spinner/loading-spinner.component";
|
||||
import JobDocuments from "./jobs-documents-gallery.component";
|
||||
|
||||
export default function JobsDocumentsContainer({
|
||||
jobId,
|
||||
billId,
|
||||
documentsList,
|
||||
billsCallback,
|
||||
}) {
|
||||
const { loading, error, data, refetch } = useQuery(GET_DOCUMENTS_BY_JOB, {
|
||||
variables: { jobId: jobId },
|
||||
fetchPolicy: "network-only",
|
||||
nextFetchPolicy: "network-only",
|
||||
skip: !!billId,
|
||||
});
|
||||
jobId,
|
||||
billId,
|
||||
documentsList,
|
||||
billsCallback,
|
||||
}) {
|
||||
const {loading, error, data, refetch} = useQuery(GET_DOCUMENTS_BY_JOB, {
|
||||
variables: {jobId: jobId},
|
||||
fetchPolicy: "network-only",
|
||||
nextFetchPolicy: "network-only",
|
||||
skip: !!billId,
|
||||
});
|
||||
|
||||
if (loading) return <LoadingSpinner />;
|
||||
if (error) return <AlertComponent type="error" message={error.message} />;
|
||||
if (loading) return <LoadingSpinner/>;
|
||||
if (error) return <AlertComponent type="error" message={error.message}/>;
|
||||
|
||||
return (
|
||||
<JobDocuments
|
||||
data={(data && data.documents) || documentsList || []}
|
||||
downloadIdentifier={data && data.jobs_by_pk.ro_number}
|
||||
totalSize={data && data.documents_aggregate.aggregate.sum.size}
|
||||
billId={billId}
|
||||
jobId={jobId}
|
||||
refetch={refetch}
|
||||
billsCallback={billsCallback}
|
||||
/>
|
||||
);
|
||||
return (
|
||||
<JobDocuments
|
||||
data={(data && data.documents) || documentsList || []}
|
||||
downloadIdentifier={data && data.jobs_by_pk.ro_number}
|
||||
totalSize={data && data.documents_aggregate.aggregate.sum.size}
|
||||
billId={billId}
|
||||
jobId={jobId}
|
||||
refetch={refetch}
|
||||
billsCallback={billsCallback}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,62 +1,62 @@
|
||||
import { QuestionCircleOutlined } from "@ant-design/icons";
|
||||
import { Button, notification, Popconfirm } from "antd";
|
||||
import {QuestionCircleOutlined} from "@ant-design/icons";
|
||||
import {Button, notification, Popconfirm} from "antd";
|
||||
import axios from "axios";
|
||||
import React, { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { logImEXEvent } from "../../firebase/firebase.utils";
|
||||
import React, {useState} from "react";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import {logImEXEvent} from "../../firebase/firebase.utils";
|
||||
//Context: currentUserEmail, bodyshop, jobid, invoiceid
|
||||
|
||||
export default function JobsDocumentsDeleteButton({
|
||||
galleryImages,
|
||||
deletionCallback,
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
galleryImages,
|
||||
deletionCallback,
|
||||
}) {
|
||||
const {t} = useTranslation();
|
||||
|
||||
const imagesToDelete = [
|
||||
...galleryImages.images.filter((image) => image.isSelected),
|
||||
...galleryImages.other.filter((image) => image.isSelected),
|
||||
];
|
||||
const [loading, setLoading] = useState(false);
|
||||
const imagesToDelete = [
|
||||
...galleryImages.images.filter((image) => image.isSelected),
|
||||
...galleryImages.other.filter((image) => image.isSelected),
|
||||
];
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const handleDelete = async () => {
|
||||
logImEXEvent("job_documents_delete", { count: imagesToDelete.length });
|
||||
setLoading(true);
|
||||
const res = await axios.post("/media/delete", {
|
||||
ids: imagesToDelete,
|
||||
});
|
||||
const handleDelete = async () => {
|
||||
logImEXEvent("job_documents_delete", {count: imagesToDelete.length});
|
||||
setLoading(true);
|
||||
const res = await axios.post("/media/delete", {
|
||||
ids: imagesToDelete,
|
||||
});
|
||||
|
||||
if (res.data.error) {
|
||||
notification["error"]({
|
||||
message: t("documents.errors.deleting", {
|
||||
error: JSON.stringify(res.data.error.response.errors),
|
||||
}),
|
||||
});
|
||||
} else {
|
||||
notification.open({
|
||||
key: "docdeletedsuccesfully",
|
||||
type: "success",
|
||||
message: t("documents.successes.delete"),
|
||||
});
|
||||
if (res.data.error) {
|
||||
notification["error"]({
|
||||
message: t("documents.errors.deleting", {
|
||||
error: JSON.stringify(res.data.error.response.errors),
|
||||
}),
|
||||
});
|
||||
} else {
|
||||
notification.open({
|
||||
key: "docdeletedsuccesfully",
|
||||
type: "success",
|
||||
message: t("documents.successes.delete"),
|
||||
});
|
||||
|
||||
if (deletionCallback) deletionCallback();
|
||||
}
|
||||
if (deletionCallback) deletionCallback();
|
||||
}
|
||||
|
||||
setLoading(false);
|
||||
};
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<Popconfirm
|
||||
disabled={imagesToDelete.length < 1}
|
||||
icon={<QuestionCircleOutlined style={{ color: "red" }} />}
|
||||
onConfirm={handleDelete}
|
||||
title={t("documents.labels.confirmdelete")}
|
||||
okText={t("general.actions.delete")}
|
||||
okButtonProps={{ type: "danger" }}
|
||||
cancelText={t("general.actions.cancel")}
|
||||
>
|
||||
<Button disabled={imagesToDelete.length < 1} loading={loading}>
|
||||
{t("documents.actions.delete")}
|
||||
</Button>
|
||||
</Popconfirm>
|
||||
);
|
||||
return (
|
||||
<Popconfirm
|
||||
disabled={imagesToDelete.length < 1}
|
||||
icon={<QuestionCircleOutlined style={{color: "red"}}/>}
|
||||
onConfirm={handleDelete}
|
||||
title={t("documents.labels.confirmdelete")}
|
||||
okText={t("general.actions.delete")}
|
||||
okButtonProps={{type: "danger"}}
|
||||
cancelText={t("general.actions.cancel")}
|
||||
>
|
||||
<Button disabled={imagesToDelete.length < 1} loading={loading}>
|
||||
{t("documents.actions.delete")}
|
||||
</Button>
|
||||
</Popconfirm>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,53 +1,54 @@
|
||||
import React, { useEffect } from "react";
|
||||
import { Gallery } from "react-grid-gallery";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { GenerateSrcUrl, GenerateThumbUrl } from "./job-documents.utility";
|
||||
import React, {useEffect} from "react";
|
||||
import {Gallery} from "react-grid-gallery";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import {GenerateSrcUrl, GenerateThumbUrl} from "./job-documents.utility";
|
||||
|
||||
function JobsDocumentGalleryExternal({
|
||||
data,
|
||||
data,
|
||||
|
||||
externalMediaState,
|
||||
}) {
|
||||
const [galleryImages, setgalleryImages] = externalMediaState;
|
||||
const { t } = useTranslation();
|
||||
externalMediaState,
|
||||
}) {
|
||||
const [galleryImages, setgalleryImages] = externalMediaState;
|
||||
const {t} = useTranslation();
|
||||
|
||||
useEffect(() => {
|
||||
let documents = data.reduce((acc, value) => {
|
||||
if (value.type.startsWith("image")) {
|
||||
acc.push({
|
||||
fullsize: GenerateSrcUrl(value),
|
||||
src: GenerateThumbUrl(value),
|
||||
thumbnailHeight: 225,
|
||||
thumbnailWidth: 225,
|
||||
isSelected: false,
|
||||
key: value.key,
|
||||
extension: value.extension,
|
||||
id: value.id,
|
||||
type: value.type,
|
||||
tags: [{ value: value.type, title: value.type }],
|
||||
size: value.size,
|
||||
});
|
||||
}
|
||||
useEffect(() => {
|
||||
let documents = data.reduce((acc, value) => {
|
||||
if (value.type.startsWith("image")) {
|
||||
acc.push({
|
||||
fullsize: GenerateSrcUrl(value),
|
||||
src: GenerateThumbUrl(value),
|
||||
thumbnailHeight: 225,
|
||||
thumbnailWidth: 225,
|
||||
isSelected: false,
|
||||
key: value.key,
|
||||
extension: value.extension,
|
||||
id: value.id,
|
||||
type: value.type,
|
||||
tags: [{value: value.type, title: value.type}],
|
||||
size: value.size,
|
||||
});
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, []);
|
||||
setgalleryImages(documents);
|
||||
}, [data, setgalleryImages, t]);
|
||||
return acc;
|
||||
}, []);
|
||||
setgalleryImages(documents);
|
||||
}, [data, setgalleryImages, t]);
|
||||
|
||||
return (
|
||||
<div className="clearfix">
|
||||
<Gallery
|
||||
images={galleryImages}
|
||||
backdropClosesModal={true}
|
||||
onSelect={(index, image) => {
|
||||
setgalleryImages(
|
||||
galleryImages.map((g, idx) =>
|
||||
index === idx ? { ...g, isSelected: !g.isSelected } : g
|
||||
)
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<div className="clearfix">
|
||||
<Gallery
|
||||
images={galleryImages}
|
||||
backdropClosesModal={true}
|
||||
onSelect={(index, image) => {
|
||||
setgalleryImages(
|
||||
galleryImages.map((g, idx) =>
|
||||
index === idx ? {...g, isSelected: !g.isSelected} : g
|
||||
)
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default JobsDocumentGalleryExternal;
|
||||
|
||||
@@ -1,67 +1,67 @@
|
||||
import { Button, Space } from "antd";
|
||||
import {Button, Space} from "antd";
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import {useTranslation} from "react-i18next";
|
||||
|
||||
export default function JobsDocumentsGallerySelectAllComponent({
|
||||
galleryImages,
|
||||
setGalleryImages,
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
galleryImages,
|
||||
setGalleryImages,
|
||||
}) {
|
||||
const {t} = useTranslation();
|
||||
|
||||
const handleSelectAll = () => {
|
||||
setGalleryImages({
|
||||
...galleryImages,
|
||||
other: galleryImages.other.map((i) => {
|
||||
return { ...i, isSelected: true };
|
||||
}),
|
||||
images: galleryImages.images.map((i) => {
|
||||
return { ...i, isSelected: true };
|
||||
}),
|
||||
});
|
||||
};
|
||||
const handleSelectAllImages = () => {
|
||||
setGalleryImages({
|
||||
...galleryImages,
|
||||
const handleSelectAll = () => {
|
||||
setGalleryImages({
|
||||
...galleryImages,
|
||||
other: galleryImages.other.map((i) => {
|
||||
return {...i, isSelected: true};
|
||||
}),
|
||||
images: galleryImages.images.map((i) => {
|
||||
return {...i, isSelected: true};
|
||||
}),
|
||||
});
|
||||
};
|
||||
const handleSelectAllImages = () => {
|
||||
setGalleryImages({
|
||||
...galleryImages,
|
||||
|
||||
images: galleryImages.images.map((i) => {
|
||||
return { ...i, isSelected: true };
|
||||
}),
|
||||
});
|
||||
};
|
||||
const handleSelectAllDocuments = () => {
|
||||
setGalleryImages({
|
||||
...galleryImages,
|
||||
other: galleryImages.other.map((i) => {
|
||||
return { ...i, isSelected: true };
|
||||
}),
|
||||
});
|
||||
};
|
||||
const handleDeselectAll = () => {
|
||||
setGalleryImages({
|
||||
...galleryImages,
|
||||
other: galleryImages.other.map((i) => {
|
||||
return { ...i, isSelected: false };
|
||||
}),
|
||||
images: galleryImages.images.map((i) => {
|
||||
return { ...i, isSelected: false };
|
||||
}),
|
||||
});
|
||||
};
|
||||
images: galleryImages.images.map((i) => {
|
||||
return {...i, isSelected: true};
|
||||
}),
|
||||
});
|
||||
};
|
||||
const handleSelectAllDocuments = () => {
|
||||
setGalleryImages({
|
||||
...galleryImages,
|
||||
other: galleryImages.other.map((i) => {
|
||||
return {...i, isSelected: true};
|
||||
}),
|
||||
});
|
||||
};
|
||||
const handleDeselectAll = () => {
|
||||
setGalleryImages({
|
||||
...galleryImages,
|
||||
other: galleryImages.other.map((i) => {
|
||||
return {...i, isSelected: false};
|
||||
}),
|
||||
images: galleryImages.images.map((i) => {
|
||||
return {...i, isSelected: false};
|
||||
}),
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Space wrap>
|
||||
<Button onClick={handleSelectAll}>
|
||||
{t("general.actions.selectall")}
|
||||
</Button>
|
||||
<Button onClick={handleSelectAllImages}>
|
||||
{t("documents.actions.selectallimages")}
|
||||
</Button>
|
||||
<Button onClick={handleSelectAllDocuments}>
|
||||
{t("documents.actions.selectallotherdocuments")}
|
||||
</Button>
|
||||
<Button onClick={handleDeselectAll}>
|
||||
{t("general.actions.deselectall")}
|
||||
</Button>
|
||||
</Space>
|
||||
);
|
||||
return (
|
||||
<Space wrap>
|
||||
<Button onClick={handleSelectAll}>
|
||||
{t("general.actions.selectall")}
|
||||
</Button>
|
||||
<Button onClick={handleSelectAllImages}>
|
||||
{t("documents.actions.selectallimages")}
|
||||
</Button>
|
||||
<Button onClick={handleSelectAllDocuments}>
|
||||
{t("documents.actions.selectallotherdocuments")}
|
||||
</Button>
|
||||
<Button onClick={handleDeselectAll}>
|
||||
{t("general.actions.deselectall")}
|
||||
</Button>
|
||||
</Space>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user