@projectcaluma/ember-form 10.0.2 → 11.0.0-beta.3
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 +1112 -0
- package/addon/components/cf-content.hbs +36 -39
- package/addon/components/cf-content.js +48 -29
- package/addon/components/cf-field/info.hbs +1 -1
- 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 +8 -9
- package/addon/components/cf-field/input/float.hbs +4 -4
- package/addon/components/cf-field/input/integer.hbs +5 -5
- package/addon/components/cf-field/input/radio.hbs +4 -1
- package/addon/components/cf-field/input/table.hbs +7 -7
- package/addon/components/cf-field/input/table.js +12 -10
- package/addon/components/cf-field/input/text.hbs +5 -5
- package/addon/components/cf-field/input/textarea.hbs +6 -5
- 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 +8 -13
- package/addon/components/cf-field.hbs +2 -2
- package/addon/components/cf-field.js +2 -3
- package/addon/components/cf-navigation-item.hbs +2 -2
- package/addon/components/cf-navigation.hbs +4 -1
- package/addon/components/document-validity.js +1 -1
- package/addon/gql/fragments/field.graphql +22 -0
- package/addon/gql/mutations/save-document-table-answer.graphql +1 -1
- package/addon/gql/mutations/save-document.graphql +1 -0
- package/addon/gql/queries/{get-document-answers.graphql → document-answers.graphql} +2 -1
- package/addon/gql/queries/{get-document-forms.graphql → document-forms.graphql} +2 -1
- package/addon/gql/queries/{get-document-used-dynamic-options.graphql → document-used-dynamic-options.graphql} +2 -1
- package/addon/gql/queries/{get-dynamic-options.graphql → dynamic-options.graphql} +2 -1
- package/addon/gql/queries/{get-fileanswer-info.graphql → fileanswer-info.graphql} +2 -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 +334 -401
- 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 +103 -94
- 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 +27 -23
- package/addon/components/cf-navigation.js +0 -9
@@ -3,7 +3,7 @@ import Component from "@glimmer/component";
|
|
3
3
|
import { queryManager } from "ember-apollo-client";
|
4
4
|
import moment from "moment";
|
5
5
|
|
6
|
-
import getFileAnswerInfoQuery from "@projectcaluma/ember-form/gql/queries/
|
6
|
+
import getFileAnswerInfoQuery from "@projectcaluma/ember-form/gql/queries/fileanswer-info.graphql";
|
7
7
|
|
8
8
|
export default class CfFieldValueComponent extends Component {
|
9
9
|
@queryManager apollo;
|
@@ -11,7 +11,7 @@ export default class CfFieldValueComponent extends Component {
|
|
11
11
|
get value() {
|
12
12
|
const field = this.args.field;
|
13
13
|
|
14
|
-
switch (field.
|
14
|
+
switch (field.questionType) {
|
15
15
|
case "ChoiceQuestion":
|
16
16
|
case "DynamicChoiceQuestion": {
|
17
17
|
return field.selected;
|
@@ -23,8 +23,8 @@ export default class CfFieldValueComponent extends Component {
|
|
23
23
|
case "FileQuestion": {
|
24
24
|
const answerValue = field.answer.value;
|
25
25
|
return {
|
26
|
-
fileAnswerId: answerValue && field.answer.id,
|
27
|
-
label: answerValue
|
26
|
+
fileAnswerId: answerValue && field.answer.raw.id,
|
27
|
+
label: answerValue?.name,
|
28
28
|
};
|
29
29
|
}
|
30
30
|
case "DateQuestion": {
|
@@ -34,22 +34,17 @@ export default class CfFieldValueComponent extends Component {
|
|
34
34
|
}
|
35
35
|
|
36
36
|
default:
|
37
|
-
return {
|
38
|
-
label: field.answer.value,
|
39
|
-
};
|
37
|
+
return { label: field.answer.value };
|
40
38
|
}
|
41
39
|
}
|
42
40
|
|
43
41
|
@action
|
44
|
-
async download(
|
42
|
+
async download(id) {
|
45
43
|
const { downloadUrl } = await this.apollo.query(
|
46
|
-
{
|
47
|
-
query: getFileAnswerInfoQuery,
|
48
|
-
variables: { id: fileAnswerId },
|
49
|
-
fetchPolicy: "cache-and-network",
|
50
|
-
},
|
44
|
+
{ query: getFileAnswerInfoQuery, variables: { id } },
|
51
45
|
"node.fileValue"
|
52
46
|
);
|
47
|
+
|
53
48
|
window.open(downloadUrl, "_blank");
|
54
49
|
}
|
55
50
|
}
|
@@ -16,8 +16,8 @@
|
|
16
16
|
{{/let}}
|
17
17
|
</div>
|
18
18
|
|
19
|
-
{{#if (and @field.question.infoText this.infoTextVisible)}}
|
20
|
-
<CfField::info @text={{@field.question.infoText}} />
|
19
|
+
{{#if (and @field.question.raw.infoText this.infoTextVisible)}}
|
20
|
+
<CfField::info @text={{@field.question.raw.infoText}} />
|
21
21
|
{{/if}}
|
22
22
|
|
23
23
|
{{#if this.saveIndicatorVisible}}
|
@@ -1,8 +1,7 @@
|
|
1
1
|
import { getOwner } from "@ember/application";
|
2
2
|
import { set } from "@ember/object";
|
3
3
|
import Component from "@glimmer/component";
|
4
|
-
import { timeout } from "ember-concurrency";
|
5
|
-
import { restartableTask } from "ember-concurrency-decorators";
|
4
|
+
import { timeout, restartableTask } from "ember-concurrency";
|
6
5
|
|
7
6
|
import { hasQuestionType } from "@projectcaluma/ember-core/helpers/has-question-type";
|
8
7
|
|
@@ -28,7 +27,7 @@ export default class CfFieldComponent extends Component {
|
|
28
27
|
|
29
28
|
get labelVisible() {
|
30
29
|
return (
|
31
|
-
!this.args.field?.question.meta.hideLabel &&
|
30
|
+
!this.args.field?.question.raw.meta.hideLabel &&
|
32
31
|
!hasQuestionType(this.args.field?.question, "static", "action-button")
|
33
32
|
);
|
34
33
|
}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
<li
|
2
2
|
class="cf-navigation__item uk-width-auto
|
3
|
-
{{if (or @item.active @item.childrenActive)
|
3
|
+
{{if (or @item.active @item.childrenActive) 'uk-active'}}"
|
4
4
|
>
|
5
5
|
<LinkTo @query={{hash displayedForm=@item.slug}}>
|
6
6
|
{{#if (and @useAsHeading this.active)}}
|
@@ -19,7 +19,7 @@
|
|
19
19
|
{{/if}}
|
20
20
|
<span
|
21
21
|
class="cf-navigation__item__icon cf-navigation__item__icon--{{@item.state}}
|
22
|
-
{{if @item.dirty
|
22
|
+
{{if @item.dirty 'cf-navigation__item__icon--dirty'}}"
|
23
23
|
></span>
|
24
24
|
</LinkTo>
|
25
25
|
|
@@ -1,4 +1,7 @@
|
|
1
|
-
<ul
|
1
|
+
<ul
|
2
|
+
class="uk-tab uk-tab-left uk-width-auto"
|
3
|
+
{{did-insert @navigation.goToNextItemIfNonNavigable}}
|
4
|
+
>
|
2
5
|
{{#each @navigation.rootItems as |item|}}
|
3
6
|
<CfNavigationItem
|
4
7
|
@item={{item}}
|
@@ -4,6 +4,7 @@
|
|
4
4
|
# When changing this file the other must also receive the same changes.
|
5
5
|
|
6
6
|
fragment SimpleQuestion on Question {
|
7
|
+
id
|
7
8
|
slug
|
8
9
|
label
|
9
10
|
isRequired
|
@@ -14,6 +15,7 @@ fragment SimpleQuestion on Question {
|
|
14
15
|
textMinLength: minLength
|
15
16
|
textMaxLength: maxLength
|
16
17
|
textDefaultAnswer: defaultAnswer {
|
18
|
+
id
|
17
19
|
value
|
18
20
|
}
|
19
21
|
placeholder
|
@@ -22,6 +24,7 @@ fragment SimpleQuestion on Question {
|
|
22
24
|
textareaMinLength: minLength
|
23
25
|
textareaMaxLength: maxLength
|
24
26
|
textareaDefaultAnswer: defaultAnswer {
|
27
|
+
id
|
25
28
|
value
|
26
29
|
}
|
27
30
|
placeholder
|
@@ -30,6 +33,7 @@ fragment SimpleQuestion on Question {
|
|
30
33
|
integerMinValue: minValue
|
31
34
|
integerMaxValue: maxValue
|
32
35
|
integerDefaultAnswer: defaultAnswer {
|
36
|
+
id
|
33
37
|
value
|
34
38
|
}
|
35
39
|
placeholder
|
@@ -38,6 +42,7 @@ fragment SimpleQuestion on Question {
|
|
38
42
|
floatMinValue: minValue
|
39
43
|
floatMaxValue: maxValue
|
40
44
|
floatDefaultAnswer: defaultAnswer {
|
45
|
+
id
|
41
46
|
value
|
42
47
|
}
|
43
48
|
placeholder
|
@@ -46,6 +51,7 @@ fragment SimpleQuestion on Question {
|
|
46
51
|
choiceOptions: options {
|
47
52
|
edges {
|
48
53
|
node {
|
54
|
+
id
|
49
55
|
slug
|
50
56
|
label
|
51
57
|
isArchived
|
@@ -53,6 +59,7 @@ fragment SimpleQuestion on Question {
|
|
53
59
|
}
|
54
60
|
}
|
55
61
|
choiceDefaultAnswer: defaultAnswer {
|
62
|
+
id
|
56
63
|
value
|
57
64
|
}
|
58
65
|
}
|
@@ -60,6 +67,7 @@ fragment SimpleQuestion on Question {
|
|
60
67
|
multipleChoiceOptions: options {
|
61
68
|
edges {
|
62
69
|
node {
|
70
|
+
id
|
63
71
|
slug
|
64
72
|
label
|
65
73
|
isArchived
|
@@ -67,11 +75,13 @@ fragment SimpleQuestion on Question {
|
|
67
75
|
}
|
68
76
|
}
|
69
77
|
multipleChoiceDefaultAnswer: defaultAnswer {
|
78
|
+
id
|
70
79
|
value
|
71
80
|
}
|
72
81
|
}
|
73
82
|
... on DateQuestion {
|
74
83
|
dateDefaultAnswer: defaultAnswer {
|
84
|
+
id
|
75
85
|
value
|
76
86
|
}
|
77
87
|
}
|
@@ -89,8 +99,10 @@ fragment SimpleQuestion on Question {
|
|
89
99
|
}
|
90
100
|
|
91
101
|
fragment FieldTableQuestion on Question {
|
102
|
+
id
|
92
103
|
... on TableQuestion {
|
93
104
|
rowForm {
|
105
|
+
id
|
94
106
|
slug
|
95
107
|
questions {
|
96
108
|
edges {
|
@@ -101,6 +113,7 @@ fragment FieldTableQuestion on Question {
|
|
101
113
|
}
|
102
114
|
}
|
103
115
|
tableDefaultAnswer: defaultAnswer {
|
116
|
+
id
|
104
117
|
value {
|
105
118
|
id
|
106
119
|
answers {
|
@@ -108,6 +121,7 @@ fragment FieldTableQuestion on Question {
|
|
108
121
|
node {
|
109
122
|
id
|
110
123
|
question {
|
124
|
+
id
|
111
125
|
slug
|
112
126
|
}
|
113
127
|
... on StringAnswer {
|
@@ -134,10 +148,12 @@ fragment FieldTableQuestion on Question {
|
|
134
148
|
}
|
135
149
|
|
136
150
|
fragment FieldQuestion on Question {
|
151
|
+
id
|
137
152
|
...SimpleQuestion
|
138
153
|
...FieldTableQuestion
|
139
154
|
... on FormQuestion {
|
140
155
|
subForm {
|
156
|
+
id
|
141
157
|
slug
|
142
158
|
name
|
143
159
|
questions {
|
@@ -145,10 +161,12 @@ fragment FieldQuestion on Question {
|
|
145
161
|
node {
|
146
162
|
# This part here limits our query to 2 level deep nested forms. This
|
147
163
|
# has to be solved in another way!
|
164
|
+
id
|
148
165
|
...SimpleQuestion
|
149
166
|
...FieldTableQuestion
|
150
167
|
... on FormQuestion {
|
151
168
|
subForm {
|
169
|
+
id
|
152
170
|
slug
|
153
171
|
name
|
154
172
|
questions {
|
@@ -171,6 +189,7 @@ fragment FieldQuestion on Question {
|
|
171
189
|
fragment SimpleAnswer on Answer {
|
172
190
|
id
|
173
191
|
question {
|
192
|
+
id
|
174
193
|
slug
|
175
194
|
}
|
176
195
|
... on StringAnswer {
|
@@ -187,6 +206,7 @@ fragment SimpleAnswer on Answer {
|
|
187
206
|
}
|
188
207
|
... on FileAnswer {
|
189
208
|
fileValue: value {
|
209
|
+
id
|
190
210
|
uploadUrl
|
191
211
|
downloadUrl
|
192
212
|
metadata
|
@@ -199,11 +219,13 @@ fragment SimpleAnswer on Answer {
|
|
199
219
|
}
|
200
220
|
|
201
221
|
fragment FieldAnswer on Answer {
|
222
|
+
id
|
202
223
|
...SimpleAnswer
|
203
224
|
... on TableAnswer {
|
204
225
|
tableValue: value {
|
205
226
|
id
|
206
227
|
form {
|
228
|
+
id
|
207
229
|
slug
|
208
230
|
questions {
|
209
231
|
edges {
|
@@ -1,6 +1,6 @@
|
|
1
1
|
#import * from '../fragments/field.graphql'
|
2
2
|
|
3
|
-
mutation
|
3
|
+
mutation SaveDocumentTableAnswer($input: SaveDocumentTableAnswerInput!) {
|
4
4
|
saveDocumentTableAnswer(input: $input) {
|
5
5
|
answer {
|
6
6
|
...FieldAnswer
|
@@ -1,9 +1,10 @@
|
|
1
1
|
#import FieldQuestion, FieldTableQuestion, SimpleQuestion from '../fragments/field.graphql'
|
2
2
|
|
3
|
-
query
|
3
|
+
query DocumentForms($slug: String!) {
|
4
4
|
allForms(filter: [{ slug: $slug }]) {
|
5
5
|
edges {
|
6
6
|
node {
|
7
|
+
id
|
7
8
|
slug
|
8
9
|
name
|
9
10
|
meta
|
@@ -1,9 +1,10 @@
|
|
1
|
-
query
|
1
|
+
query DocumentUsedDynamicOptions($document: ID!, $question: ID!) {
|
2
2
|
allUsedDynamicOptions(
|
3
3
|
filter: [{ document: $document }, { question: $question }]
|
4
4
|
) {
|
5
5
|
edges {
|
6
6
|
node {
|
7
|
+
id
|
7
8
|
slug
|
8
9
|
label
|
9
10
|
}
|
@@ -0,0 +1,50 @@
|
|
1
|
+
import Helper from "@ember/component/helper";
|
2
|
+
import { warn } from "@ember/debug";
|
3
|
+
import { inject as service } from "@ember/service";
|
4
|
+
|
5
|
+
/**
|
6
|
+
* Helper for getting the right widget.
|
7
|
+
*
|
8
|
+
* This helper expects n objects as positional parameters. It checks if the
|
9
|
+
* object has a widget override in it's metadata. If one exists it checks if
|
10
|
+
* said widget was registered in the caluma options service and then returns
|
11
|
+
* the widget name. If it doesn't have a valid widget, the next object will be
|
12
|
+
* checked. If no object returns a valid widget, the passed default widget will
|
13
|
+
* be used.
|
14
|
+
*
|
15
|
+
* ```hbs
|
16
|
+
* {{component (get-widget field.question someobject default="cf-form") foo=bar}}
|
17
|
+
* ```
|
18
|
+
*
|
19
|
+
* @function getWidget
|
20
|
+
* @param {Array} params
|
21
|
+
* @param {Object} [options]
|
22
|
+
* @param {String} [options.default]
|
23
|
+
*/
|
24
|
+
export default class GetWidgetHelper extends Helper {
|
25
|
+
@service calumaOptions;
|
26
|
+
|
27
|
+
compute(params, { default: defaultWidget = "cf-field/input" }) {
|
28
|
+
for (const obj of params) {
|
29
|
+
const widget = obj?.raw?.meta?.widgetOverride;
|
30
|
+
if (!widget) {
|
31
|
+
continue;
|
32
|
+
}
|
33
|
+
const override =
|
34
|
+
widget &&
|
35
|
+
this.calumaOptions
|
36
|
+
.getComponentOverrides()
|
37
|
+
.find(({ component }) => component === widget);
|
38
|
+
|
39
|
+
warn(
|
40
|
+
`Widget override "${widget}" is not registered. Please register it by calling \`calumaOptions.registerComponentOverride\``,
|
41
|
+
override,
|
42
|
+
{ id: "ember-caluma.unregistered-override" }
|
43
|
+
);
|
44
|
+
|
45
|
+
if (override) return widget;
|
46
|
+
}
|
47
|
+
|
48
|
+
return defaultWidget;
|
49
|
+
}
|
50
|
+
}
|
package/addon/lib/answer.js
CHANGED
@@ -1,130 +1,166 @@
|
|
1
1
|
import { getOwner } from "@ember/application";
|
2
2
|
import { assert } from "@ember/debug";
|
3
|
-
import { computed } from "@ember/object";
|
4
|
-
import { inject as service } from "@ember/service";
|
5
3
|
import { camelize } from "@ember/string";
|
6
4
|
import { isEmpty } from "@ember/utils";
|
5
|
+
import { dedupeTracked, cached } from "tracked-toolbox";
|
7
6
|
|
8
7
|
import { decodeId } from "@projectcaluma/ember-core/helpers/decode-id";
|
9
8
|
import Base from "@projectcaluma/ember-form/lib/base";
|
10
9
|
import { parseDocument } from "@projectcaluma/ember-form/lib/parsers";
|
11
10
|
|
11
|
+
/**
|
12
|
+
* Class that automatically defines all keys of the passed object as deduped
|
13
|
+
* tracked property and assigns the initial value.
|
14
|
+
*
|
15
|
+
* @class DedupedTrackedObject
|
16
|
+
* @private
|
17
|
+
*/
|
18
|
+
class DedupedTrackedObject {
|
19
|
+
constructor(obj) {
|
20
|
+
Object.entries(obj).forEach(([key, value]) => {
|
21
|
+
Object.defineProperty(
|
22
|
+
this,
|
23
|
+
key,
|
24
|
+
dedupeTracked(this, key, { initializer: () => value })
|
25
|
+
);
|
26
|
+
});
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
12
30
|
/**
|
13
31
|
* Object which represents an answer in context of a field
|
14
32
|
*
|
15
33
|
* @class Answer
|
16
34
|
*/
|
17
|
-
export default Base
|
18
|
-
|
35
|
+
export default class Answer extends Base {
|
36
|
+
constructor({ raw, field, ...args }) {
|
37
|
+
assert("`field` must be passed as an argument", field);
|
19
38
|
|
20
|
-
init(...args) {
|
21
39
|
assert(
|
22
40
|
"A graphql answer `raw` must be passed",
|
23
|
-
|
41
|
+
/Answer$/.test(raw?.__typename)
|
24
42
|
);
|
25
43
|
|
26
|
-
|
27
|
-
|
28
|
-
|
44
|
+
super({ raw, ...args });
|
45
|
+
|
46
|
+
this.field = field;
|
47
|
+
this.raw = new DedupedTrackedObject(raw);
|
29
48
|
|
30
|
-
this.
|
49
|
+
this.pushIntoStore();
|
50
|
+
}
|
51
|
+
|
52
|
+
/**
|
53
|
+
* The field this answer originates from
|
54
|
+
*
|
55
|
+
* @property {Field} field
|
56
|
+
*/
|
57
|
+
field = null;
|
58
|
+
|
59
|
+
/**
|
60
|
+
* The raw data of the answer. This is the only `raw` property that is tracked
|
61
|
+
* since only the answers properties are changed while rendering the form.
|
62
|
+
*
|
63
|
+
* @property {DedupedTrackedObject} raw
|
64
|
+
*/
|
65
|
+
raw = {};
|
31
66
|
|
32
|
-
|
33
|
-
|
67
|
+
/**
|
68
|
+
* The primary key of the answer.
|
69
|
+
*
|
70
|
+
* @property {String} pk
|
71
|
+
*/
|
72
|
+
@cached
|
73
|
+
get pk() {
|
74
|
+
return this.uuid && `Answer:${this.uuid}`;
|
75
|
+
}
|
34
76
|
|
35
77
|
/**
|
36
78
|
* The uuid of the answer
|
37
79
|
*
|
38
80
|
* @property {String} uuid
|
39
|
-
* @accessor
|
40
81
|
*/
|
41
|
-
|
82
|
+
@cached
|
83
|
+
get uuid() {
|
42
84
|
return this.raw.id ? decodeId(this.raw.id) : null;
|
43
|
-
}
|
85
|
+
}
|
44
86
|
|
45
|
-
|
87
|
+
/**
|
88
|
+
* Whether the answer is new. This is true when there is no object from the
|
89
|
+
* backend or the value is empty.
|
90
|
+
*
|
91
|
+
* @property {Boolean} isNew
|
92
|
+
*/
|
93
|
+
@cached
|
94
|
+
get isNew() {
|
46
95
|
return !this.uuid || isEmpty(this.value);
|
47
|
-
}
|
96
|
+
}
|
48
97
|
|
49
98
|
/**
|
50
99
|
* The name of the property in which the value is stored. This depends on the
|
51
100
|
* type of the answer.
|
52
101
|
*
|
53
|
-
*
|
54
102
|
* @property {String} _valueKey
|
55
|
-
* @accessor
|
56
103
|
* @private
|
57
104
|
*/
|
58
|
-
|
105
|
+
@cached
|
106
|
+
get _valueKey() {
|
59
107
|
return (
|
60
|
-
this.__typename &&
|
108
|
+
this.raw.__typename &&
|
109
|
+
camelize(this.raw.__typename.replace(/Answer$/, "Value"))
|
61
110
|
);
|
62
|
-
}
|
111
|
+
}
|
63
112
|
|
64
113
|
/**
|
65
114
|
* The value of the answer, the type of this value depends on the type of the
|
66
115
|
* answer. For table answers this returns an array of documents.
|
67
116
|
*
|
68
117
|
* @property {String|Number|String[]|Document[]} value
|
69
|
-
* @computed
|
70
118
|
*/
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
"
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
)
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
return value;
|
104
|
-
},
|
105
|
-
set(_, value) {
|
106
|
-
value = [undefined, ""].includes(value) ? null : value;
|
107
|
-
|
108
|
-
if (this._valueKey) {
|
109
|
-
this.set(this._valueKey, value);
|
110
|
-
}
|
111
|
-
|
112
|
-
return value;
|
113
|
-
},
|
119
|
+
@cached
|
120
|
+
get value() {
|
121
|
+
const value = this.raw[this._valueKey];
|
122
|
+
|
123
|
+
if (this._valueKey === "tableValue" && value) {
|
124
|
+
const owner = getOwner(this);
|
125
|
+
const Document = owner.factoryFor("caluma-model:document").class;
|
126
|
+
|
127
|
+
return value.map((document) => {
|
128
|
+
if (document instanceof Document) return document;
|
129
|
+
|
130
|
+
const existing = this.calumaStore.find(
|
131
|
+
`Document:${decodeId(document.id)}`
|
132
|
+
);
|
133
|
+
|
134
|
+
return (
|
135
|
+
existing ||
|
136
|
+
new Document({
|
137
|
+
raw: parseDocument(document),
|
138
|
+
parentDocument: this.field.document,
|
139
|
+
owner,
|
140
|
+
})
|
141
|
+
);
|
142
|
+
});
|
143
|
+
}
|
144
|
+
|
145
|
+
return value;
|
146
|
+
}
|
147
|
+
|
148
|
+
set value(value) {
|
149
|
+
if (this._valueKey) {
|
150
|
+
this.raw[this._valueKey] = [undefined, ""].includes(value) ? null : value;
|
114
151
|
}
|
115
|
-
|
152
|
+
}
|
116
153
|
|
117
154
|
/**
|
118
155
|
* The value serialized for a backend request.
|
119
156
|
*
|
120
157
|
* @property {String|Number|String[]} serializedValue
|
121
|
-
* @accessor
|
122
158
|
*/
|
123
|
-
serializedValue
|
124
|
-
if (this.__typename === "TableAnswer") {
|
159
|
+
get serializedValue() {
|
160
|
+
if (this.raw.__typename === "TableAnswer") {
|
125
161
|
return (this.value || []).map(({ uuid }) => uuid);
|
126
162
|
}
|
127
163
|
|
128
164
|
return this.value;
|
129
|
-
}
|
130
|
-
}
|
165
|
+
}
|
166
|
+
}
|