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

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.
@@ -1,41 +1,39 @@
1
- {{#if @documentId}}
2
- {{#if this.loading}}
3
- <div class="uk-text-center"><UkSpinner @ratio={{2}} /></div>
4
- {{else if this.document}}
5
- {{#let
6
- (hash
1
+ {{#if this.loading}}
2
+ <div class="uk-text-center"><UkSpinner @ratio={{2}} /></div>
3
+ {{else if this.document}}
4
+ {{#let
5
+ (hash
6
+ document=this.document
7
+ navigation=(component
8
+ "cf-navigation"
9
+ navigation=this.navigation
10
+ useAsHeading=(or @useAsHeading false)
11
+ headingBaseLevel=(or @headingBaseLevel 1)
12
+ )
13
+ pagination=(component "cf-pagination" navigation=this.navigation)
14
+ form=(component
15
+ "cf-form-wrapper"
7
16
  document=this.document
8
- navigation=(component
9
- "cf-navigation"
10
- navigation=this.navigation
11
- useAsHeading=(or @useAsHeading false)
12
- headingBaseLevel=(or @headingBaseLevel 1)
13
- )
14
- pagination=(component "cf-pagination" navigation=this.navigation)
15
- form=(component
16
- "cf-form-wrapper"
17
- document=this.document
18
- fieldset=this.fieldset
19
- context=@context
20
- disabled=@disabled
21
- )
17
+ fieldset=this.fieldset
18
+ context=@context
19
+ disabled=@disabled
22
20
  )
23
- as |content|
24
- }}
25
- {{#if (has-block)}}
26
- {{yield content}}
27
- {{else if (gt this.document.fieldsets.length 1)}}
28
- <div uk-grid>
29
- <div class="uk-width-1-1 uk-width-1-3@m"><content.navigation /></div>
30
- <div class="uk-width-1-1 uk-width-2-3@m">
31
- <content.form />
32
- <hr />
33
- <content.pagination />
34
- </div>
21
+ )
22
+ as |content|
23
+ }}
24
+ {{#if (has-block)}}
25
+ {{yield content}}
26
+ {{else if (gt this.document.fieldsets.length 1)}}
27
+ <div uk-grid>
28
+ <div class="uk-width-1-1 uk-width-1-3@m"><content.navigation /></div>
29
+ <div class="uk-width-1-1 uk-width-2-3@m">
30
+ <content.form />
31
+ <hr />
32
+ <content.pagination />
35
33
  </div>
36
- {{else}}
37
- <content.form />
38
- {{/if}}
39
- {{/let}}
40
- {{/if}}
34
+ </div>
35
+ {{else}}
36
+ <content.form />
37
+ {{/if}}
38
+ {{/let}}
41
39
  {{/if}}
@@ -120,17 +120,9 @@ export default class CfContentComponent extends Component {
120
120
  this.router.currentRoute?.queryParams.displayedForm ||
121
121
  this.document?.raw.form.slug;
122
122
 
123
- const fieldset = this.document.fieldsets.find(
123
+ return this.document.fieldsets.find(
124
124
  (fieldset) => fieldset.form.slug === slug
125
125
  );
126
-
127
- if (!fieldset) {
128
- this.router.replaceWith({
129
- queryParams: { displayedForm: "" },
130
- });
131
- }
132
-
133
- return fieldset;
134
126
  }
135
127
 
136
128
  data = useTask(this, this.fetchData, () => [this.args.documentId]);
@@ -4,7 +4,7 @@
4
4
  class="uk-icon-button"
5
5
  uk-icon="info"
6
6
  title={{t "caluma.form.info"}}
7
- {{on "click" this.showModal}}
7
+ {{on "click" (fn (mut this.modalVisible) true)}}
8
8
  >
9
9
  <span class="uk-hidden">{{t "caluma.form.info"}}</span>
10
10
  </button>
@@ -12,7 +12,7 @@
12
12
  <UkModal
13
13
  @visible={{this.modalVisible}}
14
14
  @stack={{true}}
15
- @on-hide={{this.hideModal}}
15
+ @onHide={{fn (mut this.modalVisible) false}}
16
16
  as |modal|
17
17
  >
18
18
  <modal.body>
@@ -1,21 +1,6 @@
1
- import { action } from "@ember/object";
2
1
  import Component from "@glimmer/component";
3
2
  import { tracked } from "@glimmer/tracking";
4
3
 
5
4
  export default class CfFieldInfoComponent extends Component {
6
5
  @tracked modalVisible = false;
7
-
8
- @action
9
- showModal(e) {
10
- e.preventDefault();
11
-
12
- this.modalVisible = true;
13
- }
14
-
15
- @action
16
- hideModal(e) {
17
- e.preventDefault();
18
-
19
- this.modalVisible = false;
20
- }
21
6
  }
@@ -1,19 +1,18 @@
1
- {{#unless @disabled}}
2
- <DocumentValidity
3
- @document={{@field.document}}
4
- @validateOnEnter={{this.validateOnEnter}}
5
- as |isValid validate|
6
- >
7
- <WorkItemButton
8
- @workItemId={{this.workItem}}
9
- @mutation={{this.action}}
10
- @label={{@field.question.raw.label}}
11
- @disabled={{and (not-eq isValid null) (not isValid)}}
12
- @color={{this.color}}
13
- @beforeMutate={{fn this.beforeMutate validate}}
14
- @onSuccess={{this.onSuccess}}
15
- @onError={{this.onError}}
16
- @type={{this.type}}
17
- />
18
- </DocumentValidity>
19
- {{/unless}}
1
+ <DocumentValidity
2
+ @document={{@field.document}}
3
+ @validateOnEnter={{this.validateOnEnter}}
4
+ as |isValid validate|
5
+ >
6
+ <WorkItemButton
7
+ @workItemId={{this.workItem}}
8
+ @mutation={{this.action}}
9
+ @label={{@field.question.raw.label}}
10
+ @disabled={{or (and (not-eq isValid null) (not isValid)) @disabled}}
11
+ @color={{this.color}}
12
+ @beforeMutate={{fn this.beforeMutate validate}}
13
+ @onSuccess={{this.onSuccess}}
14
+ @onError={{this.onError}}
15
+ @type={{this.type}}
16
+ class={{if @disabled "uk-hidden"}}
17
+ />
18
+ </DocumentValidity>
@@ -1,6 +1,10 @@
1
1
  {{#each @field.options as |option i|}}
2
2
  {{#if (gt i 0)}}<br />{{/if}}
3
- <label class="cf-checkbox_label {{if @field.isInvalid 'uk-form-danger'}}">
3
+ <label
4
+ class="cf-checkbox_label
5
+ {{if @field.isInvalid 'uk-form-danger'}}
6
+ {{if @field.raw.question.meta.vertical 'uk-margin-large-right'}}"
7
+ >
4
8
  <input
5
9
  class="uk-checkbox uk-margin-small-right"
6
10
  type="checkbox"
@@ -13,13 +13,16 @@
13
13
  readonly
14
14
  />
15
15
  {{else}}
16
- <PikadayInput
16
+ <input
17
17
  class="uk-input"
18
+ type="text"
18
19
  name={{@field.pk}}
19
20
  id={{@field.pk}}
20
- @format="L"
21
- @onSelection={{this.onChange}}
22
- @useUTC={{true}}
23
- @value={{@field.answer.value}}
21
+ {{pikaday
22
+ toString=this.formatDate
23
+ i18n=this.pikadayTranslations
24
+ value=@field.answer.value
25
+ onSelect=this.onChange
26
+ }}
24
27
  />
25
28
  {{/if}}
@@ -1,19 +1,37 @@
1
1
  import { action } from "@ember/object";
2
+ import { inject as service } from "@ember/service";
2
3
  import Component from "@glimmer/component";
3
- import moment from "moment";
4
+ import { DateTime, Info } from "luxon";
5
+ import { cached } from "tracked-toolbox";
4
6
 
5
7
  export default class CfFieldInputDateComponent extends Component {
8
+ @service intl;
9
+
6
10
  @action
7
11
  onChange(date) {
8
12
  // Change Javascript date to ISO string if not null.
9
- this.args.onSave(
10
- date
11
- ? moment({
12
- day: date.getUTCDate(),
13
- month: date.getUTCMonth(),
14
- year: date.getUTCFullYear(),
15
- }).format(moment.HTML5_FMT.DATE)
16
- : null
17
- );
13
+ this.args.onSave(date ? DateTime.fromJSDate(date).toISODate() : null);
14
+ }
15
+
16
+ @action
17
+ formatDate(date) {
18
+ return this.intl.formatDate(date, {
19
+ day: "2-digit",
20
+ month: "2-digit",
21
+ year: "numeric",
22
+ });
23
+ }
24
+
25
+ @cached
26
+ get pikadayTranslations() {
27
+ const locale = this.intl.primaryLocale;
28
+
29
+ return {
30
+ previousMonth: this.intl.t("caluma.form.pikaday.month-previous"),
31
+ nextMonth: this.intl.t("caluma.form.pikaday.month-next"),
32
+ months: Info.months("long", { locale }),
33
+ weekdays: Info.weekdays("long", { locale }),
34
+ weekdaysShort: Info.weekdays("short", { locale }),
35
+ };
18
36
  }
19
37
  }
@@ -8,7 +8,7 @@
8
8
  disabled={{@disabled}}
9
9
  {{on "change" this.save}}
10
10
  />
11
- <UkButton @color="primary" @disabled={{@disabled}}>
11
+ <UkButton disabled={{@disabled}}>
12
12
  {{t "caluma.form.selectFile"}}
13
13
  </UkButton>
14
14
  </div>
@@ -17,7 +17,7 @@
17
17
  <UkButton
18
18
  data-test-download-link
19
19
  @color="link"
20
- @on-click={{this.download}}
20
+ @onClick={{this.download}}
21
21
  >
22
22
  {{this.downloadName}}
23
23
  </UkButton>
@@ -22,11 +22,11 @@ export default class CfFieldInputFileComponent extends Component {
22
22
 
23
23
  @action
24
24
  async download() {
25
- const { downloadUrl } = await this.apollo.watchQuery(
25
+ const { downloadUrl } = await this.apollo.query(
26
26
  {
27
27
  query: getFileAnswerInfoQuery,
28
28
  variables: { id: this.args.field.answer.raw.id },
29
- fetchPolicy: "cache-and-network",
29
+ fetchPolicy: "network-only",
30
30
  },
31
31
  "node.fileValue"
32
32
  );
@@ -1,6 +1,9 @@
1
1
  {{#each @field.options as |option i|}}
2
2
  {{#if (gt i 0)}}<br />{{/if}}
3
- <label class={{if @field.isInvalid "uk-form-danger"}}>
3
+ <label
4
+ class="{{if @field.isInvalid 'uk-form-danger'}}
5
+ {{if @field.raw.question.meta.vertical 'uk-margin-large-right'}}"
6
+ >
4
7
  <input
5
8
  class="uk-radio uk-margin-small-right"
6
9
  type="radio"
@@ -1,4 +1,4 @@
1
1
  <MarkdownToHtml
2
- @markdown={{@field.question.staticContent}}
2
+ @markdown={{@field.question.raw.staticContent}}
3
3
  @openLinksInNewWindow={{true}}
4
4
  />
@@ -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>
@@ -9,4 +9,5 @@
9
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}}
@@ -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,50 +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
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.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
12
  const { downloadUrl } = await this.apollo.query(
44
- { query: getFileAnswerInfoQuery, variables: { id } },
13
+ {
14
+ query: getFileAnswerInfoQuery,
15
+ variables: { id },
16
+ fetchPolicy: "network-only",
17
+ },
45
18
  "node.fileValue"
46
19
  );
47
20
 
48
- window.open(downloadUrl, "_blank");
21
+ if (downloadUrl) {
22
+ window.open(downloadUrl, "_blank");
23
+ }
49
24
  }
50
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}}
@@ -24,11 +32,11 @@
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,5 +1,5 @@
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
4
  import { timeout, restartableTask } from "ember-concurrency";
5
5
 
@@ -18,6 +18,16 @@ import { hasQuestionType } from "@projectcaluma/ember-core/helpers/has-question-
18
18
  * @argument {Field} field The field data model to render
19
19
  */
20
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
+
21
31
  get visible() {
22
32
  return (
23
33
  !this.args.field?.hidden &&
@@ -41,8 +51,9 @@ export default class CfFieldComponent extends Component {
41
51
  }
42
52
 
43
53
  /**
44
- * Task to save a field. This will set the passed value to the answer and
45
- * 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.
46
57
  *
47
58
  * @method save
48
59
  * @param {String|Number|String[]} value
@@ -57,14 +68,18 @@ export default class CfFieldComponent extends Component {
57
68
  yield timeout(500);
58
69
  }
59
70
 
60
- set(this.args.field.answer, "value", value);
71
+ if (this.args.field.answer) {
72
+ this.args.field.answer.value = value;
73
+ }
61
74
 
62
75
  yield this.args.field.validate.perform();
63
76
 
64
77
  try {
78
+ // Save the new field value unlinked so the fields save task is not
79
+ // aborted when this component is destroyed
65
80
  return yield this.args.field.save.unlinked().perform();
66
81
  } catch (e) {
67
- // that's ok
82
+ // The component was destroyed before the fields save task was finished
68
83
  }
69
84
  }
70
85
  }
@@ -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}}