From 90d9ed286db9957af76992733ce3b09235f35415 Mon Sep 17 00:00:00 2001 From: Tom Butcher Date: Sat, 22 Aug 2026 20:02:50 +0100 Subject: [PATCH] Enhance Dashboard Components with New Features and Styling Improvements - Updated App.css to refine styling for object display tags and introduced a border for better visual distinction. - Enhanced NewDocumentJob component by adding a default quantity value for improved user experience. - Introduced PrinterQueue component to manage and display printer job queues, enhancing the ControlPrinter functionality. - Improved MissingPlaceholder component with additional props for customizable border and padding options. - Adjusted ObjectDisplay and ObjectList components for better layout and interaction, including cursor changes for clickable elements. - Updated ThemeContext to manage new color variables for consistent theming across components. --- assets/stylesheets/App.css | 13 +++- .../DocumentJobs/NewDocumentJob.jsx | 1 + .../Production/Printers/ControlPrinter.jsx | 39 ++++++++++- .../Dashboard/common/MissingPlaceholder.jsx | 26 +++++--- .../Dashboard/common/ObjectDisplay.jsx | 47 +++----------- .../Dashboard/common/ObjectList.jsx | 16 ++++- .../Dashboard/common/ObjectTable.jsx | 5 ++ .../Dashboard/common/PrinterQueue.jsx | 65 +++++++++++++++++++ src/components/Dashboard/common/ScrollBox.jsx | 6 +- .../Dashboard/context/ThemeContext.jsx | 4 ++ src/database/models/DocumentJob.js | 19 +++++- 11 files changed, 186 insertions(+), 55 deletions(-) create mode 100644 src/components/Dashboard/common/PrinterQueue.jsx diff --git a/assets/stylesheets/App.css b/assets/stylesheets/App.css index 2ff5e609..f95ca8d9 100644 --- a/assets/stylesheets/App.css +++ b/assets/stylesheets/App.css @@ -680,9 +680,11 @@ body { border-radius: 0px !important; } -.ant-select-selection-item .object-display-tag, -.ant-select-tree-title .object-display-tag { +.ant-select-selection-item .ant-tag.object-display-tag, +.ant-select-tree-title .ant-tag.object-display-tag, +.ant-select-dropdown .ant-tag.object-display-tag { background: transparent !important; + border: none; padding: 0; margin-right: 1px !important; } @@ -1304,7 +1306,8 @@ span.ant-skeleton-input.ant-skeleton-input-sm.text-skeleton { min-width: 0; max-width: 100%; width: auto; - overflow: hidden; + overflow-y: hidden; + overflow-x: visible; flex-grow: 0; flex-shrink: 1; flex-basis: auto; @@ -1686,6 +1689,10 @@ span.ant-skeleton-input.ant-skeleton-input-sm.text-skeleton { font-size: 95%; } +.ant-tag.object-display-tag { + border: 1px solid color-mix(in srgb, var(--color-text) 5%, transparent); +} + .code-block-editor .simplebar-content-wrapper { background-color: var(--layout-modal-bg); } diff --git a/src/components/Dashboard/Management/DocumentJobs/NewDocumentJob.jsx b/src/components/Dashboard/Management/DocumentJobs/NewDocumentJob.jsx index 01ed1410..c9ca88cc 100644 --- a/src/components/Dashboard/Management/DocumentJobs/NewDocumentJob.jsx +++ b/src/components/Dashboard/Management/DocumentJobs/NewDocumentJob.jsx @@ -73,6 +73,7 @@ const NewDocumentJob = ({ onOk, defaultValues = {} }) => { // Capture initial default values so later prop changes don't re-initialize the form const defaultValuesRef = useRef({ objectType: 'documentJob', + quantity: 1, ...defaultValues, saveToFile: false }) diff --git a/src/components/Dashboard/Production/Printers/ControlPrinter.jsx b/src/components/Dashboard/Production/Printers/ControlPrinter.jsx index c8bdc663..5582a3a3 100644 --- a/src/components/Dashboard/Production/Printers/ControlPrinter.jsx +++ b/src/components/Dashboard/Production/Printers/ControlPrinter.jsx @@ -34,6 +34,8 @@ import { ApiServerContext } from '../../context/ApiServerContext.jsx' import ScrollBox from '../../common/ScrollBox.jsx' import ObjectTableNavigationButtons from '../../common/ObjectTableNavigationButtons.jsx' import PrinterControlButtons from '../../common/PrinterControlButtons.jsx' +import PrinterQueue from '../../common/PrinterQueue.jsx' +import ListIcon from '../../../Icons/ListIcon.jsx' const log = loglevel.getLogger('ControlPrinter') log.setLevel(config.logLevel) @@ -50,6 +52,7 @@ const ControlPrinter = ({ slicerIntegration = false }) => { printer: true, job: true, subjob: true, + queue: true, filamentStock: true, temperature: true, position: true, @@ -271,7 +274,7 @@ const ControlPrinter = ({ slicerIntegration = false }) => { { key: 'subJob', label: 'Sub Job' }, + { + key: 'queue', + label: 'Queue' + }, { key: 'filamentStock', label: 'Filament Stock' @@ -401,6 +408,7 @@ const ControlPrinter = ({ slicerIntegration = false }) => { 'currentJob._id': false, currentSubJob: false, 'currentSubJob._id': false, + queue: false, createdAt: false, updatedAt: false, state: !slicerIntegration, @@ -418,6 +426,29 @@ const ControlPrinter = ({ slicerIntegration = false }) => { }} + } + collapseKey='queue' + active={collapseState.queue} + onToggle={(expanded) => + updateCollapseState('queue', expanded) + } + > + + + + } @@ -459,7 +490,9 @@ const ControlPrinter = ({ slicerIntegration = false }) => { ) : ( )} @@ -507,7 +540,9 @@ const ControlPrinter = ({ slicerIntegration = false }) => { ) : ( )} @@ -552,7 +587,9 @@ const ControlPrinter = ({ slicerIntegration = false }) => { ) : ( )} diff --git a/src/components/Dashboard/common/MissingPlaceholder.jsx b/src/components/Dashboard/common/MissingPlaceholder.jsx index c004f25a..6d6be48e 100644 --- a/src/components/Dashboard/common/MissingPlaceholder.jsx +++ b/src/components/Dashboard/common/MissingPlaceholder.jsx @@ -7,19 +7,27 @@ const { Text } = Typography const MissingPlaceholder = ({ message, hasBackground = true, - hasBorder = true + hasBorder = true, + mutedBorder = false, + padding = '16px' }) => { + var border = undefined + if (hasBorder == false) { + border = 'none' + } else if (mutedBorder == true && hasBorder == true) { + border = '1px solid var(--color-descriptions-border)' + } return ( { if (!objectData?.name) return null @@ -195,36 +194,6 @@ const ObjectDisplay = ({ {objectData.name} ) - // If hyperlink is enabled - if (showHyperlink && hyperlink != null) { - const linkElement = ( - navigate(hyperlink)} ellipsis> - {textElement} - - ) - - if (showSpotlight && objectId) { - return ( - - } - trigger={['hover', 'click']} - placement='topLeft' - arrow={false} - style={{ padding: 0 }} - > - {linkElement} - - ) - } - return linkElement - } - - // If hyperlink is disabled if (showSpotlight && objectId) { return ( {textElement} @@ -245,20 +215,23 @@ const ObjectDisplay = ({ return textElement } + const canNavigate = showHyperlink && hyperlink != null + return ( navigate(hyperlink) : undefined} > @@ -285,7 +258,7 @@ const ObjectDisplay = ({ type={objectType} longId={false} showCopy={false} - showHyperlink={showHyperlink} + showHyperlink={false} showSpotlight={showSpotlight} /> ) : null} diff --git a/src/components/Dashboard/common/ObjectList.jsx b/src/components/Dashboard/common/ObjectList.jsx index 79ea72d8..719dac19 100644 --- a/src/components/Dashboard/common/ObjectList.jsx +++ b/src/components/Dashboard/common/ObjectList.jsx @@ -17,7 +17,15 @@ const ObjectList = ({ } const listContents = ( - + {value.map((item) => (
{listContents} + return ( + + {listContents} + + ) } else { return listContents } diff --git a/src/components/Dashboard/common/ObjectTable.jsx b/src/components/Dashboard/common/ObjectTable.jsx index efea4fa5..002a26a7 100644 --- a/src/components/Dashboard/common/ObjectTable.jsx +++ b/src/components/Dashboard/common/ObjectTable.jsx @@ -944,6 +944,11 @@ const ObjectTable = forwardRef( if (connected !== true) return if (subscribedTypeRef.current === type) return + console.log( + 'subscribing to object type updates', + type, + subscriptionFilterRef.current + ) const unsubscribe = subscribeToObjectTypeUpdatesFnRef.current( type, subscriptionFilterRef.current, diff --git a/src/components/Dashboard/common/PrinterQueue.jsx b/src/components/Dashboard/common/PrinterQueue.jsx new file mode 100644 index 00000000..95727fd9 --- /dev/null +++ b/src/components/Dashboard/common/PrinterQueue.jsx @@ -0,0 +1,65 @@ +import PropTypes from 'prop-types' +import ObjectDisplay from './ObjectDisplay' +import { Steps } from 'antd' +import MissingPlaceholder from './MissingPlaceholder' + +const getId = (item) => { + if (!item) return null + if (typeof item === 'string') return item + if (typeof item._id === 'string') return item._id + if (typeof item._id === 'object' && item._id?._id) return item._id._id + return null +} + +const toObject = (item) => { + if (!item) return null + if (typeof item === 'string') return { _id: item } + return item +} + +const PrinterQueue = ({ queue, currentSubJob }) => { + const queueItems = Array.isArray(queue) + ? queue.map(toObject).filter(Boolean) + : [] + const current = toObject(currentSubJob) + const currentId = getId(current) + + const items = [] + if (current && !queueItems.some((item) => getId(item) === currentId)) { + items.push(current) + } + items.push(...queueItems) + + if (items.length === 0) { + return ( + + ) + } + + const currentIndex = currentId + ? items.findIndex((item) => getId(item) === currentId) + : -1 + + return ( + ({ + title: + }))} + /> + ) +} + +PrinterQueue.propTypes = { + queue: PropTypes.array, + currentSubJob: PropTypes.oneOfType([PropTypes.object, PropTypes.string]) +} + +export default PrinterQueue diff --git a/src/components/Dashboard/common/ScrollBox.jsx b/src/components/Dashboard/common/ScrollBox.jsx index 2a3db878..43427583 100644 --- a/src/components/Dashboard/common/ScrollBox.jsx +++ b/src/components/Dashboard/common/ScrollBox.jsx @@ -9,6 +9,7 @@ const ScrollBox = ({ verticalRightPadding = 16, inner = false, smallPadding = false, + className = '', ...rest }) => { return ( @@ -19,7 +20,7 @@ const ScrollBox = ({ '--scrollbox-vertical-right-padding': `${verticalRightPadding}px`, '--scrollbox-horizontal-bottom-padding': `${horizontalBottomPadding}px` }} - className={`${inner ? 'scrollbox-inner' : ''} ${smallPadding ? 'scrollbox-inner-small-padding' : ''}`} + className={`${inner ? 'scrollbox-inner' : ''} ${smallPadding ? 'scrollbox-inner-small-padding' : ''} ${className}`} > {children} @@ -34,7 +35,8 @@ ScrollBox.propTypes = { horizontalBottomPadding: PropTypes.number, verticalRightPadding: PropTypes.number, inner: PropTypes.bool, - smallPadding: PropTypes.bool + smallPadding: PropTypes.bool, + className: PropTypes.string } export default ScrollBox diff --git a/src/components/Dashboard/context/ThemeContext.jsx b/src/components/Dashboard/context/ThemeContext.jsx index 34f8ab90..232ad2c7 100644 --- a/src/components/Dashboard/context/ThemeContext.jsx +++ b/src/components/Dashboard/context/ThemeContext.jsx @@ -157,6 +157,10 @@ export const ThemeProvider = ({ children }) => { isDarkMode ? '#1f1f1f' : '#ffffff' ) root.style.setProperty('--color-text', isDarkMode ? '#ffffff' : '#000000') + root.style.setProperty( + '--color-descriptions-border', + isDarkMode ? 'rgba(253,253,253,0.12)' : 'rgba(5,5,5,0.06)' + ) }, [isDarkMode, primaryColorOverride]) const themeConfig = { diff --git a/src/database/models/DocumentJob.js b/src/database/models/DocumentJob.js index b7280ca9..9453ff59 100644 --- a/src/database/models/DocumentJob.js +++ b/src/database/models/DocumentJob.js @@ -88,9 +88,10 @@ export const DocumentJob = { content: () => createElement(DocumentJobInfo) } ], - columns: ['_reference', 'name', 'state', 'createdAt', 'updatedAt'], + columns: ['_reference', 'name', 'quantity', 'state', 'createdAt', 'updatedAt'], filters: [ 'name', + 'quantity', 'width', 'height', 'state', @@ -98,7 +99,7 @@ export const DocumentJob = { 'updatedAt', '_reference' ], - sorters: ['name', 'state', 'createdAt', 'updatedAt'], + sorters: ['name', 'quantity', 'state', 'createdAt', 'updatedAt'], properties: [ { name: '_id', @@ -203,6 +204,20 @@ export const DocumentJob = { online: true } } + }, + { + name: 'quantity', + label: 'Quantity', + type: 'number', + required: true, + min: 1, + step: 1, + columnWidth: 125, + value: (objectData) => { + if (objectData?.createdAt == undefined && objectData?.quantity == null) { + return 1 + } + } } ] }