Compare commits

...

3 Commits

Author SHA1 Message Date
e4657cc692 Add keyboard shortcuts to ObjectTableNavigationButtons for enhanced navigation
Some checks failed
farmcontrol/farmcontrol-ui/pipeline/head There was a failure building this commit
- Integrated KeyboardShortcut component to allow navigation using 'ALT + LEFT' and 'ALT + RIGHT' key combinations.
- Updated button handlers to trigger navigation actions based on keyboard shortcuts, improving user experience and accessibility.
- Ensured that navigation is only triggered when the buttons are not disabled and the relevant neighbors exist.
2026-08-01 14:00:45 +01:00
9d3de7bc01 Refactor KeyboardShortcut component for improved key handling and logging
- Updated the `parseShortcut` function to utilize a modifier aliases object for better readability and maintainability.
- Introduced `getPressedKey` function to streamline key detection logic.
- Replaced the previous shortcut key set management with a more efficient use of `useMemo` and `useState` for tracking pressed keys.
- Added optional `log` prop to enable logging of key events for debugging purposes.
- Enhanced the overall structure and performance of the KeyboardShortcut component.
2026-08-01 14:00:40 +01:00
0e0accc115 Update navigation button states across various components to improve user interaction
- Modified the `disabled` prop for `ObjectTableNavigationButtons` in multiple components, including InvoiceInfo, PaymentInfo, and TaxRecordInfo, to account for both loading states and editing states.
- This change enhances user experience by preventing interactions during loading or editing, ensuring a smoother workflow across the dashboard.
2026-08-01 13:36:29 +01:00
46 changed files with 227 additions and 138 deletions

View File

@ -170,7 +170,7 @@ const InvoiceInfo = () => {
loading={objectFormState.editLoading} loading={objectFormState.editLoading}
/> />
<ObjectTableNavigationButtons <ObjectTableNavigationButtons
disabled={objectFormState.loading} disabled={objectFormState.loading || objectFormState.isEditing}
_id={invoiceId} _id={invoiceId}
objectType='invoice' objectType='invoice'
showEndingDivider={true} showEndingDivider={true}

View File

@ -163,7 +163,7 @@ const PaymentInfo = () => {
loading={objectFormState.editLoading} loading={objectFormState.editLoading}
/> />
<ObjectTableNavigationButtons <ObjectTableNavigationButtons
disabled={objectFormState.loading} disabled={objectFormState.loading || objectFormState.isEditing}
_id={paymentId} _id={paymentId}
objectType='payment' objectType='payment'
showEndingDivider={true} showEndingDivider={true}

View File

@ -123,11 +123,13 @@ const TaxRecordInfo = () => {
}} }}
editLoading={objectFormState.editLoading} editLoading={objectFormState.editLoading}
formValid={objectFormState.formValid} formValid={objectFormState.formValid}
disabled={objectFormState.beingEditedByOther || objectFormState.loading} disabled={
objectFormState.beingEditedByOther || objectFormState.loading
}
loading={objectFormState.editLoading} loading={objectFormState.editLoading}
/> />
<ObjectTableNavigationButtons <ObjectTableNavigationButtons
disabled={objectFormState.loading} disabled={objectFormState.loading || objectFormState.isEditing}
_id={taxRecordId} _id={taxRecordId}
objectType='taxRecord' objectType='taxRecord'
showEndingDivider={true} showEndingDivider={true}

View File

@ -127,7 +127,7 @@ const FilamentStockInfo = () => {
loading={objectFormState.editLoading} loading={objectFormState.editLoading}
/> />
<ObjectTableNavigationButtons <ObjectTableNavigationButtons
disabled={objectFormState.loading} disabled={objectFormState.loading || objectFormState.isEditing}
_id={filamentStockId} _id={filamentStockId}
objectType='filamentStock' objectType='filamentStock'
showEndingDivider={true} showEndingDivider={true}

View File

@ -122,11 +122,13 @@ const OrderItemInfo = () => {
}} }}
editLoading={objectFormState.editLoading} editLoading={objectFormState.editLoading}
formValid={objectFormState.formValid} formValid={objectFormState.formValid}
disabled={objectFormState.beingEditedByOther || objectFormState.loading} disabled={
objectFormState.beingEditedByOther || objectFormState.loading
}
loading={objectFormState.editLoading} loading={objectFormState.editLoading}
/> />
<ObjectTableNavigationButtons <ObjectTableNavigationButtons
disabled={objectFormState.loading} disabled={objectFormState.loading || objectFormState.isEditing}
_id={orderItemId} _id={orderItemId}
objectType='orderItem' objectType='orderItem'
showEndingDivider={true} showEndingDivider={true}

View File

