173 lines
5.2 KiB
JavaScript
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;
|
|
}
|