2
0
mirror of https://github.com/inventree/InvenTree.git synced 2026-05-12 12:38:42 +00:00

frontend: more exposing for plugins (#11897)

* expose EditApiForm in context

* expose renderRemoteInstance in context

* expose useInstance in context

* export DetailDrawerComponent, useLocalLibState

* fix import/type

* add changelog entry
This commit is contained in:
Matthias Mair
2026-05-09 15:14:36 +02:00
committed by GitHub
parent ba883590ab
commit 61eb5e8d0f
9 changed files with 71 additions and 41 deletions
+11
View File
@@ -2,6 +2,17 @@
This file contains historical changelog information for the InvenTree UI components library.
### 0.11.4 - Unreleased
Adds additional functions in the plugin context related to form rendering and API invocation:
- `useInstance`
- `renderRemoteInstance`
- `EditApiForm`
Exposes sub-components related to DetailDrawer rendering:
- `DetailDrawerComponent`
- `useLocalLibState`
### 0.11.3 - April 2026
Exposes additional type definitions related to rendering drawers from tables:
@@ -26,7 +26,7 @@ export interface DrawerProps {
closeOnEscape?: boolean;
}
function DetailDrawerComponent({
export function DetailDrawerComponent({
title,
position = 'right',
size,
+3 -1
View File
@@ -135,7 +135,8 @@ export {
export {
type DrawerProps,
DetailDrawer,
DetailDrawerLink
DetailDrawerLink,
DetailDrawerComponent
} from './components/nav/DetailDrawer';
export { StylishText } from './components/StylishText';
@@ -144,3 +145,4 @@ export {
type StoredTableStateProps,
useStoredTableState
} from './states/StoredTableState';
export { useLocalLibState } from './states/LocalLibState';
+6 -1
View File
@@ -7,11 +7,12 @@ import type { ModelDict } from '../enums/ModelInformation';
import type { ModelType } from '../enums/ModelType';
import type {
ApiFormModalProps,
ApiFormProps,
BulkEditApiFormModalProps,
StockOperationProps
} from './Forms';
import type { UseModalReturn } from './Modals';
import type { RenderInstanceProps } from './Rendering';
import type { RemoteInstanceProps, RenderInstanceProps } from './Rendering';
import type { SettingsStateProps } from './Settings';
import type { InvenTreeTableRenderProps } from './Tables';
import type { UserStateProps } from './User';
@@ -46,6 +47,7 @@ export type InvenTreeFormsContext = {
create: (props: ApiFormModalProps) => UseModalReturn;
delete: (props: ApiFormModalProps) => UseModalReturn;
edit: (props: ApiFormModalProps) => UseModalReturn;
editApiForm: (props: { id?: string; props: ApiFormProps }) => React.ReactNode;
stockActions: StockAdjustmentFormsContext;
};
@@ -97,6 +99,9 @@ export type InvenTreePluginContext = {
globalSettings: SettingsStateProps;
modelInformation: ModelDict;
renderInstance: (props: Readonly<RenderInstanceProps>) => React.ReactNode;
renderRemoteInstance: (
props: Readonly<RemoteInstanceProps>
) => React.ReactNode;
host: string;
i18n: I18n;
locale: string;
+37
View File
@@ -1,4 +1,11 @@
import type {
QueryObserverResult,
UseQueryResult
} from '@tanstack/react-query';
import type { ReactNode } from 'react';
import type { ApiEndpoints } from '..';
import type { ModelType } from '../enums/ModelType';
import type { PathParams } from './Core';
/**
* Interface for rendering a model instance.
@@ -22,4 +29,34 @@ export type ModelRendererDict = EnumDictionary<
export type RenderInstanceProps = {
model: ModelType | undefined;
custom_model?: string;
} & InstanceRenderInterface;
export interface UseInstanceResult {
instance: any;
setInstance: (instance: any) => void;
refreshInstance: () => void;
refreshInstancePromise: () => Promise<QueryObserverResult<any, any>>;
instanceQuery: UseQueryResult;
isLoaded: boolean;
}
export interface useInstanceProps {
endpoint: ApiEndpoints;
pk?: string | number | undefined;
hasPrimaryKey?: boolean;
params?: any;
pathParams?: PathParams;
disabled?: boolean;
defaultValue?: any;
refetchOnMount?: boolean;
refetchOnWindowFocus?: boolean;
updateInterval?: number;
}
export interface RemoteInstanceProps {
model: ModelType;
modelUrl?: string;
modelRenderer?: (instance: any) => ReactNode;
pk: number;
}
@@ -38,6 +38,7 @@ import {
useDeleteApiFormModal,
useEditApiFormModal
} from '../../hooks/UseForm';
import { useInstance } from '../../hooks/UseInstance';
import {
type ImporterOpenOptions,
closeGlobalImporter,
@@ -46,7 +47,8 @@ import {
} from '../../states/ImporterState';
import { useServerApiState } from '../../states/ServerApiState';
import { InvenTreeTableInternal } from '../../tables/InvenTreeTable';
import { RenderInstance } from '../render/Instance';
import { EditApiForm } from '../forms/ApiForm';
import { RenderInstance, RenderRemoteInstance } from '../render/Instance';
export const useInvenTreeContext = () => {
const [locale, host] = useLocalState(useShallow((s) => [s.language, s.host]));
@@ -77,7 +79,9 @@ export const useInvenTreeContext = () => {
globalSettings: globalSettings,
userSettings: userSettings,
modelInformation: ModelInformationDict,
useInstance: useInstance,
renderInstance: RenderInstance,
renderRemoteInstance: RenderRemoteInstance,
theme: theme,
colorScheme: colorScheme,
importer: {
@@ -100,6 +104,7 @@ export const useInvenTreeContext = () => {
create: useCreateApiFormModal,
delete: useDeleteApiFormModal,
edit: useEditApiFormModal,
editApiForm: EditApiForm,
stockActions: {
addStock: useAddStockItem,
assignStock: useAssignStockItem,
@@ -18,6 +18,7 @@ import { apiUrl } from '@lib/functions/Api';
import { getBaseUrl, navigateToLink } from '@lib/functions/Navigation';
import type {
ModelRendererDict,
RemoteInstanceProps,
RenderInstanceProps
} from '@lib/types/Rendering';
export type { InstanceRenderInterface } from '@lib/types/Rendering';
@@ -124,12 +125,7 @@ export function RenderRemoteInstance({
modelUrl,
modelRenderer,
pk
}: Readonly<{
model: ModelType;
modelUrl?: string;
modelRenderer?: (instance: any) => ReactNode;
pk: number;
}>): ReactNode {
}: Readonly<RemoteInstanceProps>): ReactNode {
const api = useApi();
const { data, isLoading, isFetching } = useQuery({
+4 -30
View File
@@ -1,24 +1,9 @@
import {
type QueryObserverResult,
type UseQueryResult,
useQuery
} from '@tanstack/react-query';
import { useCallback, useMemo, useState } from 'react';
import type { ApiEndpoints } from '@lib/enums/ApiEndpoints';
import { apiUrl } from '@lib/functions/Api';
import type { PathParams } from '@lib/types/Core';
import type { UseInstanceResult, useInstanceProps } from '@lib/types/Rendering';
import { useQuery } from '@tanstack/react-query';
import { useCallback, useMemo, useState } from 'react';
import { useApi } from '../contexts/ApiContext';
export interface UseInstanceResult {
instance: any;
setInstance: (instance: any) => void;
refreshInstance: () => void;
refreshInstancePromise: () => Promise<QueryObserverResult<any, any>>;
instanceQuery: UseQueryResult;
isLoaded: boolean;
}
/**
* Custom hook for loading a single instance of an instance from the API
*
@@ -40,18 +25,7 @@ export function useInstance<T = any>({
refetchOnMount = true,
refetchOnWindowFocus = false,
updateInterval
}: {
endpoint: ApiEndpoints;
pk?: string | number | undefined;
hasPrimaryKey?: boolean;
params?: any;
pathParams?: PathParams;
disabled?: boolean;
defaultValue?: any;
refetchOnMount?: boolean;
refetchOnWindowFocus?: boolean;
updateInterval?: number;
}): UseInstanceResult {
}: useInstanceProps): UseInstanceResult {
const api = useApi();
const [instance, setInstance] = useState<T | undefined>(defaultValue);
@@ -1,6 +1,7 @@
import { ActionButton } from '@lib/components/ActionButton';
import { ApiEndpoints } from '@lib/enums/ApiEndpoints';
import { UserRoles } from '@lib/enums/Roles';
import type { UseInstanceResult } from '@lib/types/Rendering';
import { t } from '@lingui/core/macro';
import {
ActionIcon,
@@ -23,7 +24,6 @@ import { useSearchParams } from 'react-router-dom';
import { RenderUser } from '../../../components/render/User';
import useBackgroundTask from '../../../hooks/UseBackgroundTask';
import { useApiFormModal } from '../../../hooks/UseForm';
import type { UseInstanceResult } from '../../../hooks/UseInstance';
import { useUserState } from '../../../states/UserState';
import { BomCompareDrawer } from './BomCompare';