@ -137,7 +137,7 @@ const PartStockInfo = () => {
loading={objectFormState.editLoading} loading={objectFormState.editLoading}
/> />
<ObjectTableNavigationButtons <ObjectTableNavigationButtons
disabled={objectFormState.loading} disabled={objectFormState.loading || objectFormState.isEditing}
_id={partStockId} _id={partStockId}
objectType='partStock' objectType='partStock'
showEndingDivider={true} showEndingDivider={true}

View File

@ -164,7 +164,7 @@ const ProductStockInfo = () => {
loading={objectFormState.editLoading} loading={objectFormState.editLoading}
/> />
<ObjectTableNavigationButtons <ObjectTableNavigationButtons
disabled={objectFormState.loading} disabled={objectFormState.loading || objectFormState.isEditing}
_id={productStockId} _id={productStockId}
objectType='productStock' objectType='productStock'
showEndingDivider={true} showEndingDivider={true}

View File

@ -197,7 +197,7 @@ const PurchaseOrderInfo = () => {
loading={objectFormState.editLoading} loading={objectFormState.editLoading}
/> />
<ObjectTableNavigationButtons <ObjectTableNavigationButtons
disabled={objectFormState.loading} disabled={objectFormState.loading || objectFormState.isEditing}
_id={purchaseOrderId} _id={purchaseOrderId}
objectType='purchaseOrder' objectType='purchaseOrder'
showEndingDivider={true} showEndingDivider={true}

View File

@ -158,11 +158,13 @@ const PurchaseOrderInfo = () => {
}} }}
editLoading={objectFormState.editLoading} editLoading={objectFormState.editLoading}
formValid={objectFormState.formValid} formValid={objectFormState.formValid}
disabled={objectFormState.beingEditedByOther || objectFormState.loading} disabled={
objectFormState.beingEditedByOther || objectFormState.loading
}
loading={objectFormState.editLoading} loading={objectFormState.editLoading}
/> />
<ObjectTableNavigationButtons <ObjectTableNavigationButtons
disabled={objectFormState.loading} disabled={objectFormState.loading || objectFormState.isEditing}
_id={purchaseOrderId} _id={purchaseOrderId}
objectType='purchaseOrder' objectType='purchaseOrder'
showEndingDivider={true} showEndingDivider={true}

View File

@ -147,11 +147,13 @@ const ShipmentInfo = () => {
}} }}
editLoading={objectFormState.editLoading} editLoading={objectFormState.editLoading}
formValid={objectFormState.formValid} formValid={objectFormState.formValid}
disabled={objectFormState.beingEditedByOther || objectFormState.loading} disabled={
objectFormState.beingEditedByOther || objectFormState.loading
}
loading={objectFormState.editLoading} loading={objectFormState.editLoading}
/> />
<ObjectTableNavigationButtons <ObjectTableNavigationButtons
disabled={objectFormState.loading} disabled={objectFormState.loading || objectFormState.isEditing}
_id={shipmentId} _id={shipmentId}
objectType='shipment' objectType='shipment'
showEndingDivider={true} showEndingDivider={true}

View File

@ -125,11 +125,13 @@ const StockAuditInfo = () => {
}} }}
editLoading={objectFormState.editLoading} editLoading={objectFormState.editLoading}
formValid={objectFormState.formValid} formValid={objectFormState.formValid}
disabled={objectFormState.beingEditedByOther || objectFormState.loading} disabled={
objectFormState.beingEditedByOther || objectFormState.loading
}
loading={objectFormState.editLoading} loading={objectFormState.editLoading}
/> />
<ObjectTableNavigationButtons <ObjectTableNavigationButtons
disabled={objectFormState.loading} disabled={objectFormState.loading || objectFormState.isEditing}
_id={stockAuditId} _id={stockAuditId}
objectType='stockAudit' objectType='stockAudit'
showEndingDivider={true} showEndingDivider={true}

View File

@ -126,11 +126,13 @@ const StockLocationInfo = () => {
}} }}
editLoading={objectFormState.editLoading} editLoading={objectFormState.editLoading}
formValid={objectFormState.formValid} formValid={objectFormState.formValid}
disabled={objectFormState.beingEditedByOther || objectFormState.loading} disabled={
objectFormState.beingEditedByOther || objectFormState.loading
}
loading={objectFormState.editLoading} loading={objectFormState.editLoading}
/> />
<ObjectTableNavigationButtons <ObjectTableNavigationButtons
disabled={objectFormState.loading} disabled={objectFormState.loading || objectFormState.isEditing}
_id={stockLocationId} _id={stockLocationId}
objectType='stockLocation' objectType='stockLocation'
showEndingDivider={true} showEndingDivider={true}

View File

