From 0cb4e8ec1c6b4275d2051ed95a9599402f56e32c Mon Sep 17 00:00:00 2001 From: Oliver Date: Wed, 20 Mar 2024 21:56:32 +1100 Subject: [PATCH] [PUI] table fixes (#6764) * Impove link rendering in attachment table * Add "updateRecord" hook for useTable * Refactoring Make use of new table.updateRecord method * Refactor model row clicks - Just need to provide a model type * Fix BuildLineTable * Re-add required imports * Remove hard-coded paths --- .../src/components/details/Details.tsx | 3 +- .../src/components/items/AttachmentLink.tsx | 16 ++++++--- src/frontend/src/forms/AttachmentForms.tsx | 2 +- src/frontend/src/hooks/UseTable.tsx | 23 ++++++++++++- src/frontend/src/tables/InvenTreeTable.tsx | 33 ++++++++++++++++++- src/frontend/src/tables/bom/BomTable.tsx | 8 ++--- src/frontend/src/tables/bom/UsedInTable.tsx | 6 +--- .../src/tables/build/BuildOrderTable.tsx | 2 +- .../src/tables/company/AddressTable.tsx | 2 +- .../src/tables/company/CompanyTable.tsx | 1 + .../src/tables/company/ContactTable.tsx | 2 +- .../src/tables/general/AttachmentTable.tsx | 7 ++-- .../src/tables/part/ParametricPartTable.tsx | 9 +---- .../src/tables/part/PartCategoryTable.tsx | 5 ++- .../part/PartParameterTemplateTable.tsx | 2 +- src/frontend/src/tables/part/PartTable.tsx | 8 ++--- .../src/tables/part/PartTestTemplateTable.tsx | 2 +- .../purchasing/ManufacturerPartTable.tsx | 10 +----- .../purchasing/PurchaseOrderLineItemTable.tsx | 9 +---- .../tables/purchasing/PurchaseOrderTable.tsx | 6 +--- .../tables/purchasing/SupplierPartTable.tsx | 9 +---- .../src/tables/sales/ReturnOrderTable.tsx | 10 +----- .../src/tables/sales/SalesOrderTable.tsx | 6 +--- .../src/tables/settings/CustomUnitsTable.tsx | 2 +- .../src/tables/settings/ProjectCodeTable.tsx | 2 +- .../src/tables/stock/InstalledItemsTable.tsx | 9 +---- .../src/tables/stock/StockItemTable.tsx | 3 +- .../src/tables/stock/StockLocationTable.tsx | 6 ++-- 28 files changed, 99 insertions(+), 104 deletions(-) diff --git a/src/frontend/src/components/details/Details.tsx b/src/frontend/src/components/details/Details.tsx index c2587b9ecd..c4867c9aa3 100644 --- a/src/frontend/src/components/details/Details.tsx +++ b/src/frontend/src/components/details/Details.tsx @@ -20,6 +20,7 @@ import { ApiEndpoints } from '../../enums/ApiEndpoints'; import { ModelType } from '../../enums/ModelType'; import { InvenTreeIcon, InvenTreeIconType } from '../../functions/icons'; import { getDetailUrl } from '../../functions/urls'; +import { base_url } from '../../main'; import { apiUrl } from '../../states/ApiState'; import { useGlobalSettingsState } from '../../states/SettingsState'; import { ProgressBar } from '../items/ProgressBar'; @@ -292,7 +293,7 @@ function TableAnchorValue(props: FieldProps) { }> {make_link ? ( diff --git a/src/frontend/src/components/items/AttachmentLink.tsx b/src/frontend/src/components/items/AttachmentLink.tsx index c68cc0dff1..81b79346b3 100644 --- a/src/frontend/src/components/items/AttachmentLink.tsx +++ b/src/frontend/src/components/items/AttachmentLink.tsx @@ -1,5 +1,5 @@ -import { Group, Text } from '@mantine/core'; -import { IconPhoto } from '@tabler/icons-react'; +import { Anchor, Group, Text } from '@mantine/core'; +import { IconLink, IconPhoto } from '@tabler/icons-react'; import { IconFile, IconFileTypeCsv, @@ -50,14 +50,20 @@ export function attachmentIcon(attachment: string): ReactNode { * @param attachment : string - The attachment filename */ export function AttachmentLink({ - attachment + attachment, + external }: { attachment: string; + external?: boolean; }): ReactNode { + let text = external ? attachment : attachment.split('/').pop(); + return ( - {attachmentIcon(attachment)} - {attachment.split('/').pop()} + {external ? : attachmentIcon(attachment)} + + {text} + ); } diff --git a/src/frontend/src/forms/AttachmentForms.tsx b/src/frontend/src/forms/AttachmentForms.tsx index 652b358a0b..4e10655337 100644 --- a/src/frontend/src/forms/AttachmentForms.tsx +++ b/src/frontend/src/forms/AttachmentForms.tsx @@ -80,7 +80,7 @@ export function editAttachment({ model: string; pk: number; attachmentType: 'file' | 'link'; - callback?: () => void; + callback?: (record: any) => void; }) { let formFields: ApiFormFieldSet = { link: {}, diff --git a/src/frontend/src/hooks/UseTable.tsx b/src/frontend/src/hooks/UseTable.tsx index 94d97b5f22..010085861b 100644 --- a/src/frontend/src/hooks/UseTable.tsx +++ b/src/frontend/src/hooks/UseTable.tsx @@ -34,6 +34,7 @@ export type TableState = { setPage: (page: number) => void; records: any[]; setRecords: (records: any[]) => void; + updateRecord: (record: any) => void; }; /** @@ -95,6 +96,25 @@ export function useTable(tableName: string): TableState { // Table records const [records, setRecords] = useState([]); + // Update a single record in the table, by primary key value + const updateRecord = useCallback( + (record: any) => { + let _records = [...records]; + + // Find the matching record in the table + const index = _records.findIndex((r) => r.pk === record.pk); + + if (index >= 0) { + _records[index] = record; + } else { + _records.push(record); + } + + setRecords(_records); + }, + [records] + ); + return { tableKey, refreshTable, @@ -115,6 +135,7 @@ export function useTable(tableName: string): TableState { page, setPage, records, - setRecords + setRecords, + updateRecord }; } diff --git a/src/frontend/src/tables/InvenTreeTable.tsx b/src/frontend/src/tables/InvenTreeTable.tsx index 7d3ba4b598..3ec48c2444 100644 --- a/src/frontend/src/tables/InvenTreeTable.tsx +++ b/src/frontend/src/tables/InvenTreeTable.tsx @@ -21,13 +21,17 @@ import { DataTableSortStatus } from 'mantine-datatable'; import { Fragment, useCallback, useEffect, useMemo, useState } from 'react'; +import { useNavigate } from 'react-router-dom'; import { api } from '../App'; import { ActionButton } from '../components/buttons/ActionButton'; import { ButtonMenu } from '../components/buttons/ButtonMenu'; import { ApiFormFieldSet } from '../components/forms/fields/ApiFormField'; +import { ModelType } from '../enums/ModelType'; import { extractAvailableFields, mapFields } from '../functions/forms'; +import { getDetailUrl } from '../functions/urls'; import { TableState } from '../hooks/UseTable'; +import { base_url } from '../main'; import { useLocalState } from '../states/LocalState'; import { TableColumn } from './Column'; import { TableColumnSelect } from './ColumnSelect'; @@ -62,6 +66,7 @@ const defaultPageSize: number = 25; * @param rowActions : (record: any) => RowAction[] - Callback function to generate row actions * @param onRowClick : (record: any, index: number, event: any) => void - Callback function when a row is clicked * @param onCellClick : (event: any, record: any, recordIndex: number, column: any, columnIndex: number) => void - Callback function when a cell is clicked + * @param modelType: ModelType - The model type for the table */ export type InvenTreeTableProps = { params?: any; @@ -85,6 +90,7 @@ export type InvenTreeTableProps = { rowActions?: (record: T) => RowAction[]; onRowClick?: (record: T, index: number, event: any) => void; onCellClick?: DataTableCellClickHandler; + modelType?: ModelType; }; /** @@ -125,6 +131,8 @@ export function InvenTreeTable({ const { getTableColumnNames, setTableColumnNames } = useLocalState(); const [fieldNames, setFieldNames] = useState>({}); + const navigate = useNavigate(); + // Construct table filters - note that we can introspect filter labels from column names const filters: TableFilter[] = useMemo(() => { return ( @@ -501,6 +509,29 @@ export function InvenTreeTable({ }); }, [tableState.selectedRecords]); + // Callback when a row is clicked + const handleRowClick = useCallback( + (record: any, index: number, event: any) => { + if (props.onRowClick) { + // If a custom row click handler is provided, use that + props.onRowClick(record, index, event); + } else if (tableProps.modelType && record?.pk) { + // If a model type is provided, navigate to the detail view for that model + let url = getDetailUrl(tableProps.modelType, record.pk); + + // Should it be opened in a new tab? + if (event?.ctrlKey || event?.shiftKey || event?.buttons & 0x04) { + // Open in a new tab + window.open(`/${base_url}{url}`, '_blank', 'noreferrer'); + } else { + // Navigate internally + navigate(url); + } + } + }, + [props.onRowClick] + ); + return ( <> {tableProps.enableFilters && (filters.length ?? 0) > 0 && ( @@ -622,7 +653,7 @@ export function InvenTreeTable({ noRecordsText={missingRecordsText} records={tableState.records} columns={dataColumns} - onRowClick={tableProps.onRowClick} + onRowClick={handleRowClick} onCellClick={tableProps.onCellClick} defaultColumnProps={{ noWrap: true, diff --git a/src/frontend/src/tables/bom/BomTable.tsx b/src/frontend/src/tables/bom/BomTable.tsx index 8eacb88e78..5c4e602526 100644 --- a/src/frontend/src/tables/bom/BomTable.tsx +++ b/src/frontend/src/tables/bom/BomTable.tsx @@ -16,7 +16,6 @@ import { ModelType } from '../../enums/ModelType'; import { UserRoles } from '../../enums/Roles'; import { bomItemFields } from '../../forms/BomForms'; import { openDeleteApiForm, openEditApiForm } from '../../functions/forms'; -import { getDetailUrl } from '../../functions/urls'; import { useTable } from '../../hooks/UseTable'; import { apiUrl } from '../../states/ApiState'; import { useUserState } from '../../states/UserState'; @@ -55,11 +54,9 @@ export function BomTable({ partId: number; params?: any; }) { - const navigate = useNavigate(); - const user = useUserState(); - const table = useTable('bom'); + const navigate = useNavigate(); const tableColumns: TableColumn[] = useMemo(() => { return [ @@ -355,8 +352,7 @@ export function BomTable({ sub_part_detail: true }, tableFilters: tableFilters, - onRowClick: (row) => - navigate(getDetailUrl(ModelType.part, row.sub_part)), + modelType: ModelType.part, rowActions: rowActions }} /> diff --git a/src/frontend/src/tables/bom/UsedInTable.tsx b/src/frontend/src/tables/bom/UsedInTable.tsx index aa7700ee1c..1033e0effb 100644 --- a/src/frontend/src/tables/bom/UsedInTable.tsx +++ b/src/frontend/src/tables/bom/UsedInTable.tsx @@ -1,11 +1,9 @@ import { t } from '@lingui/macro'; import { useMemo } from 'react'; -import { useNavigate } from 'react-router-dom'; import { PartHoverCard } from '../../components/images/Thumbnail'; import { ApiEndpoints } from '../../enums/ApiEndpoints'; import { ModelType } from '../../enums/ModelType'; -import { getDetailUrl } from '../../functions/urls'; import { useTable } from '../../hooks/UseTable'; import { apiUrl } from '../../states/ApiState'; import { TableColumn } from '../Column'; @@ -23,8 +21,6 @@ export function UsedInTable({ partId: number; params?: any; }) { - const navigate = useNavigate(); - const table = useTable('usedin'); const tableColumns: TableColumn[] = useMemo(() => { @@ -87,7 +83,7 @@ export function UsedInTable({ sub_part_detail: true }, tableFilters: tableFilters, - onRowClick: (row) => navigate(getDetailUrl(ModelType.part, row.part)) + modelType: ModelType.part }} /> ); diff --git a/src/frontend/src/tables/build/BuildOrderTable.tsx b/src/frontend/src/tables/build/BuildOrderTable.tsx index 5e5afd8b33..66a15af959 100644 --- a/src/frontend/src/tables/build/BuildOrderTable.tsx +++ b/src/frontend/src/tables/build/BuildOrderTable.tsx @@ -178,7 +178,7 @@ export function BuildOrderTable({ }, tableActions: tableActions, tableFilters: tableFilters, - onRowClick: (row) => navigate(getDetailUrl(ModelType.build, row.pk)) + modelType: ModelType.build }} /> diff --git a/src/frontend/src/tables/company/AddressTable.tsx b/src/frontend/src/tables/company/AddressTable.tsx index d05bf2d028..8a5d8fc598 100644 --- a/src/frontend/src/tables/company/AddressTable.tsx +++ b/src/frontend/src/tables/company/AddressTable.tsx @@ -134,7 +134,7 @@ export function AddressTable({ pk: selectedAddress, title: t`Edit Address`, fields: addressFields, - onFormSuccess: table.refreshTable + onFormSuccess: (record: any) => table.updateRecord(record) }); const deleteAddress = useDeleteApiFormModal({ diff --git a/src/frontend/src/tables/company/CompanyTable.tsx b/src/frontend/src/tables/company/CompanyTable.tsx index 96062212e7..82cef9f7f5 100644 --- a/src/frontend/src/tables/company/CompanyTable.tsx +++ b/src/frontend/src/tables/company/CompanyTable.tsx @@ -6,6 +6,7 @@ import { useNavigate } from 'react-router-dom'; import { AddItemButton } from '../../components/buttons/AddItemButton'; import { Thumbnail } from '../../components/images/Thumbnail'; import { ApiEndpoints } from '../../enums/ApiEndpoints'; +import { ModelType } from '../../enums/ModelType'; import { UserRoles } from '../../enums/Roles'; import { companyFields } from '../../forms/CompanyForms'; import { useCreateApiFormModal } from '../../hooks/UseForm'; diff --git a/src/frontend/src/tables/company/ContactTable.tsx b/src/frontend/src/tables/company/ContactTable.tsx index 08f2176bbd..f5a5ed7938 100644 --- a/src/frontend/src/tables/company/ContactTable.tsx +++ b/src/frontend/src/tables/company/ContactTable.tsx @@ -72,7 +72,7 @@ export function ContactTable({ pk: selectedContact, title: t`Edit Contact`, fields: contactFields, - onFormSuccess: table.refreshTable + onFormSuccess: (record: any) => table.updateRecord(record) }); const newContact = useCreateApiFormModal({ diff --git a/src/frontend/src/tables/general/AttachmentTable.tsx b/src/frontend/src/tables/general/AttachmentTable.tsx index 7a83ca0423..3996578cc6 100644 --- a/src/frontend/src/tables/general/AttachmentTable.tsx +++ b/src/frontend/src/tables/general/AttachmentTable.tsx @@ -34,8 +34,7 @@ function attachmentTableColumns(): TableColumn[] { if (record.attachment) { return ; } else if (record.link) { - // TODO: Custom renderer for links - return record.link; + return ; } else { return '-'; } @@ -121,7 +120,9 @@ export function AttachmentTable({ model: model, pk: record.pk, attachmentType: record.attachment ? 'file' : 'link', - callback: table.refreshTable + callback: (record: any) => { + table.updateRecord(record); + } }); } }) diff --git a/src/frontend/src/tables/part/ParametricPartTable.tsx b/src/frontend/src/tables/part/ParametricPartTable.tsx index ac208119d3..e0f3140491 100644 --- a/src/frontend/src/tables/part/ParametricPartTable.tsx +++ b/src/frontend/src/tables/part/ParametricPartTable.tsx @@ -4,7 +4,6 @@ import { useHover } from '@mantine/hooks'; import { IconEdit } from '@tabler/icons-react'; import { useQuery } from '@tanstack/react-query'; import { useCallback, useMemo, useState } from 'react'; -import { useNavigate } from 'react-router-dom'; import { api } from '../../App'; import { ApiFormFieldSet } from '../../components/forms/fields/ApiFormField'; @@ -12,7 +11,6 @@ import { YesNoButton } from '../../components/items/YesNoButton'; import { ApiEndpoints } from '../../enums/ApiEndpoints'; import { ModelType } from '../../enums/ModelType'; import { UserRoles } from '../../enums/Roles'; -import { getDetailUrl } from '../../functions/urls'; import { useCreateApiFormModal, useEditApiFormModal @@ -99,7 +97,6 @@ export default function ParametricPartTable({ }) { const table = useTable('parametric-parts'); const user = useUserState(); - const navigate = useNavigate(); const categoryParmeters = useQuery({ queryKey: ['category-parameters', categoryId], @@ -289,11 +286,7 @@ export default function ParametricPartTable({ category_detail: true, parameters: true }, - onRowClick: (record) => { - if (record.pk) { - navigate(getDetailUrl(ModelType.part, record.pk)); - } - } + modelType: ModelType.part }} /> diff --git a/src/frontend/src/tables/part/PartCategoryTable.tsx b/src/frontend/src/tables/part/PartCategoryTable.tsx index 4c40a569e4..7b698e72c3 100644 --- a/src/frontend/src/tables/part/PartCategoryTable.tsx +++ b/src/frontend/src/tables/part/PartCategoryTable.tsx @@ -95,7 +95,7 @@ export function PartCategoryTable({ parentId }: { parentId?: any }) { pk: selectedCategory, title: t`Edit Part Category`, fields: partCategoryFields({}), - onFormSuccess: table.refreshTable + onFormSuccess: (record: any) => table.updateRecord(record) }); const tableActions = useMemo(() => { @@ -143,8 +143,7 @@ export function PartCategoryTable({ parentId }: { parentId?: any }) { tableFilters: tableFilters, tableActions: tableActions, rowActions: rowActions, - onRowClick: (record) => - navigate(getDetailUrl(ModelType.partcategory, record.pk)) + modelType: ModelType.partcategory }} /> diff --git a/src/frontend/src/tables/part/PartParameterTemplateTable.tsx b/src/frontend/src/tables/part/PartParameterTemplateTable.tsx index 9d4651ae00..13d0fbe13a 100644 --- a/src/frontend/src/tables/part/PartParameterTemplateTable.tsx +++ b/src/frontend/src/tables/part/PartParameterTemplateTable.tsx @@ -96,7 +96,7 @@ export default function PartParameterTemplateTable() { pk: selectedTemplate, title: t`Edit Parameter Template`, fields: partParameterTemplateFields, - onFormSuccess: table.refreshTable + onFormSuccess: (record: any) => table.updateRecord(record) }); const deleteTemplate = useDeleteApiFormModal({ diff --git a/src/frontend/src/tables/part/PartTable.tsx b/src/frontend/src/tables/part/PartTable.tsx index 0b2f281888..fc3f002461 100644 --- a/src/frontend/src/tables/part/PartTable.tsx +++ b/src/frontend/src/tables/part/PartTable.tsx @@ -4,7 +4,6 @@ import { ReactNode, useMemo } from 'react'; import { useNavigate } from 'react-router-dom'; import { AddItemButton } from '../../components/buttons/AddItemButton'; -import { Thumbnail } from '../../components/images/Thumbnail'; import { formatPriceRange } from '../../defaults/formatters'; import { ApiEndpoints } from '../../enums/ApiEndpoints'; import { ModelType } from '../../enums/ModelType'; @@ -268,8 +267,8 @@ export function PartListTable({ props }: { props: InvenTreeTableProps }) { const tableFilters = useMemo(() => partTableFilters(), []); const table = useTable('part-list'); - const navigate = useNavigate(); const user = useUserState(); + const navigate = useNavigate(); const newPart = useCreateApiFormModal({ url: ApiEndpoints.part_list, @@ -305,14 +304,13 @@ export function PartListTable({ props }: { props: InvenTreeTableProps }) { props={{ ...props, enableDownload: true, + modelType: ModelType.part, tableFilters: tableFilters, tableActions: tableActions, params: { ...props.params, category_detail: true - }, - onRowClick: (record) => - navigate(getDetailUrl(ModelType.part, record.pk)) + } }} /> diff --git a/src/frontend/src/tables/part/PartTestTemplateTable.tsx b/src/frontend/src/tables/part/PartTestTemplateTable.tsx index 1a02014a1a..ebd20c08fb 100644 --- a/src/frontend/src/tables/part/PartTestTemplateTable.tsx +++ b/src/frontend/src/tables/part/PartTestTemplateTable.tsx @@ -134,7 +134,7 @@ export default function PartTestTemplateTable({ partId }: { partId: number }) { pk: selectedTest, title: t`Edit Test Template`, fields: partTestTemplateFields, - onFormSuccess: table.refreshTable + onFormSuccess: (record: any) => table.updateRecord(record) }); const deleteTestTemplate = useDeleteApiFormModal({ diff --git a/src/frontend/src/tables/purchasing/ManufacturerPartTable.tsx b/src/frontend/src/tables/purchasing/ManufacturerPartTable.tsx index 63bdd40fe0..0955afe3d5 100644 --- a/src/frontend/src/tables/purchasing/ManufacturerPartTable.tsx +++ b/src/frontend/src/tables/purchasing/ManufacturerPartTable.tsx @@ -1,6 +1,5 @@ import { t } from '@lingui/macro'; import { ReactNode, useCallback, useMemo } from 'react'; -import { useNavigate } from 'react-router-dom'; import { AddItemButton } from '../../components/buttons/AddItemButton'; import { Thumbnail } from '../../components/images/Thumbnail'; @@ -9,8 +8,6 @@ import { ModelType } from '../../enums/ModelType'; import { UserRoles } from '../../enums/Roles'; import { useManufacturerPartFields } from '../../forms/CompanyForms'; import { openDeleteApiForm, openEditApiForm } from '../../functions/forms'; -import { notYetImplemented } from '../../functions/notifications'; -import { getDetailUrl } from '../../functions/urls'; import { useCreateApiFormModal } from '../../hooks/UseForm'; import { useTable } from '../../hooks/UseTable'; import { apiUrl } from '../../states/ApiState'; @@ -27,7 +24,6 @@ export function ManufacturerPartTable({ params }: { params: any }): ReactNode { const table = useTable('manufacturerparts'); const user = useUserState(); - const navigate = useNavigate(); // Construct table columns for this table const tableColumns: TableColumn[] = useMemo(() => { @@ -139,11 +135,7 @@ export function ManufacturerPartTable({ params }: { params: any }): ReactNode { }, rowActions: rowActions, tableActions: tableActions, - onRowClick: (record: any) => { - if (record?.pk) { - navigate(getDetailUrl(ModelType.manufacturerpart, record.pk)); - } - } + modelType: ModelType.manufacturerpart }} /> diff --git a/src/frontend/src/tables/purchasing/PurchaseOrderLineItemTable.tsx b/src/frontend/src/tables/purchasing/PurchaseOrderLineItemTable.tsx index 900839292a..85f20488ab 100644 --- a/src/frontend/src/tables/purchasing/PurchaseOrderLineItemTable.tsx +++ b/src/frontend/src/tables/purchasing/PurchaseOrderLineItemTable.tsx @@ -2,7 +2,6 @@ import { t } from '@lingui/macro'; import { Text } from '@mantine/core'; import { IconSquareArrowRight } from '@tabler/icons-react'; import { useCallback, useMemo, useState } from 'react'; -import { useNavigate } from 'react-router-dom'; import { ActionButton } from '../../components/buttons/ActionButton'; import { AddItemButton } from '../../components/buttons/AddItemButton'; @@ -16,7 +15,6 @@ import { usePurchaseOrderLineItemFields, useReceiveLineItems } from '../../forms/PurchaseOrderForms'; -import { getDetailUrl } from '../../functions/urls'; import { useCreateApiFormModal, useDeleteApiFormModal, @@ -52,7 +50,6 @@ export function PurchaseOrderLineItemTable({ }) { const table = useTable('purchase-order-line-item'); - const navigate = useNavigate(); const user = useUserState(); const [singleRecord, setSingeRecord] = useState(null); @@ -291,11 +288,7 @@ export function PurchaseOrderLineItemTable({ }, rowActions: rowActions, tableActions: tableActions, - onRowClick: (row: any) => { - if (row.part) { - navigate(getDetailUrl(ModelType.supplierpart, row.part)); - } - } + modelType: ModelType.supplierpart }} /> diff --git a/src/frontend/src/tables/purchasing/PurchaseOrderTable.tsx b/src/frontend/src/tables/purchasing/PurchaseOrderTable.tsx index 418ac20e1a..2901da0458 100644 --- a/src/frontend/src/tables/purchasing/PurchaseOrderTable.tsx +++ b/src/frontend/src/tables/purchasing/PurchaseOrderTable.tsx @@ -138,11 +138,7 @@ export function PurchaseOrderTable({ }, tableFilters: tableFilters, tableActions: tableActions, - onRowClick: (row: any) => { - if (row.pk) { - navigate(getDetailUrl(ModelType.purchaseorder, row.pk)); - } - } + modelType: ModelType.purchaseorder }} /> diff --git a/src/frontend/src/tables/purchasing/SupplierPartTable.tsx b/src/frontend/src/tables/purchasing/SupplierPartTable.tsx index d980077c2a..572c1bfbfb 100644 --- a/src/frontend/src/tables/purchasing/SupplierPartTable.tsx +++ b/src/frontend/src/tables/purchasing/SupplierPartTable.tsx @@ -1,7 +1,6 @@ import { t } from '@lingui/macro'; import { Text } from '@mantine/core'; import { ReactNode, useCallback, useMemo } from 'react'; -import { useNavigate } from 'react-router-dom'; import { AddItemButton } from '../../components/buttons/AddItemButton'; import { Thumbnail } from '../../components/images/Thumbnail'; @@ -10,7 +9,6 @@ import { ModelType } from '../../enums/ModelType'; import { UserRoles } from '../../enums/Roles'; import { useSupplierPartFields } from '../../forms/CompanyForms'; import { openDeleteApiForm, openEditApiForm } from '../../functions/forms'; -import { getDetailUrl } from '../../functions/urls'; import { useCreateApiFormModal } from '../../hooks/UseForm'; import { useTable } from '../../hooks/UseTable'; import { apiUrl } from '../../states/ApiState'; @@ -34,7 +32,6 @@ export function SupplierPartTable({ params }: { params: any }): ReactNode { const table = useTable('supplierparts'); const user = useUserState(); - const navigate = useNavigate(); // Construct table columns for this table const tableColumns: TableColumn[] = useMemo(() => { @@ -232,11 +229,7 @@ export function SupplierPartTable({ params }: { params: any }): ReactNode { }, rowActions: rowActions, tableActions: tableActions, - onRowClick: (record: any) => { - if (record?.pk) { - navigate(getDetailUrl(ModelType.supplierpart, record.pk)); - } - } + modelType: ModelType.supplierpart }} /> diff --git a/src/frontend/src/tables/sales/ReturnOrderTable.tsx b/src/frontend/src/tables/sales/ReturnOrderTable.tsx index a917e4117f..2c007848b5 100644 --- a/src/frontend/src/tables/sales/ReturnOrderTable.tsx +++ b/src/frontend/src/tables/sales/ReturnOrderTable.tsx @@ -1,6 +1,5 @@ import { t } from '@lingui/macro'; import { useCallback, useMemo } from 'react'; -import { useNavigate } from 'react-router-dom'; import { AddItemButton } from '../../components/buttons/AddItemButton'; import { Thumbnail } from '../../components/images/Thumbnail'; @@ -8,7 +7,6 @@ import { ApiEndpoints } from '../../enums/ApiEndpoints'; import { ModelType } from '../../enums/ModelType'; import { UserRoles } from '../../enums/Roles'; import { notYetImplemented } from '../../functions/notifications'; -import { getDetailUrl } from '../../functions/urls'; import { useTable } from '../../hooks/UseTable'; import { apiUrl } from '../../states/ApiState'; import { useUserState } from '../../states/UserState'; @@ -36,8 +34,6 @@ export function ReturnOrderTable({ params }: { params?: any }) { const table = useTable('return-orders'); const user = useUserState(); - const navigate = useNavigate(); - const tableFilters: TableFilter[] = useMemo(() => { return [ { @@ -115,11 +111,7 @@ export function ReturnOrderTable({ params }: { params?: any }) { }, tableFilters: tableFilters, tableActions: tableActions, - onRowClick: (row: any) => { - if (row.pk) { - navigate(getDetailUrl(ModelType.returnorder, row.pk)); - } - } + modelType: ModelType.returnorder }} /> ); diff --git a/src/frontend/src/tables/sales/SalesOrderTable.tsx b/src/frontend/src/tables/sales/SalesOrderTable.tsx index c007305072..de516eda0e 100644 --- a/src/frontend/src/tables/sales/SalesOrderTable.tsx +++ b/src/frontend/src/tables/sales/SalesOrderTable.tsx @@ -136,11 +136,7 @@ export function SalesOrderTable({ }, tableFilters: tableFilters, tableActions: tableActions, - onRowClick: (row: any) => { - if (row.pk) { - navigate(getDetailUrl(ModelType.salesorder, row.pk)); - } - } + modelType: ModelType.salesorder }} /> diff --git a/src/frontend/src/tables/settings/CustomUnitsTable.tsx b/src/frontend/src/tables/settings/CustomUnitsTable.tsx index 0f2417e6d9..75f0195af6 100644 --- a/src/frontend/src/tables/settings/CustomUnitsTable.tsx +++ b/src/frontend/src/tables/settings/CustomUnitsTable.tsx @@ -59,7 +59,7 @@ export default function CustomUnitsTable() { pk: selectedUnit, title: t`Edit Custom Unit`, fields: customUnitsFields(), - onFormSuccess: table.refreshTable + onFormSuccess: (record: any) => table.updateRecord(record) }); const deleteUnit = useDeleteApiFormModal({ diff --git a/src/frontend/src/tables/settings/ProjectCodeTable.tsx b/src/frontend/src/tables/settings/ProjectCodeTable.tsx index 9161975032..b365cc372d 100644 --- a/src/frontend/src/tables/settings/ProjectCodeTable.tsx +++ b/src/frontend/src/tables/settings/ProjectCodeTable.tsx @@ -53,7 +53,7 @@ export default function ProjectCodeTable() { pk: selectedProjectCode, title: t`Edit Project Code`, fields: projectCodeFields(), - onFormSuccess: table.refreshTable + onFormSuccess: (record: any) => table.updateRecord(record) }); const deleteProjectCode = useDeleteApiFormModal({ diff --git a/src/frontend/src/tables/stock/InstalledItemsTable.tsx b/src/frontend/src/tables/stock/InstalledItemsTable.tsx index b503feaee2..0387aa3a74 100644 --- a/src/frontend/src/tables/stock/InstalledItemsTable.tsx +++ b/src/frontend/src/tables/stock/InstalledItemsTable.tsx @@ -1,9 +1,7 @@ import { useMemo } from 'react'; -import { useNavigate } from 'react-router-dom'; import { ApiEndpoints } from '../../enums/ApiEndpoints'; import { ModelType } from '../../enums/ModelType'; -import { getDetailUrl } from '../../functions/urls'; import { useTable } from '../../hooks/UseTable'; import { apiUrl } from '../../states/ApiState'; import { useUserState } from '../../states/UserState'; @@ -18,7 +16,6 @@ export default function InstalledItemsTable({ }) { const table = useTable('stock_item_install'); const user = useUserState(); - const navigate = useNavigate(); const tableColumns: TableColumn[] = useMemo(() => { return [ @@ -60,11 +57,7 @@ export default function InstalledItemsTable({ columns={tableColumns} props={{ tableActions: tableActions, - onRowClick: (record: any) => { - if (record.pk) { - navigate(getDetailUrl(ModelType.stockitem, record.pk)); - } - }, + modelType: ModelType.stockitem, params: { belongs_to: parentId, part_detail: true diff --git a/src/frontend/src/tables/stock/StockItemTable.tsx b/src/frontend/src/tables/stock/StockItemTable.tsx index 67c73bd0da..36546c21bb 100644 --- a/src/frontend/src/tables/stock/StockItemTable.tsx +++ b/src/frontend/src/tables/stock/StockItemTable.tsx @@ -509,8 +509,7 @@ export function StockItemTable({ params = {} }: { params?: any }) { enableSelection: true, tableFilters: tableFilters, tableActions: tableActions, - onRowClick: (record) => - navigate(getDetailUrl(ModelType.stockitem, record.pk)), + modelType: ModelType.stockitem, params: { ...params, part_detail: true, diff --git a/src/frontend/src/tables/stock/StockLocationTable.tsx b/src/frontend/src/tables/stock/StockLocationTable.tsx index e534425b4d..72aa7d61e2 100644 --- a/src/frontend/src/tables/stock/StockLocationTable.tsx +++ b/src/frontend/src/tables/stock/StockLocationTable.tsx @@ -105,7 +105,7 @@ export function StockLocationTable({ parentId }: { parentId?: any }) { pk: selectedLocation, title: t`Edit Stock Location`, fields: stockLocationFields({}), - onFormSuccess: table.refreshTable + onFormSuccess: (record: any) => table.updateRecord(record) }); const tableActions = useMemo(() => { @@ -153,9 +153,7 @@ export function StockLocationTable({ parentId }: { parentId?: any }) { tableFilters: tableFilters, tableActions: tableActions, rowActions: rowActions, - onRowClick: (record) => { - navigate(getDetailUrl(ModelType.stocklocation, record.pk)); - } + modelType: ModelType.stocklocation }} />