@projectcaluma/ember-form-builder 12.6.0 → 12.8.0

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.
@@ -4,11 +4,14 @@
4
4
  <div class="uk-form-controls">
5
5
  <div
6
6
  name={{@name}}
7
- class="uk-textarea cfb-code-editor {{concat 'language-' @language}}"
7
+ class="uk-textarea cfb-code-editor
8
+ {{concat 'language-' @language}}
9
+ {{if @isValid 'uk-form-success'}}
10
+ {{if @isInvalid 'uk-form-danger'}}"
8
11
  {{did-insert this.didInsertNode}}
9
12
  {{will-destroy this.willDestroyNode}}
10
13
  {{autoresize mode="height"}}
11
- {{on "blur" @setDirty}}
14
+ {{on "blur" this.onBlur}}
12
15
  ></div>
13
16
  </div>
14
17
 
@@ -6,6 +6,8 @@ import hljs from "highlight.js/lib/core";
6
6
  import json from "highlight.js/lib/languages/json";
7
7
  import markdown from "highlight.js/lib/languages/markdown";
8
8
  import jexl from "highlightjs-jexl/src/languages/jexl";
9
+ import isEqual from "lodash.isequal";
10
+ import "highlight.js/styles/github.css";
9
11
 
10
12
  hljs.configure({ ignoreUnescapedHTML: true });
11
13
 
@@ -15,14 +17,15 @@ hljs.registerLanguage("jexl", jexl);
15
17
 
