@projectcaluma/ember-form 14.5.1 → 14.7.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.
@@ -1,9 +1,9 @@
1
1
  import { action } from "@ember/object";
2
2
  import { inject as service } from "@ember/service";
3
+ import { waitForFetch } from "@ember/test-waiters";
3
4
  import { macroCondition, isTesting } from "@embroider/macros";
4
5
  import Component from "@glimmer/component";
5
6
  import { queryManager } from "ember-apollo-client";
6
- import fetch from "fetch";
7
7
 
8
8
  import getFilesAnswerInfoQuery from "@projectcaluma/ember-form/gql/queries/filesanswer-info.graphql";
9
9
 
@@ -75,10 +75,12 @@ export default class CfFieldInputFilesComponent extends Component {
75
75
  }));
76
76
 
77
77
  const uploadFunction = async (file) => {
78
- const response = await fetch(file.uploadUrl, {
79
- method: "PUT",
80
- body: file.value,
81
- });
78
+ const response = await waitForFetch(
79
+ fetch(file.uploadUrl, {
80
+ method: "PUT",
81
+ body: file.value,
82
+ }),
83
+ );
82
84
  if (!response.ok) {
83
85
  throw new Error();
84
86
  }
@@ -55,12 +55,8 @@
55
55
  <p class="uk-text-meta uk-margin-small">
56
56
  {{t "caluma.form.error.details"}}
57
57
  </p>
58
- <pre
59
- class="uk-margin-remove"
60
- >
61
- {{~format-graphql-error
62
- this.save.last.error
63
- ~}}
58
+ <pre class="uk-margin-remove">
59
+ {{~format-graphql-error this.save.last.error~}}
64
60
  </pre>
65
61
  </div>
66
62
  {{/if}}
@@ -1,7 +1,7 @@
1
1
  {{#if @validateOnEnter}}
2
2
  <div {{in-viewport onEnter=this.validate}}>
3
- {{yield this.isValid this.validate}}
3
+ {{yield this.isValid this.validate this.isValidating}}
4
4
  </div>
5
5
  {{else}}
6
- {{yield this.isValid this.validate}}
6
+ {{yield this.isValid this.validate this.isValidating}}
7
7
  {{/if}}
@@ -39,6 +39,10 @@ export default class DocumentValidity extends Component {
39
39
  .every((f) => f.isValid);
40
40
  }
41
41
 
42
+ get isValidating() {
43
+ return this._validate.isRunning;
44
+ }
45
+
42
46
  @restartableTask
43
47
  *_validate() {
44
48
  const saveTasks = this.args.document.fields
@@ -52,9 +56,15 @@ export default class DocumentValidity extends Component {
52
56
  // itself are finished
53
57
  yield Promise.all(saveTasks);
54
58
 
55
- for (const field of this.args.document.fields) {
56
- yield field.validate.linked().perform();
57
- }
59
+ yield Promise.all(
60
+ this.args.document.fields.map(async (field) => {
61
+ await field.validate.linked().perform();
62
+
63
+ if (field.question.hasFormatValidators) {
64
+ await field.save.linked().perform();
65
+ }
66
+ }),
67
+ );
58
68
 
59
69
  if (this.isValid) {
60
70
  this.args.onValid?.();
@@ -15,12 +15,7 @@ fragment SimpleQuestion on Question {
15
15
  }
16
16
  placeholder
17
17
  formatValidators {
18
- edges {
19
- node {
20
- slug
21
- regex
22
- }
23
- }
18
+ totalCount
24
19
  }
25
20
  hintText
26
21
  }
@@ -33,12 +28,7 @@ fragment SimpleQuestion on Question {
33
28
  }
34
29
  placeholder
35
30
  formatValidators {
36
- edges {
37
- node {
38
- slug
39
- regex
40
- }
41
- }
31
+ totalCount
42
32
  }
43
33
  hintText
44
34
  }
@@ -50,6 +40,9 @@ fragment SimpleQuestion on Question {
50
40
  value
51
41
  }
52
42
  placeholder
43
+ formatValidators {
44
+ totalCount
45
+ }
53
46
  hintText
54
47
  }
55
48
  ... on FloatQuestion {
@@ -61,6 +54,9 @@ fragment SimpleQuestion on Question {
61
54
  value
62
55
  }
63
56
  placeholder
57
+ formatValidators {
58
+ totalCount
59
+ }
64
60
  hintText
65
61
  }
66
62
  ... on ChoiceQuestion {
@@ -79,6 +75,9 @@ fragment SimpleQuestion on Question {
79
75
  id
80
76
  value
81
77
  }
78
+ formatValidators {
79
+ totalCount
80
+ }
82
81
  hintText
83
82
  }
84
83
  ... on MultipleChoiceQuestion {
@@ -97,12 +96,21 @@ fragment SimpleQuestion on Question {
97
96
  id
98
97
  value
99
98
  }
99
+ formatValidators {
100
+ totalCount
101
+ }
100
102
  hintText
101
103
  }
102
104
  ... on DynamicChoiceQuestion {
105
+ formatValidators {
106
+ totalCount
107
+ }
103
108
  hintText
104
109
  }
105
110
  ... on DynamicMultipleChoiceQuestion {
111
+ formatValidators {
112
+ totalCount
113
+ }
106
114
  hintText
107
115
  }
108
116
  ... on DateQuestion {
@@ -110,6 +118,9 @@ fragment SimpleQuestion on Question {
110
118
  id
111
119
  value
112
120
  }
121
+ formatValidators {
122
+ totalCount
123
+ }
113
124
  hintText
114
125
  }
115
126
  ... on StaticQuestion {
@@ -120,6 +131,9 @@ fragment SimpleQuestion on Question {
120
131
  hintText
121
132
  }
122
133
  ... on FilesQuestion {
134
+ formatValidators {
135
+ totalCount
136
+ }
123
137
  hintText
124
138
  }
125
139
  ... on ActionButtonQuestion {
package/addon/lib/base.js CHANGED
@@ -2,6 +2,7 @@ import { setOwner } from "@ember/application";
2
2
  import { assert } from "@ember/debug";
3
3
  import { registerDestructor } from "@ember/destroyable";
4
4
  import { inject as service } from "@ember/service";
5
+ import { cached } from "tracked-toolbox";
5
6
 
6
7
  export default class Base {
7
8
  @service calumaStore;
@@ -18,8 +19,8 @@ export default class Base {
18
19
  }
19
20
 
20
21
  registerDestructor(this, () => {
21
- if (this.pk) {
22
- this.calumaStore.delete(this.pk);
22
+ if (this.storeKey) {
23
+ this.calumaStore.delete(this.storeKey);
23
24
  }
24
25
  });
25
26
  }
@@ -31,13 +32,34 @@ export default class Base {
31
32
  */
32
33
  raw = {};
33
34
 
35
+ /**
36
+ * The primary key of the lib class.
37
+ * Must be overridden in subclasses.
38
+ *
39
+ * @property {String} pk
40
+ */
41
+ @cached
42
+ get pk() {
43
+ throw new Error("pk getter must be implemented in subclass");
44
+ }
45
+
46
+ /**
47
+ * The caluma store key of the answer.
48
+ *
49
+ * @property {String} storeKey
50
+ */
51
+ @cached
52
+ get storeKey() {
53
+ return this.pk;
54
+ }
55
+
34
56
  /**
35
57
  * Push the object into the caluma store
36
58
  *
37
59
  * @method pushIntoStore
38
60
  */
39
61
  pushIntoStore() {
40
- if (this.pk) {
62
+ if (this.storeKey) {
41
63
  this.calumaStore.push(this);
42
64
  }
43
65
  }
@@ -177,6 +177,17 @@ export default class Field extends Base {
177
177
  return `${this.document.pk}:Question:${this.raw.question.slug}`;
178
178
  }
179
179
 
180
+ /**
181
+ * The caluma store key of the field.
182
+ * The form primary key is added for re-used fields in different forms.
183
+ *
184
+ * @property {String} storeKey
185
+ */
186
+ @cached
187
+ get storeKey() {
188
+ return `${this.fieldset.storeKey}:Question:${this.raw.question.slug}`;
189
+ }
190
+
180
191
  /**
181
192
  * The element ID used by the label component.
182
193
  *
@@ -52,9 +52,7 @@ export default class Fieldset extends Base {
52
52
  const fields = this.raw.form.questions.map((question) => {
53
53
  return associateDestroyableChild(
54
54
  this,
55
- this.calumaStore.find(
56
- `${this.document.pk}:Question:${question.slug}`,
57
- ) ||
55
+ this.calumaStore.find(`${this.pk}:Question:${question.slug}`) ||
58
56
  new (owner.factoryFor("caluma-model:field").class)({
59
57
  raw: {
60
58
  question,
@@ -192,4 +192,8 @@ export default class Question extends Base {
192
192
  ].includes(this.raw.__typename))
193
193
  );
194
194
  }
195
+
196
+ get hasFormatValidators() {
197
+ return (this.raw.formatValidators?.totalCount ?? 0) > 0;
198
+ }
195
199
  }
@@ -13,14 +13,14 @@ export default class CalumaStoreService extends Service {
13
13
  push(obj) {
14
14
  assert(
15
15
  `Object must have an \`pk\` in order to be pushed into the store`,
16
- obj.pk,
16
+ obj.storeKey,
17
17
  );
18
18
 
19
- const existing = this._store.get(obj.pk);
19
+ const existing = this._store.get(obj.storeKey);
20
20
 
21
21
  if (existing) {
22
22
  debug(
23
- `Object with the pk \`${obj.pk}\` already exists in the store. It will be updated.`,
23
+ `Object with the storeKey \`${obj.storeKey}\` already exists in the store. It will be updated.`,
24
24
  );
25
25
 
26
26
  set(existing, "raw", obj.raw);
@@ -28,17 +28,17 @@ export default class CalumaStoreService extends Service {
28
28
  return existing;
29
29
  }
30
30
 
31
- this._store.set(obj.pk, obj);
31
+ this._store.set(obj.storeKey, obj);
32
32
 
33
33
  return obj;
34
34
  }
35
35
 
36
- find(pk) {
37
- return this._store.get(pk) || null;
36
+ find(storeKey) {
37
+ return this._store.get(storeKey) || null;
38
38
  }
39
39
 
40
- delete(pk) {
41
- this._store.delete(pk);
40
+ delete(storeKey) {
41
+ this._store.delete(storeKey);
42
42
  }
43
43
 
44
44
  clear() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@projectcaluma/ember-form",
3
- "version": "14.5.1",
3
+ "version": "14.7.0",
4
4
  "description": "Ember addon for rendering Caluma forms.",
5
5
  "keywords": [
6
6
  "ember-addon"
@@ -11,10 +11,9 @@
11
11
  "dependencies": {
12
12
  "@babel/core": "^7.26.0",
13
13
  "@ember/string": "^3.1.1 || ^4.0.0",
14
+ "@ember/test-waiters": "^4.1.1",
14
15
  "@embroider/macros": "^1.16.10",
15
16
  "@embroider/util": "^1.13.2",
16
- "@glimmer/component": "^1.1.2",
17
- "@glimmer/tracking": "^1.1.2",
18
17
  "ember-apollo-client": "^5.0.0",
19
18
  "ember-auto-import": "^2.10.0",
20
19
  "ember-autoresize-modifier": "^0.7.0 || ^0.8.0",
@@ -24,7 +23,6 @@
24
23
  "ember-cli-showdown": "^9.0.1",
25
24
  "ember-composable-helpers": "^5.0.0",
26
25
  "ember-concurrency": "^4.0.2",
27
- "ember-fetch": "^8.1.2",
28
26
  "ember-flatpickr": "^8.0.1",
29
27
  "ember-in-viewport": "^4.1.0",
30
28
  "ember-intl": "^7.1.1",
@@ -41,13 +39,15 @@
41
39
  "luxon": "^3.5.0",
42
40
  "reactiveweb": "^1.3.0",
43
41
  "tracked-toolbox": "^2.0.0",
44
- "@projectcaluma/ember-core": "^14.5.1"
42
+ "@projectcaluma/ember-core": "^14.7.0"
45
43
  },
46
44
  "devDependencies": {
47
- "@ember/optional-features": "2.2.0",
45
+ "@ember/optional-features": "2.3.0",
48
46
  "@ember/test-helpers": "4.0.4",
49
47
  "@embroider/test-setup": "4.0.0",
50
- "@faker-js/faker": "10.0.0",
48
+ "@faker-js/faker": "10.2.0",
49
+ "@glimmer/component": "1.1.2",
50
+ "@glimmer/tracking": "1.1.2",
51
51
  "broccoli-asset-rev": "3.0.0",
52
52
  "ember-cli": "6.1.0",
53
53
  "ember-cli-clean-css": "3.0.0",
@@ -61,23 +61,25 @@
61
61
  "ember-load-initializers": "3.0.1",
62
62
  "ember-qunit": "9.0.4",
63
63
  "ember-resolver": "13.1.1",
64
+ "ember-sinon-qunit": "7.5.0",
64
65
  "ember-source": "6.1.0",
65
66
  "ember-source-channel-url": "3.0.0",
66
67
  "ember-try": "4.0.0",
67
68
  "loader.js": "4.7.0",
68
69
  "miragejs": "0.1.48",
69
- "qunit": "2.24.1",
70
+ "qunit": "2.25.0",
70
71
  "qunit-dom": "3.5.0",
71
- "sass": "1.93.2",
72
- "uikit": "3.23.13",
72
+ "sass": "1.97.3",
73
+ "sinon": "21.0.1",
74
+ "uikit": "3.25.6",
73
75
  "uuid": "13.0.0",
74
- "webpack": "5.101.3",
75
- "@projectcaluma/ember-testing": "14.5.1",
76
- "@projectcaluma/ember-workflow": "14.5.1"
76
+ "webpack": "5.104.1",
77
+ "@projectcaluma/ember-testing": "14.7.0",
78
+ "@projectcaluma/ember-workflow": "14.7.0"
77
79
  },
78
80
  "peerDependencies": {
79
81
  "ember-source": ">= 4.0.0",
80
- "@projectcaluma/ember-workflow": "^14.5.1"
82
+ "@projectcaluma/ember-workflow": "^14.7.0"
81
83
  },
82
84
  "dependenciesMeta": {
83
85
  "@projectcaluma/ember-core": {