@ -152,7 +152,7 @@ const StockTransferInfo = () => {
loading={objectFormState.editLoading} loading={objectFormState.editLoading}
/> />
<ObjectTableNavigationButtons <ObjectTableNavigationButtons
disabled={objectFormState.loading} disabled={objectFormState.loading || objectFormState.isEditing}
_id={stockTransferId} _id={stockTransferId}
objectType='stockTransfer' objectType='stockTransfer'
showEndingDivider={true} showEndingDivider={true}

View File

@ -134,7 +134,7 @@ const AppPasswordInfo = () => {
loading={objectFormState.editLoading} loading={objectFormState.editLoading}
/> />
<ObjectTableNavigationButtons <ObjectTableNavigationButtons
disabled={objectFormState.loading} disabled={objectFormState.loading || objectFormState.isEditing}
_id={appPasswordId} _id={appPasswordId}
objectType='appPassword' objectType='appPassword'
showEndingDivider={true} showEndingDivider={true}

View File

@ -125,11 +125,13 @@ const CourierServiceInfo = () => {
}} }}
editLoading={objectFormState.editLoading} editLoading={objectFormState.editLoading}
formValid={objectFormState.formValid} formValid={objectFormState.formValid}
disabled={objectFormState.beingEditedByOther || objectFormState.loading} disabled={
objectFormState.beingEditedByOther || objectFormState.loading
}
loading={objectFormState.editLoading} loading={objectFormState.editLoading}
/> />
<ObjectTableNavigationButtons <ObjectTableNavigationButtons
disabled={objectFormState.loading} disabled={objectFormState.loading || objectFormState.isEditing}
_id={courierServiceId} _id={courierServiceId}
objectType='courierService' objectType='courierService'
showEndingDivider={true} showEndingDivider={true}

View File

@ -121,11 +121,13 @@ const CourierInfo = () => {
}} }}
editLoading={objectFormState.editLoading} editLoading={objectFormState.editLoading}
formValid={objectFormState.formValid} formValid={objectFormState.formValid}
disabled={objectFormState.beingEditedByOther || objectFormState.loading} disabled={
objectFormState.beingEditedByOther || objectFormState.loading
}
loading={objectFormState.editLoading} loading={objectFormState.editLoading}
/> />
<ObjectTableNavigationButtons <ObjectTableNavigationButtons
disabled={objectFormState.loading} disabled={objectFormState.loading || objectFormState.isEditing}
_id={courierId} _id={courierId}
objectType='courier' objectType='courier'
showEndingDivider={true} showEndingDivider={true}

View File

@ -122,11 +122,13 @@ const DocumentJobInfo = () => {
}} }}
editLoading={objectFormState.editLoading} editLoading={objectFormState.editLoading}
formValid={objectFormState.formValid} formValid={objectFormState.formValid}
disabled={objectFormState.beingEditedByOther || objectFormState.loading} disabled={
objectFormState.beingEditedByOther || objectFormState.loading
}
loading={objectFormState.editLoading} loading={objectFormState.editLoading}
/> />
<ObjectTableNavigationButtons <ObjectTableNavigationButtons
disabled={objectFormState.loading} disabled={objectFormState.loading || objectFormState.isEditing}
_id={documentJobId} _id={documentJobId}
objectType='documentJob' objectType='documentJob'
showEndingDivider={true} showEndingDivider={true}

View File

@ -136,7 +136,7 @@ const DocumentPrinterInfo = () => {
loading={objectFormState.editLoading} loading={objectFormState.editLoading}
/> />
<ObjectTableNavigationButtons <ObjectTableNavigationButtons
disabled={objectFormState.loading} disabled={objectFormState.loading || objectFormState.isEditing}
_id={documentPrinterId} _id={documentPrinterId}
objectType='documentPrinter' objectType='documentPrinter'
showEndingDivider={true} showEndingDivider={true}

View File

@ -128,7 +128,7 @@ const DocumentSizeInfo = () => {
loading={objectFormState.editLoading} loading={objectFormState.editLoading}
/> />
<ObjectTableNavigationButtons <ObjectTableNavigationButtons
disabled={objectFormState.loading} disabled={objectFormState.loading || objectFormState.isEditing}
_id={documentSizeId} _id={documentSizeId}
objectType='documentSize' objectType='documentSize'
showEndingDivider={true} showEndingDivider={true}

View File

@ -133,7 +133,7 @@ const DocumentTemplateInfo = () => {
loading={objectFormState.editLoading} loading={objectFormState.editLoading}
/> />
<ObjectTableNavigationButtons <ObjectTableNavigationButtons
disabled={objectFormState.loading} disabled={objectFormState.loading || objectFormState.isEditing}
_id={documentTemplateId} _id={documentTemplateId}
objectType='documentTemplate' objectType='documentTemplate'
showEndingDivider={true} showEndingDivider={true}

View File

@ -120,11 +120,13 @@ const FilamentSkuInfo = () => {
}} }}
editLoading={objectFormState.editLoading} editLoading={objectFormState.editLoading}
formValid={objectFormState.formValid} formValid={objectFormState.formValid}
disabled={objectFormState.beingEditedByOther || objectFormState.loading} disabled={
objectFormState.beingEditedByOther || objectFormState.loading
}
loading={objectFormState.editLoading} loading={objectFormState.editLoading}
/> />
<ObjectTableNavigationButtons <ObjectTableNavigationButtons
disabled={objectFormState.loading} disabled={objectFormState.loading || objectFormState.isEditing}
_id={filamentSkuId} _id={filamentSkuId}
objectType='filamentSku' objectType='filamentSku'
showEndingDivider={true} showEndingDivider={true}

