@projectcaluma/ember-form 10.0.1 → 11.0.0-beta.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. package/CHANGELOG.md +1181 -0
  2. package/addon/components/cf-content.hbs +36 -41
  3. package/addon/components/cf-content.js +48 -29
  4. package/addon/components/cf-field/info.hbs +2 -2
  5. package/addon/components/cf-field/info.js +0 -15
  6. package/addon/components/cf-field/input/action-button.hbs +18 -19
  7. package/addon/components/cf-field/input/action-button.js +9 -7
  8. package/addon/components/cf-field/input/checkbox.hbs +6 -2
  9. package/addon/components/cf-field/input/checkbox.js +9 -29
  10. package/addon/components/cf-field/input/date.hbs +8 -5
  11. package/addon/components/cf-field/input/date.js +28 -10
  12. package/addon/components/cf-field/input/file.hbs +2 -2
  13. package/addon/components/cf-field/input/file.js +10 -11
  14. package/addon/components/cf-field/input/float.hbs +4 -4
  15. package/addon/components/cf-field/input/integer.hbs +5 -5
  16. package/addon/components/cf-field/input/radio.hbs +4 -1
  17. package/addon/components/cf-field/input/static.hbs +1 -1
  18. package/addon/components/cf-field/input/table.hbs +24 -24
  19. package/addon/components/cf-field/input/table.js +12 -10
  20. package/addon/components/cf-field/input/text.hbs +5 -5
  21. package/addon/components/cf-field/input/textarea.hbs +6 -5
  22. package/addon/components/cf-field/input.hbs +10 -1
  23. package/addon/components/cf-field/input.js +1 -1
  24. package/addon/components/cf-field/label.hbs +1 -1
  25. package/addon/components/cf-field-value.hbs +22 -7
  26. package/addon/components/cf-field-value.js +8 -38
  27. package/addon/components/cf-field.hbs +14 -6
  28. package/addon/components/cf-field.js +22 -8
  29. package/addon/components/cf-navigation-item.hbs +2 -2
  30. package/addon/components/cf-navigation.hbs +4 -1
  31. package/addon/components/document-validity.js +17 -2
  32. package/addon/gql/fragments/field.graphql +45 -0
  33. package/addon/gql/mutations/save-document-table-answer.graphql +1 -1
  34. package/addon/gql/mutations/save-document.graphql +1 -0
  35. package/addon/gql/queries/{get-document-answers.graphql → document-answers.graphql} +2 -1
  36. package/addon/gql/queries/{get-document-forms.graphql → document-forms.graphql} +2 -1
  37. package/addon/gql/queries/{get-document-used-dynamic-options.graphql → document-used-dynamic-options.graphql} +2 -1
  38. package/addon/gql/queries/{get-dynamic-options.graphql → dynamic-options.graphql} +2 -1
  39. package/addon/gql/queries/{get-fileanswer-info.graphql → fileanswer-info.graphql} +2 -1
  40. package/addon/helpers/get-widget.js +50 -0
  41. package/addon/lib/answer.js +108 -72
  42. package/addon/lib/base.js +32 -23
  43. package/addon/lib/dependencies.js +36 -71
  44. package/addon/lib/document.js +92 -96
  45. package/addon/lib/field.js +374 -407
  46. package/addon/lib/fieldset.js +46 -47
  47. package/addon/lib/form.js +27 -15
  48. package/addon/lib/navigation.js +211 -192
  49. package/addon/lib/question.js +103 -94
  50. package/addon/services/caluma-store.js +10 -6
  51. package/app/helpers/get-widget.js +4 -0
  52. package/blueprints/@projectcaluma/ember-form/index.js +1 -0
  53. package/package.json +30 -25
  54. package/addon/components/cf-navigation.js +0 -9
  55. package/addon/instance-initializers/setup-pikaday-i18n.js +0 -35
@@ -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
- <button
29
- data-test-edit-row
30
- type="button"
31
- class="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
- {{on "click" (fn this.edit document)}}
32
+ class="uk-flex-inline uk-margin-small-left"
33
+ data-test-edit-row
34
34
  >
35
35
  <UkIcon @icon="pencil" />
