@projectcaluma/ember-form 10.0.3 → 11.0.0-beta.1

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,8 +1,8 @@
1
1
  import { getOwner } from "@ember/application";
2
2
  import { assert } from "@ember/debug";
3
- import { computed, defineProperty } from "@ember/object";
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.extend({
21
- calumaStore: service(),
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
- this.raw && this.raw.__typename === "Document"
24
+ raw?.__typename === "Document"
27
25
  );
28
26
 
29
- defineProperty(this, "pk", {
30
- writable: false,
31
- value: `Document:${decodeId(this.raw.id)}`,
32
- });
27
+ super({ raw, ...args });
33
28
 
34
- this._super(...args);
29
+ this.parentDocument = parentDocument;
35
30
 
36
- this.set("fieldsets", []);
31
+ this.pushIntoStore();
37
32
 
38
33
  this._createRootForm();
39
34
  this._createFieldsets();
40
- },
35
+ }
41
36
 
42
37
  _createRootForm() {
43
- const rootForm =
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.set("rootForm", rootForm);
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 fieldsets = this.raw.forms.map((form) => {
54
- return (
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
- getOwner(this)
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 uuid of the document
65
+ * The parent document of this document. If this is set, the document is most
66
+ * likely a table row.
78
67
  *
79
- * @property {String} uuid
80
- * @accessor
68
+ * @property {Document} parentDocument
81
69
  */
82
- uuid: computed("raw.id", function () {
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: null,
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: null,
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
- fields: computed("fieldsets.@each.fields", function () {
125
- return this.fieldsets.reduce(
126
- (fields, fieldset) => [...fields, ...fieldset.fields],
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
- jexl: computed(function () {
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: computed(
186
- "rootForm.{slug,meta}",
187
- "parentDocument.jexlContext",
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: { form: this.rootForm.slug, formMeta: this.rootForm.meta },
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
- flatAnswerMap: computed("fields.@each.{question,value}", function () {
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.__typename === "TableQuestion") {
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
- ...this.fields,
277
- ...(this.parentDocument ? this.parentDocument.fields : []),
278
- ].find((field) => field.question.slug === slug);
279
- },
280
- });
272
+ return [...this.fields, ...(this.parentDocument?.fields ?? [])].find(
273
+ (field) => field.question.slug === slug
274
+ );
275
+ }
276
+ }