View File

@ -141,11 +141,13 @@ const FilamentInfo = () => {
}} }}
editLoading={objectFormState.editLoading} editLoading={objectFormState.editLoading}
formValid={objectFormState.formValid} formValid={objectFormState.formValid}
disabled={objectFormState.beingEditedByOther || objectFormState.loading} disabled={
objectFormState.beingEditedByOther || objectFormState.loading
}
loading={objectFormState.editLoading} loading={objectFormState.editLoading}
/> />
<ObjectTableNavigationButtons <ObjectTableNavigationButtons
disabled={objectFormState.loading} disabled={objectFormState.loading || objectFormState.isEditing}
_id={filamentId} _id={filamentId}
objectType='filament' objectType='filament'
showEndingDivider={true} showEndingDivider={true}

View File

@ -142,7 +142,7 @@ const FileInfo = () => {
loading={objectFormState.editLoading} loading={objectFormState.editLoading}
/> />
<ObjectTableNavigationButtons <ObjectTableNavigationButtons
disabled={objectFormState.loading} disabled={objectFormState.loading || objectFormState.isEditing}
_id={fileId} _id={fileId}
objectType='file' objectType='file'
showEndingDivider={true} showEndingDivider={true}

View File

@ -137,11 +137,13 @@ const HostInfo = () => {
}} }}
editLoading={objectFormState.editLoading} editLoading={objectFormState.editLoading}
formValid={objectFormState.formValid} formValid={objectFormState.formValid}
disabled={objectFormState.beingEditedByOther || objectFormState.loading} disabled={
objectFormState.beingEditedByOther || objectFormState.loading
}
loading={objectFormState.editLoading} loading={objectFormState.editLoading}
/> />
<ObjectTableNavigationButtons <ObjectTableNavigationButtons
disabled={objectFormState.loading} disabled={objectFormState.loading || objectFormState.isEditing}
_id={hostId} _id={hostId}
objectType='host' objectType='host'
showEndingDivider={true} showEndingDivider={true}

View File

@ -123,11 +123,13 @@ const MaterialInfo = () => {
}} }}
editLoading={objectFormState.editLoading} editLoading={objectFormState.editLoading}
formValid={objectFormState.formValid} formValid={objectFormState.formValid}
disabled={objectFormState.beingEditedByOther || objectFormState.loading} disabled={
objectFormState.beingEditedByOther || objectFormState.loading
}
loading={objectFormState.editLoading} loading={objectFormState.editLoading}
/> />
<ObjectTableNavigationButtons <ObjectTableNavigationButtons
disabled={objectFormState.loading} disabled={objectFormState.loading || objectFormState.isEditing}
_id={materialId} _id={materialId}
objectType='material' objectType='material'
showEndingDivider={true} showEndingDivider={true}

View File

@ -111,11 +111,13 @@ const NoteTypeInfo = () => {
}} }}
editLoading={objectFormState.editLoading} editLoading={objectFormState.editLoading}
formValid={objectFormState.formValid} formValid={objectFormState.formValid}
disabled={objectFormState.beingEditedByOther || objectFormState.loading} disabled={
objectFormState.beingEditedByOther || objectFormState.loading
}
loading={objectFormState.editLoading} loading={objectFormState.editLoading}
/> />
<ObjectTableNavigationButtons <ObjectTableNavigationButtons
disabled={objectFormState.loading} disabled={objectFormState.loading || objectFormState.isEditing}
_id={noteTypeId} _id={noteTypeId}
objectType='noteType' objectType='noteType'
showEndingDivider={true} showEndingDivider={true}

View File

@ -126,11 +126,13 @@ const NoteInfo = () => {
}} }}
editLoading={objectFormState.editLoading} editLoading={objectFormState.editLoading}
formValid={objectFormState.formValid} formValid={objectFormState.formValid}
disabled={objectFormState.beingEditedByOther || objectFormState.loading} disabled={
objectFormState.beingEditedByOther || objectFormState.loading
}
loading={objectFormState.editLoading} loading={objectFormState.editLoading}
/> />
<ObjectTableNavigationButtons <ObjectTableNavigationButtons
disabled={objectFormState.loading} disabled={objectFormState.loading || objectFormState.isEditing}
_id={noteId} _id={noteId}
objectType='note' objectType='note'
showEndingDivider={true} showEndingDivider={true}

View File

