Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(validation): list invalid fields for the action-button widget #2488

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,12 @@
@label={{t "caluma.form-builder.question.validateOnEnter"}}
@renderComponent={{component "cfb-toggle-switch" size="small"}}
/>
<f.input
@name="showValidation"
@required={{true}}
@label={{t "caluma.form-builder.question.showValidation"}}
@renderComponent={{component "cfb-toggle-switch" size="small"}}
/>
{{/if}}

<f.input
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ export default class CfbFormEditorQuestion extends Component {
action: ACTIONS[0],
color: COLORS[0],
validateOnEnter: false,
showValidation: false,
__typename: Object.keys(TYPES)[0],
},
},
Expand Down Expand Up @@ -348,6 +349,7 @@ export default class CfbFormEditorQuestion extends Component {
action: changeset.get("action"),
color: changeset.get("color"),
validateOnEnter: Boolean(changeset.get("validateOnEnter")),
showValidation: Boolean(changeset.get("showValidation")),
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ mutation SaveActionButtonQuestion($input: SaveActionButtonQuestionInput!) {
action
color
validateOnEnter
showValidation
}
}
clientMutationId
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ query FormEditorQuestion($slug: String!) {
action
color
validateOnEnter
showValidation
}
}
}
Expand Down
1 change: 1 addition & 0 deletions packages/form-builder/translations/de.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ caluma:
action: "Aktion"
color: "Farbe"
validateOnEnter: "Validierung beim Betreten des Fensters"
showValidation: "Validierungs-Fehler anzeigen"

actions:
COMPLETE: "Abschliessen"
Expand Down
1 change: 1 addition & 0 deletions packages/form-builder/translations/en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ caluma:
action: "Action"
color: "Color"
validateOnEnter: "Validate on entering the viewport"
showValidation: "Show validation errors"

actions:
COMPLETE: "Complete"
Expand Down
18 changes: 18 additions & 0 deletions packages/form/addon/components/cf-field/input/action-button.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,24 @@
@validateOnEnter={{this.validateOnEnter}}
as |isValid validate|
>
{{#if (and this.invalidFields.length @field.question.raw.showValidation)}}
<div class="uk-alert uk-alert-danger uk-animation-fade">
<div class="uk-flex-inline uk-flex-middle uk-text-bold">
<UkIcon @icon="warning" class="uk-margin-small-right" />
{{t "caluma.form.validation.error"}}
</div>
<ul class="uk-list uk-list-bullet">
{{#each this.invalidFields as |invalidField|}}
<li>
<LinkTo
@query={{hash displayedForm=invalidField.fieldset.form.slug}}
>{{invalidField.question.raw.label}}</LinkTo>
</li>
{{/each}}
</ul>
</div>
{{/if}}

<WorkItemButton
@workItemId={{this.workItem}}
@mutation={{this.action}}
Expand Down
11 changes: 9 additions & 2 deletions packages/form/addon/components/cf-field/input/action-button.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ if (macroCondition(dependencySatisfies("@projectcaluma/ember-workflow", ""))) {
super(...args);

assert(
"The document must have a `workItemUuid` for `<CfField::Input::ActionButton />` to work.",
this.args.field.document.workItemUuid,
"`<CfField::Input::ActionButton />` did not find a `workItem` related to the `document` or passed via `context.actionButtonWorkItemId`.",
this.args.field.document.workItemUuid ||
this.args.context?.actionButtonWorkItemId,
anehx marked this conversation as resolved.
Show resolved Hide resolved
);
}

Expand All @@ -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 (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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";

Expand All @@ -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 () {
Expand Down Expand Up @@ -85,6 +115,28 @@ module(
assert.verifySteps(["validate"]);
});

test("doesn't show validation errors if not configured", async function (assert) {
await render(
hbs`<CfField::Input::ActionButton @field={{this.invalidField}} />`,
);
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`<CfField::Input::ActionButton @field={{this.invalidField}} />`,
);
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";

Expand Down
1 change: 1 addition & 0 deletions packages/form/translations/de.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:"
1 change: 1 addition & 0 deletions packages/form/translations/en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:"
1 change: 1 addition & 0 deletions packages/form/translations/fr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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 n'ont pas encore été correctement remplies :"
3 changes: 3 additions & 0 deletions packages/testing/addon-mirage-support/factories/question.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ export default Factory.extend({
if (question.validateOnEnter === undefined) {
question.update({ validateOnEnter: false });
}
if (question.showValidation === undefined) {
question.update({ showValidation: false });
}
}
},
});
3 changes: 3 additions & 0 deletions packages/testing/addon/mirage-graphql/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ type ActionButtonQuestion implements Question & Node {
action: ButtonAction!
color: ButtonColor!
validateOnEnter: Boolean!
showValidation: Boolean!
}

input AddFormQuestionInput {
Expand Down Expand Up @@ -1874,6 +1875,7 @@ enum JSONLookupMode {
CONTAINS
ICONTAINS
IN
INTERSECTS
GTE
GT
LTE
Expand Down Expand Up @@ -2633,6 +2635,7 @@ input SaveActionButtonQuestionInput {
action: ButtonAction!
color: ButtonColor!
validateOnEnter: Boolean!
showValidation: Boolean!
clientMutationId: String
}

Expand Down