@projectcaluma/ember-form 11.0.0-beta.1 → 11.0.0-beta.5
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 +1127 -0
- package/addon/components/cf-content.js +1 -9
- package/addon/components/cf-field/info.hbs +2 -2
- package/addon/components/cf-field/info.js +0 -15
- package/addon/components/cf-field/input/checkbox.hbs +5 -1
- package/addon/components/cf-field/input/file.hbs +1 -1
- package/addon/components/cf-field/input/radio.hbs +4 -1
- package/addon/components/cf-field/input/table.hbs +7 -8
- package/addon/components/cf-field/input/textarea.hbs +1 -0
- package/addon/components/cf-field/input.hbs +10 -1
- package/addon/components/cf-field-value.hbs +1 -1
- package/addon/components/cf-field.hbs +8 -4
- package/addon/components/cf-field.js +20 -5
- package/addon/components/cf-navigation.hbs +4 -1
- package/addon/components/document-validity.js +16 -1
- package/addon/lib/field.js +10 -0
- package/addon/lib/navigation.js +28 -15
- package/blueprints/@projectcaluma/ember-form/index.js +1 -0
- package/package.json +16 -13
- package/addon/components/cf-navigation.js +0 -9
@@ -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
|
-
|
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.
|
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
|
-
@
|
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,6 +1,10 @@
|
|
1
1
|
{{#each @field.options as |option i|}}
|
2
2
|
{{#if (gt i 0)}}<br />{{/if}}
|
3
|
-
<label
|
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"
|
@@ -1,6 +1,9 @@
|
|
1
1
|
{{#each @field.options as |option i|}}
|
2
2
|
{{#if (gt i 0)}}<br />{{/if}}
|
3
|
-
<label
|
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"
|
@@ -28,7 +28,7 @@
|
|
28
28
|
<button
|
29
29
|
data-test-edit-row
|
30
30
|
type="button"
|
31
|
-
class="uk-button-link uk-flex-inline uk-margin-small-left"
|
31
|
+
class="uk-button uk-button-link uk-flex-inline uk-margin-small-left"
|
32
32
|
title={{t "caluma.form.edit"}}
|
33
33
|
{{on "click" (fn this.edit document)}}
|
34
34
|
>
|
@@ -39,7 +39,7 @@
|
|
39
39
|
<button
|
40
40
|
data-test-delete-row
|
41
41
|
type="button"
|
42
|
-
class="uk-button-link uk-flex-inline uk-margin-small-left"
|
42
|
+
class="uk-button uk-button-link uk-flex-inline uk-margin-small-left"
|
43
43
|
title={{t "caluma.form.delete"}}
|
44
44
|
{{on "click" (fn (perform this.delete) document)}}
|
45
45
|
>
|
@@ -58,8 +58,7 @@
|
|
58
58
|
<td colspan={{add this.columns.length 1}} class="uk-text-center">
|
59
59
|
<UkButton
|
60
60
|
@size="small"
|
61
|
-
@
|
62
|
-
@on-click={{perform this.add}}
|
61
|
+
@onClick={{perform this.add}}
|
63
62
|
data-test-add-row
|
64
63
|
>
|
65
64
|
<UkIcon @icon="plus" />
|
@@ -74,7 +73,7 @@
|
|
74
73
|
{{#if this.documentToEdit}}
|
75
74
|
<UkModal
|
76
75
|
@visible={{this.showAddModal}}
|
77
|
-
@
|
76
|
+
@onHide={{perform this.close}}
|
78
77
|
@bgClose={{false}}
|
79
78
|
as |modal|
|
80
79
|
>
|
@@ -91,7 +90,7 @@
|
|
91
90
|
<UkButton
|
92
91
|
@label={{t "caluma.form.close"}}
|
93
92
|
@color="primary"
|
94
|
-
@
|
93
|
+
@onClick={{perform this.close}}
|
95
94
|
@disabled={{this.close.isRunning}}
|
96
95
|
@loading={{this.close.isRunning}}
|
97
96
|
data-test-close
|
@@ -99,7 +98,7 @@
|
|
99
98
|
{{else}}
|
100
99
|
<UkButton
|
101
100
|
@label={{t "caluma.form.cancel"}}
|
102
|
-
@
|
101
|
+
@onClick={{perform this.close}}
|
103
102
|
@disabled={{this.close.isRunning}}
|
104
103
|
@loading={{this.close.isRunning}}
|
105
104
|
data-test-cancel
|
@@ -114,7 +113,7 @@
|
|
114
113
|
@type="submit"
|
115
114
|
@disabled={{or this.save.isRunning (not isValid)}}
|
116
115
|
@loading={{this.save.isRunning}}
|
117
|
-
@
|
116
|
+
@onClick={{fn (perform this.save) validate}}
|
118
117
|
data-test-save
|
119
118
|
/>
|
120
119
|
</DocumentValidity>
|
@@ -1,6 +1,15 @@
|
|
1
1
|
{{#if this.type}}
|
2
2
|
{{#let (component (concat "cf-field/input/" this.type)) as |InputComponent|}}
|
3
|
-
<div
|
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,5 +1,9 @@
|
|
1
1
|
{{#if this.visible}}
|
2
|
-
<div
|
2
|
+
<div
|
3
|
+
class="uk-margin"
|
4
|
+
{{did-insert this.registerComponent}}
|
5
|
+
{{will-destroy this.unregisterComponent}}
|
6
|
+
>
|
3
7
|
{{#if this.labelVisible}}
|
4
8
|
<CfField::label @field={{@field}} />
|
5
9
|
{{/if}}
|
@@ -24,11 +28,11 @@
|
|
24
28
|
<div
|
25
29
|
class="cf-field__icon uk-padding-remove-vertical uk-flex uk-flex-middle uk-flex-center"
|
26
30
|
>
|
27
|
-
{{#if
|
31
|
+
{{#if this.save.isRunning}}
|
28
32
|
<UkSpinner class="uk-animation-fade" />
|
29
|
-
{{else if (or
|
33
|
+
{{else if (or this.save.last.isError @field.isInvalid)}}
|
30
34
|
<UkIcon @icon="warning" class="uk-animation-fade uk-text-danger" />
|
31
|
-
{{else if
|
35
|
+
{{else if this.save.last.isSuccessful}}
|
32
36
|
<UkIcon @icon="check" class="uk-animation-fade uk-text-success" />
|
33
37
|
{{/if}}
|
34
38
|
</div>
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import { getOwner } from "@ember/application";
|
2
|
-
import {
|
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
|
-
*
|
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
|
-
|
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
|
-
//
|
82
|
+
// The component was destroyed before the fields save task was finished
|
68
83
|
}
|
69
84
|
}
|
70
85
|
}
|
@@ -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}}
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import { action } from "@ember/object";
|
2
2
|
import Component from "@glimmer/component";
|
3
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
|
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
|
}
|
package/addon/lib/field.js
CHANGED
@@ -152,6 +152,16 @@ export default class Field extends Base {
|
|
152
152
|
*/
|
153
153
|
@tracked _errors = [];
|
154
154
|
|
155
|
+
/**
|
156
|
+
* Currently rendered field components that use this field. This is used in
|
157
|
+
* the document validity component to await all current save tasks before
|
158
|
+
* validating.
|
159
|
+
*
|
160
|
+
* @property {Set} _components
|
161
|
+
* @private
|
162
|
+
*/
|
163
|
+
_components = new Set();
|
164
|
+
|
155
165
|
/**
|
156
166
|
* The primary key of the field. Consists of the document and question primary
|
157
167
|
* keys.
|
package/addon/lib/navigation.js
CHANGED
@@ -1,7 +1,11 @@
|
|
1
1
|
import { getOwner } from "@ember/application";
|
2
2
|
import { assert } from "@ember/debug";
|
3
|
-
import {
|
4
|
-
|
3
|
+
import {
|
4
|
+
associateDestroyableChild,
|
5
|
+
registerDestructor,
|
6
|
+
} from "@ember/destroyable";
|
7
|
+
import { action } from "@ember/object";
|
8
|
+
import { next, cancel, once } from "@ember/runloop";
|
5
9
|
import { inject as service } from "@ember/service";
|
6
10
|
import { cached } from "tracked-toolbox";
|
7
11
|
|
@@ -300,7 +304,18 @@ export class Navigation extends Base {
|
|
300
304
|
|
301
305
|
this._createItems();
|
302
306
|
|
303
|
-
|
307
|
+
const transitionHandler = () => {
|
308
|
+
this._timer = next(this, "goToNextItemIfNonNavigable");
|
309
|
+
};
|
310
|
+
|
311
|
+
// go to next item in next run loop, this is necessary when the user clicks
|
312
|
+
// on a non navigable item in the navigation
|
313
|
+
this.router.on("routeDidChange", this, transitionHandler);
|
314
|
+
|
315
|
+
registerDestructor(this, () => {
|
316
|
+
cancel(this._timer);
|
317
|
+
this.router.off("routeDidChange", this, transitionHandler);
|
318
|
+
});
|
304
319
|
}
|
305
320
|
|
306
321
|
/**
|
@@ -399,31 +414,29 @@ export class Navigation extends Base {
|
|
399
414
|
}
|
400
415
|
|
401
416
|
/**
|
402
|
-
*
|
403
|
-
* is not navigable.
|
417
|
+
* Replace the current item with the next navigable item if the current item
|
418
|
+
* is not navigable. This makes sure that only one transition per runloop
|
419
|
+
* happens.
|
404
420
|
*
|
405
421
|
* @method goToNextItemIfNonNavigable
|
406
422
|
*/
|
423
|
+
@action
|
407
424
|
goToNextItemIfNonNavigable() {
|
408
|
-
if (
|
425
|
+
if (this.currentItem?.navigable) {
|
409
426
|
return;
|
410
427
|
}
|
411
428
|
|
412
|
-
|
429
|
+
once(this, "_transitionToNextItem");
|
413
430
|
}
|
414
431
|
|
415
432
|
/**
|
416
|
-
*
|
433
|
+
* Transition to next item or start (empty displayed form).
|
417
434
|
*
|
418
|
-
* @method
|
435
|
+
* @method _transitionToNextItem
|
419
436
|
*/
|
420
|
-
|
421
|
-
if (!this.nextItem?.slug || this.currentItem?.navigable) {
|
422
|
-
return;
|
423
|
-
}
|
424
|
-
|
437
|
+
_transitionToNextItem() {
|
425
438
|
this.router.replaceWith({
|
426
|
-
queryParams: { displayedForm: this.nextItem
|
439
|
+
queryParams: { displayedForm: this.nextItem?.slug ?? "" },
|
427
440
|
});
|
428
441
|
}
|
429
442
|
}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@projectcaluma/ember-form",
|
3
|
-
"version": "11.0.0-beta.
|
3
|
+
"version": "11.0.0-beta.5",
|
4
4
|
"description": "Ember addon for rendering Caluma forms.",
|
5
5
|
"keywords": [
|
6
6
|
"ember-addon"
|
@@ -16,21 +16,23 @@
|
|
16
16
|
"dependencies": {
|
17
17
|
"@glimmer/component": "^1.0.4",
|
18
18
|
"@glimmer/tracking": "^1.0.4",
|
19
|
-
"@projectcaluma/ember-core": "^11.0.0-beta.
|
19
|
+
"@projectcaluma/ember-core": "^11.0.0-beta.2",
|
20
20
|
"ember-apollo-client": "^3.2.0",
|
21
|
-
"ember-auto-import": "^2.
|
21
|
+
"ember-auto-import": "^2.4.0",
|
22
|
+
"ember-autoresize-modifier": "^0.5.0",
|
22
23
|
"ember-cli-babel": "^7.26.11",
|
23
24
|
"ember-cli-htmlbars": "^6.0.1",
|
24
25
|
"ember-cli-showdown": "^6.0.1",
|
25
26
|
"ember-composable-helpers": "^5.0.0",
|
26
|
-
"ember-fetch": "^8.
|
27
|
+
"ember-fetch": "^8.1.1",
|
27
28
|
"ember-in-viewport": "^4.0.0",
|
28
29
|
"ember-intl": "^5.7.2",
|
29
|
-
"ember-math-helpers": "^2.18.
|
30
|
+
"ember-math-helpers": "^2.18.1",
|
30
31
|
"ember-pikaday": "^3.0.0",
|
31
32
|
"ember-power-select": "^5.0.3",
|
32
|
-
"ember-resources": "^4.
|
33
|
-
"ember-uikit": "^
|
33
|
+
"ember-resources": "^4.2.0",
|
34
|
+
"ember-uikit": "^5.0.0-beta.9",
|
35
|
+
"ember-validators": "^4.1.0",
|
34
36
|
"graphql": "^15.8.0",
|
35
37
|
"jexl": "^2.3.0",
|
36
38
|
"lodash.isequal": "^4.5.0",
|
@@ -40,15 +42,16 @@
|
|
40
42
|
"devDependencies": {
|
41
43
|
"@ember/optional-features": "2.0.0",
|
42
44
|
"@ember/test-helpers": "2.6.0",
|
43
|
-
"@embroider/test-setup": "0.
|
44
|
-
"@
|
45
|
-
"@projectcaluma/ember-
|
45
|
+
"@embroider/test-setup": "1.0.0",
|
46
|
+
"@faker-js/faker": "6.0.0-alpha.5",
|
47
|
+
"@projectcaluma/ember-testing": "10.2.0-beta.2",
|
48
|
+
"@projectcaluma/ember-workflow": "11.0.0-beta.3",
|
46
49
|
"broccoli-asset-rev": "3.0.0",
|
47
50
|
"ember-cli": "3.28.5",
|
48
51
|
"ember-cli-code-coverage": "1.0.3",
|
49
52
|
"ember-cli-dependency-checker": "3.2.0",
|
50
53
|
"ember-cli-inject-live-reload": "2.1.0",
|
51
|
-
"ember-cli-mirage": "2.
|
54
|
+
"ember-cli-mirage": "2.4.0",
|
52
55
|
"ember-cli-sri": "2.1.1",
|
53
56
|
"ember-cli-terser": "4.0.2",
|
54
57
|
"ember-disable-prototype-extensions": "1.1.3",
|
@@ -60,13 +63,13 @@
|
|
60
63
|
"ember-source": "3.28.8",
|
61
64
|
"ember-source-channel-url": "3.0.0",
|
62
65
|
"ember-try": "2.0.0",
|
63
|
-
"faker": "5.5.3",
|
64
66
|
"loader.js": "4.7.0",
|
67
|
+
"miragejs": "0.1.43",
|
65
68
|
"npm-run-all": "4.1.5",
|
66
69
|
"qunit": "2.17.2",
|
67
70
|
"qunit-dom": "2.0.0",
|
68
71
|
"uuid": "8.3.2",
|
69
|
-
"webpack": "5.
|
72
|
+
"webpack": "5.68.0"
|
70
73
|
},
|
71
74
|
"engines": {
|
72
75
|
"node": "12.* || 14.* || >= 16"
|