Files
bodyshop/client/src/components/documents-upload-imgproxy/documents-upload-imgproxy.utility.js
2025-03-04 11:14:43 -08:00

173 lines
5.2 KiB
JavaScript

import axios from "axios";
import exifr from "exifr";
import i18n from "i18next";
import { logImEXEvent } from "../../firebase/firebase.utils";
import { INSERT_NEW_DOCUMENT } from "../../graphql/documents.queries";
import { axiosAuthInterceptorId } from "../../utils/CleanAxios";
import client from "../../utils/GraphQLClient";
//Context: currentUserEmail, bodyshop, jobid, invoiceid
//Required to prevent headers from getting set and rejected from Cloudinary.
var cleanAxios = axios.create();
cleanAxios.interceptors.request.eject(axiosAuthInterceptorId);
export const handleUpload = (ev, context, notification) => {
logImEXEvent("document_upload", { filetype: ev.file?.type });
const { onError, onSuccess, onProgress } = ev;
const { bodyshop, jobId } = context;
const fileName = ev.file?.name || ev.filename;
let extension = fileName.split(".").pop();
let key = `${bodyshop.id}/${jobId}/${replaceAccents(fileName).replace(/[^A-Z0-9]+/gi, "_")}-${new Date().getTime()}.${extension}`;
uploadToS3(key, extension, ev.file.type, ev.file, onError, onSuccess, onProgress, context, notification).catch(
(error) => {
console.error("Error uploading file to S3", error);
notification.error({
message: i18n.t("documents.errors.insert", {
message: error.message
})
});
}
);
};
//Handles only 1 file at a time.
export const uploadToS3 = async (
key,
extension,
fileType,
file,
onError,
onSuccess,
onProgress,
context,
notification
) => {
const { bodyshop, jobId, billId, uploaded_by, callback } = context;
//Get the signed url allowing us to PUT to S3.
const signedURLResponse = await axios.post("/media/imgproxy/sign", {
filenames: [key],
bodyshopid: bodyshop.id,
jobid: jobId
});
if (signedURLResponse.status !== 200) {
if (onError) onError(signedURLResponse.statusText);
notification.error({
message: i18n.t("documents.errors.getpresignurl", {
message: signedURLResponse.statusText
})
});
return;
}
//Key should be same as we provided to maintain backwards compatibility.
const { presignedUrl: preSignedUploadUrlToS3, key: s3Key } = signedURLResponse.data.signedUrls[0];
const options = {
onUploadProgress: (e) => {
if (onProgress) onProgress({ percent: (e.loaded / e.total) * 100 });
}
};
try {
const s3UploadResponse = await cleanAxios.put(preSignedUploadUrlToS3, file, options);
//Insert the document with the matching key.
let takenat;
if (fileType.includes("image")) {
try {
const exif = await exifr.parse(file);
takenat = exif && exif.DateTimeOriginal;
} catch (error) {
console.log("Unable to parse image file for EXIF Data", error.message);
}
}
const documentInsert = await client.mutate({
mutation: INSERT_NEW_DOCUMENT,
variables: {
docInput: [
{
...(jobId ? { jobid: jobId } : {}),
...(billId ? { billid: billId } : {}),
uploaded_by: uploaded_by,
key: s3Key,
type: fileType,
extension: s3UploadResponse.data.format || extension,
bodyshopid: bodyshop.id,
size: s3UploadResponse.data.bytes || file.size, //Leftover from Cloudinary. We don't do any optimization on upload, so it will always be file.size.
takenat
}
]
}
});
if (!documentInsert.errors) {
if (onSuccess)
onSuccess({
uid: documentInsert.data.insert_documents.returning[0].id,
name: documentInsert.data.insert_documents.returning[0].name,
status: "done",
key: documentInsert.data.insert_documents.returning[0].key
});
notification.success({
key: "docuploadsuccess",
message: i18n.t("documents.successes.insert")
});
if (callback) {
callback();
}
} else {
if (onError) onError(JSON.stringify(documentInsert.errors));
notification.error({
message: i18n.t("documents.errors.insert", {
message: JSON.stringify(documentInsert.errors)
})
});
return;
}
} catch (error) {
console.log("Error uploading file to S3", error.message, error.stack);
notification.error({
message: i18n.t("documents.errors.insert", {
message: error.message
})
});
if (onError) onError(JSON.stringify(error.message));
}
};
function replaceAccents(str) {
// Verifies if the String has accents and replace them
if (str.search(/[\xC0-\xFF]/g) > -1) {
str = str
.replace(/[\xC0-\xC5]/g, "A")
.replace(/[\xC6]/g, "AE")
.replace(/[\xC7]/g, "C")
.replace(/[\xC8-\xCB]/g, "E")
.replace(/[\xCC-\xCF]/g, "I")
.replace(/[\xD0]/g, "D")
.replace(/[\xD1]/g, "N")
.replace(/[\xD2-\xD6\xD8]/g, "O")
.replace(/[\xD9-\xDC]/g, "U")
.replace(/[\xDD]/g, "Y")
.replace(/[\xDE]/g, "P")
.replace(/[\xE0-\xE5]/g, "a")
.replace(/[\xE6]/g, "ae")
.replace(/[\xE7]/g, "c")
.replace(/[\xE8-\xEB]/g, "e")
.replace(/[\xEC-\xEF]/g, "i")
.replace(/[\xF1]/g, "n")
.replace(/[\xF2-\xF6\xF8]/g, "o")
.replace(/[\xF9-\xFC]/g, "u")
.replace(/[\xFE]/g, "p")
.replace(/[\xFD\xFF]/g, "y");
}
return str;
}