From 5b9160fed21bbf72b96b349424267e26f71ec3ad Mon Sep 17 00:00:00 2001 From: alicia pritchett Date: Fri, 11 Feb 2022 10:47:39 -0500 Subject: [PATCH] validate category ID's on generation --- ...workflow-spec-category-dialog.component.ts | 111 +++++++++++++----- .../workflow-spec-list.component.ts | 4 +- 2 files changed, 81 insertions(+), 34 deletions(-) diff --git a/src/app/_dialogs/workflow-spec-category-dialog/workflow-spec-category-dialog.component.ts b/src/app/_dialogs/workflow-spec-category-dialog/workflow-spec-category-dialog.component.ts index 85dfdef..7c7a91c 100644 --- a/src/app/_dialogs/workflow-spec-category-dialog/workflow-spec-category-dialog.component.ts +++ b/src/app/_dialogs/workflow-spec-category-dialog/workflow-spec-category-dialog.component.ts @@ -1,9 +1,10 @@ import {Component, Inject} from '@angular/core'; -import {FormGroup} from '@angular/forms'; +import {FormControl, FormGroup} from '@angular/forms'; import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; import {FormlyFieldConfig, FormlyFormOptions} from '@ngx-formly/core'; -import {toSnakeCase} from 'sartography-workflow-lib'; +import {ApiService, toSnakeCase} from 'sartography-workflow-lib'; import {WorkflowSpecCategoryDialogData} from '../../_interfaces/dialog-data'; +import {of} from "rxjs"; @Component({ selector: 'app-workflow-spec-category-dialog', @@ -14,20 +15,21 @@ export class WorkflowSpecCategoryDialogComponent { form: FormGroup = new FormGroup({}); model: any = {}; options: FormlyFormOptions = {}; - fields: FormlyFieldConfig[] = [ - { - key: 'id', - type: 'input', - defaultValue: this.data.id, - templateOptions: { - label: 'ID', - type: 'number', - placeholder: 'ID of workflow spec category', - required: true, - }, - hideExpression: true, - }, - { + fields: FormlyFieldConfig[] = []; + categories: any; + + + + constructor( + private api: ApiService, + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: WorkflowSpecCategoryDialogData, + ) { + this.api.getWorkflowSpecCategoryList().subscribe(cats => { + this.categories = cats.map(c => c.id); + + this.fields = [ + { key: 'display_name', type: 'input', defaultValue: this.data.display_name, @@ -39,22 +41,69 @@ export class WorkflowSpecCategoryDialogComponent { required: true, }, }, - { - key: 'admin', - type: 'checkbox', - defaultValue: this.data.admin ? this.data.admin : false, - templateOptions: { - label: 'Admin Category', - description: 'Should this category only be shown to Admins?', - indeterminate: false, - } - } - ]; + { + key: 'id', + type: 'input', + defaultValue: this.data.id, + templateOptions: { + label: 'ID', + placeholder: 'Name of the category', + description: 'Enter a name to identify this category. It cannot be changed later.' + + 'It will be converted to all_lowercase_with_underscores when you save.', + required: true, + disabled: this.data.id !== null, + help: 'This must be in a universal format for XML standards. ' + + 'It can only contain letters, numbers, and underscores. ' + + 'It should not start with a digit.', + modelOptions: + { + updateOn: 'focus', + } + }, + expressionProperties: { + 'model.id': (m, formState, field) => { + if (!m.id && field.focus) { + m.id = m.display_name.replace(/ /g,"_").toLowerCase(); + field.formControl.markAsDirty(); + return m.id; + } else { + return m.id; + } + }, + 'templateOptions.change': (m, formState, field)=> { + if (field.focus) { + field.formControl.updateValueAndValidity(); + } + }, + }, + asyncValidators: { + uniqueID: { + expression: (control: FormControl) => { - constructor( - public dialogRef: MatDialogRef, - @Inject(MAT_DIALOG_DATA) public data: WorkflowSpecCategoryDialogData, - ) { + return of(this.categories.indexOf(control.value) === -1); + }, + message: 'This ID name is already taken.', + }, + }, + validators: { + formatter: { + expression: (c) => !c.value || /^[A-Za-z_][A-Za-z0-9]*(?:_[A-Za-z0-9]+)*$/.test(c.value), + message: (error, field: FormlyFieldConfig) => `"${field.formControl.value}" is not in a valid format.`, + }, + }, + }, + { + key: 'admin', + type: 'checkbox', + defaultValue: this.data.admin ? this.data.admin : false, + templateOptions: { + label: 'Admin Category', + description: 'Should this category only be shown to Admins?', + indeterminate: false, + } + }, + ]; + }); } onNoClick() { diff --git a/src/app/workflow-spec-list/workflow-spec-list.component.ts b/src/app/workflow-spec-list/workflow-spec-list.component.ts index c0e3381..d718c9d 100644 --- a/src/app/workflow-spec-list/workflow-spec-list.component.ts +++ b/src/app/workflow-spec-list/workflow-spec-list.component.ts @@ -318,7 +318,6 @@ export class WorkflowSpecListComponent implements OnInit { if (selectedSpecName && selectedSpecName === ws.id) { this.selectedSpec = ws; this.selectedCatID = ws.category_id; - // TODO: maybe fix expression changes after init error this.setCatByID(ws.category_id); } }); @@ -361,9 +360,8 @@ export class WorkflowSpecListComponent implements OnInit { }; this._updateWorkflowSpecCategory(data.id, newCat); } else { - // TODO: prompt user for somethin about the id generation const newCat: WorkflowSpecCategory = { - id: data.display_name, + id: data.id, display_name: data.display_name, admin: data.admin, };