URL nav improvements (#6356)

* Implement getDetailUrl method

* Add nav link for PurchaseOrderLineItem table

* URL cleanup

- Replace hard-coded URLs with lookup
This commit is contained in:
Oliver 2024-01-29 16:51:54 +11:00 committed by GitHub
parent b42f8a620b
commit 0f7d385755
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 64 additions and 18 deletions

View File

@ -10,9 +10,11 @@ import { useNavigate } from 'react-router-dom';
import { formatPriceRange } from '../../../defaults/formatters';
import { ApiPaths } from '../../../enums/ApiEndpoints';
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';
@ -364,7 +366,8 @@ export function BomTable({
sub_part_detail: true
},
tableFilters: tableFilters,
onRowClick: (row) => navigate(`/part/${row.sub_part}`),
onRowClick: (row) =>
navigate(getDetailUrl(ModelType.part, row.sub_part)),
rowActions: rowActions
}}
/>

View File

@ -3,6 +3,8 @@ import { useMemo } from 'react';
import { useNavigate } from 'react-router-dom';
import { ApiPaths } from '../../../enums/ApiEndpoints';
import { ModelType } from '../../../enums/ModelType';
import { getDetailUrl } from '../../../functions/urls';
import { useTable } from '../../../hooks/UseTable';
import { apiUrl } from '../../../states/ApiState';
import { PartHoverCard } from '../../images/Thumbnail';
@ -93,7 +95,7 @@ export function UsedInTable({
sub_part_detail: true
},
tableFilters: tableFilters,
onRowClick: (row) => navigate(`/part/${row.part}`)
onRowClick: (row) => navigate(getDetailUrl(ModelType.part, row.part))
}}
/>
);

View File

@ -9,6 +9,8 @@ import { useCallback, useMemo } from 'react';
import { useNavigate } from 'react-router-dom';
import { ApiPaths } 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';
@ -233,7 +235,7 @@ export default function BuildLineTable({ params = {} }: { params?: any }) {
rowActions: rowActions,
onRowClick: (row: any) => {
if (row?.part_detail?.pk) {
navigate(`/part/${row.part_detail.pk}`);
navigate(getDetailUrl(ModelType.part, row.part_detail.pk));
}
}
}}

View File

@ -5,6 +5,7 @@ import { useNavigate } from 'react-router-dom';
import { renderDate } from '../../../defaults/formatters';
import { ApiPaths } from '../../../enums/ApiEndpoints';
import { ModelType } from '../../../enums/ModelType';
import { getDetailUrl } from '../../../functions/urls';
import { useTable } from '../../../hooks/UseTable';
import { apiUrl } from '../../../states/ApiState';
import { PartHoverCard } from '../../images/Thumbnail';
@ -144,7 +145,7 @@ export function BuildOrderTable({ params = {} }: { params?: any }) {
part_detail: true
},
tableFilters: tableFilters,
onRowClick: (row) => navigate(`/build/${row.pk}`)
onRowClick: (row) => navigate(getDetailUrl(ModelType.build, row.pk))
}}
/>
);

View File

@ -3,9 +3,11 @@ import { useCallback, useMemo } from 'react';
import { useNavigate } from 'react-router-dom';
import { ApiPaths } from '../../../enums/ApiEndpoints';
import { ModelType } from '../../../enums/ModelType';
import { UserRoles } from '../../../enums/Roles';
import { partCategoryFields } from '../../../forms/PartForms';
import { openCreateApiForm, openEditApiForm } from '../../../functions/forms';
import { getDetailUrl } from '../../../functions/urls';
import { useTable } from '../../../hooks/UseTable';
import { apiUrl } from '../../../states/ApiState';
import { useUserState } from '../../../states/UserState';
@ -140,9 +142,8 @@ export function PartCategoryTable({ parentId }: { parentId?: any }) {
tableFilters: tableFilters,
tableActions: tableActions,
rowActions: rowActions,
onRowClick: (record, index, event) => {
navigate(`/part/category/${record.pk}`);
}
onRowClick: (record, index, event) =>
navigate(getDetailUrl(ModelType.partcategory, record.pk))
}}
/>
);

View File

@ -5,7 +5,9 @@ import { useNavigate } from 'react-router-dom';
import { formatPriceRange } from '../../../defaults/formatters';
import { ApiPaths } from '../../../enums/ApiEndpoints';
import { ModelType } from '../../../enums/ModelType';
import { shortenString } from '../../../functions/tables';
import { getDetailUrl } from '../../../functions/urls';
import { useTable } from '../../../hooks/UseTable';
import { apiUrl } from '../../../states/ApiState';
import { Thumbnail } from '../../images/Thumbnail';
@ -280,9 +282,8 @@ export function PartListTable({ props }: { props: InvenTreeTableProps }) {
...props.params,
category_detail: true
},
onRowClick: (record, _index, _event) => {
navigate(`/part/${record.pk}/`);
}
onRowClick: (record) =>
navigate(getDetailUrl(ModelType.part, record.pk))
}}
/>
);

View File

@ -3,10 +3,12 @@ import { ReactNode, useCallback, useMemo } from 'react';
import { useNavigate } from 'react-router-dom';
import { ApiPaths } from '../../../enums/ApiEndpoints';
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 { useTable } from '../../../hooks/UseTable';
import { apiUrl } from '../../../states/ApiState';
import { useUserState } from '../../../states/UserState';
@ -132,7 +134,7 @@ export function ManufacturerPartTable({ params }: { params: any }): ReactNode {
tableActions: tableActions,
onRowClick: (record: any) => {
if (record?.pk) {
navigate(`/purchasing/manufacturer-part/${record.pk}/`);
navigate(getDetailUrl(ModelType.manufacturerpart, record.pk));
}
}
}}

