From d68763bc4c9a5cce77b16a20df29a9e35606e171 Mon Sep 17 00:00:00 2001 From: Jonas Lehmann Date: Thu, 10 Aug 2023 11:37:41 +0200 Subject: [PATCH 1/2] feat(validation): list invalid fields for the action-button widget --- .../cf-field/input/action-button.hbs | 18 ++++++++++++++++++ .../components/cf-field/input/action-button.js | 11 +++++++++-- packages/form/translations/de.yaml | 1 + packages/form/translations/en.yaml | 1 + packages/form/translations/fr.yaml | 1 + 5 files changed, 30 insertions(+), 2 deletions(-) diff --git a/packages/form/addon/components/cf-field/input/action-button.hbs b/packages/form/addon/components/cf-field/input/action-button.hbs index ffbccf26e..a355965c2 100644 --- a/packages/form/addon/components/cf-field/input/action-button.hbs +++ b/packages/form/addon/components/cf-field/input/action-button.hbs @@ -8,6 +8,24 @@ @validateOnEnter={{this.validateOnEnter}} as |isValid validate| > + {{#if (and this.invalidFields.length @context.showValidation)}} +
+
+ + {{t "caluma.form.validation.error"}} +
+ +
+ {{/if}} + ` to work.", - this.args.field.document.workItemUuid, + "The document or context must have a `workItem` for `` to work.", + this.args.field.document.workItemUuid || + this.args.context?.actionButtonWorkItemId, ); } @@ -39,6 +40,12 @@ if (macroCondition(dependencySatisfies("@projectcaluma/ember-workflow", ""))) { ); } + get invalidFields() { + return this.args.field.document.fields.filter( + (field) => !field.hidden && field.isInvalid, + ); + } + @action async beforeMutate(validateFn) { if ( diff --git a/packages/form/translations/de.yaml b/packages/form/translations/de.yaml index cc4a80967..a8f275ae6 100644 --- a/packages/form/translations/de.yaml +++ b/packages/form/translations/de.yaml @@ -51,3 +51,4 @@ caluma: uploadFailed: "Beim Hochladen ist ein Fehler aufgetreten." format: "{errorMsg}" table: "Mindestens eine Zeile der Tabelle wurde nicht korrekt ausgefüllt" + error: "Folgende Fragen sind noch nicht korrekt ausgefüllt:" diff --git a/packages/form/translations/en.yaml b/packages/form/translations/en.yaml index 66b9790c6..78115fe7a 100644 --- a/packages/form/translations/en.yaml +++ b/packages/form/translations/en.yaml @@ -51,3 +51,4 @@ caluma: uploadFailed: "An error occured during upload." format: "{errorMsg}" table: "At least one row of the table was not filled in correctly" + error: "The following questions have not yet been filled in correctly:" diff --git a/packages/form/translations/fr.yaml b/packages/form/translations/fr.yaml index 379a369f3..b671c9d88 100644 --- a/packages/form/translations/fr.yaml +++ b/packages/form/translations/fr.yaml @@ -51,3 +51,4 @@ caluma: uploadFailed: "Une erreur s'est produite pendant le téléchargement." format: "{errorMsg}" table: "Au moins une ligne du tableau n'a pas été remplie correctement" + error: "Les questions suivantes ne sont pas encore correctement remplies :" From 643ea668d3c3eadafb45c087d848ca73f080e4a4 Mon Sep 17 00:00:00 2001 From: Christian Zosel Date: Tue, 22 Aug 2023 18:06:21 +0200 Subject: [PATCH 2/2] fix: refactor to use showValidation flag instead of context, add tests --- .../components/cfb-form-editor/question.hbs | 6 ++ .../components/cfb-form-editor/question.js | 2 + .../save-action-button-question.graphql | 1 + .../gql/queries/form-editor-question.graphql | 1 + packages/form-builder/translations/de.yaml | 1 + packages/form-builder/translations/en.yaml | 1 + .../cf-field/input/action-button.hbs | 2 +- .../cf-field/input/action-button.js | 2 +- .../cf-field/input/action-button-test.js | 88 +++++++++++++++---- packages/form/translations/fr.yaml | 2 +- .../factories/question.js | 3 + .../addon/mirage-graphql/schema.graphql | 3 + 12 files changed, 91 insertions(+), 21 deletions(-) diff --git a/packages/form-builder/addon/components/cfb-form-editor/question.hbs b/packages/form-builder/addon/components/cfb-form-editor/question.hbs index 5821f4437..600b7a7a2 100644 --- a/packages/form-builder/addon/components/cfb-form-editor/question.hbs +++ b/packages/form-builder/addon/components/cfb-form-editor/question.hbs @@ -405,6 +405,12 @@ @label={{t "caluma.form-builder.question.validateOnEnter"}} @renderComponent={{component "cfb-toggle-switch" size="small"}} /> + {{/if}} - {{#if (and this.invalidFields.length @context.showValidation)}} + {{#if (and this.invalidFields.length @field.question.raw.showValidation)}}
diff --git a/packages/form/addon/components/cf-field/input/action-button.js b/packages/form/addon/components/cf-field/input/action-button.js index 19414199c..e55f42632 100644 --- a/packages/form/addon/components/cf-field/input/action-button.js +++ b/packages/form/addon/components/cf-field/input/action-button.js @@ -12,7 +12,7 @@ if (macroCondition(dependencySatisfies("@projectcaluma/ember-workflow", ""))) { super(...args); assert( - "The document or context must have a `workItem` for `` to work.", + "`` did not find a `workItem` related to the `document` or passed via `context.actionButtonWorkItemId`.", this.args.field.document.workItemUuid || this.args.context?.actionButtonWorkItemId, ); diff --git a/packages/form/tests/integration/components/cf-field/input/action-button-test.js b/packages/form/tests/integration/components/cf-field/input/action-button-test.js index 43233a35d..3a33a512a 100644 --- a/packages/form/tests/integration/components/cf-field/input/action-button-test.js +++ b/packages/form/tests/integration/components/cf-field/input/action-button-test.js @@ -3,6 +3,7 @@ import { tracked } from "@glimmer/tracking"; import { hbs } from "ember-cli-htmlbars"; import { setupMirage } from "ember-cli-mirage/test-support"; import { restartableTask } from "ember-concurrency"; +import { setupIntl } from "ember-intl/test-support"; import { module, test } from "qunit"; import UIkit from "uikit"; @@ -13,35 +14,64 @@ module( function (hooks) { setupRenderingTest(hooks); setupMirage(hooks); + setupIntl(hooks); hooks.beforeEach(function (assert) { UIkit.container = this.owner.rootElement; + const validField = new (class { + @tracked isValid = true; + + @restartableTask + *validate() { + yield assert.step("validate"); + } + })(); + + const invalidField = new (class { + @tracked isValid = true; + @tracked hidden = false; + + get isInvalid() { + return !this.isValid; + } + + question = { raw: { label: "foo" } }; + + @restartableTask + validate() { + this.isValid = false; + } + })(); + + const question = { + raw: { + label: "Submit", + infoText: "Really?", + action: "COMPLETE", + color: "SECONDARY", + validateOnEnter: false, + showValidation: false, + }, + }; + this.field = { document: { workItemUuid: this.server.create("work-item", { case: this.server.create("case"), }).id, - fields: [ - new (class { - @tracked isValid = true; - - @restartableTask - *validate() { - yield assert.step("validate"); - } - })(), - ], + fields: [validField], }, - question: { - raw: { - label: "Submit", - infoText: "Really?", - action: "COMPLETE", - color: "SECONDARY", - validateOnEnter: false, - }, + question, + }; + this.invalidField = { + document: { + workItemUuid: this.server.create("work-item", { + case: this.server.create("case"), + }).id, + fields: [invalidField], }, + question, }; this.success = function () { @@ -85,6 +115,28 @@ module( assert.verifySteps(["validate"]); }); + test("doesn't show validation errors if not configured", async function (assert) { + await render( + hbs``, + ); + await click("button.uk-button-secondary"); + + assert.dom(".uk-alert-danger").doesNotExist(); + }); + + test("shows validation errors if configured", async function (assert) { + this.invalidField.question.raw.showValidation = true; + + await render( + hbs``, + ); + await click("button.uk-button-secondary"); + + assert + .dom(".uk-alert-danger") + .hasText("t:caluma.form.validation.error:() foo"); + }); + test("does not validate if action is skip", async function (assert) { this.field.question.raw.action = "skip"; diff --git a/packages/form/translations/fr.yaml b/packages/form/translations/fr.yaml index b671c9d88..7a19a7023 100644 --- a/packages/form/translations/fr.yaml +++ b/packages/form/translations/fr.yaml @@ -51,4 +51,4 @@ caluma: uploadFailed: "Une erreur s'est produite pendant le téléchargement." format: "{errorMsg}" table: "Au moins une ligne du tableau n'a pas été remplie correctement" - error: "Les questions suivantes ne sont pas encore correctement remplies :" + error: "Les questions suivantes n'ont pas encore été correctement remplies :" diff --git a/packages/testing/addon-mirage-support/factories/question.js b/packages/testing/addon-mirage-support/factories/question.js index c6f53fd58..5875ff226 100644 --- a/packages/testing/addon-mirage-support/factories/question.js +++ b/packages/testing/addon-mirage-support/factories/question.js @@ -88,6 +88,9 @@ export default Factory.extend({ if (question.validateOnEnter === undefined) { question.update({ validateOnEnter: false }); } + if (question.showValidation === undefined) { + question.update({ showValidation: false }); + } } }, }); diff --git a/packages/testing/addon/mirage-graphql/schema.graphql b/packages/testing/addon/mirage-graphql/schema.graphql index 9f6fe5e2b..09938c799 100644 --- a/packages/testing/addon/mirage-graphql/schema.graphql +++ b/packages/testing/addon/mirage-graphql/schema.graphql @@ -44,6 +44,7 @@ type ActionButtonQuestion implements Question & Node { action: ButtonAction! color: ButtonColor! validateOnEnter: Boolean! + showValidation: Boolean! } input AddFormQuestionInput { @@ -1874,6 +1875,7 @@ enum JSONLookupMode { CONTAINS ICONTAINS IN + INTERSECTS GTE GT LTE @@ -2633,6 +2635,7 @@ input SaveActionButtonQuestionInput { action: ButtonAction! color: ButtonColor! validateOnEnter: Boolean! + showValidation: Boolean! clientMutationId: String }