@beinformed/ui 1.27.0 → 1.27.2

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.
Files changed (54) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/esm/models/attributes/AttributeDataHelper.js +2 -2
  3. package/esm/models/attributes/AttributeDataHelper.js.map +1 -1
  4. package/esm/models/attributes/CaptchaAttributeModel.js +19 -0
  5. package/esm/models/attributes/CaptchaAttributeModel.js.map +1 -1
  6. package/esm/models/attributes/_createAttribute.js +2 -2
  7. package/esm/models/attributes/_createAttribute.js.map +1 -1
  8. package/esm/models/base/BaseCollection.js +3 -9
  9. package/esm/models/base/BaseCollection.js.map +1 -1
  10. package/esm/models/base/BaseModel.js +2 -8
  11. package/esm/models/base/BaseModel.js.map +1 -1
  12. package/esm/modularui/CaptchaRequest.js +25 -8
  13. package/esm/modularui/CaptchaRequest.js.map +1 -1
  14. package/esm/redux/actions/FormValidations.js +1 -1
  15. package/esm/redux/actions/FormValidations.js.map +1 -1
  16. package/lib/models/attributes/AttributeDataHelper.js +2 -2
  17. package/lib/models/attributes/AttributeDataHelper.js.flow +2 -2
  18. package/lib/models/attributes/AttributeDataHelper.js.map +1 -1
  19. package/lib/models/attributes/CaptchaAttributeModel.js +19 -0
  20. package/lib/models/attributes/CaptchaAttributeModel.js.flow +16 -0
  21. package/lib/models/attributes/CaptchaAttributeModel.js.map +1 -1
  22. package/lib/models/attributes/__tests__/ChoiceAttributeModel.spec.js.flow +3 -0
  23. package/lib/models/attributes/__tests__/CompositeAttributeModel.spec.js.flow +3 -0
  24. package/lib/models/attributes/_createAttribute.js +2 -2
  25. package/lib/models/attributes/_createAttribute.js.flow +2 -2
  26. package/lib/models/attributes/_createAttribute.js.map +1 -1
  27. package/lib/models/base/BaseCollection.js +3 -9
  28. package/lib/models/base/BaseCollection.js.flow +4 -10
  29. package/lib/models/base/BaseCollection.js.map +1 -1
  30. package/lib/models/base/BaseModel.js +2 -8
  31. package/lib/models/base/BaseModel.js.flow +3 -9
  32. package/lib/models/base/BaseModel.js.map +1 -1
  33. package/lib/models/base/__tests__/BaseModel.spec.js.flow +3 -7
  34. package/lib/modularui/CaptchaRequest.js +25 -8
  35. package/lib/modularui/CaptchaRequest.js.flow +51 -10
  36. package/lib/modularui/CaptchaRequest.js.map +1 -1
  37. package/lib/redux/actions/FormValidations.js +1 -1
  38. package/lib/redux/actions/FormValidations.js.flow +1 -1
  39. package/lib/redux/actions/FormValidations.js.map +1 -1
  40. package/package.json +13 -12
  41. package/src/models/attributes/AttributeDataHelper.js +2 -2
  42. package/src/models/attributes/CaptchaAttributeModel.js +16 -0
  43. package/src/models/attributes/__tests__/ChoiceAttributeModel.spec.js +3 -0
  44. package/src/models/attributes/__tests__/CompositeAttributeModel.spec.js +3 -0
  45. package/src/models/attributes/_createAttribute.js +2 -2
  46. package/src/models/base/BaseCollection.js +4 -10
  47. package/src/models/base/BaseModel.js +3 -9
  48. package/src/models/base/__tests__/BaseModel.spec.js +3 -7
  49. package/src/modularui/CaptchaRequest.js +51 -10
  50. package/src/redux/actions/FormValidations.js +1 -1
  51. package/types/models/attributes/CaptchaAttributeModel.d.ts +9 -0
  52. package/types/models/base/BaseCollection.d.ts +2 -2
  53. package/types/models/base/BaseModel.d.ts +1 -1
  54. package/types/modularui/CaptchaRequest.d.ts +29 -1
