From 19ca7bffae9ebb23e475ee79f7b460193c0d96ce Mon Sep 17 00:00:00 2001 From: Oliver Date: Wed, 14 Aug 2024 20:12:51 +1000 Subject: [PATCH] [PUI] Edit shortcut (#7870) * Adds shortcut to edit item on * Add hooks for shortcut key * Add unit tests for edit shortcut --- src/frontend/src/components/nav/PageDetail.tsx | 18 +++++++++++++++++- src/frontend/src/pages/build/BuildDetail.tsx | 2 ++ .../src/pages/company/CompanyDetail.tsx | 2 ++ .../pages/company/ManufacturerPartDetail.tsx | 2 ++ .../src/pages/company/SupplierPartDetail.tsx | 2 ++ src/frontend/src/pages/part/CategoryDetail.tsx | 2 ++ src/frontend/src/pages/part/PartDetail.tsx | 2 ++ .../pages/purchasing/PurchaseOrderDetail.tsx | 2 ++ .../src/pages/sales/ReturnOrderDetail.tsx | 2 ++ .../src/pages/sales/SalesOrderDetail.tsx | 2 ++ .../src/pages/stock/LocationDetail.tsx | 2 ++ src/frontend/src/pages/stock/StockDetail.tsx | 2 ++ src/frontend/tests/pages/pui_build.spec.ts | 7 +++++++ src/frontend/tests/pages/pui_part.spec.ts | 9 +++++++++ 14 files changed, 55 insertions(+), 1 deletion(-) diff --git a/src/frontend/src/components/nav/PageDetail.tsx b/src/frontend/src/components/nav/PageDetail.tsx index d3f3d50478..de7a36556a 100644 --- a/src/frontend/src/components/nav/PageDetail.tsx +++ b/src/frontend/src/components/nav/PageDetail.tsx @@ -1,4 +1,5 @@ import { Group, Paper, Space, Stack, Text } from '@mantine/core'; +import { useHotkeys } from '@mantine/hooks'; import { Fragment, ReactNode } from 'react'; import { ApiImage } from '../images/ApiImage'; @@ -15,6 +16,8 @@ interface PageDetailInterface { breadcrumbs?: Breadcrumb[]; breadcrumbAction?: () => void; actions?: ReactNode[]; + editAction?: () => void; + editEnabled?: boolean; } /** @@ -32,8 +35,21 @@ export function PageDetail({ imageUrl, breadcrumbs, breadcrumbAction, - actions + actions, + editAction, + editEnabled }: Readonly) { + useHotkeys([ + [ + 'mod+E', + () => { + if (editEnabled ?? true) { + editAction?.(); + } + } + ] + ]); + return ( {breadcrumbs && breadcrumbs.length > 0 && ( diff --git a/src/frontend/src/pages/build/BuildDetail.tsx b/src/frontend/src/pages/build/BuildDetail.tsx index 3a2773c052..9bb2566000 100644 --- a/src/frontend/src/pages/build/BuildDetail.tsx +++ b/src/frontend/src/pages/build/BuildDetail.tsx @@ -542,6 +542,8 @@ export default function BuildDetail() { title={build.reference} subtitle={build.title} badges={buildBadges} + editAction={editBuild.open} + editEnabled={user.hasChangePermission(ModelType.part)} imageUrl={build.part_detail?.image ?? build.part_detail?.thumbnail} breadcrumbs={[ { name: t`Build Orders`, url: '/build' }, diff --git a/src/frontend/src/pages/company/CompanyDetail.tsx b/src/frontend/src/pages/company/CompanyDetail.tsx index 39070a0814..dab24dd724 100644 --- a/src/frontend/src/pages/company/CompanyDetail.tsx +++ b/src/frontend/src/pages/company/CompanyDetail.tsx @@ -330,6 +330,8 @@ export default function CompanyDetail(props: Readonly) { imageUrl={company.image} breadcrumbs={props.breadcrumbs} badges={badges} + editAction={editCompany.open} + editEnabled={user.hasChangePermission(ModelType.company)} /> diff --git a/src/frontend/src/pages/company/ManufacturerPartDetail.tsx b/src/frontend/src/pages/company/ManufacturerPartDetail.tsx index bb97ac4300..d1120c32f9 100644 --- a/src/frontend/src/pages/company/ManufacturerPartDetail.tsx +++ b/src/frontend/src/pages/company/ManufacturerPartDetail.tsx @@ -283,6 +283,8 @@ export default function ManufacturerPartDetail() { breadcrumbs={breadcrumbs} actions={manufacturerPartActions} imageUrl={manufacturerPart?.part_detail?.thumbnail} + editAction={editManufacturerPart.open} + editEnabled={user.hasChangePermission(ModelType.manufacturerpart)} /> diff --git a/src/frontend/src/pages/company/SupplierPartDetail.tsx b/src/frontend/src/pages/company/SupplierPartDetail.tsx index 4cd97e537c..f519e2d761 100644 --- a/src/frontend/src/pages/company/SupplierPartDetail.tsx +++ b/src/frontend/src/pages/company/SupplierPartDetail.tsx @@ -375,6 +375,8 @@ export default function SupplierPartDetail() { badges={badges} actions={supplierPartActions} imageUrl={supplierPart?.part_detail?.thumbnail} + editAction={editSupplierPart.open} + editEnabled={user.hasChangePermission(ModelType.supplierpart)} /> diff --git a/src/frontend/src/pages/part/CategoryDetail.tsx b/src/frontend/src/pages/part/CategoryDetail.tsx index d135805942..2f0c8f6ada 100644 --- a/src/frontend/src/pages/part/CategoryDetail.tsx +++ b/src/frontend/src/pages/part/CategoryDetail.tsx @@ -310,6 +310,8 @@ export default function CategoryDetail() { setTreeOpen(true); }} actions={categoryActions} + editAction={editCategory.open} + editEnabled={user.hasChangePermission(ModelType.partcategory)} /> diff --git a/src/frontend/src/pages/part/PartDetail.tsx b/src/frontend/src/pages/part/PartDetail.tsx index 638f156e5d..988418e965 100644 --- a/src/frontend/src/pages/part/PartDetail.tsx +++ b/src/frontend/src/pages/part/PartDetail.tsx @@ -1057,6 +1057,8 @@ export default function PartDetail() { breadcrumbAction={() => { setTreeOpen(true); }} + editAction={editPart.open} + editEnabled={user.hasChangeRole(UserRoles.part)} actions={partActions} detail={ enableRevisionSelection ? ( diff --git a/src/frontend/src/pages/purchasing/PurchaseOrderDetail.tsx b/src/frontend/src/pages/purchasing/PurchaseOrderDetail.tsx index 1eda995305..3a68a21023 100644 --- a/src/frontend/src/pages/purchasing/PurchaseOrderDetail.tsx +++ b/src/frontend/src/pages/purchasing/PurchaseOrderDetail.tsx @@ -442,6 +442,8 @@ export default function PurchaseOrderDetail() { breadcrumbs={[{ name: t`Purchasing`, url: '/purchasing/' }]} actions={poActions} badges={orderBadges} + editAction={editPurchaseOrder.open} + editEnabled={user.hasChangePermission(ModelType.purchaseorder)} /> diff --git a/src/frontend/src/pages/sales/ReturnOrderDetail.tsx b/src/frontend/src/pages/sales/ReturnOrderDetail.tsx index d685862b26..c892f62302 100644 --- a/src/frontend/src/pages/sales/ReturnOrderDetail.tsx +++ b/src/frontend/src/pages/sales/ReturnOrderDetail.tsx @@ -430,6 +430,8 @@ export default function ReturnOrderDetail() { badges={orderBadges} actions={orderActions} breadcrumbs={[{ name: t`Sales`, url: '/sales/' }]} + editAction={editReturnOrder.open} + editEnabled={user.hasChangePermission(ModelType.returnorder)} /> diff --git a/src/frontend/src/pages/sales/SalesOrderDetail.tsx b/src/frontend/src/pages/sales/SalesOrderDetail.tsx index e2e38de37e..cd1467e0c6 100644 --- a/src/frontend/src/pages/sales/SalesOrderDetail.tsx +++ b/src/frontend/src/pages/sales/SalesOrderDetail.tsx @@ -482,6 +482,8 @@ export default function SalesOrderDetail() { badges={orderBadges} actions={soActions} breadcrumbs={[{ name: t`Sales`, url: '/sales/' }]} + editAction={editSalesOrder.open} + editEnabled={user.hasChangePermission(ModelType.salesorder)} /> diff --git a/src/frontend/src/pages/stock/LocationDetail.tsx b/src/frontend/src/pages/stock/LocationDetail.tsx index 3d2b405114..1bb074b9d5 100644 --- a/src/frontend/src/pages/stock/LocationDetail.tsx +++ b/src/frontend/src/pages/stock/LocationDetail.tsx @@ -388,6 +388,8 @@ export default function Stock() { subtitle={location?.name} icon={location?.icon && } actions={locationActions} + editAction={editLocation.open} + editEnabled={user.hasChangePermission(ModelType.stocklocation)} breadcrumbs={breadcrumbs} breadcrumbAction={() => { setTreeOpen(true); diff --git a/src/frontend/src/pages/stock/StockDetail.tsx b/src/frontend/src/pages/stock/StockDetail.tsx index 1f5083bbb6..2730f12ee9 100644 --- a/src/frontend/src/pages/stock/StockDetail.tsx +++ b/src/frontend/src/pages/stock/StockDetail.tsx @@ -621,6 +621,8 @@ export default function StockDetail() { title={t`Stock Item`} subtitle={stockitem.part_detail?.full_name} imageUrl={stockitem.part_detail?.thumbnail} + editAction={editStockItem.open} + editEnabled={user.hasChangePermission(ModelType.stockitem)} badges={stockBadges} breadcrumbs={breadcrumbs} breadcrumbAction={() => { diff --git a/src/frontend/tests/pages/pui_build.spec.ts b/src/frontend/tests/pages/pui_build.spec.ts index 14cc5e4c46..f36f740049 100644 --- a/src/frontend/tests/pages/pui_build.spec.ts +++ b/src/frontend/tests/pages/pui_build.spec.ts @@ -19,6 +19,13 @@ test('PUI - Pages - Build Order', async ({ page }) => { // This build order should be "on hold" await page.getByText('On Hold').first().waitFor(); + + // Edit the build order (via keyboard shortcut) + await page.keyboard.press('Control+E'); + await page.getByLabel('text-field-title').waitFor(); + await page.getByLabel('related-field-project_code').waitFor(); + await page.getByRole('button', { name: 'Cancel' }).click(); + await page.getByRole('button', { name: 'Issue Order' }).click(); await page.getByRole('button', { name: 'Cancel' }).click(); diff --git a/src/frontend/tests/pages/pui_part.spec.ts b/src/frontend/tests/pages/pui_part.spec.ts index 025bcc73b9..3f56ec6e7e 100644 --- a/src/frontend/tests/pages/pui_part.spec.ts +++ b/src/frontend/tests/pages/pui_part.spec.ts @@ -226,6 +226,15 @@ test('PUI - Pages - Part - Notes', async ({ page }) => { await page.goto(`${baseUrl}/part/69/notes`); // Enable editing + await page.getByLabel('toggle-notes-editing').waitFor(); + + // Use keyboard shortcut to "edit" the part + await page.keyboard.press('Control+E'); + await page.getByLabel('text-field-name').waitFor(); + await page.getByLabel('text-field-description').waitFor(); + await page.getByLabel('related-field-category').waitFor(); + await page.getByRole('button', { name: 'Cancel' }).click(); + await page.getByLabel('toggle-notes-editing').click(); // Enter some text