@ -115,11 +115,13 @@ const PartSkuInfo = () => {
}} }}
editLoading={objectFormState.editLoading} editLoading={objectFormState.editLoading}
formValid={objectFormState.formValid} formValid={objectFormState.formValid}
disabled={objectFormState.beingEditedByOther || objectFormState.loading} disabled={
objectFormState.beingEditedByOther || objectFormState.loading
}
loading={objectFormState.editLoading} loading={objectFormState.editLoading}
/> />
<ObjectTableNavigationButtons <ObjectTableNavigationButtons
disabled={objectFormState.loading} disabled={objectFormState.loading || objectFormState.isEditing}
_id={partSkuId} _id={partSkuId}
objectType='partSku' objectType='partSku'
showEndingDivider={true} showEndingDivider={true}

View File

@ -121,11 +121,13 @@ const PartInfo = () => {
}} }}
editLoading={objectFormState.editLoading} editLoading={objectFormState.editLoading}
formValid={objectFormState.formValid} formValid={objectFormState.formValid}
disabled={objectFormState.beingEditedByOther || objectFormState.loading} disabled={
objectFormState.beingEditedByOther || objectFormState.loading
}
loading={objectFormState.editLoading} loading={objectFormState.editLoading}
/> />
<ObjectTableNavigationButtons <ObjectTableNavigationButtons
disabled={objectFormState.loading} disabled={objectFormState.loading || objectFormState.isEditing}
_id={partId} _id={partId}
objectType='part' objectType='part'
showEndingDivider={true} showEndingDivider={true}

View File

@ -120,11 +120,13 @@ const ProductCategoryInfo = () => {
}} }}
editLoading={objectFormState.editLoading} editLoading={objectFormState.editLoading}
formValid={objectFormState.formValid} formValid={objectFormState.formValid}
disabled={objectFormState.beingEditedByOther || objectFormState.loading} disabled={
objectFormState.beingEditedByOther || objectFormState.loading
}
loading={objectFormState.editLoading} loading={objectFormState.editLoading}
/> />
<ObjectTableNavigationButtons <ObjectTableNavigationButtons
disabled={objectFormState.loading} disabled={objectFormState.loading || objectFormState.isEditing}
_id={productCategoryId} _id={productCategoryId}
objectType='productCategory' objectType='productCategory'
showEndingDivider={true} showEndingDivider={true}

View File

@ -123,11 +123,13 @@ const ProductSkuInfo = () => {
}} }}
editLoading={objectFormState.editLoading} editLoading={objectFormState.editLoading}
formValid={objectFormState.formValid} formValid={objectFormState.formValid}
disabled={objectFormState.beingEditedByOther || objectFormState.loading} disabled={
objectFormState.beingEditedByOther || objectFormState.loading
}
loading={objectFormState.editLoading} loading={objectFormState.editLoading}
/> />
<ObjectTableNavigationButtons <ObjectTableNavigationButtons
disabled={objectFormState.loading} disabled={objectFormState.loading || objectFormState.isEditing}
_id={productSkuId} _id={productSkuId}
objectType='productSku' objectType='productSku'
showEndingDivider={true} showEndingDivider={true}

View File

@ -121,11 +121,13 @@ const ProductInfo = () => {
}} }}
editLoading={objectFormState.editLoading} editLoading={objectFormState.editLoading}
formValid={objectFormState.formValid} formValid={objectFormState.formValid}
disabled={objectFormState.beingEditedByOther || objectFormState.loading} disabled={
objectFormState.beingEditedByOther || objectFormState.loading
}
loading={objectFormState.editLoading} loading={objectFormState.editLoading}
/> />
<ObjectTableNavigationButtons <ObjectTableNavigationButtons
disabled={objectFormState.loading} disabled={objectFormState.loading || objectFormState.isEditing}
_id={productId} _id={productId}
objectType='product' objectType='product'
showEndingDivider={true} showEndingDivider={true}

View File

@ -120,11 +120,13 @@ const TaxRateInfo = () => {
}} }}
editLoading={objectFormState.editLoading} editLoading={objectFormState.editLoading}
formValid={objectFormState.formValid} formValid={objectFormState.formValid}
disabled={objectFormState.beingEditedByOther || objectFormState.loading} disabled={
objectFormState.beingEditedByOther || objectFormState.loading
}
loading={objectFormState.editLoading} loading={objectFormState.editLoading}
/> />
<ObjectTableNavigationButtons <ObjectTableNavigationButtons
disabled={objectFormState.loading} disabled={objectFormState.loading || objectFormState.isEditing}
_id={taxRateId} _id={taxRateId}
objectType='taxRate' objectType='taxRate'
showEndingDivider={true} showEndingDivider={true}

View File

@ -126,11 +126,13 @@ const UserInfo = () => {
}} }}
editLoading={objectFormState.editLoading} editLoading={objectFormState.editLoading}
formValid={objectFormState.formValid} formValid={objectFormState.formValid}
disabled={objectFormState.beingEditedByOther || objectFormState.loading} disabled={
objectFormState.beingEditedByOther || objectFormState.loading
}
loading={objectFormState.editLoading} loading={objectFormState.editLoading}
/> />
<ObjectTableNavigationButtons <ObjectTableNavigationButtons
disabled={objectFormState.loading} disabled={objectFormState.loading || objectFormState.isEditing}
_id={userId} _id={userId}
objectType='user' objectType='user'
showEndingDivider={true} showEndingDivider={true}

