From 066b9004095a2a5fbf5c4120972ae9e6f8a16c18 Mon Sep 17 00:00:00 2001 From: Patrick Fic Date: Fri, 24 Jan 2020 12:52:13 -0800 Subject: [PATCH] Added document delete + refined document upload --- bodyshop_translations.babel | 42 ++++++++++ .../jobs-documents.component.jsx | 78 +++++++++++++++---- client/src/graphql/documents.queries.js | 15 ++++ client/src/translations/en_us/common.json | 2 + client/src/translations/es/common.json | 2 + client/src/translations/fr/common.json | 2 + s3upload.js | 22 ++++++ server.js | 7 +- 8 files changed, 152 insertions(+), 18 deletions(-) diff --git a/bodyshop_translations.babel b/bodyshop_translations.babel index 8c606e919..8b29804b6 100644 --- a/bodyshop_translations.babel +++ b/bodyshop_translations.babel @@ -24,6 +24,27 @@ errors + + deletes3 + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + getpresignurl false @@ -118,6 +139,27 @@ successes + + delete + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + insert false diff --git a/client/src/components/jobs-documents/jobs-documents.component.jsx b/client/src/components/jobs-documents/jobs-documents.component.jsx index d3a092682..1bbd68d12 100644 --- a/client/src/components/jobs-documents/jobs-documents.component.jsx +++ b/client/src/components/jobs-documents/jobs-documents.component.jsx @@ -4,7 +4,10 @@ import React, { useState } from "react"; import { useMutation } from "react-apollo"; import { useTranslation } from "react-i18next"; import Resizer from "react-image-file-resizer"; -import { INSERT_NEW_DOCUMENT } from "../../graphql/documents.queries"; +import { + INSERT_NEW_DOCUMENT, + DELETE_DOCUMENT +} from "../../graphql/documents.queries"; import "./jobs-documents.styles.scss"; import { generateCdnThumb } from "../../utils/DocHelpers"; @@ -20,6 +23,7 @@ function getBase64(file) { function JobsDocumentsComponent({ shopId, jobId, loading, data, currentUser }) { const { t } = useTranslation(); const [insertNewDocument] = useMutation(INSERT_NEW_DOCUMENT); + const [deleteDocument] = useMutation(DELETE_DOCUMENT); const [state, setState] = useState({ previewVisible: false, @@ -32,7 +36,9 @@ function JobsDocumentsComponent({ shopId, jobId, loading, data, currentUser }) { uid: value.id, url: value.thumb_url, name: value.name, - status: "done" + status: "done", + full_url: value.url, + key: value.key }); return acc; }, []) @@ -69,7 +75,7 @@ function JobsDocumentsComponent({ shopId, jobId, loading, data, currentUser }) { axios .put(signedRequest, file, options) .then(response => { - onSuccess(response.body); + console.log("response from axios", response); insertNewDocument({ variables: { docInput: [ @@ -83,7 +89,14 @@ function JobsDocumentsComponent({ shopId, jobId, loading, data, currentUser }) { ] } }).then(r => { - console.log(r); + onSuccess({ + uid: r.data.insert_documents.returning[0].id, + url: r.data.insert_documents.returning[0].thumb_url, + name: r.data.insert_documents.returning[0].name, + status: "done", + full_url: r.data.insert_documents.returning[0].url, + key: r.data.insert_documents.returning[0].key + }); notification["success"]({ message: t("documents.successes.insert") }); @@ -135,23 +148,62 @@ function JobsDocumentsComponent({ shopId, jobId, loading, data, currentUser }) { const handleCancel = () => setState({ ...state, previewVisible: false }); const handlePreview = async file => { - if (!file.url && !file.preview) { + if (!file.full_url && !file.url) { file.preview = await getBase64(file.originFileObj); } setState({ ...state, - previewImage: file.url || file.preview, + previewImage: file.full_url || file.url, previewVisible: true }); }; const handleChange = props => { - const { fileList } = props; - setFileList(fileList); + const { event, fileList, file } = props; + //Required to ensure that the state accurately reflects new data and that images can be deleted in feeded. + if (!event) { + //SPread the new file in where the old one was. + const newFileList = fileList.map(i => + i.uid === file.uid ? Object.assign({}, i, file.response) : i + ); + setFileList(newFileList); + } else { + setFileList(fileList); + } }; const { previewVisible, previewImage } = state; + const handleRemove = file => { + console.log("file", file); + + //Remove the file on S3 + axios + .post("/delete_s3", { fileName: file.key }) + .then(response => { + //Delete the record in our database. + if (response.status === 200) { + deleteDocument({ variables: { id: file.uid } }).then(r => { + notification["success"]({ + message: t("documents.successes.delete") + }); + }); + } else { + notification["error"]({ + message: + 1 + + t("documents.errors.deletes3") + + JSON.stringify(response.message) + }); + } + }) + .catch(error => { + notification["error"]({ + message: "2" + t("documents.errors.deletes3") + JSON.stringify(error) + }); + }); + }; + return (

diff --git a/client/src/graphql/documents.queries.js b/client/src/graphql/documents.queries.js index 5a2cc937d..58c22a411 100644 --- a/client/src/graphql/documents.queries.js +++ b/client/src/graphql/documents.queries.js @@ -7,6 +7,7 @@ export const GET_DOCUMENTS_BY_JOB = gql` url thumb_url name + key } } `; @@ -14,6 +15,20 @@ export const GET_DOCUMENTS_BY_JOB = gql` export const INSERT_NEW_DOCUMENT = gql` mutation INSERT_NEW_DOCUMENT($docInput: [documents_insert_input!]!) { insert_documents(objects: $docInput) { + returning { + id + url + thumb_url + name + key + } + } + } +`; + +export const DELETE_DOCUMENT = gql` + mutation DELETE_DOCUMENT($id: uuid) { + delete_documents(where: { id: { _eq: $id } }) { returning { id } diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json index 7a6db6841..a657b41eb 100644 --- a/client/src/translations/en_us/common.json +++ b/client/src/translations/en_us/common.json @@ -2,6 +2,7 @@ "translation": { "documents": { "errors": { + "deletes3": "Error deleting document from storage. ", "getpresignurl": "Error obtaining presigned URL for document. ", "insert": "Unable to upload file.", "nodocuments": "There are no documents." @@ -10,6 +11,7 @@ "upload": "Upload" }, "successes": { + "delete": "Document deleted successfully.", "insert": "Uploaded document successfully. " } }, diff --git a/client/src/translations/es/common.json b/client/src/translations/es/common.json index fda17bd90..c102ca788 100644 --- a/client/src/translations/es/common.json +++ b/client/src/translations/es/common.json @@ -2,6 +2,7 @@ "translation": { "documents": { "errors": { + "deletes3": "Error al eliminar el documento del almacenamiento.", "getpresignurl": "Error al obtener la URL prescrita para el documento.", "insert": "Incapaz de cargar el archivo.", "nodocuments": "No hay documentos" @@ -10,6 +11,7 @@ "upload": "Subir" }, "successes": { + "delete": "Documento eliminado con éxito.", "insert": "Documento cargado con éxito." } }, diff --git a/client/src/translations/fr/common.json b/client/src/translations/fr/common.json index 53926ea54..bca75b8ae 100644 --- a/client/src/translations/fr/common.json +++ b/client/src/translations/fr/common.json @@ -2,6 +2,7 @@ "translation": { "documents": { "errors": { + "deletes3": "Erreur lors de la suppression du document du stockage.", "getpresignurl": "Erreur lors de l'obtention de l'URL présignée pour le document.", "insert": "Incapable de télécharger le fichier.", "nodocuments": "Il n'y a pas de documents." @@ -10,6 +11,7 @@ "upload": "Télécharger" }, "successes": { + "delete": "Le document a bien été supprimé.", "insert": "Document téléchargé avec succès." } }, diff --git a/s3upload.js b/s3upload.js index c5e5ad221..1091873b2 100644 --- a/s3upload.js +++ b/s3upload.js @@ -71,3 +71,25 @@ exports.get_s3 = (req, res) => { res.json({ success: true, data: { returnData } }); }); }; + +exports.delete_s3 = (req, res) => { + const s3 = new aws.S3(); // Create a new instance of S3 + const fileName = req.body.fileName; + //const fileType = req.body.fileType; + // Set up the payload of what we are sending to the S3 api + console.log("fileName", req.body); + const s3Params = { + Bucket: S3_BUCKET, + Key: fileName + }; + + s3.deleteObject(s3Params, function(err, data) { + if (err) { + res.json({ success: false, message: err.message }); + } + // error + else { + res.json({ success: true, data }); + } // deleted + }); +}; diff --git a/server.js b/server.js index 2648a0659..7acc0a49d 100644 --- a/server.js +++ b/server.js @@ -21,10 +21,11 @@ app.use(cors()); var s3upload = require("./s3upload"); app.post("/sign_s3", s3upload.sign_s3); app.get("/sign_s3", s3upload.get_s3); +app.post("/delete_s3", s3upload.delete_s3); -app.get("/test", function(req, res) { - res.json({ success: true }); -}); +// app.get("/test", function(req, res) { +// res.json({ success: true }); +// }); if (process.env.NODE_ENV === "production") { app.use(express.static(path.join(__dirname, "client/build")));