@projectcaluma/ember-form 10.0.3 → 11.0.0-beta.4
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +1119 -0
- package/addon/components/cf-content.hbs +36 -39
- package/addon/components/cf-content.js +46 -27
- package/addon/components/cf-field/info.hbs +2 -2
- package/addon/components/cf-field/info.js +0 -15
- package/addon/components/cf-field/input/action-button.hbs +1 -1
- package/addon/components/cf-field/input/action-button.js +9 -7
- package/addon/components/cf-field/input/checkbox.hbs +6 -2
- package/addon/components/cf-field/input/checkbox.js +9 -29
- package/addon/components/cf-field/input/file.hbs +1 -1
- package/addon/components/cf-field/input/file.js +7 -8
- package/addon/components/cf-field/input/float.hbs +2 -2
- package/addon/components/cf-field/input/integer.hbs +3 -3
- package/addon/components/cf-field/input/radio.hbs +4 -1
- package/addon/components/cf-field/input/table.hbs +7 -8
- package/addon/components/cf-field/input/table.js +12 -10
- package/addon/components/cf-field/input/text.hbs +3 -3
- package/addon/components/cf-field/input/textarea.hbs +4 -3
- package/addon/components/cf-field/input.hbs +10 -1
- package/addon/components/cf-field/input.js +1 -1
- package/addon/components/cf-field/label.hbs +1 -1
- package/addon/components/cf-field-value.hbs +1 -1
- package/addon/components/cf-field-value.js +7 -12
- package/addon/components/cf-field.hbs +2 -2
- package/addon/components/cf-field.js +2 -3
- package/addon/components/cf-navigation.hbs +4 -1
- package/addon/components/document-validity.js +1 -1
- package/addon/helpers/get-widget.js +50 -0
- package/addon/lib/answer.js +108 -72
- package/addon/lib/base.js +32 -23
- package/addon/lib/dependencies.js +36 -71
- package/addon/lib/document.js +92 -96
- package/addon/lib/field.js +333 -400
- package/addon/lib/fieldset.js +46 -47
- package/addon/lib/form.js +27 -15
- package/addon/lib/navigation.js +211 -192
- package/addon/lib/question.js +102 -93
- package/addon/services/caluma-store.js +10 -6
- package/app/helpers/get-widget.js +4 -0
- package/blueprints/@projectcaluma/ember-form/index.js +1 -0
- package/package.json +24 -20
- package/addon/components/cf-navigation.js +0 -9
package/addon/lib/document.js
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
import { getOwner } from "@ember/application";
|
2
2
|
import { assert } from "@ember/debug";
|
3
|
-
import {
|
4
|
-
import { inject as service } from "@ember/service";
|
3
|
+
import { associateDestroyableChild } from "@ember/destroyable";
|
5
4
|
import jexl from "jexl";
|
5
|
+
import { cached } from "tracked-toolbox";
|
6
6
|
|
7
7
|
import { decodeId } from "@projectcaluma/ember-core/helpers/decode-id";
|
8
8
|
import { intersects, mapby } from "@projectcaluma/ember-core/utils/jexl";
|
@@ -17,124 +17,123 @@ const sum = (nums) => nums.reduce((num, base) => base + num, 0);
|
|
17
17
|
*
|
18
18
|
* @class Document
|
19
19
|
*/
|
20
|
-
export default Base
|
21
|
-
|
22
|
-
|
23
|
-
init(...args) {
|
20
|
+
export default class Document extends Base {
|
21
|
+
constructor({ raw, parentDocument, ...args }) {
|
24
22
|
assert(
|
25
23
|
"A graphql document `raw` must be passed",
|
26
|
-
|
24
|
+
raw?.__typename === "Document"
|
27
25
|
);
|
28
26
|
|
29
|
-
|
30
|
-
writable: false,
|
31
|
-
value: `Document:${decodeId(this.raw.id)}`,
|
32
|
-
});
|
27
|
+
super({ raw, ...args });
|
33
28
|
|
34
|
-
this.
|
29
|
+
this.parentDocument = parentDocument;
|
35
30
|
|
36
|
-
this.
|
31
|
+
this.pushIntoStore();
|
37
32
|
|
38
33
|
this._createRootForm();
|
39
34
|
this._createFieldsets();
|
40
|
-
}
|
35
|
+
}
|
41
36
|
|
42
37
|
_createRootForm() {
|
43
|
-
const
|
44
|
-
this.calumaStore.find(`Form:${this.raw.rootForm.slug}`) ||
|
45
|
-
getOwner(this)
|
46
|
-
.factoryFor("caluma-model:form")
|
47
|
-
.create({ raw: this.raw.rootForm });
|
38
|
+
const owner = getOwner(this);
|
48
39
|
|
49
|
-
this.
|
50
|
-
|
40
|
+
this.rootForm =
|
41
|
+
this.calumaStore.find(`Form:${this.raw.rootForm.slug}`) ||
|
42
|
+
new (owner.factoryFor("caluma-model:form").class)({
|
43
|
+
raw: this.raw.rootForm,
|
44
|
+
owner,
|
45
|
+
});
|
46
|
+
}
|
51
47
|
|
52
48
|
_createFieldsets() {
|
53
|
-
const
|
54
|
-
|
49
|
+
const owner = getOwner(this);
|
50
|
+
|
51
|
+
this.fieldsets = this.raw.forms.map((form) => {
|
52
|
+
return associateDestroyableChild(
|
53
|
+
this,
|
55
54
|
this.calumaStore.find(`${this.pk}:Form:${form.slug}`) ||
|
56
|
-
|
57
|
-
.factoryFor("caluma-model:fieldset")
|
58
|
-
.create({
|
55
|
+
new (owner.factoryFor("caluma-model:fieldset").class)({
|
59
56
|
raw: { form, answers: this.raw.answers },
|
60
57
|
document: this,
|
58
|
+
owner,
|
61
59
|
})
|
62
60
|
);
|
63
61
|
});
|
64
|
-
|
65
|
-
this.set("fieldsets", fieldsets);
|
66
|
-
},
|
67
|
-
|
68
|
-
willDestroy(...args) {
|
69
|
-
this._super(...args);
|
70
|
-
|
71
|
-
const fieldsets = this.fieldsets;
|
72
|
-
this.set("fieldsets", []);
|
73
|
-
fieldsets.forEach((fieldset) => fieldset.destroy());
|
74
|
-
},
|
62
|
+
}
|
75
63
|
|
76
64
|
/**
|
77
|
-
* The
|
65
|
+
* The parent document of this document. If this is set, the document is most
|
66
|
+
* likely a table row.
|
78
67
|
*
|
79
|
-
* @property {
|
80
|
-
* @accessor
|
68
|
+
* @property {Document} parentDocument
|
81
69
|
*/
|
82
|
-
|
83
|
-
return decodeId(this.raw.id);
|
84
|
-
}),
|
85
|
-
|
86
|
-
workItemUuid: computed(
|
87
|
-
"raw.{workItem.id,case.workItems.edges.[]}",
|
88
|
-
function () {
|
89
|
-
// The document is either directly attached to a work item (via
|
90
|
-
// CompleteTaskFormTask) or it's the case document and therefore
|
91
|
-
// indirectly attached to a work item (via CompleteWorkflowFormTask)
|
92
|
-
const rawId =
|
93
|
-
this.raw.workItem?.id ||
|
94
|
-
this.raw.case?.workItems.edges.find(
|
95
|
-
(edge) => edge.node.task.__typename === "CompleteWorkflowFormTask"
|
96
|
-
)?.node.id;
|
97
|
-
|
98
|
-
return rawId ? decodeId(rawId) : null;
|
99
|
-
}
|
100
|
-
),
|
70
|
+
parentDocument = null;
|
101
71
|
|
102
72
|
/**
|
103
73
|
* The root form of this document
|
104
74
|
*
|
105
75
|
* @property {Form} rootForm
|
106
|
-
* @accessor
|
107
76
|
*/
|
108
|
-
rootForm
|
77
|
+
rootForm = null;
|
109
78
|
|
110
79
|
/**
|
111
80
|
* The fieldsets of this document
|
112
81
|
*
|
113
82
|
* @property {Fieldset[]} fieldsets
|
114
|
-
* @accessor
|
115
83
|
*/
|
116
|
-
fieldsets
|
84
|
+
fieldsets = [];
|
85
|
+
|
86
|
+
/**
|
87
|
+
* The primary key of the document.
|
88
|
+
*
|
89
|
+
* @property {String} pk
|
90
|
+
*/
|
91
|
+
@cached
|
92
|
+
get pk() {
|
93
|
+
return `Document:${this.uuid}`;
|
94
|
+
}
|
95
|
+
|
96
|
+
/**
|
97
|
+
* The uuid of the document
|
98
|
+
*
|
99
|
+
* @property {String} uuid
|
100
|
+
*/
|
101
|
+
@cached
|
102
|
+
get uuid() {
|
103
|
+
return decodeId(this.raw.id);
|
104
|
+
}
|
105
|
+
|
106
|
+
@cached
|
107
|
+
get workItemUuid() {
|
108
|
+
// The document is either directly attached to a work item (via
|
109
|
+
// CompleteTaskFormTask) or it's the case document and therefore
|
110
|
+
// indirectly attached to a work item (via CompleteWorkflowFormTask)
|
111
|
+
const rawId =
|
112
|
+
this.raw.workItem?.id ||
|
113
|
+
this.raw.case?.workItems.edges.find(
|
114
|
+
(edge) => edge.node.task.__typename === "CompleteWorkflowFormTask"
|
115
|
+
)?.node.id;
|
116
|
+
|
117
|
+
return rawId ? decodeId(rawId) : null;
|
118
|
+
}
|
117
119
|
|
118
120
|
/**
|
119
121
|
* All fields of all fieldsets of this document
|
120
122
|
*
|
121
123
|
* @property {Field[]} fields
|
122
|
-
* @accessor
|
123
124
|
*/
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
);
|
129
|
-
}),
|
125
|
+
@cached
|
126
|
+
get fields() {
|
127
|
+
return this.fieldsets.flatMap((fieldset) => fieldset.fields);
|
128
|
+
}
|
130
129
|
|
131
130
|
/**
|
132
131
|
* The JEXL object for evaluating jexl expressions on this document
|
133
132
|
*
|
134
133
|
* @property {JEXL} jexl
|
135
|
-
* @accessor
|
136
134
|
*/
|
137
|
-
|
135
|
+
@cached
|
136
|
+
get jexl() {
|
138
137
|
const documentJexl = new jexl.Jexl();
|
139
138
|
|
140
139
|
documentJexl.addTransform("answer", (slug, defaultValue) =>
|
@@ -174,31 +173,29 @@ export default Base.extend({
|
|
174
173
|
documentJexl.addTransform("stringify", (input) => JSON.stringify(input));
|
175
174
|
|
176
175
|
return documentJexl;
|
177
|
-
}
|
176
|
+
}
|
178
177
|
|
179
178
|
/**
|
180
179
|
* The JEXL context object for passing to the evaluation of jexl expessions
|
181
180
|
*
|
182
181
|
* @property {Object} jexlContext
|
183
|
-
* @accessor
|
184
182
|
*/
|
185
|
-
jexlContext
|
186
|
-
|
187
|
-
|
188
|
-
function () {
|
189
|
-
if (this.parentDocument) return this.parentDocument.jexlContext;
|
190
|
-
|
191
|
-
return {
|
183
|
+
get jexlContext() {
|
184
|
+
return (
|
185
|
+
this.parentDocument?.jexlContext ?? {
|
192
186
|
// JEXL interprets null in an expression as variable instead of a
|
193
187
|
// primitive. This resolves that issue.
|
194
188
|
null: null,
|
195
189
|
form: this.rootForm.slug,
|
196
190
|
info: {
|
197
|
-
root: {
|
191
|
+
root: {
|
192
|
+
form: this.rootForm.slug,
|
193
|
+
formMeta: this.rootForm.raw.meta,
|
194
|
+
},
|
198
195
|
},
|
199
|
-
}
|
200
|
-
|
201
|
-
|
196
|
+
}
|
197
|
+
);
|
198
|
+
}
|
202
199
|
|
203
200
|
/**
|
204
201
|
* Object representation of a document. The question slug as key and the
|
@@ -215,9 +212,9 @@ export default Base.extend({
|
|
215
212
|
* answer.
|
216
213
|
*
|
217
214
|
* @property {Object} flatAnswerMap
|
218
|
-
* @accessor
|
219
215
|
*/
|
220
|
-
|
216
|
+
@cached
|
217
|
+
get flatAnswerMap() {
|
221
218
|
return this.fields.reduce(
|
222
219
|
(answerMap, field) => ({
|
223
220
|
...answerMap,
|
@@ -225,7 +222,7 @@ export default Base.extend({
|
|
225
222
|
}),
|
226
223
|
{}
|
227
224
|
);
|
228
|
-
}
|
225
|
+
}
|
229
226
|
|
230
227
|
/**
|
231
228
|
* Find an answer for a given question slug
|
@@ -249,7 +246,7 @@ export default Base.extend({
|
|
249
246
|
return defaultValue ?? field.question.isMultipleChoice ? [] : null;
|
250
247
|
}
|
251
248
|
|
252
|
-
if (field.question.
|
249
|
+
if (field.question.isTable) {
|
253
250
|
return field.value.map((doc) =>
|
254
251
|
doc.fields
|
255
252
|
.filter((field) => !field.hidden)
|
@@ -263,7 +260,7 @@ export default Base.extend({
|
|
263
260
|
}
|
264
261
|
|
265
262
|
return field.value;
|
266
|
-
}
|
263
|
+
}
|
267
264
|
|
268
265
|
/**
|
269
266
|
* Find a field in the document by a given question slug
|
@@ -272,9 +269,8 @@ export default Base.extend({
|
|
272
269
|
* @return {Field} The wanted field
|
273
270
|
*/
|
274
271
|
findField(slug) {
|
275
|
-
return [
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
});
|
272
|
+
return [...this.fields, ...(this.parentDocument?.fields ?? [])].find(
|
273
|
+
(field) => field.question.slug === slug
|
274
|
+
);
|
275
|
+
}
|
276
|
+
}
|