@beinformed/ui 1.65.9 → 1.65.11
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 +21 -0
- package/esm/hooks/useDeepCompareEffect.js +22 -8
- package/esm/hooks/useDeepCompareEffect.js.flow +26 -10
- package/esm/hooks/useDeepCompareEffect.js.map +1 -1
- package/esm/hooks/useList.js +18 -15
- package/esm/hooks/useList.js.flow +17 -16
- package/esm/hooks/useList.js.map +1 -1
- package/esm/hooks/useModularUIBasic.js +10 -3
- package/esm/hooks/useModularUIBasic.js.flow +11 -1
- package/esm/hooks/useModularUIBasic.js.map +1 -1
- package/esm/hooks/usePanel.js.flow +1 -1
- package/esm/hooks/usePanel.js.map +1 -1
- package/esm/hooks/useRouter.js +12 -6
- package/esm/hooks/useRouter.js.flow +29 -23
- package/esm/hooks/useRouter.js.map +1 -1
- package/esm/models/attributes/AttributeModel.js +14 -0
- package/esm/models/attributes/AttributeModel.js.flow +14 -0
- package/esm/models/attributes/AttributeModel.js.map +1 -1
- package/esm/models/attributes/CompositeAttributeModel.js +11 -11
- package/esm/models/attributes/CompositeAttributeModel.js.flow +11 -11
- package/esm/models/attributes/CompositeAttributeModel.js.map +1 -1
- package/esm/models/attributes/PasswordAttributeModel.js +3 -3
- package/esm/models/attributes/PasswordAttributeModel.js.flow +3 -3
- package/esm/models/attributes/PasswordAttributeModel.js.map +1 -1
- package/esm/models/filters/FilterModel.js +1 -1
- package/esm/models/filters/FilterModel.js.flow +1 -1
- package/esm/models/filters/FilterModel.js.map +1 -1
- package/esm/models/filters/RangeFilterModel.js +1 -1
- package/esm/models/filters/RangeFilterModel.js.flow +1 -1
- package/esm/models/filters/RangeFilterModel.js.map +1 -1
- package/esm/models/href/Href.js +27 -2
- package/esm/models/href/Href.js.flow +30 -2
- package/esm/models/href/Href.js.map +1 -1
- package/esm/models/href/ListHref.js +3 -2
- package/esm/models/href/ListHref.js.flow +4 -2
- package/esm/models/href/ListHref.js.map +1 -1
- package/esm/models/list/ListModel.js +7 -1
- package/esm/models/list/ListModel.js.flow +8 -2
- package/esm/models/list/ListModel.js.map +1 -1
- package/esm/models/parameter/Parameter.js +6 -6
- package/esm/models/parameter/Parameter.js.flow +6 -6
- package/esm/models/parameter/Parameter.js.map +1 -1
- package/lib/hooks/useDeepCompareEffect.js +22 -11
- package/lib/hooks/useDeepCompareEffect.js.map +1 -1
- package/lib/hooks/useList.js +18 -15
- package/lib/hooks/useList.js.map +1 -1
- package/lib/hooks/useModularUIBasic.js +9 -2
- package/lib/hooks/useModularUIBasic.js.map +1 -1
- package/lib/hooks/usePanel.js.map +1 -1
- package/lib/hooks/useRouter.js +12 -6
- package/lib/hooks/useRouter.js.map +1 -1
- package/lib/models/attributes/AttributeModel.js +14 -0
- package/lib/models/attributes/AttributeModel.js.map +1 -1
- package/lib/models/attributes/CompositeAttributeModel.js +11 -11
- package/lib/models/attributes/CompositeAttributeModel.js.map +1 -1
- package/lib/models/attributes/PasswordAttributeModel.js +3 -3
- package/lib/models/attributes/PasswordAttributeModel.js.map +1 -1
- package/lib/models/filters/FilterModel.js +1 -1
- package/lib/models/filters/FilterModel.js.map +1 -1
- package/lib/models/filters/RangeFilterModel.js +1 -1
- package/lib/models/filters/RangeFilterModel.js.map +1 -1
- package/lib/models/href/Href.js +27 -2
- package/lib/models/href/Href.js.map +1 -1
- package/lib/models/href/ListHref.js +3 -2
- package/lib/models/href/ListHref.js.map +1 -1
- package/lib/models/list/ListModel.js +7 -1
- package/lib/models/list/ListModel.js.map +1 -1
- package/lib/models/parameter/Parameter.js +6 -6
- package/lib/models/parameter/Parameter.js.map +1 -1
- package/package.json +4 -4
- package/src/hooks/useDeepCompareEffect.js +26 -10
- package/src/hooks/useList.js +17 -16
- package/src/hooks/useModularUIBasic.js +11 -1
- package/src/hooks/usePanel.js +1 -1
- package/src/hooks/useRouter.js +29 -23
- package/src/models/attributes/AttributeModel.js +14 -0
- package/src/models/attributes/CompositeAttributeModel.js +11 -11
- package/src/models/attributes/PasswordAttributeModel.js +3 -3
- package/src/models/filters/FilterModel.js +1 -1
- package/src/models/filters/RangeFilterModel.js +1 -1
- package/src/models/href/Href.js +30 -2
- package/src/models/href/ListHref.js +4 -2
- package/src/models/list/ListModel.js +8 -2
- package/src/models/parameter/Parameter.js +6 -6
|
@@ -4,7 +4,7 @@ import { useSelector } from "react-redux";
|
|
|
4
4
|
import { useMemo } from "react";
|
|
5
5
|
import { useModularUI } from "./useModularUI";
|
|
6
6
|
|
|
7
|
-
import { MODULARUI_STATUS } from "../constants";
|
|
7
|
+
import { HTTP_METHODS, MODULARUI_STATUS } from "../constants";
|
|
8
8
|
import { useModularUIKey } from "./useModularUIKey";
|
|
9
9
|
|
|
10
10
|
import type { ModularUIModel, Href } from "../models";
|
|
@@ -13,6 +13,7 @@ export type HookOptions = {
|
|
|
13
13
|
origin?: string,
|
|
14
14
|
contextPath?: string,
|
|
15
15
|
removeOnUnmount?: boolean,
|
|
16
|
+
formdata?: any,
|
|
16
17
|
};
|
|
17
18
|
|
|
18
19
|
export type UseModularUIBasicOptions<T: ModularUIModel> = {
|
|
@@ -25,6 +26,7 @@ export type UseModularUIBasicOptions<T: ModularUIModel> = {
|
|
|
25
26
|
key?: string,
|
|
26
27
|
isReload?: boolean,
|
|
27
28
|
removeOnUnmount?: boolean,
|
|
29
|
+
formdata?: any,
|
|
28
30
|
};
|
|
29
31
|
|
|
30
32
|
// Helper to create useModularUI options
|
|
@@ -41,6 +43,8 @@ const createUseModularUIOptions = <T: ModularUIModel>(
|
|
|
41
43
|
contextPath: undefined,
|
|
42
44
|
cache: false,
|
|
43
45
|
removeOnUnmount: false,
|
|
46
|
+
method: HTTP_METHODS.GET,
|
|
47
|
+
data: undefined,
|
|
44
48
|
};
|
|
45
49
|
|
|
46
50
|
// Handle targetModel and forceTargetModel
|
|
@@ -62,6 +66,11 @@ const createUseModularUIOptions = <T: ModularUIModel>(
|
|
|
62
66
|
baseOptions.removeOnUnmount = true;
|
|
63
67
|
}
|
|
64
68
|
|
|
69
|
+
if (options.formdata != null) {
|
|
70
|
+
baseOptions.method = HTTP_METHODS.POST;
|
|
71
|
+
baseOptions.data = options.formdata;
|
|
72
|
+
}
|
|
73
|
+
|
|
65
74
|
// Handle origin and contextPath options
|
|
66
75
|
baseOptions.origin = options.origin ?? baseOptions.origin;
|
|
67
76
|
baseOptions.contextPath = options.contextPath ?? baseOptions.contextPath;
|
|
@@ -94,6 +103,7 @@ export const useModularUIBasic = <T: ModularUIModel>(
|
|
|
94
103
|
origin: undefined,
|
|
95
104
|
contextPath: undefined,
|
|
96
105
|
key: undefined,
|
|
106
|
+
formdata: undefined,
|
|
97
107
|
},
|
|
98
108
|
): T | null => {
|
|
99
109
|
const memoizedHref = useMemo(() => href.toString(), [href]);
|
package/src/hooks/usePanel.js
CHANGED
|
@@ -64,7 +64,7 @@ const useUrl = (href?: string | Href, fromRoute: boolean = false) => {
|
|
|
64
64
|
*/
|
|
65
65
|
export const usePanel = (
|
|
66
66
|
href?: string | Href,
|
|
67
|
-
options?: HookOptions
|
|
67
|
+
options?: { ...HookOptions, fromRoute?: boolean },
|
|
68
68
|
): ListModel | GroupingPanelModel | DetailModel | null => {
|
|
69
69
|
const { fromRoute, ...hookOptions } = options || { fromRoute: false };
|
|
70
70
|
|
package/src/hooks/useRouter.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// @flow
|
|
2
|
+
import { useMemo } from "react";
|
|
2
3
|
import { useDispatch, useSelector } from "react-redux";
|
|
3
|
-
import type { Location, LocationShape } from "react-router";
|
|
4
4
|
|
|
5
5
|
import {
|
|
6
6
|
push,
|
|
@@ -9,6 +9,8 @@ import {
|
|
|
9
9
|
goBack,
|
|
10
10
|
goForward,
|
|
11
11
|
} from "../redux/_router/RouterActions";
|
|
12
|
+
|
|
13
|
+
import type { Location, LocationShape } from "react-router";
|
|
12
14
|
import type {
|
|
13
15
|
GoAction,
|
|
14
16
|
GoBackAction,
|
|
@@ -17,48 +19,52 @@ import type {
|
|
|
17
19
|
ReplaceAction,
|
|
18
20
|
} from "../redux";
|
|
19
21
|
|
|
20
|
-
type
|
|
21
|
-
type UseLocationKeyHook = () => string;
|
|
22
|
-
type UseQuerystringHook = () => string;
|
|
23
|
-
type UsePathnameHook = () => string;
|
|
24
|
-
type UseNavigationHook = () => {
|
|
22
|
+
type NavigationAPI = {|
|
|
25
23
|
push: (location: LocationShape | string, state?: { ... }) => PushAction,
|
|
26
24
|
replace: (location: LocationShape | string, state?: { ... }) => ReplaceAction,
|
|
27
25
|
go: (delta: number) => GoAction,
|
|
28
26
|
goBack: () => GoBackAction,
|
|
29
27
|
goForward: () => GoForwardAction,
|
|
30
|
-
};
|
|
28
|
+
|};
|
|
31
29
|
|
|
32
30
|
/**
|
|
31
|
+
* Returns the full location object from the router state.
|
|
33
32
|
*/
|
|
34
|
-
export const useLocation
|
|
35
|
-
useSelector((state) => state.router
|
|
33
|
+
export const useLocation = (): Location =>
|
|
34
|
+
useSelector((state) => state.router?.location || {});
|
|
36
35
|
|
|
37
36
|
/**
|
|
37
|
+
* Returns the unique key of the current location.
|
|
38
38
|
*/
|
|
39
|
-
export const useLocationKey
|
|
40
|
-
|
|
39
|
+
export const useLocationKey = (): string =>
|
|
40
|
+
useSelector((state) => state.router?.location?.key ?? "");
|
|
41
41
|
|
|
42
42
|
/**
|
|
43
|
+
* Returns the current search (querystring) portion of the URL.
|
|
43
44
|
*/
|
|
44
|
-
export const useQuerystring
|
|
45
|
+
export const useQuerystring = (): string =>
|
|
46
|
+
useSelector((state) => state.router?.location?.search ?? "");
|
|
45
47
|
|
|
46
48
|
/**
|
|
49
|
+
* Returns the current URL pathname.
|
|
47
50
|
*/
|
|
48
|
-
export const usePathname
|
|
51
|
+
export const usePathname = (): string =>
|
|
52
|
+
useSelector((state) => state.router?.location?.pathname ?? "");
|
|
49
53
|
|
|
50
54
|
/**
|
|
55
|
+
* Provides navigation methods.
|
|
51
56
|
*/
|
|
52
|
-
export const useNavigation
|
|
57
|
+
export const useNavigation = (): NavigationAPI => {
|
|
53
58
|
const dispatch = useDispatch();
|
|
54
59
|
|
|
55
|
-
return
|
|
56
|
-
|
|
57
|
-
dispatch(push(location, state)),
|
|
58
|
-
|
|
59
|
-
dispatch(
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
60
|
+
return useMemo(
|
|
61
|
+
() => ({
|
|
62
|
+
push: (location, state) => dispatch(push(location, state)),
|
|
63
|
+
replace: (location, state) => dispatch(replace(location, state)),
|
|
64
|
+
go: (delta) => dispatch(go(delta)),
|
|
65
|
+
goBack: () => dispatch(goBack()),
|
|
66
|
+
goForward: () => dispatch(goForward()),
|
|
67
|
+
}),
|
|
68
|
+
[dispatch],
|
|
69
|
+
);
|
|
64
70
|
};
|
|
@@ -613,6 +613,20 @@ export default class AttributeModel
|
|
|
613
613
|
return this.validate(this.validateValue);
|
|
614
614
|
}
|
|
615
615
|
|
|
616
|
+
/**
|
|
617
|
+
* Get valid status
|
|
618
|
+
*/
|
|
619
|
+
getIsValid(): boolean {
|
|
620
|
+
return this._isValid;
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
/**
|
|
624
|
+
* Set valid status
|
|
625
|
+
*/
|
|
626
|
+
setIsValid(isValid: boolean) {
|
|
627
|
+
this._isValid = isValid;
|
|
628
|
+
}
|
|
629
|
+
|
|
616
630
|
/**
|
|
617
631
|
* Retrieve applicable constraint for this attribute
|
|
618
632
|
*/
|
|
@@ -155,13 +155,20 @@ class CompositeAttributeModel extends AttributeModel {
|
|
|
155
155
|
return true;
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
-
|
|
158
|
+
let isValid = this.children.validate();
|
|
159
159
|
|
|
160
|
-
if (
|
|
161
|
-
|
|
160
|
+
if (isValid) {
|
|
161
|
+
isValid = this.constraintCollection.validate();
|
|
162
162
|
}
|
|
163
163
|
|
|
164
|
-
|
|
164
|
+
this.setIsValid(isValid);
|
|
165
|
+
return this.getIsValid();
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
*/
|
|
170
|
+
get isValid(): boolean {
|
|
171
|
+
return this.validate("");
|
|
165
172
|
}
|
|
166
173
|
|
|
167
174
|
/**
|
|
@@ -193,13 +200,6 @@ class CompositeAttributeModel extends AttributeModel {
|
|
|
193
200
|
return constraints;
|
|
194
201
|
}
|
|
195
202
|
|
|
196
|
-
/**
|
|
197
|
-
* Indicates if attribute input is valid
|
|
198
|
-
*/
|
|
199
|
-
get isValid(): boolean {
|
|
200
|
-
return this.validate("");
|
|
201
|
-
}
|
|
202
|
-
|
|
203
203
|
/**
|
|
204
204
|
*/
|
|
205
205
|
hasServerErrors(): boolean {
|
|
@@ -222,13 +222,13 @@ export default class PasswordAttributeModel extends StringAttributeModel {
|
|
|
222
222
|
}
|
|
223
223
|
|
|
224
224
|
if (this.isOptionalAndEmpty(value)) {
|
|
225
|
-
this.
|
|
225
|
+
this.setIsValid(true);
|
|
226
226
|
} else if (this._validatedValue !== `${this.confirmValue}-${value}`) {
|
|
227
|
-
this.
|
|
227
|
+
this.setIsValid(this.constraintCollection.validate(value));
|
|
228
228
|
}
|
|
229
229
|
this._validatedValue = `${this.confirmValue}-${value}`;
|
|
230
230
|
|
|
231
|
-
return this.
|
|
231
|
+
return this.getIsValid();
|
|
232
232
|
}
|
|
233
233
|
|
|
234
234
|
/**
|
|
@@ -131,7 +131,7 @@ export default class FilterModel extends BaseFilterModel implements IFilter {
|
|
|
131
131
|
* Inidiates if filter is valid
|
|
132
132
|
*/
|
|
133
133
|
get isValid(): boolean {
|
|
134
|
-
return this.attribute?.isValid
|
|
134
|
+
return this.attribute?.isValid ?? true;
|
|
135
135
|
}
|
|
136
136
|
|
|
137
137
|
/**
|
|
@@ -13,7 +13,7 @@ export default class RangeFilterModel extends FilterModel implements IFilter {
|
|
|
13
13
|
update(attribute: AttributeType, value: string) {
|
|
14
14
|
if (this.attribute instanceof CompositeAttributeModel) {
|
|
15
15
|
this.attribute.update(value, attribute);
|
|
16
|
-
} else if (this.attribute
|
|
16
|
+
} else if (this.attribute != null) {
|
|
17
17
|
this.attribute.update(value);
|
|
18
18
|
}
|
|
19
19
|
}
|
package/src/models/href/Href.js
CHANGED
|
@@ -322,7 +322,8 @@ class Href {
|
|
|
322
322
|
(param) =>
|
|
323
323
|
param.isModUIParameter &&
|
|
324
324
|
(!prefix || !param.prefix || param.prefix === prefix) &&
|
|
325
|
-
param.value != null
|
|
325
|
+
param.value != null &&
|
|
326
|
+
param.value !== "",
|
|
326
327
|
)
|
|
327
328
|
.map((param) => param.toQuerystring(false))
|
|
328
329
|
.join("&");
|
|
@@ -335,6 +336,15 @@ class Href {
|
|
|
335
336
|
return this.getQuerystring(false);
|
|
336
337
|
}
|
|
337
338
|
|
|
339
|
+
/**
|
|
340
|
+
* Retrieve all parameters from the parameter collection in a querystring style prefix~name1=value1&prefix~name2=value2, with the prefix
|
|
341
|
+
* The prefix is used to identify parameters per component on a grouping panel
|
|
342
|
+
* @returns {string}
|
|
343
|
+
*/
|
|
344
|
+
get publicQuerystring(): string {
|
|
345
|
+
return this.getQuerystring(true);
|
|
346
|
+
}
|
|
347
|
+
|
|
338
348
|
/**
|
|
339
349
|
* Set the path of the Href, the part before the querystring question mark
|
|
340
350
|
*/
|
|
@@ -412,6 +422,23 @@ class Href {
|
|
|
412
422
|
return this;
|
|
413
423
|
}
|
|
414
424
|
|
|
425
|
+
/**
|
|
426
|
+
*/
|
|
427
|
+
set formdata(formdata: any) {
|
|
428
|
+
const currentState = this.state ?? {};
|
|
429
|
+
|
|
430
|
+
this.state = {
|
|
431
|
+
...currentState,
|
|
432
|
+
formdata,
|
|
433
|
+
};
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
/**
|
|
437
|
+
*/
|
|
438
|
+
get formdata(): any {
|
|
439
|
+
return this.state?.formdata;
|
|
440
|
+
}
|
|
441
|
+
|
|
415
442
|
/**
|
|
416
443
|
* Set resourctype
|
|
417
444
|
*/
|
|
@@ -550,7 +577,8 @@ class Href {
|
|
|
550
577
|
toLocation(): LocationShape {
|
|
551
578
|
return {
|
|
552
579
|
pathname: this.path,
|
|
553
|
-
search:
|
|
580
|
+
search:
|
|
581
|
+
this.publicQuerystring.length > 0 ? `?${this.publicQuerystring}` : "",
|
|
554
582
|
hash: this.hash.length > 0 ? `#${this.hash}` : "",
|
|
555
583
|
state: {
|
|
556
584
|
origin: this.origin,
|
|
@@ -28,7 +28,7 @@ export default class ListHref extends Href {
|
|
|
28
28
|
this._isPrefixed = isPrefixed;
|
|
29
29
|
|
|
30
30
|
if (list != null) {
|
|
31
|
-
this.
|
|
31
|
+
this.setParametersFromListModel(list);
|
|
32
32
|
} else if (href != null && href instanceof ListHref) {
|
|
33
33
|
this.setParameterNamesFromHref(href);
|
|
34
34
|
}
|
|
@@ -47,7 +47,7 @@ export default class ListHref extends Href {
|
|
|
47
47
|
/**
|
|
48
48
|
* Retrieve parameter names and settings from List model
|
|
49
49
|
*/
|
|
50
|
-
|
|
50
|
+
setParametersFromListModel(list: ListModel) {
|
|
51
51
|
this._prefix = this._isPrefixed ? list.key : null;
|
|
52
52
|
|
|
53
53
|
this._pagingName = list.paging ? list.paging.name : "";
|
|
@@ -65,6 +65,8 @@ export default class ListHref extends Href {
|
|
|
65
65
|
this.sort = list.sorting && list.sorting.param ? list.sorting.param : null;
|
|
66
66
|
|
|
67
67
|
this.filterCollection = list.filterCollection;
|
|
68
|
+
|
|
69
|
+
this.formdata = list.formdata;
|
|
68
70
|
}
|
|
69
71
|
|
|
70
72
|
/**
|
|
@@ -448,7 +448,13 @@ export default class ListModel extends ResourceModel {
|
|
|
448
448
|
|
|
449
449
|
/**
|
|
450
450
|
*/
|
|
451
|
-
get formdata(): string {
|
|
452
|
-
|
|
451
|
+
get formdata(): string | null {
|
|
452
|
+
const { formdata } = this.filterCollection;
|
|
453
|
+
|
|
454
|
+
if (formdata != null) {
|
|
455
|
+
return JSON.stringify(formdata);
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
return null;
|
|
453
459
|
}
|
|
454
460
|
}
|
|
@@ -52,14 +52,14 @@ class Parameter {
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
// parameter has the structure prefix~name=value
|
|
55
|
-
const namePart = parameter.
|
|
56
|
-
const value = parameter.
|
|
55
|
+
const namePart = parameter.substring(0, parameter.indexOf("="));
|
|
56
|
+
const value = parameter.substring(parameter.indexOf("=") + 1);
|
|
57
57
|
|
|
58
58
|
let prefix;
|
|
59
|
-
let name = namePart;
|
|
60
|
-
if (
|
|
61
|
-
prefix =
|
|
62
|
-
name =
|
|
59
|
+
let name = decodeURIComponent(namePart);
|
|
60
|
+
if (name.includes(PARAMETER_SEPARATOR)) {
|
|
61
|
+
prefix = name.substring(0, name.indexOf("~"));
|
|
62
|
+
name = name.substring(name.indexOf("~") + 1);
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
if (name === "") {
|