From 98be18508836185fa4bf46ecc5eac97e7ba5ac17 Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Wed, 17 Mar 2021 13:23:36 -0700 Subject: [PATCH] Fixed validation --- .../component/editor-nav.component.html | 4 +- .../domain/component/editor-nav.component.ts | 1 + .../filter/action/collection.action.ts | 10 +- .../metadata/filter/action/editor.action.ts | 8 -- .../filter/action/filter.action.spec.ts | 2 +- .../container/edit-filter-step.component.ts | 42 +++++-- .../container/edit-filter.component.html | 26 ++--- .../filter/container/edit-filter.component.ts | 15 ++- .../container/new-filter-step.component.html | 15 +++ .../container/new-filter-step.component.ts | 104 ++++++++++++++++++ .../container/new-filter.component.html | 51 +++++---- .../filter/container/new-filter.component.ts | 94 ++++++++-------- .../filter/effect/collection.effect.ts | 16 +-- .../metadata/filter/effect/filter.effect.ts | 1 + ui/src/app/metadata/filter/filter.module.ts | 2 + .../model/nameid-configuration.filter.ts | 10 +- .../metadata/filter/reducer/editor.reducer.ts | 11 +- .../metadata/filter/reducer/filter.reducer.ts | 3 +- ui/src/app/metadata/filter/reducer/index.ts | 12 +- .../container/provider-select.component.ts | 1 - .../app/metadata/provider/provider.routing.ts | 13 ++- 21 files changed, 300 insertions(+), 141 deletions(-) create mode 100644 ui/src/app/metadata/filter/container/new-filter-step.component.html create mode 100644 ui/src/app/metadata/filter/container/new-filter-step.component.ts diff --git a/ui/src/app/metadata/domain/component/editor-nav.component.html b/ui/src/app/metadata/domain/component/editor-nav.component.html index 9fe804c85..7307e79fb 100644 --- a/ui/src/app/metadata/domain/component/editor-nav.component.html +++ b/ui/src/app/metadata/domain/component/editor-nav.component.html @@ -15,7 +15,7 @@ @@ -32,7 +32,7 @@ href="" class="nav-link" [ngClass]="{'active': (currentPage$ | async) === route.path}" - [routerLink]="['../', 'edit', route.path]" + [routerLink]="['../', path, route.path]" role="button" [attr.aria-label]="route.label"> diff --git a/ui/src/app/metadata/domain/component/editor-nav.component.ts b/ui/src/app/metadata/domain/component/editor-nav.component.ts index 32653fb43..7cf57ed1b 100644 --- a/ui/src/app/metadata/domain/component/editor-nav.component.ts +++ b/ui/src/app/metadata/domain/component/editor-nav.component.ts @@ -21,6 +21,7 @@ export enum NAV_FORMATS { export class EditorNavComponent { @Input() format: string; @Input() status: string[] = []; + @Input() path: string = 'edit'; @Output() onPageSelect: EventEmitter = new EventEmitter(); diff --git a/ui/src/app/metadata/filter/action/collection.action.ts b/ui/src/app/metadata/filter/action/collection.action.ts index 11ffad3ca..8c14693e2 100644 --- a/ui/src/app/metadata/filter/action/collection.action.ts +++ b/ui/src/app/metadata/filter/action/collection.action.ts @@ -112,13 +112,19 @@ export class UpdateFilterConflict implements Action { export class AddFilterRequest implements Action { readonly type = FilterCollectionActionTypes.ADD_FILTER_REQUEST; - constructor(public payload: MetadataFilter) { } + constructor(public payload: { + filter: MetadataFilter, + providerId: string + }) { } } export class AddFilterSuccess implements Action { readonly type = FilterCollectionActionTypes.ADD_FILTER_SUCCESS; - constructor(public payload: MetadataFilter) { } + constructor(public payload: { + filter: MetadataFilter, + providerId: string + }) { } } export class AddFilterFail implements Action { diff --git a/ui/src/app/metadata/filter/action/editor.action.ts b/ui/src/app/metadata/filter/action/editor.action.ts index 7c4dba2cf..7ea0a867b 100644 --- a/ui/src/app/metadata/filter/action/editor.action.ts +++ b/ui/src/app/metadata/filter/action/editor.action.ts @@ -2,7 +2,6 @@ import { Action } from '@ngrx/store'; export enum EditorActionTypes { UPDATE_STATUS = '[Filter Editor] Update Status', - SELECT_PROVIDER_TYPE = '[Filter Editor] Select Filter Type', CLEAR = '[Filter Editor] Clear' } @@ -12,17 +11,10 @@ export class UpdateStatus implements Action { constructor(public payload: { [key: string]: string }) { } } -export class SelectFilterType implements Action { - readonly type = EditorActionTypes.SELECT_PROVIDER_TYPE; - - constructor(public payload: string) { } -} - export class ClearEditor implements Action { readonly type = EditorActionTypes.CLEAR; } export type EditorActionUnion = | UpdateStatus - | SelectFilterType | ClearEditor; diff --git a/ui/src/app/metadata/filter/action/filter.action.spec.ts b/ui/src/app/metadata/filter/action/filter.action.spec.ts index db844107e..921f12385 100644 --- a/ui/src/app/metadata/filter/action/filter.action.spec.ts +++ b/ui/src/app/metadata/filter/action/filter.action.spec.ts @@ -2,7 +2,7 @@ import { FilterActionTypes, CancelCreateFilter, SelectId } from './filter.action describe('Filter Actions', () => { it('should provide actions', () => { - expect(new CancelCreateFilter().type).toBe(FilterActionTypes.CANCEL_CREATE_FILTER); + expect(new CancelCreateFilter('id').type).toBe(FilterActionTypes.CANCEL_CREATE_FILTER); expect(new SelectId('foo').type).toBe(FilterActionTypes.SELECT_ID); }); }); diff --git a/ui/src/app/metadata/filter/container/edit-filter-step.component.ts b/ui/src/app/metadata/filter/container/edit-filter-step.component.ts index d09f78cbf..963add6bf 100644 --- a/ui/src/app/metadata/filter/container/edit-filter-step.component.ts +++ b/ui/src/app/metadata/filter/container/edit-filter-step.component.ts @@ -1,4 +1,4 @@ -import { Component, OnDestroy } from '@angular/core'; +import { ChangeDetectorRef, Component, OnDestroy } from '@angular/core'; import { Store } from '@ngrx/store'; import { Subject, Observable, Subscription } from 'rxjs'; @@ -8,9 +8,10 @@ import { MetadataFilter } from '../../domain/model'; import { SchemaService } from '../../../schema-form/service/schema.service'; import { UpdateFilterChanges } from '../action/filter.action'; import { PreviewEntity } from '../../domain/action/entity.action'; -import { shareReplay, map, withLatestFrom, filter, switchMap, takeUntil } from 'rxjs/operators'; +import { map, withLatestFrom, filter, takeUntil, distinctUntilChanged, skip } from 'rxjs/operators'; import * as fromWizard from '../../../wizard/reducer'; import { LockEditor, UnlockEditor } from '../../../wizard/action/wizard.action'; +import { UpdateStatus } from '../action/editor.action'; @Component({ selector: 'edit-filter-step-page', @@ -44,12 +45,13 @@ export class EditFilterStepComponent implements OnDestroy { actions: any; defSub: Subscription; + currentPage: string; constructor( private store: Store, - private schemaService: SchemaService + private ref: ChangeDetectorRef ) { - this.definition$ = this.store.select(fromWizard.getWizardDefinition).pipe(filter(d => !!d)) + this.definition$ = this.store.select(fromWizard.getWizardDefinition).pipe(filter(d => !!d)); this.defSub = this.definition$.subscribe(d => this.definition = d); @@ -70,13 +72,29 @@ export class EditFilterStepComponent implements OnDestroy { this.model$ = this.store.select(fromFilter.getSelectedFilter); this.type$ = this.model$.pipe(map(f => f && f.hasOwnProperty('@type') ? f['@type'] : '')); - this.valueChangeEmitted$.subscribe(changes => this.store.dispatch(new UpdateFilterChanges(changes.value))); - this.statusChangeEmitted$.subscribe(valid => { - this.isValid = valid.value ? valid.value.length === 0 : true; - }); + this.valueChangeEmitted$.pipe(takeUntil(this.ngUnsubscribe)).subscribe(changes => this.store.dispatch(new UpdateFilterChanges(changes.value))); + + this.statusChangeEmitted$ + .pipe( + skip(1), + takeUntil(this.ngUnsubscribe), + withLatestFrom(this.model$), + distinctUntilChanged() + ) + .subscribe(([errors, model]) => { + this.updateStatus(errors); + }); this.status$ = this.store.select(fromFilter.getInvalidEditorForms); + this.status$.pipe(takeUntil(this.ngUnsubscribe)).subscribe(() => { + this.ref.detach(); + setTimeout(() => { + this.ref.detectChanges(); + this.ref.reattach(); + }, 250); + }) + this.validators$ = this.store.select(fromFilter.getFilterNames).pipe( takeUntil(this.ngUnsubscribe), withLatestFrom( @@ -90,6 +108,7 @@ export class EditFilterStepComponent implements OnDestroy { this.store .select(fromFilter.getFilter) + .pipe(takeUntil(this.ngUnsubscribe)) .subscribe(filter => this.filter = filter); this.actions = { @@ -97,6 +116,13 @@ export class EditFilterStepComponent implements OnDestroy { this.preview(parameters.filterId); } }; + + this.store.select(fromWizard.getWizardIndex).pipe(takeUntil(this.ngUnsubscribe)).subscribe(i => this.currentPage = i); + } + + updateStatus(errors: any): void { + const status = { [this.currentPage]: !(errors.value) ? 'VALID' : 'INVALID' }; + this.store.dispatch(new UpdateStatus(status)); } ngOnDestroy(): void { diff --git a/ui/src/app/metadata/filter/container/edit-filter.component.html b/ui/src/app/metadata/filter/container/edit-filter.component.html index c003e2ddf..fa9e113b5 100644 --- a/ui/src/app/metadata/filter/container/edit-filter.component.html +++ b/ui/src/app/metadata/filter/container/edit-filter.component.html @@ -22,20 +22,18 @@
- - -   - - + +   +

diff --git a/ui/src/app/metadata/filter/container/edit-filter.component.ts b/ui/src/app/metadata/filter/container/edit-filter.component.ts index 6eb9e7908..9f6bbfba7 100644 --- a/ui/src/app/metadata/filter/container/edit-filter.component.ts +++ b/ui/src/app/metadata/filter/container/edit-filter.component.ts @@ -1,6 +1,6 @@ import { Component, OnDestroy } from '@angular/core'; import { Store } from '@ngrx/store'; -import { Subject, Observable, Subscription } from 'rxjs'; +import { Subject, Observable, Subscription, combineLatest } from 'rxjs'; import * as fromFilter from '../reducer'; import { FormDefinition } from '../../../wizard/model'; @@ -9,7 +9,7 @@ import { UpdateFilterRequest } from '../action/collection.action'; import { CancelCreateFilter } from '../action/filter.action'; import { PreviewEntity } from '../../domain/action/entity.action'; import { NAV_FORMATS } from '../../domain/component/editor-nav.component'; -import { map, filter } from 'rxjs/operators'; +import { map, filter, takeUntil, withLatestFrom, skip } from 'rxjs/operators'; import * as fromWizard from '../../../wizard/reducer'; import { ActivatedRoute } from '@angular/router'; import { LoadSchemaRequest, SetIndex } from '../../../wizard/action/wizard.action'; @@ -31,6 +31,7 @@ export class EditFilterComponent implements OnDestroy { filter: MetadataFilter; isValid$: Observable; isInvalid$: Observable; + cantSave$: Observable; type$: Observable; status$: Observable; @@ -40,6 +41,7 @@ export class EditFilterComponent implements OnDestroy { defSub: Subscription; formats = NAV_FORMATS; + currentPage constructor( private store: Store, @@ -52,7 +54,7 @@ export class EditFilterComponent implements OnDestroy { this.store .select(fromWizard.getCurrentWizardSchema) - .pipe(filter(s => !!s)) + .pipe(filter(s => !!s), takeUntil(this.ngUnsubscribe)) .subscribe(s => { if (s) { this.store.dispatch(new LoadSchemaRequest(s)); @@ -61,7 +63,6 @@ export class EditFilterComponent implements OnDestroy { let startIndex$ = this.route.firstChild.params.pipe(map(p => p.form || 'filters')); startIndex$.subscribe(index => this.store.dispatch(new SetIndex(index))); - this.isSaving$ = this.store.select(fromFilter.getCollectionSaving); this.model$ = this.store.select(fromFilter.getSelectedFilter); @@ -69,8 +70,9 @@ export class EditFilterComponent implements OnDestroy { this.status$ = this.store.select(fromFilter.getInvalidEditorForms); - this.isValid$ = this.store.select(fromFilter.getEditorIsValid); + this.isValid$ = this.store.select(fromFilter.getFilterIsValid); this.isInvalid$ = this.isValid$.pipe(map(v => !v)); + this.cantSave$ = this.store.select(fromFilter.cantSaveFilter).pipe(skip(1)); this.store .select(fromFilter.getFilter) @@ -96,7 +98,8 @@ export class EditFilterComponent implements OnDestroy { })); } - cancel(): void { + cancel(event: MouseEvent): void { + event.preventDefault(); this.store.dispatch(new CancelCreateFilter(this.route.snapshot.params.providerId)); } diff --git a/ui/src/app/metadata/filter/container/new-filter-step.component.html b/ui/src/app/metadata/filter/container/new-filter-step.component.html new file mode 100644 index 000000000..f8d748c37 --- /dev/null +++ b/ui/src/app/metadata/filter/container/new-filter-step.component.html @@ -0,0 +1,15 @@ + +
+ + + {{ lock.value ? 'Locked' : 'Unlocked' }} + + For Advanced Knowledge Only +
+ +
\ No newline at end of file diff --git a/ui/src/app/metadata/filter/container/new-filter-step.component.ts b/ui/src/app/metadata/filter/container/new-filter-step.component.ts new file mode 100644 index 000000000..a927b5d8c --- /dev/null +++ b/ui/src/app/metadata/filter/container/new-filter-step.component.ts @@ -0,0 +1,104 @@ +import { Component, OnDestroy, OnInit } from '@angular/core'; +import { Store } from '@ngrx/store'; +import { FormBuilder } from '@angular/forms'; +import { Subject, Observable } from 'rxjs'; + +import { takeUntil, shareReplay, withLatestFrom, map, switchMap, filter, distinctUntilChanged } from 'rxjs/operators'; + + +import * as fromFilter from '../reducer'; +import { FormDefinition, WizardStep } from '../../../wizard/model'; +import { MetadataFilter } from '../../domain/model'; +import { SchemaService } from '../../../schema-form/service/schema.service'; +import { UpdateFilterChanges } from '../action/filter.action'; +import { ActivatedRoute } from '@angular/router'; +import * as fromWizard from '../../../wizard/reducer'; +import { SetIndex } from '../../../wizard/action/wizard.action'; +import { UpdateStatus } from '../action/editor.action'; + +@Component({ + selector: 'new-filter-step-page', + templateUrl: './new-filter-step.component.html' +}) +export class NewFilterStepComponent implements OnDestroy, OnInit { + + private ngUnsubscribe: Subject = new Subject(); + + valueChangeSubject = new Subject>(); + private valueChangeEmitted$ = this.valueChangeSubject.asObservable(); + + statusChangeSubject = new Subject<{ value: any[] }>(); + private statusChangeEmitted$ = this.statusChangeSubject.asObservable(); + + definition$: Observable>; + schema$: Observable; + + changes$: Observable; + isSaving$: Observable; + filter: MetadataFilter; + + validators$: Observable<{ [key: string]: any }>; + + options$: Observable[]>; + + step$: Observable; + + currentPage: string; + + constructor( + private store: Store, + private schemaService: SchemaService, + private fb: FormBuilder, + private route: ActivatedRoute + ) { + this.isSaving$ = this.store.select(fromFilter.getCollectionSaving); + this.changes$ = this.store.select(fromFilter.getFilter); + this.step$ = this.store.select(fromWizard.getCurrent); + this.definition$ = this.store.select(fromWizard.getWizardDefinition).pipe(filter(d => !!d)); + this.schema$ = this.store.select(fromWizard.getSchema); + + this.validators$ = this.definition$.pipe( + takeUntil(this.ngUnsubscribe), + withLatestFrom(this.store.select(fromFilter.getFilterNames)), + map(([definition, names]) => definition.getValidators(names)) + ); + + let startIndex$ = this.route.params.pipe(map(p => p.form || 'filters')); + startIndex$.subscribe(index => this.store.dispatch(new SetIndex(index))); + } + + ngOnInit(): void { + this.valueChangeEmitted$ + .pipe(takeUntil(this.ngUnsubscribe)) + .subscribe(changes => this.store.dispatch(new UpdateFilterChanges(changes.value))); + this.statusChangeEmitted$ + .pipe( + takeUntil(this.ngUnsubscribe), + distinctUntilChanged() + ) + .subscribe(errors => { + this.updateStatus(errors); + }); + + this.store + .select(fromFilter.getFilter) + .pipe( + takeUntil(this.ngUnsubscribe), + withLatestFrom(this.definition$), + map(([filter, definition]) => definition.parser(filter)) + ) + .subscribe(filter => this.filter = filter); + + this.store.select(fromWizard.getWizardIndex).subscribe(i => this.currentPage = i); + } + + updateStatus(errors: any): void { + const status = { [this.currentPage]: !(errors.value) ? 'VALID' : 'INVALID' }; + this.store.dispatch(new UpdateStatus(status)); + } + + ngOnDestroy(): void { + this.ngUnsubscribe.next(); + this.ngUnsubscribe.complete(); + } +} diff --git a/ui/src/app/metadata/filter/container/new-filter.component.html b/ui/src/app/metadata/filter/container/new-filter.component.html index a30cb77fc..3976b1ff9 100644 --- a/ui/src/app/metadata/filter/container/new-filter.component.html +++ b/ui/src/app/metadata/filter/container/new-filter.component.html @@ -12,9 +12,9 @@
-
+
-
+
-
- - -   - - +
+ +   +
-
- +
+
+
+ + +
+
+ +
diff --git a/ui/src/app/metadata/filter/container/new-filter.component.ts b/ui/src/app/metadata/filter/container/new-filter.component.ts index 785473738..51907707a 100644 --- a/ui/src/app/metadata/filter/container/new-filter.component.ts +++ b/ui/src/app/metadata/filter/container/new-filter.component.ts @@ -1,20 +1,19 @@ import { Component, OnDestroy, OnInit } from '@angular/core'; import { Store } from '@ngrx/store'; import { Validators, FormBuilder, FormGroup } from '@angular/forms'; -import { Subject, Observable, of } from 'rxjs'; - -import { takeUntil, shareReplay, withLatestFrom, map, switchMap, filter, startWith, distinctUntilChanged, share } from 'rxjs/operators'; - +import { Subject, Observable, of, combineLatest } from 'rxjs'; +import { ActivatedRoute } from '@angular/router'; +import { takeUntil, withLatestFrom, map, filter, distinctUntilChanged, skip } from 'rxjs/operators'; import * as fromFilter from '../reducer'; -import { MetadataFilterTypes } from '../model'; +import { MetadataFilterEditorTypes, MetadataFilterTypes } from '../model'; import { FormDefinition } from '../../../wizard/model'; import { MetadataFilter } from '../../domain/model'; -import { SchemaService } from '../../../schema-form/service/schema.service'; import { AddFilterRequest } from '../action/collection.action'; -import { CancelCreateFilter, UpdateFilterChanges, SelectFilterType } from '../action/filter.action'; -import { ActivatedRoute } from '@angular/router'; - +import { CancelCreateFilter, SelectFilterType } from '../action/filter.action'; +import * as fromWizard from '../../../wizard/reducer'; +import { LoadSchemaRequest, SetDefinition, SetIndex } from '../../../wizard/action/wizard.action'; +import { NAV_FORMATS } from '../../domain/component/editor-nav.component'; @Component({ selector: 'new-filter-page', @@ -24,20 +23,14 @@ export class NewFilterComponent implements OnDestroy, OnInit { private ngUnsubscribe: Subject = new Subject(); - valueChangeSubject = new Subject>(); - private valueChangeEmitted$ = this.valueChangeSubject.asObservable(); - - statusChangeSubject = new Subject<{ value: any[] }>(); - private statusChangeEmitted$ = this.statusChangeSubject.asObservable(); - definition$: Observable>; schema$: Observable; - changes$: Observable; - model: any; isSaving$: Observable; filter: MetadataFilter; - isValid: boolean; + isValid$: Observable; + isInvalid$: Observable; + cantSave$: Observable; validators$: Observable<{ [key: string]: any }>; @@ -47,17 +40,22 @@ export class NewFilterComponent implements OnDestroy, OnInit { options$: Observable[]>; + formats = NAV_FORMATS; + + status$: Observable; + + type$: Observable = this.store.select(fromFilter.getFilterType); + constructor( private store: Store, - private schemaService: SchemaService, private fb: FormBuilder, private route: ActivatedRoute ) { this.isSaving$ = this.store.select(fromFilter.getCollectionSaving); + this.isValid$ = this.store.select(fromFilter.getFilterIsValid); + this.isInvalid$ = this.isValid$.pipe(map(v => !v)); - this.changes$ = this.store.select(fromFilter.getFilter); - - this.model = {}; + this.cantSave$ = this.store.select(fromFilter.cantSaveFilter).pipe(skip(1)); this.definition$ = this.store.select(fromFilter.getFilterType).pipe( takeUntil(this.ngUnsubscribe), @@ -65,21 +63,19 @@ export class NewFilterComponent implements OnDestroy, OnInit { map(t => MetadataFilterTypes[t]) ); - this.schema$ = this.definition$.pipe( - takeUntil(this.ngUnsubscribe), - filter(d => !!d), - switchMap(d => { - return this.schemaService.get(d.schema).pipe(takeUntil(this.ngUnsubscribe)); - }), - shareReplay() - ); + this.store + .select(fromWizard.getCurrentWizardSchema) + .pipe(filter(s => !!s), takeUntil(this.ngUnsubscribe)) + .subscribe(s => { + if (s) { + this.store.dispatch(new LoadSchemaRequest(s)); + } + }); - this.validators$ = this.definition$.pipe( - takeUntil(this.ngUnsubscribe), - withLatestFrom(this.store.select(fromFilter.getFilterNames)), - map(([definition, names]) => definition.getValidators(names)) - ); + let startIndex$ = this.route.params.pipe(map(p => p.form || 'filters'), takeUntil(this.ngUnsubscribe)); + startIndex$.subscribe(index => this.store.dispatch(new SetIndex(index))); + this.status$ = this.store.select(fromFilter.getInvalidEditorForms); this.options$ = of(Object.values(MetadataFilterTypes)); this.form.get('type').valueChanges @@ -87,19 +83,22 @@ export class NewFilterComponent implements OnDestroy, OnInit { takeUntil(this.ngUnsubscribe), distinctUntilChanged() ) - .subscribe(type => this.store.dispatch(new SelectFilterType(type))); + .subscribe(type => { + this.store.dispatch(new SelectFilterType(type)); + }); + + this.type$.pipe( + takeUntil(this.ngUnsubscribe) + ).subscribe((t: string) => { + if (t) { + this.store.dispatch(new SetDefinition({ + ...MetadataFilterEditorTypes.find(def => def.type === t) + })); + } + }); } ngOnInit(): void { - this.valueChangeEmitted$ - .pipe(takeUntil(this.ngUnsubscribe)) - .subscribe(changes => this.store.dispatch(new UpdateFilterChanges(changes.value))); - this.statusChangeEmitted$ - .pipe(takeUntil(this.ngUnsubscribe)) - .subscribe(valid => { - this.isValid = valid.value ? valid.value.length === 0 : true; - }); - this.store .select(fromFilter.getFilter) .pipe( @@ -116,7 +115,10 @@ export class NewFilterComponent implements OnDestroy, OnInit { } save(): void { - this.store.dispatch(new AddFilterRequest(this.filter)); + this.store.dispatch(new AddFilterRequest({ + filter: this.filter, + providerId: this.route.snapshot.params.providerId + })); } cancel(): void { diff --git a/ui/src/app/metadata/filter/effect/collection.effect.ts b/ui/src/app/metadata/filter/effect/collection.effect.ts index 9e15e691c..db94eacaf 100644 --- a/ui/src/app/metadata/filter/effect/collection.effect.ts +++ b/ui/src/app/metadata/filter/effect/collection.effect.ts @@ -90,12 +90,14 @@ export class FilterCollectionEffects { addFilter$ = this.actions$.pipe( ofType(FilterCollectionActionTypes.ADD_FILTER_REQUEST), map(action => action.payload), - withLatestFrom(this.store.select(fromProvider.getSelectedProviderId).pipe(skipWhile(id => !id))), - switchMap(([unsaved, providerId]) => { + switchMap(({filter, providerId}) => { return this.filterService - .save(providerId, unsaved as MetadataFilter) + .save(providerId, filter as MetadataFilter) .pipe( - map(saved => new AddFilterSuccess(saved)), + map(saved => new AddFilterSuccess({ + filter: saved, + providerId: providerId + })), catchError(error => of(new AddFilterFail(error))) ); }) @@ -104,16 +106,14 @@ export class FilterCollectionEffects { addFilterSuccessRedirect$ = this.actions$.pipe( ofType(FilterCollectionActionTypes.ADD_FILTER_SUCCESS), map(action => action.payload), - withLatestFrom(this.store.select(fromProvider.getSelectedProviderId).pipe(skipWhile(id => !id))), - tap(([filter, provider]) => this.navigateToParent(provider)) + tap(({ providerId }) => this.navigateToParent(providerId)) ); @Effect() addFilterSuccessReloadParent$ = this.actions$.pipe( ofType(FilterCollectionActionTypes.ADD_FILTER_SUCCESS), map(action => action.payload), - withLatestFrom(this.store.select(fromProvider.getSelectedProviderId).pipe(skipWhile(id => !id))), - map(([filter, provider]) => new SelectProviderRequest(provider)) + map(({ providerId }) => new SelectProviderRequest(providerId)) ); @Effect() diff --git a/ui/src/app/metadata/filter/effect/filter.effect.ts b/ui/src/app/metadata/filter/effect/filter.effect.ts index 65c5f8e89..2bdc60bc9 100644 --- a/ui/src/app/metadata/filter/effect/filter.effect.ts +++ b/ui/src/app/metadata/filter/effect/filter.effect.ts @@ -65,6 +65,7 @@ export class FilterEffects { @Effect({ dispatch: false }) cancelChanges$ = this.actions$.pipe( ofType(FilterActionTypes.CANCEL_CREATE_FILTER), + map(action => action.payload), tap((providerId) => { this.router.navigate(['/', 'metadata', 'provider', providerId, 'configuration']); }) diff --git a/ui/src/app/metadata/filter/filter.module.ts b/ui/src/app/metadata/filter/filter.module.ts index 6514b5a06..e7c3bfcff 100644 --- a/ui/src/app/metadata/filter/filter.module.ts +++ b/ui/src/app/metadata/filter/filter.module.ts @@ -24,10 +24,12 @@ import { I18nModule } from '../../i18n/i18n.module'; import { FilterComponent } from './container/filter.component'; import { FilterListComponent } from './component/filter-list.component'; import { EditFilterStepComponent } from './container/edit-filter-step.component'; +import { NewFilterStepComponent } from './container/new-filter-step.component'; @NgModule({ declarations: [ NewFilterComponent, + NewFilterStepComponent, EditFilterComponent, EditFilterStepComponent, SelectFilterComponent, diff --git a/ui/src/app/metadata/filter/model/nameid-configuration.filter.ts b/ui/src/app/metadata/filter/model/nameid-configuration.filter.ts index 4ff615ac6..5520f4919 100644 --- a/ui/src/app/metadata/filter/model/nameid-configuration.filter.ts +++ b/ui/src/app/metadata/filter/model/nameid-configuration.filter.ts @@ -6,10 +6,14 @@ export const NameIDFilterConfiguration: Wizard = { ...NameIDFilter, steps: [ { - id: 'target', + id: 'common', label: 'label.target', index: 1, fields: [ + 'name', + 'filterEnabled', + '@type', + 'resourceId', 'nameIdFormatFilterTarget' ] }, @@ -19,10 +23,6 @@ export const NameIDFilterConfiguration: Wizard = { index: 1, initialValues: [], fields: [ - 'name', - 'filterEnabled', - '@type', - 'resourceId', 'removeExistingFormats', 'formats' ] diff --git a/ui/src/app/metadata/filter/reducer/editor.reducer.ts b/ui/src/app/metadata/filter/reducer/editor.reducer.ts index 0d56550b7..dcb0620f4 100644 --- a/ui/src/app/metadata/filter/reducer/editor.reducer.ts +++ b/ui/src/app/metadata/filter/reducer/editor.reducer.ts @@ -2,28 +2,21 @@ import { EditorActionTypes, EditorActionUnion } from '../action/editor.action'; export interface EditorState { status: { [key: string]: string }; - type: string; } export const initialState: EditorState = { - status: {}, - type: null + status: {} }; export function reducer(state = initialState, action: EditorActionUnion): EditorState { switch (action.type) { - case EditorActionTypes.SELECT_PROVIDER_TYPE: { - return { - ...state, - type: action.payload - }; - } case EditorActionTypes.CLEAR: { return { ...initialState }; } case EditorActionTypes.UPDATE_STATUS: { + //console.log(action) return { ...state, status: { diff --git a/ui/src/app/metadata/filter/reducer/filter.reducer.ts b/ui/src/app/metadata/filter/reducer/filter.reducer.ts index 68aaf40ed..bda4668ca 100644 --- a/ui/src/app/metadata/filter/reducer/filter.reducer.ts +++ b/ui/src/app/metadata/filter/reducer/filter.reducer.ts @@ -39,13 +39,14 @@ export function reducer(state = initialState, action: FilterActionsUnion): Filte }; } case FilterActionTypes.UPDATE_FILTER: { - return { + const s = { ...state, changes: { ...state.changes, ...action.payload } }; + return s; } case FilterActionTypes.CLEAR_FILTER: case FilterActionTypes.CANCEL_CREATE_FILTER: { diff --git a/ui/src/app/metadata/filter/reducer/index.ts b/ui/src/app/metadata/filter/reducer/index.ts index 71d71707e..ee2da9bf3 100644 --- a/ui/src/app/metadata/filter/reducer/index.ts +++ b/ui/src/app/metadata/filter/reducer/index.ts @@ -85,10 +85,10 @@ Editor State */ export const getEditorIsValid = createSelector(getEditorState, fromEditor.isEditorValid); - export const getFormStatus = createSelector(getEditorState, fromEditor.getFormStatus); export const getInvalidEditorForms = createSelector(getEditorState, fromEditor.getInvalidForms); + /* * Combine pieces of State */ @@ -97,8 +97,12 @@ export const mergeFn = (changes, filter) => ({ ...filter, ...changes }); export const detectFilterType = (changes) => changes.type ? changes.type : changes.hasOwnProperty('@type') ? changes['@type'] : null; export const getFilterWithChanges = createSelector(getFilter, getSelectedFilter, mergeFn); -export const getFilterType = createSelector(getFilter, (changes: MetadataFilter) => { - const type = changes ? detectFilterType(changes) : null; - return type; +export const getFilterType = createSelector(getFilter, (changes: MetadataFilter) => changes ? detectFilterType(changes) : null); + +export const getFilterIsValid = createSelector(getEditorIsValid, getFilterType, getFormStatus, (isValid, type, status) => { + return isValid && type !== null && Object.keys(status).length > 0; }); +export const cantSaveFilter = createSelector(getCollectionSaving, getFilterIsValid, (isSaving, isValid) => { + return (isSaving || !isValid); +}); \ No newline at end of file diff --git a/ui/src/app/metadata/provider/container/provider-select.component.ts b/ui/src/app/metadata/provider/container/provider-select.component.ts index 160ad8332..6e300d302 100644 --- a/ui/src/app/metadata/provider/container/provider-select.component.ts +++ b/ui/src/app/metadata/provider/container/provider-select.component.ts @@ -37,7 +37,6 @@ export class ProviderSelectComponent implements OnDestroy { this.providerSubscription = this.provider$.subscribe(provider => { this.setDefinition(provider); }); - console.log('hi there') } setDefinition(provider: MetadataProvider): void { diff --git a/ui/src/app/metadata/provider/provider.routing.ts b/ui/src/app/metadata/provider/provider.routing.ts index 975b9b427..635edc45f 100644 --- a/ui/src/app/metadata/provider/provider.routing.ts +++ b/ui/src/app/metadata/provider/provider.routing.ts @@ -14,6 +14,7 @@ import { CanDeactivateGuard } from '../../core/service/can-deactivate.guard'; import { FilterComponent } from '../filter/container/filter.component'; import { AdminGuard } from '../../core/service/admin.guard'; import { MetadataProviderPageComponent } from './provider.component'; +import { NewFilterStepComponent } from '../filter/container/new-filter-step.component'; export const ProviderRoutes: Routes = [ { @@ -33,7 +34,7 @@ export const ProviderRoutes: Routes = [ { path: 'new', component: ProviderWizardStepComponent, - data: { title: `Create Provider`, subtitle: true } + data: { title: `Create Provider`, subtitle: true }, } ] }, @@ -70,7 +71,15 @@ export const ProviderRoutes: Routes = [ { path: 'new', component: NewFilterComponent, - data: { title: `Create New Filter` } + data: { title: `Create New Filter` }, + children: [ + { path: '', redirectTo: 'common', pathMatch: 'prefix' }, + { + path: ':form', + component: NewFilterStepComponent, + data: { title: `Create Filter`, subtitle: true } + } + ] }, { path: ':filterId',