@projectcaluma/ember-form-builder 11.0.0-beta.1 → 11.0.0-beta.12

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.
Files changed (57) hide show
  1. package/CHANGELOG.md +1181 -0
  2. package/addon/components/cfb-code-editor.hbs +2 -1
  3. package/addon/components/cfb-code-editor.js +59 -11
  4. package/addon/components/cfb-form-editor/general.hbs +2 -4
  5. package/addon/components/cfb-form-editor/general.js +5 -7
  6. package/addon/components/cfb-form-editor/question/options.hbs +1 -1
  7. package/addon/components/cfb-form-editor/question/validation.hbs +3 -2
  8. package/addon/components/cfb-form-editor/question/validation.js +17 -13
  9. package/addon/components/cfb-form-editor/question-list/item.hbs +4 -4
  10. package/addon/components/cfb-form-editor/question-list/item.js +2 -2
  11. package/addon/components/cfb-form-editor/question-list.hbs +6 -6
  12. package/addon/components/cfb-form-editor/question-list.js +11 -6
  13. package/addon/components/cfb-form-editor/question.hbs +31 -15
  14. package/addon/components/cfb-form-editor/question.js +44 -20
  15. package/addon/components/cfb-form-editor.hbs +5 -5
  16. package/addon/components/cfb-form-list/item.hbs +1 -1
  17. package/addon/components/cfb-form-list.hbs +9 -9
  18. package/addon/components/cfb-form-list.js +44 -11
  19. package/addon/components/cfb-toggle-switch.hbs +1 -1
  20. package/addon/controllers/index.js +6 -0
  21. package/addon/engine.js +8 -11
  22. package/addon/gql/fragments/field.graphql +12 -0
  23. package/addon/gql/mutations/save-calculated-float-question.graphql +1 -0
  24. package/addon/gql/mutations/save-choice-question.graphql +1 -0
  25. package/addon/gql/mutations/save-date-question.graphql +3 -0
  26. package/addon/gql/mutations/save-dynamic-choice-question.graphql +1 -0
  27. package/addon/gql/mutations/save-dynamic-multiple-choice-question.graphql +1 -0
  28. package/addon/gql/mutations/save-file-question.graphql +3 -0
  29. package/addon/gql/mutations/save-float-question.graphql +1 -0
  30. package/addon/gql/mutations/save-integer-question.graphql +1 -0
  31. package/addon/gql/mutations/save-multiple-choice-question.graphql +1 -0
  32. package/addon/gql/mutations/save-table-question.graphql +1 -0
  33. package/addon/gql/mutations/save-text-question.graphql +1 -0
  34. package/addon/gql/mutations/save-textarea-question.graphql +1 -0
  35. package/addon/gql/queries/all-format-validators.graphql +10 -0
  36. package/addon/gql/queries/form-editor-question.graphql +28 -0
  37. package/addon/instance-initializers/form-builder-widget-overrides.js +15 -0
  38. package/addon/modifiers/pikaday.js +2 -0
  39. package/addon/templates/edit/questions/edit.hbs +1 -1
  40. package/addon/templates/edit/questions/new.hbs +1 -4
  41. package/addon/templates/edit.hbs +5 -5
  42. package/addon/templates/index.hbs +8 -1
  43. package/addon/templates/new.hbs +1 -1
  44. package/addon/utils/and.js +47 -0
  45. package/addon/utils/or.js +40 -0
  46. package/addon/validations/option.js +1 -1
  47. package/addon/validations/question.js +8 -2
  48. package/addon/validators/slug.js +1 -1
  49. package/app/instance-initializers/form-builder-widget-overrides.js +4 -0
  50. package/app/styles/@projectcaluma/ember-form-builder.scss +1 -1
  51. package/app/utils/and.js +1 -0
  52. package/app/utils/or.js +1 -0
  53. package/index.js +4 -8
  54. package/package.json +39 -30
  55. package/translations/de.yaml +6 -5
  56. package/translations/en.yaml +3 -2
  57. package/translations/fr.yaml +154 -1
@@ -1,16 +1,14 @@
1
- import { getOwner } from "@ember/application";
2
1
  import { A } from "@ember/array";
3
2
  import { action } from "@ember/object";
4
3
  import { inject as service } from "@ember/service";
5
4
  import { camelize } from "@ember/string";
5
+ import { macroCondition, isTesting } from "@embroider/macros";
6
6
  import Component from "@glimmer/component";
