diff --git a/client/src/components/chat-presets/chat-presets.component.jsx b/client/src/components/chat-presets/chat-presets.component.jsx index 3b3bcf400..730f2a0dc 100644 --- a/client/src/components/chat-presets/chat-presets.component.jsx +++ b/client/src/components/chat-presets/chat-presets.component.jsx @@ -1,5 +1,5 @@ import { PlusCircleOutlined } from "@ant-design/icons"; -import { Dropdown, Menu } from "antd"; +import { Dropdown } from "antd"; import React from "react"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; @@ -16,19 +16,16 @@ const mapDispatchToProps = (dispatch) => ({ }); export function ChatPresetsComponent({ bodyshop, setMessage, className }) { - const menuItems = bodyshop.md_messaging_presets.map((i, idx) => ({ + + const items = bodyshop.md_messaging_presets.map((i, idx) => ({ key: idx, - label: i.label, + label: (i.label), onClick: () => setMessage(i.text), })); - const menu = ( - - ); - return (
- +
diff --git a/client/src/components/contracts-rates-change-button/contracts-rates-change-button.component.jsx b/client/src/components/contracts-rates-change-button/contracts-rates-change-button.component.jsx index 2039150a8..d5e01049a 100644 --- a/client/src/components/contracts-rates-change-button/contracts-rates-change-button.component.jsx +++ b/client/src/components/contracts-rates-change-button/contracts-rates-change-button.component.jsx @@ -24,11 +24,8 @@ export function ContractsRatesChangeButton({ disabled, form, bodyshop }) { value: i, })); - const menu = ( -
- -
- ); + const menu = {items: menuItems, onClick: handleClick} + return ( diff --git a/client/src/components/courtesy-cars-list/courtesy-cars-list.component.jsx b/client/src/components/courtesy-cars-list/courtesy-cars-list.component.jsx index cbe62c22f..f03422631 100644 --- a/client/src/components/courtesy-cars-list/courtesy-cars-list.component.jsx +++ b/client/src/components/courtesy-cars-list/courtesy-cars-list.component.jsx @@ -179,7 +179,7 @@ export default function CourtesyCarsList({ loading, courtesycars, refetch }) { ) : courtesycars; - const menuItems = [ + const items = [ { key: "courtesycar_inventory", label: t("printcenter.courtesycarcontract.courtesy_car_inventory"), @@ -205,11 +205,7 @@ export default function CourtesyCarsList({ loading, courtesycars, refetch }) { - - } + diff --git a/client/src/components/dashboard-grid/dashboard-grid.component.jsx b/client/src/components/dashboard-grid/dashboard-grid.component.jsx index 442369eaf..1f57f9b38 100644 --- a/client/src/components/dashboard-grid/dashboard-grid.component.jsx +++ b/client/src/components/dashboard-grid/dashboard-grid.component.jsx @@ -131,9 +131,7 @@ export function DashboardGridComponent({ currentUser, bodyshop }) { disabled: existingLayoutKeys.includes(key), })); - const addComponentOverlay = ( - - ); + const menu = {items: menuItems, onClick: handleAddComponent}; if (error) return ; @@ -145,7 +143,7 @@ export function DashboardGridComponent({ currentUser, bodyshop }) { - + diff --git a/client/src/components/dms-post-form/dms-post-form.component.jsx b/client/src/components/dms-post-form/dms-post-form.component.jsx index cc5a7a089..0fbd4b9a5 100644 --- a/client/src/components/dms-post-form/dms-post-form.component.jsx +++ b/client/src/components/dms-post-form/dms-post-form.component.jsx @@ -291,25 +291,23 @@ export function DmsPostForm({bodyshop, socket, job, logsRef}) { label={
{t("jobs.fields.dms.payer.controlnumber")}{" "} - ({ - key: idx, - label: key.name, - onClick: () => { - form.setFieldsValue({ - payers: form.getFieldValue("payers").map((row, mapIndex) => { - if (index !== mapIndex) return row; - return { - ...row, - controlnumber: key.controlnumber, - }; - }), - }); - }, - }))} - />} - > + ({ + key: idx, + label: key.name, + onClick: () => { + form.setFieldsValue({ + payers: form.getFieldValue("payers").map((row, mapIndex) => { + if (index !== mapIndex) return row; + return { + ...row, + controlnumber: key.controlnumber, + }; + }), + }); + }, + })) + }}> e.preventDefault()}> diff --git a/client/src/components/email-overlay/email-overlay.component.jsx b/client/src/components/email-overlay/email-overlay.component.jsx index 38495df4f..ebb222b17 100644 --- a/client/src/components/email-overlay/email-overlay.component.jsx +++ b/client/src/components/email-overlay/email-overlay.component.jsx @@ -1,5 +1,5 @@ import {UploadOutlined, UserAddOutlined} from "@ant-design/icons"; -import {Button, Divider, Dropdown, Form, Input, Menu, Select, Space, Tabs, Upload,} from "antd"; +import {Button, Divider, Dropdown, Form, Input, Select, Space, Tabs, Upload,} from "antd"; import _ from "lodash"; import React from "react"; import {useTranslation} from "react-i18next"; @@ -50,47 +50,40 @@ export function EmailOverlayComponent({ }); }; - const menu = ( - e.user_email) - .map((e, idx) => ({ - key: idx, - label: `${e.first_name} ${e.last_name}`, - value: e.user_email, - })), - ...bodyshop.md_to_emails.map((e, idx) => ({ - key: idx + "group", - label: e.label, - value: e.emails, - })), - ]} - /> - ); - - const menuCC = ( -
- e.user_email) - .map((e, idx) => ({ - key: idx, - label: `${e.first_name} ${e.last_name}`, - value: e.user_email, - })), - ...bodyshop.md_to_emails.map((e, idx) => ({ - key: idx + "group", - label: e.label, - value: e.emails, - })), - ]} - /> -
- ); + const emailsToMenu = { + items: [ + ...bodyshop.employees + .filter((e) => e.user_email) + .map((e, idx) => ({ + key: idx, + label: `${e.first_name} ${e.last_name}`, + value: e.user_email, + })), + ...bodyshop.md_to_emails.map((e, idx) => ({ + key: idx + "group", + label: e.label, + value: e.emails, + })), + ], + onClick: handleClick, + }; + const menuCC = { + items: [ + ...bodyshop.employees + .filter((e) => e.user_email) + .map((e, idx) => ({ + key: idx, + label: `${e.first_name} ${e.last_name}`, + value: e.user_email, + })), + ...bodyshop.md_to_emails.map((e, idx) => ({ + key: idx + "group", + label: e.label, + value: e.emails, + })), + ], + onClick: handle_CC_Click, + }; return (
@@ -119,7 +112,7 @@ export function EmailOverlayComponent({ label={ {t("emails.fields.to")} - + ({ + + const menu = { + items: [ + ...(bodyshop.appt_alt_transport || []).map((alt) => ({ key: alt, label: alt, - })), - { key: "null", label: t("general.actions.clear") }, - ]} - /> - ); + })), + { key: "null", label: t("general.actions.clear") }, + ], + onClick: onClick, + defaultSelectedKeys: [job && job.alt_transport] + } + return ( e.preventDefault()}> diff --git a/client/src/components/job-at-change/schedule-event.color.component.jsx b/client/src/components/job-at-change/schedule-event.color.component.jsx index b11c615de..d997834e3 100644 --- a/client/src/components/job-at-change/schedule-event.color.component.jsx +++ b/client/src/components/job-at-change/schedule-event.color.component.jsx @@ -4,7 +4,7 @@ import { UPDATE_APPOINTMENT } from "../../graphql/appointments.queries"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; -import { Dropdown, Menu, notification } from "antd"; +import { Dropdown, notification } from "antd"; import { DownOutlined } from "@ant-design/icons"; import { selectBodyshop } from "../../redux/user/user.selectors"; @@ -44,21 +44,20 @@ export function ScheduleEventColor({ bodyshop, event }) { bodyshop.appt_colors.filter((color) => color.color.hex === event.color)[0] ?.label; - const menu = ( - ({ - key: color.color.hex, - label: color.label, - style: { color: color.color.hex }, - })), - { key: "divider", label:
, disabled: true }, - { key: "null", label: t("general.actions.clear") }, - ]} - /> - ); + + const menu = { + defaultSelectedKeys: [event.color], + onClick: onClick, + items: [ + ...(bodyshop.appt_colors || []).map((color) => ({ + key: color.color.hex, + label: color.label, + style: { color: color.color.hex }, + })), + { key: "divider", label:
, disabled: true }, + { key: "null", label: t("general.actions.clear") }, + ] + }; return ( @@ -69,4 +68,5 @@ export function ScheduleEventColor({ bodyshop, event }) { ); } + export default connect(mapStateToProps, mapDispatchToProps)(ScheduleEventColor); diff --git a/client/src/components/job-at-change/schedule-event.component.jsx b/client/src/components/job-at-change/schedule-event.component.jsx index 9cc3fceda..a7ad65ca5 100644 --- a/client/src/components/job-at-change/schedule-event.component.jsx +++ b/client/src/components/job-at-change/schedule-event.component.jsx @@ -5,7 +5,6 @@ import { Dropdown, Form, Input, - Menu, notification, Popover, Select, @@ -185,58 +184,54 @@ export function ScheduleEventComponent({ ) : null} {event.job ? ( { - const Template = TemplateList("job").appointment_reminder; - GenerateDocument( - { - name: Template.key, - variables: { id: event.job.id }, - }, - { - to: event.job && event.job.ownr_ea, - subject: Template.subject, - }, - "e", - event.job && event.job.id + menu={{items: [ + { + key: "email", + label: t("general.labels.email"), + disabled: event.arrived, + onClick: () => { + const Template = TemplateList("job").appointment_reminder; + GenerateDocument( + { + name: Template.key, + variables: { id: event.job.id }, + }, + { + to: event.job && event.job.ownr_ea, + subject: Template.subject, + }, + "e", + event.job && event.job.id + ); + }, + }, + { + key: "sms", + label: t("general.labels.sms"), + disabled: event.arrived || !bodyshop.messagingservicesid, + onClick: () => { + const p = parsePhoneNumber(event.job.ownr_ph1, "CA"); + if (p && p.isValid()) { + openChatByPhone({ + phone_num: p.formatInternational(), + jobid: event.job.id, + }); + setMessage( + t("appointments.labels.reminder", { + shopname: bodyshop.shopname, + date: dayjs(event.start).format("MM/DD/YYYY"), + time: dayjs(event.start).format("HH:mm a"), + }) ); - }, + setVisible(false); + } else { + notification["error"]({ + message: t("messaging.error.invalidphone"), + }); + } }, - { - key: "sms", - label: t("general.labels.sms"), - disabled: event.arrived || !bodyshop.messagingservicesid, - onClick: () => { - const p = parsePhoneNumber(event.job.ownr_ph1, "CA"); - if (p && p.isValid()) { - openChatByPhone({ - phone_num: p.formatInternational(), - jobid: event.job.id, - }); - setMessage( - t("appointments.labels.reminder", { - shopname: bodyshop.shopname, - date: dayjs(event.start).format("MM/DD/YYYY"), - time: dayjs(event.start).format("HH:mm a"), - }) - ); - setVisible(false); - } else { - notification["error"]({ - message: t("messaging.error.invalidphone"), - }); - } - }, - }, - ]} - /> - } + }, + ]}} > diff --git a/client/src/components/job-detail-lines/job-lines.component.jsx b/client/src/components/job-detail-lines/job-lines.component.jsx index c34402cd6..0aaf1d953 100644 --- a/client/src/components/job-detail-lines/job-lines.component.jsx +++ b/client/src/components/job-detail-lines/job-lines.component.jsx @@ -13,7 +13,6 @@ import { Button, Dropdown, Input, - Menu, Space, Table, Tag, @@ -410,19 +409,17 @@ export function JobLinesComponent({ } }; - const markMenu = ( -
, disabled: true }, - { key: "clear", label: t("general.labels.clear") }, - ]} - /> - ); + const markMenu = { + onClick: handleMark, + items: [ + { key: "PAA", label: t("joblines.fields.part_types.PAA") }, + { key: "PAN", label: t("joblines.fields.part_types.PAN") }, + { key: "PAL", label: t("joblines.fields.part_types.PAL") }, + { key: "PAS", label: t("joblines.fields.part_types.PAS") }, + { key: "divider", label:
, disabled: true }, + { key: "clear", label: t("general.labels.clear") }, + ] + } return (
diff --git a/client/src/components/job-lines-preset-button/job-lines-preset-button.component.jsx b/client/src/components/job-lines-preset-button/job-lines-preset-button.component.jsx index b1af48abc..29c3e924e 100644 --- a/client/src/components/job-lines-preset-button/job-lines-preset-button.component.jsx +++ b/client/src/components/job-lines-preset-button/job-lines-preset-button.component.jsx @@ -1,5 +1,5 @@ import { DownOutlined } from "@ant-design/icons"; -import { Dropdown, Menu } from "antd"; +import { Dropdown } from "antd"; import React from "react"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; @@ -21,22 +21,21 @@ export function JoblinePresetButton({ bodyshop, form }) { form.setFieldsValue(item); }; - const menu = ( - ({ - key: idx, - label: i.label, - style: { breakInside: "avoid" }, - onClick: () => handleSelect(i), - }))} - /> - ); + + const menu = { + items: bodyshop.md_jobline_presets.map((i, idx) => ({ + key: idx, + label: i.label, + style: { breakInside: "avoid" }, + onClick: () => handleSelect(i), + })), + style: { + columnCount: Math.max( + Math.floor(bodyshop.md_jobline_presets.length / 15), + 1 + ), + }, + } return (
diff --git a/client/src/components/jobs-admin-change-status/jobs-admin-change.status.component.jsx b/client/src/components/jobs-admin-change-status/jobs-admin-change.status.component.jsx index e4b99a216..df522d3e6 100644 --- a/client/src/components/jobs-admin-change-status/jobs-admin-change.status.component.jsx +++ b/client/src/components/jobs-admin-change-status/jobs-admin-change.status.component.jsx @@ -40,20 +40,18 @@ export function JobsAdminStatus({ insertAuditTrail, bodyshop, job }) { }); }; - const statusmenu = ( - { - updateJobStatus(e.key); - }} - items={bodyshop.md_ro_statuses.statuses.map((item) => ({ - key: item, - label: item, - }))} - /> - ); + const statusMenu = { + items: bodyshop.md_ro_statuses.statuses.map((item) => ({ + key: item, + label: item, + })), + onClick: (e) => { + updateJobStatus(e.key); + }, + } return ( - + ) : ( diff --git a/client/src/components/jobs-detail-change-estimator/jobs-detail-change-estimator.component.jsx b/client/src/components/jobs-detail-change-estimator/jobs-detail-change-estimator.component.jsx index 2f4d3c52f..2c55549b7 100644 --- a/client/src/components/jobs-detail-change-estimator/jobs-detail-change-estimator.component.jsx +++ b/client/src/components/jobs-detail-change-estimator/jobs-detail-change-estimator.component.jsx @@ -1,5 +1,5 @@ import { DownOutlined } from "@ant-design/icons"; -import { Dropdown, Menu } from "antd"; +import { Dropdown } from "antd"; import React from "react"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; @@ -15,16 +15,14 @@ export function JobsDetailChangeEstimator({ disabled, form, bodyshop }) { form.setFieldsValue(est); }; - const menu = ( - ({ + const menu = { + items: bodyshop.md_estimators.map((est, idx) => ({ key: idx, label: `${est.est_ct_fn} ${est.est_ct_ln}`, value: est, - }))} - /> - ); + })), + onClick: handleClick + } return ( diff --git a/client/src/components/jobs-detail-change-filehandler/jobs-detail-change-filehandler.component.jsx b/client/src/components/jobs-detail-change-filehandler/jobs-detail-change-filehandler.component.jsx index 58ac230ad..51cefa0c8 100644 --- a/client/src/components/jobs-detail-change-filehandler/jobs-detail-change-filehandler.component.jsx +++ b/client/src/components/jobs-detail-change-filehandler/jobs-detail-change-filehandler.component.jsx @@ -15,20 +15,18 @@ export function JobsDetailChangeFilehandler({ disabled, form, bodyshop }) { form.setFieldsValue(est); }; - const menu = ( - ({ - key: idx, - label: `${est.ins_ct_fn} ${est.ins_ct_ln}`, - value: est, - style: { breakInside: "avoid" }, - }))} - /> - ); + const menu = { + items: bodyshop.md_filehandlers.map((est, idx) => ({ + key: idx, + label: `${est.ins_ct_fn} ${est.ins_ct_ln}`, + value: est, + style: { breakInside: "avoid" }, + })), + style: { + columnCount: Math.floor(bodyshop.md_filehandlers.length / 10) + 1, + }, + onClick: handleClick + } return ( diff --git a/client/src/components/jobs-detail-rates-change-button/jobs-detail-rates-change-button.component.jsx b/client/src/components/jobs-detail-rates-change-button/jobs-detail-rates-change-button.component.jsx index e2aeab96a..c6c546db2 100644 --- a/client/src/components/jobs-detail-rates-change-button/jobs-detail-rates-change-button.component.jsx +++ b/client/src/components/jobs-detail-rates-change-button/jobs-detail-rates-change-button.component.jsx @@ -1,5 +1,5 @@ import { DownOutlined } from "@ant-design/icons"; -import { Dropdown, Menu } from "antd"; +import { Dropdown } from "antd"; import React from "react"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; @@ -18,16 +18,14 @@ export function JobsDetailRatesChangeButton({ disabled, form, bodyshop }) { form.setFieldsValue({ ...rate, labor_rate_desc: rate.rate_label }); }; - const menu = ( - ({ - key: idx, - label: rate.rate_label, - value: rate, - }))} - /> - ); + const menu = { + items: bodyshop.md_labor_rates.map((rate, idx) => ({ + key: idx, + label: rate.rate_label, + value: rate, + })), + onClick: handleClick + } return ( diff --git a/client/src/components/notes-preset-button/notes-preset-button.component.jsx b/client/src/components/notes-preset-button/notes-preset-button.component.jsx index 331eb03fb..15c57fffb 100644 --- a/client/src/components/notes-preset-button/notes-preset-button.component.jsx +++ b/client/src/components/notes-preset-button/notes-preset-button.component.jsx @@ -1,53 +1,52 @@ -import { DownOutlined } from "@ant-design/icons"; -import { Dropdown, Menu } from "antd"; +import {DownOutlined} from "@ant-design/icons"; +import {Dropdown} from "antd"; import React from "react"; -import { useTranslation } from "react-i18next"; -import { connect } from "react-redux"; -import { createStructuredSelector } from "reselect"; -import { selectBodyshop } from "../../redux/user/user.selectors"; +import {useTranslation} from "react-i18next"; +import {connect} from "react-redux"; +import {createStructuredSelector} from "reselect"; +import {selectBodyshop} from "../../redux/user/user.selectors"; const mapStateToProps = createStructuredSelector({ - //currentUser: selectCurrentUser - bodyshop: selectBodyshop, + //currentUser: selectCurrentUser + bodyshop: selectBodyshop, }); const mapDispatchToProps = (dispatch) => ({ - //setUserLanguage: language => dispatch(setUserLanguage(language)) + //setUserLanguage: language => dispatch(setUserLanguage(language)) }); -export function NotesPresetButton({ bodyshop, form }) { - const { t } = useTranslation(); +export function NotesPresetButton({bodyshop, form}) { + const {t} = useTranslation(); - const handleSelect = (item) => { - form.setFieldsValue({ text: item.text }); - }; + const handleSelect = (item) => { + form.setFieldsValue({text: item.text}); + }; - const menu = ( - ({ - key: idx, - label: i.label, - style: { breakInside: "avoid" }, - onClick: () => handleSelect(i), - }))} - /> - ); - return ( - - ); + const menu = { + items: bodyshop.md_notes_presets.map((i, idx) => ({ + key: idx, + label: i.label, + style: {breakInside: "avoid"}, + onClick: () => handleSelect(i), + })), + style: { + columnCount: Math.floor(bodyshop.md_notes_presets.length / 10) + 1, + }, + } + + return ( + + ); } export default connect(mapStateToProps, mapDispatchToProps)(NotesPresetButton); diff --git a/client/src/components/parts-order-modal/parts-order-modal-price-change.component.jsx b/client/src/components/parts-order-modal/parts-order-modal-price-change.component.jsx index d500fc859..4c7c17e0d 100644 --- a/client/src/components/parts-order-modal/parts-order-modal-price-change.component.jsx +++ b/client/src/components/parts-order-modal/parts-order-modal-price-change.component.jsx @@ -1,97 +1,95 @@ -import { DownOutlined } from "@ant-design/icons"; -import { Dropdown, InputNumber, Menu, Space } from "antd"; +import {DownOutlined} from "@ant-design/icons"; +import {Dropdown, InputNumber, Space} from "antd"; import React from "react"; -import { useTranslation } from "react-i18next"; -export default function PartsOrderModalPriceChange({ form, field }) { - const { t } = useTranslation(); - const menu = ( - { - if (key === "custom") return; - const values = form.getFieldsValue(); +import {useTranslation} from "react-i18next"; - const { parts_order_lines } = values; +export default function PartsOrderModalPriceChange({form, field}) { + const {t} = useTranslation(); + const menu = { + items: [ + { + key: "5", + label: t("parts_orders.labels.discount", {percent: "5%"}), + }, + { + key: "10", + label: t("parts_orders.labels.discount", {percent: "10%"}), + }, + { + key: "15", + label: t("parts_orders.labels.discount", {percent: "15%"}), + }, + { + key: "20", + label: t("parts_orders.labels.discount", {percent: "20%"}), + }, + { + key: "25", + label: t("parts_orders.labels.discount", {percent: "25%"}), + }, + { + key: "custom", + label: ( + e.stopPropagation()} + addonAfter="%" + onKeyUp={(e) => { + if (e.key === "Enter") { + const values = form.getFieldsValue(); + const {parts_order_lines} = values; - form.setFieldsValue({ - parts_order_lines: { - data: parts_order_lines.data.map((p, idx) => { - if (idx !== field.name) return p; - return { - ...p, - act_price: (p.act_price || 0) * ((100 - key) / 100), - }; - }), - }, - }); - }} - items={[ - { - key: "5", - label: t("parts_orders.labels.discount", { percent: "5%" }), - }, - { - key: "10", - label: t("parts_orders.labels.discount", { percent: "10%" }), - }, - { - key: "15", - label: t("parts_orders.labels.discount", { percent: "15%" }), - }, - { - key: "20", - label: t("parts_orders.labels.discount", { percent: "20%" }), - }, - { - key: "25", - label: t("parts_orders.labels.discount", { percent: "25%" }), - }, - { - key: "custom", - label: ( - e.stopPropagation()} - addonAfter="%" - onKeyUp={(e) => { - if (e.key === "Enter") { - const values = form.getFieldsValue(); - const { parts_order_lines } = values; - - form.setFieldsValue({ - parts_order_lines: { - data: parts_order_lines.data.map((p, idx) => { + form.setFieldsValue({ + parts_order_lines: { + data: parts_order_lines.data.map((p, idx) => { + if (idx !== field.name) return p; + console.log( + p, + e.target.value, + (p.act_price || 0) * + ((100 - (e.target.value || 0)) / 100) + ); + return { + ...p, + act_price: + (p.act_price || 0) * + ((100 - (e.target.value || 0)) / 100), + }; + }), + }, + }); + e.target.value = 0; + } + }} + min={0} + max={100} + /> + ), + }, + ], + onClick: ({key}) => { + if (key === "custom") return; + const values = form.getFieldsValue(); + const {parts_order_lines} = values; + form.setFieldsValue({ + parts_order_lines: { + data: parts_order_lines.data.map((p, idx) => { if (idx !== field.name) return p; - console.log( - p, - e.target.value, - (p.act_price || 0) * - ((100 - (e.target.value || 0)) / 100) - ); return { - ...p, - act_price: - (p.act_price || 0) * - ((100 - (e.target.value || 0)) / 100), + ...p, + act_price: (p.act_price || 0) * ((100 - key) / 100), }; - }), - }, - }); - e.target.value = 0; - } - }} - min={0} - max={100} - /> - ), - }, - ]} - /> - ); - return ( - - - % - - - - ); + }), + }, + }); + } + }; + + return ( + + + % + + + + ); } diff --git a/client/src/components/parts-order-modal/parts-order-modal.component.jsx b/client/src/components/parts-order-modal/parts-order-modal.component.jsx index 663ccffa1..28d718471 100644 --- a/client/src/components/parts-order-modal/parts-order-modal.component.jsx +++ b/client/src/components/parts-order-modal/parts-order-modal.component.jsx @@ -39,16 +39,14 @@ export function PartsOrderModalComponent({bodyshop, vendorList, sendTypeState, i form.setFieldsValue({comments: item.props.value}); }; - const menu = ( - ({ - key: idx, - label: comment.label, - value: comment.comment, - }))} - /> - ); + const menu = { + items: bodyshop.md_parts_order_comment.map((comment, idx) => ({ + key: idx, + label: comment.label, + value: comment.comment, + })), + onClick: handleClick + }; return (
diff --git a/client/src/components/production-list-columns/production-list-columns.add.component.jsx b/client/src/components/production-list-columns/production-list-columns.add.component.jsx index bc71cfd41..b80979c75 100644 --- a/client/src/components/production-list-columns/production-list-columns.add.component.jsx +++ b/client/src/components/production-list-columns/production-list-columns.add.component.jsx @@ -47,21 +47,21 @@ export function ProductionColumnsComponent({ state: tableState, activeStatuses: bodyshop.md_ro_statuses.active_statuses, }); - const menu = ( - !columnKeys.includes(i.key)) - .map((item) => ({ - key: item.key, - label: item.title, - style: { breakInside: "avoid" }, - }))} - /> - ); + + const menu = { + items: cols + .filter((i) => !columnKeys.includes(i.key)) + .map((item) => ({ + key: item.key, + label: item.title, + style: { breakInside: "avoid" }, + })), + style: { + columnCount: Math.max(Math.floor(cols.length / 10), 1), + }, + onClick: handleAdd, + }; + return (
diff --git a/client/src/components/production-list-columns/production-list-columns.alert.component.jsx b/client/src/components/production-list-columns/production-list-columns.alert.component.jsx index 1ed2d33dd..f14452340 100644 --- a/client/src/components/production-list-columns/production-list-columns.alert.component.jsx +++ b/client/src/components/production-list-columns/production-list-columns.alert.component.jsx @@ -1,6 +1,6 @@ import { ExclamationCircleFilled } from "@ant-design/icons"; import { useMutation } from "@apollo/client"; -import { Dropdown, Menu } from "antd"; +import { Dropdown } from "antd"; import React from "react"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; @@ -51,23 +51,21 @@ export function ProductionListColumnAlert({ record, insertAuditTrail }) { }); }; + const menu = { + items: [ + { + key: "toggleAlert", + label: record.production_vars && record.production_vars.alert + ? t("production.labels.alertoff") + : t("production.labels.alerton"), + onClick: handleAlertToggle, + }, + ] + }; + return ( - } - trigger={["contextMenu"]} - > + menu={menu} trigger={["contextMenu"]}>
({ + key: index + 1, + label: ( +
+ {index + 1} +
+ ), + })), + }, + ], + onClick: handleSetBodyPriority + }; + return ( - ({ - key: index + 1, - label: ( -
- {index + 1} -
- ), - })), - }, - ]} - /> - } - trigger={["click"]} - > +
{record.production_vars && record.production_vars.bodypriority}
diff --git a/client/src/components/production-list-columns/production-list-columns.detailpriority.component.jsx b/client/src/components/production-list-columns/production-list-columns.detailpriority.component.jsx index fa389d0ea..c4afd29a4 100644 --- a/client/src/components/production-list-columns/production-list-columns.detailpriority.component.jsx +++ b/client/src/components/production-list-columns/production-list-columns.detailpriority.component.jsx @@ -29,33 +29,31 @@ export default function ProductionListColumnDetailPriority({ record }) { }); }; + const menu = { + items: [ + { + key: "clearDetailPriority", + label: t("production.actions.detailpriority-clear"), + }, + { + key: "set", + label: t("production.actions.detailpriority-set"), + children: new Array(15).fill().map((value, index) => ({ + key: index + 1, + label: ( +
+ {index + 1} +
+ ), + })), + }, + ], + onClick: handleSetDetailPriority + } + return ( ({ - key: index + 1, - label: ( -
- {index + 1} -
- ), - })), - }, - ]} - /> - } - trigger={["click"]} - > + menu={menu} trigger={["click"]}>
{record.production_vars && record.production_vars.detailpriority}
diff --git a/client/src/components/production-list-columns/production-list-columns.paintpriority.component.jsx b/client/src/components/production-list-columns/production-list-columns.paintpriority.component.jsx index 8ba00bc18..2b0289379 100644 --- a/client/src/components/production-list-columns/production-list-columns.paintpriority.component.jsx +++ b/client/src/components/production-list-columns/production-list-columns.paintpriority.component.jsx @@ -1,5 +1,5 @@ import { useMutation } from "@apollo/client"; -import { Dropdown, Menu } from "antd"; +import { Dropdown } from "antd"; import React from "react"; import { useTranslation } from "react-i18next"; import { UPDATE_JOB } from "../../graphql/jobs.queries"; @@ -29,33 +29,30 @@ export default function ProductionListColumnPaintPriority({ record }) { }); }; + const menu = { + items: [ + { + key: "clearPaintPriority", + label: t("production.actions.paintpriority-clear"), + }, + { + key: "set", + label: t("production.actions.paintpriority-set"), + children: new Array(15).fill().map((value, index) => ({ + key: index + 1, + label: ( +
+ {index + 1} +
+ ), + })), + }, + ], + onClick: handleSetPaintPriority + }; + return ( - ({ - key: index + 1, - label: ( -
- {index + 1} -
- ), - })), - }, - ]} - /> - } - trigger={["click"]} - > +
{record.production_vars && record.production_vars.paintpriority}
diff --git a/client/src/components/production-list-columns/production-list-columns.status.category.jsx b/client/src/components/production-list-columns/production-list-columns.status.category.jsx index b0448c43a..1477d2b1e 100644 --- a/client/src/components/production-list-columns/production-list-columns.status.category.jsx +++ b/client/src/components/production-list-columns/production-list-columns.status.category.jsx @@ -1,5 +1,5 @@ import { useMutation } from "@apollo/client"; -import { Dropdown, Menu, Spin } from "antd"; +import { Dropdown, Spin } from "antd"; import React, { useState } from "react"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; @@ -36,20 +36,20 @@ export function ProductionListColumnCategory({ record, bodyshop }) { setLoading(false); }; + const menu = { + items: bodyshop.md_categories.map((item) => ({ + key: item, + label: item, + })), + onClick: handleSetStatus, + style: { + maxHeight: "200px", + overflowY: "auto", + } + }; + return ( - ({ - key: item, - label: item, - }))} - /> - } - trigger={["click"]} - > +
{record.category} {loading && } diff --git a/client/src/components/production-list-columns/production-list-columns.status.component.jsx b/client/src/components/production-list-columns/production-list-columns.status.component.jsx index d9df58f37..d84e61a58 100644 --- a/client/src/components/production-list-columns/production-list-columns.status.component.jsx +++ b/client/src/components/production-list-columns/production-list-columns.status.component.jsx @@ -1,5 +1,5 @@ import { useMutation } from "@apollo/client"; -import { Dropdown, Menu, Spin } from "antd"; +import { Dropdown, Spin } from "antd"; import React, { useState } from "react"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; @@ -45,20 +45,20 @@ export function ProductionListColumnStatus({ setLoading(false); }; + const menu = { + items: bodyshop.md_ro_statuses.production_statuses.map((item) => ({ + key: item, + label: item, + })), + onClick: handleSetStatus, + style: { + maxHeight: "200px", + overflowY: "auto", + } + }; + return ( - ({ - key: item, - label: item, - }))} - /> - } - trigger={["click"]} - > +
{record.status} {loading && } diff --git a/client/src/components/production-list-table/production-list-print.component.jsx b/client/src/components/production-list-table/production-list-print.component.jsx index 81e8a4051..b198fcf2a 100644 --- a/client/src/components/production-list-table/production-list-print.component.jsx +++ b/client/src/components/production-list-table/production-list-print.component.jsx @@ -1,4 +1,4 @@ -import { Button, Dropdown, Menu } from "antd"; +import { Button, Dropdown } from "antd"; import React, { useState } from "react"; import { TemplateList } from "../../utils/TemplateConstants"; import { useTranslation } from "react-i18next"; @@ -28,58 +28,55 @@ export default connect( export function ProductionListPrint({ bodyshop }) { const { t } = useTranslation(); const [loading, setLoading] = useState(false); - return ( - { - setLoading(true); - await GenerateDocument( - { - name: ProdTemplates[e.key].key, - // variables: { id: contract.id }, - }, - {}, - "p" - ); - setLoading(false); - }} - items={[ - ...Object.keys(ProdTemplates).map((key) => ({ - key: key, - label: ProdTemplates[key].title, - })), - { - key: "production_by_technician_one", - label: t("reportcenter.templates.production_by_technician_one"), - children: bodyshop.employees - .filter((e) => e.active) - .map((e) => ({ + const menu = { + items: [ + ...Object.keys(ProdTemplates).map((key) => ({ + key: key, + label: ProdTemplates[key].title, + })), + { + key: "production_by_technician_one", + label: t("reportcenter.templates.production_by_technician_one"), + children: bodyshop.employees + .filter((e) => e.active) + .map((e) => ({ key: e.id, label: `${e.first_name} ${e.last_name}`, - })), - }, - { - key: "production_by_category_one", - label: t("reportcenter.templates.production_by_category_one"), - children: bodyshop.md_categories.map((e) => ({ + })), + }, + { + key: "production_by_category_one", + label: t("reportcenter.templates.production_by_category_one"), + children: bodyshop.md_categories.map((e) => ({ key: e, label: e, - })), - }, - { - key: "production_by_repair_status_one", - label: t("reportcenter.templates.production_by_repair_status_one"), - children: bodyshop.md_ro_statuses.production_statuses.map((e) => ({ + })), + }, + { + key: "production_by_repair_status_one", + label: t("reportcenter.templates.production_by_repair_status_one"), + children: bodyshop.md_ro_statuses.production_statuses.map((e) => ({ key: e, label: e, - })), + })), + }, + ], + onClick: async (e) => { + setLoading(true); + await GenerateDocument( + { + name: ProdTemplates[e.key].key, + // variables: { id: contract.id }, }, - ]} - /> - } - > + {}, + "p" + ); + setLoading(false); + }, + + } + return ( + ); diff --git a/client/src/components/production-list-table/production-list-table.component.jsx b/client/src/components/production-list-table/production-list-table.component.jsx index 30bc4028a..b817a379d 100644 --- a/client/src/components/production-list-table/production-list-table.component.jsx +++ b/client/src/components/production-list-table/production-list-table.component.jsx @@ -1,6 +1,6 @@ import {SyncOutlined} from "@ant-design/icons"; import {useSplitTreatments} from "@splitsoftware/splitio-react"; -import {Button, Dropdown, Input, Menu, Space, Statistic, Table,} from "antd"; +import {Button, Dropdown, Input, Space, Statistic, Table,} from "antd"; import {PageHeader} from "@ant-design/pro-layout"; import React, {useMemo, useState} from "react"; import ReactDragListView from "react-drag-listview"; @@ -28,10 +28,10 @@ export function ProductionListTable({loading, data, refetch, bodyshop, technicia const [searchText, setSearchText] = useState(""); - const { treatments: {Production_List_Status_Colors} } = useSplitTreatments({ + const {treatments: {Production_List_Status_Colors}} = useSplitTreatments({ attributes: {}, names: ["Production_List_Status_Colors"], - splitKey: bodyshop.imexshopid, + splitKey: bodyshop.imexshopid, }); @@ -105,25 +105,28 @@ export function ProductionListTable({loading, data, refetch, bodyshop, technicia setColumns(nextColumns); }; - const headerItem = (col) => ( - - } - trigger={["contextMenu"]} - > - {col.title} - - ); + + const headerItem = (col) => { + const menu = { + onClick: removeColumn, + items: [ + { + key: col.key, + label: t("production.actions.removecolumn"), + }, + ] + } + + return ( + + {col.title} + + ) + }; const dataSource = searchText === "" diff --git a/client/src/components/schedule-block-day/schedule-block-day.component.jsx b/client/src/components/schedule-block-day/schedule-block-day.component.jsx index 8eab30a51..ad80b2b77 100644 --- a/client/src/components/schedule-block-day/schedule-block-day.component.jsx +++ b/client/src/components/schedule-block-day/schedule-block-day.component.jsx @@ -1,5 +1,5 @@ import { useMutation } from "@apollo/client"; -import { Dropdown, Menu, notification } from "antd"; +import { Dropdown, notification } from "antd"; import dayjs from "../../utils/day"; import React from "react"; import { useTranslation } from "react-i18next"; @@ -55,17 +55,15 @@ export function ScheduleBlockDay({ } }; - const menu = ( - - ); + const menu = { + items: [ + { + key: "block", + label: t("appointments.actions.block"), + }, + ], + onClick: handleMenu, + } return ( template.name); - const availableTemplateKeys = Object.keys(TemplateList()).filter( - (tkey) => !shopTemplateKeys.includes(tkey) - ); + const shopTemplateKeys = shopTemplateList.map((template) => template.name); + const availableTemplateKeys = Object.keys(TemplateList()).filter( + (tkey) => !shopTemplateKeys.includes(tkey) + ); - const handleAdd = async (item) => { - logImEXEvent("shop_template_add"); + const handleAdd = async (item) => { + logImEXEvent("shop_template_add"); - const defaultTemplateData = await client.query({ - query: QUERY_TEMPLATES_BY_NAME_FOR_DUPE, - variables: { name: item.key }, - }); + const defaultTemplateData = await client.query({ + query: QUERY_TEMPLATES_BY_NAME_FOR_DUPE, + variables: {name: item.key}, + }); - const template = defaultTemplateData.data.templates.filter( - (t) => t.bodyshopid === null - )[0]; + const template = defaultTemplateData.data.templates.filter( + (t) => t.bodyshopid === null + )[0]; - const result = await insertTemplate({ - variables: { - template: { - name: item.key, - bodyshopid: bodyshop.id, - jsontemplate: template && template.jsontemplate, - html: template && template.html, - query: template && template.query, - }, - }, - }); + const result = await insertTemplate({ + variables: { + template: { + name: item.key, + bodyshopid: bodyshop.id, + jsontemplate: template && template.jsontemplate, + html: template && template.html, + query: template && template.query, + }, + }, + }); - const returningId = result.data.insert_templates.returning[0].id; - search.customTemplateId = returningId; - history({ search: queryString.stringify(search) }); - if (!!refetch) refetch(); - }; - const TemplateListGenerated = TemplateList(); - const menu = ( - 0 - ? availableTemplateKeys.map((tkey) => ({ - key: tkey, - label: TemplateListGenerated[tkey].title, + const returningId = result.data.insert_templates.returning[0].id; + search.customTemplateId = returningId; + history({search: queryString.stringify(search)}); + if (!!refetch) refetch(); + }; + const TemplateListGenerated = TemplateList(); + const menu = { + onClick: handleAdd, + + items: availableTemplateKeys.length > 0 + ? availableTemplateKeys.map((tkey) => ({ + key: tkey, + label: TemplateListGenerated[tkey].title, })) - : [ - { - key: "no-templates", - label: t("bodyshop.labels.notemplatesavailable"), - disabled: true, - }, + : [ + { + key: "no-templates", + label: t("bodyshop.labels.notemplatesavailable"), + disabled: true, + }, ] - } - /> - ); + }; - return ( - + return ( + - {t("bodyshop.actions.addtemplate")} + {t("bodyshop.actions.addtemplate")} - - ); + + ); } diff --git a/client/src/pages/contract-detail/contract-detail.page.component.jsx b/client/src/pages/contract-detail/contract-detail.page.component.jsx index 8fb392549..e1bdd0b6c 100644 --- a/client/src/pages/contract-detail/contract-detail.page.component.jsx +++ b/client/src/pages/contract-detail/contract-detail.page.component.jsx @@ -1,136 +1,118 @@ -import { - Button, - Col, - Dropdown, - Form, - Menu, - Row, - Space, - Typography, -} from "antd"; +import {Button, Col, Dropdown, Form, Row, Space, Typography,} from "antd"; import {PageHeader} from "@ant-design/pro-layout"; import React from "react"; -import { useTranslation } from "react-i18next"; -import { connect } from "react-redux"; +import {useTranslation} from "react-i18next"; +import {connect} from "react-redux"; import ContractConvertToRo from "../../components/contract-convert-to-ro/contract-convert-to-ro.component"; -import ContractCourtesyCarBlock from "../../components/contract-courtesy-car-block/contract-courtesy-car-block.component"; +import ContractCourtesyCarBlock + from "../../components/contract-courtesy-car-block/contract-courtesy-car-block.component"; import ContractFormComponent from "../../components/contract-form/contract-form.component"; import ContractJobBlock from "../../components/contract-job-block/contract-job-block.component"; -import { setModalContext } from "../../redux/modals/modals.actions"; -import { GenerateDocument } from "../../utils/RenderTemplate"; -import { TemplateList } from "../../utils/TemplateConstants"; +import {setModalContext} from "../../redux/modals/modals.actions"; +import {GenerateDocument} from "../../utils/RenderTemplate"; +import {TemplateList} from "../../utils/TemplateConstants"; const mapDispatchToProps = (dispatch) => ({ - setCourtesyCarReturnModalContext: (context) => - dispatch(setModalContext({ context: context, modal: "courtesyCarReturn" })), + setCourtesyCarReturnModalContext: (context) => + dispatch(setModalContext({context: context, modal: "courtesyCarReturn"})), }); -export function ContractDetailPage({ - contract, - job, - courtesyCar, - setCourtesyCarReturnModalContext, - refetch, - form, - saveLoading, -}) { - const { t } = useTranslation(); - return ( -
- - - - - {() => { - return ( - - - - { - GenerateDocument( - { - name: TemplateList("courtesycarcontract")[e.key].key, - variables: { id: contract.id }, - }, - {}, - "p" - ); - }} - items={[ - { - key: "courtesy_car_contract", - label: t("contracts.actions.printcontract"), - }, - { - key: "courtesy_car_terms", - label: t("printcenter.courtesycarcontract.courtesy_car_terms"), - }, - { - key: "courtesy_car_impound", - label: t("printcenter.courtesycarcontract.courtesy_car_impound"), - }, - ]} - /> - } - > - - +export function ContractDetailPage({contract, job, courtesyCar, setCourtesyCarReturnModalContext, refetch, form, saveLoading}) { + const {t} = useTranslation(); + return ( +
+ + + + + {() => { + const menu = { + onClick: (e) => { + GenerateDocument( + { + name: TemplateList("courtesycarcontract")[e.key].key, + variables: {id: contract.id}, + }, + {}, + "p" + ); + }, + items: [ + { + key: "courtesy_car_contract", + label: t("contracts.actions.printcontract"), + }, + { + key: "courtesy_car_terms", + label: t("printcenter.courtesycarcontract.courtesy_car_terms"), + }, + { + key: "courtesy_car_impound", + label: t("printcenter.courtesycarcontract.courtesy_car_impound"), + }, + ] + }; - - - ); - }} - - } - /> - - - - - - - - - - - -
- ); + return ( + + + + + + + + + + ); + }} + + } + /> + + + + + + + + + + + +
+ ); } + export default connect(null, mapDispatchToProps)(ContractDetailPage);