diff --git a/bodyshop_translations.babel b/bodyshop_translations.babel
index d6de7fd77..c6fbd2117 100644
--- a/bodyshop_translations.babel
+++ b/bodyshop_translations.babel
@@ -37640,6 +37640,27 @@
+
+ production_by_technician
+ false
+
+
+
+
+
+ en-US
+ false
+
+
+ es-MX
+ false
+
+
+ fr-CA
+ false
+
+
+
purchases_by_cost_center_detail
false
diff --git a/client/package.json b/client/package.json
index 3cf72787b..34ae41cea 100644
--- a/client/package.json
+++ b/client/package.json
@@ -78,7 +78,8 @@
"workbox-range-requests": "^6.4.2",
"workbox-routing": "^6.4.2",
"workbox-strategies": "^6.4.2",
- "workbox-streams": "^6.4.2"
+ "workbox-streams": "^6.4.2",
+ "yauzl": "^2.10.0"
},
"scripts": {
"analyze": "source-map-explorer 'build/static/js/*.js'",
diff --git a/client/src/components/global-search/global-search.component.jsx b/client/src/components/global-search/global-search.component.jsx
index 4135f8dc7..ebd4bdd8d 100644
--- a/client/src/components/global-search/global-search.component.jsx
+++ b/client/src/components/global-search/global-search.component.jsx
@@ -172,8 +172,7 @@ export default function GlobalSearch() {
options={options}
onSearch={handleSearch}
placeholder={t("general.labels.globalsearch")}
- >
-
-
+ allowClear
+ >
);
}
diff --git a/client/src/components/jobs-documents-gallery/jobs-document-gallery.download.component.jsx b/client/src/components/jobs-documents-gallery/jobs-document-gallery.download.component.jsx
index a1be3e834..5f63fe12c 100644
--- a/client/src/components/jobs-documents-gallery/jobs-document-gallery.download.component.jsx
+++ b/client/src/components/jobs-documents-gallery/jobs-document-gallery.download.component.jsx
@@ -5,45 +5,124 @@ 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";
-export default function JobsDocumentsDownloadButton({
+import { connect } from "react-redux";
+import { createStructuredSelector } from "reselect";
+import { selectBodyshop } from "../../redux/user/user.selectors";
+const mapStateToProps = createStructuredSelector({
+ bodyshop: selectBodyshop,
+});
+const mapDispatchToProps = (dispatch) => ({
+ //setUserLanguage: language => dispatch(setUserLanguage(language))
+});
+export default connect(
+ 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),
];
- const handleDownload = () => {
- logImEXEvent("jobs_documents_download");
- axios
- .post("/media/download", {
- ids: imagesToDownload.map((_) => _.key),
- })
- .then((r) => {
- // window.open(r.data);
- downloadAs(
- r.data,
- `${identifier || "documents"}.zip`,
- (progressEvent) => {
- setDownload((currentDownloadState) => {
- return {
- downloaded: progressEvent.loaded || 0,
- speed:
- (progressEvent.loaded || 0) -
- ((currentDownloadState && currentDownloadState.downloaded) ||
- 0),
- };
- });
- },
- () => setDownload(null)
- );
- });
- };
+ function downloadProgress(progressEvent) {
+ setDownload((currentDownloadState) => {
+ return {
+ downloaded: progressEvent.loaded || 0,
+ speed:
+ (progressEvent.loaded || 0) -
+ ((currentDownloadState && currentDownloadState.downloaded) || 0),
+ };
+ });
+ }
+ 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 (
<>