From 85f6d2dc3c8e921e2b333090230477ea440c5679 Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Wed, 25 Sep 2019 10:53:36 -0700 Subject: [PATCH] SHIBUI-1478 Updated UI to support new schemas --- .../metadata/configuration/reducer/index.ts | 11 +++- .../model/dynamic-http.provider.form.ts | 12 +---- .../model/file-backed-http.provider.form.ts | 13 ++--- .../model/file-system.provider.form.ts | 10 ---- .../model/local-dynamic.provider.form.ts | 10 ---- .../app/metadata/provider/model/utilities.ts | 25 +++++++++ .../widget/number/float.component.html | 8 +-- .../widget/number/float.component.ts | 51 ++++++++++++++++++- ui/src/app/wizard/model/form-definition.ts | 1 + ui/src/app/wizard/reducer/index.ts | 6 ++- 10 files changed, 99 insertions(+), 48 deletions(-) create mode 100644 ui/src/app/metadata/provider/model/utilities.ts diff --git a/ui/src/app/metadata/configuration/reducer/index.ts b/ui/src/app/metadata/configuration/reducer/index.ts index 38087a034..2a46f79e5 100644 --- a/ui/src/app/metadata/configuration/reducer/index.ts +++ b/ui/src/app/metadata/configuration/reducer/index.ts @@ -51,9 +51,18 @@ export const getConfigurationModelKind = createSelector(getConfigurationState, f export const getConfigurationModelId = createSelector(getConfigurationState, fromConfiguration.getModelId); export const getConfigurationDefinition = createSelector(getConfigurationState, fromConfiguration.getDefinition); -export const getConfigurationSchema = createSelector(getConfigurationState, fromConfiguration.getSchema); +export const getSchema = createSelector(getConfigurationState, fromConfiguration.getSchema); export const getConfigurationXml = createSelector(getConfigurationState, fromConfiguration.getXml); +export const processSchemaFn = (definition, schema) => { + return definition && schema ? + definition.schemaPreprocessor ? + definition.schemaPreprocessor(schema) : schema + : schema; +}; + +export const getConfigurationSchema = createSelector(getConfigurationDefinition, getSchema, processSchemaFn); + export const assignValueToProperties = (models, properties, definition: any): any[] => { return properties.map(prop => { const differences = models.some((model, index, array) => { diff --git a/ui/src/app/metadata/provider/model/dynamic-http.provider.form.ts b/ui/src/app/metadata/provider/model/dynamic-http.provider.form.ts index 80de5ab17..2096ac38b 100644 --- a/ui/src/app/metadata/provider/model/dynamic-http.provider.form.ts +++ b/ui/src/app/metadata/provider/model/dynamic-http.provider.form.ts @@ -1,21 +1,13 @@ import { Wizard } from '../../../wizard/model'; import { DynamicHttpMetadataProvider } from '../../domain/model/providers/dynamic-http-metadata-provider'; import { BaseMetadataProviderEditor } from './base.provider.form'; +import { metadataFilterProcessor } from './utilities'; export const DynamicHttpMetadataProviderWizard: Wizard = { ...BaseMetadataProviderEditor, label: 'DynamicHttpMetadataProvider', type: 'DynamicHttpMetadataResolver', - formatter: (changes: DynamicHttpMetadataProvider) => { - let base = BaseMetadataProviderEditor.formatter(changes); - if (base.dynamicMetadataResolverAttributes) { - if (base.dynamicMetadataResolverAttributes.refreshDelayFactor) { - base.dynamicMetadataResolverAttributes.refreshDelayFactor = - base.dynamicMetadataResolverAttributes.refreshDelayFactor.toString(); - } - } - return base; - }, + schemaPreprocessor: metadataFilterProcessor, getValidators(namesList: string[] = [], xmlIdList: string[] = []): any { const validators = BaseMetadataProviderEditor.getValidators(namesList, xmlIdList); diff --git a/ui/src/app/metadata/provider/model/file-backed-http.provider.form.ts b/ui/src/app/metadata/provider/model/file-backed-http.provider.form.ts index d3e4d9995..15064bd64 100644 --- a/ui/src/app/metadata/provider/model/file-backed-http.provider.form.ts +++ b/ui/src/app/metadata/provider/model/file-backed-http.provider.form.ts @@ -3,20 +3,13 @@ import { FileBackedHttpMetadataProvider } from '../../domain/model/providers/fil import { BaseMetadataProviderEditor } from './base.provider.form'; import { UriValidator } from '../../../shared/validation/uri.validator'; +import { metadataFilterProcessor } from './utilities'; + export const FileBackedHttpMetadataProviderWizard: Wizard = { ...BaseMetadataProviderEditor, label: 'FileBackedHttpMetadataProvider', type: 'FileBackedHttpMetadataResolver', - formatter: (changes: FileBackedHttpMetadataProvider) => { - let base = BaseMetadataProviderEditor.formatter(changes); - if (base.reloadableMetadataResolverAttributes) { - if (base.reloadableMetadataResolverAttributes.refreshDelayFactor) { - base.reloadableMetadataResolverAttributes.refreshDelayFactor = - base.reloadableMetadataResolverAttributes.refreshDelayFactor.toString(); - } - } - return base; - }, + schemaPreprocessor: metadataFilterProcessor, getValidators(namesList: string[] = [], xmlIdList: string[] = []): any { const validators = BaseMetadataProviderEditor.getValidators(namesList, xmlIdList); validators['/metadataURL'] = (value, property, form) => { diff --git a/ui/src/app/metadata/provider/model/file-system.provider.form.ts b/ui/src/app/metadata/provider/model/file-system.provider.form.ts index fcf780ac5..9fcf7fb6d 100644 --- a/ui/src/app/metadata/provider/model/file-system.provider.form.ts +++ b/ui/src/app/metadata/provider/model/file-system.provider.form.ts @@ -6,16 +6,6 @@ export const FileSystemMetadataProviderWizard: Wizard { - let base = BaseMetadataProviderEditor.formatter(changes); - if (base.reloadableMetadataResolverAttributes) { - if (base.reloadableMetadataResolverAttributes.refreshDelayFactor) { - base.reloadableMetadataResolverAttributes.refreshDelayFactor = - base.reloadableMetadataResolverAttributes.refreshDelayFactor.toString(); - } - } - return base; - }, schema: '/api/ui/MetadataResolver/FilesystemMetadataResolver', steps: [ { diff --git a/ui/src/app/metadata/provider/model/local-dynamic.provider.form.ts b/ui/src/app/metadata/provider/model/local-dynamic.provider.form.ts index c53562873..c79bc487d 100644 --- a/ui/src/app/metadata/provider/model/local-dynamic.provider.form.ts +++ b/ui/src/app/metadata/provider/model/local-dynamic.provider.form.ts @@ -7,16 +7,6 @@ export const LocalDynamicMetadataProviderWizard: Wizard { - let base = BaseMetadataProviderEditor.formatter(changes); - if (base.dynamicMetadataResolverAttributes) { - if (base.dynamicMetadataResolverAttributes.refreshDelayFactor) { - base.dynamicMetadataResolverAttributes.refreshDelayFactor = - base.dynamicMetadataResolverAttributes.refreshDelayFactor.toString(); - } - } - return base; - }, schema: '/api/ui/MetadataResolver/LocalDynamicMetadataResolver', steps: [ { diff --git a/ui/src/app/metadata/provider/model/utilities.ts b/ui/src/app/metadata/provider/model/utilities.ts new file mode 100644 index 000000000..aea90bc21 --- /dev/null +++ b/ui/src/app/metadata/provider/model/utilities.ts @@ -0,0 +1,25 @@ +export const metadataFilterProcessor = (schema) => { + console.log(schema); + if (!schema) { + return null; + } + if (!schema.properties || !schema.properties.metadataFilters) { + return schema; + } + const filters = schema.properties.metadataFilters; + const processed = ({ + ...schema, + properties: { + ...schema.properties, + metadataFilters: { + type: 'object', + properties: filters.items.reduce((collection, filterType) => ({ + ...collection, + [filterType.$id]: filterType + }), {}) + } + } + }); + console.log(processed); + return processed; +}; diff --git a/ui/src/app/schema-form/widget/number/float.component.html b/ui/src/app/schema-form/widget/number/float.component.html index c1c78d34c..56e15bc69 100644 --- a/ui/src/app/schema-form/widget/number/float.component.html +++ b/ui/src/app/schema-form/widget/number/float.component.html @@ -9,17 +9,17 @@ {{schema.description}} - diff --git a/ui/src/app/schema-form/widget/number/float.component.ts b/ui/src/app/schema-form/widget/number/float.component.ts index 3278829ba..4a465a6ef 100644 --- a/ui/src/app/schema-form/widget/number/float.component.ts +++ b/ui/src/app/schema-form/widget/number/float.component.ts @@ -1,5 +1,5 @@ import { - Component, + Component, AfterViewInit, ViewChild, ElementRef, } from '@angular/core'; import { IntegerWidget } from 'ngx-schema-form'; import { SchemaService } from '../../service/schema.service'; @@ -8,14 +8,61 @@ import { SchemaService } from '../../service/schema.service'; selector: 'float-component', templateUrl: `./float.component.html` }) -export class CustomFloatComponent extends IntegerWidget { +export class CustomFloatComponent extends IntegerWidget implements AfterViewInit { + private _displayValue: string; + @ViewChild('input') element: ElementRef; + constructor( private widgetService: SchemaService ) { super(); } + ngAfterViewInit() { + super.ngAfterViewInit(); + const control = this.control; + this.formProperty.valueChanges.subscribe((newValue) => { + if (typeof this._displayValue !== 'undefined') { + // Ignore the model value, use the display value instead + if (control.value !== this._displayValue) { + control.setValue(this._displayValue, { emitEvent: false }); + } + } else { + if (control.value !== newValue) { + control.setValue(newValue, { emitEvent: false }); + } + } + }); + this.formProperty.errorsChanges.subscribe((errors) => { + control.setErrors(errors, { emitEvent: true }); + const messages = (errors || []) + .filter(e => { + return e.path && e.path.slice(1) === this.formProperty.path; + }) + .map(e => e.message); + this.errorMessages = messages.filter((m, i) => messages.indexOf(m) === i); + }); + control.valueChanges.subscribe((newValue) => { + const native = (this.element.nativeElement); + this._displayValue = newValue; + this.formProperty.setValue(newValue, false); + if (newValue === '' && native.validity.badInput) { + this.formProperty.extendErrors([{ + code: 'INVALID_NUMBER', + path: `#${this.formProperty.path}`, + message: 'Invalid number', + }]); + } + }); + } + get required(): boolean { return this.widgetService.isRequired(this.formProperty); } + + get minimum(): number { + return this.required ? + this.schema.minimum : + this.formProperty.value === null ? null : this.schema.minimum; + } } diff --git a/ui/src/app/wizard/model/form-definition.ts b/ui/src/app/wizard/model/form-definition.ts index bde8e10ad..5e3cbb6ea 100644 --- a/ui/src/app/wizard/model/form-definition.ts +++ b/ui/src/app/wizard/model/form-definition.ts @@ -10,4 +10,5 @@ export interface FormDefinition { parser(changes: Partial, schema?: any); formatter(changes: Partial, schema?: any); getValidators?(...args: any[]): { [key: string]: any }; + schemaPreprocessor?(schema: any): any; } diff --git a/ui/src/app/wizard/reducer/index.ts b/ui/src/app/wizard/reducer/index.ts index d85d930be..027ac1673 100644 --- a/ui/src/app/wizard/reducer/index.ts +++ b/ui/src/app/wizard/reducer/index.ts @@ -128,8 +128,12 @@ export const getLockedStatus = createSelector(getState, fromWizard.getLocked); export const getSchemaLockedFn = (step, locked) => step ? step.locked ? locked : false : false; export const getLocked = createSelector(getCurrent, getLockedStatus, getSchemaLockedFn); +export const getSchemaProcessedFn = (schema, definition) => + definition.schemaPreprocessor ? definition.schemaPreprocessor(schema) : schema; + export const getSchemaObject = createSelector(getState, fromWizard.getSchema); -export const getParsedSchema = createSelector(getSchemaObject, getLocked, getSchemaParseFn); +export const getProcessedSchema = createSelector(getSchemaObject, getWizardDefinition, getSchemaProcessedFn); +export const getParsedSchema = createSelector(getProcessedSchema, getLocked, getSchemaParseFn); export const getSchema = createSelector(getParsedSchema, getCurrent, getSplitSchema);