@beinformed/ui 1.65.17 → 1.65.19
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 +16 -0
- package/esm/hooks/index.js +1 -0
- package/esm/hooks/index.js.flow +1 -0
- package/esm/hooks/index.js.map +1 -1
- package/esm/hooks/useModelSelectors.js +73 -0
- package/esm/hooks/useModelSelectors.js.flow +98 -0
- package/esm/hooks/useModelSelectors.js.map +1 -0
- package/esm/hooks/useModularUI.js +53 -10
- package/esm/hooks/useModularUI.js.flow +51 -10
- package/esm/hooks/useModularUI.js.map +1 -1
- package/esm/hooks/useModularUIBasic.js +50 -5
- package/esm/hooks/useModularUIBasic.js.flow +49 -7
- package/esm/hooks/useModularUIBasic.js.map +1 -1
- package/esm/redux/_modularui/ModularUIConnector.js +17 -46
- package/esm/redux/_modularui/ModularUIConnector.js.flow +22 -60
- package/esm/redux/_modularui/ModularUIConnector.js.map +1 -1
- package/esm/redux/_router/RouterConnectors.js +5 -0
- package/esm/redux/_router/RouterConnectors.js.flow +5 -0
- package/esm/redux/_router/RouterConnectors.js.map +1 -1
- package/esm/redux/connectors/Application.js +1 -0
- package/esm/redux/connectors/Application.js.flow +1 -0
- package/esm/redux/connectors/Application.js.map +1 -1
- package/esm/redux/connectors/Breadcrumb.js +1 -0
- package/esm/redux/connectors/Breadcrumb.js.flow +1 -0
- package/esm/redux/connectors/Breadcrumb.js.map +1 -1
- package/esm/redux/connectors/CaseView.js +1 -0
- package/esm/redux/connectors/CaseView.js.flow +1 -0
- package/esm/redux/connectors/CaseView.js.map +1 -1
- package/esm/redux/connectors/ConceptDetail.js +1 -0
- package/esm/redux/connectors/ConceptDetail.js.flow +1 -0
- package/esm/redux/connectors/ConceptDetail.js.map +1 -1
- package/esm/redux/connectors/ContentBrowser.js +1 -0
- package/esm/redux/connectors/ContentBrowser.js.flow +1 -0
- package/esm/redux/connectors/ContentBrowser.js.map +1 -1
- package/esm/redux/connectors/ContentDetail.js +1 -0
- package/esm/redux/connectors/ContentDetail.js.flow +1 -0
- package/esm/redux/connectors/ContentDetail.js.map +1 -1
- package/esm/redux/connectors/ContentDetailSection.js +1 -0
- package/esm/redux/connectors/ContentDetailSection.js.flow +1 -0
- package/esm/redux/connectors/ContentDetailSection.js.map +1 -1
- package/esm/redux/connectors/Form.js +1 -0
- package/esm/redux/connectors/Form.js.flow +1 -0
- package/esm/redux/connectors/Form.js.map +1 -1
- package/esm/redux/connectors/FormAttributeSet.js +1 -0
- package/esm/redux/connectors/FormAttributeSet.js.flow +1 -0
- package/esm/redux/connectors/FormAttributeSet.js.map +1 -1
- package/esm/redux/connectors/ListDetail.js +1 -0
- package/esm/redux/connectors/ListDetail.js.flow +1 -0
- package/esm/redux/connectors/ListDetail.js.map +1 -1
- package/esm/redux/connectors/Modal.js +1 -0
- package/esm/redux/connectors/Modal.js.flow +1 -0
- package/esm/redux/connectors/Modal.js.map +1 -1
- package/esm/redux/connectors/ModelCatalog.js +1 -0
- package/esm/redux/connectors/ModelCatalog.js.flow +1 -0
- package/esm/redux/connectors/ModelCatalog.js.map +1 -1
- package/esm/redux/connectors/Notification.js +1 -0
- package/esm/redux/connectors/Notification.js.flow +1 -0
- package/esm/redux/connectors/Notification.js.map +1 -1
- package/esm/redux/connectors/PanelRenderer.js +1 -0
- package/esm/redux/connectors/PanelRenderer.js.flow +1 -0
- package/esm/redux/connectors/PanelRenderer.js.map +1 -1
- package/esm/redux/connectors/Preferences.js +2 -0
- package/esm/redux/connectors/Preferences.js.flow +2 -0
- package/esm/redux/connectors/Preferences.js.map +1 -1
- package/esm/redux/connectors/Progress.js +1 -0
- package/esm/redux/connectors/Progress.js.flow +1 -0
- package/esm/redux/connectors/Progress.js.map +1 -1
- package/esm/redux/connectors/ProgressIndicator.js +1 -0
- package/esm/redux/connectors/ProgressIndicator.js.flow +1 -0
- package/esm/redux/connectors/ProgressIndicator.js.map +1 -1
- package/esm/redux/connectors/QuickSearch.js +1 -0
- package/esm/redux/connectors/QuickSearch.js.flow +1 -0
- package/esm/redux/connectors/QuickSearch.js.map +1 -1
- package/esm/redux/connectors/SignIn.js +1 -0
- package/esm/redux/connectors/SignIn.js.flow +1 -0
- package/esm/redux/connectors/SignIn.js.map +1 -1
- package/esm/redux/connectors/SignOut.js +1 -0
- package/esm/redux/connectors/SignOut.js.flow +1 -0
- package/esm/redux/connectors/SignOut.js.map +1 -1
- package/esm/redux/connectors/Tab.js +1 -0
- package/esm/redux/connectors/Tab.js.flow +1 -0
- package/esm/redux/connectors/Tab.js.map +1 -1
- package/lib/hooks/index.js +11 -0
- package/lib/hooks/index.js.map +1 -1
- package/lib/hooks/useModelSelectors.js +87 -0
- package/lib/hooks/useModelSelectors.js.map +1 -0
- package/lib/hooks/useModularUI.js +52 -9
- package/lib/hooks/useModularUI.js.map +1 -1
- package/lib/hooks/useModularUIBasic.js +47 -5
- package/lib/hooks/useModularUIBasic.js.map +1 -1
- package/lib/redux/_modularui/ModularUIConnector.js +15 -44
- package/lib/redux/_modularui/ModularUIConnector.js.map +1 -1
- package/lib/redux/_router/RouterConnectors.js +5 -0
- package/lib/redux/_router/RouterConnectors.js.map +1 -1
- package/lib/redux/connectors/Application.js +1 -0
- package/lib/redux/connectors/Application.js.map +1 -1
- package/lib/redux/connectors/Breadcrumb.js +1 -0
- package/lib/redux/connectors/Breadcrumb.js.map +1 -1
- package/lib/redux/connectors/CaseView.js +1 -0
- package/lib/redux/connectors/CaseView.js.map +1 -1
- package/lib/redux/connectors/ConceptDetail.js +1 -0
- package/lib/redux/connectors/ConceptDetail.js.map +1 -1
- package/lib/redux/connectors/ContentBrowser.js +1 -0
- package/lib/redux/connectors/ContentBrowser.js.map +1 -1
- package/lib/redux/connectors/ContentDetail.js +1 -0
- package/lib/redux/connectors/ContentDetail.js.map +1 -1
- package/lib/redux/connectors/ContentDetailSection.js +1 -0
- package/lib/redux/connectors/ContentDetailSection.js.map +1 -1
- package/lib/redux/connectors/Form.js +1 -0
- package/lib/redux/connectors/Form.js.map +1 -1
- package/lib/redux/connectors/FormAttributeSet.js +1 -0
- package/lib/redux/connectors/FormAttributeSet.js.map +1 -1
- package/lib/redux/connectors/ListDetail.js +1 -0
- package/lib/redux/connectors/ListDetail.js.map +1 -1
- package/lib/redux/connectors/Modal.js +1 -0
- package/lib/redux/connectors/Modal.js.map +1 -1
- package/lib/redux/connectors/ModelCatalog.js +1 -0
- package/lib/redux/connectors/ModelCatalog.js.map +1 -1
- package/lib/redux/connectors/Notification.js +1 -0
- package/lib/redux/connectors/Notification.js.map +1 -1
- package/lib/redux/connectors/PanelRenderer.js +1 -0
- package/lib/redux/connectors/PanelRenderer.js.map +1 -1
- package/lib/redux/connectors/Preferences.js +2 -0
- package/lib/redux/connectors/Preferences.js.map +1 -1
- package/lib/redux/connectors/Progress.js +1 -0
- package/lib/redux/connectors/Progress.js.map +1 -1
- package/lib/redux/connectors/ProgressIndicator.js +1 -0
- package/lib/redux/connectors/ProgressIndicator.js.map +1 -1
- package/lib/redux/connectors/QuickSearch.js +1 -0
- package/lib/redux/connectors/QuickSearch.js.map +1 -1
- package/lib/redux/connectors/SignIn.js +1 -0
- package/lib/redux/connectors/SignIn.js.map +1 -1
- package/lib/redux/connectors/SignOut.js +1 -0
- package/lib/redux/connectors/SignOut.js.map +1 -1
- package/lib/redux/connectors/Tab.js +1 -0
- package/lib/redux/connectors/Tab.js.map +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
## [1.65.19](https://git.beinformed.com/public/nl.beinformed.bi.layout.lib.ui/compare/v1.65.18...v1.65.19) (2026-01-16)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* **connector:** handle modularui connector with useModularUIBasic hook ([b44b1c4](https://git.beinformed.com/public/nl.beinformed.bi.layout.lib.ui/commit/b44b1c4bc5230d983331b28094e1811b9ba04ba4))
|
|
11
|
+
* **hooks:** add `useModelSelectors` and deprecate legacy connector methods in favor of equivalent hooks ([db59fd9](https://git.beinformed.com/public/nl.beinformed.bi.layout.lib.ui/commit/db59fd9087fe6dffafcdf429d6e2a0ce40aaf57b))
|
|
12
|
+
* **hooks:** enhance URL normalization, add query handling with `useRef`, and improve reload logic in modularui hooks ([f042c03](https://git.beinformed.com/public/nl.beinformed.bi.layout.lib.ui/commit/f042c0347c4f0609c232dccef73dbb844a8be01c))
|
|
13
|
+
|
|
14
|
+
## [1.65.18](https://git.beinformed.com/public/nl.beinformed.bi.layout.lib.ui/compare/v1.65.17...v1.65.18) (2026-01-15)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
### Bug Fixes
|
|
18
|
+
|
|
19
|
+
* **hooks:** update `removeOnUnmount` default to `true` and clean up unused option in `useModularUIBasic` ([81c6662](https://git.beinformed.com/public/nl.beinformed.bi.layout.lib.ui/commit/81c66624e019f1a14611759ec281ec046a1dea5e))
|
|
20
|
+
|
|
5
21
|
## [1.65.17](https://git.beinformed.com/public/nl.beinformed.bi.layout.lib.ui/compare/v1.65.15...v1.65.17) (2026-01-15)
|
|
6
22
|
|
|
7
23
|
|
package/esm/hooks/index.js
CHANGED
|
@@ -8,6 +8,7 @@ export * from "./useLookup";
|
|
|
8
8
|
export * from "./useModal";
|
|
9
9
|
export * from "./useModelCatalog";
|
|
10
10
|
export * from "./useModels";
|
|
11
|
+
export * from "./useModelSelectors";
|
|
11
12
|
export * from "./useModularUI";
|
|
12
13
|
export * from "./useModularUIBasic";
|
|
13
14
|
export * from "./useModularUIModel";
|
package/esm/hooks/index.js.flow
CHANGED
|
@@ -9,6 +9,7 @@ export * from "./useLookup";
|
|
|
9
9
|
export * from "./useModal";
|
|
10
10
|
export * from "./useModelCatalog";
|
|
11
11
|
export * from "./useModels";
|
|
12
|
+
export * from "./useModelSelectors";
|
|
12
13
|
export * from "./useModularUI";
|
|
13
14
|
export * from "./useModularUIBasic";
|
|
14
15
|
export * from "./useModularUIModel";
|
package/esm/hooks/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/hooks/index.js"],"sourcesContent":["// @flow\nexport * from \"./useAllFormsOnModel\";\nexport * from \"./useAuthentication\";\nexport * from \"./useContent\";\nexport * from \"./useForm\";\nexport * from \"./useI18n\";\nexport * from \"./useList\";\nexport * from \"./useLookup\";\nexport * from \"./useModal\";\nexport * from \"./useModelCatalog\";\nexport * from \"./useModels\";\nexport * from \"./useModularUI\";\nexport * from \"./useModularUIBasic\";\nexport * from \"./useModularUIModel\";\nexport * from \"./useModularUIRequest\";\nexport * from \"./useNotification\";\nexport * from \"./usePanel\";\nexport * from \"./usePreference\";\nexport * from \"./useProgressIndicator\";\nexport * from \"./useRouter\";\nexport * from \"./useSearch\";\n"],"mappings":"AACA,cAAc,sBAAsB;AACpC,cAAc,qBAAqB;AACnC,cAAc,cAAc;AAC5B,cAAc,WAAW;AACzB,cAAc,WAAW;AACzB,cAAc,WAAW;AACzB,cAAc,aAAa;AAC3B,cAAc,YAAY;AAC1B,cAAc,mBAAmB;AACjC,cAAc,aAAa;AAC3B,cAAc,gBAAgB;AAC9B,cAAc,qBAAqB;AACnC,cAAc,qBAAqB;AACnC,cAAc,uBAAuB;AACrC,cAAc,mBAAmB;AACjC,cAAc,YAAY;AAC1B,cAAc,iBAAiB;AAC/B,cAAc,wBAAwB;AACtC,cAAc,aAAa;AAC3B,cAAc,aAAa","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/hooks/index.js"],"sourcesContent":["// @flow\nexport * from \"./useAllFormsOnModel\";\nexport * from \"./useAuthentication\";\nexport * from \"./useContent\";\nexport * from \"./useForm\";\nexport * from \"./useI18n\";\nexport * from \"./useList\";\nexport * from \"./useLookup\";\nexport * from \"./useModal\";\nexport * from \"./useModelCatalog\";\nexport * from \"./useModels\";\nexport * from \"./useModelSelectors\";\nexport * from \"./useModularUI\";\nexport * from \"./useModularUIBasic\";\nexport * from \"./useModularUIModel\";\nexport * from \"./useModularUIRequest\";\nexport * from \"./useNotification\";\nexport * from \"./usePanel\";\nexport * from \"./usePreference\";\nexport * from \"./useProgressIndicator\";\nexport * from \"./useRouter\";\nexport * from \"./useSearch\";\n"],"mappings":"AACA,cAAc,sBAAsB;AACpC,cAAc,qBAAqB;AACnC,cAAc,cAAc;AAC5B,cAAc,WAAW;AACzB,cAAc,WAAW;AACzB,cAAc,WAAW;AACzB,cAAc,aAAa;AAC3B,cAAc,YAAY;AAC1B,cAAc,mBAAmB;AACjC,cAAc,aAAa;AAC3B,cAAc,qBAAqB;AACnC,cAAc,gBAAgB;AAC9B,cAAc,qBAAqB;AACnC,cAAc,qBAAqB;AACnC,cAAc,uBAAuB;AACrC,cAAc,mBAAmB;AACjC,cAAc,YAAY;AAC1B,cAAc,iBAAiB;AAC/B,cAAc,wBAAwB;AACtC,cAAc,aAAa;AAC3B,cAAc,aAAa","ignoreList":[]}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { useSelector } from "react-redux";
|
|
2
|
+
import { getAllModelsByInstance, getFirstModelByInstance, getActiveModelByInstance, modelByHref, keyByHref, allKeysByHref, getActiveModels, getAllFinishedModels } from "../redux/_modularui/ModularUISelectors";
|
|
3
|
+
import Href from "../models/href/Href";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Returns all models in the store that are instances of the provided class
|
|
7
|
+
* and match the current application locale.
|
|
8
|
+
*/
|
|
9
|
+
export const useAllModelsByInstance = instance => {
|
|
10
|
+
return useSelector(state => getAllModelsByInstance(state, instance));
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Returns the first model found in the store that is an instance of the
|
|
15
|
+
* provided class and matches the current locale.
|
|
16
|
+
*/
|
|
17
|
+
export const useFirstModelByInstance = instance => {
|
|
18
|
+
return useSelector(state => getFirstModelByInstance(state, instance));
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Returns the model instance that is currently "active" based on the URL path.
|
|
23
|
+
* It checks if the current router location starts with the model's selfhref path.
|
|
24
|
+
*/
|
|
25
|
+
export const useActiveModelByInstance = instance => {
|
|
26
|
+
return useSelector(state => getActiveModelByInstance(state, instance));
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Retrieves a specific model from the store based on its unique Href.
|
|
31
|
+
* @param {Href | string} href - The Href object or string path of the model.
|
|
32
|
+
* @returns {ModularUIModel | null} The model matching the href or null.
|
|
33
|
+
*/
|
|
34
|
+
export const useModelByHref = href => {
|
|
35
|
+
return useSelector(state => modelByHref(state, href));
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Returns the unique store key (identifier) for a model associated with a specific Href.
|
|
40
|
+
* @param {Href | string} href - The Href object or string path.
|
|
41
|
+
* @returns {string | null | void} The internal key of the model.
|
|
42
|
+
*/
|
|
43
|
+
export const useKeyByHref = href => {
|
|
44
|
+
return useSelector(state => keyByHref(state, href));
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Returns all internal keys found in the store for a specific Href.
|
|
49
|
+
* Useful if multiple versions/entries exist for the same path.
|
|
50
|
+
* @param {Href | string} href - The Href object or string path.
|
|
51
|
+
* @returns {Array<string>} An array of keys.
|
|
52
|
+
*/
|
|
53
|
+
export const useAllKeysByHref = href => {
|
|
54
|
+
return useSelector(state => allKeysByHref(state, href));
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Returns a list of simplified model info (key, href, label, type) for all
|
|
59
|
+
* models currently active in the navigation context (breadcrumbs).
|
|
60
|
+
* @returns {Array<{key: string, href: Href, label: string, type: string}>}
|
|
61
|
+
*/
|
|
62
|
+
export const useActiveModels = () => {
|
|
63
|
+
return useSelector(getActiveModels);
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Returns all models in the store that have a status of MODULARUI_STATUS.FINISHED.
|
|
68
|
+
* @returns {Array<ModularUIModel>} An array of fully loaded models.
|
|
69
|
+
*/
|
|
70
|
+
export const useAllFinishedModels = () => {
|
|
71
|
+
return useSelector(getAllFinishedModels);
|
|
72
|
+
};
|
|
73
|
+
//# sourceMappingURL=useModelSelectors.js.map
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
import { useSelector } from "react-redux";
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
getAllModelsByInstance,
|
|
6
|
+
getFirstModelByInstance,
|
|
7
|
+
getActiveModelByInstance,
|
|
8
|
+
modelByHref,
|
|
9
|
+
keyByHref,
|
|
10
|
+
allKeysByHref,
|
|
11
|
+
getActiveModels,
|
|
12
|
+
getAllFinishedModels,
|
|
13
|
+
} from "../redux/_modularui/ModularUISelectors";
|
|
14
|
+
import type { ModularUIModel } from "../models/types";
|
|
15
|
+
import type { ReduxState } from "../redux/types";
|
|
16
|
+
import Href from "../models/href/Href";
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Returns all models in the store that are instances of the provided class
|
|
20
|
+
* and match the current application locale.
|
|
21
|
+
*/
|
|
22
|
+
export const useAllModelsByInstance = <T>(
|
|
23
|
+
instance: Class<T>,
|
|
24
|
+
): Array<ModularUIModel> => {
|
|
25
|
+
return useSelector((state: ReduxState) =>
|
|
26
|
+
getAllModelsByInstance(state, instance),
|
|
27
|
+
);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Returns the first model found in the store that is an instance of the
|
|
32
|
+
* provided class and matches the current locale.
|
|
33
|
+
*/
|
|
34
|
+
export const useFirstModelByInstance = <T>(instance: Class<T>): T | null => {
|
|
35
|
+
return useSelector((state: ReduxState) =>
|
|
36
|
+
getFirstModelByInstance(state, instance),
|
|
37
|
+
);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Returns the model instance that is currently "active" based on the URL path.
|
|
42
|
+
* It checks if the current router location starts with the model's selfhref path.
|
|
43
|
+
*/
|
|
44
|
+
export const useActiveModelByInstance = <T>(instance: Class<T>): T | null => {
|
|
45
|
+
return useSelector((state: ReduxState) =>
|
|
46
|
+
getActiveModelByInstance(state, instance),
|
|
47
|
+
);
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Retrieves a specific model from the store based on its unique Href.
|
|
52
|
+
* @param {Href | string} href - The Href object or string path of the model.
|
|
53
|
+
* @returns {ModularUIModel | null} The model matching the href or null.
|
|
54
|
+
*/
|
|
55
|
+
export const useModelByHref = (href: Href | string): null | ModularUIModel => {
|
|
56
|
+
return useSelector((state: ReduxState) => modelByHref(state, href));
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Returns the unique store key (identifier) for a model associated with a specific Href.
|
|
61
|
+
* @param {Href | string} href - The Href object or string path.
|
|
62
|
+
* @returns {string | null | void} The internal key of the model.
|
|
63
|
+
*/
|
|
64
|
+
export const useKeyByHref = (href: Href | string): ?string => {
|
|
65
|
+
return useSelector((state: ReduxState) => keyByHref(state, href));
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Returns all internal keys found in the store for a specific Href.
|
|
70
|
+
* Useful if multiple versions/entries exist for the same path.
|
|
71
|
+
* @param {Href | string} href - The Href object or string path.
|
|
72
|
+
* @returns {Array<string>} An array of keys.
|
|
73
|
+
*/
|
|
74
|
+
export const useAllKeysByHref = (href: Href | string): Array<string> => {
|
|
75
|
+
return useSelector((state: ReduxState) => allKeysByHref(state, href));
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Returns a list of simplified model info (key, href, label, type) for all
|
|
80
|
+
* models currently active in the navigation context (breadcrumbs).
|
|
81
|
+
* @returns {Array<{key: string, href: Href, label: string, type: string}>}
|
|
82
|
+
*/
|
|
83
|
+
export const useActiveModels = (): Array<{
|
|
84
|
+
key: string,
|
|
85
|
+
href: Href,
|
|
86
|
+
label: string,
|
|
87
|
+
type: string,
|
|
88
|
+
}> => {
|
|
89
|
+
return useSelector(getActiveModels);
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Returns all models in the store that have a status of MODULARUI_STATUS.FINISHED.
|
|
94
|
+
* @returns {Array<ModularUIModel>} An array of fully loaded models.
|
|
95
|
+
*/
|
|
96
|
+
export const useAllFinishedModels = (): Array<ModularUIModel> => {
|
|
97
|
+
return useSelector(getAllFinishedModels);
|
|
98
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useModelSelectors.js","names":["useSelector","getAllModelsByInstance","getFirstModelByInstance","getActiveModelByInstance","modelByHref","keyByHref","allKeysByHref","getActiveModels","getAllFinishedModels","Href","useAllModelsByInstance","instance","state","useFirstModelByInstance","useActiveModelByInstance","useModelByHref","href","useKeyByHref","useAllKeysByHref","useActiveModels","useAllFinishedModels"],"sources":["../../src/hooks/useModelSelectors.js"],"sourcesContent":["// @flow\nimport { useSelector } from \"react-redux\";\n\nimport {\n getAllModelsByInstance,\n getFirstModelByInstance,\n getActiveModelByInstance,\n modelByHref,\n keyByHref,\n allKeysByHref,\n getActiveModels,\n getAllFinishedModels,\n} from \"../redux/_modularui/ModularUISelectors\";\nimport type { ModularUIModel } from \"../models/types\";\nimport type { ReduxState } from \"../redux/types\";\nimport Href from \"../models/href/Href\";\n\n/**\n * Returns all models in the store that are instances of the provided class\n * and match the current application locale.\n */\nexport const useAllModelsByInstance = <T>(\n instance: Class<T>,\n): Array<ModularUIModel> => {\n return useSelector((state: ReduxState) =>\n getAllModelsByInstance(state, instance),\n );\n};\n\n/**\n * Returns the first model found in the store that is an instance of the\n * provided class and matches the current locale.\n */\nexport const useFirstModelByInstance = <T>(instance: Class<T>): T | null => {\n return useSelector((state: ReduxState) =>\n getFirstModelByInstance(state, instance),\n );\n};\n\n/**\n * Returns the model instance that is currently \"active\" based on the URL path.\n * It checks if the current router location starts with the model's selfhref path.\n */\nexport const useActiveModelByInstance = <T>(instance: Class<T>): T | null => {\n return useSelector((state: ReduxState) =>\n getActiveModelByInstance(state, instance),\n );\n};\n\n/**\n * Retrieves a specific model from the store based on its unique Href.\n * @param {Href | string} href - The Href object or string path of the model.\n * @returns {ModularUIModel | null} The model matching the href or null.\n */\nexport const useModelByHref = (href: Href | string): null | ModularUIModel => {\n return useSelector((state: ReduxState) => modelByHref(state, href));\n};\n\n/**\n * Returns the unique store key (identifier) for a model associated with a specific Href.\n * @param {Href | string} href - The Href object or string path.\n * @returns {string | null | void} The internal key of the model.\n */\nexport const useKeyByHref = (href: Href | string): ?string => {\n return useSelector((state: ReduxState) => keyByHref(state, href));\n};\n\n/**\n * Returns all internal keys found in the store for a specific Href.\n * Useful if multiple versions/entries exist for the same path.\n * @param {Href | string} href - The Href object or string path.\n * @returns {Array<string>} An array of keys.\n */\nexport const useAllKeysByHref = (href: Href | string): Array<string> => {\n return useSelector((state: ReduxState) => allKeysByHref(state, href));\n};\n\n/**\n * Returns a list of simplified model info (key, href, label, type) for all\n * models currently active in the navigation context (breadcrumbs).\n * @returns {Array<{key: string, href: Href, label: string, type: string}>}\n */\nexport const useActiveModels = (): Array<{\n key: string,\n href: Href,\n label: string,\n type: string,\n}> => {\n return useSelector(getActiveModels);\n};\n\n/**\n * Returns all models in the store that have a status of MODULARUI_STATUS.FINISHED.\n * @returns {Array<ModularUIModel>} An array of fully loaded models.\n */\nexport const useAllFinishedModels = (): Array<ModularUIModel> => {\n return useSelector(getAllFinishedModels);\n};\n"],"mappings":"AACA,SAASA,WAAW,QAAQ,aAAa;AAEzC,SACEC,sBAAsB,EACtBC,uBAAuB,EACvBC,wBAAwB,EACxBC,WAAW,EACXC,SAAS,EACTC,aAAa,EACbC,eAAe,EACfC,oBAAoB,QACf,wCAAwC;AAG/C,OAAOC,IAAI,MAAM,qBAAqB;;AAEtC;AACA;AACA;AACA;AACA,OAAO,MAAMC,sBAAsB,GACjCC,QAAkB,IACQ;EAC1B,OAAOX,WAAW,CAAEY,KAAiB,IACnCX,sBAAsB,CAACW,KAAK,EAAED,QAAQ,CACxC,CAAC;AACH,CAAC;;AAED;AACA;AACA;AACA;AACA,OAAO,MAAME,uBAAuB,GAAOF,QAAkB,IAAe;EAC1E,OAAOX,WAAW,CAAEY,KAAiB,IACnCV,uBAAuB,CAACU,KAAK,EAAED,QAAQ,CACzC,CAAC;AACH,CAAC;;AAED;AACA;AACA;AACA;AACA,OAAO,MAAMG,wBAAwB,GAAOH,QAAkB,IAAe;EAC3E,OAAOX,WAAW,CAAEY,KAAiB,IACnCT,wBAAwB,CAACS,KAAK,EAAED,QAAQ,CAC1C,CAAC;AACH,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMI,cAAc,GAAIC,IAAmB,IAA4B;EAC5E,OAAOhB,WAAW,CAAEY,KAAiB,IAAKR,WAAW,CAACQ,KAAK,EAAEI,IAAI,CAAC,CAAC;AACrE,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,YAAY,GAAID,IAAmB,IAAc;EAC5D,OAAOhB,WAAW,CAAEY,KAAiB,IAAKP,SAAS,CAACO,KAAK,EAAEI,IAAI,CAAC,CAAC;AACnE,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAME,gBAAgB,GAAIF,IAAmB,IAAoB;EACtE,OAAOhB,WAAW,CAAEY,KAAiB,IAAKN,aAAa,CAACM,KAAK,EAAEI,IAAI,CAAC,CAAC;AACvE,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMG,eAAe,GAAGA,CAAA,KAKzB;EACJ,OAAOnB,WAAW,CAACO,eAAe,CAAC;AACrC,CAAC;;AAED;AACA;AACA;AACA;AACA,OAAO,MAAMa,oBAAoB,GAAGA,CAAA,KAA6B;EAC/D,OAAOpB,WAAW,CAACQ,oBAAoB,CAAC;AAC1C,CAAC","ignoreList":[]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useEffect, useMemo } from "react";
|
|
1
|
+
import { useEffect, useMemo, useRef } from "react";
|
|
2
2
|
import { useDispatch, useSelector } from "react-redux";
|
|
3
3
|
import { useLocation } from "react-router";
|
|
4
4
|
import { HTTP_METHODS, MODULARUI_STATUS } from "../constants";
|
|
@@ -7,17 +7,40 @@ import useDeepCompareEffect from "./useDeepCompareEffect";
|
|
|
7
7
|
import { useModularUIKey } from "./useModularUIKey";
|
|
8
8
|
import Href from "../models/href/Href";
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
10
|
+
* A custom hook to fetch and manage Be Informed modular UI resources.
|
|
11
|
+
* It handles automatic data fetching based on URL/query changes, manages Redux state
|
|
12
|
+
* synchronization, and provides cleanup logic when components unmount.
|
|
13
|
+
*
|
|
14
|
+
* @param {string} modelKey - A unique identifier for the type of model being fetched.
|
|
15
|
+
* @param {string | Href} url - The endpoint URL or Href instance to fetch data from.
|
|
16
|
+
* @param {RequestModularUIOptions} options - Configuration for the request (method, headers, etc.).
|
|
17
|
+
* @returns {ModelEntry} The model data retrieved from the Redux store.
|
|
11
18
|
*/
|
|
12
19
|
export const useModularUI = (modelKey, url, options = {}) => {
|
|
13
20
|
const dispatch = useDispatch();
|
|
14
|
-
|
|
15
|
-
|
|
21
|
+
|
|
22
|
+
// Normalize the URL input into a Href instance to safely access query params and paths
|
|
23
|
+
const hrefInstance = useMemo(() => new Href(url), [url]);
|
|
24
|
+
const requestUrl = useMemo(() => hrefInstance.toString(), [hrefInstance]);
|
|
25
|
+
const currentQueryString = hrefInstance.querystring;
|
|
26
|
+
|
|
27
|
+
// Persistence ref to detect if query parameters have changed between renders
|
|
28
|
+
const prevQueryRef = useRef(currentQueryString);
|
|
29
|
+
|
|
30
|
+
// Generate a unique key for the Redux store based on the model type and the full URL
|
|
31
|
+
const key = useModularUIKey(modelKey, requestUrl);
|
|
32
|
+
|
|
33
|
+
// Select the specific piece of state corresponding to this modular UI component
|
|
16
34
|
const model = useSelector(state => state.modularui[key]);
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Memoize request options to prevent unnecessary re-renders.
|
|
38
|
+
* Merges default settings (GET method, auto-cleanup) with user-provided options.
|
|
39
|
+
*/
|
|
17
40
|
const requestOptions = useMemo(() => {
|
|
18
41
|
const merged = {
|
|
19
42
|
method: HTTP_METHODS.GET,
|
|
20
|
-
removeOnUnmount:
|
|
43
|
+
removeOnUnmount: true,
|
|
21
44
|
...options
|
|
22
45
|
};
|
|
23
46
|
if (url instanceof Href) {
|
|
@@ -28,14 +51,34 @@ export const useModularUI = (modelKey, url, options = {}) => {
|
|
|
28
51
|
}, [options, url]);
|
|
29
52
|
const location = useLocation();
|
|
30
53
|
const redirectLocation = location.state?.redirectLocation;
|
|
31
|
-
const shouldLoad = model == null || model.status === MODULARUI_STATUS.ERROR || (redirectLocation instanceof Href ? redirectLocation?.equals(href) : false) || requestOptions.isReload === true;
|
|
32
54
|
|
|
33
|
-
|
|
55
|
+
/**
|
|
56
|
+
* Determines if a network request should be initiated.
|
|
57
|
+
* Logic includes:
|
|
58
|
+
* - Model doesn't exist yet (Initial load)
|
|
59
|
+
* - Previous request resulted in an error (Retry)
|
|
60
|
+
* - The query parameters changed (Filtering/Paging)
|
|
61
|
+
* - A redirect was triggered specifically for this URL
|
|
62
|
+
* - Manual 'isReload' flag is passed in options
|
|
63
|
+
*/
|
|
64
|
+
const shouldLoad = model == null || model.status === MODULARUI_STATUS.ERROR || prevQueryRef.current !== currentQueryString || (redirectLocation instanceof Href ? redirectLocation.equals(requestUrl) : false) || requestOptions.isReload === true;
|
|
65
|
+
|
|
66
|
+
// Synchronize the ref after the render cycle determines if we should load
|
|
67
|
+
useEffect(() => {
|
|
68
|
+
prevQueryRef.current = currentQueryString;
|
|
69
|
+
}, [currentQueryString]);
|
|
70
|
+
|
|
71
|
+
// Execute the load action. Deep compare is used on options to prevent
|
|
72
|
+
// infinite loops caused by passing inline object literals.
|
|
34
73
|
useDeepCompareEffect(() => {
|
|
35
|
-
if (
|
|
36
|
-
dispatch(loadModularUI(key,
|
|
74
|
+
if (requestUrl !== "" && shouldLoad) {
|
|
75
|
+
dispatch(loadModularUI(key, requestUrl, requestOptions));
|
|
37
76
|
}
|
|
38
|
-
}, [key,
|
|
77
|
+
}, [key, requestUrl, requestOptions, shouldLoad]);
|
|
78
|
+
|
|
79
|
+
// Cleanup Effect:
|
|
80
|
+
// If 'removeOnUnmount' is true, this removes the model data from the Redux store
|
|
81
|
+
// when the component using this hook is destroyed.
|
|
39
82
|
useEffect(() => {
|
|
40
83
|
if (requestOptions.removeOnUnmount) {
|
|
41
84
|
return () => {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @flow
|
|
2
|
-
import { useEffect, useMemo } from "react";
|
|
2
|
+
import { useEffect, useMemo, useRef } from "react";
|
|
3
3
|
import { useDispatch, useSelector } from "react-redux";
|
|
4
4
|
import { useLocation } from "react-router";
|
|
5
5
|
|
|
@@ -13,10 +13,19 @@ import useDeepCompareEffect from "./useDeepCompareEffect";
|
|
|
13
13
|
import { useModularUIKey } from "./useModularUIKey";
|
|
14
14
|
|
|
15
15
|
import Href from "../models/href/Href";
|
|
16
|
+
|
|
16
17
|
import type { RequestModularUIOptions } from "../utils";
|
|
18
|
+
import type { ModelEntry } from "../redux";
|
|
17
19
|
|
|
18
20
|
/**
|
|
19
|
-
*
|
|
21
|
+
* A custom hook to fetch and manage Be Informed modular UI resources.
|
|
22
|
+
* It handles automatic data fetching based on URL/query changes, manages Redux state
|
|
23
|
+
* synchronization, and provides cleanup logic when components unmount.
|
|
24
|
+
*
|
|
25
|
+
* @param {string} modelKey - A unique identifier for the type of model being fetched.
|
|
26
|
+
* @param {string | Href} url - The endpoint URL or Href instance to fetch data from.
|
|
27
|
+
* @param {RequestModularUIOptions} options - Configuration for the request (method, headers, etc.).
|
|
28
|
+
* @returns {ModelEntry} The model data retrieved from the Redux store.
|
|
20
29
|
*/
|
|
21
30
|
export const useModularUI = (
|
|
22
31
|
modelKey: string,
|
|
@@ -25,15 +34,28 @@ export const useModularUI = (
|
|
|
25
34
|
): any => {
|
|
26
35
|
const dispatch = useDispatch();
|
|
27
36
|
|
|
28
|
-
|
|
29
|
-
const
|
|
37
|
+
// Normalize the URL input into a Href instance to safely access query params and paths
|
|
38
|
+
const hrefInstance = useMemo(() => new Href(url), [url]);
|
|
39
|
+
const requestUrl = useMemo(() => hrefInstance.toString(), [hrefInstance]);
|
|
40
|
+
const currentQueryString = hrefInstance.querystring;
|
|
41
|
+
|
|
42
|
+
// Persistence ref to detect if query parameters have changed between renders
|
|
43
|
+
const prevQueryRef = useRef(currentQueryString);
|
|
44
|
+
|
|
45
|
+
// Generate a unique key for the Redux store based on the model type and the full URL
|
|
46
|
+
const key = useModularUIKey(modelKey, requestUrl);
|
|
30
47
|
|
|
48
|
+
// Select the specific piece of state corresponding to this modular UI component
|
|
31
49
|
const model = useSelector((state) => state.modularui[key]);
|
|
32
50
|
|
|
51
|
+
/**
|
|
52
|
+
* Memoize request options to prevent unnecessary re-renders.
|
|
53
|
+
* Merges default settings (GET method, auto-cleanup) with user-provided options.
|
|
54
|
+
*/
|
|
33
55
|
const requestOptions = useMemo(() => {
|
|
34
56
|
const merged = {
|
|
35
57
|
method: HTTP_METHODS.GET,
|
|
36
|
-
removeOnUnmount:
|
|
58
|
+
removeOnUnmount: true,
|
|
37
59
|
...options,
|
|
38
60
|
};
|
|
39
61
|
|
|
@@ -47,21 +69,40 @@ export const useModularUI = (
|
|
|
47
69
|
const location = useLocation();
|
|
48
70
|
const redirectLocation = location.state?.redirectLocation;
|
|
49
71
|
|
|
72
|
+
/**
|
|
73
|
+
* Determines if a network request should be initiated.
|
|
74
|
+
* Logic includes:
|
|
75
|
+
* - Model doesn't exist yet (Initial load)
|
|
76
|
+
* - Previous request resulted in an error (Retry)
|
|
77
|
+
* - The query parameters changed (Filtering/Paging)
|
|
78
|
+
* - A redirect was triggered specifically for this URL
|
|
79
|
+
* - Manual 'isReload' flag is passed in options
|
|
80
|
+
*/
|
|
50
81
|
const shouldLoad =
|
|
51
82
|
model == null ||
|
|
52
83
|
model.status === MODULARUI_STATUS.ERROR ||
|
|
84
|
+
prevQueryRef.current !== currentQueryString ||
|
|
53
85
|
(redirectLocation instanceof Href
|
|
54
|
-
? redirectLocation
|
|
86
|
+
? redirectLocation.equals(requestUrl)
|
|
55
87
|
: false) ||
|
|
56
88
|
requestOptions.isReload === true;
|
|
57
89
|
|
|
58
|
-
//
|
|
90
|
+
// Synchronize the ref after the render cycle determines if we should load
|
|
91
|
+
useEffect(() => {
|
|
92
|
+
prevQueryRef.current = currentQueryString;
|
|
93
|
+
}, [currentQueryString]);
|
|
94
|
+
|
|
95
|
+
// Execute the load action. Deep compare is used on options to prevent
|
|
96
|
+
// infinite loops caused by passing inline object literals.
|
|
59
97
|
useDeepCompareEffect(() => {
|
|
60
|
-
if (
|
|
61
|
-
dispatch(loadModularUI(key,
|
|
98
|
+
if (requestUrl !== "" && shouldLoad) {
|
|
99
|
+
dispatch(loadModularUI(key, requestUrl, requestOptions));
|
|
62
100
|
}
|
|
63
|
-
}, [key,
|
|
101
|
+
}, [key, requestUrl, requestOptions, shouldLoad]);
|
|
64
102
|
|
|
103
|
+
// Cleanup Effect:
|
|
104
|
+
// If 'removeOnUnmount' is true, this removes the model data from the Redux store
|
|
105
|
+
// when the component using this hook is destroyed.
|
|
65
106
|
useEffect(() => {
|
|
66
107
|
if (requestOptions.removeOnUnmount) {
|
|
67
108
|
return () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useModularUI.js","names":["useEffect","useMemo","useDispatch","useSelector","useLocation","HTTP_METHODS","MODULARUI_STATUS","loadModularUI","removeModelByKey","useDeepCompareEffect","useModularUIKey","Href","useModularUI","modelKey","url","options","dispatch","
|
|
1
|
+
{"version":3,"file":"useModularUI.js","names":["useEffect","useMemo","useRef","useDispatch","useSelector","useLocation","HTTP_METHODS","MODULARUI_STATUS","loadModularUI","removeModelByKey","useDeepCompareEffect","useModularUIKey","Href","useModularUI","modelKey","url","options","dispatch","hrefInstance","requestUrl","toString","currentQueryString","querystring","prevQueryRef","key","model","state","modularui","requestOptions","merged","method","GET","removeOnUnmount","origin","contextPath","location","redirectLocation","shouldLoad","status","ERROR","current","equals","isReload"],"sources":["../../src/hooks/useModularUI.js"],"sourcesContent":["// @flow\nimport { useEffect, useMemo, useRef } from \"react\";\nimport { useDispatch, useSelector } from \"react-redux\";\nimport { useLocation } from \"react-router\";\n\nimport { HTTP_METHODS, MODULARUI_STATUS } from \"../constants\";\nimport {\n loadModularUI,\n removeModelByKey,\n} from \"../redux/_modularui/ModularUIActions\";\n\nimport useDeepCompareEffect from \"./useDeepCompareEffect\";\nimport { useModularUIKey } from \"./useModularUIKey\";\n\nimport Href from \"../models/href/Href\";\n\nimport type { RequestModularUIOptions } from \"../utils\";\nimport type { ModelEntry } from \"../redux\";\n\n/**\n * A custom hook to fetch and manage Be Informed modular UI resources.\n * It handles automatic data fetching based on URL/query changes, manages Redux state\n * synchronization, and provides cleanup logic when components unmount.\n *\n * @param {string} modelKey - A unique identifier for the type of model being fetched.\n * @param {string | Href} url - The endpoint URL or Href instance to fetch data from.\n * @param {RequestModularUIOptions} options - Configuration for the request (method, headers, etc.).\n * @returns {ModelEntry} The model data retrieved from the Redux store.\n */\nexport const useModularUI = (\n modelKey: string,\n url: string | Href,\n options: RequestModularUIOptions = (({}: any): RequestModularUIOptions),\n): any => {\n const dispatch = useDispatch();\n\n // Normalize the URL input into a Href instance to safely access query params and paths\n const hrefInstance = useMemo(() => new Href(url), [url]);\n const requestUrl = useMemo(() => hrefInstance.toString(), [hrefInstance]);\n const currentQueryString = hrefInstance.querystring;\n\n // Persistence ref to detect if query parameters have changed between renders\n const prevQueryRef = useRef(currentQueryString);\n\n // Generate a unique key for the Redux store based on the model type and the full URL\n const key = useModularUIKey(modelKey, requestUrl);\n\n // Select the specific piece of state corresponding to this modular UI component\n const model = useSelector((state) => state.modularui[key]);\n\n /**\n * Memoize request options to prevent unnecessary re-renders.\n * Merges default settings (GET method, auto-cleanup) with user-provided options.\n */\n const requestOptions = useMemo(() => {\n const merged = {\n method: HTTP_METHODS.GET,\n removeOnUnmount: true,\n ...options,\n };\n\n if (url instanceof Href) {\n merged.origin = merged.origin ?? url.origin;\n merged.contextPath = merged.contextPath ?? url.contextPath;\n }\n return merged;\n }, [options, url]);\n\n const location = useLocation();\n const redirectLocation = location.state?.redirectLocation;\n\n /**\n * Determines if a network request should be initiated.\n * Logic includes:\n * - Model doesn't exist yet (Initial load)\n * - Previous request resulted in an error (Retry)\n * - The query parameters changed (Filtering/Paging)\n * - A redirect was triggered specifically for this URL\n * - Manual 'isReload' flag is passed in options\n */\n const shouldLoad =\n model == null ||\n model.status === MODULARUI_STATUS.ERROR ||\n prevQueryRef.current !== currentQueryString ||\n (redirectLocation instanceof Href\n ? redirectLocation.equals(requestUrl)\n : false) ||\n requestOptions.isReload === true;\n\n // Synchronize the ref after the render cycle determines if we should load\n useEffect(() => {\n prevQueryRef.current = currentQueryString;\n }, [currentQueryString]);\n\n // Execute the load action. Deep compare is used on options to prevent\n // infinite loops caused by passing inline object literals.\n useDeepCompareEffect(() => {\n if (requestUrl !== \"\" && shouldLoad) {\n dispatch(loadModularUI(key, requestUrl, requestOptions));\n }\n }, [key, requestUrl, requestOptions, shouldLoad]);\n\n // Cleanup Effect:\n // If 'removeOnUnmount' is true, this removes the model data from the Redux store\n // when the component using this hook is destroyed.\n useEffect(() => {\n if (requestOptions.removeOnUnmount) {\n return () => {\n dispatch(removeModelByKey(key));\n };\n }\n }, [dispatch, key, requestOptions.removeOnUnmount]);\n\n return model;\n};\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -5,13 +5,29 @@ import { useMemo } from "react";
|
|
|
5
5
|
import { useModularUI } from "./useModularUI";
|
|
6
6
|
import { HTTP_METHODS, MODULARUI_STATUS } from "../constants";
|
|
7
7
|
import { useModularUIKey } from "./useModularUIKey";
|
|
8
|
-
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Configuration options for low-level modular UI requests.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Configuration options for the useModularUIBasic hook.
|
|
15
|
+
* Allows for type enforcement, caching control, and reload behavior.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Internal helper to transform high-level hook options into a configuration
|
|
20
|
+
* object compatible with the core useModularUI fetcher.
|
|
21
|
+
* Logic:
|
|
22
|
+
* 1. Defaults to GET method.
|
|
23
|
+
* 2. If 'formdata' is present, it switches to POST and assigns 'data'.
|
|
24
|
+
* 3. Forces 'isReload' if the useReload check returns true.
|
|
25
|
+
*/
|
|
9
26
|
const createUseModularUIOptions = (options, href, mustReload) => {
|
|
10
27
|
const baseOptions = {
|
|
11
28
|
expectedModels: [],
|
|
12
29
|
method: HTTP_METHODS.GET,
|
|
13
30
|
data: undefined,
|
|
14
|
-
removeOnUnmount: false,
|
|
15
31
|
...options,
|
|
16
32
|
isReload: mustReload || options.isReload
|
|
17
33
|
};
|
|
@@ -22,7 +38,10 @@ const createUseModularUIOptions = (options, href, mustReload) => {
|
|
|
22
38
|
return baseOptions;
|
|
23
39
|
};
|
|
24
40
|
|
|
25
|
-
|
|
41
|
+
/**
|
|
42
|
+
* Validates that the returned model type matches one of the expected model strings.
|
|
43
|
+
* Logs a warning to the console if there is a mismatch (useful for debugging UI-backend contracts).
|
|
44
|
+
*/
|
|
26
45
|
const validateModel = (model, expectedModels) => {
|
|
27
46
|
if (expectedModels.length > 0) {
|
|
28
47
|
const isCorrectModel = _includesInstanceProperty(expectedModels).call(expectedModels, model.type);
|
|
@@ -33,15 +52,28 @@ const validateModel = (model, expectedModels) => {
|
|
|
33
52
|
};
|
|
34
53
|
|
|
35
54
|
/**
|
|
36
|
-
*
|
|
55
|
+
* A simplified abstraction over useModularUI that includes automatic
|
|
56
|
+
* model validation and smart-reload logic based on router state.
|
|
57
|
+
*
|
|
58
|
+
* @param {string} defaultKey - The default identifier for the model.
|
|
59
|
+
* @param {string | Href} href - The endpoint to fetch.
|
|
60
|
+
* @param {UseModularUIBasicOptions} options - Extended configuration options.
|
|
37
61
|
*/
|
|
38
62
|
export const useModularUIBasic = (defaultKey, href, options = {}) => {
|
|
39
63
|
const memoizedHref = useMemo(() => href.toString(), [href]);
|
|
64
|
+
|
|
65
|
+
// Use the key provided in options if available, otherwise fallback to the default
|
|
40
66
|
const key = options.key ?? defaultKey;
|
|
67
|
+
|
|
68
|
+
// Determine if we need to bypass cache based on navigation 'reload' signals
|
|
41
69
|
const mustReload = useReload(key, memoizedHref);
|
|
70
|
+
|
|
71
|
+
// Memoize options to prevent useModularUI from re-fetching on every parent render
|
|
42
72
|
const modularUIOptions = useMemo(() => createUseModularUIOptions(options, memoizedHref, mustReload), [options, memoizedHref, mustReload]);
|
|
43
73
|
const modularUI = useModularUI(key, href, modularUIOptions);
|
|
44
74
|
const expectedModels = useMemo(() => options.expectedModels ?? [], [options.expectedModels]);
|
|
75
|
+
|
|
76
|
+
// Extract and validate the model from the modularUI wrapper object
|
|
45
77
|
return useMemo(() => {
|
|
46
78
|
if (modularUI?.model) {
|
|
47
79
|
validateModel(modularUI.model, expectedModels);
|
|
@@ -52,17 +84,30 @@ export const useModularUIBasic = (defaultKey, href, options = {}) => {
|
|
|
52
84
|
};
|
|
53
85
|
|
|
54
86
|
/**
|
|
55
|
-
*
|
|
87
|
+
* Determines if a model should be reloaded based on the 'reload' timestamp
|
|
88
|
+
* found in the React Router location state.
|
|
89
|
+
* This is used for "force refresh" scenarios where a user navigates to a
|
|
90
|
+
* page and expects fresh data (e.g., after a form submission elsewhere).
|
|
91
|
+
* @param {string} modelKey - The model type key.
|
|
92
|
+
* @param {string} url - The resource URL.
|
|
93
|
+
* @returns {boolean} True if the store data is stale compared to the reload signal.
|
|
56
94
|
*/
|
|
57
95
|
export const useReload = (modelKey, url) => {
|
|
58
96
|
const location = useLocation();
|
|
59
97
|
const key = useModularUIKey(modelKey, url);
|
|
98
|
+
|
|
99
|
+
// Access the current entry in the Redux store
|
|
60
100
|
const modelEntry = useSelector(state => state.modularui[key]);
|
|
61
101
|
if (modelEntry) {
|
|
62
102
|
const reload = location.state?.reload || 0;
|
|
103
|
+
|
|
104
|
+
// If a reload timestamp exists in the router state
|
|
63
105
|
if (reload > 0) {
|
|
64
106
|
const isFullyLoaded = modelEntry?.status === MODULARUI_STATUS.FINISHED;
|
|
65
107
|
const lastModification = modelEntry?.lastModification ?? 0;
|
|
108
|
+
|
|
109
|
+
// Trigger reload only if the model is already finished loading
|
|
110
|
+
// AND the data we have is older than the requested reload time.
|
|
66
111
|
if (isFullyLoaded && lastModification < reload) {
|
|
67
112
|
return true;
|
|
68
113
|
}
|