diff --git a/client/package-lock.json b/client/package-lock.json index 568cc6058..225d2ba06 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -12,6 +12,10 @@ "@amplitude/analytics-browser": "^2.34.0", "@ant-design/pro-layout": "^7.22.6", "@apollo/client": "^4.1.3", + "@dnd-kit/core": "^6.3.1", + "@dnd-kit/modifiers": "^9.0.0", + "@dnd-kit/sortable": "^10.0.0", + "@dnd-kit/utilities": "^3.2.2", "@emotion/is-prop-valid": "^1.4.0", "@fingerprintjs/fingerprintjs": "^5.0.1", "@firebase/analytics": "^0.10.19", @@ -60,7 +64,6 @@ "react-color": "^2.19.3", "react-cookie": "^8.0.1", "react-dom": "^19.2.4", - "react-drag-listview": "^2.0.0", "react-grid-gallery": "^1.0.1", "react-grid-layout": "^2.2.2", "react-i18next": "^16.5.4", @@ -2494,6 +2497,73 @@ "node": ">=10" } }, + "node_modules/@dnd-kit/accessibility": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@dnd-kit/accessibility/-/accessibility-3.1.1.tgz", + "integrity": "sha512-2P+YgaXF+gRsIihwwY1gCsQSYnu9Zyj2py8kY5fFvUM1qm2WA2u639R6YNVfU4GWr+ZM5mqEsfHZZLoRONbemw==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@dnd-kit/core": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/@dnd-kit/core/-/core-6.3.1.tgz", + "integrity": "sha512-xkGBRQQab4RLwgXxoqETICr6S5JlogafbhNsidmrkVv2YRs5MLwpjoF2qpiGjQt8S9AoxtIV603s0GIUpY5eYQ==", + "license": "MIT", + "dependencies": { + "@dnd-kit/accessibility": "^3.1.1", + "@dnd-kit/utilities": "^3.2.2", + "tslib": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@dnd-kit/modifiers": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@dnd-kit/modifiers/-/modifiers-9.0.0.tgz", + "integrity": "sha512-ybiLc66qRGuZoC20wdSSG6pDXFikui/dCNGthxv4Ndy8ylErY0N3KVxY2bgo7AWwIbxDmXDg3ylAFmnrjcbVvw==", + "license": "MIT", + "dependencies": { + "@dnd-kit/utilities": "^3.2.2", + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@dnd-kit/core": "^6.3.0", + "react": ">=16.8.0" + } + }, + "node_modules/@dnd-kit/sortable": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@dnd-kit/sortable/-/sortable-10.0.0.tgz", + "integrity": "sha512-+xqhmIIzvAYMGfBYYnbKuNicfSsk4RksY2XdmJhT+HAC01nix6fHCztU68jooFiMUB01Ky3F0FyOvhG/BZrWkg==", + "license": "MIT", + "dependencies": { + "@dnd-kit/utilities": "^3.2.2", + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@dnd-kit/core": "^6.3.0", + "react": ">=16.8.0" + } + }, + "node_modules/@dnd-kit/utilities": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@dnd-kit/utilities/-/utilities-3.2.2.tgz", + "integrity": "sha512-+MKAJEOfaBe5SmV6t34p80MMKhjvUz0vRrvVJbPT0WElzaOJ/1xs+D+KDv+tD/NE5ujfrChEcshd4fLn0wpiqg==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, "node_modules/@dotenvx/dotenvx": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/@dotenvx/dotenvx/-/dotenvx-1.52.0.tgz", @@ -8396,16 +8466,6 @@ "@babel/types": "^7.26.0" } }, - "node_modules/babel-runtime": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==", - "license": "MIT", - "dependencies": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" - } - }, "node_modules/bail": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", @@ -9192,14 +9252,6 @@ "node": ">=18" } }, - "node_modules/core-js": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", - "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", - "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.", - "hasInstallScript": true, - "license": "MIT" - }, "node_modules/core-js-compat": { "version": "3.47.0", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.47.0.tgz", @@ -15376,16 +15428,6 @@ "react": "^19.2.4" } }, - "node_modules/react-drag-listview": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/react-drag-listview/-/react-drag-listview-2.0.0.tgz", - "integrity": "sha512-7Apx/1Xt4qu+JHHP0rH6aLgZgS7c2MX8ocHVGCi03KfeIWEu0t14MhT3boQKM33l5eJrE/IWfExFTvoYq22fsg==", - "license": "MIT", - "dependencies": { - "babel-runtime": "^6.26.0", - "prop-types": "^15.5.8" - } - }, "node_modules/react-draggable": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/react-draggable/-/react-draggable-4.5.0.tgz", @@ -15972,12 +16014,6 @@ "node": ">=4" } }, - "node_modules/regenerator-runtime": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", - "license": "MIT" - }, "node_modules/regexp.prototype.flags": { "version": "1.5.4", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", diff --git a/client/package.json b/client/package.json index 8b88d8e43..b0cbdf6b8 100644 --- a/client/package.json +++ b/client/package.json @@ -11,6 +11,10 @@ "@amplitude/analytics-browser": "^2.34.0", "@ant-design/pro-layout": "^7.22.6", "@apollo/client": "^4.1.3", + "@dnd-kit/core": "^6.3.1", + "@dnd-kit/modifiers": "^9.0.0", + "@dnd-kit/sortable": "^10.0.0", + "@dnd-kit/utilities": "^3.2.2", "@emotion/is-prop-valid": "^1.4.0", "@fingerprintjs/fingerprintjs": "^5.0.1", "@firebase/analytics": "^0.10.19", @@ -59,7 +63,6 @@ "react-color": "^2.19.3", "react-cookie": "^8.0.1", "react-dom": "^19.2.4", - "react-drag-listview": "^2.0.0", "react-grid-gallery": "^1.0.1", "react-grid-layout": "^2.2.2", "react-i18next": "^16.5.4", diff --git a/client/src/App/App.styles.scss b/client/src/App/App.styles.scss index 09745eac9..657520e49 100644 --- a/client/src/App/App.styles.scss +++ b/client/src/App/App.styles.scss @@ -446,3 +446,32 @@ //.rbc-time-header-gutter { // padding: 0; //} + +/* globally allow shrink inside table cells */ +.prod-list-table .ant-table-cell, +.prod-list-table .ant-table-cell > * { + min-width: 0; +} + +/* common AntD offenders */ +.prod-list-table > .ant-table-cell .ant-space, +.ant-table-cell .ant-space-item { + min-width: 0; +} + +/* Keep your custom header content on the left, push AntD sorter to the far right */ +.prod-list-table .ant-table-column-sorters { + display: flex !important; + align-items: center; + width: 100%; +} + +.prod-list-table .ant-table-column-title { + flex: 1 1 auto; + min-width: 0; /* allows ellipsis to work */ +} + +.prod-list-table .ant-table-column-sorter { + margin-left: auto; + flex: 0 0 auto; +} diff --git a/client/src/components/bill-form/bill-form.lines.component.jsx b/client/src/components/bill-form/bill-form.lines.component.jsx index 73b0a21a9..a841f0534 100644 --- a/client/src/components/bill-form/bill-form.lines.component.jsx +++ b/client/src/components/bill-form/bill-form.lines.component.jsx @@ -1,6 +1,7 @@ import { DeleteFilled, DollarCircleFilled } from "@ant-design/icons"; import { useTreatmentsWithConfig } from "@splitsoftware/splitio-react"; import { Button, Checkbox, Form, Input, InputNumber, Select, Space, Switch, Table, Tooltip } from "antd"; +import { useRef } from "react"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; @@ -32,6 +33,7 @@ export function BillEnterModalLinesComponent({ }) { const { t } = useTranslation(); const { setFieldsValue, getFieldsValue, getFieldValue } = form; + const firstFieldRefs = useRef({}); const CONTROL_HEIGHT = 32; @@ -155,6 +157,9 @@ export function BillEnterModalLinesComponent({ ), formInput: (record, index) => ( { + firstFieldRefs.current[index] = el; + }} disabled={disabled} options={lineData} style={{ @@ -205,7 +210,7 @@ export function BillEnterModalLinesComponent({ label: t("billlines.fields.line_desc"), rules: [{ required: true }] }), - formInput: () => + formInput: () => }, { title: t("billlines.fields.quantity"), @@ -234,7 +239,7 @@ export function BillEnterModalLinesComponent({ }) ] }), - formInput: () => + formInput: () => }, { title: t("billlines.fields.actual_price"), @@ -251,6 +256,7 @@ export function BillEnterModalLinesComponent({ { if (e.key === "Tab" && !e.shiftKey) autofillActualCost(index); @@ -328,6 +334,7 @@ export function BillEnterModalLinesComponent({ min={0} disabled={disabled} controls={false} + tabIndex={0} style={{ width: "100%", height: CONTROL_HEIGHT }} // NOTE: No auto-fill on focus/blur; only triggered from Retail on Tab /> @@ -392,7 +399,7 @@ export function BillEnterModalLinesComponent({ rules: [{ required: true }] }), formInput: () => ( - {bodyshopHasDmsKey(bodyshop) ? CiecaSelect(true, false) : responsibilityCenters.costs.map((item) => {item.name})} @@ -412,7 +419,7 @@ export function BillEnterModalLinesComponent({ name: [field.name, "location"] }), formInput: () => ( - {bodyshop.md_parts_locations.map((loc, idx) => ( {loc} @@ -432,7 +439,7 @@ export function BillEnterModalLinesComponent({ key: `${field.name}deductedfromlbr`, name: [field.name, "deductedfromlbr"] }), - formInput: () => , + formInput: () => , additional: (record, index) => ( {() => { @@ -523,7 +530,7 @@ export function BillEnterModalLinesComponent({ rome: false }) }), - formInput: () => + formInput: () => } ] }), @@ -538,7 +545,7 @@ export function BillEnterModalLinesComponent({ valuePropName: "checked", name: [field.name, "applicable_taxes", "state"] }), - formInput: () => + formInput: () => }, ...InstanceRenderManager({ @@ -554,7 +561,7 @@ export function BillEnterModalLinesComponent({ valuePropName: "checked", name: [field.name, "applicable_taxes", "local"] }), - formInput: () => + formInput: () => } ] }), @@ -574,6 +581,7 @@ export function BillEnterModalLinesComponent({ icon={} disabled={disabled || invLen > 0} onClick={() => remove(record.name)} + tabIndex={0} /> {Simple_Inventory.treatment === "on" && ( @@ -645,12 +653,19 @@ export function BillEnterModalLinesComponent({