36
- <span class="uk-hidden">{{t "caluma.form.edit"}}</span>
37
- </button>
36
+ <span hidden>{{t "caluma.form.edit"}}</span>
37
+ </UkButton>
38
38
  {{#unless @disabled}}
39
- <button
40
- data-test-delete-row
41
- type="button"
42
- class="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
- {{on "click" (fn (perform this.delete) document)}}
43
+ class="uk-flex-inline uk-margin-small-left"
44
+ data-test-delete-row
45
45
  >
46
46
  <UkIcon @icon="trash" />
47
- <span class="uk-hidden">{{t "caluma.form.delete"}}</span>
48
- </button>
47
+ <span hidden>{{t "caluma.form.delete"}}</span>
48
+ </UkButton>
49
49
  {{/unless}}
50
50
  </div>
51
51
  </td>
@@ -57,13 +57,13 @@
57
57
  <tr>
58
58
  <td colspan={{add this.columns.length 1}} class="uk-text-center">
59
59
  <UkButton
60
- @size="small"
61
- @color="default"
62
- @on-click={{perform this.add}}
60
+ @color="link"
61
+ @onClick={{perform this.add}}
62
+ title={{t "caluma.form.addRow"}}
63
63
  data-test-add-row
64
64
  >
65
65
  <UkIcon @icon="plus" />
66
- <span class="uk-hidden">{{t "caluma.form.addRow"}}</span>
66
+ <span hidden>{{t "caluma.form.addRow"}}</span>
67
67
  </UkButton>
68
68
  </td>
69
69
  </tr>
@@ -74,7 +74,7 @@
74
74
  {{#if this.documentToEdit}}
75
75
  <UkModal
76
76
  @visible={{this.showAddModal}}
77
- @on-hide={{perform this.closeModal}}
77
+ @onHide={{perform this.close}}
78
78
  @bgClose={{false}}
79
79
  as |modal|
80
80
  >
@@ -86,12 +86,12 @@
86
86
  />
87
87
  </modal.body>
88
88
 
89
- <modal.footer @class="uk-text-right">
89
+ <modal.footer class="uk-text-right">
90
90
  {{#if @disabled}}
91
91
  <UkButton
92
92
  @label={{t "caluma.form.close"}}
93
93
  @color="primary"
94
- @on-click={{perform this.close}}
94
+ @onClick={{perform this.close}}
95
95
  @disabled={{this.close.isRunning}}
96
96
  @loading={{this.close.isRunning}}
97
97
  data-test-close
@@ -99,7 +99,7 @@
99
99
  {{else}}
100
100
  <UkButton
101
101
  @label={{t "caluma.form.cancel"}}
102
- @on-click={{perform this.close}}
102
+ @onClick={{perform this.close}}
103
103
  @disabled={{this.close.isRunning}}
104
104
  @loading={{this.close.isRunning}}
105
105
  data-test-cancel
@@ -114,7 +114,7 @@
114
114
  @type="submit"
115
115
  @disabled={{or this.save.isRunning (not isValid)}}
116
116
  @loading={{this.save.isRunning}}
117
- @on-click={{fn (perform this.save) validate}}
117
+ @onClick={{fn (perform this.save) validate}}
118
118
  data-test-save
119
119
  />
120
120
  </DocumentValidity>
@@ -4,7 +4,7 @@ import { inject as service } from "@ember/service";
4
4
  import Component from "@glimmer/component";
5
5
  import { tracked } from "@glimmer/tracking";
6
6
  import { queryManager } from "ember-apollo-client";
7
- import { dropTask } from "ember-concurrency-decorators";
7
+ import { dropTask } from "ember-concurrency";
8
8
  import UIkit from "uikit";
9
9
 
10
10
  import removeDocumentMutation from "@projectcaluma/ember-form/gql/mutations/remove-document.graphql";
@@ -37,13 +37,13 @@ export default class CfFieldInputTableComponent extends Component {
37
37
  }
38
38
 
39
39
  get questions() {
40
- return this.args.field.question.rowForm.questions.edges.map(
40
+ return this.args.field.question.raw.rowForm.questions.edges.map(
41
41
  (edge) => edge.node
42
42
  );
43
43
  }
44
44
 
45
45
  get columns() {
46
- const config = this.args.field.question.meta.columnsToDisplay;
46
+ const config = this.args.field.question.raw.meta.columnsToDisplay;
47
47
 
48
48
  if (config?.length) {
49
49
  return this.questions.filter((question) =>
@@ -59,17 +59,19 @@ export default class CfFieldInputTableComponent extends Component {
59
59
  const raw = yield this.apollo.mutate(
60
60
  {
61
61
  mutation: saveDocumentMutation,
62
- variables: { input: { form: this.args.field.question.rowForm.slug } },
62
+ variables: {
63
+ input: { form: this.args.field.question.raw.rowForm.slug },
64
+ },
63
65
  },
64
66
  "saveDocument.document"
65
67
  );
66
68
 
67
- const newDocument = getOwner(this)
68
- .factoryFor("caluma-model:document")
69
- .create({
70
- raw: this.parseDocument(raw),
71
- parentDocument: this.args.field.document,
72
- });
69
+ const owner = getOwner(this);
70
+ const newDocument = new (owner.factoryFor("caluma-model:document").class)({
71
+ raw: this.parseDocument(raw),
72
+ parentDocument: this.args.field.document,
73
+ owner,
74
+ });
73
75
 
74
76
  this.documentToEditIsNew = true;
75
77
  this.documentToEdit = newDocument;
@@ -1,14 +1,14 @@
1
1
  <input
2
2
  type="text"
3
3
  class="uk-input
4
- {{if @field.isInvalid "uk-form-danger"}}
5
- {{if @disabled "uk-disabled"}}"
4
+ {{if @field.isInvalid 'uk-form-danger'}}
5
+ {{if @disabled 'uk-disabled'}}"
6
6
  name={{@field.pk}}
7
7
  id={{@field.pk}}
8
8
  value={{@field.answer.value}}
9
- placeholder={{@field.question.placeholder}}
9
+ placeholder={{@field.question.raw.placeholder}}
10
10
  readonly={{@disabled}}
11
- minlength={{@field.question.textMinLength}}
12
- maxlength={{@field.question.textMaxLength}}
11
+ minlength={{@field.question.raw.textMinLength}}
12
+ maxlength={{@field.question.raw.textMaxLength}}
13
13
  {{on "input" this.input}}
14
14
  />
@@ -1,12 +1,13 @@
1
1
  <textarea
2
2
  class="uk-textarea
3
- {{if @field.isInvalid "uk-form-danger"}}
4
- {{if @disabled "uk-disabled"}}"
3
+ {{if @field.isInvalid 'uk-form-danger'}}
4
+ {{if @disabled 'uk-disabled'}}"
5
5
  name={{@field.pk}}
6
6
  id={{@field.pk}}
7
- placeholder={{@field.question.placeholder}}
8
- minlength={{@field.question.textareaMinLength}}
9
- maxlength={{@field.question.textareaMaxLength}}
7
+ placeholder={{@field.question.raw.placeholder}}
8
+ minlength={{@field.question.raw.textareaMinLength}}
9
+ maxlength={{@field.question.raw.textareaMaxLength}}
10
10
  readonly={{@disabled}}
11
11
  {{on "input" this.input}}
12
+ {{autoresize mode="height"}}
12
13
  >{{@field.answer.value}}</textarea>
@@ -1,6 +1,15 @@
1
1
  {{#if this.type}}
2
2
  {{#let (component (concat "cf-field/input/" this.type)) as |InputComponent|}}
3
- <div class="uk-form-controls">
3
+ <div
4
+ class="uk-form-controls
5
+ {{if
6
+ (and
7
+ (has-question-type @field.question 'multiple-choice' 'choice')
8
+ @field.question.raw.meta.vertical
9
+ )
10
+ 'uk-flex'
11
+ }}"
12
+ >
4
13
  <InputComponent
5
14
  @field={{@field}}
6
15
  @disabled={{@disabled}}
@@ -22,7 +22,7 @@ export default class CfFieldInputComponent extends Component {
22
22
  * @accessor
23
23
  */
24
24
  get type() {
25
- const typename = this.args.field?.question.__typename;
25
+ const typename = this.args.field?.question.raw.__typename;
26
26
 
27
27
  return (
28
28
  typename &&
@@ -1,6 +1,6 @@
1
1
  <label class="uk-form-label" for={{@field.pk}}>
2
2
  <span class="uk-text-bold">
3
- {{@field.question.label}}
3
+ {{@field.question.raw.label}}
4
4
  </span>
5
5
 
6
6
  {{#if this.optional}}
@@ -1,9 +1,24 @@
1
- {{#if this.value.fileAnswerId}}
2
- <UkButton
3
- @color="link"
4
- @label={{this.value.label}}
5
- @on-click={{fn this.download this.value.fileAnswerId}}
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 "file")}}
15
+ {{#if @field.answer.value}}
16
+ <UkButton
17
+ @color="link"
18
+ @label={{@field.answer.value.name}}
19
+ @onClick={{fn this.download @field.answer.raw.id}}
20
+ />
21
+ {{/if}}
7
22
  {{else}}
8
- {{this.value.label}}
23
+ {{@field.answer.value}}
9
24
  {{/if}}
@@ -1,55 +1,25 @@
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 getFileAnswerInfoQuery from "@projectcaluma/ember-form/gql/queries/get-fileanswer-info.graphql";
5
+ import getFileAnswerInfoQuery from "@projectcaluma/ember-form/gql/queries/fileanswer-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.question.__typename) {
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.id,
27
- label: answerValue && 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 {
38
- label: field.answer.value,
39
- };
40
- }
41
- }
42
-
43
10
  @action
44
- async download(fileAnswerId) {
11
+ async download(id) {
45
12
  const { downloadUrl } = await this.apollo.query(
46
13
  {
47
14
  query: getFileAnswerInfoQuery,
48
- variables: { id: fileAnswerId },
49
- fetchPolicy: "cache-and-network",
15
+ variables: { id },
16
+ fetchPolicy: "network-only",
50
17
  },
51
18
  "node.fileValue"
52
19
  );
53
- window.open(downloadUrl, "_blank");
20
+
21
+ if (downloadUrl) {
22
+ window.open(downloadUrl, "_blank");
23
+ }
54
24
  }
55
25
  }
@@ -1,5 +1,13 @@
1
1
  {{#if this.visible}}
2
- <div class="uk-margin">
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
12
  <CfField::label @field={{@field}} />
5
13
  {{/if}}
@@ -16,19 +24,19 @@
16
24
  {{/let}}
17
25
  </div>
18
26
 
19
- {{#if (and @field.question.infoText this.infoTextVisible)}}
20
- <CfField::info @text={{@field.question.infoText}} />
27
+ {{#if (and @field.question.raw.infoText this.infoTextVisible)}}
28
+ <CfField::info @text={{@field.question.raw.infoText}} />
21
29
  {{/if}}
22
30
 
23
31
  {{#if this.saveIndicatorVisible}}
24
32
  <div
25
33
  class="cf-field__icon uk-padding-remove-vertical uk-flex uk-flex-middle uk-flex-center"
26
34
  >
27
- {{#if @field.save.isRunning}}
35
+ {{#if this.save.isRunning}}
28
36
  <UkSpinner class="uk-animation-fade" />
29
- {{else if (or @field.save.last.isError @field.isInvalid)}}
37
+ {{else if (or this.save.last.isError @field.isInvalid)}}
30
38
  <UkIcon @icon="warning" class="uk-animation-fade uk-text-danger" />
31
- {{else if @field.save.last.isSuccessful}}
39
+ {{else if this.save.last.isSuccessful}}
32
40
  <UkIcon @icon="check" class="uk-animation-fade uk-text-success" />
33
41
  {{/if}}
34
42
  </div>
@@ -1,8 +1,7 @@
1
1
  import { getOwner } from "@ember/application";
2
- import { set } from "@ember/object";
2
+ import { action } 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
 
@@ -19,6 +18,16 @@ import { hasQuestionType } from "@projectcaluma/ember-core/helpers/has-question-
19
18
  * @argument {Field} field The field data model to render
20
19
  */
21
20
  export default class CfFieldComponent extends Component {
21
+ @action
22
+ registerComponent() {
23
+ this.args.field._components.add(this);
24
+ }
25
+
26
+ @action
27
+ unregisterComponent() {
28
+ this.args.field._components.delete(this);
29
+ }
30
+
22
31
  get visible() {
23
32
  return (
24
33
  !this.args.field?.hidden &&
@@ -28,7 +37,7 @@ export default class CfFieldComponent extends Component {
28
37
 
29
38
  get labelVisible() {
30
39
  return (
31
- !this.args.field?.question.meta.hideLabel &&
40
+ !this.args.field?.question.raw.meta.hideLabel &&
32
41
  !hasQuestionType(this.args.field?.question, "static", "action-button")
33
42
  );
34
43
  }
@@ -42,8 +51,9 @@ export default class CfFieldComponent extends Component {
42
51
  }
43
52
 
44
53
  /**
45
- * Task to save a field. This will set the passed value to the answer and
46
- * save the field to the API after a timeout off 500 milliseconds.
54
+ * Task to save a field. This will set the passed value to the answer and save
55
+ * the field to the API after a timeout of 500 milliseconds which intends to
56
+ * reduce the amount of saved values when changed rapidly.
47
57
  *
48
58
  * @method save
49
59
  * @param {String|Number|String[]} value
@@ -58,14 +68,18 @@ export default class CfFieldComponent extends Component {
58
68
  yield timeout(500);
59
69
  }
60
70
 
61
- set(this.args.field.answer, "value", value);
71
+ if (this.args.field.answer) {
72
+ this.args.field.answer.value = value;
73
+ }
62
74
 
63
75
  yield this.args.field.validate.perform();
64
76
 
65
77
  try {
78
+ // Save the new field value unlinked so the fields save task is not
79
+ // aborted when this component is destroyed
66
80
  return yield this.args.field.save.unlinked().perform();
67
81
  } catch (e) {
68
- // that's ok
82
+ // The component was destroyed before the fields save task was finished
69
83
  }
70
84
  }
71
85
  }
@@ -1,6 +1,6 @@
1
1
  <li
2
2
  class="cf-navigation__item uk-width-auto
3
- {{if (or @item.active @item.childrenActive) "uk-active"}}"
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 "cf-navigation__item__icon--dirty"}}"
22
+ {{if @item.dirty 'cf-navigation__item__icon--dirty'}}"
23
23
  ></span>
24
24
  </LinkTo>
25
25
 
@@ -1,4 +1,7 @@
1
- <ul class="uk-tab uk-tab-left uk-width-auto" {{did-insert this.goToNextItem}}>
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}}
@@ -1,6 +1,7 @@
1
1
  import { action } from "@ember/object";
2
2
  import Component from "@glimmer/component";
3
- import { restartableTask } from "ember-concurrency-decorators";
3
+ import { restartableTask } from "ember-concurrency";
4
+ import { cached } from "tracked-toolbox";
4
5
 
5
6
  /**
6
7
  * Component to check the validity of a document
@@ -31,12 +32,26 @@ export default class DocumentValidity extends Component {
31
32
  * @argument {Boolean} validateOnEnter
32
33
  */
33
34
 
35
+ @cached
34
36
  get isValid() {
35
- return this.args.document.fields.every((f) => f.isValid);
37
+ return this.args.document.fields
38
+ .filter((f) => !f.hidden)
39
+ .every((f) => f.isValid);
36
40
  }
37
41
 
38
42
  @restartableTask
39
43
  *_validate() {
44
+ const saveTasks = this.args.document.fields
45
+ .flatMap((field) => [
46
+ ...[...(field._components ?? [])].map((c) => c.save.last),
47
+ field.save?.last,
48
+ ])
49
+ .filter(Boolean);
50
+
51
+ // Wait until all currently running save tasks in the UI and in the field
52
+ // itself are finished
53
+ yield Promise.all(saveTasks);
54
+
40
55
  for (const field of this.args.document.fields) {
41
56
  yield field.validate.linked().perform();
42
57
  }
@@ -1,4 +1,10 @@
1
+ # We can not symlink this file so an exact copy exists in another package:
2
+ # packages/form-builder/addon/gql/fragments/field.graphql
3
+ #
4
+ # When changing this file the other must also receive the same changes.
5
+
1
6
  fragment SimpleQuestion on Question {
7
+ id
2
8
  slug
3
9
  label
4
10
  isRequired
@@ -9,22 +15,43 @@ fragment SimpleQuestion on Question {
9
15
  textMinLength: minLength
10
16
  textMaxLength: maxLength
11
17
  textDefaultAnswer: defaultAnswer {
18
+ id
12
19
  value
13
20
  }
14
21
  placeholder
22
+ formatValidators {
23
+ edges {
24
+ node {
25
+ slug
26
+ regex
27
+ errorMsg
28
+ }
29
+ }
30
+ }
15
31
  }
16
32
  ... on TextareaQuestion {
17
33
  textareaMinLength: minLength
18
34
  textareaMaxLength: maxLength
19
35
  textareaDefaultAnswer: defaultAnswer {
36
+ id
20
37
  value
21
38
  }
22
39
  placeholder
40
+ formatValidators {
41
+ edges {
42
+ node {
43
+ slug
44
+ regex
45
+ errorMsg
46
+ }
47
+ }
48
+ }
23
49
  }
24
50
  ... on IntegerQuestion {
25
51
  integerMinValue: minValue
26
52
  integerMaxValue: maxValue
27
53
  integerDefaultAnswer: defaultAnswer {
54
+ id
28
55
  value
29
56
  }
30
57
  placeholder
@@ -33,6 +60,7 @@ fragment SimpleQuestion on Question {
33
60
  floatMinValue: minValue
34
61
  floatMaxValue: maxValue
35
62
  floatDefaultAnswer: defaultAnswer {
63
+ id
36
64
  value
37
65
  }
38
66
  placeholder
@@ -41,6 +69,7 @@ fragment SimpleQuestion on Question {
41
69
  choiceOptions: options {
42
70
  edges {
43
71
  node {
72
+ id
44
73
  slug
45
74
  label
46
75
  isArchived
@@ -48,6 +77,7 @@ fragment SimpleQuestion on Question {
48
77
  }
49
78
  }
50
79
  choiceDefaultAnswer: defaultAnswer {
80
+ id
51
81
  value
52
82
  }
53
83
  }
@@ -55,6 +85,7 @@ fragment SimpleQuestion on Question {
55
85
  multipleChoiceOptions: options {
56
86
  edges {
57
87
  node {
88
+ id
58
89
  slug
59
90
  label
60
91
  isArchived
@@ -62,11 +93,13 @@ fragment SimpleQuestion on Question {
62
93
  }
63
94
  }
64
95
  multipleChoiceDefaultAnswer: defaultAnswer {
96
+ id
65
97
  value
66
98
  }
67
99
  }
68
100
  ... on DateQuestion {
69
101
  dateDefaultAnswer: defaultAnswer {
102
+ id
70
103
  value
71
104
  }
72
105
  }
@@ -84,8 +117,10 @@ fragment SimpleQuestion on Question {
84
117
  }
85
118
 
86
119
  fragment FieldTableQuestion on Question {
120
+ id
87
121
  ... on TableQuestion {
88
122
  rowForm {
123
+ id
89
124
  slug
90
125
  questions {
91
126
  edges {
@@ -96,6 +131,7 @@ fragment FieldTableQuestion on Question {
96
131
  }
97
132
  }
98
133
  tableDefaultAnswer: defaultAnswer {
134
+ id
99
135
  value {
100
136
  id
101
137
  answers {
@@ -103,6 +139,7 @@ fragment FieldTableQuestion on Question {
103
139
  node {
104
140
  id
105
141
  question {
142
+ id
106
143
  slug
107
144
  }
108
145
  ... on StringAnswer {
@@ -129,10 +166,12 @@ fragment FieldTableQuestion on Question {
129
166
  }
130
167
 
131
168
  fragment FieldQuestion on Question {
169
+ id
132
170
  ...SimpleQuestion
133
171
  ...FieldTableQuestion
134
172
  ... on FormQuestion {
135
173
  subForm {
174
+ id
136
175
  slug
137
176
  name
138
177
  questions {
@@ -140,10 +179,12 @@ fragment FieldQuestion on Question {
140
179
  node {
141
180
  # This part here limits our query to 2 level deep nested forms. This
142
181
  # has to be solved in another way!
182
+ id
143
183
  ...SimpleQuestion
144
184
  ...FieldTableQuestion
145
185
  ... on FormQuestion {
146
186
  subForm {
187
+ id
147
188
  slug
148
189
  name
149
190
  questions {
@@ -166,6 +207,7 @@ fragment FieldQuestion on Question {
166
207
  fragment SimpleAnswer on Answer {
167
208
  id
168
209
  question {
210
+ id
169
211
  slug
170
212
  }
171
213
  ... on StringAnswer {
@@ -182,6 +224,7 @@ fragment SimpleAnswer on Answer {
182
224
  }
183
225
  ... on FileAnswer {
184
226
  fileValue: value {
227
+ id
185
228
  uploadUrl
186
229
  downloadUrl
187
230
  metadata
@@ -194,11 +237,13 @@ fragment SimpleAnswer on Answer {
194
237
  }
195
238
 
196
239
  fragment FieldAnswer on Answer {
240
+ id
197
241
  ...SimpleAnswer
198
242
  ... on TableAnswer {
199
243
  tableValue: value {
200
244
  id
201
245
  form {
246
+ id
202
247
  slug
203
248
  questions {
204
249
  edges {