7
7
  import { tracked } from "@glimmer/tracking";
8
8
  import { queryManager } from "ember-apollo-client";
9
9
  import Changeset from "ember-changeset";
10
10
  import lookupValidator from "ember-changeset-validations";
11
- import { optional } from "ember-composable-helpers/helpers/optional";
12
11
  import { dropTask, restartableTask, task, timeout } from "ember-concurrency";
13
- import { all } from "rsvp";
14
12
 
15
13
  import { hasQuestionType } from "@projectcaluma/ember-core/helpers/has-question-type";
16
14
  import slugify from "@projectcaluma/ember-core/utils/slugify";
@@ -107,6 +105,7 @@ export default class CfbFormEditorQuestion extends Component {
107
105
  subForm: {},
108
106
  meta: {},
109
107
  dataSource: "",
108
+ formatValidators: null,
110
109
  // action button
111
110
  action: ACTIONS[0],
112
111
  color: COLORS[0],
@@ -183,16 +182,10 @@ export default class CfbFormEditorQuestion extends Component {
183
182
 
184
183
  get availableOverrides() {
185
184
  const type = this.changeset.get("__typename");
186
- const overrides = this.calumaOptions
187
- .getComponentOverrides()
188
- .filter((override) => {
189
- return !override.types || override.types.includes(type);
190
- });
191
185
 
192
- return [
193
- { label: this.intl.t("caluma.form.power-select.null"), component: "" },
194
- ...overrides,
195
- ];
186
+ return this.calumaOptions.getComponentOverrides().filter((override) => {
187
+ return !override.types || override.types.includes(type);
188
+ });
196
189
  }
197
190
 
198
191
  get model() {
@@ -213,16 +206,20 @@ export default class CfbFormEditorQuestion extends Component {
213
206
  const slug =
214
207
  ((!this.args.slug && this.prefix) || "") + changeset.get("slug");
215
208
 
209
+ const rawMeta = changeset.get("meta");
210
+
216
211
  const input = {
217
212
  slug,
218
213
  label: changeset.get("label"),
219
214
  isHidden: changeset.get("isHidden"),
220
215
  infoText: changeset.get("infoText"),
221
- meta: JSON.stringify(changeset.get("meta").unwrap()),
216
+ meta: JSON.stringify(rawMeta?.unwrap?.() ?? rawMeta),
222
217
  isArchived: changeset.get("isArchived"),
223
218
  };
224
219
 
225
- if (!hasQuestionType(changeset, "static", "calculated-float")) {
220
+ if (
221
+ !hasQuestionType(changeset, "static", "calculated-float", "action-button")
222
+ ) {
226
223
  Object.assign(input, {
227
224
  isRequired: changeset.get("isRequired"),
228
225
  });
@@ -241,6 +238,7 @@ export default class CfbFormEditorQuestion extends Component {
241
238
  minValue: parseInt(changeset.get("integerMinValue")),
242
239
  maxValue: parseInt(changeset.get("integerMaxValue")),
243
240
  placeholder: changeset.get("placeholder"),
241
+ hintText: changeset.get("hintText"),
244
242
  };
245
243
  }
246
244
 
@@ -249,6 +247,7 @@ export default class CfbFormEditorQuestion extends Component {
249
247
  minValue: parseFloat(changeset.get("floatMinValue")),
250
248
  maxValue: parseFloat(changeset.get("floatMaxValue")),
251
249
  placeholder: changeset.get("placeholder"),
250
+ hintText: changeset.get("hintText"),
252
251
  };
253
252
  }
254
253
 
@@ -257,6 +256,10 @@ export default class CfbFormEditorQuestion extends Component {
257
256
  minLength: parseInt(changeset.get("minLength")),
258
257
  maxLength: parseInt(changeset.get("maxLength")),
259
258
  placeholder: changeset.get("placeholder"),
259
+ formatValidators: changeset
260
+ .get("formatValidators")
261
+ ?.edges.map((edge) => edge.node.slug),
262
+ hintText: changeset.get("hintText"),
260
263
  };
261
264
  }
262
265
 
@@ -265,36 +268,51 @@ export default class CfbFormEditorQuestion extends Component {
265
268
  minLength: parseInt(changeset.get("minLength")),
266
269
  maxLength: parseInt(changeset.get("maxLength")),
267
270
  placeholder: changeset.get("placeholder"),
271
+ formatValidators: changeset
272
+ .get("formatValidators")
273
+ ?.edges.map((edge) => edge.node.slug),
274
+ hintText: changeset.get("hintText"),
275
+ };
276
+ }
277
+
278
+ _getDateQuestionInput(changeset) {
279
+ return {
280
+ hintText: changeset.get("hintText"),
268
281
  };
269
282
  }
270
283
 
271
284
  _getMultipleChoiceQuestionInput(changeset) {
272
285
  return {
273
286
  options: changeset.get("options.edges").map(({ node: { slug } }) => slug),
287
+ hintText: changeset.get("hintText"),
274
288
  };
275
289
  }
276
290
 
277
291
  _getChoiceQuestionInput(changeset) {
278
292
  return {
279
293
  options: changeset.get("options.edges").map(({ node: { slug } }) => slug),
294
+ hintText: changeset.get("hintText"),
280
295
  };
281
296
  }
282
297
 
283
298
  _getDynamicMultipleChoiceQuestionInput(changeset) {
284
299
  return {
285
300
  dataSource: changeset.get("dataSource"),
301
+ hintText: changeset.get("hintText"),
286
302
  };
287
303
  }
288
304
 
289
305
  _getDynamicChoiceQuestionInput(changeset) {
290
306
  return {
291
307
  dataSource: changeset.get("dataSource"),
308
+ hintText: changeset.get("hintText"),
292
309
  };
293
310
  }
294
311
 
295
312
  _getTableQuestionInput(changeset) {
296
313
  return {
297
314
  rowForm: changeset.get("rowForm.slug"),
315
+ hintText: changeset.get("hintText"),
298
316
  };
299
317
  }
300
318
 
@@ -313,6 +331,13 @@ export default class CfbFormEditorQuestion extends Component {
313
331
  _getCalculatedFloatQuestionInput(changeset) {
314
332
  return {
315
333
  calcExpression: changeset.get("calcExpression"),
334
+ hintText: changeset.get("hintText"),
335
+ };
336
+ }
337
+
338
+ _getFileQuestionInput(changeset) {
339
+ return {
340
+ hintText: changeset.get("hintText"),
316
341
  };
317
342
  }
318
343
 
@@ -326,7 +351,7 @@ export default class CfbFormEditorQuestion extends Component {
326
351
 
327
352
  @task
328
353
  *saveOptions(changeset) {
329
- yield all(
354
+ yield Promise.all(
330
355
  (changeset.get("options.edges") || []).map(async ({ node: option }) => {
331
356
  const { label, slug, isArchived } = option;
332
357
 
@@ -406,7 +431,7 @@ export default class CfbFormEditorQuestion extends Component {
406
431
  this.intl.t("caluma.form-builder.notification.question.save.success")
407
432
  );
408
433
 
409
- optional([this.args["on-after-submit"]])(question);
434
+ this.args.onAfterSubmit?.(question);
410
435
  } catch (e) {
411
436
  // eslint-disable-next-line no-console
412
437
  console.error(e);
@@ -419,10 +444,9 @@ export default class CfbFormEditorQuestion extends Component {
419
444
  @restartableTask
420
445
  *validateSlug(slug, changeset) {
421
446
  /* istanbul ignore next */
422
- if (
423
- getOwner(this).resolveRegistration("config:environment").environment !==
424
- "test"
425
- ) {
447
+ if (macroCondition(isTesting())) {
448
+ // no timeout
449
+ } else {
426
450
  yield timeout(500);
427
451
  }
428
452
 
@@ -12,11 +12,11 @@
12
12
  {{else}}
13
13
  <CfbFormEditor::QuestionList
14
14
  @form={{@slug}}
15
- @on-edit-question={{@on-edit-question}}
16
- @on-create-question={{@on-create-question}}
17
- @on-after-add-question={{@on-after-add-question}}
18
- @on-after-remove-question={{@on-after-remove-question}}
19
- @on-click-form={{@on-click-form}}
15
+ @onEditQuestion={{@onEditQuestion}}
16
+ @onCreateQuestion={{@onCreateQuestion}}
17
+ @onAfterAddQuestion={{@onAfterAddQuestion}}
18
+ @onAfterRemoveQuestion={{@onAfterRemoveQuestion}}
19
+ @onClickForm={{@onClickForm}}
20
20
  />
21
21
  {{/if}}
22
22
  </div>
@@ -12,7 +12,7 @@
12
12
  type="button"
13
13
  uk-icon="pencil"
14
14
  class="uk-icon-button"
15
- {{on "click" (fn (optional @on-edit-form) @item)}}
15
+ {{on "click" (fn (optional @onEditForm) @item)}}
16
16
  >
17
17
  </button>
18
18
  </span>
@@ -1,18 +1,18 @@
1
1
  <div class="uk-flex uk-flex-between">
2
2
  <div class="uk-button-group">
3
- {{#each (array "active" "archived" "all") as |category|}}
3
+ {{#each this.categories as |category|}}
4
4
  <UkButton
5
- data-test-filter={{category}}
6
- @on-click={{fn (perform this.setFilter) "category" category}}
7
- @label={{t (concat "caluma.form-builder.form." category)}}
8
- @class={{if (eq this.category category) "uk-button-primary" ""}}
5
+ data-test-filter={{category.value}}
6
+ @onClick={{fn @onUpdateCategory category.value}}
7
+ @label={{category.label}}
8
+ @color={{if (eq @category category.value) "primary"}}
9
9
  />
10
10
  {{/each}}
11
11
  </div>
12
12
  <div>
13
13
  <UkButton
14
14
  data-test-new-form
15
- @on-click={{optional @on-new-form}}
15
+ @onClick={{optional @onNewForm}}
16
16
  @label={{t "caluma.form-builder.form.new"}}
17
17
  />
18
18
  </div>
@@ -26,8 +26,8 @@
26
26
  type="search"
27
27
  placeholder="{{t 'caluma.form-builder.global.search'}}..."
28
28
  aria-label="{{t 'caluma.form-builder.global.search'}}"
29
- value={{this.search}}
30
- {{on "input" (fn (perform this.setFilter) "search")}}
29
+ value={{@search}}
30
+ {{on "input" (perform this.search)}}
31
31
  />
32
32
  </div>
33
33
 
@@ -37,7 +37,7 @@
37
37
  <CfbFormList::Item
38
38
  data-test-form-list-item={{item.slug}}
39
39
  @item={{item}}
40
- @on-edit-form={{@on-edit-form}}
40
+ @onEditForm={{@onEditForm}}
41
41
  />
42
42
  {{/each}}
43
43
  {{#if this.formsQuery.isLoading}}
@@ -1,38 +1,71 @@
1
+ import { inject as service } from "@ember/service";
2
+ import { macroCondition, isTesting } from "@embroider/macros";
1
3
  import Component from "@glimmer/component";
2
- import { tracked } from "@glimmer/tracking";
3
4
  import { timeout, restartableTask } from "ember-concurrency";
4
5
 
5
6
  import { useCalumaQuery } from "@projectcaluma/ember-core/caluma-query";
6
7
  import { allForms } from "@projectcaluma/ember-core/caluma-query/queries";
7
8
 
8
9
  export default class ComponentsCfbFormListComponent extends Component {
10
+ @service intl;
11
+
9
12
  formsQuery = useCalumaQuery(this, allForms, () => ({
10
13
  options: { pageSize: 20 },
11
14
  filter: this.filter,
12
15
  order: [{ attribute: "NAME", direction: "ASC" }],
13
16
  }));
14
17
 
15
- @tracked category = "active";
16
- @tracked search = "";
18
+ get categories() {
19
+ return [
20
+ {
21
+ value: "active",
22
+ label: this.intl.t("caluma.form-builder.form.active"),
23
+ },
24
+ {
25
+ value: "archived",
26
+ label: this.intl.t("caluma.form-builder.form.isArchived"),
27
+ },
28
+ {
29
+ value: "published",
30
+ label: this.intl.t("caluma.form-builder.form.isPublished"),
31
+ },
32
+ {
33
+ value: "unpublished",
34
+ label: this.intl.t("caluma.form-builder.form.draft"),
35
+ },
36
+ { value: "all", label: this.intl.t("caluma.form-builder.form.all") },
37
+ ];
38
+ }
17
39
 
18
40
  get filter() {
19
41
  const isArchived =
20
- this.category === "active"
42
+ this.args.category === "active"
21
43
  ? { isArchived: false }
22
- : this.category === "archived"
44
+ : this.args.category === "archived"
23
45
  ? { isArchived: true }
24
46
  : null;
25
47
 
26
- const search = this.search ? { search: this.search } : null;
48
+ const search = this.args.search ? { search: this.args.search } : null;
49
+
50
+ const isPublished =
51
+ this.args.category === "unpublished"
52
+ ? { isPublished: false }
53
+ : this.args.category === "published"
54
+ ? { isPublished: true }
55
+ : null;
27
56
 
28
- return [isArchived, search].filter(Boolean) || null;
57
+ return [isArchived, isPublished, search].filter(Boolean) || null;
29
58
  }
30
59
 
31
60
  @restartableTask
32
- *setFilter(name, eventOrValue) {
33
- yield timeout(500);
61
+ *search(event) {
62
+ /* istanbul ignore next */
63
+ if (macroCondition(isTesting())) {
64
+ // no timeout
65
+ } else {
66
+ yield timeout(500);
67
+ }
34
68
 
35
- this[name] =
36
- eventOrValue instanceof Event ? eventOrValue.target.value : eventOrValue;
69
+ this.args.onUpdateSearch(event.target.value);
37
70
  }
38
71
  }
@@ -7,7 +7,7 @@
7
7
  @size={{@size}}
8
8
  @name={{@name}}
9
9
  @disabled={{@disabled}}
10
- @on-toggle={{@update}}
10
+ @onToggle={{@update}}
11
11
  />
12
12
  </div>
13
13
 
@@ -1,10 +1,16 @@
1
1
  import Controller from "@ember/controller";
2
2
  import { action } from "@ember/object";
3
3
  import { inject as service } from "@ember/service";
4
+ import { tracked } from "@glimmer/tracking";
4
5
 
5
6
  export default class IndexController extends Controller {
6
7
  @service router;
7
8
 
9
+ queryParams = ["search", "category"];
10
+
11
+ @tracked search = "";
12
+ @tracked category = "active";
13
+
8
14
  @action
9
15
  newForm() {
10
16
  this.router.transitionTo("new");
package/addon/engine.js CHANGED
@@ -6,16 +6,13 @@ import config from "./config/environment";
6
6
 
7
7
  const { modulePrefix } = config;
8
8
 
9
- /* eslint-disable ember/avoid-leaking-state-in-ember-objects */
10
- const Eng = Engine.extend({
11
- modulePrefix,
12
- Resolver,
9
+ export default class FormBuilderEngine extends Engine {
10
+ modulePrefix = modulePrefix;
11
+ Resolver = Resolver;
13
12
 
14
- dependencies: {
15
- services: ["apollo", "notification", "intl", "caluma-options", "validator"],
16
- },
17
- });
13
+ dependencies = {
14
+ services: ["apollo", "notification", "intl", "caluma-options"],
15
+ };
16
+ }
18
17
 
19
- loadInitializers(Eng, modulePrefix);
20
-
21
- export default Eng;
18
+ loadInitializers(FormBuilderEngine, modulePrefix);
@@ -19,6 +19,7 @@ fragment SimpleQuestion on Question {
19
19
  value
20
20
  }
21
21
  placeholder
22
+ hintText
22
23
  }
23
24
  ... on TextareaQuestion {
24
25
  textareaMinLength: minLength
@@ -28,6 +29,7 @@ fragment SimpleQuestion on Question {
28
29
  value
29
30
  }
30
31
  placeholder
32
+ hintText
31
33
  }
32
34
  ... on IntegerQuestion {
33
35
  integerMinValue: minValue
@@ -37,6 +39,7 @@ fragment SimpleQuestion on Question {
37
39
  value
38
40
  }
39
41
  placeholder
42
+ hintText
40
43
  }
41
44
  ... on FloatQuestion {
42
45
  floatMinValue: minValue
@@ -46,6 +49,7 @@ fragment SimpleQuestion on Question {
46
49
  value
47
50
  }
48
51
  placeholder
52
+ hintText
49
53
  }
50
54
  ... on ChoiceQuestion {
51
55
  choiceOptions: options {
@@ -62,6 +66,7 @@ fragment SimpleQuestion on Question {
62
66
  id
63
67
  value
64
68
  }
69
+ hintText
65
70
  }
66
71
  ... on MultipleChoiceQuestion {
67
72
  multipleChoiceOptions: options {
@@ -78,18 +83,24 @@ fragment SimpleQuestion on Question {
78
83
  id
79
84
  value
80
85
  }
86
+ hintText
81
87
  }
82
88
  ... on DateQuestion {
83
89
  dateDefaultAnswer: defaultAnswer {
84
90
  id
85
91
  value
86
92
  }
93
+ hintText
87
94
  }
88
95
  ... on StaticQuestion {
89
96
  staticContent
90
97
  }
91
98
  ... on CalculatedFloatQuestion {
92
99
  calcExpression
100
+ hintText
101
+ }
102
+ ... on FileQuestion {
103
+ hintText
93
104
  }
94
105
  ... on ActionButtonQuestion {
95
106
  action
@@ -112,6 +123,7 @@ fragment FieldTableQuestion on Question {
112
123
  }
113
124
  }
114
125
  }
126
+ hintText
115
127
  tableDefaultAnswer: defaultAnswer {
116
128
  id
117
129
  value {
@@ -9,6 +9,7 @@ mutation SaveCalculatedFloatQuestion(
9
9
  ...QuestionInfo
10
10
  ... on CalculatedFloatQuestion {
11
11
  calcExpression
12
+ hintText
12
13
  }
13
14
  }
14
15
  clientMutationId
@@ -15,6 +15,7 @@ mutation SaveChoiceQuestion($input: SaveChoiceQuestionInput!) {
15
15
  }
16
16
  }
17
17
  }
18
+ hintText
18
19
  }
19
20
  }
20
21
  clientMutationId
@@ -5,6 +5,9 @@ mutation SaveDateQuestion($input: SaveDateQuestionInput!) {
5
5
  question {
6
6
  id
7
7
  ...QuestionInfo
8
+ ... on DateQuestion {
9
+ hintText
10
+ }
8
11
  }
9
12
  clientMutationId
10
13
  }
@@ -7,6 +7,7 @@ mutation SaveDynamicChoiceQuestion($input: SaveDynamicChoiceQuestionInput!) {
7
7
  ...QuestionInfo
8
8
  ... on DynamicChoiceQuestion {
9
9
  dataSource
10
+ hintText
10
11
  }
11
12
  }
12
13
  clientMutationId
@@ -9,6 +9,7 @@ mutation SaveDynamicMultipleChoiceQuestion(
9
9
  ...QuestionInfo
10
10
  ... on DynamicMultipleChoiceQuestion {
11
11
  dataSource
12
+ hintText
12
13
  }
13
14
  }
14
15
  clientMutationId
@@ -5,6 +5,9 @@ mutation SaveFileQuestion($input: SaveFileQuestionInput!) {
5
5
  question {
6
6
  id
7
7
  ...QuestionInfo
8
+ ... on FileQuestion {
9
+ hintText
10
+ }
8
11
  }
9
12
  clientMutationId
10
13
  }
@@ -8,6 +8,7 @@ mutation SaveFloatQuestion($input: SaveFloatQuestionInput!) {
8
8
  ... on FloatQuestion {
9
9
  floatMinValue: minValue
10
10
  floatMaxValue: maxValue
11
+ hintText
11
12
  }
12
13
  }
13
14
  clientMutationId
@@ -8,6 +8,7 @@ mutation SaveIntegerQuestion($input: SaveIntegerQuestionInput!) {
8
8
  ... on IntegerQuestion {
9
9
  integerMinValue: minValue
10
10
  integerMaxValue: maxValue
11
+ hintText
11
12
  }
12
13
  }
13
14
  clientMutationId
@@ -15,6 +15,7 @@ mutation SaveMultipleChoiceQuestion($input: SaveMultipleChoiceQuestionInput!) {
15
15
  }
16
16
  }
17
17
  }
18
+ hintText
18
19
  }
19
20
  }
20
21
  clientMutationId
@@ -10,6 +10,7 @@ mutation SaveTableQuestion($input: SaveTableQuestionInput!) {
10
10
  id
11
11
  slug
12
12
  }
13
+ hintText
13
14
  }
14
15
  }
15
16
  clientMutationId
@@ -8,6 +8,7 @@ mutation SaveTextQuestion($input: SaveTextQuestionInput!) {
8
8
  ... on TextQuestion {
9
9
  minLength
10
10
  maxLength
11
+ hintText
11
12
  }
12
13
  }
13
14
  clientMutationId
@@ -8,6 +8,7 @@ mutation SaveTextareaQuestion($input: SaveTextareaQuestionInput!) {
8
8
  ... on TextareaQuestion {
9
9
  minLength
10
10
  maxLength
11
+ hintText
11
12
  }
12
13
  }
13
14
  clientMutationId
@@ -0,0 +1,10 @@
1
+ query AllFormatValidators {
2
+ allFormatValidators {
3
+ edges {
4
+ node {
5
+ slug
6
+ name
7
+ }
8
+ }
9
+ }
10
+ }