View File

@ -120,11 +120,13 @@ const VendorInfo = () => {
}} }}
editLoading={objectFormState.editLoading} editLoading={objectFormState.editLoading}
formValid={objectFormState.formValid} formValid={objectFormState.formValid}
disabled={objectFormState.beingEditedByOther || objectFormState.loading} disabled={
objectFormState.beingEditedByOther || objectFormState.loading
}
loading={objectFormState.editLoading} loading={objectFormState.editLoading}
/> />
<ObjectTableNavigationButtons <ObjectTableNavigationButtons
disabled={objectFormState.loading} disabled={objectFormState.loading || objectFormState.isEditing}
_id={vendorId} _id={vendorId}
objectType='vendor' objectType='vendor'
showEndingDivider={true} showEndingDivider={true}

View File

@ -129,11 +129,13 @@ const GCodeFileInfo = () => {
}} }}
editLoading={objectFormState.editLoading} editLoading={objectFormState.editLoading}
formValid={objectFormState.formValid} formValid={objectFormState.formValid}
disabled={objectFormState.beingEditedByOther || objectFormState.loading} disabled={
objectFormState.beingEditedByOther || objectFormState.loading
}
loading={objectFormState.editLoading} loading={objectFormState.editLoading}
/> />
<ObjectTableNavigationButtons <ObjectTableNavigationButtons
disabled={objectFormState.loading} disabled={objectFormState.loading || objectFormState.isEditing}
_id={gcodeFileId} _id={gcodeFileId}
objectType='gcodeFile' objectType='gcodeFile'
showEndingDivider={true} showEndingDivider={true}

View File

@ -147,7 +147,7 @@ const JobInfo = () => {
loading={objectFormState.editLoading} loading={objectFormState.editLoading}
/> />
<ObjectTableNavigationButtons <ObjectTableNavigationButtons
disabled={objectFormState.loading} disabled={objectFormState.loading || objectFormState.isEditing}
_id={jobId} _id={jobId}
objectType='job' objectType='job'
showEndingDivider={true} showEndingDivider={true}

View File

@ -137,7 +137,7 @@ const PrinterInfo = () => {
loading={objectFormState.editLoading} loading={objectFormState.editLoading}
/> />
<ObjectTableNavigationButtons <ObjectTableNavigationButtons
disabled={objectFormState.loading} disabled={objectFormState.loading || objectFormState.isEditing}
_id={printerId} _id={printerId}
objectType='printer' objectType='printer'
showEndingDivider={true} showEndingDivider={true}

View File

@ -117,7 +117,7 @@ const SubJobInfo = () => {
loading={objectFormState.editLoading} loading={objectFormState.editLoading}
/> />
<ObjectTableNavigationButtons <ObjectTableNavigationButtons
disabled={objectFormState.loading} disabled={objectFormState.loading || objectFormState.isEditing}
_id={subJobId} _id={subJobId}
objectType='subJob' objectType='subJob'
showEndingDivider={true} showEndingDivider={true}

View File

@ -120,11 +120,13 @@ const ClientInfo = () => {
}} }}
editLoading={objectFormState.editLoading} editLoading={objectFormState.editLoading}
formValid={objectFormState.formValid} formValid={objectFormState.formValid}
disabled={objectFormState.beingEditedByOther || objectFormState.loading} disabled={
objectFormState.beingEditedByOther || objectFormState.loading
}
loading={objectFormState.editLoading} loading={objectFormState.editLoading}
/> />
<ObjectTableNavigationButtons <ObjectTableNavigationButtons
disabled={objectFormState.loading} disabled={objectFormState.loading || objectFormState.isEditing}
_id={clientId} _id={clientId}
objectType='client' objectType='client'
showEndingDivider={true} showEndingDivider={true}

View File

@ -137,11 +137,13 @@ const ListingVarientInfo = () => {
}} }}
editLoading={objectFormState.editLoading} editLoading={objectFormState.editLoading}
formValid={objectFormState.formValid} formValid={objectFormState.formValid}
disabled={objectFormState.beingEditedByOther || objectFormState.loading} disabled={
objectFormState.beingEditedByOther || objectFormState.loading
}
loading={objectFormState.editLoading} loading={objectFormState.editLoading}
/> />
<ObjectTableNavigationButtons <ObjectTableNavigationButtons
disabled={objectFormState.loading} disabled={objectFormState.loading || objectFormState.isEditing}
_id={listingVarientId} _id={listingVarientId}
objectType='listingVarient' objectType='listingVarient'
showEndingDivider={true} showEndingDivider={true}

View File

