From c68835153fcb598e6c2a771fa10f0070300cf35e Mon Sep 17 00:00:00 2001 From: Patrick Fic <> Date: Wed, 30 Sep 2020 07:58:37 -0700 Subject: [PATCH] WIP Code Cleanup for document upload. BOD-420 --- .../documents-upload.component.jsx | 53 +++- .../documents-upload.container.jsx | 41 --- .../documents-upload.utility.js | 265 ++++++++++-------- .../jobs-documents-gallery.component.jsx | 28 +- 4 files changed, 204 insertions(+), 183 deletions(-) delete mode 100644 client/src/components/documents-upload/documents-upload.container.jsx diff --git a/client/src/components/documents-upload/documents-upload.component.jsx b/client/src/components/documents-upload/documents-upload.component.jsx index 287866f00..412918683 100644 --- a/client/src/components/documents-upload/documents-upload.component.jsx +++ b/client/src/components/documents-upload/documents-upload.component.jsx @@ -1,20 +1,47 @@ import { UploadOutlined } from "@ant-design/icons"; import { Button, Upload } from "antd"; import React from "react"; +import { connect } from "react-redux"; +import { createStructuredSelector } from "reselect"; +import { + selectBodyshop, + selectCurrentUser, +} from "../../redux/user/user.selectors"; +import { handleUpload } from "./documents-upload.utility"; -export default function DocumentsUploadComponent({ handleUpload, UploadRef }) { +const mapStateToProps = createStructuredSelector({ + currentUser: selectCurrentUser, + bodyshop: selectBodyshop, +}); + +export function DocumentsUploadComponent({ + currentUser, + bodyshop, + jobId, + tagsArray, + billId, + callbackAfterUpload, +}) { return ( -
- - - -
+ + handleUpload(ev, { + bodyshop: bodyshop, + uploaded_by: currentUser.email, + jobId: jobId, + billId: billId, + tagsArray: tagsArray, + callback: callbackAfterUpload, + }) + } + accept="audio/*,video/*,image/*" + showUploadList={false} + > + + ); } +export default connect(mapStateToProps, null)(DocumentsUploadComponent); diff --git a/client/src/components/documents-upload/documents-upload.container.jsx b/client/src/components/documents-upload/documents-upload.container.jsx deleted file mode 100644 index 1cfd6bfae..000000000 --- a/client/src/components/documents-upload/documents-upload.container.jsx +++ /dev/null @@ -1,41 +0,0 @@ -import React from "react"; -import { connect } from "react-redux"; -import { createStructuredSelector } from "reselect"; -import { - selectBodyshop, - selectCurrentUser, -} from "../../redux/user/user.selectors"; -import DocumentsUploadComponent from "./documents-upload.component"; -import { handleUpload } from "./documents-upload.utility"; - -const mapStateToProps = createStructuredSelector({ - currentUser: selectCurrentUser, - bodyshop: selectBodyshop, -}); - -export function DocumentsUploadContainer({ - jobId, - tagsArray, - billId, - currentUser, - bodyshop, - callbackAfterUpload, - onChange, -}) { - return ( - - handleUpload(ev, { - bodyshop: bodyshop, - uploaded_by: currentUser.email, - jobId: jobId, - billId: billId, - tagsArray: tagsArray, - callback: callbackAfterUpload, - }) - } - /> - ); -} - -export default connect(mapStateToProps, null)(DocumentsUploadContainer); diff --git a/client/src/components/documents-upload/documents-upload.utility.js b/client/src/components/documents-upload/documents-upload.utility.js index c04b44841..c5e43831b 100644 --- a/client/src/components/documents-upload/documents-upload.utility.js +++ b/client/src/components/documents-upload/documents-upload.utility.js @@ -12,7 +12,7 @@ var cleanAxios = axios.create(); cleanAxios.interceptors.request.eject(axiosAuthInterceptorId); export const handleUpload = (ev, context) => { - console.log("ev", ev); + console.log("Handling Upload", ev); logImEXEvent("document_upload", { filetype: ev.file.type }); @@ -22,43 +22,53 @@ export const handleUpload = (ev, context) => { //If JPEG, resize and upload. //TODO If this is just an invoice job? Where to put it? let key = `${bodyshop.id}/${jobId}/${ev.file.name}`; - if (ev.file.type.includes("image")) { - Resizer.imageFileResizer( - ev.file, - 2500, - 2500, - "JPEG", - 75, - 0, - (uri) => { - let file = new File([uri], ev.file.name, {}); - file.uid = ev.file.uid; - uploadToS3( - key, - file.type, - file, - onError, - onSuccess, - onProgress, - context - ); - }, - "blob" - ); - } else { - uploadToS3( - key, - ev.file.type, - ev.file, - onError, - onSuccess, - onProgress, - context - ); - } + uploadToCloudinary( + key, + ev.file.type, + ev.file, + onError, + onSuccess, + onProgress, + context + ); + + // if (ev.file.type.includes("image")) { + // Resizer.imageFileResizer( + // ev.file, + // 2500, + // 2500, + // "JPEG", + // 75, + // 0, + // (uri) => { + // let file = new File([uri], ev.file.name, {}); + // file.uid = ev.file.uid; + // uploadToCloudinary( + // key, + // file.type, + // file, + // onError, + // onSuccess, + // onProgress, + // context + // ); + // }, + // "blob" + // ); + // } else { + // uploadToCloudinary( + // key, + // ev.file.type, + // ev.file, + // onError, + // onSuccess, + // onProgress, + // context + // ); + // } }; -export const uploadToS3 = ( +export const uploadToCloudinary = async ( fileName, fileType, file, @@ -69,92 +79,115 @@ export const uploadToS3 = ( ) => { const { bodyshop, jobId, billId, uploaded_by, callback, tagsArray } = context; + //Set variables for getting the signed URL. let timestamp = Math.floor(Date.now() / 1000); let public_id = fileName; let tags = `${bodyshop.textid},${ tagsArray ? tagsArray.map((tag) => `${tag},`) : "" }`; let eager = process.env.REACT_APP_CLOUDINARY_THUMB_TRANSFORMATIONS; - axios - .post("/media/sign", { - eager: eager, - public_id: public_id, - tags: tags, - timestamp: timestamp, - }) - .then((response) => { - var signature = response.data; - var options = { - headers: { "X-Requested-With": "XMLHttpRequest" }, - onUploadProgress: (e) => { - if (!!onProgress) onProgress({ percent: (e.loaded / e.total) * 100 }); - }, - }; - const formData = new FormData(); - formData.append("file", file); - formData.append("eager", eager); - formData.append("api_key", process.env.REACT_APP_CLOUDINARY_API_KEY); - formData.append("public_id", public_id); - formData.append("tags", tags); - formData.append("timestamp", timestamp); - formData.append("signature", signature); - cleanAxios - .post(`${process.env.REACT_APP_CLOUDINARY_ENDPOINT}/upload`, formData, { - ...options, - }) - .then((response) => { - console.log("Upload Response", response); - client - .mutate({ - mutation: INSERT_NEW_DOCUMENT, - variables: { - docInput: [ - { - jobid: jobId, - uploaded_by: uploaded_by, - key: fileName, - billid: billId, - type: fileType, - }, - ], - }, - }) - .then((r) => { - if (!!onSuccess) - onSuccess({ - uid: r.data.insert_documents.returning[0].id, - name: r.data.insert_documents.returning[0].name, - status: "done", - key: r.data.insert_documents.returning[0].key, - }); - notification["success"]({ - message: i18n.t("documents.successes.insert"), - }); - if (callback) { - callback(); - } - // if (onChange) { - // //Used in a form. - // onChange(UploadRef.current.state.fileList); - // } - }); - }) - .catch((error) => { - if (!!onError) onError(error); - notification["error"]({ - message: i18n.t("documents.errors.insert", { - message: JSON.stringify(error), - }), - }); - }); - }) - .catch((error) => { - console.log("error", error); - notification["error"]({ - message: i18n.t("documents.errors.getpresignurl", { - message: JSON.stringify(error), - }), - }); + //Get the signed url. + + const signedURLResponse = await axios.post("/media/sign", { + eager: eager, + public_id: public_id, + tags: tags, + timestamp: timestamp, + }); + + if (signedURLResponse.status !== 200) { + console.log("Error Getting Signed URL", signedURLResponse.statusText); + if (!!onError) onError(signedURLResponse.statusText); + notification["error"]({ + message: i18n.t("documents.errors.getpresignurl", { + message: signedURLResponse.statusText, + }), }); + return; + } + + //Build request to end to cloudinary. + var signature = signedURLResponse.data; + var options = { + headers: { "X-Requested-With": "XMLHttpRequest" }, + onUploadProgress: (e) => { + if (!!onProgress) onProgress({ percent: (e.loaded / e.total) * 100 }); + }, + }; + const formData = new FormData(); + formData.append("file", file); + formData.append("eager", eager); + formData.append("api_key", process.env.REACT_APP_CLOUDINARY_API_KEY); + formData.append("public_id", public_id); + formData.append("tags", tags); + formData.append("timestamp", timestamp); + formData.append("signature", signature); + + //Upload request to Cloudinary + const cloudinaryUploadResponse = await cleanAxios.post( + `${process.env.REACT_APP_CLOUDINARY_ENDPOINT}/upload`, + formData, + { + ...options, + } + ); + console.log("Upload Response", cloudinaryUploadResponse.data); + + if (cloudinaryUploadResponse.status !== 200) { + console.log( + "Error uploading to cloudinary.", + cloudinaryUploadResponse.statusText + ); + if (!!onError) onError(cloudinaryUploadResponse.statusText); + notification["error"]({ + message: i18n.t("documents.errors.insert", { + message: cloudinaryUploadResponse.statusText, + }), + }); + return; + } + + //Insert the document with the matching key. + const documentInsert = await client.mutate({ + mutation: INSERT_NEW_DOCUMENT, + variables: { + docInput: [ + { + jobid: jobId, + uploaded_by: uploaded_by, + key: fileName, + billid: billId, + type: fileType, + }, + ], + }, + }); + 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"]({ + 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(JSON.stringify(documentInsert.errors)), + }), + }); + return; + } + // if (onChange) { + // //Used in a form. + // onChange(UploadRef.current.state.fileList); + // } }; diff --git a/client/src/components/jobs-documents-gallery/jobs-documents-gallery.component.jsx b/client/src/components/jobs-documents-gallery/jobs-documents-gallery.component.jsx index e14ca8d42..edc7190bb 100644 --- a/client/src/components/jobs-documents-gallery/jobs-documents-gallery.component.jsx +++ b/client/src/components/jobs-documents-gallery/jobs-documents-gallery.component.jsx @@ -1,6 +1,7 @@ +import { Space } from "antd"; import React, { useEffect, useState } from "react"; import Gallery from "react-grid-gallery"; -import DocumentsUploadContainer from "../documents-upload/documents-upload.container"; +import DocumentsUploadComponent from "../documents-upload/documents-upload.component"; import JobsDocumentsDownloadButton from "./jobs-document-gallery.download.component"; import JobsDocumentsDeleteButton from "./jobs-documents-gallery.delete.component"; @@ -35,18 +36,19 @@ function JobsDocumentsComponent({ return (
- - - - + + + + +