@projectcaluma/ember-form 10.0.2 → 11.0.0-beta.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
}
|