diff --git a/src/frontend/src/components/render/ModelType.tsx b/src/frontend/src/components/render/ModelType.tsx
index af24c8fa9b..d5718aa674 100644
--- a/src/frontend/src/components/render/ModelType.tsx
+++ b/src/frontend/src/components/render/ModelType.tsx
@@ -3,7 +3,7 @@ import { t } from '@lingui/macro';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { ModelType } from '../../enums/ModelType';
-interface ModelInformationInterface {
+export interface ModelInformationInterface {
label: string;
label_multiple: string;
url_overview?: string;
@@ -12,11 +12,11 @@ interface ModelInformationInterface {
cui_detail?: string;
}
-type ModelDictory = {
+export type ModelDict = {
[key in keyof typeof ModelType]: ModelInformationInterface;
};
-export const ModelInformationDict: ModelDictory = {
+export const ModelInformationDict: ModelDict = {
part: {
label: t`Part`,
label_multiple: t`Parts`,
@@ -165,3 +165,12 @@ export const ModelInformationDict: ModelDictory = {
api_endpoint: ApiEndpoints.user_list
}
};
+
+/*
+ * Extract model definition given the provided type
+ * @param type - ModelType to extract information from
+ * @returns ModelInformationInterface
+ */
+export function getModelInfo(type: ModelType): ModelInformationInterface {
+ return ModelInformationDict[type];
+}
diff --git a/src/frontend/src/pages/part/PartDetail.tsx b/src/frontend/src/pages/part/PartDetail.tsx
index eab798de80..c2ecf2884d 100644
--- a/src/frontend/src/pages/part/PartDetail.tsx
+++ b/src/frontend/src/pages/part/PartDetail.tsx
@@ -44,6 +44,7 @@ import { PartCategoryTree } from '../../components/nav/PartCategoryTree';
import { NotesEditor } from '../../components/widgets/MarkdownEditor';
import { formatPriceRange } from '../../defaults/formatters';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
+import { ModelType } from '../../enums/ModelType';
import { UserRoles } from '../../enums/Roles';
import { partFields } from '../../forms/PartForms';
import { useEditApiFormModal } from '../../hooks/UseForm';
@@ -122,8 +123,7 @@ export default function PartDetail() {
type: 'link',
name: 'variant_of',
label: t`Variant of`,
- path: ApiEndpoints.part_list,
- dest: '/part/'
+ model: ModelType.part
}
]);
}
@@ -226,8 +226,7 @@ export default function PartDetail() {
type: 'link',
name: 'category',
label: t`Category`,
- path: ApiEndpoints.category_list,
- dest: '/part/category/'
+ model: ModelType.partcategory
}
]);
}
@@ -336,7 +335,7 @@ export default function PartDetail() {
const { data } = useSuspenseQuery({
queryKey: ['stocktake', id],
queryFn: async () => {
- const url = ApiEndpoints.part_stocktake_list;
+ const url = apiUrl(ApiEndpoints.part_stocktake_list);
return api
.get(url, { params: { part: id, ordering: 'date' } })
@@ -364,7 +363,7 @@ export default function PartDetail() {
const { data } = useSuspenseQuery({
queryKey: ['stocktake', id],
queryFn: async () => {
- const url = ApiEndpoints.part_stocktake_list;
+ const url = apiUrl(ApiEndpoints.part_stocktake_list);
return api
.get(url, { params: { part: id, ordering: 'date' } })
@@ -392,8 +391,7 @@ export default function PartDetail() {
type: 'link',
name: 'default_location',
label: t`Default Location`,
- path: ApiEndpoints.stock_location_list,
- dest: '/stock/location/'
+ model: ModelType.stocklocation
}
]);
}
@@ -404,8 +402,7 @@ export default function PartDetail() {
type: 'link',
name: 'default_supplier',
label: t`Default Supplier`,
- path: ApiEndpoints.supplier_part_list,
- dest: '/part/'
+ model: ModelType.supplierpart
}
]);
}
diff --git a/src/frontend/src/tables/Details.tsx b/src/frontend/src/tables/Details.tsx
index e62b8f23c8..d32dba6fbc 100644
--- a/src/frontend/src/tables/Details.tsx
+++ b/src/frontend/src/tables/Details.tsx
@@ -11,12 +11,15 @@ import {
Tooltip
} from '@mantine/core';
import { useSuspenseQuery } from '@tanstack/react-query';
-import { Suspense } from 'react';
+import { Suspense, useMemo } from 'react';
import { api } from '../App';
import { ProgressBar } from '../components/items/ProgressBar';
+import { getModelInfo } from '../components/render/ModelType';
import { ApiEndpoints } from '../enums/ApiEndpoints';
+import { ModelType } from '../enums/ModelType';
import { InvenTreeIcon } from '../functions/icons';
+import { getDetailUrl } from '../functions/urls';
import { apiUrl } from '../states/ApiState';
import { useGlobalSettingsState } from '../states/SettingsState';
@@ -53,8 +56,7 @@ type LinkDetailField = {
} & (InternalLinkField | ExternalLinkField);
type InternalLinkField = {
- path: ApiEndpoints;
- dest: string;
+ model: ModelType;
};
type ExternalLinkField = {
@@ -292,9 +294,15 @@ function TableAnchorValue(props: FieldProps) {
}
const { data } = useSuspenseQuery({
- queryKey: ['detail', props.field_data.path],
+ queryKey: ['detail', props.field_data.model, props.field_value],
queryFn: async () => {
- const url = apiUrl(props.field_data.path, props.field_value);
+ const modelDef = getModelInfo(props.field_data.model);
+
+ if (!modelDef.api_endpoint) {
+ return {};
+ }
+
+ const url = apiUrl(modelDef.api_endpoint, props.field_value);
return api
.get(url)
@@ -312,14 +320,16 @@ function TableAnchorValue(props: FieldProps) {
}
});
+ const detailUrl = useMemo(() => {
+ return getDetailUrl(props.field_data.model, props.field_value);
+ }, [props.field_data.model, props.field_value]);
+
return (
}>
{data.name ?? 'No name defined'}