mirror of
				https://github.com/optim-enterprises-bv/vault.git
				synced 2025-10-30 18:17:55 +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() | ||||
| export default class NamespaceModel extends Model { | ||||
|   @attr('string', { | ||||
|     validationAttr: 'pathIsValid', | ||||
|     invalidMessage: 'You have entered and invalid path please only include letters, numbers, -, ., and _.', | ||||
| @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') | ||||
|   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
	 Chelsea Shaw
					Chelsea Shaw