diff --git a/ui/src/app/metadata/metadata.component.ts b/ui/src/app/metadata/metadata.component.ts
index 52ca814e2..62170d286 100644
--- a/ui/src/app/metadata/metadata.component.ts
+++ b/ui/src/app/metadata/metadata.component.ts
@@ -5,6 +5,7 @@ import { LoadResolverRequest } from './resolver/action/collection.action';
import { LoadFilterRequest } from './filter/action/collection.action';
import { LoadDraftRequest } from './resolver/action/draft.action';
import * as fromRoot from '../app.reducer';
+import { LoadProviderRequest } from './provider/action/collection.action';
@Component({
selector: 'metadata-page',
@@ -20,5 +21,6 @@ export class MetadataPageComponent {
this.store.dispatch(new LoadResolverRequest());
this.store.dispatch(new LoadFilterRequest());
this.store.dispatch(new LoadDraftRequest());
+ this.store.dispatch(new LoadProviderRequest());
}
}
diff --git a/ui/src/app/metadata/provider/container/provider-wizard-step.component.html b/ui/src/app/metadata/provider/container/provider-wizard-step.component.html
index b04035bf7..831e71fbb 100644
--- a/ui/src/app/metadata/provider/container/provider-wizard-step.component.html
+++ b/ui/src/app/metadata/provider/container/provider-wizard-step.component.html
@@ -1,5 +1,6 @@
\ No newline at end of file
+ [validators]="validators"
+ (onChange)="valueChangeSubject.next($event)"
+ (onErrorChange)="statusChangeSubject.next($event)">
\ No newline at end of file
diff --git a/ui/src/app/metadata/provider/container/provider-wizard-step.component.ts b/ui/src/app/metadata/provider/container/provider-wizard-step.component.ts
index 962445d30..ed583d251 100644
--- a/ui/src/app/metadata/provider/container/provider-wizard-step.component.ts
+++ b/ui/src/app/metadata/provider/container/provider-wizard-step.component.ts
@@ -1,6 +1,6 @@
import { Component, OnDestroy } from '@angular/core';
import { Observable, Subject } from 'rxjs';
-import { withLatestFrom, map } from 'rxjs/operators';
+import { withLatestFrom, map, distinctUntilChanged } from 'rxjs/operators';
import { Store } from '@ngrx/store';
import * as fromProvider from '../reducer';
@@ -21,8 +21,11 @@ import { pick } from '../../../shared/util';
})
export class ProviderWizardStepComponent implements OnDestroy {
- changeSubject = new Subject>();
- private changeEmitted$ = this.changeSubject.asObservable();
+ valueChangeSubject = new Subject>();
+ private valueChangeEmitted$ = this.valueChangeSubject.asObservable();
+
+ statusChangeSubject = new Subject>();
+ private statusChangeEmitted$ = this.statusChangeSubject.asObservable();
schema$: Observable;
schema: any;
@@ -32,6 +35,35 @@ export class ProviderWizardStepComponent implements OnDestroy {
valid$: Observable;
model$: Observable;
+ namesList: string[] = [];
+
+ validators = {
+ '/': (value, property, form_current) => {
+ let errors;
+ // iterate all customer
+ Object.keys(value).forEach((key) => {
+ const item = value[key];
+ const validatorKey = `/${key}`;
+ const validator = this.validators.hasOwnProperty(validatorKey) ? this.validators[validatorKey] : null;
+ const error = validator ? validator(item, { path: `/${key}` }, form_current) : null;
+ if (error) {
+ errors = errors || [];
+ errors.push(error);
+ }
+ });
+ return errors;
+ },
+ '/name': (value, property, form) => {
+ const err = this.namesList.indexOf(value) > -1 ? {
+ code: 'INVALID_NAME',
+ path: `#${property.path}`,
+ message: 'Name must be unique.',
+ params: [value]
+ } : null;
+ return err;
+ }
+ };
+
constructor(
private store: Store
) {
@@ -39,6 +71,8 @@ export class ProviderWizardStepComponent implements OnDestroy {
this.definition$ = this.store.select(fromWizard.getWizardDefinition);
this.changes$ = this.store.select(fromProvider.getEntityChanges);
+ this.store.select(fromProvider.getProviderNames).subscribe(list => this.namesList = list);
+
this.model$ = this.schema$.pipe(
withLatestFrom(
this.store.select(fromWizard.getModel),
@@ -55,7 +89,7 @@ export class ProviderWizardStepComponent implements OnDestroy {
map(({ model, definition }) => definition.translate ? definition.translate.formatter(model) : model)
);
- this.changeEmitted$.pipe(
+ this.valueChangeEmitted$.pipe(
withLatestFrom(this.schema$, this.definition$),
map(([changes, schema, definition]) => {
const type = changes.value['@type'];
@@ -78,15 +112,20 @@ export class ProviderWizardStepComponent implements OnDestroy {
map(({ changes, definition }) => definition.translate ? definition.translate.parser(changes) : changes)
)
.subscribe(changes => this.store.dispatch(new UpdateProvider(changes)));
- }
- ngOnDestroy() {
- this.changeSubject.complete();
+ this.statusChangeEmitted$.pipe(
+ distinctUntilChanged()
+ ).subscribe(errors => {
+ console.log(!(errors.value));
+ const status = { [this.currentPage]: !(errors.value) ? 'VALID' : 'INVALID' };
+ this.store.dispatch(new UpdateStatus(status));
+ });
+
+ this.store.select(fromWizard.getWizardIndex).subscribe(i => this.currentPage = i);
}
- onStatusChange(value): void {
- const status = { [this.currentPage]: value ? 'VALID' : 'INVALID' };
- this.store.dispatch(new UpdateStatus(status));
+ ngOnDestroy() {
+ this.valueChangeSubject.complete();
}
}
diff --git a/ui/src/app/metadata/provider/container/provider-wizard.component.ts b/ui/src/app/metadata/provider/container/provider-wizard.component.ts
index ad042590b..793f491da 100644
--- a/ui/src/app/metadata/provider/container/provider-wizard.component.ts
+++ b/ui/src/app/metadata/provider/container/provider-wizard.component.ts
@@ -35,14 +35,6 @@ export class ProviderWizardComponent implements OnDestroy {
provider: MetadataProvider;
- namesList: string[] = [];
-
- validators = {
- '/name': (value, property, form) => {
- return this.namesList.indexOf(value) > -1 ? { 'name': { 'expectedValue': 'unique' } } : null;
- }
- };
-
constructor(
private store: Store,
private router: Router,
@@ -75,8 +67,6 @@ export class ProviderWizardComponent implements OnDestroy {
);
this.changes$.subscribe(c => this.provider = c);
-
- this.store.select(fromProvider.getProviderNames).subscribe(list => this.namesList = list);
}
ngOnDestroy() {
diff --git a/ui/src/app/metadata/provider/effect/collection.effect.ts b/ui/src/app/metadata/provider/effect/collection.effect.ts
index 19e521f3c..5a471dfdd 100644
--- a/ui/src/app/metadata/provider/effect/collection.effect.ts
+++ b/ui/src/app/metadata/provider/effect/collection.effect.ts
@@ -9,7 +9,10 @@ import {
ProviderCollectionActionTypes,
AddProviderRequest,
AddProviderSuccess,
- AddProviderFail
+ AddProviderFail,
+ LoadProviderRequest,
+ LoadProviderSuccess,
+ LoadProviderError
} from '../action/collection.action';
import { MetadataProviderService } from '../../domain/service/provider.service';
@@ -17,6 +20,19 @@ import { MetadataProviderService } from '../../domain/service/provider.service';
@Injectable()
export class CollectionEffects {
+ @Effect()
+ loadFilters$ = this.actions$.pipe(
+ ofType(ProviderCollectionActionTypes.LOAD_PROVIDER_REQUEST),
+ switchMap(() =>
+ this.providerService
+ .query()
+ .pipe(
+ map(providers => new LoadProviderSuccess(providers)),
+ catchError(error => of(new LoadProviderError(error)))
+ )
+ )
+ );
+
@Effect()
createProvider$ = this.actions$.pipe(
ofType(ProviderCollectionActionTypes.ADD_PROVIDER_REQUEST),
@@ -38,14 +54,12 @@ export class CollectionEffects {
tap(provider => this.router.navigate(['metadata']))
);
- /*
@Effect()
addResolverSuccessReload$ = this.actions$.pipe(
- ofType(EntityActionTypes.CREATE_PROVIDER_SUCCESS),
+ ofType(ProviderCollectionActionTypes.ADD_PROVIDER_SUCCESS),
map(action => action.payload),
map(provider => new LoadProviderRequest())
);
- */
constructor(
private actions$: Actions,
diff --git a/ui/src/app/metadata/provider/provider.module.ts b/ui/src/app/metadata/provider/provider.module.ts
index 7d60e47bb..104bae13d 100644
--- a/ui/src/app/metadata/provider/provider.module.ts
+++ b/ui/src/app/metadata/provider/provider.module.ts
@@ -18,6 +18,7 @@ import { FormModule } from '../../schema-form/schema-form.module';
import { CustomWidgetRegistry } from '../../schema-form/registry';
import { SummaryPropertyComponent } from './component/summary-property.component';
import { CollectionEffects } from './effect/collection.effect';
+import { SharedModule } from '../../shared/shared.module';
@NgModule({
@@ -34,6 +35,7 @@ import { CollectionEffects } from './effect/collection.effect';
CommonModule,
WizardModule,
RouterModule,
+ SharedModule,
FormModule
],
exports: []
diff --git a/ui/src/app/schema-form/widget/text/string.component.html b/ui/src/app/schema-form/widget/text/string.component.html
index b581f242e..435c2079a 100644
--- a/ui/src/app/schema-form/widget/text/string.component.html
+++ b/ui/src/app/schema-form/widget/text/string.component.html
@@ -11,6 +11,7 @@
{{ schema.description }}
+
+ {{ errorMessages }}
+
+
+ {{ schema.widget.help }}
+
\ No newline at end of file
diff --git a/ui/src/app/schema-form/widget/text/string.component.ts b/ui/src/app/schema-form/widget/text/string.component.ts
index 26c1f5c44..cf46aa6e2 100644
--- a/ui/src/app/schema-form/widget/text/string.component.ts
+++ b/ui/src/app/schema-form/widget/text/string.component.ts
@@ -1,18 +1,9 @@
import { Component } from '@angular/core';
-import { ControlWidget } from 'ngx-schema-form';
+import { StringWidget } from 'ngx-schema-form';
@Component({
selector: 'custom-string',
templateUrl: `./string.component.html`,
styleUrls: ['../widget.component.scss']
})
-export class CustomStringComponent extends ControlWidget {
-
- getInputType() {
- if (!this.schema.widget.id || this.schema.widget.id === 'string') {
- return 'text';
- } else {
- return this.schema.widget.id;
- }
- }
-}
+export class CustomStringComponent extends StringWidget {}
diff --git a/ui/src/app/shared/shared.module.ts b/ui/src/app/shared/shared.module.ts
index 4af6af8ce..f166ad254 100644
--- a/ui/src/app/shared/shared.module.ts
+++ b/ui/src/app/shared/shared.module.ts
@@ -35,6 +35,7 @@ import { PrettyXml } from './pipe/pretty-xml.pipe';
InputDefaultsDirective,
I18nTextComponent,
ValidFormIconComponent,
+ ValidationClassDirective,
InfoLabelDirective
]
})
diff --git a/ui/src/assets/schema/provider/metadata-provider.schema.json b/ui/src/assets/schema/provider/metadata-provider.schema.json
index af33d3e45..f5a840f35 100644
--- a/ui/src/assets/schema/provider/metadata-provider.schema.json
+++ b/ui/src/assets/schema/provider/metadata-provider.schema.json
@@ -1,5 +1,5 @@
{
- "title": "@MetadataResolver",
+ "title": "MetadataResolver",
"type": "object",
"widget": {
"id": "fieldset"
@@ -8,7 +8,11 @@
"name": {
"title": "Metadata Provider Name (Dashboard Display Only)",
"description": "Metadata Provider Name (Dashboard Display Only)",
- "type": "string"
+ "type": "string",
+ "widget": {
+ "id": "string",
+ "help": "Must be unique."
+ }
},
"@type": {
"title": "Metadata Provider Type",