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. 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 ### 0.11.3 - April 2026
Exposes additional type definitions related to rendering drawers from tables: Exposes additional type definitions related to rendering drawers from tables:
@@ -26,7 +26,7 @@ export interface DrawerProps {
closeOnEscape?: boolean; closeOnEscape?: boolean;
} }
function DetailDrawerComponent({ export function DetailDrawerComponent({
title, title,
position = 'right', position = 'right',
size, size,
+3 -1
View File
@@ -135,7 +135,8 @@ export {
export { export {
type DrawerProps, type DrawerProps,
DetailDrawer, DetailDrawer,
DetailDrawerLink DetailDrawerLink,
DetailDrawerComponent
} from './components/nav/DetailDrawer'; } from './components/nav/DetailDrawer';
export { StylishText } from './components/StylishText'; export { StylishText } from './components/StylishText';
@@ -144,3 +145,4 @@ export {
type StoredTableStateProps, type StoredTableStateProps,
useStoredTableState useStoredTableState
} from './states/StoredTableState'; } 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 { ModelType } from '../enums/ModelType';
import type { import type {
ApiFormModalProps, ApiFormModalProps,
ApiFormProps,
BulkEditApiFormModalProps, BulkEditApiFormModalProps,
StockOperationProps StockOperationProps
} from './Forms'; } from './Forms';
import type { UseModalReturn } from './Modals'; import type { UseModalReturn } from './Modals';
import type { RenderInstanceProps } from './Rendering'; import type { RemoteInstanceProps, RenderInstanceProps } from './Rendering';
import type { SettingsStateProps } from './Settings'; import type { SettingsStateProps } from './Settings';
import type { InvenTreeTableRenderProps } from './Tables'; import type { InvenTreeTableRenderProps } from './Tables';
import type { UserStateProps } from './User'; import type { UserStateProps } from './User';
@@ -46,6 +47,7 @@ export type InvenTreeFormsContext = {
create: (props: ApiFormModalProps) => UseModalReturn; create: (props: ApiFormModalProps) => UseModalReturn;
delete: (props: ApiFormModalProps) => UseModalReturn; delete: (props: ApiFormModalProps) => UseModalReturn;
edit: (props: ApiFormModalProps) => UseModalReturn; edit: (props: ApiFormModalProps) => UseModalReturn;
editApiForm: (props: { id?: string; props: ApiFormProps }) => React.ReactNode;
stockActions: StockAdjustmentFormsContext; stockActions: StockAdjustmentFormsContext;
}; };
@@ -97,6 +99,9 @@ export type InvenTreePluginContext = {
globalSettings: SettingsStateProps; globalSettings: SettingsStateProps;
modelInformation: ModelDict; modelInformation: ModelDict;
renderInstance: (props: Readonly<RenderInstanceProps>) => React.ReactNode; renderInstance: (props: Readonly<RenderInstanceProps>) => React.ReactNode;
renderRemoteInstance: (
props: Readonly<RemoteInstanceProps>
) => React.ReactNode;
host: string; host: string;
i18n: I18n; i18n: I18n;
locale: string; 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 { ModelType } from '../enums/ModelType';
import type { PathParams } from './Core';
/** /**
* Interface for rendering a model instance. * Interface for rendering a model instance.
@@ -22,4 +29,34 @@ export type ModelRendererDict = EnumDictionary<
export type RenderInstanceProps = { export type RenderInstanceProps = {
model: ModelType | undefined; model: ModelType | undefined;
custom_model?: string;
} & InstanceRenderInterface; } & 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, useDeleteApiFormModal,
useEditApiFormModal useEditApiFormModal
} from '../../hooks/UseForm'; } from '../../hooks/UseForm';
import { useInstance } from '../../hooks/UseInstance';
import { import {
type ImporterOpenOptions, type ImporterOpenOptions,
closeGlobalImporter, closeGlobalImporter,
@@ -46,7 +47,8 @@ import {
} from '../../states/ImporterState'; } from '../../states/ImporterState';
import { useServerApiState } from '../../states/ServerApiState'; import { useServerApiState } from '../../states/ServerApiState';
import { InvenTreeTableInternal } from '../../tables/InvenTreeTable'; import { InvenTreeTableInternal } from '../../tables/InvenTreeTable';
import { RenderInstance } from '../render/Instance'; import { EditApiForm } from '../forms/ApiForm';
import { RenderInstance, RenderRemoteInstance } from '../render/Instance';
export const useInvenTreeContext = () => { export const useInvenTreeContext = () => {
const [locale, host] = useLocalState(useShallow((s) => [s.language, s.host])); const [locale, host] = useLocalState(useShallow((s) => [s.language, s.host]));
@@ -77,7 +79,9 @@ export const useInvenTreeContext = () => {
globalSettings: globalSettings, globalSettings: globalSettings,
userSettings: userSettings, userSettings: userSettings,
modelInformation: ModelInformationDict, modelInformation: ModelInformationDict,
useInstance: useInstance,
renderInstance: RenderInstance, renderInstance: RenderInstance,
renderRemoteInstance: RenderRemoteInstance,
theme: theme, theme: theme,
colorScheme: colorScheme, colorScheme: colorScheme,
importer: { importer: {
@@ -100,6 +104,7 @@ export const useInvenTreeContext = () => {
create: useCreateApiFormModal, create: useCreateApiFormModal,
delete: useDeleteApiFormModal, delete: useDeleteApiFormModal,
edit: useEditApiFormModal, edit: useEditApiFormModal,
editApiForm: EditApiForm,
stockActions: { stockActions: {
addStock: useAddStockItem, addStock: useAddStockItem,
assignStock: useAssignStockItem, assignStock: useAssignStockItem,
@@ -18,6 +18,7 @@ import { apiUrl } from '@lib/functions/Api';
import { getBaseUrl, navigateToLink } from '@lib/functions/Navigation'; import { getBaseUrl, navigateToLink } from '@lib/functions/Navigation';
import type { import type {
ModelRendererDict, ModelRendererDict,
RemoteInstanceProps,
RenderInstanceProps RenderInstanceProps
} from '@lib/types/Rendering'; } from '@lib/types/Rendering';
export type { InstanceRenderInterface } from '@lib/types/Rendering'; export type { InstanceRenderInterface } from '@lib/types/Rendering';
@@ -124,12 +125,7 @@ export function RenderRemoteInstance({
modelUrl, modelUrl,
modelRenderer, modelRenderer,
pk pk
}: Readonly<{ }: Readonly<RemoteInstanceProps>): ReactNode {
model: ModelType;
modelUrl?: string;
modelRenderer?: (instance: any) => ReactNode;
pk: number;
}>): ReactNode {
const api = useApi(); const api = useApi();
const { data, isLoading, isFetching } = useQuery({ 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 { 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'; 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 * Custom hook for loading a single instance of an instance from the API
* *
@@ -40,18 +25,7 @@ export function useInstance<T = any>({
refetchOnMount = true, refetchOnMount = true,
refetchOnWindowFocus = false, refetchOnWindowFocus = false,
updateInterval updateInterval
}: { }: useInstanceProps): UseInstanceResult {
endpoint: ApiEndpoints;
pk?: string | number | undefined;
hasPrimaryKey?: boolean;
params?: any;
pathParams?: PathParams;
disabled?: boolean;
defaultValue?: any;
refetchOnMount?: boolean;
refetchOnWindowFocus?: boolean;
updateInterval?: number;
}): UseInstanceResult {
const api = useApi(); const api = useApi();
const [instance, setInstance] = useState<T | undefined>(defaultValue); const [instance, setInstance] = useState<T | undefined>(defaultValue);
@@ -1,6 +1,7 @@
import { ActionButton } from '@lib/components/ActionButton'; import { ActionButton } from '@lib/components/ActionButton';
import { ApiEndpoints } from '@lib/enums/ApiEndpoints'; import { ApiEndpoints } from '@lib/enums/ApiEndpoints';
import { UserRoles } from '@lib/enums/Roles'; import { UserRoles } from '@lib/enums/Roles';
import type { UseInstanceResult } from '@lib/types/Rendering';
import { t } from '@lingui/core/macro'; import { t } from '@lingui/core/macro';
import { import {
ActionIcon, ActionIcon,
@@ -23,7 +24,6 @@ import { useSearchParams } from 'react-router-dom';
import { RenderUser } from '../../../components/render/User'; import { RenderUser } from '../../../components/render/User';
import useBackgroundTask from '../../../hooks/UseBackgroundTask'; import useBackgroundTask from '../../../hooks/UseBackgroundTask';
import { useApiFormModal } from '../../../hooks/UseForm'; import { useApiFormModal } from '../../../hooks/UseForm';
import type { UseInstanceResult } from '../../../hooks/UseInstance';
import { useUserState } from '../../../states/UserState'; import { useUserState } from '../../../states/UserState';
import { BomCompareDrawer } from './BomCompare'; import { BomCompareDrawer } from './BomCompare';