Skip to content

Commit

Permalink
Merged in feature/SHIBUI-284 (pull request #5)
Browse files Browse the repository at this point in the history
Added fields for entity ID search

* Added fields for entity ID search

* Fixed unit tests

* Added test for action

Approved-by: Ryan Mathis <rmathis@unicon.net>
  • Loading branch information
rmathis committed Mar 12, 2018
1 parent 93b434d commit 0f1091f
Show file tree
Hide file tree
Showing 14 changed files with 346 additions and 44 deletions.
2 changes: 2 additions & 0 deletions ui/src/app/app.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ import { AppComponent } from './app.component';
import { User } from './core/model/user';
import * as fromUser from './core/reducer/user.reducer';
import { NotificationModule } from './notification/notification.module';
import { NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap';

describe('AppComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
NgbDropdownModule.forRoot(),
RouterTestingModule,
StoreModule.forRoot({
user: combineReducers(fromUser.reducer),
Expand Down
20 changes: 20 additions & 0 deletions ui/src/app/metadata-filter/action/collection.action.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Action } from '@ngrx/store';

export const CANCEL_CREATE_FILTER = '[Filter Collection] Cancel Create Filter';

export class CancelCreateFilter implements Action {
readonly type = CANCEL_CREATE_FILTER;

constructor(public payload: boolean) { }
}

/*
export class SaveChanges implements Action {
readonly type = SAVE_CHANGES;
constructor(public payload: MetadataProvider) { }
}
*/

export type Actions =
| CancelCreateFilter;
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,3 @@ export class QueryEntityIds implements Action {

constructor(public payload: string[]) { }
}

export type Actions =
| QueryEntityIds;
68 changes: 67 additions & 1 deletion ui/src/app/metadata-filter/container/new-filter.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,73 @@
</div>
</div>
<div class="section-body p-4 border border-top-0 border-info">
Body
<form [formGroup]="form">
<div class="row">
<div class="col-lg-6 col-xs-9 ">
<fieldset class="">
<div class="form-group">
<label for="filterName">
<ng-container i18n="@@label--filter-name">
Filter Name
</ng-container>
<ng-container i18n="@@label--dashboard-display-only">
(Dashboard Display Only)
</ng-container>
<i class="fa fa-asterisk text-danger" aria-hidden="true"></i>
</label>
<input id="filterName" type="text" class="form-control" placeholder="" formControlName="filterName" />
<ng-container *ngIf="form.get('filterName').touched && form.get('filterName').invalid">
<small class="form-text text-danger" *ngIf="form.get('filterName').hasError('required')">
<ng-container i18n="@@message--service-provider-name-required">Filter Name is required</ng-container>
</small>
</ng-container>
</div>
<div class="form-group">
<label for="entityId">
<ng-container i18n="@@label--search-entity-id">Search Entity ID</ng-container>
<i class="fa fa-asterisk text-danger" aria-hidden="true"></i>
</label>
<auto-complete
id="entityId"
formControlName="entityId"
[options]="entityIds$ | async"
[required]="true"
(more)="onViewMore($event)">
</auto-complete>
<ng-container *ngIf="form.get('entityId').touched && form.get('entityId').invalid">
<small class="form-text text-danger" *ngIf="form.get('entityId').hasError('required')">
<ng-container i18n="@@message--entity-id-required">Entity ID is required</ng-container>
</small>
</ng-container>
<small class="form-text text-danger" *ngIf="form.get('entityId').hasError('unique')">
<ng-container i18n="@@message--entity-id-must-be-unique">Entity ID must be unique</ng-container>
</small>
</div>
</fieldset>
</div>
<div class="col-lg-6 col-xs-3 text-right">
<button (click)="save()" type="submit" class="btn btn-primary" [disabled]="form.invalid">
<i class="fa fa-save fa-lg"></i>
<ng-container i18n="@@action--save-changes">Save Changes</ng-container>
</button>
<button (click)="cancel()" type="reset" class="btn btn-secondary">
<ng-container i18n="@@action--cancel">Cancel</ng-container>
</button>
</div>
</div>
<div class="row">
<div class="col-12">
<hr />
<h2>TESTING: </h2>
Test Options:
<pre>{{ entityIds$ | async | json }}</pre>
Current Form Values:
<pre>{{ form.value | json }}</pre>
<!--<relying-party-form [provider]="latest$ | async"></relying-party-form>
<attribute-release-form [provider]="latest$ | async"></attribute-release-form>-->
</div>
</div>
</form>
</div>
</section>
</div>
21 changes: 18 additions & 3 deletions ui/src/app/metadata-filter/container/new-filter.component.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { TestBed, ComponentFixture } from '@angular/core/testing';
import { ReactiveFormsModule } from '@angular/forms';
import { ReactiveFormsModule, FormBuilder } from '@angular/forms';
import { StoreModule, Store, combineReducers } from '@ngrx/store';
import { NewFilterComponent } from './new-filter.component';
import * as fromFilter from '../reducer';
import { ProviderEditorFormModule } from '../../metadata-provider/component';
import { ProviderStatusEmitter, ProviderValueEmitter } from '../../metadata-provider/service/provider-change-emitter.service';

describe('New Metadata Filter Page', () => {
let fixture: ComponentFixture<NewFilterComponent>;
Expand All @@ -11,12 +13,17 @@ describe('New Metadata Filter Page', () => {

beforeEach(() => {
TestBed.configureTestingModule({
providers: [],
providers: [
ProviderStatusEmitter,
ProviderValueEmitter,
FormBuilder
],
imports: [
StoreModule.forRoot({
providers: combineReducers(fromFilter.reducers),
}),
ReactiveFormsModule
ReactiveFormsModule,
ProviderEditorFormModule
],
declarations: [NewFilterComponent],
});
Expand All @@ -33,4 +40,12 @@ describe('New Metadata Filter Page', () => {

expect(fixture).toBeDefined();
});

describe('cancel method', () => {
it('should dispatch a cancel changes action', () => {
fixture.detectChanges();
instance.cancel();
expect(store.dispatch).toHaveBeenCalled();
});
});
});
48 changes: 42 additions & 6 deletions ui/src/app/metadata-filter/container/new-filter.component.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,54 @@
import { Component } from '@angular/core';
import { Component, OnInit, OnChanges, OnDestroy } from '@angular/core';
import { FormBuilder, Validators } from '@angular/forms';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';

import * as fromFilter from '../reducer';
import { ProviderFormFragmentComponent } from '../../metadata-provider/component/forms/provider-form-fragment.component';
import { ProviderStatusEmitter, ProviderValueEmitter } from '../../metadata-provider/service/provider-change-emitter.service';
import { CancelCreateFilter } from '../action/collection.action';

@Component({
selector: 'new-filter-page',
templateUrl: './new-filter.component.html'
})
export class NewFilterComponent {
export class NewFilterComponent extends ProviderFormFragmentComponent implements OnInit, OnChanges, OnDestroy {

entityIds$: Observable<string[]>;

constructor(
private store: Store<fromFilter.State>
) {}
private store: Store<fromFilter.State>,
protected statusEmitter: ProviderStatusEmitter,
protected valueEmitter: ProviderValueEmitter,
protected fb: FormBuilder
) {
super(fb, statusEmitter, valueEmitter);
}

createForm(): void {
this.form = this.fb.group({
entityId: ['', Validators.required],
filterName: ['', Validators.required]
});
}

ngOnInit(): void {
super.ngOnInit();
this.entityIds$ = Observable.of(['foo', 'bar', 'baz']);
}

ngOnChanges(): void {}

ngOnDestroy(): void {}

onViewMore($event): void {}

save(): void {}
save(): void {
console.log('Save!');
}

cancel(): void {}
cancel(): void {
this.store.dispatch(new CancelCreateFilter(true));
}
}
20 changes: 20 additions & 0 deletions ui/src/app/metadata-filter/effect/filter.effect.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Injectable } from '@angular/core';
import { Effect, Actions } from '@ngrx/effects';

import * as filter from '../action/collection.action';
import { Router } from '@angular/router';

@Injectable()
export class FilterEffects {

@Effect({ dispatch: false })
cancelChanges$ = this.actions$
.ofType<filter.CancelCreateFilter>(filter.CANCEL_CREATE_FILTER)
.map(action => action.payload)
.switchMap(() => this.router.navigate(['/dashboard']));

constructor(
private actions$: Actions,
private router: Router
) { }
}
8 changes: 6 additions & 2 deletions ui/src/app/metadata-filter/filter.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import { EffectsModule } from '@ngrx/effects';

import { NewFilterComponent } from './container/new-filter.component';
import { reducers } from './reducer';
import { ProviderFormFragmentComponent } from '../metadata-provider/component/forms/provider-form-fragment.component';
import { ProviderEditorFormModule } from '../metadata-provider/component';
import { FilterEffects } from './effect/filter.effect';

export const routes: Routes = [
{
Expand All @@ -26,8 +29,9 @@ export const routes: Routes = [
RouterModule,
ReactiveFormsModule,
StoreModule.forFeature('metadata-filter', reducers),
EffectsModule.forFeature([]),
RouterModule.forChild(routes)
EffectsModule.forFeature([FilterEffects]),
RouterModule.forChild(routes),
ProviderEditorFormModule
],
providers: []
})
Expand Down
8 changes: 6 additions & 2 deletions ui/src/app/metadata-filter/reducer/filter.reducer.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import { createSelector, createFeatureSelector } from '@ngrx/store';
import { MetadataProvider } from '../../metadata-provider/model/metadata-provider';
import * as filter from '../action/filter.action';
import * as filter from '../action/collection.action';
import * as fromRoot from '../../core/reducer';

export interface FilterState {
entityIds: string[];
loading: boolean;
error: string | null;
}

export const initialState: FilterState = {
entityIds: []
entityIds: [],
loading: false,
error: null
};

export function reducer(state = initialState, action: filter.Actions): FilterState {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { TestBed, async, inject } from '@angular/core/testing';
import { Observable } from 'rxjs/Observable';
import { AbstractControl, FormBuilder, ReactiveFormsModule } from '@angular/forms';
import 'rxjs/add/observable/of';

import * as AutoCompleteValidators from './autocomplete-validators.service';

let ids = ['foo', 'bar', 'baz'];

describe(`existsInCollection`, () => {

beforeEach(() => {
TestBed.configureTestingModule({
imports: [
ReactiveFormsModule
],
providers: [
FormBuilder
]
});
});

describe('createUniqueIdValidator', () => {
it('should detect that a provided id is in the collection', async(inject([FormBuilder], (fb) => {
let obs = Observable.of(ids),
validator = AutoCompleteValidators.existsInCollection(obs),
ctrl = fb.control('foo');
validator(ctrl).subscribe(next => {
expect(next).toBeNull();
});
})));

it('should detect that a provided id is not in the collection', async(inject([FormBuilder], (fb) => {
let obs = Observable.of(ids),
validator = AutoCompleteValidators.existsInCollection(obs),
ctrl = fb.control('hi');
validator(ctrl).subscribe(next => {
expect(next).toBeTruthy();
});
})));
});
});
17 changes: 17 additions & 0 deletions ui/src/app/widget/autocomplete/autocomplete-validators.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Observable } from 'rxjs/Observable';
import { AbstractControl } from '@angular/forms';
import 'rxjs/add/operator/take';
import 'rxjs/add/operator/startWith';
import 'rxjs/add/operator/map';

export function existsInCollection (ids$: Observable<string[]>) {
return(control: AbstractControl) => {
return ids$
.map(ids => ids.find(id => id === control.value))
.map(ids => ids && !!ids.length)
.map((exists: boolean) => {
return exists ? null : { exists: true };
})
.take(1);
};
}
Loading

0 comments on commit 0f1091f

Please sign in to comment.