diff --git a/bodyshop_translations.babel b/bodyshop_translations.babel
index 3fc2627a3..25c76f851 100644
--- a/bodyshop_translations.babel
+++ b/bodyshop_translations.babel
@@ -13447,6 +13447,27 @@
+
+ deleting
+ false
+
+
+
+
+
+ en-US
+ false
+
+
+ es-MX
+ false
+
+
+ fr-CA
+ false
+
+
+
deleting_cloudinary
false
diff --git a/client/src/components/jobs-documents-gallery/jobs-document-gallery.reassign.component.jsx b/client/src/components/jobs-documents-gallery/jobs-document-gallery.reassign.component.jsx
index f08dedadb..18be6fb62 100644
--- a/client/src/components/jobs-documents-gallery/jobs-document-gallery.reassign.component.jsx
+++ b/client/src/components/jobs-documents-gallery/jobs-document-gallery.reassign.component.jsx
@@ -1,14 +1,11 @@
-import { useApolloClient, useMutation } from "@apollo/client";
+import { useApolloClient } from "@apollo/client";
import { Button, Form, notification, Popover, Space } from "antd";
import axios from "axios";
import React, { useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
-import {
- GET_DOC_SIZE_BY_JOB,
- UPDATE_DOCUMENT,
-} from "../../graphql/documents.queries";
+import { GET_DOC_SIZE_BY_JOB } from "../../graphql/documents.queries";
import { selectBodyshop } from "../../redux/user/user.selectors";
import JobSearchSelect from "../job-search-select/job-search-select.component";
@@ -23,7 +20,11 @@ export default connect(
mapDispatchToProps
)(JobsDocumentsGalleryReassign);
-export function JobsDocumentsGalleryReassign({ bodyshop, galleryImages }) {
+export function JobsDocumentsGalleryReassign({
+ bodyshop,
+ galleryImages,
+ callback,
+}) {
const { t } = useTranslation();
const [form] = Form.useForm();
@@ -36,34 +37,33 @@ export function JobsDocumentsGalleryReassign({ bodyshop, galleryImages }) {
const client = useApolloClient();
const [visible, setVisible] = useState(false);
const [loading, setLoading] = useState(false);
- const [updateDocument] = useMutation(UPDATE_DOCUMENT);
- const updateImage = async (i, jobid) => {
- //Move the cloudinary image
+ // const updateImage = async (i, jobid) => {
+ // //Move the cloudinary image
- //Update it in the database.
- const result = await updateDocument({
- variables: {
- id: i.id,
- document: {
- key: i.public_id,
- jobid: jobid,
- },
- },
- });
+ // //Update it in the database.
+ // const result = await updateDocument({
+ // variables: {
+ // id: i.id,
+ // document: {
+ // key: i.public_id,
+ // jobid: jobid,
+ // },
+ // },
+ // });
- if (!!result.errors) {
- notification["error"]({
- message: t("documents.errors.updating", {
- message: JSON.stringify(result.errors),
- }),
- });
- } else {
- notification["success"]({
- message: t("documents.successes.updated"),
- });
- }
- };
+ // if (!!result.errors) {
+ // notification["error"]({
+ // message: t("documents.errors.updating", {
+ // message: JSON.stringify(result.errors),
+ // }),
+ // });
+ // } else {
+ // notification["success"]({
+ // message: t("documents.successes.updated"),
+ // });
+ // }
+ // };
const handleFinish = async ({ jobid }) => {
setLoading(true);
@@ -96,6 +96,7 @@ export function JobsDocumentsGalleryReassign({ bodyshop, galleryImages }) {
}
const res = await axios.post("/media/rename", {
+ tojobid: jobid,
documents: selectedImages.map((i) => {
//Need to check if the current key folder is null, or another job.
const currentKeys = i.key.split("/");
@@ -110,24 +111,21 @@ export function JobsDocumentsGalleryReassign({ bodyshop, galleryImages }) {
};
}),
});
+ //Add in confirmation & errors.
+ if (callback) callback();
- res.data
- .filter((d) => d.error)
- .forEach((d) => {
- notification["error"]({ message: t("documents.errors.updating") });
- console.error("Error updating job document", d);
+ if (res.errors) {
+ notification["error"]({
+ message: t("documents.errors.updating", {
+ message: JSON.stringify(res.errors),
+ }),
});
-
- const proms = [];
-
- res.data
- .filter((d) => !d.error)
- .forEach((d) => {
- proms.push(updateImage(d, jobid));
+ }
+ if (!res.mutationResult?.errors) {
+ notification["success"]({
+ message: t("documents.successes.updated"),
});
-
- await Promise.all(proms);
-
+ }
setVisible(false);
setLoading(false);
};
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 dbc603660..dbd04dddc 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
@@ -125,7 +125,10 @@ function JobsDocumentsComponent({
deletionCallback={billsCallback || refetch}
/>
{!billId && (
-
+
)}
diff --git a/client/src/components/jobs-documents-gallery/jobs-documents-gallery.delete.component.jsx b/client/src/components/jobs-documents-gallery/jobs-documents-gallery.delete.component.jsx
index 4928c572b..ce5669df2 100644
--- a/client/src/components/jobs-documents-gallery/jobs-documents-gallery.delete.component.jsx
+++ b/client/src/components/jobs-documents-gallery/jobs-documents-gallery.delete.component.jsx
@@ -1,11 +1,9 @@
import { QuestionCircleOutlined } from "@ant-design/icons";
-import { useMutation } from "@apollo/client";
import { Button, notification, Popconfirm } from "antd";
import axios from "axios";
import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import { logImEXEvent } from "../../firebase/firebase.utils";
-import { DELETE_DOCUMENTS } from "../../graphql/documents.queries";
//Context: currentUserEmail, bodyshop, jobid, invoiceid
export default function JobsDocumentsDeleteButton({
@@ -13,7 +11,7 @@ export default function JobsDocumentsDeleteButton({
deletionCallback,
}) {
const { t } = useTranslation();
- const [deleteDocument] = useMutation(DELETE_DOCUMENTS);
+
const imagesToDelete = [
...galleryImages.images.filter((image) => image.isSelected),
...galleryImages.other.filter((image) => image.isSelected),
@@ -27,31 +25,10 @@ export default function JobsDocumentsDeleteButton({
ids: imagesToDelete,
});
- const successfulDeletes = [];
- res.data.forEach((resType) => {
- Object.keys(resType.deleted).forEach((key) => {
- if (resType.deleted[key] !== "deleted") {
- notification["error"]({
- message: t("documents.errors.deleting_cloudinary", {
- message: JSON.stringify(resType.deleted[key]),
- }),
- });
- } else {
- successfulDeletes.push(key.replace(/\.[^/.]+$/, ""));
- }
- });
- });
- const delres = await deleteDocument({
- variables: {
- ids: imagesToDelete
- .filter((i) => successfulDeletes.includes(i.key))
- .map((i) => i.id),
- },
- });
- if (delres.errors) {
+ if (res.data.error) {
notification["error"]({
message: t("documents.errors.deleting", {
- message: JSON.stringify(delres.errors),
+ error: JSON.stringify(res.data.error.response.errors),
}),
});
} else {
diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json
index 2ce90edf6..299c554fa 100644
--- a/client/src/translations/en_us/common.json
+++ b/client/src/translations/en_us/common.json
@@ -835,6 +835,7 @@
},
"errors": {
"deletes3": "Error deleting document from storage. ",
+ "deleting": "Error deleting documents {{error}}",
"deleting_cloudinary": "Error deleting document from storage. {{message}}",
"getpresignurl": "Error obtaining presigned URL for document. {{message}}",
"insert": "Unable to upload file. {{message}}",
diff --git a/client/src/translations/es/common.json b/client/src/translations/es/common.json
index eab3ad308..bd8f3bcb2 100644
--- a/client/src/translations/es/common.json
+++ b/client/src/translations/es/common.json
@@ -835,6 +835,7 @@
},
"errors": {
"deletes3": "Error al eliminar el documento del almacenamiento.",
+ "deleting": "",
"deleting_cloudinary": "",
"getpresignurl": "Error al obtener la URL prescrita para el documento. {{message}}",
"insert": "Incapaz de cargar el archivo. {{message}}",
diff --git a/client/src/translations/fr/common.json b/client/src/translations/fr/common.json
index d40a31e33..a79c49a92 100644
--- a/client/src/translations/fr/common.json
+++ b/client/src/translations/fr/common.json
@@ -835,6 +835,7 @@
},
"errors": {
"deletes3": "Erreur lors de la suppression du document du stockage.",
+ "deleting": "",
"deleting_cloudinary": "",
"getpresignurl": "Erreur lors de l'obtention de l'URL présignée pour le document. {{message}}",
"insert": "Incapable de télécharger le fichier. {{message}}",
diff --git a/server/graphql-client/queries.js b/server/graphql-client/queries.js
index 7a01b8a85..db92f3c0e 100644
--- a/server/graphql-client/queries.js
+++ b/server/graphql-client/queries.js
@@ -1611,3 +1611,13 @@ exports.INSERT_EMAIL_AUDIT = `mutation INSERT_EMAIL_AUDIT($email: email_audit_tr
}
}
`;
+
+exports.DELETE_MEDIA_DOCUMENTS = `
+mutation DELETE_DOCUMENTS($ids: [uuid!]!) {
+ delete_documents(where: { id: { _in: $ids } }) {
+ returning {
+ id
+ }
+ }
+}
+`;
diff --git a/server/media/media.js b/server/media/media.js
index dbd2887ed..7f199cb75 100644
--- a/server/media/media.js
+++ b/server/media/media.js
@@ -1,6 +1,8 @@
const path = require("path");
const _ = require("lodash");
const logger = require("../utils/logger");
+const client = require("../graphql-client/graphql-client").client;
+const queries = require("../graphql-client/queries");
require("dotenv").config({
path: path.resolve(
@@ -69,11 +71,38 @@ exports.deleteFiles = async (req, res) => {
);
}
- res.send(returns);
+ // Delete it on apollo.
+ const successfulDeletes = [];
+ returns.forEach((resType) => {
+ Object.keys(resType.deleted).forEach((key) => {
+ if (
+ resType.deleted[key] === "deleted" ||
+ resType.deleted[key] === "not_found"
+ ) {
+ successfulDeletes.push(key.replace(/\.[^/.]+$/, ""));
+ }
+ });
+ });
+
+ try {
+ const result = await client.request(queries.DELETE_MEDIA_DOCUMENTS, {
+ ids: ids
+ .filter((i) => successfulDeletes.includes(i.key))
+ .map((i) => i.id),
+ });
+
+ res.send({ returns, result });
+ } catch (error) {
+ logger.log("media-delete-error", "ERROR", req.user.email, null, [
+ { ids, error: error.message || JSON.stringify(error) },
+ ]);
+
+ res.json({ error });
+ }
};
exports.renameKeys = async (req, res) => {
- const { documents } = req.body;
+ const { documents, tojobid } = req.body;
logger.log("media-bulk-rename", "DEBUG", req.user.email, null, documents);
const proms = [];
@@ -98,8 +127,37 @@ exports.renameKeys = async (req, res) => {
let result;
result = await Promise.all(proms);
+ const errors = [];
+ result
+ .filter((d) => d.error)
+ .forEach((d) => {
+ errors.push(d);
+ });
- res.send(result);
+ let mutations = "";
+
+ result
+ .filter((d) => !d.error)
+ .forEach((d, idx) => {
+ //Create mutation text
+
+ mutations =
+ mutations +
+ `
+ update_doc${idx}:update_documents_by_pk(pk_columns: { id: "${d.id}" }, _set: {key: "${d.public_id}", jobid: "${tojobid}"}){
+ id
+ }
+ `;
+ });
+
+ if (mutations !== "") {
+ const mutationResult = await client.request(`mutation {
+ ${mutations}
+ }`);
+ res.json({ errors, mutationResult });
+ } else {
+ res.json({ errors: "No images were succesfully moved on remote server. " });
+ }
};
//Also needs to be updated in upload utility and mobile app.