@k-int/stripes-kint-components 5.17.0 → 5.19.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 +20 -0
- package/LICENSE +1 -1
- package/es/index.js +32 -12
- package/es/lib/EditableSettingsList/EditableSettingsList.js +4 -3
- package/es/lib/EditableSettingsList/EditableSettingsListFieldArray/EditableSettingsListFieldArray.js +110 -0
- package/es/lib/EditableSettingsList/{EditableSettingsListFieldArray.test.js → EditableSettingsListFieldArray/EditableSettingsListFieldArray.test.js} +3 -4
- package/es/lib/EditableSettingsList/EditableSettingsListFieldArray/index.js +13 -0
- package/es/lib/EditableSettingsList/SettingField/{EditSettingValue.js → EditSettingValue/EditSettingValue.js} +2 -2
- package/es/lib/EditableSettingsList/SettingField/{EditSettingValue.test.js → EditSettingValue/EditSettingValue.test.js} +2 -3
- package/es/lib/EditableSettingsList/SettingField/EditSettingValue/index.js +13 -0
- package/es/lib/EditableSettingsList/SettingField/{RenderSettingValue.js → RenderSettingValue/RenderSettingValue.js} +1 -1
- package/es/lib/EditableSettingsList/SettingField/{RenderSettingValue.test.js → RenderSettingValue/RenderSettingValue.test.js} +2 -2
- package/es/lib/EditableSettingsList/SettingField/RenderSettingValue/index.js +13 -0
- package/es/lib/EditableSettingsList/SettingField/SettingField.js +5 -5
- package/es/lib/EditableSettingsList/SettingField/SettingField.test.js +54 -44
- package/es/lib/EditableSettingsList/index.js +12 -0
- package/es/lib/SASQLookupComponent/SASQLookupComponent.js +5 -1
- package/es/lib/SearchKeyControl/SearchKeyControl.js +95 -0
- package/es/lib/SearchKeyControl/SearchKeyControl.test.js +177 -0
- package/es/lib/SearchKeyControl/index.js +13 -0
- package/es/lib/SettingPage/SettingPage.js +3 -1
- package/es/lib/SettingPage/{SettingPagePane.js → SettingPagePane/SettingPagePane.js} +2 -2
- package/es/lib/SettingPage/SettingPagePane/index.js +13 -0
- package/es/lib/hooks/__mocks__/index.js +2 -2
- package/es/lib/hooks/index.js +33 -21
- package/es/lib/hooks/intlHooks/index.js +27 -0
- package/es/lib/hooks/intlHooks/useIntlKey/index.js +13 -0
- package/es/lib/hooks/{useIntlKey.js → intlHooks/useIntlKey/useIntlKey.js} +1 -1
- package/es/lib/hooks/intlHooks/useIntlKeyStore/index.js +13 -0
- package/es/lib/hooks/intlHooks/useKintIntl/index.js +13 -0
- package/es/lib/hooks/{useKintIntl.js → intlHooks/useKintIntl/useKintIntl.js} +1 -1
- package/es/lib/hooks/useInvalidateRefdata/index.js +13 -0
- package/es/lib/hooks/{useInvalidateRefdata.js → useInvalidateRefdata/useInvalidateRefdata.js} +1 -1
- package/es/lib/hooks/useMutateCustomProperties/index.js +13 -0
- package/es/lib/hooks/{useMutateCustomProperties.js → useMutateCustomProperties/useMutateCustomProperties.js} +1 -1
- package/es/lib/hooks/useMutateGeneric/index.js +13 -0
- package/es/lib/hooks/useMutateRefdataCategory/index.js +13 -0
- package/es/lib/hooks/{useMutateRefdataCategory.js → useMutateRefdataCategory/useMutateRefdataCategory.js} +2 -2
- package/es/lib/hooks/useMutateRefdataValue/index.js +13 -0
- package/es/lib/hooks/{useMutateRefdataValue.js → useMutateRefdataValue/useMutateRefdataValue.js} +2 -2
- package/es/lib/settingsHooks/useAppSettings/index.js +13 -0
- package/es/lib/settingsHooks/{useAppSettings.js → useAppSettings/useAppSettings.js} +1 -1
- package/es/lib/settingsHooks/useSettingSection/index.js +13 -0
- package/es/lib/settingsHooks/{useSettingSection.js → useSettingSection/useSettingSection.js} +1 -1
- package/es/lib/settingsHooks/useSettings/index.js +13 -0
- package/es/lib/settingsHooks/{useSettings.js → useSettings/useSettings.js} +10 -9
- package/es/lib/utils/refdataQueryKey/index.js +13 -0
- package/package.json +1 -1
- package/src/index.js +8 -3
- package/src/lib/ActionList/README.md +18 -18
- package/src/lib/EditableSettingsList/EditableSettingsList.js +3 -2
- package/src/lib/EditableSettingsList/EditableSettingsListFieldArray/EditableSettingsListFieldArray.js +118 -0
- package/src/lib/EditableSettingsList/{EditableSettingsListFieldArray.test.js → EditableSettingsListFieldArray/EditableSettingsListFieldArray.test.js} +3 -5
- package/src/lib/EditableSettingsList/EditableSettingsListFieldArray/README.md +68 -0
- package/src/lib/EditableSettingsList/EditableSettingsListFieldArray/index.js +1 -0
- package/src/lib/EditableSettingsList/README.md +74 -0
- package/src/lib/EditableSettingsList/SettingField/{EditSettingValue.js → EditSettingValue/EditSettingValue.js} +2 -2
- package/src/lib/EditableSettingsList/SettingField/{EditSettingValue.test.js → EditSettingValue/EditSettingValue.test.js} +2 -5
- package/src/lib/EditableSettingsList/SettingField/EditSettingValue/README.md +63 -0
- package/src/lib/EditableSettingsList/SettingField/EditSettingValue/index.js +1 -0
- package/src/lib/EditableSettingsList/SettingField/README.md +61 -0
- package/src/lib/EditableSettingsList/SettingField/{RenderSettingValue.js → RenderSettingValue/RenderSettingValue.js} +1 -1
- package/src/lib/EditableSettingsList/SettingField/{RenderSettingValue.test.js → RenderSettingValue/RenderSettingValue.test.js} +2 -2
- package/src/lib/EditableSettingsList/SettingField/RenderSettingValue/index.js +1 -0
- package/src/lib/EditableSettingsList/SettingField/SettingField.js +5 -3
- package/src/lib/EditableSettingsList/SettingField/SettingField.test.js +65 -44
- package/src/lib/EditableSettingsList/index.js +1 -1
- package/src/lib/NumberField/README.md +134 -0
- package/src/lib/SASQLookupComponent/README.md +172 -0
- package/src/lib/SASQLookupComponent/SASQLookupComponent.js +6 -1
- package/src/lib/SASQLookupComponent/TableBody/README.md +113 -0
- package/src/lib/SASQRoute/README.md +49 -18
- package/src/lib/SASQViewComponent/README.md +132 -0
- package/src/lib/SearchKeyControl/README.md +70 -0
- package/src/lib/SearchKeyControl/SearchKeyControl.js +98 -0
- package/src/lib/SearchKeyControl/SearchKeyControl.test.js +165 -0
- package/src/lib/SearchKeyControl/index.js +1 -0
- package/src/lib/SettingPage/README.md +66 -0
- package/src/lib/SettingPage/SettingPage.js +3 -1
- package/src/lib/SettingPage/SettingPagePane/README.md +31 -0
- package/src/lib/SettingPage/{SettingPagePane.js → SettingPagePane/SettingPagePane.js} +2 -2
- package/src/lib/SettingPage/SettingPagePane/index.js +1 -0
- package/src/lib/hooks/README.md +26 -121
- package/src/lib/hooks/__mocks__/index.js +2 -2
- package/src/lib/hooks/index.js +2 -3
- package/src/lib/hooks/intlHooks/README.md +31 -0
- package/src/lib/hooks/intlHooks/index.js +3 -0
- package/src/lib/hooks/intlHooks/useIntlKey/README.md +23 -0
- package/src/lib/hooks/intlHooks/useIntlKey/index.js +1 -0
- package/src/lib/hooks/{useIntlKey.js → intlHooks/useIntlKey/useIntlKey.js} +1 -1
- package/src/lib/hooks/intlHooks/useIntlKeyStore/README.md +32 -0
- package/src/lib/hooks/intlHooks/useIntlKeyStore/index.js +1 -0
- package/src/lib/hooks/intlHooks/useKintIntl/README.md +42 -0
- package/src/lib/hooks/intlHooks/useKintIntl/index.js +1 -0
- package/src/lib/hooks/{useKintIntl.js → intlHooks/useKintIntl/useKintIntl.js} +1 -1
- package/src/lib/hooks/useInvalidateRefdata/README.md +72 -0
- package/src/lib/hooks/useInvalidateRefdata/index.js +1 -0
- package/src/lib/hooks/{useInvalidateRefdata.js → useInvalidateRefdata/useInvalidateRefdata.js} +1 -1
- package/src/lib/hooks/useMutateCustomProperties/README.md +88 -0
- package/src/lib/hooks/useMutateCustomProperties/index.js +1 -0
- package/src/lib/hooks/{useMutateCustomProperties.js → useMutateCustomProperties/useMutateCustomProperties.js} +1 -1
- package/src/lib/hooks/useMutateGeneric/README.md +187 -0
- package/src/lib/hooks/useMutateGeneric/index.js +1 -0
- package/src/lib/hooks/useMutateRefdataCategory/README.md +85 -0
- package/src/lib/hooks/useMutateRefdataCategory/index.js +1 -0
- package/src/lib/hooks/{useMutateRefdataCategory.js → useMutateRefdataCategory/useMutateRefdataCategory.js} +2 -2
- package/src/lib/hooks/useMutateRefdataValue/README.md +154 -0
- package/src/lib/hooks/useMutateRefdataValue/index.js +1 -0
- package/src/lib/hooks/{useMutateRefdataValue.js → useMutateRefdataValue/useMutateRefdataValue.js} +2 -2
- package/src/lib/settingsHooks/useAppSettings/README.md +24 -0
- package/src/lib/settingsHooks/useAppSettings/index.js +1 -0
- package/src/lib/settingsHooks/{useAppSettings.js → useAppSettings/useAppSettings.js} +1 -1
- package/src/lib/settingsHooks/useSettingSection/README.md +54 -0
- package/src/lib/settingsHooks/useSettingSection/index.js +1 -0
- package/src/lib/settingsHooks/{useSettingSection.js → useSettingSection/useSettingSection.js} +1 -1
- package/src/lib/settingsHooks/useSettings/README.md +84 -0
- package/src/lib/settingsHooks/useSettings/index.js +1 -0
- package/src/lib/settingsHooks/{useSettings.js → useSettings/useSettings.js} +10 -7
- package/src/lib/utils/refdataQueryKey/README.md +38 -0
- package/src/lib/utils/refdataQueryKey/index.js +1 -0
- package/styles/SearchKeyControl.css +14 -0
- package/es/lib/EditableSettingsList/EditableSettingsListFieldArray.js +0 -57
- package/src/lib/EditableSettingsList/EditableSettingsListFieldArray.js +0 -58
- /package/es/lib/hooks/{useIntlKeyStore.js → intlHooks/useIntlKeyStore/useIntlKeyStore.js} +0 -0
- /package/es/lib/hooks/{useMutateGeneric.js → useMutateGeneric/useMutateGeneric.js} +0 -0
- /package/es/lib/utils/{refdataQueryKey.js → refdataQueryKey/refdataQueryKey.js} +0 -0
- /package/src/lib/hooks/{useIntlKeyStore.js → intlHooks/useIntlKeyStore/useIntlKeyStore.js} +0 -0
- /package/src/lib/hooks/{useMutateGeneric.js → useMutateGeneric/useMutateGeneric.js} +0 -0
- /package/src/lib/utils/{refdataQueryKey.js → refdataQueryKey/refdataQueryKey.js} +0 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# EditSettingValue
|
|
2
|
+
|
|
3
|
+
A component responsible for rendering the correct input field when a setting is in edit mode within the `SettingField` component. It selects and configures the appropriate `react-final-form` `<Field>`-wrapped input component (`@folio/stripes/components` `TextField`, `Select`, or a custom `RefdataButtons` component) based on the `settingType` specified in the setting's configuration (`currentSetting` prop).
|
|
4
|
+
|
|
5
|
+
This component is designed to be rendered by `SettingField` when the `editing` prop is true. It receives form control props (`input`) from the parent `react-final-form` `<Field>` and contextual data (`refdata`, `templates`) needed for specific input types like dropdowns or radio buttons. It ensures that the edited value is correctly bound to the `.value` property of the setting object within the form state.
|
|
6
|
+
|
|
7
|
+
## Basic Usage
|
|
8
|
+
|
|
9
|
+
`EditSettingValue` is used internally by the `SettingField` component when its `editing` prop is true. It's not typically instantiated directly in application code but rather chosen dynamically by `SettingField`.
|
|
10
|
+
|
|
11
|
+
```jsx
|
|
12
|
+
// EditSettingValue is used internally by the SettingField component
|
|
13
|
+
// when its 'editing' prop is true.
|
|
14
|
+
|
|
15
|
+
// Simplified structure within SettingField's render method:
|
|
16
|
+
import EditSettingValue from './EditSettingValue'; // Adjust path
|
|
17
|
+
import RenderSettingValue from './RenderSettingValue'; // For comparison
|
|
18
|
+
|
|
19
|
+
const SettingField = ({ editing, input, meta, currentSetting, refdata, templates, ...rest }) => {
|
|
20
|
+
// ... other logic like fetching refdata/templates ...
|
|
21
|
+
|
|
22
|
+
let RenderFunction;
|
|
23
|
+
if (editing === false) {
|
|
24
|
+
// When not editing, SettingField uses RenderSettingValue
|
|
25
|
+
RenderFunction = RenderSettingValue;
|
|
26
|
+
} else {
|
|
27
|
+
// When editing is true, SettingField switches to EditSettingValue:
|
|
28
|
+
RenderFunction = EditSettingValue;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<Card /* Card setup */ >
|
|
33
|
+
{/* RenderFunction will be EditSettingValue when editing is true */}
|
|
34
|
+
<RenderFunction
|
|
35
|
+
currentSetting={currentSetting}
|
|
36
|
+
input={input} // Passed from the parent <Field>
|
|
37
|
+
meta={meta} // Also passed from the parent <Field>
|
|
38
|
+
refdata={refdata} // Fetched refdata if settingType is 'Refdata'
|
|
39
|
+
templates={templates} // Fetched templates if settingType is 'Template'
|
|
40
|
+
{...rest} // Other relevant props like intlKey, intlNS, labelOverrides etc.
|
|
41
|
+
/>
|
|
42
|
+
</Card>
|
|
43
|
+
);
|
|
44
|
+
};
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The specific input rendered depends on `currentSetting.settingType`:
|
|
48
|
+
* **'Refdata'**: Renders `<Select>` or `<RefdataButtons>` based on the number of options in the `refdata` prop.
|
|
49
|
+
* **'Password'**: Renders `<TextField type="password">`.
|
|
50
|
+
* **'Template'**: Renders `<Select>` populated from the `templates` prop.
|
|
51
|
+
* **Default/Other**: Renders a standard `<TextField>`.
|
|
52
|
+
|
|
53
|
+
## Props
|
|
54
|
+
|
|
55
|
+
| Name | Type | Description | default | required |
|
|
56
|
+
|------------------|----------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------|-------------------------------------|
|
|
57
|
+
| `currentSetting` | `object` | The configuration object for the setting being edited. Its `settingType` property dictates which input component is rendered, and `key` is used for generating labels. | `undefined` | ✓ |
|
|
58
|
+
| `input` | `object` | Provided by the parent `react-final-form` `<Field>`. Contains the field's `name`, `value`, `onChange`, `onBlur`, etc., connecting the rendered input to the form state. The component uses `input.name` to construct the name for the nested field (e.g., `parentName.value`). | `undefined` | ✓ |
|
|
59
|
+
| `intlKey` | `string` | Base key for internationalization passed to the `useKintIntl` hook, used for generating the `aria-label`. | `undefined` | ✕ |
|
|
60
|
+
| `intlNS` | `string` | Namespace for internationalization passed to the `useKintIntl` hook, used for generating the `aria-label`. | `undefined` | ✕ |
|
|
61
|
+
| `labelOverrides` | `object` | An object potentially containing overrides for specific internationalization message IDs used in this component (e.g., `valueFor`). | `{}` | ✕ |
|
|
62
|
+
| `refdata` | `array` | An array of reference data objects (typically `{ id, value, label }`). Expected to be provided if `currentSetting.settingType` is 'Refdata'. Used to populate the `Select` or `RefdataButtons` component. | `undefined` | Conditional (✓ for 'Refdata' type) |
|
|
63
|
+
| `templates` | `array` | An array of template objects (expected shape `{ id, name }`). Expected to be provided if `currentSetting.settingType` is 'Template'. Used to populate the `Select` component. | `undefined` | Conditional (✓ for 'Template' type) |
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from './EditSettingValue';
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# SettingField
|
|
2
|
+
|
|
3
|
+
A component designed to render a single setting within a settings list. It handles fetching contextual data (like reference data via `useRefdata` or templates via `useTemplates` based on the setting's configuration), displays the setting's name, help text (`InfoPopover`), and value, and manages the switch between display mode (using `RenderSettingValue`) and edit mode (using `EditSettingValue`).
|
|
4
|
+
|
|
5
|
+
It is typically used as the `component` prop for a `react-final-form` `<Field>` within the structure provided by `EditableSettingsListFieldArray` and `EditableSettingsList`. It utilizes `@folio/stripes/components` (`Card`, `Button`, `InfoPopover`) for its UI structure and relies on `SettingsContext` to determine API endpoints for fetching related data.
|
|
6
|
+
|
|
7
|
+
## Basic Usage
|
|
8
|
+
|
|
9
|
+
`SettingField` is usually rendered internally by the `DefaultField` implementation within `EditableSettingsListField`. It receives props from `react-final-form`'s `<Field>` (like `input`, `meta`) and custom props from `EditableSettingsListField` (like `editing`, `setEditing`, `settingData`, `onSave`).
|
|
10
|
+
|
|
11
|
+
```jsx
|
|
12
|
+
// SettingField is typically used internally by EditableSettingsListField.
|
|
13
|
+
// The default implementation within EditableSettingsListField looks
|
|
14
|
+
// somewhat like this:
|
|
15
|
+
|
|
16
|
+
import { Field } from 'react-final-form';
|
|
17
|
+
|
|
18
|
+
// Inside EditableSettingsListField's render logic (simplified):
|
|
19
|
+
<Field
|
|
20
|
+
// Props passed down:
|
|
21
|
+
allowEdit={props.allowEdit}
|
|
22
|
+
component={SettingField} // <-- Usage of SettingField
|
|
23
|
+
editing={props.editing}
|
|
24
|
+
intlKey={props.intlKey}
|
|
25
|
+
intlNS={props.intlNS}
|
|
26
|
+
labelOverrides={props.labelOverrides}
|
|
27
|
+
onSave={props.onSave} // Specific save handler for this row
|
|
28
|
+
setEditing={props.setEditing} // Function to toggle editing state for this row
|
|
29
|
+
settingData={props.settingData} // Object containing currentSetting etc.
|
|
30
|
+
|
|
31
|
+
// Props provided by Field:
|
|
32
|
+
name={settingIdentifier} // The name/path for this field within the form
|
|
33
|
+
// 'input' and 'meta' props are also automatically passed by Field
|
|
34
|
+
/>
|
|
35
|
+
|
|
36
|
+
// Direct usage is less common but possible if customizing the `render` prop
|
|
37
|
+
// of EditableSettingsListFieldArray or EditableSettingsList.
|
|
38
|
+
|
|
39
|
+
// Note: The actual rendering of the setting's value in view or edit mode
|
|
40
|
+
// is delegated to the RenderSettingValue and EditSettingValue components,
|
|
41
|
+
// respectively, based on the 'editing' prop and the setting's configuration
|
|
42
|
+
// (currentSetting.settingType).
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**Note:** This component requires `SettingsContext` to be available higher up in the component tree to provide `refdataEndpoint` and `templateEndpoint`.
|
|
46
|
+
|
|
47
|
+
## Props
|
|
48
|
+
|
|
49
|
+
| Name | Type | Description | default | required |
|
|
50
|
+
|------------------------------|-----------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------|------------|
|
|
51
|
+
| `allowEdit` | `boolean` | Controls whether the "Edit"/"Save" button is displayed and if editing is permitted. Passed down from parent components. | `true` | ✕ |
|
|
52
|
+
| `editing` | `boolean` | Determines if the field should render in display mode (`RenderSettingValue`) or edit mode (`EditSettingValue`). This state is typically managed by the parent `EditableSettingsListField`. | `undefined` | ✓ |
|
|
53
|
+
| `input` | `object` | Provided by `react-final-form`'s `<Field>`. Contains field state like `value`, `name`, and callbacks like `onChange`, `onBlur`. Crucial for connecting to the form state, passed down to `EditSettingValue`. | `undefined` | ✓ (by RFF) |
|
|
54
|
+
| `intlKey` | `string` | Base key for internationalization, used by the internal `useKintIntl` hook for fetching labels and messages. | `undefined` | ✕ |
|
|
55
|
+
| `intlNS` | `string` | Namespace for internationalization, used by the internal `useKintIntl` hook. | `undefined` | ✕ |
|
|
56
|
+
| `labelOverrides` | `object` | An object potentially used to override default labels, passed down to `RenderSettingValue`/`EditSettingValue`. | `{}` | ✕ |
|
|
57
|
+
| `meta` | `object` | Provided by `react-final-form`'s `<Field>`. Contains metadata about the field state, such as `touched`, `error`, `dirty`, `valid`, etc. | `undefined` | ✓ (by RFF) |
|
|
58
|
+
| `onSave` | `func` | Callback function triggered when the "Save" button is clicked (while `editing` is true). It should handle the persistence logic for this *single setting* and is expected to return a `Promise`. The success of the promise determines whether the component switches back to display mode (`setEditing(false)`). | `undefined` | ✓ |
|
|
59
|
+
| `setEditing` | `func` | A function, provided by the parent component (e.g., `EditableSettingsListField`), used to signal a change in the editing state (e.g., `setEditing(true)` when "Edit" is clicked, or `setEditing(false)` after a successful save). | `undefined` | ✓ |
|
|
60
|
+
| `settingData` | `object` | An object containing data pertinent to the specific setting being rendered. | `undefined` | ✓ |
|
|
61
|
+
| `settingData.currentSetting` | `object` | The core configuration object for the setting currently being rendered. Contains properties like `key`, `section`, `settingType`, `vocab`, etc., which drive the component's behavior (fetching data, rendering labels, choosing input types via `EditSettingValue`). | `undefined` | ✓ |
|
|
@@ -2,9 +2,9 @@ import React from 'react';
|
|
|
2
2
|
|
|
3
3
|
import RenderSettingValue from './RenderSettingValue';
|
|
4
4
|
|
|
5
|
-
import { renderWithKintHarness } from '
|
|
5
|
+
import { renderWithKintHarness } from '../../../../../test/jest/helpers';
|
|
6
6
|
|
|
7
|
-
jest.mock('
|
|
7
|
+
jest.mock('../../../hooks');
|
|
8
8
|
|
|
9
9
|
const stringSetting = {
|
|
10
10
|
id: '12345',
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from './RenderSettingValue';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { useContext } from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
|
|
4
4
|
import {
|
|
@@ -18,16 +18,17 @@ import renderHelpTextCSS from '../../../../styles/renderHelpText.css';
|
|
|
18
18
|
const SettingField = (settingFieldProps) => {
|
|
19
19
|
const {
|
|
20
20
|
allowEdit = true,
|
|
21
|
+
editing,
|
|
21
22
|
intlKey: passedIntlKey,
|
|
22
23
|
intlNS: passedIntlNS,
|
|
23
24
|
labelOverrides = {},
|
|
24
25
|
onSave,
|
|
26
|
+
setEditing,
|
|
25
27
|
settingData: {
|
|
26
28
|
currentSetting
|
|
27
29
|
} = {}
|
|
28
30
|
} = settingFieldProps;
|
|
29
31
|
|
|
30
|
-
const [editing, setEditing] = useState(false);
|
|
31
32
|
const kintIntl = useKintIntl(passedIntlKey, passedIntlNS);
|
|
32
33
|
const { refdataEndpoint, templateEndpoint } = useContext(SettingsContext);
|
|
33
34
|
|
|
@@ -39,7 +40,8 @@ const SettingField = (settingFieldProps) => {
|
|
|
39
40
|
endpoint: refdataEndpoint,
|
|
40
41
|
desc: currentSetting.vocab,
|
|
41
42
|
queryParams: {
|
|
42
|
-
enabled: !!currentSetting?.vocab && currentSetting.settingType === 'Refdata'
|
|
43
|
+
enabled: !!currentSetting?.vocab && currentSetting.settingType === 'Refdata',
|
|
44
|
+
staleTime: 1000 * 60 * 2 // 2 minutes staletime for refdata in settings?
|
|
43
45
|
}
|
|
44
46
|
});
|
|
45
47
|
|
|
@@ -25,50 +25,71 @@ const setting = {
|
|
|
25
25
|
value: 'diku-shared'
|
|
26
26
|
};
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
let renderComponent;
|
|
30
|
-
beforeEach(async () => {
|
|
31
|
-
renderComponent = renderWithKintHarness(
|
|
32
|
-
<TestForm
|
|
33
|
-
initialValues={{}}
|
|
34
|
-
onSubmit={onSubmit}
|
|
35
|
-
>
|
|
36
|
-
<Field
|
|
37
|
-
component={SettingField}
|
|
38
|
-
name="test"
|
|
39
|
-
onSave={onSave}
|
|
40
|
-
settingData={{
|
|
41
|
-
currentSetting: setting
|
|
42
|
-
}}
|
|
43
|
-
/>
|
|
44
|
-
</TestForm>
|
|
45
|
-
);
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
it('renders RenderSettingValue', async () => {
|
|
49
|
-
const { getByText } = renderComponent;
|
|
50
|
-
await waitFor(async () => expect(await getByText('RenderSettingValue')).toBeInTheDocument());
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
test('renders the edit button', () => {
|
|
54
|
-
Button('Edit').exists();
|
|
55
|
-
});
|
|
28
|
+
const setEditing = jest.fn();
|
|
56
29
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
30
|
+
let renderComponent;
|
|
31
|
+
describe('SettingField', () => {
|
|
32
|
+
describe.each([
|
|
33
|
+
{
|
|
34
|
+
editing: false,
|
|
35
|
+
expectedRender: 'RenderSettingValue',
|
|
36
|
+
expectedButton: 'Edit',
|
|
37
|
+
expectedCallback: setEditing,
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
editing: true,
|
|
41
|
+
expectedRender: 'EditSettingValue',
|
|
42
|
+
expectedButton: 'Save',
|
|
43
|
+
expectedCallback: onSave,
|
|
44
|
+
|
|
45
|
+
}
|
|
46
|
+
])('render SettingField with editing: editing', ({
|
|
47
|
+
editing,
|
|
48
|
+
expectedButton,
|
|
49
|
+
expectedCallback,
|
|
50
|
+
expectedRender
|
|
51
|
+
}) => {
|
|
52
|
+
beforeEach(async () => {
|
|
53
|
+
setEditing.mockClear();
|
|
54
|
+
onSave.mockClear();
|
|
55
|
+
renderComponent = renderWithKintHarness(
|
|
56
|
+
<TestForm
|
|
57
|
+
initialValues={{}}
|
|
58
|
+
onSubmit={onSubmit}
|
|
59
|
+
>
|
|
60
|
+
<Field
|
|
61
|
+
component={SettingField}
|
|
62
|
+
editing={editing}
|
|
63
|
+
name="test"
|
|
64
|
+
onSave={onSave}
|
|
65
|
+
setEditing={setEditing}
|
|
66
|
+
settingData={{
|
|
67
|
+
currentSetting: setting
|
|
68
|
+
}}
|
|
69
|
+
/>
|
|
70
|
+
</TestForm>
|
|
71
|
+
);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it(`renders ${expectedRender}`, () => {
|
|
75
|
+
const { getByText } = renderComponent;
|
|
76
|
+
expect(getByText(expectedRender)).toBeInTheDocument();
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
test(`renders the ${expectedButton} button`, () => {
|
|
80
|
+
Button('Edit').exists();
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
describe(`clicking the ${expectedButton} button`, () => {
|
|
84
|
+
beforeEach(async () => {
|
|
85
|
+
await waitFor(async () => {
|
|
86
|
+
await Button(expectedButton).click();
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it('fired expected callback', () => {
|
|
91
|
+
expect(expectedCallback).toHaveBeenCalled();
|
|
92
|
+
});
|
|
93
|
+
});
|
|
73
94
|
});
|
|
74
95
|
});
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { default as EditableSettingsList } from './EditableSettingsList';
|
|
2
2
|
export { default as EditableSettingsListFieldArray } from './EditableSettingsListFieldArray';
|
|
3
|
-
export { SettingField } from './SettingField';
|
|
3
|
+
export { SettingField, RenderSettingValue, EditSettingValue } from './SettingField';
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# NumberField
|
|
2
|
+
|
|
3
|
+
A controlled input component designed for numeric values, providing parsing, validation, and seamless integration with form libraries like React Final Form. **NumberField** ensures that user input is always treated as a numeric value (or empty string) while maintaining compatibility with browser-native number input validation.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Controlled/Uncontrolled Support:** Works as a controlled component (via `value`) or within form libraries (via `input`).
|
|
8
|
+
- **Automatic Parsing:** Converts user input to a numeric value (float) or empty string.
|
|
9
|
+
- **Form Integration:** Compatible with React Final Form's `Field` component.
|
|
10
|
+
- **Dual Input Handling:** Uses a visible `TextField` for user interaction and a hidden input for form state management.
|
|
11
|
+
- **Validation:** Leverages HTML5 `type="number"` validation with fallback to numeric parsing.
|
|
12
|
+
|
|
13
|
+
## Basic Usage
|
|
14
|
+
|
|
15
|
+
### Standalone (Controlled)
|
|
16
|
+
|
|
17
|
+
```jsx
|
|
18
|
+
import { useState } from 'react';
|
|
19
|
+
import { NumberField } from '@k-int/stripes-kint-components';
|
|
20
|
+
|
|
21
|
+
const AgeInput = () => {
|
|
22
|
+
const [age, setAge] = useState('');
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<NumberField
|
|
26
|
+
label="Enter your age"
|
|
27
|
+
value={age}
|
|
28
|
+
onChange={(e, value) => setAge(value)}
|
|
29
|
+
aria-label="Age input"
|
|
30
|
+
/>
|
|
31
|
+
);
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export default AgeInput;
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### With React Final Form
|
|
38
|
+
|
|
39
|
+
```jsx
|
|
40
|
+
import { Field } from 'react-final-form';
|
|
41
|
+
import { NumberField } from '@k-int/stripes-kint-components';
|
|
42
|
+
|
|
43
|
+
const FormAgeField = () => (
|
|
44
|
+
<Field
|
|
45
|
+
name="age"
|
|
46
|
+
render={({ input }) => (
|
|
47
|
+
<NumberField
|
|
48
|
+
label="Age"
|
|
49
|
+
input={input}
|
|
50
|
+
aria-label="Form age input"
|
|
51
|
+
/>
|
|
52
|
+
)}
|
|
53
|
+
/>
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
export default FormAgeField;
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Props
|
|
60
|
+
|
|
61
|
+
| Prop | Type | Required | Description |
|
|
62
|
+
|-------------|------------|----------|--------------------------------------------------------------------------------------------------------------|
|
|
63
|
+
| `input` | `object` | ✕ | Form library input object (e.g., from React Final Form). Must contain `name`, `onChange`, and `value`. |
|
|
64
|
+
| `value` | `number` | ✕ | Controlled value (use either `input` or `value`, not both). |
|
|
65
|
+
| `onChange` | `function` | ✕ | Custom change handler: `(event: React.ChangeEvent, value: number | '') => void`. |
|
|
66
|
+
| `onBlur` | `function` | ✕ | Custom blur handler: `(event: React.FocusEvent) => void`. |
|
|
67
|
+
| ...TextFieldProps | `any` | ✕ | All other props passed to underlying [TextField](https://stripes.github.io/stripes-components/TextField). |
|
|
68
|
+
|
|
69
|
+
## Behavior Details
|
|
70
|
+
|
|
71
|
+
### Input Handling
|
|
72
|
+
- **User Input:** Directly manipulates a visible `TextField`
|
|
73
|
+
- **Value Parsing:**
|
|
74
|
+
```js
|
|
75
|
+
const parsedValue = parseFloat(userInput);
|
|
76
|
+
// Returns number or NaN
|
|
77
|
+
```
|
|
78
|
+
- **Form State:** Maintains a hidden `<input>` that always contains:
|
|
79
|
+
- Valid number (as float)
|
|
80
|
+
- Empty string (for invalid/empty input)
|
|
81
|
+
|
|
82
|
+
### Value Propagation
|
|
83
|
+
1. User types "12.5" ➔ `handleUserChange`:
|
|
84
|
+
```js
|
|
85
|
+
parsedValue = 12.5
|
|
86
|
+
setNumValue(12.5) // Updates visible field
|
|
87
|
+
changeField(12.5) // Updates hidden input
|
|
88
|
+
```
|
|
89
|
+
2. Hidden input's `onChange`:
|
|
90
|
+
```js
|
|
91
|
+
input.onChange(12.5) // Propagates to form library
|
|
92
|
+
passedOnChange(12.5) // Notifies custom handler
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Integration Notes
|
|
96
|
+
|
|
97
|
+
### Form Library Requirements
|
|
98
|
+
When using with React Final Form:
|
|
99
|
+
```jsx
|
|
100
|
+
<Field
|
|
101
|
+
name="quantity"
|
|
102
|
+
parse={v => v === '' ? undefined : Number(v)} // Convert empty string to undefined
|
|
103
|
+
render={({ input }) => (
|
|
104
|
+
<NumberField
|
|
105
|
+
input={input}
|
|
106
|
+
label="Quantity"
|
|
107
|
+
/>
|
|
108
|
+
)}
|
|
109
|
+
/>
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Styling/Validation
|
|
113
|
+
- Inherits all styling capabilities from `@folio/stripes-components/TextField`
|
|
114
|
+
- Browser-native number validation shown via:
|
|
115
|
+
```jsx
|
|
116
|
+
<NumberField
|
|
117
|
+
type="number"
|
|
118
|
+
min={0}
|
|
119
|
+
max={100}
|
|
120
|
+
step={0.1}
|
|
121
|
+
/>
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Error Handling
|
|
125
|
+
Implement custom error states through form library integrations or wrapper components:
|
|
126
|
+
```jsx
|
|
127
|
+
const ErrorProneField = ({ meta, ...props }) => (
|
|
128
|
+
<NumberField
|
|
129
|
+
{...props}
|
|
130
|
+
error={meta.touched && meta.error}
|
|
131
|
+
aria-label="Error-prone field"
|
|
132
|
+
/>
|
|
133
|
+
);
|
|
134
|
+
```
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# SASQLookupComponent
|
|
2
|
+
|
|
3
|
+
A highly configurable component that renders a lookup view for displaying data in a multi-pane layout. **SASQLookupComponent** combines a search and sort query (SASQ) interface, a filter pane, and a main content pane into a unified view. It leverages components from `@folio/stripes/smart-components` and `@folio/stripes/components` to provide a persistent paneset layout with integrated search, filtering, and pagination.
|
|
4
|
+
|
|
5
|
+
> **Note:** Detailed documentation for sub-components (such as **SearchAndSortQuery**, **PersistedPaneset**, **CollapseFilterPaneButton**, and **ExpandFilterPaneButton**) is available separately. **SASQLookupComponent** is designed to work seamlessly with these components while allowing for significant customization via its props.
|
|
6
|
+
|
|
7
|
+
## Basic Usage
|
|
8
|
+
|
|
9
|
+
Below is an example demonstrating how to use **SASQLookupComponent**. In this example, the component is configured with custom fetch parameters, filtering behavior, and a custom table body for rendering results. The component automatically manages query state, pagination, and filter pane visibility.
|
|
10
|
+
|
|
11
|
+
```jsx
|
|
12
|
+
import { FormattedMessage } from 'react-intl';
|
|
13
|
+
import { SASQLookupComponent } from '@k-int/stripes-kint-components';
|
|
14
|
+
import CustomFilter from './CustomFilter';
|
|
15
|
+
import CustomTableBody from './CustomTableBody';
|
|
16
|
+
|
|
17
|
+
const MyLookupView = () => {
|
|
18
|
+
const fetchParameters = {
|
|
19
|
+
endpoint: '/api/my-items',
|
|
20
|
+
SASQ_MAP: {
|
|
21
|
+
searchKey: 'name',
|
|
22
|
+
perPage: 25,
|
|
23
|
+
// Additional SASQ configuration
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<SASQLookupComponent
|
|
29
|
+
id="my-lookup"
|
|
30
|
+
path="/my-lookup"
|
|
31
|
+
fetchParameters={fetchParameters}
|
|
32
|
+
FilterComponent={CustomFilter}
|
|
33
|
+
RenderBody={CustomTableBody}
|
|
34
|
+
intlKey="myLookup"
|
|
35
|
+
intlNS="myApp"
|
|
36
|
+
labelOverrides={{ foundValues: 'Items Found' }}
|
|
37
|
+
resultColumns={[
|
|
38
|
+
{ propertyPath: 'name', label: <FormattedMessage id="myApp.item.name" /> },
|
|
39
|
+
{ propertyPath: 'status', label: <FormattedMessage id="myApp.item.status" /> }
|
|
40
|
+
]}
|
|
41
|
+
searchFieldAriaLabel="Search items"
|
|
42
|
+
>
|
|
43
|
+
{/* Optionally, additional children can be rendered */}
|
|
44
|
+
</SASQLookupComponent>
|
|
45
|
+
);
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export default MyLookupView;
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
In this example, **SASQLookupComponent**:
|
|
52
|
+
|
|
53
|
+
- Uses `fetchParameters` to configure data fetching.
|
|
54
|
+
- Provides a custom filter interface via `FilterComponent`.
|
|
55
|
+
- Renders results using a custom table body (or defaults to an internal **TableBody**).
|
|
56
|
+
- Manages pagination and query state via hooks like `usePrevNextPagination` and `useKiwtSASQuery`.
|
|
57
|
+
|
|
58
|
+
## Props
|
|
59
|
+
|
|
60
|
+
| Name | Type | Description | Default | Required |
|
|
61
|
+
|---------------------------------|-------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------|----------|
|
|
62
|
+
| `id` | `string` | A unique identifier for the lookup instance. Used to generate unique keys for query state, persistent paneset, and filter pane visibility in local storage. | | ✓ |
|
|
63
|
+
| `fetchParameters` | `object` | An object that defines the endpoints and SASQ configuration used for fetching data. It must include:<br><br>• **endpoint:** The URL used to fetch the main data set.<br>• **SASQ_MAP:** An object containing settings for search, filter, pagination (e.g., `searchKey`, `perPage`, etc.). Additional keys (such as `itemEndpoint`) can also be provided if needed. | `{}` | ✓ |
|
|
64
|
+
| `FilterComponent` | `func` or `node` | A custom component used to render additional filtering options in the filter pane. This component receives props for managing active filters, search state, and resetting filters. | `() => null` | ✕ |
|
|
65
|
+
| `FilterPaneHeaderComponent` | `func` or `node` | A component rendered at the top of the filter pane. Use this to customize the header area of the filter pane. | `() => null` | ✕ |
|
|
66
|
+
| `filterPaneProps` | `object` | Additional props to be passed to the filter pane. These props can customize the appearance and behavior of the filter pane (such as first or last menu elements). | `{}` | ✕ |
|
|
67
|
+
| `intlKey` | `string` | A base internationalization key used by the internal `useKintIntl` hook to resolve localized messages (e.g., for labels or pane titles). | | ✕ |
|
|
68
|
+
| `intlNS` | `string` | An internationalization namespace used by the internal `useKintIntl` hook. | | ✕ |
|
|
69
|
+
| `labelOverrides` | `object` | An object for overriding default labels, such as the text for displaying the count of found values. | `{}` | ✕ |
|
|
70
|
+
| `lookupQueryNamespaceGenerator` | `func` | A function that generates a query namespace (an array) for `react-query` based on provided parameters such as `currentPage`, `namespace`, `id`, `query`, etc. This ensures that queries are uniquely identified. | See default implementation in source code | ✕ |
|
|
71
|
+
| `mainPaneProps` | `object` | Additional props to be passed to the main pane containing the lookup results. This can include custom menu elements or styling. | `{}` | ✕ |
|
|
72
|
+
| `mclProps` | `object` | Custom properties to be passed to the underlying Multi-Column List (MCL) component. These properties are merged with pagination props derived from `usePrevNextPagination`. | `{}` | ✕ |
|
|
73
|
+
| `noSearchField` | `bool` | When set to `true`, the search field is not rendered in the filter pane. Use this if you want to disable search input. | `false` | ✕ |
|
|
74
|
+
| `persistedPanesetProps` | `object` | Additional props to be passed to the **PersistedPaneset** component, which manages the persistent layout of the filter and main panes. | `{}` | ✕ |
|
|
75
|
+
| `queryParameterGenerator` | `func` | A function that takes the SASQ_MAP configuration and current query values to generate an array of query parameters for the fetch call. Defaults to `generateKiwtQuery`. | `generateKiwtQuery` | ✕ |
|
|
76
|
+
| `RenderBody` | `func` or `node` | A component used to render the body of the main pane (typically a table). If not provided, the internal **TableBody** component is used. | `TableBody` | ✕ |
|
|
77
|
+
| `rowNavigation` | `bool` | Flag to enable or disable row navigation. When enabled, clicking on a row triggers navigation to a detailed view. | `true` | ✕ |
|
|
78
|
+
| `sasqProps` | `object` | Additional props to override or extend the default SASQ query behavior. These props can include custom query values, setters, or getters. | | ✕ |
|
|
79
|
+
| `searchableIndexes` | `arrayOf(object)` | An array of objects defining the options for the search index selection component (`SearchKeyControl`), rendered below the search field. Each object typically has `value` and `label` keys. If empty or omitted, the qindex checkboxes are not shown. | `[]` | ✕ |
|
|
80
|
+
| `searchFieldAriaLabel` | `string` | Accessibility label for the search field. | | ✕ |
|
|
81
|
+
| `searchFieldProps` | `object` | Additional props to be passed to the **SearchField** component for customizing its behavior or styling. | | ✕ |
|
|
82
|
+
| `children` | `node`, `func` | Optional children to be rendered below the main pane. These are rendered within the **PersistedPaneset** container. | | ✕ |
|
|
83
|
+
Below is an additional section for **SASQLookupComponent** documentation that describes the available functionality on the component's ref along with a worked example.
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
## Exposed Ref Functionality
|
|
87
|
+
|
|
88
|
+
**SASQLookupComponent** uses `forwardRef` and `useImperativeHandle` to expose specific properties to parent components. This allows external components to access certain internal states and query-related information directly. The ref object includes the following properties:
|
|
89
|
+
|
|
90
|
+
- **`lookupQueryProps`**:
|
|
91
|
+
An object containing:
|
|
92
|
+
- **`data`**: The latest data fetched by the component.
|
|
93
|
+
- Additional query-related properties returned from `useQuery` (such as loading state, error, etc.).
|
|
94
|
+
|
|
95
|
+
- **`queryParams`**:
|
|
96
|
+
The array of query parameters generated by the component, based on the provided SASQ configuration and current query state. This reflects the current filters, pagination, and search criteria used for the data fetch.
|
|
97
|
+
|
|
98
|
+
In general is is recommended not to use this functionality, as it represents an antipattern in React to pass information back up to the parents. Instead the implementing developer should try to replace the inner rendered components and do their logic there with the passed information.
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
### Worked Example
|
|
102
|
+
|
|
103
|
+
Below is a sample usage demonstrating how to access the exposed ref properties:
|
|
104
|
+
|
|
105
|
+
```jsx
|
|
106
|
+
import { useRef, useEffect } from 'react';
|
|
107
|
+
import { SASQLookupComponent } from '@k-int/stripes-kint-components';
|
|
108
|
+
|
|
109
|
+
const LookupWithRefExample = () => {
|
|
110
|
+
// Create a ref to access SASQLookupComponent's exposed methods and properties
|
|
111
|
+
const lookupRef = useRef();
|
|
112
|
+
|
|
113
|
+
useEffect(() => {
|
|
114
|
+
// When the component mounts or updates, you can access the lookupQueryProps and queryParams
|
|
115
|
+
if (lookupRef.current) {
|
|
116
|
+
const { lookupQueryProps, queryParams } = lookupRef.current;
|
|
117
|
+
console.log('Fetched data:', lookupQueryProps.data);
|
|
118
|
+
console.log('Current query parameters:', queryParams);
|
|
119
|
+
|
|
120
|
+
// Example: Check if data is loaded and then trigger some side-effect
|
|
121
|
+
if (!lookupQueryProps.isLoading && lookupQueryProps.data) {
|
|
122
|
+
// Perform an action with the fetched data
|
|
123
|
+
console.log('Data is ready for processing');
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}, []);
|
|
127
|
+
|
|
128
|
+
const fetchParameters = {
|
|
129
|
+
endpoint: '/api/my-items',
|
|
130
|
+
SASQ_MAP: {
|
|
131
|
+
searchKey: 'name',
|
|
132
|
+
perPage: 25
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
return (
|
|
137
|
+
<SASQLookupComponent
|
|
138
|
+
id="my-lookup"
|
|
139
|
+
path="/my-lookup"
|
|
140
|
+
fetchParameters={fetchParameters}
|
|
141
|
+
intlKey="myLookup"
|
|
142
|
+
intlNS="myApp"
|
|
143
|
+
ref={lookupRef} // Attach the ref here
|
|
144
|
+
searchableIndexes={[
|
|
145
|
+
{ key: 'name' },
|
|
146
|
+
{ key: 'description' }
|
|
147
|
+
]} // Provide options for search key selection
|
|
148
|
+
/>
|
|
149
|
+
);
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
export default LookupWithRefExample;
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## How It Works
|
|
156
|
+
|
|
157
|
+
1. **Query and Pagination Management:**
|
|
158
|
+
+ The component leverages hooks such as `usePrevNextPagination` (for page state), `useKiwtSASQuery` (for search/filter/sort state), and `useQuery` (from `react-query` for data fetching). The query parameters string is generated using the provided `queryParameterGenerator` function based on the `WorkspaceParameters.SASQ_MAP` and the current state from the hooks.
|
|
159
|
+
2. **Filter Pane & Main Pane Layout:**
|
|
160
|
+
- **Filter Pane:**
|
|
161
|
+
+ Rendered conditionally based on local storage state (`filterPaneVisible`), it contains a search section (SearchField, SearchKeyControl if `searchableIndexes` are provided, Submit/Reset buttons - unless `noSearchField` is true) and custom filtering options provided via `FilterComponent` and `FilterPaneHeaderComponent`. Buttons for collapsing the pane are included.
|
|
162
|
+
- **Main Pane:**
|
|
163
|
+
+ Displays the fetched data using the `RenderBody` component (defaulting to `TableBody`). It integrates pagination controls (via `mclProps` passed to `RenderBody`) and displays record counts in the header. An expand button is shown if the filter pane is collapsed.
|
|
164
|
+
3. **Persistent Layout:**
|
|
165
|
+
The component wraps its content in a **PersistedPaneset** which maintains pane states (such as sizes and visibility) across sessions.
|
|
166
|
+
|
|
167
|
+
4. **Customization and Extensibility:**
|
|
168
|
+
Through various props, consumers can inject custom components (`FilterComponent`, `FilterPaneHeaderComponent`, `RenderBody`), override query generation (`queryParameterGenerator`, `lookupQueryNamespaceGenerator`), configure data fetching (`WorkspaceParameters`), pass props down to underlying components (`filterPaneProps`, `mainPaneProps`, `mclProps`, `persistedPanesetProps`, `searchFieldProps`), tweak SASQ behavior (`sasqProps`), and adjust UI elements (`noSearchField`, `labelOverrides`, `searchableIndexes`).
|
|
169
|
+
5. **Ref Forwarding:**
|
|
170
|
+
Using `forwardRef` and `useImperativeHandle`, the component exposes certain query properties and generated query parameters to parent components.
|
|
171
|
+
|
|
172
|
+
This design enables **SASQLookupComponent** to serve as a robust and flexible foundation for building data lookup views with advanced filtering, search, and pagination functionalities.
|