@@ -1,5 +1,5 @@
1
1
  // @flow
2
- import cloneDeep from "lodash/cloneDeep";
2
+ import { klona } from "klona/full";
3
3
  import pick from "lodash/pick";
4
4
 
5
5
  import { has, isPlainObject } from "../../utils/helpers/objects";
@@ -33,7 +33,7 @@ class AttributeDataHelper {
33
33
  ) || {};
34
34
  this._value = this.getValue(this._attribute);
35
35
  } else {
36
- const attributeData = cloneDeep(data);
36
+ const attributeData = klona(data);
37
37
  attributeData._links = pick(data._links, [
38
38
  "concept",
39
39
  "download",
@@ -5,6 +5,8 @@ import AttributeModel from "./AttributeModel";
5
5
  * Password attribute
6
6
  */
7
7
  export default class CaptchaAttributeModel extends AttributeModel {
8
+ _answer: string = "";
9
+
8
10
  /**
9
11
  */
10
12
  static isApplicableModel(contributions: Object): boolean {
@@ -27,6 +29,20 @@ export default class CaptchaAttributeModel extends AttributeModel {
27
29
  return this;
28
30
  }
29
31
 
32
+ /**
33
+ */
34
+ setAnswer(answer: string) {
35
+ this._answer = answer;
36
+ }
37
+
38
+ /**
39
+ * Retrieve the given answer for the captcha
40
+ * The value of this attribute is the token id of the captcha
41
+ */
42
+ getAnswer(): string {
43
+ return this._answer;
44
+ }
45
+
30
46
  /**
31
47
  */
32
48
  get hasDynamicValidationData(): boolean {
@@ -130,6 +130,9 @@ describe("choiceAttributeModel", () => {
130
130
  expect(attribute.format).toBeNull();
131
131
 
132
132
  expect(attribute.options).toHaveLength(4);
133
+
134
+ const clonedAttribute = attribute.clone();
135
+ expect(clonedAttribute).toStrictEqual(attribute);
133
136
  });
134
137
 
135
138
  it("handles sort-options hint", () => {
@@ -202,6 +202,9 @@ describe("compositeAttributeModel", () => {
202
202
  PrintingHouse: "Printers united",
203
203
  Title: "Matilda",
204
204
  });
205
+
206
+ const clonedAttribute = attribute.clone();
207
+ expect(clonedAttribute).toStrictEqual(attribute);
205
208
  });
206
209
 
207
210
  it("creates a composite attribute for a choice attribute with a table codemap on a list, multiple choice", () => {
@@ -1,5 +1,5 @@
1
1
  // @flow
2
- import cloneDeep from "lodash/cloneDeep";
2
+ import { klona } from "klona/full";
3
3
 
4
4
  import { has, isPlainObject } from "../../utils/helpers/objects";
5
5
 
@@ -105,7 +105,7 @@ const updateData = (
105
105
  data: Object,
106
106
  contributions: Object
107
107
  ): Object => {
108
- const newData = cloneDeep(data);
108
+ const newData = klona(data);
109
109
 
110
110
  if (contributions.dynamicschemaId) {
111
111
  newData.dynamicschemaId = contributions.dynamicschemaId;
@@ -1,6 +1,5 @@
1
1
  // @flow
2
- import clone from "lodash/clone";
3
- import cloneDeep from "lodash/cloneDeep";
2
+ import { klona } from "klona/full";
4
3
 
5
4
  /**
6
5
  * Base class for collections of models
@@ -182,15 +181,10 @@ class BaseCollection<T> {
182
181
  }
183
182
 
184
183
  /**
185
- * Returns a clone of the model (this is not a deep copy)
184
+ * Returns a clone of the model
186
185
  */
187
- clone(deepcopy: boolean = false): this {
188
- // deepcopy can be expensive, use with care!
189
- if (deepcopy) {
190
- return cloneDeep(this);
191
- }
192
-
193
- return clone(this);
186
+ clone(): this {
187
+ return klona(this);
194
188
  }
195
189
  }
196
190
 
@@ -1,6 +1,5 @@
1
1
  // @flow
2
- import clone from "lodash/clone";
3
- import cloneDeep from "lodash/cloneDeep";
2
+ import { klona } from "klona/full";
4
3
 
5
4
  import LayoutHintCollection from "../layouthint/LayoutHintCollection";
6
5
 
@@ -118,13 +117,8 @@ class BaseModel {
118
117
  /**
119
118
  * Returns a clone of the model
120
119
  */
121
- clone(deepcopy: boolean = false): any {
122
- // deepcopy can be expensive, use with care!
123
- if (deepcopy) {
124
- return cloneDeep(this);
125
- }
126
-
127
- return clone(this);
120
+ clone(): any {
121
+ return klona(this);
128
122
  }
129
123
  }
130
124
 
@@ -11,7 +11,8 @@ describe("baseModel", () => {
11
11
  expect(model.contributions).toStrictEqual({});
12
12
  expect(model.hasData).toBeFalsy();
13
13
 
14
- expect(model.clone()).toStrictEqual(model);
14
+ const clonedModel = model.clone();
15
+ expect(clonedModel).toStrictEqual(model);
15
16
  });
16
17
 
17
18
  it("should handle data without contributions", () => {
@@ -72,12 +73,7 @@ describe("baseModel", () => {
72
73
  },
73
74
  });
74
75
 
75
- const shallowClone = model.clone();
76
- expect(model).not.toBe(shallowClone);
77
- expect(model.data.prop).toBe(shallowClone.data.prop);
78
- expect(model.data.prop.child).toBe(shallowClone.data.prop.child);
79
-
80
- const deepClone = model.clone(true);
76
+ const deepClone = model.clone();
81
77
  expect(model).not.toBe(deepClone);
82
78
  expect(model.data.prop === deepClone.data.prop).toBeFalsy();
83
79
  expect(model.data.prop.child).toBe(deepClone.data.prop.child);
@@ -2,30 +2,65 @@
2
2
  import xhr from "../utils/fetch/xhr";
3
3
  import { getCaptchaPath, HTTP_METHODS } from "../constants";
4
4
 
5
+ type CaptchaInitialResponse = {
6
+ tokenId: string,
7
+ image: string,
8
+ };
9
+
10
+ type CaptchaValidResponse = {
11
+ valid: boolean,
12
+ };
13
+
14
+ type CaptchaInvalidResponse = {
15
+ tokenId: string,
16
+ image: string,
17
+ valid: boolean,
18
+ error: { id: string },
19
+ };
20
+
5
21
  type CaptchaResponse = {
6
22
  tokenId: string,
7
- image: any,
23
+ image: string,
8
24
  valid: boolean,
25
+ error: { id: string } | null,
9
26
  };
10
27
 
11
28
  /**
12
29
  */
13
30
  class CaptchaRequest {
14
31
  _tokenId: string;
32
+ _image: string;
15
33
 
16
34
  /**
17
35
  */
36
+ captchaResponse(
37
+ response:
38
+ | CaptchaInitialResponse
39
+ | CaptchaValidResponse
40
+ | CaptchaInvalidResponse
41
+ ): CaptchaResponse {
42
+ this._tokenId = response.tokenId ?? this._tokenId;
43
+ this._image = response.image ?? this._image;
44
+
45
+ return {
46
+ tokenId: this._tokenId,
47
+ image: this._image,
48
+ valid: response.valid ?? false,
49
+ error: response.error ?? null,
50
+ };
51
+ }
52
+
53
+ /**
54
+ * Initiate the captcha request
55
+ */
18
56
  init(): Promise<CaptchaResponse> {
19
57
  return xhr({
20
58
  url: getCaptchaPath(),
21
- }).then((response) => {
22
- this._tokenId = response.tokenId;
23
-
24
- return response;
25
- });
59
+ }).then((response) => this.captchaResponse(response));
26
60
  }
27
61
 
28
62
  /**
63
+ * Answer the captcha
29
64
  */
30
65
  send(answer?: string): Promise<CaptchaResponse> {
31
66
  return xhr({
@@ -35,10 +70,16 @@ class CaptchaRequest {
35
70
  tokenId: this._tokenId ?? "",
36
71
  answer: answer ?? "",
37
72
  },
38
- }).catch((error) => {
39
- this._tokenId = error.response.tokenId;
40
- return error.response;
41
- });
73
+ })
74
+ .then((response) => this.captchaResponse(response))
75
+ .catch((error) => this.captchaResponse(error.response));
76
+ }
77
+
78
+ /**
79
+ * Reset the captcha and receive a new token and image
80
+ */
81
+ refresh(): Promise<CaptchaResponse> {
82
+ return this.init();
42
83
  }
43
84
  }
44
85
 
@@ -25,7 +25,7 @@ const updateValidations =
25
25
  const currentForm = getState().modularui[form.connectKey];
26
26
 
27
27
  if (currentForm) {
28
- const validatedForm = currentForm.model.clone(true);
28
+ const validatedForm = currentForm.model.clone();
29
29
  if (validatedForm instanceof FormModel) {
30
30
  validatedForm.updateValidations(formWithValidations.data);
31
31
  }
@@ -2,9 +2,18 @@
2
2
  * Password attribute
3
3
  */
4
4
  export default class CaptchaAttributeModel extends AttributeModel {
5
+ _answer: string;
5
6
  /**
6
7
  * Update the attribute by name and value
7
8
  */
8
9
  update(value: string): this;
10
+ /**
11
+ */
12
+ setAnswer(answer: string): void;
13
+ /**
14
+ * Retrieve the given answer for the captcha
15
+ * The value of this attribute is the token id of the captcha
16
+ */
17
+ getAnswer(): string;
9
18
  }
10
19
  import AttributeModel from "./AttributeModel";
@@ -83,7 +83,7 @@ declare class BaseCollection<T> {
83
83
  */
84
84
  get sorted(): T[];
85
85
  /**
86
- * Returns a clone of the model (this is not a deep copy)
86
+ * Returns a clone of the model
87
87
  */
88
- clone(deepcopy?: boolean): this;
88
+ clone(): this;
89
89
  }
@@ -62,6 +62,6 @@ declare class BaseModel {
62
62
  /**
63
63
  * Returns a clone of the model
64
64
  */
65
- clone(deepcopy?: boolean): any;
65
+ clone(): any;
66
66
  }
67
67
  import LayoutHintCollection from "../layouthint/LayoutHintCollection";
@@ -3,15 +3,43 @@ export default CaptchaRequest;
3
3
  */
4
4
  declare class CaptchaRequest {
5
5
  _tokenId: string;
6
+ _image: string;
6
7
  /**
7
8
  */
9
+ captchaResponse(response: CaptchaInitialResponse | CaptchaValidResponse | CaptchaInvalidResponse): CaptchaResponse;
10
+ /**
11
+ * Initiate the captcha request
12
+ */
8
13
  init(): Promise<CaptchaResponse>;
9
14
  /**
15
+ * Answer the captcha
10
16
  */
11
17
  send(answer?: string): Promise<CaptchaResponse>;
18
+ /**
19
+ * Reset the captcha and receive a new token and image
20
+ */
21
+ refresh(): Promise<CaptchaResponse>;
12
22
  }
23
+ type CaptchaInitialResponse = {
24
+ tokenId: string;
25
+ image: string;
26
+ };
27
+ type CaptchaValidResponse = {
28
+ valid: boolean;
29
+ };
30
+ type CaptchaInvalidResponse = {
31
+ tokenId: string;
32
+ image: string;
33
+ valid: boolean;
34
+ error: {
35
+ id: string;
36
+ };
37
+ };
13
38
  type CaptchaResponse = {
14
39
  tokenId: string;
15
- image: any;
40
+ image: string;
16
41
  valid: boolean;
42
+ error: {
43
+ id: string;
44
+ };
17
45
  };