diff --git a/client/src/components/jobs-list/jobs-list.component.jsx b/client/src/components/jobs-list/jobs-list.component.jsx
index d11e4b688..6d04bcd47 100644
--- a/client/src/components/jobs-list/jobs-list.component.jsx
+++ b/client/src/components/jobs-list/jobs-list.component.jsx
@@ -184,12 +184,15 @@ export function JobsList({ bodyshop }) {
),
sortOrder: state.sortedInfo.columnKey === "vehicle" && state.sortedInfo.order,
render: (text, record) => {
+ const vehicleLabel =
+ `${record.v_model_yr || ""} ${record.v_make_desc || ""} ${record.v_model_desc || ""}`.trim();
+
return record.vehicleid ? (
e.stopPropagation()}>
- {`${record.v_model_yr || ""} ${record.v_make_desc || ""} ${record.v_model_desc || ""}`}
+ {vehicleLabel}
) : (
- {`${record.v_model_yr || ""} ${record.v_make_desc || ""} ${record.v_model_desc || ""}`}
+ {vehicleLabel}
);
}
},
diff --git a/client/src/components/responsive-table/responsive-table.component.jsx b/client/src/components/responsive-table/responsive-table.component.jsx
index 4228d9efe..94ed7fc02 100644
--- a/client/src/components/responsive-table/responsive-table.component.jsx
+++ b/client/src/components/responsive-table/responsive-table.component.jsx
@@ -1,9 +1,12 @@
import { Grid, Table } from "antd";
import { useMemo } from "react";
+import "./responsive-table.styles.scss";
-function ResponsiveTable({ columns, mobileColumnKeys, scroll, ...rest }) {
+function ResponsiveTable({ className, columns, mobileColumnKeys, scroll, tableLayout, ...rest }) {
const screens = Grid.useBreakpoint();
const isPhone = !screens.md;
+ const isCompactViewport = !screens.lg;
+ const prefersHorizontalScroll = isPhone || isCompactViewport;
const isResponsiveFilteringEnabled = ["1", "true", "yes", "on"].includes(
String(import.meta.env.VITE_APP_ENABLE_RESPONSIVE_TABLE_FILTERING || "")
.trim()
@@ -38,9 +41,53 @@ function ResponsiveTable({ columns, mobileColumnKeys, scroll, ...rest }) {
return filteredColumns.length > 0 ? filteredColumns : columns;
}, [columns, isPhone, isResponsiveFilteringEnabled, mobileColumnKeys]);
- const resolvedScroll = scroll ?? { x: "max-content" };
+ const resolvedScroll = useMemo(() => {
+ if (prefersHorizontalScroll) {
+ if (scroll == null) {
+ return { x: "max-content" };
+ }
- return
;
+ if (typeof scroll !== "object" || Array.isArray(scroll)) {
+ return scroll;
+ }
+
+ const { x, ...baseScroll } = scroll;
+
+ return { ...baseScroll, x: x ?? "max-content" };
+ }
+
+ if (scroll == null) {
+ // Explicitly override ConfigProvider table.scroll desktop defaults.
+ return {};
+ }
+
+ if (typeof scroll !== "object" || Array.isArray(scroll)) {
+ return scroll;
+ }
+
+ const { x, ...desktopScroll } = scroll;
+
+ // On desktop we prefer fitting columns with ellipsis over forced horizontal scroll.
+ if (x == null) {
+ return desktopScroll;
+ }
+
+ return desktopScroll;
+ }, [prefersHorizontalScroll, scroll]);
+
+ const resolvedTableLayout = tableLayout ?? (prefersHorizontalScroll ? "auto" : "fixed");
+ const responsiveClassName = prefersHorizontalScroll ? undefined : "responsive-table-fit";
+ const resolvedClassName = [responsiveClassName, className].filter(Boolean).join(" ");
+
+ return (
+
+ );
}
ResponsiveTable.Summary = Table.Summary;
diff --git a/client/src/components/responsive-table/responsive-table.styles.scss b/client/src/components/responsive-table/responsive-table.styles.scss
new file mode 100644
index 000000000..349a46024
--- /dev/null
+++ b/client/src/components/responsive-table/responsive-table.styles.scss
@@ -0,0 +1,27 @@
+.responsive-table-fit .ant-table-cell,
+.responsive-table-fit .ant-table-cell > * {
+ min-width: 0;
+}
+
+.responsive-table-fit .ant-table-content > table {
+ width: 100%;
+}
+
+.responsive-table-fit .ant-table-column-sorters {
+ width: 100%;
+}
+
+.responsive-table-fit .ant-table-column-title,
+.responsive-table-fit .ant-space,
+.responsive-table-fit .ant-space-item {
+ min-width: 0;
+}
+
+.responsive-table-fit .ant-table-cell-ellipsis > a,
+.responsive-table-fit .ant-table-cell-ellipsis > span {
+ display: block;
+ max-width: 100%;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
diff --git a/server/web-sockets/createLogEvent.js b/server/web-sockets/createLogEvent.js
index 0e0d52cbc..b1824d334 100644
--- a/server/web-sockets/createLogEvent.js
+++ b/server/web-sockets/createLogEvent.js
@@ -1,114 +1,113 @@
const { isArray } = require("lodash");
const logger = require("../utils/logger");
-
function createLogEvent(socket, level, message) {
- if (LogLevelHierarchy(socket.log_level) >= LogLevelHierarchy(level)) {
- // console.log(`[WS LOG EVENT] ${level} - ${new Date()} - ${socket.user.email} - ${socket.id} - ${message}`);
- socket.emit("log-event", {
- timestamp: new Date(),
- level,
- message
- });
+ if (LogLevelHierarchy(socket.log_level) >= LogLevelHierarchy(level)) {
+ // console.log(`[WS LOG EVENT] ${level} - ${new Date()} - ${socket.user.email} - ${socket.id} - ${message}`);
+ socket.emit("log-event", {
+ timestamp: new Date(),
+ level,
+ message
+ });
- logger.log("ws-log-event", level, socket.user.email, socket.recordid, {
- wsmessage: message
- });
-
- if (socket.logEvents && isArray(socket.logEvents)) {
- socket.logEvents.push({
- timestamp: new Date(),
- level,
- message
- });
- }
- // if (level === "ERROR") {
- // throw new Error(message);
- // }
- }
-}
-
-function createJsonEvent(socket, level, message, json) {
- if (LogLevelHierarchy(socket.log_level) >= LogLevelHierarchy(level)) {
- //console.log(`[WS LOG EVENT] ${level} - ${new Date()} - ${socket.user.email} - ${socket.id} - ${message}`);
- socket.emit("log-event", {
- timestamp: new Date(),
- level,
- message
- });
- }
- logger.log(
- "ws-log-event-json",
- level,
- socket.user.email,
- socket.recordid,
- {
- wsmessage: message,
- json
- },
- true
- );
+ logger.log("ws-log-event", level, socket.user.email, socket.recordid, {
+ wsmessage: message
+ });
if (socket.logEvents && isArray(socket.logEvents)) {
- socket.logEvents.push({
- timestamp: new Date(),
- level,
- message
- });
+ socket.logEvents.push({
+ timestamp: new Date(),
+ level,
+ message
+ });
}
// if (level === "ERROR") {
// throw new Error(message);
// }
+ }
+}
+
+function createJsonEvent(socket, level, message, json) {
+ if (LogLevelHierarchy(socket.log_level) >= LogLevelHierarchy(level)) {
+ //console.log(`[WS LOG EVENT] ${level} - ${new Date()} - ${socket.user.email} - ${socket.id} - ${message}`);
+ socket.emit("log-event", {
+ timestamp: new Date(),
+ level,
+ message
+ });
+ }
+ logger.log(
+ "ws-log-event-json",
+ level,
+ socket.user.email,
+ socket.recordid,
+ {
+ wsmessage: message,
+ json
+ },
+ true
+ );
+
+ if (socket.logEvents && isArray(socket.logEvents)) {
+ socket.logEvents.push({
+ timestamp: new Date(),
+ level,
+ message
+ });
+ }
+ // if (level === "ERROR") {
+ // throw new Error(message);
+ // }
}
function createXmlEvent(socket, xml, message, isError = false) {
- if (LogLevelHierarchy(socket.log_level) >= LogLevelHierarchy("SILLY")) {
- socket.emit("log-event", {
- timestamp: new Date(),
- level: isError ? "ERROR" : "SILLY",
- message: `${message}: ${xml}`
- });
- }
+ if (LogLevelHierarchy(socket.log_level) >= LogLevelHierarchy("SILLY")) {
+ socket.emit("log-event", {
+ timestamp: new Date(),
+ level: isError ? "ERROR" : "SILLY",
+ message: `${message}: ${xml}`
+ });
+ }
- logger.log(
- isError ? "ws-log-event-xml-error" : "ws-log-event-xml",
- isError ? "ERROR" : "SILLY",
- socket.user.email,
- socket.recordid,
- {
- wsmessage: message,
- xml
- },
- true
- );
+ logger.log(
+ isError ? "ws-log-event-xml-error" : "ws-log-event-xml",
+ isError ? "ERROR" : "SILLY",
+ socket.user.email,
+ socket.recordid,
+ {
+ wsmessage: message,
+ xml
+ },
+ true
+ );
- if (socket.logEvents && isArray(socket.logEvents)) {
- socket.logEvents.push({
- timestamp: new Date(),
- level: isError ? "ERROR" : "SILLY",
- message,
- xml
- });
- }
+ if (socket.logEvents && isArray(socket.logEvents)) {
+ socket.logEvents.push({
+ timestamp: new Date(),
+ level: isError ? "ERROR" : "SILLY",
+ message,
+ xml
+ });
+ }
}
function LogLevelHierarchy(level) {
- switch (level) {
- case "XML":
- return 5;
- case "SILLY":
- return 5;
- case "DEBUG":
- return 4;
- case "INFO":
- return 3;
- case "WARN":
- return 2;
- case "ERROR":
- return 1;
- default:
- return 3;
- }
+ switch (level) {
+ case "XML":
+ return 5;
+ case "SILLY":
+ return 5;
+ case "DEBUG":
+ return 4;
+ case "INFO":
+ return 3;
+ case "WARN":
+ return 2;
+ case "ERROR":
+ return 1;
+ default:
+ return 3;
+ }
}
exports.createLogEvent = createLogEvent;