@projectcaluma/ember-form 11.0.0-beta.4 → 11.0.0-beta.40
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 +202 -0
- package/addon/components/cf-content.hbs +38 -37
- package/addon/components/cf-content.js +7 -3
- package/addon/components/cf-field/hint.hbs +5 -0
- package/addon/components/cf-field/input/action-button.hbs +8 -4
- package/addon/components/cf-field/input/action-button.js +60 -59
- package/addon/components/cf-field/input/checkbox.hbs +2 -3
- package/addon/components/cf-field/input/date.hbs +12 -25
- package/addon/components/cf-field/input/date.js +19 -11
- package/addon/components/cf-field/input/files.hbs +38 -0
- package/addon/components/cf-field/input/files.js +113 -0
- package/addon/components/cf-field/input/powerselect.hbs +27 -29
- package/addon/components/cf-field/input/powerselect.js +8 -2
- package/addon/components/cf-field/input/radio.hbs +2 -2
- package/addon/components/cf-field/input/static.hbs +1 -1
- package/addon/components/cf-field/input/table.hbs +20 -18
- package/addon/components/cf-field/input/table.js +1 -11
- package/addon/components/cf-field/input.hbs +8 -21
- package/addon/components/cf-field/input.js +32 -14
- package/addon/components/cf-field/label.hbs +4 -2
- package/addon/components/cf-field-value.hbs +22 -7
- package/addon/components/cf-field-value.js +12 -36
- package/addon/components/cf-field.hbs +42 -9
- package/addon/components/cf-field.js +41 -17
- package/addon/components/cf-form-wrapper.hbs +4 -1
- package/addon/components/cf-form.hbs +6 -1
- package/addon/components/document-validity.js +16 -1
- package/addon/gql/fragments/field.graphql +32 -7
- package/addon/gql/mutations/save-document-files-answer.graphql +9 -0
- package/addon/gql/queries/document-forms.graphql +1 -1
- package/addon/gql/queries/dynamic-options.graphql +4 -4
- package/addon/gql/queries/{fileanswer-info.graphql → filesanswer-info.graphql} +4 -4
- package/addon/helpers/format-graphql-error.js +21 -0
- package/addon/helpers/get-widget.js +16 -2
- package/addon/instance-initializers/form-widget-overrides.js +52 -0
- package/addon/lib/document.js +9 -1
- package/addon/lib/field.js +96 -59
- package/addon/lib/navigation.js +3 -1
- package/addon/lib/question.js +18 -5
- package/addon/modifiers/autoresize.js +14 -0
- package/addon/services/caluma-store.js +2 -0
- package/app/components/cf-field/{input/file.js → hint.js} +1 -1
- package/app/components/cf-field/input/files.js +1 -0
- package/app/helpers/format-graphql-error.js +1 -0
- package/app/helpers/get-widget.js +1 -4
- package/app/instance-initializers/form-widget-overrides.js +4 -0
- package/app/modifiers/autoresize.js +1 -0
- package/app/styles/@projectcaluma/ember-form.scss +5 -15
- package/app/styles/_flatpickr.scss +47 -0
- package/blueprints/@projectcaluma/ember-form/index.js +1 -1
- package/index.js +12 -0
- package/package.json +47 -37
- package/translations/de.yaml +6 -6
- package/translations/en.yaml +6 -6
- package/translations/fr.yaml +6 -6
- package/addon/components/cf-field/input/file.hbs +0 -32
- package/addon/components/cf-field/input/file.js +0 -89
- package/addon/components/cf-field/label.js +0 -11
- package/addon/gql/mutations/remove-answer.graphql +0 -7
- package/addon/gql/mutations/save-document-file-answer.graphql +0 -9
- package/addon/instance-initializers/setup-pikaday-i18n.js +0 -35
- package/config/environment.js +0 -5
@@ -0,0 +1,113 @@
|
|
1
|
+
import { action } from "@ember/object";
|
2
|
+
import { inject as service } from "@ember/service";
|
3
|
+
import { macroCondition, isTesting } from "@embroider/macros";
|
4
|
+
import Component from "@glimmer/component";
|
5
|
+
import { queryManager } from "ember-apollo-client";
|
6
|
+
import fetch from "fetch";
|
7
|
+
|
8
|
+
import getFilesAnswerInfoQuery from "@projectcaluma/ember-form/gql/queries/filesanswer-info.graphql";
|
9
|
+
|
10
|
+
export default class CfFieldInputFilesComponent extends Component {
|
11
|
+
@service intl;
|
12
|
+
|
13
|
+
@queryManager apollo;
|
14
|
+
|
15
|
+
get files() {
|
16
|
+
return this.args.field?.answer?.value;
|
17
|
+
}
|
18
|
+
|
19
|
+
@action
|
20
|
+
async download(fileId) {
|
21
|
+
if (!fileId) {
|
22
|
+
return;
|
23
|
+
}
|
24
|
+
const answers = await this.apollo.query(
|
25
|
+
{
|
26
|
+
query: getFilesAnswerInfoQuery,
|
27
|
+
variables: { id: this.args.field.answer.raw.id },
|
28
|
+
fetchPolicy: "network-only",
|
29
|
+
},
|
30
|
+
"node.value"
|
31
|
+
);
|
32
|
+
const { downloadUrl } =
|
33
|
+
answers.find((file) =>
|
34
|
+
// the testing graph-ql setup does a base64 encoding of `__typename: fileID`
|
35
|
+
macroCondition(isTesting())
|
36
|
+
? file.id === fileId ||
|
37
|
+
atob(file.id).substring(file.__typename.length + 1) === fileId
|
38
|
+
: file.id === fileId
|
39
|
+
) ?? {};
|
40
|
+
if (downloadUrl) {
|
41
|
+
window.open(downloadUrl, "_blank");
|
42
|
+
}
|
43
|
+
}
|
44
|
+
|
45
|
+
@action
|
46
|
+
async save({ target }) {
|
47
|
+
// store the old list of files
|
48
|
+
// unwrap files from FileList construct
|
49
|
+
let newFiles = Array.from(target.files).map((file) => ({
|
50
|
+
name: file.name,
|
51
|
+
value: file,
|
52
|
+
}));
|
53
|
+
|
54
|
+
const fileList = [...(this.files || []), ...newFiles];
|
55
|
+
|
56
|
+
if (newFiles.length === 0) {
|
57
|
+
return;
|
58
|
+
}
|
59
|
+
|
60
|
+
// trigger save action for file list of old and new files with
|
61
|
+
// reduces properties to match gql format
|
62
|
+
const { filesValue: savedAnswerValue } = await this.args.onSave(
|
63
|
+
fileList.map(({ name, id }) => ({ name, id }))
|
64
|
+
);
|
65
|
+
|
66
|
+
try {
|
67
|
+
// iterate over list of new files and enrich with graphql answer values
|
68
|
+
newFiles = newFiles.map((file) => ({
|
69
|
+
...savedAnswerValue.find(
|
70
|
+
(value) =>
|
71
|
+
file.name === value.name &&
|
72
|
+
!fileList.find((file) => file.id === value.id)
|
73
|
+
),
|
74
|
+
value: file.value,
|
75
|
+
}));
|
76
|
+
|
77
|
+
const uploadFunction = async (file) => {
|
78
|
+
const response = await fetch(file.uploadUrl, {
|
79
|
+
method: "PUT",
|
80
|
+
body: file.value,
|
81
|
+
});
|
82
|
+
if (!response.ok) {
|
83
|
+
throw new Error();
|
84
|
+
}
|
85
|
+
return response;
|
86
|
+
};
|
87
|
+
|
88
|
+
// upload the actual file to data storage
|
89
|
+
await Promise.all(newFiles.map((file) => uploadFunction(file)));
|
90
|
+
|
91
|
+
this.args.field.answer.value = savedAnswerValue;
|
92
|
+
} catch (error) {
|
93
|
+
await this.args.onSave([]);
|
94
|
+
this.args.field._errors = [{ type: "uploadFailed" }];
|
95
|
+
} finally {
|
96
|
+
// eslint-disable-next-line require-atomic-updates
|
97
|
+
target.value = "";
|
98
|
+
}
|
99
|
+
}
|
100
|
+
|
101
|
+
@action
|
102
|
+
async delete(fileId) {
|
103
|
+
const remainingFiles = this.files
|
104
|
+
.filter((file) => file.id !== fileId)
|
105
|
+
.map(({ name, id }) => ({ name, id }));
|
106
|
+
|
107
|
+
try {
|
108
|
+
await this.args.onSave(remainingFiles);
|
109
|
+
} catch (error) {
|
110
|
+
this.args.field._errors = [{ type: "deleteFailed" }];
|
111
|
+
}
|
112
|
+
}
|
113
|
+
}
|
@@ -1,29 +1,27 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
{{
|
26
|
-
|
27
|
-
|
28
|
-
</DynamicSelect>
|
29
|
-
{{/let}}
|
1
|
+
<this.selectComponent
|
2
|
+
@options={{@field.options}}
|
3
|
+
@selected={{@field.selected}}
|
4
|
+
@disabled={{@disabled}}
|
5
|
+
@allowClear={{true}}
|
6
|
+
@preventScroll={{true}}
|
7
|
+
@searchEnabled={{this.searchEnabled}}
|
8
|
+
@searchField="label"
|
9
|
+
@triggerId={{@field.pk}}
|
10
|
+
@renderInPlace={{true}}
|
11
|
+
@placeholder={{this.placeholder}}
|
12
|
+
@loadingMessage={{t "caluma.form.power-select.options-loading"}}
|
13
|
+
@searchMessage={{t "caluma.form.power-select.options-empty"}}
|
14
|
+
@searchPlaceholder={{t "caluma.form.power-select.search-placeholder"}}
|
15
|
+
@noMatchesMessage={{t "caluma.form.power-select.search-empty"}}
|
16
|
+
@onChange={{this.change}}
|
17
|
+
as |option|
|
18
|
+
>
|
19
|
+
{{#if (and option.disabled (not @disabled))}}
|
20
|
+
<del
|
21
|
+
class="uk-text-muted"
|
22
|
+
title={{t "caluma.form.optionNotAvailable"}}
|
23
|
+
>{{option.label}}</del>
|
24
|
+
{{else}}
|
25
|
+
{{option.label}}
|
26
|
+
{{/if}}
|
27
|
+
</this.selectComponent>
|
@@ -1,7 +1,10 @@
|
|
1
1
|
import { getOwner } from "@ember/application";
|
2
2
|
import { action } from "@ember/object";
|
3
3
|
import { inject as service } from "@ember/service";
|
4
|
+
import { ensureSafeComponent } from "@embroider/util";
|
4
5
|
import Component from "@glimmer/component";
|
6
|
+
import PowerSelectComponent from "ember-power-select/components/power-select";
|
7
|
+
import PowerSelectMultipleComponent from "ember-power-select/components/power-select-multiple";
|
5
8
|
|
6
9
|
/**
|
7
10
|
* Dropdown component for the single and multiple choice question type
|
@@ -16,8 +19,11 @@ export default class CfFieldInputPowerselectComponent extends Component {
|
|
16
19
|
return this.args.field?.question.isMultipleChoice;
|
17
20
|
}
|
18
21
|
|
19
|
-
get
|
20
|
-
return
|
22
|
+
get selectComponent() {
|
23
|
+
return ensureSafeComponent(
|
24
|
+
this.multiple ? PowerSelectMultipleComponent : PowerSelectComponent,
|
25
|
+
this
|
26
|
+
);
|
21
27
|
}
|
22
28
|
|
23
29
|
get searchEnabled() {
|
@@ -1,5 +1,5 @@
|
|
1
1
|
{{#each @field.options as |option i|}}
|
2
|
-
{{#if (gt i 0)}}<br />{{/if}}
|
2
|
+
{{#if (and (gt i 0) (not @field.raw.question.meta.vertical))}}<br />{{/if}}
|
3
3
|
<label
|
4
4
|
class="{{if @field.isInvalid 'uk-form-danger'}}
|
5
5
|
{{if @field.raw.question.meta.vertical 'uk-margin-large-right'}}"
|
@@ -10,7 +10,7 @@
|
|
10
10
|
name={{@field.pk}}
|
11
11
|
value={{option.slug}}
|
12
12
|
checked={{eq option.slug @field.answer.value}}
|
13
|
-
disabled={{@disabled}}
|
13
|
+
disabled={{or option.disabled @disabled}}
|
14
14
|
{{on "change" (fn @onSave option.slug)}}
|
15
15
|
/>
|
16
16
|
{{#if (and option.disabled (not @disabled))}}
|
@@ -1,4 +1,4 @@
|
|
1
|
-
<table class="uk-table uk-table-divider">
|
1
|
+
<table class="uk-table uk-table-divider uk-margin-remove-vertical">
|
2
2
|
<thead>
|
3
3
|
<tr>
|
4
4
|
{{#each this.columns as |column|}}
|
@@ -25,27 +25,27 @@
|
|
25
25
|
class="uk-animation-fade uk-text-danger"
|
26
26
|
/>
|
27
27
|
{{/if}}
|
28
|
-
<
|
29
|
-
|
30
|
-
|
31
|
-
class="uk-button uk-button-link uk-flex-inline uk-margin-small-left"
|
28
|
+
<UkButton
|
29
|
+
@color="link"
|
30
|
+
@onClick={{fn this.edit document}}
|
32
31
|
title={{t "caluma.form.edit"}}
|
33
|
-
|
32
|
+
class="uk-flex-inline uk-margin-small-left table-controls"
|
33
|
+
data-test-edit-row
|
34
34
|
>
|
35
35
|
<UkIcon @icon="pencil" />
|
36
|
-
<span
|
37
|
-
</
|
36
|
+
<span hidden>{{t "caluma.form.edit"}}</span>
|
37
|
+
</UkButton>
|
38
38
|
{{#unless @disabled}}
|
39
|
-
<
|
40
|
-
|
41
|
-
|
42
|
-
class="uk-button uk-button-link uk-flex-inline uk-margin-small-left"
|
39
|
+
<UkButton
|
40
|
+
@color="link"
|
41
|
+
@onClick={{fn (perform this.delete) document}}
|
43
42
|
title={{t "caluma.form.delete"}}
|
44
|
-
|
43
|
+
class="uk-flex-inline uk-margin-small-left table-controls"
|
44
|
+
data-test-delete-row
|
45
45
|
>
|
46
46
|
<UkIcon @icon="trash" />
|
47
|
-
<span
|
48
|
-
</
|
47
|
+
<span hidden>{{t "caluma.form.delete"}}</span>
|
48
|
+
</UkButton>
|
49
49
|
{{/unless}}
|
50
50
|
</div>
|
51
51
|
</td>
|
@@ -57,12 +57,13 @@
|
|
57
57
|
<tr>
|
58
58
|
<td colspan={{add this.columns.length 1}} class="uk-text-center">
|
59
59
|
<UkButton
|
60
|
-
@
|
60
|
+
@color="link"
|
61
61
|
@onClick={{perform this.add}}
|
62
|
+
title={{t "caluma.form.addRow"}}
|
62
63
|
data-test-add-row
|
63
64
|
>
|
64
65
|
<UkIcon @icon="plus" />
|
65
|
-
<span
|
66
|
+
<span hidden>{{t "caluma.form.addRow"}}</span>
|
66
67
|
</UkButton>
|
67
68
|
</td>
|
68
69
|
</tr>
|
@@ -82,10 +83,11 @@
|
|
82
83
|
@document={{this.documentToEdit}}
|
83
84
|
@fieldset={{object-at 0 this.documentToEdit.fieldsets}}
|
84
85
|
@disabled={{@disabled}}
|
86
|
+
@context={{@context}}
|
85
87
|
/>
|
86
88
|
</modal.body>
|
87
89
|
|
88
|
-
<modal.footer
|
90
|
+
<modal.footer class="uk-text-right">
|
89
91
|
{{#if @disabled}}
|
90
92
|
<UkButton
|
91
93
|
@label={{t "caluma.form.close"}}
|
@@ -5,22 +5,12 @@ import Component from "@glimmer/component";
|
|
5
5
|
import { tracked } from "@glimmer/tracking";
|
6
6
|
import { queryManager } from "ember-apollo-client";
|
7
7
|
import { dropTask } from "ember-concurrency";
|
8
|
-
import
|
8
|
+
import { confirm } from "ember-uikit";
|
9
9
|
|
10
10
|
import removeDocumentMutation from "@projectcaluma/ember-form/gql/mutations/remove-document.graphql";
|
11
11
|
import saveDocumentMutation from "@projectcaluma/ember-form/gql/mutations/save-document.graphql";
|
12
12
|
import { parseDocument } from "@projectcaluma/ember-form/lib/parsers";
|
13
13
|
|
14
|
-
async function confirm(text) {
|
15
|
-
try {
|
16
|
-
await UIkit.modal.confirm(text);
|
17
|
-
|
18
|
-
return true;
|
19
|
-
} catch (error) {
|
20
|
-
return false;
|
21
|
-
}
|
22
|
-
}
|
23
|
-
|
24
14
|
export default class CfFieldInputTableComponent extends Component {
|
25
15
|
@service notification;
|
26
16
|
@service intl;
|
@@ -1,21 +1,8 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
)
|
10
|
-
'uk-flex'
|
11
|
-
}}"
|
12
|
-
>
|
13
|
-
<InputComponent
|
14
|
-
@field={{@field}}
|
15
|
-
@disabled={{@disabled}}
|
16
|
-
@onSave={{@onSave}}
|
17
|
-
@context={{@context}}
|
18
|
-
/>
|
19
|
-
</div>
|
20
|
-
{{/let}}
|
21
|
-
{{/if}}
|
1
|
+
<div class="uk-form-controls">
|
2
|
+
<this.inputComponent
|
3
|
+
@field={{@field}}
|
4
|
+
@disabled={{@disabled}}
|
5
|
+
@onSave={{@onSave}}
|
6
|
+
@context={{@context}}
|
7
|
+
/>
|
8
|
+
</div>
|
@@ -1,12 +1,33 @@
|
|
1
|
-
import {
|
1
|
+
import { ensureSafeComponent } from "@embroider/util";
|
2
2
|
import Component from "@glimmer/component";
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
4
|
+
import ActionButtonComponent from "@projectcaluma/ember-form/components/cf-field/input/action-button";
|
5
|
+
import CheckboxComponent from "@projectcaluma/ember-form/components/cf-field/input/checkbox";
|
6
|
+
import DateComponent from "@projectcaluma/ember-form/components/cf-field/input/date";
|
7
|
+
import FilesComponent from "@projectcaluma/ember-form/components/cf-field/input/files";
|
8
|
+
import FloatComponent from "@projectcaluma/ember-form/components/cf-field/input/float";
|
9
|
+
import IntegerComponent from "@projectcaluma/ember-form/components/cf-field/input/integer";
|
10
|
+
import RadioComponent from "@projectcaluma/ember-form/components/cf-field/input/radio";
|
11
|
+
import StaticComponent from "@projectcaluma/ember-form/components/cf-field/input/static";
|
12
|
+
import TableComponent from "@projectcaluma/ember-form/components/cf-field/input/table";
|
13
|
+
import TextComponent from "@projectcaluma/ember-form/components/cf-field/input/text";
|
14
|
+
import TextareaComponent from "@projectcaluma/ember-form/components/cf-field/input/textarea";
|
15
|
+
|
16
|
+
const COMPONENT_MAPPING = {
|
17
|
+
ActionButtonQuestion: ActionButtonComponent,
|
18
|
+
CalculatedFloatQuestion: FloatComponent,
|
19
|
+
ChoiceQuestion: RadioComponent,
|
20
|
+
DateQuestion: DateComponent,
|
21
|
+
DynamicChoiceQuestion: RadioComponent,
|
22
|
+
DynamicMultipleChoiceQuestion: CheckboxComponent,
|
23
|
+
FilesQuestion: FilesComponent,
|
24
|
+
FloatQuestion: FloatComponent,
|
25
|
+
IntegerQuestion: IntegerComponent,
|
26
|
+
MultipleChoiceQuestion: CheckboxComponent,
|
27
|
+
StaticQuestion: StaticComponent,
|
28
|
+
TableQuestion: TableComponent,
|
29
|
+
TextareaQuestion: TextareaComponent,
|
30
|
+
TextQuestion: TextComponent,
|
10
31
|
};
|
11
32
|
|
12
33
|
/**
|
@@ -16,17 +37,14 @@ const mapping = {
|
|
16
37
|
*/
|
17
38
|
export default class CfFieldInputComponent extends Component {
|
18
39
|
/**
|
19
|
-
* The input component
|
40
|
+
* The input component
|
20
41
|
*
|
21
|
-
* @property {
|
42
|
+
* @property {Component} inputComponent
|
22
43
|
* @accessor
|
23
44
|
*/
|
24
|
-
get
|
45
|
+
get inputComponent() {
|
25
46
|
const typename = this.args.field?.question.raw.__typename;
|
26
47
|
|
27
|
-
return (
|
28
|
-
typename &&
|
29
|
-
(mapping[typename] || dasherize(typename.replace(/Question$/, "")))
|
30
|
-
);
|
48
|
+
return ensureSafeComponent(COMPONENT_MAPPING[typename], this);
|
31
49
|
}
|
32
50
|
}
|
@@ -1,11 +1,13 @@
|
|
1
|
-
<label class="uk-form-label" for={{@field.pk}}>
|
1
|
+
<label class="uk-form-label" for={{@field.pk}} ...attributes>
|
2
2
|
<span class="uk-text-bold">
|
3
3
|
{{@field.question.raw.label}}
|
4
4
|
</span>
|
5
5
|
|
6
|
-
{{#if
|
6
|
+
{{#if (and (not @field.question.isCalculated) @field.optional)}}
|
7
7
|
<span
|
8
8
|
class="uk-margin-small-left uk-text-muted uk-text-lowercase uk-text-normal"
|
9
9
|
>({{t "caluma.form.optional"}})</span>
|
10
10
|
{{/if}}
|
11
|
+
|
12
|
+
{{yield}}
|
11
13
|
</label>
|
@@ -1,9 +1,24 @@
|
|
1
|
-
{{#if
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
1
|
+
{{#if (has-question-type @field.question "choice" "dynamic-choice")}}
|
2
|
+
{{@field.selected.label}}
|
3
|
+
{{else if (has-question-type
|
4
|
+
@field.question "multiple-choice" "multiple-dynamic-choice"
|
5
|
+
)}}
|
6
|
+
{{#each @field.selected as |opt i|}}{{if (gt i 0) ", "}}{{opt.label}}{{/each}}
|
7
|
+
{{else if (has-question-type @field.question "date")}}
|
8
|
+
{{format-date
|
9
|
+
@field.answer.value
|
10
|
+
day="2-digit"
|
11
|
+
month="2-digit"
|
12
|
+
year="numeric"
|
13
|
+
}}
|
14
|
+
{{else if (has-question-type @field.question "files")}}
|
15
|
+
{{#each @field.answer.value as |file|}}
|
16
|
+
<UkButton
|
17
|
+
@color="link"
|
18
|
+
@label={{file.name}}
|
19
|
+
@onClick={{fn this.download file.id}}
|
20
|
+
/>
|
21
|
+
{{/each}}
|
7
22
|
{{else}}
|
8
|
-
{{
|
23
|
+
{{@field.answer.value}}
|
9
24
|
{{/if}}
|
@@ -1,50 +1,26 @@
|
|
1
1
|
import { action } from "@ember/object";
|
2
2
|
import Component from "@glimmer/component";
|
3
3
|
import { queryManager } from "ember-apollo-client";
|
4
|
-
import moment from "moment";
|
5
4
|
|
6
|
-
import
|
5
|
+
import getFilesAnswerInfoQuery from "@projectcaluma/ember-form/gql/queries/filesanswer-info.graphql";
|
7
6
|
|
8
7
|
export default class CfFieldValueComponent extends Component {
|
9
8
|
@queryManager apollo;
|
10
9
|
|
11
|
-
get value() {
|
12
|
-
const field = this.args.field;
|
13
|
-
|
14
|
-
switch (field.questionType) {
|
15
|
-
case "ChoiceQuestion":
|
16
|
-
case "DynamicChoiceQuestion": {
|
17
|
-
return field.selected;
|
18
|
-
}
|
19
|
-
case "MultipleChoiceQuestion":
|
20
|
-
case "DynamicMultipleChoiceQuestion": {
|
21
|
-
return { label: field.selected.map(({ label }) => label).join(", ") };
|
22
|
-
}
|
23
|
-
case "FileQuestion": {
|
24
|
-
const answerValue = field.answer.value;
|
25
|
-
return {
|
26
|
-
fileAnswerId: answerValue && field.answer.raw.id,
|
27
|
-
label: answerValue?.name,
|
28
|
-
};
|
29
|
-
}
|
30
|
-
case "DateQuestion": {
|
31
|
-
return {
|
32
|
-
label: field.answer.value && moment(field.answer.value).format("L"),
|
33
|
-
};
|
34
|
-
}
|
35
|
-
|
36
|
-
default:
|
37
|
-
return { label: field.answer.value };
|
38
|
-
}
|
39
|
-
}
|
40
|
-
|
41
10
|
@action
|
42
11
|
async download(id) {
|
43
|
-
const
|
44
|
-
{
|
45
|
-
|
12
|
+
const files = await this.apollo.query(
|
13
|
+
{
|
14
|
+
query: getFilesAnswerInfoQuery,
|
15
|
+
variables: { id: this.args.field.answer.raw.id },
|
16
|
+
fetchPolicy: "network-only",
|
17
|
+
},
|
18
|
+
"node.value"
|
46
19
|
);
|
47
20
|
|
48
|
-
|
21
|
+
const { downloadUrl } = files?.find((file) => file.id === id);
|
22
|
+
if (downloadUrl) {
|
23
|
+
window.open(downloadUrl, "_blank");
|
24
|
+
}
|
49
25
|
}
|
50
26
|
}
|
@@ -1,12 +1,23 @@
|
|
1
1
|
{{#if this.visible}}
|
2
|
-
<div
|
2
|
+
<div
|
3
|
+
class="uk-margin
|
4
|
+
{{if
|
5
|
+
(and @disabled (has-question-type @field.question 'action-button'))
|
6
|
+
'uk-hidden'
|
7
|
+
}}"
|
8
|
+
{{did-insert this.registerComponent}}
|
9
|
+
{{will-destroy this.unregisterComponent}}
|
10
|
+
>
|
3
11
|
{{#if this.labelVisible}}
|
4
|
-
<CfField::
|
12
|
+
<CfField::Label @field={{@field}} />
|
5
13
|
{{/if}}
|
6
14
|
|
7
15
|
<div class="uk-flex">
|
8
16
|
<div class="uk-width-expand">
|
9
|
-
{{#let
|
17
|
+
{{#let
|
18
|
+
(component (ensure-safe-component (get-widget @field.question)))
|
19
|
+
as |FieldComponent|
|
20
|
+
}}
|
10
21
|
<FieldComponent
|
11
22
|
@field={{@field}}
|
12
23
|
@disabled={{@disabled}}
|
@@ -17,26 +28,48 @@
|
|
17
28
|
</div>
|
18
29
|
|
19
30
|
{{#if (and @field.question.raw.infoText this.infoTextVisible)}}
|
20
|
-
<CfField::
|
31
|
+
<CfField::Info @text={{@field.question.raw.infoText}} />
|
21
32
|
{{/if}}
|
22
33
|
|
23
34
|
{{#if this.saveIndicatorVisible}}
|
24
35
|
<div
|
25
36
|
class="cf-field__icon uk-padding-remove-vertical uk-flex uk-flex-middle uk-flex-center"
|
26
37
|
>
|
27
|
-
{{#if
|
38
|
+
{{#if this.save.isRunning}}
|
28
39
|
<UkSpinner class="uk-animation-fade" />
|
29
|
-
{{else if (or
|
30
|
-
<
|
31
|
-
|
40
|
+
{{else if (or this.save.last.isError @field.isInvalid)}}
|
41
|
+
<div class="uk-flex-inline">
|
42
|
+
<UkIcon
|
43
|
+
@icon="warning"
|
44
|
+
class="uk-animation-fade uk-text-danger"
|
45
|
+
/>
|
46
|
+
{{#if this.save.last.error}}
|
47
|
+
<div uk-dropdown="pos: bottom-left" class="uk-padding-small">
|
48
|
+
<div class="uk-alert uk-alert-danger uk-margin-small">
|
49
|
+
{{t "caluma.form.error.intro"}}
|
50
|
+
</div>
|
51
|
+
<p class="uk-text-meta uk-margin-small">
|
52
|
+
{{t "caluma.form.error.details"}}
|
53
|
+
</p>
|
54
|
+
<pre class="uk-margin-remove">
|
55
|
+
{{~format-graphql-error this.save.last.error~}}
|
56
|
+
</pre>
|
57
|
+
</div>
|
58
|
+
{{/if}}
|
59
|
+
</div>
|
60
|
+
{{else if this.save.last.isSuccessful}}
|
32
61
|
<UkIcon @icon="check" class="uk-animation-fade uk-text-success" />
|
33
62
|
{{/if}}
|
34
63
|
</div>
|
35
64
|
{{/if}}
|
36
65
|
</div>
|
37
66
|
|
67
|
+
{{#if (and @field.question.raw.hintText this.hintTextVisible)}}
|
68
|
+
<CfField::Hint @field={{@field}} />
|
69
|
+
{{/if}}
|
70
|
+
|
38
71
|
{{#if @field.errors.length}}
|
39
|
-
<CfField::
|
72
|
+
<CfField::Errors @field={{@field}} />
|
40
73
|
{{/if}}
|
41
74
|
</div>
|
42
75
|
{{/if}}
|