mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-10-30 02:02:43 +00:00
UI: Namespace validation update (#22820)
This commit is contained in:
@@ -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]);
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)))}}
|
||||
<AlertInline @type="danger" @message={{@attr.options.invalidMessage}} />
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</div>
|
||||
{{else if (or (eq @attr.type "boolean") (eq @attr.options.editType "boolean"))}}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
SPDX-License-Identifier: BUSL-1.1
|
||||
~}}
|
||||
|
||||
<div class="field is-grouped is-grouped-split is-fullwidth box is-bottomless {{if (eq @includeBox false) 'is-shadowless'}}">
|
||||
<div class="field is-fullwidth box is-bottomless {{if (eq @includeBox false) 'is-shadowless'}}">
|
||||
<div class="field is-grouped">
|
||||
<div class="control">
|
||||
<button
|
||||
@@ -24,10 +24,11 @@
|
||||
{{/if}}
|
||||
{{#if @onCancel}}
|
||||
<div class="control">
|
||||
<button type="button" class="button" onclick={{action this.onCancel}} data-test-cancel-button>
|
||||
<button type="button" class="button" onclick={{action @onCancel}} data-test-cancel-button>
|
||||
{{or @cancelButtonText "Cancel"}}
|
||||
</button>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{yield to="error"}}
|
||||
</div>
|
||||
@@ -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
|
||||
* <FormSaveButtons @saveButtonText="Save" @isSaving={{isSaving}} @cancelLinkParams={{array
|
||||
* "foo.route"}} />
|
||||
* "foo.route"}}>
|
||||
* <:error>This is an error</:error>
|
||||
* </FormSaveButtons>
|
||||
* ```
|
||||
*
|
||||
* @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 };
|
||||
}),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,17 +9,29 @@
|
||||
<NamespaceReminder @mode="save" />
|
||||
{{#if (or this.model.fields this.model.attrs)}}
|
||||
{{#each (or this.model.fields this.model.attrs) as |attr|}}
|
||||
<FormField data-test-field @attr={{attr}} @model={{this.model}} @mode={{@mode}} />
|
||||
<FormField
|
||||
data-test-field
|
||||
@attr={{attr}}
|
||||
@model={{this.model}}
|
||||
@mode={{@mode}}
|
||||
@modelValidations={{this.modelValidations}}
|
||||
/>
|
||||
{{/each}}
|
||||
{{else if this.model.fieldGroups}}
|
||||
<FormFieldGroups @model={{this.model}} @mode={{@mode}} />
|
||||
<FormFieldGroups @model={{this.model}} @mode={{@mode}} @modelValidations={{this.modelValidations}} />
|
||||
{{/if}}
|
||||
</div>
|
||||
<FormSaveButtons
|
||||
@isSaving={{this.save.isRunning}}
|
||||
@saveButtonText={{this.saveButtonText}}
|
||||
@canceLinkParams={{@canceLinkParams}}
|
||||
@cancelLinkParams={{@cancelLinkParams}}
|
||||
@includeBox={{this.includeBox}}
|
||||
@onCancel={{@onCancel}}
|
||||
/>
|
||||
>
|
||||
<:error>
|
||||
{{#if this.invalidFormAlert}}
|
||||
<AlertInline @type="danger" @paddingTop={{true}} @message={{this.invalidFormAlert}} @mimicRefresh={{true}} />
|
||||
{{/if}}
|
||||
</:error>
|
||||
</FormSaveButtons>
|
||||
</form>
|
||||
Reference in New Issue
Block a user