@inventreedb/ui 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/dist/.vite/manifest.json +444 -1
- package/dist/components/Boundary.d.ts +10 -0
- package/dist/components/Boundary.js +37 -0
- package/dist/components/Boundary.js.map +1 -0
- package/dist/components/CopyButton.d.ts +13 -0
- package/dist/components/CopyButton.js +51 -0
- package/dist/components/CopyButton.js.map +1 -0
- package/dist/components/CopyableCell.d.ts +11 -0
- package/dist/components/CopyableCell.js +24 -0
- package/dist/components/CopyableCell.js.map +1 -0
- package/dist/components/InvenTreeTable.d.ts +17 -0
- package/dist/components/InvenTreeTable.js +41 -0
- package/dist/components/InvenTreeTable.js.map +1 -0
- package/dist/components/TableColumnSelect.d.ts +4 -0
- package/dist/components/TableColumnSelect.js +38 -0
- package/dist/components/TableColumnSelect.js.map +1 -0
- package/dist/enums/ApiEndpoints.d.ts +1 -1
- package/dist/enums/ApiEndpoints.js +1 -1
- package/dist/enums/ApiEndpoints.js.map +1 -1
- package/dist/enums/ModelInformation.js +17 -0
- package/dist/enums/ModelInformation.js.map +1 -1
- package/dist/enums/ModelType.d.ts +1 -0
- package/dist/enums/ModelType.js +1 -0
- package/dist/enums/ModelType.js.map +1 -1
- package/dist/functions/Forms.d.ts +11 -0
- package/dist/functions/Forms.js +27 -0
- package/dist/functions/Forms.js.map +1 -0
- package/dist/functions/Notification.d.ts +16 -0
- package/dist/functions/Notification.js +82 -0
- package/dist/functions/Notification.js.map +1 -0
- package/dist/functions/String.d.ts +13 -0
- package/dist/functions/String.js +25 -0
- package/dist/functions/String.js.map +1 -0
- package/dist/hooks/UseFilterSet.d.ts +2 -0
- package/dist/hooks/UseFilterSet.js +35 -0
- package/dist/hooks/UseFilterSet.js.map +1 -0
- package/dist/hooks/UseTable.d.ts +12 -0
- package/dist/hooks/UseTable.js +92 -0
- package/dist/hooks/UseTable.js.map +1 -0
- package/dist/index.d.ts +13 -2
- package/dist/index.js +32 -4
- package/dist/index.js.map +1 -1
- package/dist/node_modules/@mantine/hooks/esm/use-local-storage/create-storage.js +129 -0
- package/dist/node_modules/@mantine/hooks/esm/use-local-storage/create-storage.js.map +1 -0
- package/dist/node_modules/@mantine/hooks/esm/use-local-storage/use-local-storage.js +8 -0
- package/dist/node_modules/@mantine/hooks/esm/use-local-storage/use-local-storage.js.map +1 -0
- package/dist/node_modules/@mantine/hooks/esm/use-window-event/use-window-event.js +11 -0
- package/dist/node_modules/@mantine/hooks/esm/use-window-event/use-window-event.js.map +1 -0
- package/dist/node_modules/@mantine/hooks/esm/utils/random-id/random-id.js +7 -0
- package/dist/node_modules/@mantine/hooks/esm/utils/random-id/random-id.js.map +1 -0
- package/dist/node_modules/@remix-run/router/dist/router.js +272 -0
- package/dist/node_modules/@remix-run/router/dist/router.js.map +1 -0
- package/dist/node_modules/@sentry/browser/build/npm/esm/prod/debug-build.js +5 -0
- package/dist/node_modules/@sentry/browser/build/npm/esm/prod/debug-build.js.map +1 -0
- package/dist/node_modules/@sentry/browser/build/npm/esm/prod/helpers.js +6 -0
- package/dist/node_modules/@sentry/browser/build/npm/esm/prod/helpers.js.map +1 -0
- package/dist/node_modules/@sentry/browser/build/npm/esm/prod/report-dialog.js +54 -0
- package/dist/node_modules/@sentry/browser/build/npm/esm/prod/report-dialog.js.map +1 -0
- package/dist/node_modules/@sentry/core/build/esm/api.js +41 -0
- package/dist/node_modules/@sentry/core/build/esm/api.js.map +1 -0
- package/dist/node_modules/@sentry/core/build/esm/asyncContext/index.js +13 -0
- package/dist/node_modules/@sentry/core/build/esm/asyncContext/index.js.map +1 -0
- package/dist/node_modules/@sentry/core/build/esm/asyncContext/stackStrategy.js +124 -0
- package/dist/node_modules/@sentry/core/build/esm/asyncContext/stackStrategy.js.map +1 -0
- package/dist/node_modules/@sentry/core/build/esm/carrier.js +22 -0
- package/dist/node_modules/@sentry/core/build/esm/carrier.js.map +1 -0
- package/dist/node_modules/@sentry/core/build/esm/currentScopes.js +34 -0
- package/dist/node_modules/@sentry/core/build/esm/currentScopes.js.map +1 -0
- package/dist/node_modules/@sentry/core/build/esm/debug-build.js +5 -0
- package/dist/node_modules/@sentry/core/build/esm/debug-build.js.map +1 -0
- package/dist/node_modules/@sentry/core/build/esm/defaultScopes.js +13 -0
- package/dist/node_modules/@sentry/core/build/esm/defaultScopes.js.map +1 -0
- package/dist/node_modules/@sentry/core/build/esm/exports.js +13 -0
- package/dist/node_modules/@sentry/core/build/esm/exports.js.map +1 -0
- package/dist/node_modules/@sentry/core/build/esm/scope.js +577 -0
- package/dist/node_modules/@sentry/core/build/esm/scope.js.map +1 -0
- package/dist/node_modules/@sentry/core/build/esm/session.js +61 -0
- package/dist/node_modules/@sentry/core/build/esm/session.js.map +1 -0
- package/dist/node_modules/@sentry/core/build/esm/utils/chain-and-copy-promiselike.js +39 -0
- package/dist/node_modules/@sentry/core/build/esm/utils/chain-and-copy-promiselike.js.map +1 -0
- package/dist/node_modules/@sentry/core/build/esm/utils/debug-logger.js +79 -0
- package/dist/node_modules/@sentry/core/build/esm/utils/debug-logger.js.map +1 -0
- package/dist/node_modules/@sentry/core/build/esm/utils/dsn.js +88 -0
- package/dist/node_modules/@sentry/core/build/esm/utils/dsn.js.map +1 -0
- package/dist/node_modules/@sentry/core/build/esm/utils/is.js +35 -0
- package/dist/node_modules/@sentry/core/build/esm/utils/is.js.map +1 -0
- package/dist/node_modules/@sentry/core/build/esm/utils/merge.js +19 -0
- package/dist/node_modules/@sentry/core/build/esm/utils/merge.js.map +1 -0
- package/dist/node_modules/@sentry/core/build/esm/utils/misc.js +32 -0
- package/dist/node_modules/@sentry/core/build/esm/utils/misc.js.map +1 -0
- package/dist/node_modules/@sentry/core/build/esm/utils/object.js +18 -0
- package/dist/node_modules/@sentry/core/build/esm/utils/object.js.map +1 -0
- package/dist/node_modules/@sentry/core/build/esm/utils/prepareEvent.js +34 -0
- package/dist/node_modules/@sentry/core/build/esm/utils/prepareEvent.js.map +1 -0
- package/dist/node_modules/@sentry/core/build/esm/utils/propagationContext.js +8 -0
- package/dist/node_modules/@sentry/core/build/esm/utils/propagationContext.js.map +1 -0
- package/dist/node_modules/@sentry/core/build/esm/utils/randomSafeContext.js +27 -0
- package/dist/node_modules/@sentry/core/build/esm/utils/randomSafeContext.js.map +1 -0
- package/dist/node_modules/@sentry/core/build/esm/utils/spanOnScope.js +17 -0
- package/dist/node_modules/@sentry/core/build/esm/utils/spanOnScope.js.map +1 -0
- package/dist/node_modules/@sentry/core/build/esm/utils/string.js +10 -0
- package/dist/node_modules/@sentry/core/build/esm/utils/string.js.map +1 -0
- package/dist/node_modules/@sentry/core/build/esm/utils/time.js +26 -0
- package/dist/node_modules/@sentry/core/build/esm/utils/time.js.map +1 -0
- package/dist/node_modules/@sentry/core/build/esm/utils/version.js +5 -0
- package/dist/node_modules/@sentry/core/build/esm/utils/version.js.map +1 -0
- package/dist/node_modules/@sentry/core/build/esm/utils/worldwide.js +5 -0
- package/dist/node_modules/@sentry/core/build/esm/utils/worldwide.js.map +1 -0
- package/dist/node_modules/@sentry/react/build/esm/debug-build.js +5 -0
- package/dist/node_modules/@sentry/react/build/esm/debug-build.js.map +1 -0
- package/dist/node_modules/@sentry/react/build/esm/error.js +40 -0
- package/dist/node_modules/@sentry/react/build/esm/error.js.map +1 -0
- package/dist/node_modules/@sentry/react/build/esm/errorboundary.js +103 -0
- package/dist/node_modules/@sentry/react/build/esm/errorboundary.js.map +1 -0
- package/dist/node_modules/@tabler/icons-react/dist/esm/createReactComponent.js +0 -6
- package/dist/node_modules/@tabler/icons-react/dist/esm/createReactComponent.js.map +1 -1
- package/dist/node_modules/@tabler/icons-react/dist/esm/defaultAttributes.js +0 -6
- package/dist/node_modules/@tabler/icons-react/dist/esm/defaultAttributes.js.map +1 -1
- package/dist/node_modules/@tabler/icons-react/dist/esm/icons/IconAdjustments.js +8 -0
- package/dist/node_modules/@tabler/icons-react/dist/esm/icons/IconAdjustments.js.map +1 -0
- package/dist/node_modules/@tabler/icons-react/dist/esm/icons/IconArrowRight.js +0 -6
- package/dist/node_modules/@tabler/icons-react/dist/esm/icons/IconArrowRight.js.map +1 -1
- package/dist/node_modules/@tabler/icons-react/dist/esm/icons/IconCheck.js +8 -0
- package/dist/node_modules/@tabler/icons-react/dist/esm/icons/IconCheck.js.map +1 -0
- package/dist/node_modules/@tabler/icons-react/dist/esm/icons/IconCircleCheck.js +0 -6
- package/dist/node_modules/@tabler/icons-react/dist/esm/icons/IconCircleCheck.js.map +1 -1
- package/dist/node_modules/@tabler/icons-react/dist/esm/icons/IconCircleX.js +0 -6
- package/dist/node_modules/@tabler/icons-react/dist/esm/icons/IconCircleX.js.map +1 -1
- package/dist/node_modules/@tabler/icons-react/dist/esm/icons/IconCopy.js +0 -6
- package/dist/node_modules/@tabler/icons-react/dist/esm/icons/IconCopy.js.map +1 -1
- package/dist/node_modules/@tabler/icons-react/dist/esm/icons/IconDots.js +0 -6
- package/dist/node_modules/@tabler/icons-react/dist/esm/icons/IconDots.js.map +1 -1
- package/dist/node_modules/@tabler/icons-react/dist/esm/icons/IconEdit.js +0 -6
- package/dist/node_modules/@tabler/icons-react/dist/esm/icons/IconEdit.js.map +1 -1
- package/dist/node_modules/@tabler/icons-react/dist/esm/icons/IconExclamationCircle.js +0 -6
- package/dist/node_modules/@tabler/icons-react/dist/esm/icons/IconExclamationCircle.js.map +1 -1
- package/dist/node_modules/@tabler/icons-react/dist/esm/icons/IconPlus.js +0 -6
- package/dist/node_modules/@tabler/icons-react/dist/esm/icons/IconPlus.js.map +1 -1
- package/dist/node_modules/@tabler/icons-react/dist/esm/icons/IconSearch.js +0 -6
- package/dist/node_modules/@tabler/icons-react/dist/esm/icons/IconSearch.js.map +1 -1
- package/dist/node_modules/@tabler/icons-react/dist/esm/icons/IconTrash.js +0 -6
- package/dist/node_modules/@tabler/icons-react/dist/esm/icons/IconTrash.js.map +1 -1
- package/dist/node_modules/react/cjs/react-jsx-runtime.development.js +1 -10
- package/dist/node_modules/react/cjs/react-jsx-runtime.development.js.map +1 -1
- package/dist/node_modules/react/cjs/react-jsx-runtime.production.js +1 -10
- package/dist/node_modules/react/cjs/react-jsx-runtime.production.js.map +1 -1
- package/dist/node_modules/react-router/dist/index.js +377 -0
- package/dist/node_modules/react-router/dist/index.js.map +1 -0
- package/dist/node_modules/react-router-dom/dist/index.js +560 -0
- package/dist/node_modules/react-router-dom/dist/index.js.map +1 -0
- package/dist/node_modules/zustand/esm/middleware.js +202 -0
- package/dist/node_modules/zustand/esm/middleware.js.map +1 -0
- package/dist/node_modules/zustand/esm/react.js +24 -0
- package/dist/node_modules/zustand/esm/react.js.map +1 -0
- package/dist/node_modules/zustand/esm/vanilla.js +26 -0
- package/dist/node_modules/zustand/esm/vanilla.js.map +1 -0
- package/dist/states/StoredTableState.d.ts +37 -0
- package/dist/states/StoredTableState.js +58 -0
- package/dist/states/StoredTableState.js.map +1 -0
- package/dist/types/Forms.d.ts +2 -0
- package/dist/types/Plugins.d.ts +14 -7
- package/dist/types/Plugins.js +1 -1
- package/dist/types/Plugins.js.map +1 -1
- package/dist/types/Tables.d.ts +10 -0
- package/lib/components/Boundary.tsx +46 -0
- package/lib/components/CopyButton.tsx +76 -0
- package/lib/components/CopyableCell.tsx +51 -0
- package/lib/components/InvenTreeTable.tsx +63 -0
- package/lib/components/TableColumnSelect.tsx +40 -0
- package/lib/enums/ApiEndpoints.tsx +1 -1
- package/lib/enums/ModelInformation.tsx +7 -0
- package/lib/enums/ModelType.tsx +1 -0
- package/lib/functions/Forms.tsx +47 -0
- package/lib/functions/Notification.tsx +50 -0
- package/lib/functions/String.tsx +38 -0
- package/lib/hooks/UseFilterSet.tsx +47 -0
- package/lib/hooks/UseTable.tsx +160 -0
- package/lib/index.ts +49 -1
- package/lib/states/StoredTableState.tsx +91 -0
- package/lib/types/Forms.tsx +2 -0
- package/lib/types/Plugins.tsx +15 -7
- package/lib/types/Tables.tsx +11 -0
- package/package.json +2 -2
package/dist/types/Plugins.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ import { ApiFormModalProps, BulkEditApiFormModalProps, StockOperationProps } fro
|
|
|
9
9
|
import { UseModalReturn } from './Modals';
|
|
10
10
|
import { RenderInstanceProps } from './Rendering';
|
|
11
11
|
import { SettingsStateProps } from './Settings';
|
|
12
|
+
import { InvenTreeTableRenderProps } from './Tables';
|
|
12
13
|
import { UserStateProps } from './User';
|
|
13
14
|
export interface PluginProps {
|
|
14
15
|
name: string;
|
|
@@ -39,6 +40,9 @@ export type InvenTreeFormsContext = {
|
|
|
39
40
|
edit: (props: ApiFormModalProps) => UseModalReturn;
|
|
40
41
|
stockActions: StockAdjustmentFormsContext;
|
|
41
42
|
};
|
|
43
|
+
export type InvenTreeTablesContext<T extends Record<string, any>> = {
|
|
44
|
+
renderTable: (props: InvenTreeTableRenderProps<T>) => React.ReactNode;
|
|
45
|
+
};
|
|
42
46
|
export type ImporterDrawerContext = {
|
|
43
47
|
open: (sessionId: number, options?: {
|
|
44
48
|
onClose?: () => void;
|
|
@@ -53,20 +57,22 @@ export type ImporterDrawerContext = {
|
|
|
53
57
|
*
|
|
54
58
|
* @param version - The version of the running InvenTree software stack
|
|
55
59
|
* @param api - The Axios API instance (see ../states/ApiState.tsx)
|
|
60
|
+
* @param queryClient - The Tanstack QueryClient instance (see ../states/QueryState.tsx)
|
|
56
61
|
* @param user - The current user instance (see ../states/UserState.tsx)
|
|
57
62
|
* @param userSettings - The current user settings (see ../states/SettingsState.tsx)
|
|
58
63
|
* @param globalSettings - The global settings (see ../states/SettingsState.tsx)
|
|
64
|
+
* @param modelInformation - A dictionary of available model information
|
|
65
|
+
* @param renderInstance - A component function for rendering a model instance
|
|
66
|
+
* @param host - The current host URL
|
|
67
|
+
* @param i18n - The i18n instance for translations (from @lingui/core)
|
|
68
|
+
* @param locale - The current locale string (e.g. 'en' / 'de')
|
|
59
69
|
* @param navigate - The navigation function (see react-router-dom)
|
|
60
70
|
* @param theme - The current Mantine theme
|
|
71
|
+
* @param colorScheme - The current Mantine color scheme (e.g. 'light' / 'dark')
|
|
61
72
|
* @param forms - A set of functions for opening various API forms (see ../components/Forms.tsx)
|
|
73
|
+
* @param tables - A set of functions for rendering API tables
|
|
62
74
|
* @param importer - A set of functions for controlling the global importer drawer (see ../components/importer/GlobalImporterDrawer.tsx)
|
|
63
|
-
* @param colorScheme - The current Mantine color scheme (e.g. 'light' / 'dark')
|
|
64
|
-
* @param host - The current host URL
|
|
65
|
-
* @param i18n - The i18n instance for translations (from @lingui/core)
|
|
66
|
-
* @param locale - The current locale string (e.g. 'en' / 'de')
|
|
67
75
|
* @param model - The model type associated with the rendered component (if applicable)
|
|
68
|
-
* @param modelInformation - A dictionary of available model information
|
|
69
|
-
* @param renderInstance - A component function for rendering a model instance
|
|
70
76
|
* @param id - The ID (primary key) of the model instance for the plugin (if applicable)
|
|
71
77
|
* @param instance - The model instance data (if available)
|
|
72
78
|
* @param reloadContent - A function which can be called to reload the plugin content
|
|
@@ -87,9 +93,10 @@ export type InvenTreePluginContext = {
|
|
|
87
93
|
locale: string;
|
|
88
94
|
navigate: NavigateFunction;
|
|
89
95
|
theme: MantineTheme;
|
|
96
|
+
colorScheme: MantineColorScheme;
|
|
90
97
|
forms: InvenTreeFormsContext;
|
|
98
|
+
tables: InvenTreeTablesContext<any>;
|
|
91
99
|
importer: ImporterDrawerContext;
|
|
92
|
-
colorScheme: MantineColorScheme;
|
|
93
100
|
model?: ModelType | string;
|
|
94
101
|
id?: string | number | null;
|
|
95
102
|
instance?: any;
|
package/dist/types/Plugins.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Plugins.js","sources":["../../lib/types/Plugins.tsx"],"sourcesContent":["import type { I18n } from '@lingui/core';\nimport type { MantineColorScheme, MantineTheme } from '@mantine/core';\nimport type { QueryClient } from '@tanstack/react-query';\nimport type { AxiosInstance } from 'axios';\nimport type { NavigateFunction } from 'react-router-dom';\nimport type { ModelDict } from '../enums/ModelInformation';\nimport type { ModelType } from '../enums/ModelType';\nimport type {\n ApiFormModalProps,\n BulkEditApiFormModalProps,\n StockOperationProps\n} from './Forms';\nimport type { UseModalReturn } from './Modals';\nimport type { RenderInstanceProps } from './Rendering';\nimport type { SettingsStateProps } from './Settings';\nimport type { UserStateProps } from './User';\n\nexport interface PluginProps {\n name: string;\n slug: string;\n version: null | string;\n}\n\nexport interface PluginVersion {\n inventree: string;\n react: string;\n reactDom: string;\n mantine: string;\n}\n\nexport type StockAdjustmentFormsContext = {\n addStock: (props: StockOperationProps) => UseModalReturn;\n assignStock: (props: StockOperationProps) => UseModalReturn;\n changeStatus: (props: StockOperationProps) => UseModalReturn;\n countStock: (props: StockOperationProps) => UseModalReturn;\n deleteStock: (props: StockOperationProps) => UseModalReturn;\n mergeStock: (props: StockOperationProps) => UseModalReturn;\n removeStock: (props: StockOperationProps) => UseModalReturn;\n transferStock: (props: StockOperationProps) => UseModalReturn;\n returnStock: (props: StockOperationProps) => UseModalReturn;\n};\n\nexport type InvenTreeFormsContext = {\n bulkEdit: (props: BulkEditApiFormModalProps) => UseModalReturn;\n create: (props: ApiFormModalProps) => UseModalReturn;\n delete: (props: ApiFormModalProps) => UseModalReturn;\n edit: (props: ApiFormModalProps) => UseModalReturn;\n stockActions: StockAdjustmentFormsContext;\n};\n\nexport type ImporterDrawerContext = {\n open: (sessionId: number, options?: { onClose?: () => void }) => void;\n close: () => void;\n isOpen: () => boolean;\n sessionId: () => number | null;\n};\n\n/**\n * A set of properties which are passed to a plugin,\n * for rendering an element in the user interface.\n *\n * @param version - The version of the running InvenTree software stack\n * @param api - The Axios API instance (see ../states/ApiState.tsx)\n * @param
|
|
1
|
+
{"version":3,"file":"Plugins.js","sources":["../../lib/types/Plugins.tsx"],"sourcesContent":["import type { I18n } from '@lingui/core';\nimport type { MantineColorScheme, MantineTheme } from '@mantine/core';\nimport type { QueryClient } from '@tanstack/react-query';\nimport type { AxiosInstance } from 'axios';\nimport type { NavigateFunction } from 'react-router-dom';\nimport type { ModelDict } from '../enums/ModelInformation';\nimport type { ModelType } from '../enums/ModelType';\nimport type {\n ApiFormModalProps,\n BulkEditApiFormModalProps,\n StockOperationProps\n} from './Forms';\nimport type { UseModalReturn } from './Modals';\nimport type { RenderInstanceProps } from './Rendering';\nimport type { SettingsStateProps } from './Settings';\nimport type { InvenTreeTableRenderProps } from './Tables';\nimport type { UserStateProps } from './User';\n\nexport interface PluginProps {\n name: string;\n slug: string;\n version: null | string;\n}\n\nexport interface PluginVersion {\n inventree: string;\n react: string;\n reactDom: string;\n mantine: string;\n}\n\nexport type StockAdjustmentFormsContext = {\n addStock: (props: StockOperationProps) => UseModalReturn;\n assignStock: (props: StockOperationProps) => UseModalReturn;\n changeStatus: (props: StockOperationProps) => UseModalReturn;\n countStock: (props: StockOperationProps) => UseModalReturn;\n deleteStock: (props: StockOperationProps) => UseModalReturn;\n mergeStock: (props: StockOperationProps) => UseModalReturn;\n removeStock: (props: StockOperationProps) => UseModalReturn;\n transferStock: (props: StockOperationProps) => UseModalReturn;\n returnStock: (props: StockOperationProps) => UseModalReturn;\n};\n\nexport type InvenTreeFormsContext = {\n bulkEdit: (props: BulkEditApiFormModalProps) => UseModalReturn;\n create: (props: ApiFormModalProps) => UseModalReturn;\n delete: (props: ApiFormModalProps) => UseModalReturn;\n edit: (props: ApiFormModalProps) => UseModalReturn;\n stockActions: StockAdjustmentFormsContext;\n};\n\nexport type InvenTreeTablesContext<T extends Record<string, any>> = {\n renderTable: (props: InvenTreeTableRenderProps<T>) => React.ReactNode;\n};\n\nexport type ImporterDrawerContext = {\n open: (sessionId: number, options?: { onClose?: () => void }) => void;\n close: () => void;\n isOpen: () => boolean;\n sessionId: () => number | null;\n};\n\n/**\n * A set of properties which are passed to a plugin,\n * for rendering an element in the user interface.\n *\n * @param version - The version of the running InvenTree software stack\n * @param api - The Axios API instance (see ../states/ApiState.tsx)\n * @param queryClient - The Tanstack QueryClient instance (see ../states/QueryState.tsx)\n * @param user - The current user instance (see ../states/UserState.tsx)\n * @param userSettings - The current user settings (see ../states/SettingsState.tsx)\n * @param globalSettings - The global settings (see ../states/SettingsState.tsx)\n * @param modelInformation - A dictionary of available model information\n * @param renderInstance - A component function for rendering a model instance\n * @param host - The current host URL\n * @param i18n - The i18n instance for translations (from @lingui/core)\n * @param locale - The current locale string (e.g. 'en' / 'de')\n * @param navigate - The navigation function (see react-router-dom)\n * @param theme - The current Mantine theme\n * @param colorScheme - The current Mantine color scheme (e.g. 'light' / 'dark')\n * @param forms - A set of functions for opening various API forms (see ../components/Forms.tsx)\n * @param tables - A set of functions for rendering API tables\n * @param importer - A set of functions for controlling the global importer drawer (see ../components/importer/GlobalImporterDrawer.tsx)\n * @param model - The model type associated with the rendered component (if applicable)\n * @param id - The ID (primary key) of the model instance for the plugin (if applicable)\n * @param instance - The model instance data (if available)\n * @param reloadContent - A function which can be called to reload the plugin content\n * @param reloadInstance - A function which can be called to reload the model instance\n * @param context - Any additional context data which may be passed to the plugin\n */\nexport type InvenTreePluginContext = {\n version: PluginVersion;\n api: AxiosInstance;\n queryClient: QueryClient;\n user: UserStateProps;\n userSettings: SettingsStateProps;\n globalSettings: SettingsStateProps;\n modelInformation: ModelDict;\n renderInstance: (props: Readonly<RenderInstanceProps>) => React.ReactNode;\n host: string;\n i18n: I18n;\n locale: string;\n navigate: NavigateFunction;\n theme: MantineTheme;\n colorScheme: MantineColorScheme;\n forms: InvenTreeFormsContext;\n tables: InvenTreeTablesContext<any>;\n importer: ImporterDrawerContext;\n model?: ModelType | string;\n id?: string | number | null;\n instance?: any;\n reloadContent?: () => void;\n reloadInstance?: () => void;\n context?: any;\n};\n\n/*\n * The version of the InvenTree plugin context interface.\n * This number should be incremented if the interface changes.\n */\n\n// @ts-ignore\nexport const INVENTREE_PLUGIN_VERSION: string = __INVENTREE_LIB_VERSION__;\n// @ts-ignore\nexport const INVENTREE_REACT_VERSION: string = __INVENTREE_REACT_VERSION__;\n// @ts-ignore\nexport const INVENTREE_REACT_DOM_VERSION: string =\n // @ts-ignore\n __INVENTREE_REACT_DOM_VERSION__;\n// @ts-ignore\nexport const INVENTREE_MANTINE_VERSION: string = __INVENTREE_MANTINE_VERSION__;\n"],"names":["INVENTREE_PLUGIN_VERSION","__INVENTREE_LIB_VERSION__","INVENTREE_REACT_VERSION","__INVENTREE_REACT_VERSION__","INVENTREE_REACT_DOM_VERSION","__INVENTREE_REACT_DOM_VERSION__","INVENTREE_MANTINE_VERSION","__INVENTREE_MANTINE_VERSION__"],"mappings":"AA0HO,MAAMA,2BAAmCC;AAEzC,MAAMC,0BAAkCC;AAExC,MAAMC;AAAAA;AAAAA,EAEXC;AAAAA;AAEK,MAAMC,4BAAoCC;"}
|
package/dist/types/Tables.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { MantineStyleProp } from '@mantine/core';
|
|
2
|
+
import { AxiosInstance } from 'axios';
|
|
2
3
|
import { DataTableCellClickHandler, DataTableRowExpansionProps } from 'mantine-datatable';
|
|
3
4
|
import { ReactNode } from 'react';
|
|
4
5
|
import { NavigateFunction, SetURLSearchParams } from 'react-router-dom';
|
|
@@ -174,4 +175,13 @@ export type InvenTreeTableProps<T = any> = {
|
|
|
174
175
|
minHeight?: number;
|
|
175
176
|
noHeader?: boolean;
|
|
176
177
|
};
|
|
178
|
+
export type InvenTreeTableRenderProps<T extends Record<string, any>> = {
|
|
179
|
+
url?: string;
|
|
180
|
+
tableState: TableState;
|
|
181
|
+
tableData?: T[];
|
|
182
|
+
columns: TableColumn<T>[];
|
|
183
|
+
props: InvenTreeTableProps<T>;
|
|
184
|
+
api: AxiosInstance;
|
|
185
|
+
navigate: NavigateFunction;
|
|
186
|
+
};
|
|
177
187
|
export {};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { t } from '@lingui/core/macro';
|
|
2
|
+
import { Alert } from '@mantine/core';
|
|
3
|
+
import { ErrorBoundary, type FallbackRender } from '@sentry/react';
|
|
4
|
+
import { IconExclamationCircle } from '@tabler/icons-react';
|
|
5
|
+
import { type ReactNode, useCallback } from 'react';
|
|
6
|
+
|
|
7
|
+
export function DefaultFallback({
|
|
8
|
+
title
|
|
9
|
+
}: Readonly<{ title: string }>): ReactNode {
|
|
10
|
+
return (
|
|
11
|
+
<Alert
|
|
12
|
+
color='red'
|
|
13
|
+
icon={<IconExclamationCircle />}
|
|
14
|
+
title={`${t`Error rendering component`}: ${title}`}
|
|
15
|
+
>
|
|
16
|
+
{t`An error occurred while rendering this component. Refer to the console for more information.`}
|
|
17
|
+
</Alert>
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function Boundary({
|
|
22
|
+
children,
|
|
23
|
+
label,
|
|
24
|
+
fallback
|
|
25
|
+
}: Readonly<{
|
|
26
|
+
children: ReactNode;
|
|
27
|
+
label: string;
|
|
28
|
+
fallback?: React.ReactElement<any> | FallbackRender;
|
|
29
|
+
}>): ReactNode {
|
|
30
|
+
const onError = useCallback(
|
|
31
|
+
(error: unknown, componentStack: string | undefined, eventId: string) => {
|
|
32
|
+
console.error(`ERR: Error rendering component: ${label}`);
|
|
33
|
+
console.error(error);
|
|
34
|
+
},
|
|
35
|
+
[]
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<ErrorBoundary
|
|
40
|
+
fallback={fallback ?? <DefaultFallback title={label} />}
|
|
41
|
+
onError={onError}
|
|
42
|
+
>
|
|
43
|
+
{children}
|
|
44
|
+
</ErrorBoundary>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { t } from '@lingui/core/macro';
|
|
2
|
+
import {
|
|
3
|
+
ActionIcon,
|
|
4
|
+
type ActionIconVariant,
|
|
5
|
+
Button,
|
|
6
|
+
type DefaultMantineColor,
|
|
7
|
+
type FloatingPosition,
|
|
8
|
+
CopyButton as MantineCopyButton,
|
|
9
|
+
type MantineSize,
|
|
10
|
+
Text,
|
|
11
|
+
Tooltip
|
|
12
|
+
} from '@mantine/core';
|
|
13
|
+
import { IconCheck, IconCopy } from '@tabler/icons-react';
|
|
14
|
+
|
|
15
|
+
import type { JSX } from 'react';
|
|
16
|
+
|
|
17
|
+
export function CopyButton({
|
|
18
|
+
value,
|
|
19
|
+
label,
|
|
20
|
+
tooltip,
|
|
21
|
+
disabled,
|
|
22
|
+
tooltipPosition,
|
|
23
|
+
content,
|
|
24
|
+
size,
|
|
25
|
+
color = 'gray',
|
|
26
|
+
variant = 'transparent'
|
|
27
|
+
}: Readonly<{
|
|
28
|
+
value: any;
|
|
29
|
+
label?: string;
|
|
30
|
+
tooltip?: string;
|
|
31
|
+
disabled?: boolean;
|
|
32
|
+
tooltipPosition?: FloatingPosition;
|
|
33
|
+
content?: JSX.Element;
|
|
34
|
+
size?: MantineSize;
|
|
35
|
+
color?: DefaultMantineColor;
|
|
36
|
+
variant?: ActionIconVariant;
|
|
37
|
+
}>) {
|
|
38
|
+
const ButtonComponent = label ? Button : ActionIcon;
|
|
39
|
+
|
|
40
|
+
// Disable the copy button if we are not in a secure context, as the Clipboard API is not available
|
|
41
|
+
if (!window.isSecureContext) {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<MantineCopyButton value={value}>
|
|
47
|
+
{({ copied, copy }) => (
|
|
48
|
+
<Tooltip
|
|
49
|
+
label={copied ? t`Copied` : (tooltip ?? t`Copy`)}
|
|
50
|
+
withArrow
|
|
51
|
+
position={tooltipPosition}
|
|
52
|
+
>
|
|
53
|
+
<ButtonComponent
|
|
54
|
+
disabled={disabled}
|
|
55
|
+
color={copied ? 'teal' : color}
|
|
56
|
+
onClick={(e: any) => {
|
|
57
|
+
e.stopPropagation();
|
|
58
|
+
e.preventDefault();
|
|
59
|
+
copy();
|
|
60
|
+
}}
|
|
61
|
+
variant={copied ? 'transparent' : (variant ?? 'transparent')}
|
|
62
|
+
size={size ?? 'sm'}
|
|
63
|
+
>
|
|
64
|
+
{copied ? <IconCheck /> : <IconCopy />}
|
|
65
|
+
{content}
|
|
66
|
+
{label && (
|
|
67
|
+
<Text p={size ?? 'sm'} size={size ?? 'sm'}>
|
|
68
|
+
{label}
|
|
69
|
+
</Text>
|
|
70
|
+
)}
|
|
71
|
+
</ButtonComponent>
|
|
72
|
+
</Tooltip>
|
|
73
|
+
)}
|
|
74
|
+
</MantineCopyButton>
|
|
75
|
+
);
|
|
76
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { Group } from '@mantine/core';
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { CopyButton } from './CopyButton';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A wrapper component that adds a copy button to cell content on hover
|
|
7
|
+
* This component is used to make table cells copyable without adding visual clutter
|
|
8
|
+
*
|
|
9
|
+
* @param children - The cell content to render
|
|
10
|
+
* @param value - The value to copy when the copy button is clicked
|
|
11
|
+
*/
|
|
12
|
+
export function CopyableCell({
|
|
13
|
+
children,
|
|
14
|
+
value
|
|
15
|
+
}: Readonly<{
|
|
16
|
+
children: React.ReactNode;
|
|
17
|
+
value: string;
|
|
18
|
+
}>) {
|
|
19
|
+
const [isHovered, setIsHovered] = useState(false);
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<Group
|
|
23
|
+
gap={0}
|
|
24
|
+
p={0}
|
|
25
|
+
wrap='nowrap'
|
|
26
|
+
onMouseEnter={() => setIsHovered(true)}
|
|
27
|
+
onMouseLeave={() => setIsHovered(false)}
|
|
28
|
+
justify='space-between'
|
|
29
|
+
align='center'
|
|
30
|
+
>
|
|
31
|
+
{children}
|
|
32
|
+
{window.isSecureContext && isHovered && value != null && (
|
|
33
|
+
<span
|
|
34
|
+
style={{ position: 'relative' }}
|
|
35
|
+
onClick={(e) => e.stopPropagation()}
|
|
36
|
+
onKeyDown={(e) => e.stopPropagation()}
|
|
37
|
+
>
|
|
38
|
+
<div
|
|
39
|
+
style={{
|
|
40
|
+
position: 'absolute',
|
|
41
|
+
right: 0,
|
|
42
|
+
transform: 'translateY(-50%)'
|
|
43
|
+
}}
|
|
44
|
+
>
|
|
45
|
+
<CopyButton value={value} variant={'default'} />
|
|
46
|
+
</div>
|
|
47
|
+
</span>
|
|
48
|
+
)}
|
|
49
|
+
</Group>
|
|
50
|
+
);
|
|
51
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { Alert } from '@mantine/core';
|
|
2
|
+
import {
|
|
3
|
+
INVENTREE_PLUGIN_VERSION,
|
|
4
|
+
type InvenTreePluginContext
|
|
5
|
+
} from '../types/Plugins';
|
|
6
|
+
import type {
|
|
7
|
+
InvenTreeTableProps,
|
|
8
|
+
TableColumn,
|
|
9
|
+
TableState
|
|
10
|
+
} from '../types/Tables';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Wrapper function which allows plugins to render an InvenTree component instance directly,
|
|
14
|
+
* in a similar way to the standard InvenTreeTable component.
|
|
15
|
+
*
|
|
16
|
+
* Note: The InventreePluginContext "context" object must be provided when rendering the table
|
|
17
|
+
*
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
export default function InvenTreeTable({
|
|
21
|
+
url,
|
|
22
|
+
tableState,
|
|
23
|
+
tableData,
|
|
24
|
+
columns,
|
|
25
|
+
props,
|
|
26
|
+
context
|
|
27
|
+
}: {
|
|
28
|
+
url?: string;
|
|
29
|
+
tableState: TableState;
|
|
30
|
+
tableData?: any[];
|
|
31
|
+
columns: TableColumn<any>[];
|
|
32
|
+
props: InvenTreeTableProps;
|
|
33
|
+
context: InvenTreePluginContext;
|
|
34
|
+
}) {
|
|
35
|
+
if (!context?.tables?.renderTable) {
|
|
36
|
+
return (
|
|
37
|
+
<Alert title='Plugin Version Error' color='red'>
|
|
38
|
+
{
|
|
39
|
+
'The <InvenTreeTable> component cannot be rendered because the plugin context is missing the "renderTable" function.'
|
|
40
|
+
}
|
|
41
|
+
<br />
|
|
42
|
+
{
|
|
43
|
+
'This means that the InvenTree UI library version is incompatible with this plugin version.'
|
|
44
|
+
}
|
|
45
|
+
<br />
|
|
46
|
+
<b>Plugin Version:</b> {INVENTREE_PLUGIN_VERSION}
|
|
47
|
+
<br />
|
|
48
|
+
<b>UI Version:</b> {context?.version?.inventree || 'unknown'}
|
|
49
|
+
<br />
|
|
50
|
+
</Alert>
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return context?.tables.renderTable({
|
|
55
|
+
url: url,
|
|
56
|
+
tableState: tableState,
|
|
57
|
+
tableData: tableData,
|
|
58
|
+
columns: columns,
|
|
59
|
+
props: props,
|
|
60
|
+
api: context.api,
|
|
61
|
+
navigate: context.navigate
|
|
62
|
+
});
|
|
63
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { t } from '@lingui/core/macro';
|
|
2
|
+
import { ActionIcon, Checkbox, Divider, Menu, Tooltip } from '@mantine/core';
|
|
3
|
+
import { IconAdjustments } from '@tabler/icons-react';
|
|
4
|
+
|
|
5
|
+
export function TableColumnSelect({
|
|
6
|
+
columns,
|
|
7
|
+
onToggleColumn
|
|
8
|
+
}: Readonly<{
|
|
9
|
+
columns: any[];
|
|
10
|
+
onToggleColumn: (columnName: string) => void;
|
|
11
|
+
}>) {
|
|
12
|
+
return (
|
|
13
|
+
<Menu shadow='xs' closeOnItemClick={false}>
|
|
14
|
+
<Menu.Target>
|
|
15
|
+
<ActionIcon variant='transparent' aria-label='table-select-columns'>
|
|
16
|
+
<Tooltip label={t`Select Columns`} position='top-end'>
|
|
17
|
+
<IconAdjustments />
|
|
18
|
+
</Tooltip>
|
|
19
|
+
</ActionIcon>
|
|
20
|
+
</Menu.Target>
|
|
21
|
+
|
|
22
|
+
<Menu.Dropdown style={{ maxHeight: '400px', overflowY: 'auto' }}>
|
|
23
|
+
<Menu.Label>{t`Select Columns`}</Menu.Label>
|
|
24
|
+
<Divider />
|
|
25
|
+
{columns
|
|
26
|
+
.filter((col) => col.switchable ?? true)
|
|
27
|
+
.map((col) => (
|
|
28
|
+
<Menu.Item key={col.accessor}>
|
|
29
|
+
<Checkbox
|
|
30
|
+
checked={!col.hidden}
|
|
31
|
+
label={col.title || col.accessor}
|
|
32
|
+
onChange={() => onToggleColumn(col.accessor)}
|
|
33
|
+
radius='sm'
|
|
34
|
+
/>
|
|
35
|
+
</Menu.Item>
|
|
36
|
+
))}
|
|
37
|
+
</Menu.Dropdown>
|
|
38
|
+
</Menu>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
@@ -64,7 +64,7 @@ export enum ApiEndpoints {
|
|
|
64
64
|
content_type_list = 'contenttype/',
|
|
65
65
|
icons = 'icons/',
|
|
66
66
|
selectionlist_list = 'selection/',
|
|
67
|
-
|
|
67
|
+
selectionentry_list = 'selection/:id/entry/',
|
|
68
68
|
|
|
69
69
|
// Barcode API endpoints
|
|
70
70
|
barcode = 'barcode/',
|
|
@@ -287,6 +287,13 @@ export const ModelInformationDict: ModelDict = {
|
|
|
287
287
|
api_endpoint: ApiEndpoints.selectionlist_list,
|
|
288
288
|
icon: 'list_details'
|
|
289
289
|
},
|
|
290
|
+
selectionentry: {
|
|
291
|
+
label: () => t`Selection Entry`,
|
|
292
|
+
label_multiple: () => t`Selection Entries`,
|
|
293
|
+
url_overview: '/settings/admin/part-parameters',
|
|
294
|
+
api_endpoint: ApiEndpoints.selectionentry_list,
|
|
295
|
+
icon: 'list_details'
|
|
296
|
+
},
|
|
290
297
|
error: {
|
|
291
298
|
label: () => t`Error`,
|
|
292
299
|
label_multiple: () => t`Errors`,
|
package/lib/enums/ModelType.tsx
CHANGED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { ApiEndpoints } from '../enums/ApiEndpoints';
|
|
2
|
+
import type { PathParams } from '../types/Core';
|
|
3
|
+
import type { ApiFormFieldSet, ApiFormFieldType } from '../types/Forms';
|
|
4
|
+
import { apiUrl } from './Api';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Construct an API url from the provided ApiFormProps object
|
|
8
|
+
*/
|
|
9
|
+
export function constructFormUrl(
|
|
10
|
+
url: ApiEndpoints | string,
|
|
11
|
+
pk?: string | number,
|
|
12
|
+
pathParams?: PathParams,
|
|
13
|
+
queryParams?: URLSearchParams
|
|
14
|
+
): string {
|
|
15
|
+
let formUrl = apiUrl(url, pk, pathParams);
|
|
16
|
+
|
|
17
|
+
if (queryParams) {
|
|
18
|
+
formUrl += `?${queryParams.toString()}`;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return formUrl;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export type NestedDict = { [key: string]: string | number | NestedDict };
|
|
25
|
+
|
|
26
|
+
export function mapFields(
|
|
27
|
+
fields: ApiFormFieldSet,
|
|
28
|
+
fieldFunction: (path: string, value: ApiFormFieldType, key: string) => any,
|
|
29
|
+
_path?: string
|
|
30
|
+
): NestedDict {
|
|
31
|
+
const res: NestedDict = {};
|
|
32
|
+
|
|
33
|
+
for (const [k, v] of Object.entries(fields)) {
|
|
34
|
+
const path = _path ? `${_path}.${k}` : k;
|
|
35
|
+
let value: any;
|
|
36
|
+
|
|
37
|
+
if (v.field_type === 'nested object' && v.children) {
|
|
38
|
+
value = mapFields(v.children, fieldFunction, path);
|
|
39
|
+
} else {
|
|
40
|
+
value = fieldFunction(path, v, k);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (value !== undefined) res[k] = value;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return res;
|
|
47
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { t } from '@lingui/core/macro';
|
|
2
|
+
import { notifications } from '@mantine/notifications';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Show a notification that the feature is not yet implemented
|
|
6
|
+
*/
|
|
7
|
+
export function notYetImplemented() {
|
|
8
|
+
notifications.hide('not-implemented');
|
|
9
|
+
|
|
10
|
+
notifications.show({
|
|
11
|
+
title: t`Not implemented`,
|
|
12
|
+
message: t`This feature is not yet implemented`,
|
|
13
|
+
color: 'red',
|
|
14
|
+
id: 'not-implemented'
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Show a notification that the user does not have permission to perform the action
|
|
20
|
+
*/
|
|
21
|
+
export function permissionDenied() {
|
|
22
|
+
notifications.show({
|
|
23
|
+
title: t`Permission Denied`,
|
|
24
|
+
message: t`You do not have permission to perform this action`,
|
|
25
|
+
color: 'red'
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Display a notification on an invalid return code
|
|
31
|
+
*/
|
|
32
|
+
export function invalidResponse(returnCode: number) {
|
|
33
|
+
// TODO: Specific return code messages
|
|
34
|
+
notifications.show({
|
|
35
|
+
title: t`Invalid Return Code`,
|
|
36
|
+
message: t`Server returned status ${returnCode}`,
|
|
37
|
+
color: 'red'
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Display a notification on timeout
|
|
43
|
+
*/
|
|
44
|
+
export function showTimeoutNotification() {
|
|
45
|
+
notifications.show({
|
|
46
|
+
title: t`Timeout`,
|
|
47
|
+
message: t`The request timed out`,
|
|
48
|
+
color: 'red'
|
|
49
|
+
});
|
|
50
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reduce an input string to a given length, adding an ellipsis if necessary
|
|
3
|
+
* @param str - String to shorten
|
|
4
|
+
* @param len - Length to shorten to
|
|
5
|
+
*/
|
|
6
|
+
export function shortenString({
|
|
7
|
+
str,
|
|
8
|
+
len = 100
|
|
9
|
+
}: {
|
|
10
|
+
str: string | undefined;
|
|
11
|
+
len?: number;
|
|
12
|
+
}) {
|
|
13
|
+
// Ensure that the string is a string
|
|
14
|
+
str = str ?? '';
|
|
15
|
+
str = str.toString();
|
|
16
|
+
|
|
17
|
+
// If the string is already short enough, return it
|
|
18
|
+
if (str.length <= len) {
|
|
19
|
+
return str;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Otherwise, shorten it
|
|
23
|
+
const N = Math.floor(len / 2 - 1);
|
|
24
|
+
|
|
25
|
+
return `${str.slice(0, N)} ... ${str.slice(-N)}`;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Generate a short hash from a long string
|
|
30
|
+
*/
|
|
31
|
+
export function hashString(str: string): string {
|
|
32
|
+
let hash = 0;
|
|
33
|
+
for (let i = 0; i < str.length; i++) {
|
|
34
|
+
hash = (hash << 5) - hash + str.charCodeAt(i);
|
|
35
|
+
hash |= 0; // Convert to 32bit integer
|
|
36
|
+
}
|
|
37
|
+
return hash.toString(36);
|
|
38
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { useLocalStorage } from '@mantine/hooks';
|
|
2
|
+
import { useCallback, useMemo } from 'react';
|
|
3
|
+
import type { FilterSetState, TableFilter } from '../types/Filters';
|
|
4
|
+
|
|
5
|
+
export default function useFilterSet(
|
|
6
|
+
filterKey: string,
|
|
7
|
+
initialFilters?: TableFilter[]
|
|
8
|
+
): FilterSetState {
|
|
9
|
+
// Array of active filters (saved to local storage)
|
|
10
|
+
const [storedFilters, setStoredFilters] = useLocalStorage<
|
|
11
|
+
TableFilter[] | null
|
|
12
|
+
>({
|
|
13
|
+
key: `inventree-filterset-${filterKey}`,
|
|
14
|
+
defaultValue: null,
|
|
15
|
+
sync: false,
|
|
16
|
+
getInitialValueInEffect: false
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
const activeFilters: TableFilter[] = useMemo(() => {
|
|
20
|
+
if (storedFilters == null) {
|
|
21
|
+
// If there are no stored filters, set initial values
|
|
22
|
+
const filters = initialFilters || [];
|
|
23
|
+
setStoredFilters(filters);
|
|
24
|
+
return filters;
|
|
25
|
+
}
|
|
26
|
+
return storedFilters || [];
|
|
27
|
+
}, [storedFilters]);
|
|
28
|
+
|
|
29
|
+
// Callback to clear all active filters from the table
|
|
30
|
+
const clearActiveFilters = useCallback(() => {
|
|
31
|
+
setStoredFilters([]);
|
|
32
|
+
}, []);
|
|
33
|
+
|
|
34
|
+
const setActiveFilters = useCallback(
|
|
35
|
+
(filters: TableFilter[]) => {
|
|
36
|
+
setStoredFilters(filters);
|
|
37
|
+
},
|
|
38
|
+
[setStoredFilters]
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
filterKey,
|
|
43
|
+
activeFilters,
|
|
44
|
+
setActiveFilters,
|
|
45
|
+
clearActiveFilters
|
|
46
|
+
};
|
|
47
|
+
}
|