16
18
  export default class CfbCodeEditorComponent extends Component {
17
19
  _editor = null;
18
- _cursor = null;
19
- _lastValue = null;
20
-
21
- get value() {
22
- const value = this.args.value;
23
-
24
- if (this.args.language === "json" && typeof value === "object") {
25
- return JSON.stringify(value?.unwrap?.() ?? value, null, 2);
20
+ _lastValue = this.args.value;
21
+
22
+ get stringValue() {
23
+ if (this.args.language === "json" && typeof this.args.value === "object") {
24
+ return JSON.stringify(
25
+ this.args.value?.unwrap?.() ?? this.args.value,
26
+ null,
27
+ 2,
28
+ );
26
29
  }
27
30
 
28
31
  return this.args.value;
@@ -30,10 +33,6 @@ export default class CfbCodeEditorComponent extends Component {
30
33
 
31
34
  @action
32
35
  onUpdate(value) {
33
- if (this._lastValue === value) return;
34
-
35
- this._cursor = this._editor.save();
36
-
37
36
  if (this.args.language === "json") {
38
37
  try {
39
38
  value = JSON.parse(value);
@@ -42,26 +41,37 @@ export default class CfbCodeEditorComponent extends Component {
42
41
  }
43
42
  }
44
43
 
44
+ if (isEqual(this._lastValue, value)) return;
45
+
45
46
  this._lastValue = value;
46
47
  this.args.update(value);
47
48
  }
48
49
 
49
50
  @action
50
51
  updateCode() {
51
- this._editor.updateCode(this.value);
52
+ if (isEqual(this._lastValue, this.args.value)) return;
52
53
 
53
- if (this._cursor) {
54
- this._editor.restore(this._cursor);
55
- this._cursor = null;
56
- }
54
+ this._editor.updateCode(this.stringValue, false);
55
+ }
56
+
57
+ @action
58
+ onBlur() {
59
+ this._editor.updateCode(this.stringValue);
60
+ this.args.setDirty();
57
61
  }
58
62
 
59
63
  @action
60
64
  didInsertNode(element) {
61
- this._editor = CodeJar(element, (editor) => hljs.highlightElement(editor));
62
- this._editor.onUpdate(this.onUpdate);
65
+ this._editor = CodeJar(element, (editor) => {
66
+ editor.removeAttribute("data-highlighted");
67
+ hljs.highlightElement(editor);
68
+ });
69
+
70
+ // set initial value
71
+ this._editor.updateCode(this.stringValue);
63
72
 
64
- this.updateCode();
73
+ // register update method
74
+ this._editor.onUpdate(this.onUpdate);
65
75
 
66
76
  // eslint-disable-next-line ember/no-observers
67
77
  addObserver(this.args, "value", this, "updateCode");
@@ -23,8 +23,8 @@ export default class CfbFormEditorQuestionListItem extends Component {
23
23
  return required === true
24
24
  ? "required"
25
25
  : required
26
- ? "conditional"
27
- : "not-required";
26
+ ? "conditional"
27
+ : "not-required";
28
28
  }
29
29
 
30
30
  get hidden() {
@@ -0,0 +1,50 @@
1
+ {{#if this.otherForms}}
2
+ <a
3
+ ...attributes
4
+ href="#"
5
+ {{on "click" (fn (mut this.modalVisible) true)}}
6
+ data-test-show-question-usage-modal-link
7
+ >
8
+ {{this.title}}
9
+ </a>
10
+ {{/if}}
11
+
12
+ <UkModal
13
+ @visible={{this.modalVisible}}
14
+ @stack={{true}}
15
+ @onHide={{fn (mut this.modalVisible) false}}
16
+ data-test-question-usage-modal
17
+ as |modal|
18
+ >
19
+ <modal.header>
20
+ {{t "caluma.form-builder.question.usage.references-heading"}}
21
+ </modal.header>
22
+ <modal.body>
23
+ <ul class="uk-list uk-list-divider">
24
+ {{#each this.forms.value as |form|}}
25
+ <li data-test-question-form-item={{form.node.slug}}>
26
+ <div class="uk-flex uk-flex-middle">
27
+ <span class="uk-width-expand">
28
+ <LinkTo @route="edit" @model={{form.node.slug}}>
29
+ {{form.node.name}}
30
+ </LinkTo>
31
+ </span>
32
+
33
+ {{#if form.node.isArchived}}
34
+ <UkBadge>
35
+ {{t "caluma.form-builder.form.isArchived"}}
36
+ </UkBadge>
37
+ {{/if}}
38
+
39
+ {{#unless form.node.isPublished}}
40
+ <UkBadge class="uk-margin-small-left">
41
+ {{t "caluma.form-builder.question.usage.not-published"}}
42
+ </UkBadge>
43
+ {{/unless}}
44
+ </div>
45
+ <div class="uk-text-muted uk-text-small">{{form.node.slug}}</div>
46
+ </li>
47
+ {{/each}}
48
+ </ul>
49
+ </modal.body>
50
+ </UkModal>
@@ -0,0 +1,46 @@
1
+ import { inject as service } from "@ember/service";
2
+ import Component from "@glimmer/component";
3
+ import { tracked } from "@glimmer/tracking";
4
+ import { queryManager } from "ember-apollo-client";
5
+ import { trackedFunction } from "ember-resources/util/function";
6
+
7
+ import allFormsForQuestionQuery from "@projectcaluma/ember-form-builder/gql/queries/all-forms-for-question.graphql";
8
+
9
+ export default class CfbFormEditorQuestionUsage extends Component {
10
+ @service intl;
11
+ @queryManager apollo;
12
+
13
+ @tracked modalVisible = false;
14
+
15
+ get title() {
16
+ return this.intl.t("caluma.form-builder.question.usage.title", {
17
+ n: this.otherForms,
18
+ // for highlighting the number we use the <b> tag
19
+ htmlSafe: true,
20
+ });
21
+ }
22
+
23
+ get otherForms() {
24
+ return this.forms.value?.length - 1 ?? 0;
25
+ }
26
+
27
+ forms = trackedFunction(this, async () => {
28
+ try {
29
+ const forms = await this.apollo.query(
30
+ {
31
+ query: allFormsForQuestionQuery,
32
+ variables: {
33
+ slug: this.args.model.slug,
34
+ },
35
+ fetchPolicy: "no-cache",
36
+ },
37
+ "allForms.edges",
38
+ );
39
+
40
+ return forms;
41
+ } catch (error) {
42
+ console.error(error);
43
+ return { value: [] };
44
+ }
45
+ });
46
+ }
@@ -440,7 +440,9 @@
440
440
  />
441
441
  {{/if}}
442
442
 
443
- <div class="uk-text-right">
443
+ <div class="uk-flex uk-flex-between uk-flex-middle uk-flex-row-reverse">
444
+ <CfbFormEditor::QuestionUsage @model={{f.model}} class="uk-flex-last" />
445
+
444
446
  <f.submit
445
447
  @disabled={{f.loading}}
446
448
  @label={{t "caluma.form-builder.global.save"}}
@@ -42,8 +42,8 @@ export default class ComponentsCfbFormListComponent extends Component {
42
42
  this.args.category === "active"
43
43
  ? { isArchived: false }
44
44
  : this.args.category === "archived"
45
- ? { isArchived: true }
46
- : null;
45
+ ? { isArchived: true }
46
+ : null;
47
47
 
48
48
  const search = this.args.search ? { search: this.args.search } : null;
49
49
 
@@ -51,8 +51,8 @@ export default class ComponentsCfbFormListComponent extends Component {
51
51
  this.args.category === "unpublished"
52
52
  ? { isPublished: false }
53
53
  : this.args.category === "published"
54
- ? { isPublished: true }
55
- : null;
54
+ ? { isPublished: true }
55
+ : null;
56
56
 
57
57
  return [isArchived, isPublished, search].filter(Boolean) || null;
58
58
  }
@@ -0,0 +1,13 @@
1
+ query AllFormsForQuestion($slug: String!) {
2
+ allForms(filter: [{ questions: [$slug] }]) {
3
+ edges {
4
+ node {
5
+ id
6
+ slug
7
+ name
8
+ isArchived
9
+ isPublished
10
+ }
11
+ }
12
+ }
13
+ }
@@ -1,6 +1,5 @@
1
1
  import Route from "@ember/routing/route";
2
2
  import { inject as service } from "@ember/service";
3
- import { t } from "ember-intl";
4
3
 
5
4
  import { navigationTitle } from "@projectcaluma/ember-form-builder/decorators";
6
5
 
@@ -8,6 +7,7 @@ export default class ApplicationRoute extends Route {
8
7
  @service intl;
9
8
 
10
9
  @navigationTitle
11
- @t("caluma.form-builder.form.allForms")
12
- title;
10
+ get title() {
11
+ return this.intl.t("caluma.form-builder.form.allForms");
12
+ }
13
13
  }
@@ -1,6 +1,5 @@
1
1
  import Route from "@ember/routing/route";
2
2
  import { inject as service } from "@ember/service";
3
- import { t } from "ember-intl";
4
3
 
5
4
  import { navigationTitle } from "@projectcaluma/ember-form-builder/decorators";
6
5
 
@@ -8,8 +7,9 @@ export default class EditQuestionsNewRoute extends Route {
8
7
  @service intl;
9
8
 
10
9
  @navigationTitle
11
- @t("caluma.form-builder.question.new")
12
- title;
10
+ get title() {
11
+ return this.intl.t("caluma.form-builder.question.new");
12
+ }
13
13
 
14
14
  model() {
15
15
  return this.modelFor("edit");
@@ -1,6 +1,5 @@
1
1
  import Route from "@ember/routing/route";
2
2
  import { inject as service } from "@ember/service";
3
- import { t } from "ember-intl";
4
3
 
5
4
  import { navigationTitle } from "@projectcaluma/ember-form-builder/decorators";
6
5
 
@@ -8,6 +7,7 @@ export default class NewRoute extends Route {
8
7
  @service intl;
9
8
 
10
9
  @navigationTitle
11
- @t("caluma.form-builder.form.new")
12
- title;
10
+ get title() {
11
+ return this.intl.t("caluma.form-builder.form.new");
12
+ }
13
13
  }
@@ -0,0 +1 @@
1
+ export { default } from "@projectcaluma/ember-form-builder/components/cfb-form-editor/question-usage";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@projectcaluma/ember-form-builder",
3
- "version": "12.6.0",
3
+ "version": "12.8.0",
4
4
  "description": "Ember engine for building Caluma forms.",
5
5
  "keywords": [
6
6
  "ember-addon",
@@ -10,39 +10,41 @@
10
10
  "homepage": "https://docs.caluma.io/ember-caluma",
11
11
  "repository": "github:projectcaluma/ember-caluma",
12
12
  "dependencies": {
13
- "@ember/legacy-built-in-components": "^0.4.2",
13
+ "@babel/core": "^7.23.6",
14
+ "@ember/legacy-built-in-components": "^0.5.0",
14
15
  "@ember/render-modifiers": "^2.1.0",
15
16
  "@ember/string": "^3.1.1",
16
- "@embroider/macros": "^1.13.0",
17
+ "@embroider/macros": "^1.13.4",
17
18
  "@glimmer/component": "^1.1.2",
18
19
  "@glimmer/tracking": "^1.1.2",
19
- "codejar": "^3.7.0",
20
+ "codejar": "^4.2.0",
20
21
  "ember-apollo-client": "~4.0.2",
21
- "ember-auto-import": "^2.6.3",
22
+ "ember-auto-import": "^2.7.1",
22
23
  "ember-changeset": "^4.1.2",
23
24
  "ember-changeset-validations": "^4.1.1",
24
- "ember-cli-babel": "^7.26.11",
25
- "ember-cli-htmlbars": "^6.2.0",
25
+ "ember-cli-babel": "^8.2.0",
26
+ "ember-cli-htmlbars": "^6.3.0",
26
27
  "ember-composable-helpers": "^5.0.0",
27
- "ember-concurrency": "^3.0.0",
28
- "ember-engines-router-service": "^0.3.0",
28
+ "ember-concurrency": "^3.1.1",
29
+ "ember-engines-router-service": "^0.5.0",
29
30
  "ember-fetch": "^8.1.2",
30
31
  "ember-flatpickr": "^4.0.0",
31
- "ember-intl": "^5.7.2",
32
- "ember-math-helpers": "^3.0.0",
33
- "ember-power-select": "^7.1.0",
34
- "ember-resources": "^6.4.0",
32
+ "ember-intl": "^6.4.0",
33
+ "ember-math-helpers": "^4.0.0",
34
+ "ember-power-select": "^7.2.0",
35
+ "ember-resources": "^6.4.2",
35
36
  "ember-test-selectors": "^6.0.0",
36
- "ember-uikit": "^8.0.0",
37
- "ember-validated-form": "^6.2.0",
37
+ "ember-uikit": "^9.0.0",
38
+ "ember-validated-form": "^7.0.0",
38
39
  "graphql": "^15.8.0",
39
40
  "graphql-tag": "^2.12.6",
40
- "highlight.js": "^11.8.0",
41
+ "highlight.js": "^11.9.0",
41
42
  "highlightjs-jexl": "^0.0.5",
42
43
  "jexl": "^2.3.0",
43
- "uikit": "^3.16.26",
44
- "@projectcaluma/ember-core": "^12.6.0",
45
- "@projectcaluma/ember-form": "^12.6.0"
44
+ "lodash.isequal": "^4.5.0",
45
+ "uikit": "^3.17.11",
46
+ "@projectcaluma/ember-form": "^12.8.0",
47
+ "@projectcaluma/ember-core": "^12.8.0"
46
48
  },
47
49
  "//": [
48
50
  "TODO: remove obsolete dependency to `ember-data` which is only necessary",
@@ -52,39 +54,51 @@
52
54
  ],
53
55
  "devDependencies": {
54
56
  "@ember/optional-features": "2.0.0",
55
- "@ember/test-helpers": "3.2.0",
56
- "@embroider/test-setup": "3.0.1",
57
- "@faker-js/faker": "8.0.2",
57
+ "@ember/test-helpers": "3.2.1",
58
+ "@embroider/test-setup": "3.0.3",
59
+ "@faker-js/faker": "8.3.1",
58
60
  "broccoli-asset-rev": "3.0.0",
59
61
  "ember-autoresize-modifier": "0.7.0",
60
- "ember-cli": "4.12.2",
61
- "ember-cli-code-coverage": "2.0.0",
62
+ "ember-cli": "5.5.0",
63
+ "ember-cli-clean-css": "3.0.0",
64
+ "ember-cli-code-coverage": "2.0.3",
62
65
  "ember-cli-dependency-checker": "3.3.2",
63
66
  "ember-cli-inject-live-reload": "2.1.0",
64
- "ember-cli-mirage": "3.0.0-alpha.3",
67
+ "ember-cli-mirage": "3.0.2",
65
68
  "ember-cli-sri": "2.1.1",
66
69
  "ember-cli-terser": "4.0.2",
67
- "ember-data": "4.12.3",
70
+ "ember-data": "5.3.0",
68
71
  "ember-engines": "0.9.0",
69
72
  "ember-load-initializers": "2.1.2",
70
- "ember-qunit": "7.0.0",
71
- "ember-resolver": "11.0.0",
72
- "ember-source": "4.12.3",
73
+ "ember-qunit": "8.0.2",
74
+ "ember-resolver": "11.0.1",
75
+ "ember-source": "5.5.0",
73
76
  "ember-source-channel-url": "3.0.0",
74
- "ember-try": "2.0.0",
77
+ "ember-try": "3.0.0",
75
78
  "loader.js": "4.7.0",
76
- "miragejs": "0.1.47",
77
- "qunit": "2.19.4",
78
- "qunit-dom": "2.0.0",
79
+ "miragejs": "0.1.48",
80
+ "qunit": "2.20.0",
81
+ "qunit-dom": "3.0.0",
79
82
  "webpack": "5.89.0",
80
- "@projectcaluma/ember-testing": "12.6.0"
83
+ "@projectcaluma/ember-testing": "12.8.0"
81
84
  },
82
85
  "peerDependencies": {
83
86
  "ember-engines": "^0.9.0",
84
87
  "ember-source": "^4.0.0"
85
88
  },
89
+ "dependenciesMeta": {
90
+ "@projectcaluma/ember-core": {
91
+ "injected": true
92
+ },
93
+ "@projectcaluma/ember-form": {
94
+ "injected": true
95
+ },
96
+ "@projectcaluma/ember-testing": {
97
+ "injected": true
98
+ }
99
+ },
86
100
  "engines": {
87
- "node": "14.* || 16.* || >= 18"
101
+ "node": ">= 18"
88
102
  },
89
103
  "ember": {
90
104
  "edition": "octane"
@@ -134,6 +134,11 @@ caluma:
134
134
 
135
135
  hideLabel: "Label verstecken"
136
136
 
137
+ usage:
138
+ title: "Diese Frage wird in {n,plural, =1 {<b>einem</b> Formular} other {<b>#</b> Formularen}} verwendet."
139
+ references-heading: "Alle Verweise auf diese Frage"
140
+ not-published: "nicht publiziert"
141
+
137
142
  options:
138
143
  delete: "Option löschen"
139
144
  archive: "Option archivieren (verstecken)"
@@ -134,6 +134,11 @@ caluma:
134
134
 
135
135
  hideLabel: "Hide label"
136
136
 
137
+ usage:
138
+ title: "This question is used in {n,plural, =1 {<b>another</b> form} other {<b>#</b> other forms}}"
139
+ references-heading: "All references of this question"
140
+ not-published: "not published"
141
+
137
142
  options:
138
143
  delete: "Delete option"
139
144
  archive: "Archive (hide) option"
@@ -134,6 +134,11 @@ caluma:
134
134
 
135
135
  hideLabel: "Cacher l'étiquette"
136
136
 
137
+ usage:
138
+ title: "Cette question est {n,plural, =1 {utilisé sous <b>une</b> forme} other {utilisé sous <b>#</b> formes}}."
139
+ references-heading: "Toutes les références à cette question"
140
+ not-published: "non publié"
141
+
137
142
  options:
138
143
  delete: "Supprimer l'option"
139
144
  archive: "Archiver (masquer) l'option"
@@ -0,0 +1,10 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "declarationDir": "declarations",
5
+ "emitDeclarationOnly": true,
6
+ "noEmit": false,
7
+ "rootDir": "."
8
+ },
9
+ "include": ["addon", "addon-test-support"]
10
+ }