Skip to content

Commit

Permalink
fix(form-builder): improve validation of slugs with namespaces
Browse files Browse the repository at this point in the history
- Fix display of namespaces / prefixes on slugs
- Convert manual slug uniqueness validation to proper validator
- Validate option slugs with the prefix of the question and check for
  uniqueness as well

Fixes #1264
Closes #1283
  • Loading branch information
anehx committed Apr 25, 2023
1 parent 39df7e8 commit 40848b4
Show file tree
Hide file tree
Showing 33 changed files with 694 additions and 536 deletions.
2 changes: 2 additions & 0 deletions packages/-ember-caluma/app/services/caluma-options.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ export default class CustomCalumaOptionsService extends CalumaOptionsService {
@service intl;
@service store;

namespace = "demo";

constructor(...args) {
super(...args);

Expand Down
6 changes: 6 additions & 0 deletions packages/form-builder/addon/-private/application.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/**
* This module holds the application instance which is needed in the validations
* to allow context of the ember container in order to allow injections of
* services. The `instance` property will be set in an instance initializer.
*/
export default { instance: null };
47 changes: 12 additions & 35 deletions packages/form-builder/addon/components/cfb-form-editor/general.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -16,40 +16,17 @@
@on-update={{this.updateName}}
/>

{{#if (or @slug (not this.prefix))}}
<f.input
@type="text"
@name="slug"
@label={{t "caluma.form-builder.form.slug"}}
@required={{true}}
@disabled={{@slug}}
@on-update={{this.updateSlug}}
/>
{{else}}
<f.input
@name="slug"
@required={{true}}
@disabled={{@slug}}
@label={{t "caluma.form-builder.question.slug"}}
@on-update={{this.updateSlug value="target.value"}}
as |fi|
>
<div class="cfb-prefixed">
<span class="cfb-prefixed-slug">{{this.prefix}}</span>
<f.input
@type="text"
@model={{fi.model}}
@name={{fi.name}}
@value={{fi.value}}
@update={{fi.update}}
@setDirty={{fi.setDirty}}
@inputId={{fi.inputId}}
@isValid={{fi.isValid}}
@isInvalid={{fi.isInvalid}}
/>
</div>
</f.input>
{{/if}}
<f.input
@type="text"
@name="slug"
@label={{t "caluma.form-builder.form.slug"}}
@required={{true}}
@disabled={{not (is-empty @slug)}}
@renderComponent={{component
"cfb-slug-input"
onUnlink=(fn (mut this.slugUnlinked) true)
}}
/>

<f.input
@name="description"
Expand All @@ -74,7 +51,7 @@

<div class="uk-text-right">
<f.submit
@disabled={{or f.loading f.model.isInvalid}}
@disabled={{f.loading}}
@label={{t "caluma.form-builder.global.save"}}
/>
</div>
Expand Down
49 changes: 6 additions & 43 deletions packages/form-builder/addon/components/cfb-form-editor/general.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
import { action } from "@ember/object";
import { inject as service } from "@ember/service";
import { macroCondition, isTesting } from "@embroider/macros";
import Component from "@glimmer/component";
import { queryManager } from "ember-apollo-client";
import { timeout, restartableTask, dropTask } from "ember-concurrency";
import { restartableTask, dropTask } from "ember-concurrency";
import { trackedTask } from "ember-resources/util/ember-concurrency";

import FormValidations from "../../validations/form";

import slugify from "@projectcaluma/ember-core/utils/slugify";
import saveFormMutation from "@projectcaluma/ember-form-builder/gql/mutations/save-form.graphql";
import checkFormSlugQuery from "@projectcaluma/ember-form-builder/gql/queries/check-form-slug.graphql";
import formEditorGeneralQuery from "@projectcaluma/ember-form-builder/gql/queries/form-editor-general.graphql";

export default class CfbFormEditorGeneral extends Component {
Expand Down Expand Up @@ -61,16 +59,13 @@ export default class CfbFormEditorGeneral extends Component {
@dropTask
*submit(changeset) {
try {
const slug =
((!this.args.slug && this.prefix) || "") + changeset.get("slug");

const form = yield this.apollo.mutate(
{
mutation: saveFormMutation,
variables: {
input: {
name: changeset.get("name"),
slug,
slug: changeset.get("slug"),
description: changeset.get("description"),
isArchived: changeset.get("isArchived"),
isPublished: changeset.get("isPublished"),
Expand Down Expand Up @@ -100,47 +95,15 @@ export default class CfbFormEditorGeneral extends Component {
}
}

@restartableTask
*validateSlug(slug, changeset) {
/* istanbul ignore next */
if (macroCondition(isTesting())) {
// no timeout
} else {
yield timeout(500);
}

const res = yield this.apollo.query(
{
query: checkFormSlugQuery,
variables: { slug },
},
"allForms.edges"
);

if (res && res.length) {
changeset.pushErrors(
"slug",
this.intl.t("caluma.form-builder.validations.form.slug")
);
}
}

@action
updateName(value, changeset) {
changeset.set("name", value);

if (!this.args.slug) {
const slug = slugify(value, { locale: this.intl.primaryLocale });
changeset.set("slug", slug);
if (!this.args.slug && !this.slugUnlinked) {
const slugifiedName = slugify(value, { locale: this.intl.primaryLocale });
const slug = slugifiedName ? this.prefix + slugifiedName : "";

this.validateSlug.perform(this.prefix + slug, changeset);
changeset.set("slug", slug);
}
}

@action
updateSlug(value, changeset) {
changeset.set("slug", value);

this.validateSlug.perform(this.prefix + value, changeset);
}
}
47 changes: 12 additions & 35 deletions packages/form-builder/addon/components/cfb-form-editor/question.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
@hint={{t "caluma.form-builder.question.type-disabled"}}
@name="__typename"
@required={{true}}
@disabled={{@slug}}
@disabled={{not (is-empty @slug)}}
@on-update={{changeset-set f.model "__typename"}}
/>

Expand All @@ -47,39 +47,16 @@

<div uk-grid class="uk-grid-small uk-margin">
<div class="uk-width-expand">
{{#if (or @slug (not this.prefix))}}
<f.input
@name="slug"
@label={{t "caluma.form-builder.question.slug"}}
@required={{true}}
@disabled={{@slug}}
@on-update={{this.updateSlug}}
/>
{{else}}
<f.input
@name="slug"
@label={{t "caluma.form-builder.question.slug"}}
@required={{true}}
@disabled={{@slug}}
@on-update={{this.updateSlug value="target.value"}}
as |fi|
>
<div class="cfb-prefixed">
<span class="cfb-prefixed-slug">{{this.prefix}}</span>

<f.input
@model={{fi.model}}
@name={{fi.name}}
@value={{fi.value}}
@update={{fi.update}}
@setDirty={{fi.setDirty}}
@inputId={{fi.inputId}}
@isValid={{fi.isValid}}
@isInvalid={{fi.isInvalid}}
/>
</div>
</f.input>
{{/if}}
<f.input
@name="slug"
@label={{t "caluma.form-builder.question.slug"}}
@required={{true}}
@disabled={{not (is-empty @slug)}}
@renderComponent={{component
"cfb-slug-input"
onUnlink=(fn (mut this.slugUnlinked) true)
}}
/>
</div>

{{#if
Expand Down Expand Up @@ -459,7 +436,7 @@

<div class="uk-text-right">
<f.submit
@disabled={{or f.loading f.model.isInvalid}}
@disabled={{f.loading}}
@label={{t "caluma.form-builder.global.save"}}
/>
</div>
Expand Down
Loading

0 comments on commit 40848b4

Please sign in to comment.