- |
+
+ {
+ form.setFieldsValue({
+ billlines: form
+ .getFieldsValue()
+ .billlines.map((b) => ({
+ ...b,
+ selected: e.target.checked,
+ })),
+ });
+ }}
+ />
+ |
{t("billlines.fields.line_desc")} |
{t("billlines.fields.quantity")} |
{t("billlines.fields.actual_price")} |
diff --git a/client/src/components/bills-list-table/bills-list-table.component.jsx b/client/src/components/bills-list-table/bills-list-table.component.jsx
index 8257c0b39..9dea48f71 100644
--- a/client/src/components/bills-list-table/bills-list-table.component.jsx
+++ b/client/src/components/bills-list-table/bills-list-table.component.jsx
@@ -67,39 +67,7 @@ export function BillsListTableComponent({
jobRO
}
/>
-
+
{record.isinhouse && (
record.oem_partno,
+ render: (text, record) =>
+ `${record.oem_partno || ""} ${
+ record.alt_partno ? `(${record.alt_partno})` : ""
+ }`.trim(),
},
{
title: t("joblines.fields.op_code_desc"),
@@ -461,7 +464,12 @@ export function JobLinesComponent({
context: {
jobId: job.id,
job: job,
- linesToOrder: selectedLines,
+ linesToOrder: selectedLines.map((l) => ({
+ ...l,
+ oem_partno: `${l.oem_partno || ""} ${
+ l.alt_partno ? `(${l.alt_partno})` : ""
+ }`.trim(),
+ })),
},
});
@@ -477,7 +485,18 @@ export function JobLinesComponent({
setState({
...state,
filteredInfo: {
- part_type: ["PAN","PAC","PAR","PAL","PAA","PAM","PAP","PAS","PASL","PAG"],
+ part_type: [
+ "PAN",
+ "PAC",
+ "PAR",
+ "PAL",
+ "PAA",
+ "PAM",
+ "PAP",
+ "PAS",
+ "PASL",
+ "PAG",
+ ],
},
});
}}
diff --git a/client/src/components/jobs-documents-local-gallery/jobs-documents-local-gallery.container.jsx b/client/src/components/jobs-documents-local-gallery/jobs-documents-local-gallery.container.jsx
index 92ba94f17..f58c8025c 100644
--- a/client/src/components/jobs-documents-local-gallery/jobs-documents-local-gallery.container.jsx
+++ b/client/src/components/jobs-documents-local-gallery/jobs-documents-local-gallery.container.jsx
@@ -14,6 +14,7 @@ import { selectAllMedia } from "../../redux/media/media.selectors";
import { selectBodyshop } from "../../redux/user/user.selectors";
import { CreateExplorerLinkForJob } from "../../utils/localmedia";
import DocumentsLocalUploadComponent from "../documents-local-upload/documents-local-upload.component";
+import JobsLocalGalleryDownloadButton from "./jobs-documents-local-gallery.download";
import JobsDocumentsLocalGalleryReassign from "./jobs-documents-local-gallery.reassign.component";
import JobsDocumentsLocalGallerySelectAllComponent from "./jobs-documents-local-gallery.selectall.component";
@@ -78,6 +79,7 @@ export function JobsDocumentsLocalGallery({
+
({
+ //setUserLanguage: language => dispatch(setUserLanguage(language))
+});
+export default connect(
+ mapStateToProps,
+ mapDispatchToProps
+)(JobsLocalGalleryDownloadButton);
+
+export function JobsLocalGalleryDownloadButton({
+ bodyshop,
+ galleryImages,
+ allMedia,
+ job,
+}) {
+ const { t } = useTranslation();
+ const [download, setDownload] = useState(null);
+
+ function downloadProgress(progressEvent) {
+ setDownload((currentDownloadState) => {
+ return {
+ downloaded: progressEvent.loaded || 0,
+ speed:
+ (progressEvent.loaded || 0) -
+ ((currentDownloadState && currentDownloadState.downloaded) || 0),
+ };
+ });
+ }
+
+ const handleDownload = async () => {
+ const theDownloadedZip = await cleanAxios.post(
+ `${bodyshop.localmediaserverhttp}/jobs/download`,
+ {
+ jobid: job.id,
+ files: ((allMedia && allMedia[job.id]) || [])
+ .filter((i) => i.isSelected)
+ .map((i) => i.filename),
+ },
+ {
+ headers: { ims_token: bodyshop.localmediatoken },
+ responseType: "arraybuffer",
+ onDownloadProgress: downloadProgress,
+ }
+ );
+ setDownload(null);
+ standardMediaDownload(theDownloadedZip.data, job.ro_number);
+ };
+
+ return (
+
+ );
+}
+
+function standardMediaDownload(bufferData, filename) {
+ const a = document.createElement("a");
+ const url = window.URL.createObjectURL(new Blob([bufferData]));
+ a.href = url;
+ a.download = `${filename}.zip`;
+ a.click();
+}
diff --git a/client/src/components/jobs-list/jobs-list.component.jsx b/client/src/components/jobs-list/jobs-list.component.jsx
index 3c2553462..82620dd63 100644
--- a/client/src/components/jobs-list/jobs-list.component.jsx
+++ b/client/src/components/jobs-list/jobs-list.component.jsx
@@ -264,6 +264,32 @@ export function JobsList({ bodyshop }) {
{record.clm_total}
),
},
+ {
+ title: t("jobs.labels.estimator"),
+ dataIndex: "jobs.labels.estimator",
+ key: "jobs.labels.estimator",
+ ellipsis: true,
+ responsive: ["xl"],
+ filterSearch: true,
+ filters:
+ (jobs &&
+ jobs
+ .map((j) => `${j.est_ct_fn || ""} ${j.est_ct_ln || ""}`.trim())
+ .filter(onlyUnique)
+ .map((s) => {
+ return {
+ text: s || "N/A",
+ value: [s],
+ };
+ })) ||
+ [],
+ onFilter: (value, record) =>
+ value.includes(
+ `${record.est_ct_fn || ""} ${record.est_ct_ln || ""}`.trim()
+ ),
+ render: (text, record) =>
+ `${record.est_ct_fn || ""} ${record.est_ct_ln || ""}`.trim(),
+ },
{
title: t("jobs.fields.comment"),
dataIndex: "comment",
diff --git a/client/src/components/jobs-notes/jobs.notes.component.jsx b/client/src/components/jobs-notes/jobs.notes.component.jsx
index 8f60e879d..4aaf95caf 100644
--- a/client/src/components/jobs-notes/jobs.notes.component.jsx
+++ b/client/src/components/jobs-notes/jobs.notes.component.jsx
@@ -14,6 +14,7 @@ import { selectJobReadOnly } from "../../redux/application/application.selectors
import { setModalContext } from "../../redux/modals/modals.actions";
import { DateTimeFormatter } from "../../utils/DateFormatter";
import { TemplateList } from "../../utils/TemplateConstants";
+import useLocalStorage from "../../utils/useLocalStorage";
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
import NoteUpsertModal from "../note-upsert-modal/note-upsert-modal.container";
import PrintWrapperComponent from "../print-wrapper/print-wrapper.component";
@@ -40,6 +41,8 @@ export function JobNotesComponent({
relatedRos,
}) {
const { t } = useTranslation();
+ const [filter, setFilter] = useLocalStorage("filter_job_notes_icons", null);
+
const Templates = TemplateList("job_special", {
ro_number,
});
@@ -50,6 +53,18 @@ export function JobNotesComponent({
dataIndex: "icons",
key: "icons",
width: 80,
+ filteredValue: filter?.icons || null,
+ filters: [
+ {
+ text: t("notes.labels.usernotes"),
+ value: false,
+ },
+ {
+ text: t("notes.labels.systemnotes"),
+ value: true,
+ },
+ ],
+ onFilter: (value, record) => record.audit === value,
render: (text, record) => (
{record.critical ? (
@@ -131,6 +146,10 @@ export function JobNotesComponent({
},
];
+ const handleTableChange = (pagination, filters, sorter) => {
+ setFilter(filters);
+ };
+
return (
@@ -166,6 +185,7 @@ export function JobNotesComponent({
columns={columns}
rowKey="id"
dataSource={data}
+ onChange={handleTableChange}
/>
diff --git a/client/src/components/jobs-ready-list/jobs-ready-list.component.jsx b/client/src/components/jobs-ready-list/jobs-ready-list.component.jsx
index e1a598562..47fd2fc15 100644
--- a/client/src/components/jobs-ready-list/jobs-ready-list.component.jsx
+++ b/client/src/components/jobs-ready-list/jobs-ready-list.component.jsx
@@ -276,6 +276,32 @@ export function JobsReadyList({ bodyshop }) {
{record.clm_total}
),
},
+ {
+ title: t("jobs.labels.estimator"),
+ dataIndex: "jobs.labels.estimator",
+ key: "jobs.labels.estimator",
+ ellipsis: true,
+ responsive: ["xl"],
+ filterSearch: true,
+ filters:
+ (jobs &&
+ jobs
+ .map((j) => `${j.est_ct_fn || ""} ${j.est_ct_ln || ""}`.trim())
+ .filter(onlyUnique)
+ .map((s) => {
+ return {
+ text: s || "N/A",
+ value: [s],
+ };
+ })) ||
+ [],
+ onFilter: (value, record) =>
+ value.includes(
+ `${record.est_ct_fn || ""} ${record.est_ct_ln || ""}`.trim()
+ ),
+ render: (text, record) =>
+ `${record.est_ct_fn || ""} ${record.est_ct_ln || ""}`.trim(),
+ },
{
title: t("jobs.fields.comment"),
dataIndex: "comment",
diff --git a/client/src/graphql/jobs.queries.js b/client/src/graphql/jobs.queries.js
index 71534b18d..f902c19a0 100644
--- a/client/src/graphql/jobs.queries.js
+++ b/client/src/graphql/jobs.queries.js
@@ -40,6 +40,8 @@ export const QUERY_ALL_ACTIVE_JOBS = gql`
updated_at
ded_amt
suspended
+ est_ct_fn
+ est_ct_ln
}
}
`;
@@ -685,6 +687,7 @@ export const GET_JOB_BY_PK = gql`
line_ref
part_type
oem_partno
+ alt_partno
db_price
act_price
part_qty
diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json
index e639faaff..b4748b540 100644
--- a/client/src/translations/en_us/common.json
+++ b/client/src/translations/en_us/common.json
@@ -1616,6 +1616,7 @@
"duplicateconfirm": "Are you sure you want to duplicate this job? Some elements of this job will not be duplicated.",
"employeeassignments": "Employee Assignments",
"estimatelines": "Estimate Lines",
+ "estimator": "Estimator",
"existing_jobs": "Existing Jobs",
"federal_tax_amt": "Federal Taxes",
"gpdollars": "$ G.P.",
@@ -1919,7 +1920,9 @@
"labels": {
"addtorelatedro": "Add to Related ROs",
"newnoteplaceholder": "Add a note...",
- "notetoadd": "Note to Add"
+ "notetoadd": "Note to Add",
+ "systemnotes": "System Notes",
+ "usernotes": "User Notes"
},
"successes": {
"create": "Note created successfully.",
diff --git a/client/src/translations/es/common.json b/client/src/translations/es/common.json
index d0de45bf3..63d161450 100644
--- a/client/src/translations/es/common.json
+++ b/client/src/translations/es/common.json
@@ -1616,6 +1616,7 @@
"duplicateconfirm": "",
"employeeassignments": "",
"estimatelines": "",
+ "estimator": "",
"existing_jobs": "Empleos existentes",
"federal_tax_amt": "",
"gpdollars": "",
@@ -1919,7 +1920,9 @@
"labels": {
"addtorelatedro": "",
"newnoteplaceholder": "Agrega una nota...",
- "notetoadd": ""
+ "notetoadd": "",
+ "systemnotes": "",
+ "usernotes": ""
},
"successes": {
"create": "Nota creada con éxito.",
diff --git a/client/src/translations/fr/common.json b/client/src/translations/fr/common.json
index b1dfc0c2d..eeef96c19 100644
--- a/client/src/translations/fr/common.json
+++ b/client/src/translations/fr/common.json
@@ -1616,6 +1616,7 @@
"duplicateconfirm": "",
"employeeassignments": "",
"estimatelines": "",
+ "estimator": "",
"existing_jobs": "Emplois existants",
"federal_tax_amt": "",
"gpdollars": "",
@@ -1919,7 +1920,9 @@
"labels": {
"addtorelatedro": "",
"newnoteplaceholder": "Ajouter une note...",
- "notetoadd": ""
+ "notetoadd": "",
+ "systemnotes": "",
+ "usernotes": ""
},
"successes": {
"create": "Remarque créée avec succès.",