@ -142,11 +142,13 @@ const ListingInfo = () => {
}} }}
editLoading={objectFormState.editLoading} editLoading={objectFormState.editLoading}
formValid={objectFormState.formValid} formValid={objectFormState.formValid}
disabled={objectFormState.beingEditedByOther || objectFormState.loading} disabled={
objectFormState.beingEditedByOther || objectFormState.loading
}
loading={objectFormState.editLoading} loading={objectFormState.editLoading}
/> />
<ObjectTableNavigationButtons <ObjectTableNavigationButtons
disabled={objectFormState.loading} disabled={objectFormState.loading || objectFormState.isEditing}
_id={listingId} _id={listingId}
objectType='listing' objectType='listing'
showEndingDivider={true} showEndingDivider={true}

View File

@ -210,11 +210,13 @@ const MarketplaceInfo = () => {
}} }}
editLoading={objectFormState.editLoading} editLoading={objectFormState.editLoading}
formValid={objectFormState.formValid} formValid={objectFormState.formValid}
disabled={objectFormState.beingEditedByOther || objectFormState.loading} disabled={
objectFormState.beingEditedByOther || objectFormState.loading
}
loading={objectFormState.editLoading} loading={objectFormState.editLoading}
/> />
<ObjectTableNavigationButtons <ObjectTableNavigationButtons
disabled={objectFormState.loading} disabled={objectFormState.loading || objectFormState.isEditing}
_id={marketplaceId} _id={marketplaceId}
objectType='marketplace' objectType='marketplace'
showEndingDivider={true} showEndingDivider={true}

View File

