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
}}
/>
>