View File

@ -2,12 +2,15 @@ import { t } from '@lingui/macro';
import { Text } from '@mantine/core';
import { IconSquareArrowRight } from '@tabler/icons-react';
import { useCallback, useMemo } from 'react';
import { useNavigate } from 'react-router-dom';
import { ProgressBar } from '../../../components/items/ProgressBar';
import { ApiPaths } from '../../../enums/ApiEndpoints';
import { ModelType } from '../../../enums/ModelType';
import { UserRoles } from '../../../enums/Roles';
import { purchaseOrderLineItemFields } from '../../../forms/PurchaseOrderForms';
import { openCreateApiForm, openEditApiForm } from '../../../functions/forms';
import { getDetailUrl } from '../../../functions/urls';
import { useTable } from '../../../hooks/UseTable';
import { apiUrl } from '../../../states/ApiState';
import { useUserState } from '../../../states/UserState';
@ -41,6 +44,7 @@ export function PurchaseOrderLineItemTable({
}) {
const table = useTable('purchase-order-line-item');
const navigate = useNavigate();
const user = useUserState();
const rowActions = useCallback(
@ -260,7 +264,12 @@ export function PurchaseOrderLineItemTable({
part_detail: true
},
rowActions: rowActions,
tableActions: tableActions
tableActions: tableActions,
onRowClick: (row: any) => {
if (row.part) {
navigate(getDetailUrl(ModelType.supplierpart, row.part));
}
}
}}
/>
);

View File

@ -6,6 +6,7 @@ import { ApiPaths } 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';
@ -127,7 +128,7 @@ export function PurchaseOrderTable({ params }: { params?: any }) {
tableActions: tableActions,
onRowClick: (row: any) => {
if (row.pk) {
navigate(`/purchasing/purchase-order/${row.pk}`);
navigate(getDetailUrl(ModelType.purchaseorder, row.pk));
}
}
}}

View File

@ -4,9 +4,11 @@ import { ReactNode, useCallback, useMemo } from 'react';
import { useNavigate } from 'react-router-dom';
import { ApiPaths } from '../../../enums/ApiEndpoints';
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';
@ -234,7 +236,7 @@ export function SupplierPartTable({ params }: { params: any }): ReactNode {
tableActions: tableActions,
onRowClick: (record: any) => {
if (record?.pk) {
navigate(`/purchasing/supplier-part/${record.pk}/`);
navigate(getDetailUrl(ModelType.supplierpart, record.pk));
}
}
}}

View File

@ -6,6 +6,7 @@ import { ApiPaths } 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';
@ -123,7 +124,7 @@ export function ReturnOrderTable({ params }: { params?: any }) {
tableActions: tableActions,
onRowClick: (row: any) => {
if (row.pk) {
navigate(`/sales/return-order/${row.pk}/`);
navigate(getDetailUrl(ModelType.returnorder, row.pk));
}
}
}}

View File

@ -6,6 +6,7 @@ import { ApiPaths } 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';
@ -124,7 +125,7 @@ export function SalesOrderTable({ params }: { params?: any }) {
tableActions: tableActions,
onRowClick: (row: any) => {
if (row.pk) {
navigate(`/sales/sales-order/${row.pk}/`);
navigate(getDetailUrl(ModelType.salesorder, row.pk));
}
}
}}

View File

@ -6,6 +6,7 @@ import { useNavigate } from 'react-router-dom';
import { formatCurrency, renderDate } from '../../../defaults/formatters';
import { ApiPaths } 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';
@ -345,7 +346,8 @@ export function StockItemTable({ params = {} }: { params?: any }) {
enableDownload: true,
enableSelection: true,
tableFilters: tableFilters,
onRowClick: (record) => navigate(`/stock/item/${record.pk}`),
onRowClick: (record) =>
navigate(getDetailUrl(ModelType.stockitem, record.pk)),
params: {
...params,
part_detail: true,

View File

@ -3,9 +3,11 @@ import { useCallback, useMemo } from 'react';
import { useNavigate } from 'react-router-dom';
import { ApiPaths } from '../../../enums/ApiEndpoints';
import { ModelType } from '../../../enums/ModelType';
import { UserRoles } from '../../../enums/Roles';
import { stockLocationFields } from '../../../forms/StockForms';
import { openCreateApiForm, openEditApiForm } from '../../../functions/forms';
import { getDetailUrl } from '../../../functions/urls';
import { useTable } from '../../../hooks/UseTable';
import { apiUrl } from '../../../states/ApiState';
import { useUserState } from '../../../states/UserState';
@ -164,7 +166,7 @@ export function StockLocationTable({ parentId }: { parentId?: any }) {
tableActions: tableActions,
rowActions: rowActions,
onRowClick: (record) => {
navigate(`/stock/location/${record.pk}`);
navigate(getDetailUrl(ModelType.stocklocation, record.pk));
}
// TODO: allow for "tree view" with cascade
}}

View File

@ -0,0 +1,16 @@
import { ModelInformationDict } from '../components/render/ModelType';
import { ModelType } from '../enums/ModelType';
/**
* Returns the detail view URL for a given model type
*/
export function getDetailUrl(model: ModelType, pk: number | string): string {
const modelInfo = ModelInformationDict[model];
if (modelInfo && modelInfo.url_detail) {
return modelInfo.url_detail.replace(':pk', pk.toString());
}
console.error(`No detail URL found for model ${model}!`);
return '';
}