IO-134 Prevent doc reassignment with limit
This commit is contained in:
@@ -10211,6 +10211,48 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>reassign_limitexceeded</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
<description></description>
|
||||
<comment></comment>
|
||||
<default_text></default_text>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>es-MX</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>fr-CA</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>reassign_limitexceeded_title</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
<description></description>
|
||||
<comment></comment>
|
||||
<default_text></default_text>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>es-MX</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>fr-CA</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>storageexceeded</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
@@ -28533,6 +28575,27 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>supplement_ratio_source</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
<description></description>
|
||||
<comment></comment>
|
||||
<default_text></default_text>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>es-MX</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>fr-CA</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>timetickets</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
|
||||
@@ -24,6 +24,7 @@ export function DocumentsUploadComponent({
|
||||
billId,
|
||||
callbackAfterUpload,
|
||||
totalSize,
|
||||
ignoreSizeLimit = false,
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
@@ -33,7 +34,7 @@ export function DocumentsUploadComponent({
|
||||
);
|
||||
}, [bodyshop, totalSize]);
|
||||
|
||||
if (pct > 100)
|
||||
if (pct > 100 && !ignoreSizeLimit)
|
||||
return (
|
||||
<Result
|
||||
status="error"
|
||||
@@ -46,6 +47,7 @@ export function DocumentsUploadComponent({
|
||||
<Upload.Dragger
|
||||
multiple={true}
|
||||
beforeUpload={(file, fileList) => {
|
||||
if (ignoreSizeLimit) return true;
|
||||
const newFiles = fileList.reduce((acc, val) => acc + val.size, 0);
|
||||
const shouldStopUpload =
|
||||
(totalSize + newFiles) / ((bodyshop && bodyshop.jobsizelimit) || 1) >=
|
||||
@@ -84,16 +86,18 @@ export function DocumentsUploadComponent({
|
||||
<p className="ant-upload-text">
|
||||
Click or drag files to this area to upload.
|
||||
</p>
|
||||
<Space wrap className="ant-upload-text">
|
||||
<Progress type="dashboard" percent={pct} size="small" />
|
||||
<span>
|
||||
{t("documents.labels.usage", {
|
||||
percent: pct,
|
||||
used: formatBytes(totalSize),
|
||||
total: formatBytes(bodyshop && bodyshop.jobsizelimit),
|
||||
})}
|
||||
</span>
|
||||
</Space>
|
||||
{!ignoreSizeLimit && (
|
||||
<Space wrap className="ant-upload-text">
|
||||
<Progress type="dashboard" percent={pct} size="small" />
|
||||
<span>
|
||||
{t("documents.labels.usage", {
|
||||
percent: pct,
|
||||
used: formatBytes(totalSize),
|
||||
total: formatBytes(bodyshop && bodyshop.jobsizelimit),
|
||||
})}
|
||||
</span>
|
||||
</Space>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</Upload.Dragger>
|
||||
|
||||
@@ -1,12 +1,29 @@
|
||||
import { Button, Form, Popover, notification, Space } from "antd";
|
||||
import React, { useState, useMemo } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import JobSearchSelect from "../job-search-select/job-search-select.component";
|
||||
import { useMutation } from "@apollo/client";
|
||||
import { UPDATE_DOCUMENT } from "../../graphql/documents.queries";
|
||||
import { useApolloClient, useMutation } 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 { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import JobSearchSelect from "../job-search-select/job-search-select.component";
|
||||
|
||||
export default function JobsDocumentsGalleryReassign({ galleryImages }) {
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
});
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
||||
});
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(JobsDocumentsGalleryReassign);
|
||||
|
||||
export function JobsDocumentsGalleryReassign({ bodyshop, galleryImages }) {
|
||||
const { t } = useTranslation();
|
||||
const [form] = Form.useForm();
|
||||
|
||||
@@ -16,7 +33,7 @@ export default function JobsDocumentsGalleryReassign({ galleryImages }) {
|
||||
...galleryImages.other.filter((image) => image.isSelected),
|
||||
];
|
||||
}, [galleryImages]);
|
||||
|
||||
const client = useApolloClient();
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [updateDocument] = useMutation(UPDATE_DOCUMENT);
|
||||
@@ -48,10 +65,37 @@ export default function JobsDocumentsGalleryReassign({ galleryImages }) {
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
console.log("selectedImages :>> ", selectedImages);
|
||||
const handleFinish = async ({ jobid }) => {
|
||||
setLoading(true);
|
||||
|
||||
//Check to see if the space remaining on the new job is sufficient. If it isn't cancel this.
|
||||
const newJobData = await client.query({
|
||||
query: GET_DOC_SIZE_BY_JOB,
|
||||
variables: { jobId: jobid },
|
||||
});
|
||||
|
||||
const transferedDocSizeTotal = selectedImages.reduce(
|
||||
(acc, val) => acc + val.size,
|
||||
0
|
||||
);
|
||||
|
||||
const shouldPreventTransfer =
|
||||
bodyshop.jobsizelimit -
|
||||
newJobData.data.documents_aggregate.aggregate.sum.size <
|
||||
transferedDocSizeTotal;
|
||||
|
||||
if (shouldPreventTransfer) {
|
||||
notification.open({
|
||||
key: "cannotuploaddocuments",
|
||||
type: "error",
|
||||
message: t("documents.labels.reassign_limitexceeded_title"),
|
||||
description: t("documents.labels.reassign_limitexceeded"),
|
||||
});
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const res = await axios.post("/media/rename", {
|
||||
documents: selectedImages.map((i) => {
|
||||
//Need to check if the current key folder is null, or another job.
|
||||
|
||||
@@ -18,6 +18,7 @@ function JobsDocumentsComponent({
|
||||
billsCallback,
|
||||
totalSize,
|
||||
bodyshop,
|
||||
ignoreSizeLimit,
|
||||
}) {
|
||||
const [galleryImages, setgalleryImages] = useState({ images: [], other: [] });
|
||||
const { t } = useTranslation();
|
||||
@@ -43,6 +44,7 @@ function JobsDocumentsComponent({
|
||||
extension: value.extension,
|
||||
id: value.id,
|
||||
type: value.type,
|
||||
size: value.size,
|
||||
tags: [{ value: value.type, title: value.type }],
|
||||
});
|
||||
} else {
|
||||
@@ -95,6 +97,7 @@ function JobsDocumentsComponent({
|
||||
key: value.key,
|
||||
id: value.id,
|
||||
type: value.type,
|
||||
size: value.size,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -131,6 +134,7 @@ function JobsDocumentsComponent({
|
||||
totalSize={totalSize}
|
||||
billId={billId}
|
||||
callbackAfterUpload={billsCallback || refetch}
|
||||
ignoreSizeLimit={ignoreSizeLimit}
|
||||
/>
|
||||
</Card>
|
||||
</Col>
|
||||
|
||||
@@ -167,6 +167,7 @@ export const QUERY_BILL_BY_PK = gql`
|
||||
key
|
||||
name
|
||||
type
|
||||
size
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ export const GET_DOCUMENTS_BY_JOB = gql`
|
||||
name
|
||||
key
|
||||
type
|
||||
size
|
||||
bill {
|
||||
id
|
||||
invoice_number
|
||||
@@ -27,6 +28,18 @@ export const GET_DOCUMENTS_BY_JOB = gql`
|
||||
}
|
||||
`;
|
||||
|
||||
export const GET_DOC_SIZE_BY_JOB = gql`
|
||||
query GET_DOC_SIZE_BY_JOB($jobId: uuid!) {
|
||||
documents_aggregate(where: { jobid: { _eq: $jobId } }) {
|
||||
aggregate {
|
||||
sum {
|
||||
size
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const INSERT_NEW_DOCUMENT = gql`
|
||||
mutation INSERT_NEW_DOCUMENT($docInput: [documents_insert_input!]!) {
|
||||
insert_documents(objects: $docInput) {
|
||||
@@ -34,6 +47,7 @@ export const INSERT_NEW_DOCUMENT = gql`
|
||||
id
|
||||
name
|
||||
key
|
||||
size
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -60,6 +74,7 @@ export const QUERY_TEMPORARY_DOCS = gql`
|
||||
key
|
||||
type
|
||||
extension
|
||||
size
|
||||
}
|
||||
}
|
||||
`;
|
||||
@@ -75,6 +90,7 @@ export const UPDATE_DOCUMENT = gql`
|
||||
name
|
||||
type
|
||||
key
|
||||
size
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -811,6 +811,7 @@ export const QUERY_TECH_JOB_DETAILS = gql`
|
||||
documents(order_by: { created_at: desc }) {
|
||||
id
|
||||
key
|
||||
size
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ export default function TemporaryDocsComponent() {
|
||||
jobId={null}
|
||||
billId={null}
|
||||
refetch={refetch}
|
||||
ignoreSizeLimit
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -658,11 +658,13 @@
|
||||
"confirmdelete": "Are you sure you want to delete these documents. This CANNOT be undone.",
|
||||
"doctype": "Document Type",
|
||||
"newjobid": "Assign to Job",
|
||||
"reassign_limitexceeded": "Reassigning all selected documents will exceed the job storage limit for your shop. ",
|
||||
"reassign_limitexceeded_title": "Unable to reassign document(s)",
|
||||
"storageexceeded": "You've exceeded your storage limit for this job. Please remove documents, or increase your storage plan.",
|
||||
"storageexceeded_title": "Storage Limit Exceeded",
|
||||
"upload": "Upload",
|
||||
"upload_limitexceeded": "Uploading all selected files will exceed the job storage limit for your shop. ",
|
||||
"upload_limitexceeded_title": "Unable to upload file(s)",
|
||||
"upload_limitexceeded": "Uploading all selected documents will exceed the job storage limit for your shop. ",
|
||||
"upload_limitexceeded_title": "Unable to upload document(s)",
|
||||
"usage": "of job storage used. ({{used}} / {{total}})"
|
||||
},
|
||||
"successes": {
|
||||
@@ -1719,6 +1721,7 @@
|
||||
"purchases_by_vendor_detailed_date_range": "Purchases By Vendor - Detailed",
|
||||
"purchases_by_vendor_summary_date_range": "Purchases by Vendor - Summary",
|
||||
"schedule": "Appointment Schedule",
|
||||
"supplement_ratio_source": "Supplement Ratio by Source",
|
||||
"timetickets": "Time Tickets",
|
||||
"timetickets_employee": "Employee Time Tickets",
|
||||
"timetickets_summary": "Time Tickets Summary"
|
||||
|
||||
@@ -658,6 +658,8 @@
|
||||
"confirmdelete": "",
|
||||
"doctype": "",
|
||||
"newjobid": "",
|
||||
"reassign_limitexceeded": "",
|
||||
"reassign_limitexceeded_title": "",
|
||||
"storageexceeded": "",
|
||||
"storageexceeded_title": "",
|
||||
"upload": "Subir",
|
||||
@@ -1719,6 +1721,7 @@
|
||||
"purchases_by_vendor_detailed_date_range": "",
|
||||
"purchases_by_vendor_summary_date_range": "",
|
||||
"schedule": "",
|
||||
"supplement_ratio_source": "",
|
||||
"timetickets": "",
|
||||
"timetickets_employee": "",
|
||||
"timetickets_summary": ""
|
||||
|
||||
@@ -658,6 +658,8 @@
|
||||
"confirmdelete": "",
|
||||
"doctype": "",
|
||||
"newjobid": "",
|
||||
"reassign_limitexceeded": "",
|
||||
"reassign_limitexceeded_title": "",
|
||||
"storageexceeded": "",
|
||||
"storageexceeded_title": "",
|
||||
"upload": "Télécharger",
|
||||
@@ -1719,6 +1721,7 @@
|
||||
"purchases_by_vendor_detailed_date_range": "",
|
||||
"purchases_by_vendor_summary_date_range": "",
|
||||
"schedule": "",
|
||||
"supplement_ratio_source": "",
|
||||
"timetickets": "",
|
||||
"timetickets_employee": "",
|
||||
"timetickets_summary": ""
|
||||
|
||||
@@ -511,6 +511,14 @@ export const TemplateList = (type, context) => {
|
||||
//idtype: "vendor",
|
||||
disabled: false,
|
||||
},
|
||||
supplement_ratio_source: {
|
||||
title: i18n.t("reportcenter.templates.supplement_ratio_source"),
|
||||
description: "",
|
||||
subject: i18n.t("reportcenter.templates.supplement_ratio_source"),
|
||||
key: "supplement_ratio_source",
|
||||
//idtype: "vendor",
|
||||
disabled: false,
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
...(!type || type === "courtesycarcontract"
|
||||
|
||||
Reference in New Issue
Block a user