diff --git a/ui/app/models/namespace.js b/ui/app/models/namespace.js index 0cfc5949d8..5a2b2174b6 100644 --- a/ui/app/models/namespace.js +++ b/ui/app/models/namespace.js @@ -5,19 +5,23 @@ import Model, { attr } from '@ember-data/model'; import { withExpandedAttributes } from 'vault/decorators/model-expanded-attributes'; +import { withModelValidations } from 'vault/decorators/model-validations'; @withExpandedAttributes() +@withModelValidations({ + path: [ + { type: 'presence', message: `Path can't be blank.` }, + { type: 'endsInSlash', message: `Path can't end in forward slash '/'.` }, + { + type: 'containsWhiteSpace', + message: "Path can't contain whitespace.", + }, + ], +}) export default class NamespaceModel extends Model { - @attr('string', { - validationAttr: 'pathIsValid', - invalidMessage: 'You have entered and invalid path please only include letters, numbers, -, ., and _.', - }) + @attr('string') path; - get pathIsValid() { - return this.path && this.path.match(/^[\w\d-.]+$/g); - } - get fields() { return ['path'].map((f) => this.allByKey[f]); } diff --git a/ui/lib/core/addon/components/edit-form.js b/ui/lib/core/addon/components/edit-form.js index e71c09f7d8..12f8b8205d 100644 --- a/ui/lib/core/addon/components/edit-form.js +++ b/ui/lib/core/addon/components/edit-form.js @@ -15,6 +15,9 @@ export default Component.extend({ layout, flashMessages: service(), + // internal validations + invalidFormAlert: '', + modelValidations: null, // public API model: null, successMessage: 'Saved!', @@ -38,10 +41,25 @@ export default Component.extend({ // is the case, set this value to true callOnSaveAfterRender: false, + checkModelValidity(model) { + if (model.validate) { + const { isValid, state, invalidFormMessage } = model.validate(); + this.set('modelValidations', state); + this.set('invalidFormAlert', invalidFormMessage); + return isValid; + } + // no validations on model; return true + return true; + }, + save: task( waitFor(function* (model, options = { method: 'save' }) { const { method } = options; const messageKey = method === 'save' ? 'successMessage' : 'deleteSuccessMessage'; + if (method === 'save' && !this.checkModelValidity(model)) { + // if saving and model invalid, don't continue + return; + } try { yield model[method](); } catch (err) { diff --git a/ui/lib/core/addon/components/form-field.hbs b/ui/lib/core/addon/components/form-field.hbs index 7c9e4b5af0..31be930f44 100644 --- a/ui/lib/core/addon/components/form-field.hbs +++ b/ui/lib/core/addon/components/form-field.hbs @@ -281,12 +281,6 @@ class="input {{if this.validationError 'has-error-border'}}" maxLength={{@attr.options.characterLimit}} /> - {{! TODO: explore removing in favor of new model validations pattern since it is only used on the namespace model }} - {{#if @attr.options.validationAttr}} - {{#if (and (get @model this.valuePath) (not (get @model @attr.options.validationAttr)))}} - - {{/if}} - {{/if}} {{/if}} {{else if (or (eq @attr.type "boolean") (eq @attr.options.editType "boolean"))}} diff --git a/ui/lib/core/addon/templates/components/form-save-buttons.hbs b/ui/lib/core/addon/components/form-save-buttons.hbs similarity index 77% rename from ui/lib/core/addon/templates/components/form-save-buttons.hbs rename to ui/lib/core/addon/components/form-save-buttons.hbs index cf55864579..2f6194d7a9 100644 --- a/ui/lib/core/addon/templates/components/form-save-buttons.hbs +++ b/ui/lib/core/addon/components/form-save-buttons.hbs @@ -3,7 +3,7 @@ SPDX-License-Identifier: BUSL-1.1 ~}} -
+
{{/if}}
+ {{yield to="error"}}
\ No newline at end of file diff --git a/ui/lib/core/addon/components/form-save-buttons.js b/ui/lib/core/addon/components/form-save-buttons.js index 24cffe4ea1..a5029c1f6d 100644 --- a/ui/lib/core/addon/components/form-save-buttons.js +++ b/ui/lib/core/addon/components/form-save-buttons.js @@ -3,18 +3,19 @@ * SPDX-License-Identifier: BUSL-1.1 */ -import Component from '@ember/component'; -import { computed } from '@ember/object'; -import layout from '../templates/components/form-save-buttons'; +import Component from '@glimmer/component'; /** * @module FormSaveButtons * `FormSaveButtons` displays a button save and a cancel button at the bottom of a form. + * To show an overall inline error message, use the :error yielded block like shown below. * * @example * ```js * + * "foo.route"}}> + * <:error>This is an error + * * ``` * * @param [saveButtonText="Save" {String}] - The text that will be rendered on the Save button. @@ -26,13 +27,11 @@ import layout from '../templates/components/form-save-buttons'; * */ -export default Component.extend({ - layout, - tagName: '', - - cancelLink: computed('cancelLinkParams.[]', function () { - if (!Array.isArray(this.cancelLinkParams) || !this.cancelLinkParams.length) return; - const [route, ...models] = this.cancelLinkParams; +export default class FormSaveButtons extends Component { + get cancelLink() { + const { cancelLinkParams } = this.args; + if (!Array.isArray(cancelLinkParams) || !cancelLinkParams.length) return null; + const [route, ...models] = cancelLinkParams; return { route, models }; - }), -}); + } +} diff --git a/ui/lib/core/addon/templates/components/edit-form.hbs b/ui/lib/core/addon/templates/components/edit-form.hbs index 11248b5479..02f0b12a0e 100644 --- a/ui/lib/core/addon/templates/components/edit-form.hbs +++ b/ui/lib/core/addon/templates/components/edit-form.hbs @@ -9,17 +9,29 @@ {{#if (or this.model.fields this.model.attrs)}} {{#each (or this.model.fields this.model.attrs) as |attr|}} - + {{/each}} {{else if this.model.fieldGroups}} - + {{/if}}
+ > + <:error> + {{#if this.invalidFormAlert}} + + {{/if}} + + \ No newline at end of file