+
{setting ? (
) : (
diff --git a/src/frontend/src/components/tables/Column.tsx b/src/frontend/src/components/tables/Column.tsx
index 460386c2dc..4917689b99 100644
--- a/src/frontend/src/components/tables/Column.tsx
+++ b/src/frontend/src/components/tables/Column.tsx
@@ -1,14 +1,14 @@
/**
* Interface for the table column definition
*/
-export type TableColumn = {
+export type TableColumn = {
accessor: string; // The key in the record to access
ordering?: string; // The key in the record to sort by (defaults to accessor)
title: string; // The title of the column
sortable?: boolean; // Whether the column is sortable
switchable?: boolean; // Whether the column is switchable
hidden?: boolean; // Whether the column is hidden
- render?: (record: any) => any; // A custom render function
+ render?: (record: T) => any; // A custom render function
filter?: any; // A custom filter function
filtering?: boolean; // Whether the column is filterable
width?: number; // The width of the column
diff --git a/src/frontend/src/components/tables/InvenTreeTable.tsx b/src/frontend/src/components/tables/InvenTreeTable.tsx
index 51cd0ae6eb..1ec524293f 100644
--- a/src/frontend/src/components/tables/InvenTreeTable.tsx
+++ b/src/frontend/src/components/tables/InvenTreeTable.tsx
@@ -6,7 +6,7 @@ import { IconFilter, IconRefresh } from '@tabler/icons-react';
import { IconBarcode, IconPrinter } from '@tabler/icons-react';
import { useQuery } from '@tanstack/react-query';
import { DataTable, DataTableSortStatus } from 'mantine-datatable';
-import { useEffect, useMemo, useState } from 'react';
+import { Fragment, useEffect, useMemo, useState } from 'react';
import { api } from '../../App';
import { ButtonMenu } from '../buttons/ButtonMenu';
@@ -44,7 +44,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
*/
-export type InvenTreeTableProps = {
+export type InvenTreeTableProps = {
params?: any;
defaultSortColumn?: string;
noRecordsText?: string;
@@ -57,12 +57,12 @@ export type InvenTreeTableProps = {
pageSize?: number;
barcodeActions?: any[];
customFilters?: TableFilter[];
- customActionGroups?: any[];
+ customActionGroups?: React.ReactNode[];
printingActions?: any[];
idAccessor?: string;
- dataFormatter?: (data: any) => any;
- rowActions?: (record: any) => RowAction[];
- onRowClick?: (record: any, index: number, event: any) => void;
+ dataFormatter?: (data: T) => any;
+ rowActions?: (record: T) => RowAction[];
+ onRowClick?: (record: T, index: number, event: any) => void;
};
/**
@@ -90,7 +90,7 @@ const defaultInvenTreeTableProps: InvenTreeTableProps = {
/**
* Table Component which extends DataTable with custom InvenTree functionality
*/
-export function InvenTreeTable({
+export function InvenTreeTable({
url,
tableKey,
columns,
@@ -98,8 +98,8 @@ export function InvenTreeTable({
}: {
url: string;
tableKey: string;
- columns: TableColumn[];
- props: InvenTreeTableProps;
+ columns: TableColumn[];
+ props: InvenTreeTableProps;
}) {
// Use the first part of the table key as the table name
const tableName: string = useMemo(() => {
@@ -107,7 +107,7 @@ export function InvenTreeTable({
}, []);
// Build table properties based on provided props (and default props)
- const tableProps: InvenTreeTableProps = useMemo(() => {
+ const tableProps: InvenTreeTableProps = useMemo(() => {
return {
...defaultInvenTreeTableProps,
...props
@@ -432,9 +432,9 @@ export function InvenTreeTable({
- {tableProps.customActionGroups?.map(
- (group: any, idx: number) => group
- )}
+ {tableProps.customActionGroups?.map((group, idx) => (
+ {group}
+ ))}
{(tableProps.barcodeActions?.length ?? 0 > 0) && (
- {visibleActions.map((action, _idx) => (
-
+ {visibleActions.map((action) => (
+
))}
diff --git a/src/frontend/src/functions/forms.tsx b/src/frontend/src/functions/forms.tsx
index 031b076721..127f910165 100644
--- a/src/frontend/src/functions/forms.tsx
+++ b/src/frontend/src/functions/forms.tsx
@@ -11,15 +11,19 @@ import {
} from '../components/forms/fields/ApiFormField';
import { StylishText } from '../components/items/StylishText';
import { ApiPaths } from '../enums/ApiEndpoints';
-import { apiUrl } from '../states/ApiState';
+import { PathParams, apiUrl } from '../states/ApiState';
import { invalidResponse, permissionDenied } from './notifications';
import { generateUniqueId } from './uid';
/**
* Construct an API url from the provided ApiFormProps object
*/
-export function constructFormUrl(url: ApiPaths, pk?: string | number): string {
- return apiUrl(url, pk);
+export function constructFormUrl(
+ url: ApiPaths,
+ pk?: string | number,
+ pathParams?: PathParams
+): string {
+ return apiUrl(url, pk, pathParams);
}
/**
@@ -208,7 +212,7 @@ export function openModalApiForm(props: OpenApiFormProps) {
modals.close(modalId);
};
- let url = constructFormUrl(props.url, props.pk);
+ let url = constructFormUrl(props.url, props.pk, props.pathParams);
// Make OPTIONS request first
api
diff --git a/src/frontend/src/states/ApiState.tsx b/src/frontend/src/states/ApiState.tsx
index 4a4b5ef0ae..6713f9e23d 100644
--- a/src/frontend/src/states/ApiState.tsx
+++ b/src/frontend/src/states/ApiState.tsx
@@ -1,5 +1,5 @@
import { create } from 'zustand';
-import { persist } from 'zustand/middleware';
+import { createJSONStorage, persist } from 'zustand/middleware';
import { api } from '../App';
import { StatusCodeListInterface } from '../components/render/StatusRenderer';
@@ -15,7 +15,7 @@ interface ServerApiStateProps {
server: ServerAPIProps;
setServer: (newServer: ServerAPIProps) => void;
fetchServerApiState: () => void;
- status: StatusLookup | undefined;
+ status?: StatusLookup;
}
export const useServerApiState = create()(
@@ -44,7 +44,7 @@ export const useServerApiState = create()(
}),
{
name: 'server-api-state',
- getStorage: () => sessionStorage
+ storage: createJSONStorage(() => sessionStorage)
}
)
);
@@ -189,13 +189,15 @@ export function apiEndpoint(path: ApiPaths): string {
}
}
+export type PathParams = Record;
+
/**
* Construct an API URL with an endpoint and (optional) pk value
*/
export function apiUrl(
path: ApiPaths,
pk?: any,
- data?: Record
+ pathParams?: PathParams
): string {
let _url = apiEndpoint(path);
@@ -208,9 +210,9 @@ export function apiUrl(
_url += `${pk}/`;
}
- if (_url && data) {
- for (const key in data) {
- _url = _url.replace(`:${key}`, `${data[key]}`);
+ if (_url && pathParams) {
+ for (const key in pathParams) {
+ _url = _url.replace(`:${key}`, `${pathParams[key]}`);
}
}
diff --git a/src/frontend/src/states/SessionState.tsx b/src/frontend/src/states/SessionState.tsx
index d49a223910..54f1e58b9e 100644
--- a/src/frontend/src/states/SessionState.tsx
+++ b/src/frontend/src/states/SessionState.tsx
@@ -1,11 +1,11 @@
import { create } from 'zustand';
-import { persist } from 'zustand/middleware';
+import { createJSONStorage, persist } from 'zustand/middleware';
import { setApiDefaults } from '../App';
interface SessionStateProps {
- token: string | undefined;
- setToken: (newToken: string | undefined) => void;
+ token?: string;
+ setToken: (newToken?: string) => void;
}
export const useSessionState = create()(
@@ -19,7 +19,7 @@ export const useSessionState = create()(
}),
{
name: 'session-state',
- getStorage: () => sessionStorage
+ storage: createJSONStorage(() => sessionStorage)
}
)
);
diff --git a/src/frontend/src/states/SettingsState.tsx b/src/frontend/src/states/SettingsState.tsx
index 6270446117..42da0e9f28 100644
--- a/src/frontend/src/states/SettingsState.tsx
+++ b/src/frontend/src/states/SettingsState.tsx
@@ -6,7 +6,7 @@ import { create } from 'zustand';
import { api } from '../App';
import { ApiPaths } from '../enums/ApiEndpoints';
import { isTrue } from '../functions/conversion';
-import { apiUrl } from './ApiState';
+import { PathParams, apiUrl } from './ApiState';
import { Setting, SettingsLookup } from './states';
export interface SettingsStateProps {
@@ -14,6 +14,7 @@ export interface SettingsStateProps {
lookup: SettingsLookup;
fetchSettings: () => void;
endpoint: ApiPaths;
+ pathParams?: PathParams;
getSetting: (key: string, default_value?: string) => string; // Return a raw setting value
isSet: (key: string, default_value?: boolean) => boolean; // Check a "boolean" setting
}