@ -194,7 +194,7 @@ const SalesOrderInfo = () => {
loading={objectFormState.editLoading} loading={objectFormState.editLoading}
/> />
<ObjectTableNavigationButtons <ObjectTableNavigationButtons
disabled={objectFormState.loading} disabled={objectFormState.loading || objectFormState.isEditing}
_id={salesOrderId} _id={salesOrderId}
objectType='salesOrder' objectType='salesOrder'
showEndingDivider={true} showEndingDivider={true}

View File

@ -1,62 +1,76 @@
import { useEffect, useRef, cloneElement, useCallback } from 'react' import { useEffect, useRef, cloneElement, useMemo, useState } from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import { Popover, Typography } from 'antd' import { Popover, Typography } from 'antd'
// Utility to parse shortcut string like 'cmd+shift+p' or 'ctrl+s' const MODIFIER_ALIASES = {
cmd: 'meta',
meta: 'meta',
ctrl: 'control',
control: 'control',
alt: 'alt',
option: 'alt',
shift: 'shift'
}
function parseShortcut(shortcut) { function parseShortcut(shortcut) {
const parts = shortcut.toLowerCase().split('+') return shortcut
return { .toLowerCase()
meta: parts.includes('cmd') || parts.includes('meta') || false, .split('+')
ctrl: parts.includes('ctrl') || parts.includes('control') || false, .map((part) => MODIFIER_ALIASES[part] ?? part)
alt: parts.includes('alt') || parts.includes('option') || false, }
shift: parts.includes('shift') || false,
key: parts.find( function getPressedKey(event) {
(p) => if (
!['cmd', 'meta', 'ctrl', 'control', 'alt', 'option', 'shift'].includes( event.key === 'Meta' ||
p event.key === 'Control' ||
) event.key === 'Alt' ||
)[0] event.key === 'Shift'
) {
return event.key.toLowerCase()
} }
if (event.code) {
const code = event.code.toLowerCase()
if (code.startsWith('key')) {
return code.slice(3)
}
return code
}
return null
} }
const { Text } = Typography const { Text } = Typography
const KeyboardShortcut = ({ shortcut, children, hint, onTrigger }) => { const KeyboardShortcut = ({
shortcut,
children,
hint,
onTrigger,
log = false
}) => {
const childRef = useRef() const childRef = useRef()
const shortcutObj = parseShortcut(shortcut) const pressedKeysRef = useRef(new Set())
const shortcutKeys = useMemo(() => parseShortcut(shortcut), [shortcut])
// Helper to get the set of keys required for the shortcut const [pressedKeys, setPressedKeys] = useState([])
const getShortcutKeySet = useCallback((shortcutObj) => {
const keys = []
if (shortcutObj.meta) keys.push('Meta')
if (shortcutObj.ctrl) keys.push('Control')
if (shortcutObj.alt) keys.push('Alt')
if (shortcutObj.shift) keys.push('Shift')
// shortcutObj.code is like 'keyp', so extract the last char
if (shortcutObj.key) {
keys.push('Key' + shortcutObj.key.toUpperCase())
}
return new Set(keys)
}, [])
const shortcutKeySet = getShortcutKeySet(shortcutObj)
useEffect(() => { useEffect(() => {
const pressedKeys = new Set() const syncPressedKeys = () => {
setPressedKeys([...pressedKeysRef.current])
}
const handleKeyDown = (event) => { const handleKeyDown = (event) => {
if ( const key = getPressedKey(event)
event.key === 'Meta' || if (key) {
event.key === 'Control' || pressedKeysRef.current.add(key)
event.key === 'Alt' || syncPressedKeys()
event.key === 'Shift'
) {
pressedKeys.add(event.key)
} else if (event.code && event.code.startsWith('Key')) {
pressedKeys.add(event.code)
} }
if (log) {
console.log('Key Down:', key, 'Pressed Keys:', [...pressedKeysRef.current])
}
if ( if (
shortcutKeySet.size && shortcutKeys.length &&
[...shortcutKeySet].every((k) => pressedKeys.has(k)) shortcutKeys.every((k) => pressedKeysRef.current.has(k))
) { ) {
if (typeof onTrigger === 'function') { if (typeof onTrigger === 'function') {
onTrigger(event) onTrigger(event)
@ -64,27 +78,24 @@ const KeyboardShortcut = ({ shortcut, children, hint, onTrigger }) => {
event.preventDefault() event.preventDefault()
} }
} }
const handleKeyUp = (event) => { const handleKeyUp = (event) => {
if ( const key = getPressedKey(event)
event.key === 'Meta' || if (key) {
event.key === 'Control' || pressedKeysRef.current.delete(key)
event.key === 'Alt' || syncPressedKeys()
event.key === 'Shift'
) {
pressedKeys.delete(event.key)
} else if (event.code && event.code.startsWith('Key')) {
pressedKeys.delete(event.key.toUpperCase())
} }
} }
window.addEventListener('keydown', handleKeyDown) window.addEventListener('keydown', handleKeyDown)
window.addEventListener('keyup', handleKeyUp) window.addEventListener('keyup', handleKeyUp)
return () => { return () => {
window.removeEventListener('keydown', handleKeyDown) window.removeEventListener('keydown', handleKeyDown)
window.removeEventListener('keyup', handleKeyUp) window.removeEventListener('keyup', handleKeyUp)
} }
}, [shortcut, shortcutObj, onTrigger, shortcutKeySet]) }, [shortcutKeys, onTrigger, log])
// Clone the child to attach a ref
const element = cloneElement(children, { ref: childRef }) const element = cloneElement(children, { ref: childRef })
if (hint) { if (hint) {
@ -108,7 +119,8 @@ KeyboardShortcut.propTypes = {
shortcut: PropTypes.string.isRequired, // e.g. 'cmd+shift+p' shortcut: PropTypes.string.isRequired, // e.g. 'cmd+shift+p'
onTrigger: PropTypes.func.isRequired, onTrigger: PropTypes.func.isRequired,
children: PropTypes.element.isRequired, children: PropTypes.element.isRequired,
hint: PropTypes.string // Optional, e.g. ' P' hint: PropTypes.string, // Optional, e.g. ' P'
log: PropTypes.bool // Optional, e.g. true
} }
export default KeyboardShortcut export default KeyboardShortcut

View File

@ -7,6 +7,7 @@ import PropTypes from 'prop-types'
import { ApiServerContext } from '../context/ApiServerContext' import { ApiServerContext } from '../context/ApiServerContext'
import { AuthContext } from '../context/AuthContext' import { AuthContext } from '../context/AuthContext'
import { useTableStatePersistence } from '../context/TableStateContext' import { useTableStatePersistence } from '../context/TableStateContext'
import KeyboardShortcut from './KeyboardShortcut.jsx'
const ObjectTableNavigationButtons = ({ const ObjectTableNavigationButtons = ({
disabled, disabled,
@ -95,16 +96,36 @@ const ObjectTableNavigationButtons = ({
<Divider type='vertical' style={{ margin: '0 4px', height: '18px' }} /> <Divider type='vertical' style={{ margin: '0 4px', height: '18px' }} />
)} )}
<Space size='small'> <Space size='small'>
<Button <KeyboardShortcut
icon={<ArrowLeftIcon />} shortcut='alt+arrowleft'
onClick={handlePrevious} hint='ALT LEFT'
disabled={disabled || loading || !neighbors.previous?._id} onTrigger={useCallback(() => {
/> if (!disabled && !loading && neighbors.previous?._id) {
<Button handlePrevious()
icon={<ArrowRightIcon />} }
onClick={handleNext} }, [disabled, loading, neighbors.previous?._id])}
disabled={disabled || loading || !neighbors.next?._id} >
/> <Button
icon={<ArrowLeftIcon />}
onClick={handlePrevious}
disabled={disabled || loading || !neighbors.previous?._id}
/>
</KeyboardShortcut>
<KeyboardShortcut
shortcut='alt+arrowright'
hint='ALT RIGHT'
onTrigger={useCallback(() => {
if (!disabled && !loading && neighbors.next?._id) {
handleNext()
}
}, [disabled, loading, neighbors.next?._id])}
>
<Button
icon={<ArrowRightIcon />}
onClick={handleNext}
disabled={disabled || loading || !neighbors.next?._id}
/>
</KeyboardShortcut>
</Space> </Space>
</Flex> </Flex>
) )