Skip to content

Commit

Permalink
Merged in feature/SHIBUI-297 (pull request #28)
Browse files Browse the repository at this point in the history
SHIBUI-297: Implemented modal search

Approved-by: Ryan Mathis <rmathis@unicon.net>
  • Loading branch information
rmathis committed Mar 26, 2018
1 parent 9294428 commit 142cca6
Show file tree
Hide file tree
Showing 17 changed files with 196 additions and 77 deletions.
5 changes: 5 additions & 0 deletions ui/src/app/core/model/query.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export interface QueryParams {
term: string;
limit?: number;
offset?: number;
}
5 changes: 2 additions & 3 deletions ui/src/app/metadata-filter/action/filter.action.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@ describe('Filter Actions', () => {
it('should provide actions', () => {
expect(new actions.CancelCreateFilter().type).toBe(actions.CANCEL_CREATE_FILTER);
expect(new actions.CancelViewMore().type).toBe(actions.CANCEL_VIEW_MORE);
expect(new actions.LoadEntityIds('foo').type).toBe(actions.LOAD_ENTITY_IDS);
expect(new actions.QueryEntityIds({term: 'foo'}).type).toBe(actions.QUERY_ENTITY_IDS);
expect(new actions.LoadEntityIdsSuccess([]).type).toBe(actions.LOAD_ENTITY_IDS_SUCCESS);
expect(new actions.LoadEntityIdsError(new Error('Foobar!')).type).toBe(actions.LOAD_ENTITY_IDS_ERROR);
expect(new actions.ViewMoreIds([]).type).toBe(actions.VIEW_MORE_IDS);
expect(new actions.ViewMoreIds('foo').type).toBe(actions.VIEW_MORE_IDS);
expect(new actions.SelectId('foo').type).toBe(actions.SELECT_ID);
expect(new actions.QueryEntityIds([]).type).toBe(actions.QUERY_ENTITY_IDS);
});
});
15 changes: 4 additions & 11 deletions ui/src/app/metadata-filter/action/filter.action.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import { Action } from '@ngrx/store';

import { QueryParams } from '../../core/model/query';

export const QUERY_ENTITY_IDS = '[Filter] Query Entity Ids';
export const VIEW_MORE_IDS = '[Filter] View More Ids Modal';
export const CANCEL_VIEW_MORE = '[Filter] Cancel View More';
export const SELECT_ID = '[Filter] Select Entity ID';
export const CANCEL_CREATE_FILTER = '[Filter] Cancel Create Filter';

export const LOAD_ENTITY_IDS = '[Entity ID Collection] Load Entity Ids';
export const LOAD_ENTITY_IDS_SUCCESS = '[Entity ID Collection] Load Entity Ids Success';
export const LOAD_ENTITY_IDS_ERROR = '[Entity ID Collection] Load Entity Ids Error';

export class QueryEntityIds implements Action {
readonly type = QUERY_ENTITY_IDS;

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

export class CancelCreateFilter implements Action {
Expand All @@ -23,7 +23,7 @@ export class CancelCreateFilter implements Action {
export class ViewMoreIds implements Action {
readonly type = VIEW_MORE_IDS;

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

export class CancelViewMore implements Action {
Expand All @@ -36,12 +36,6 @@ export class SelectId implements Action {
constructor(public payload: string) { }
}

export class LoadEntityIds implements Action {
readonly type = LOAD_ENTITY_IDS;

constructor(public payload: string) { }
}

export class LoadEntityIdsSuccess implements Action {
readonly type = LOAD_ENTITY_IDS_SUCCESS;

Expand All @@ -59,7 +53,6 @@ export type Actions =
| CancelViewMore
| CancelCreateFilter
| SelectId
| LoadEntityIds
| LoadEntityIdsSuccess
| LoadEntityIdsError
| QueryEntityIds;
35 changes: 30 additions & 5 deletions ui/src/app/metadata-filter/component/search-dialog.component.html
Original file line number Diff line number Diff line change
@@ -1,16 +1,41 @@
<div class="modal-header">
<h4 class="modal-title">Heading</h4>
<h4 class="modal-title">
<ng-container i18n="@@label--search-entity-id">Search Entity Id ({{ source }})</ng-container>

</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close" (click)="activeModal.dismiss()">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
Body
<form [formGroup]="form">
<div class="form-row">
<div class="form-group col-9">
<input type="text"
formControlName="search"
class="form-control"
/>
</div>
<div class="form-group col-3">
<button class="btn btn-primary btn-block">
<i class="fa fa-search"></i>
<ng-container i18n="@@action--search">Search</ng-container>
</button>
</div>
</div>
</form>
<div class="list-group list-group-flush scrolled my-2" id="list-tab" role="tablist">
<a href=""
*ngFor="let item of matches$ | async"
class="list-group-item list-group-item-action p-1"
[class.active]="item === selected"
(click)="select($event, item)">{{ item }}</a>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" (click)="activeModal.close('https://account.example.com/sso')">
<button type="button" class="btn btn-primary" (click)="activeModal.close(selected)">
<i class="fa fa-save"></i>
Select ID
<ng-container i18n="@@action--select-id">Select ID</ng-container>
</button>
<button type="button" class="btn btn-secondary" (click)="activeModal.dismiss()" i18n="@@action--cancel">Cancel</button>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
:host {
.scrolled {
max-height: 400px;
overflow: scroll;
}
}
50 changes: 43 additions & 7 deletions ui/src/app/metadata-filter/component/search-dialog.component.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,63 @@
import { Component, OnChanges, OnInit } from '@angular/core';
import { Component, AfterViewInit, Input, OnInit, SimpleChange, SimpleChanges } from '@angular/core';
import { NgbModal, NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
import { Observable } from 'rxjs/Observable';
import { Store } from '@ngrx/store';

import * as fromFilter from '../reducer';
import { QueryEntityIds } from '../action/filter.action';
import { FormBuilder, FormGroup } from '@angular/forms';

@Component({
selector: 'search-dialog',
templateUrl: './search-dialog.component.html'
templateUrl: './search-dialog.component.html',
styleUrls: ['./search-dialog.component.scss']
})
export class SearchDialogComponent implements OnInit, OnChanges {
export class SearchDialogComponent implements OnInit, AfterViewInit {

@Input() term: string;
@Input() source = 'InCommon';

matches$: Observable<string[]>;

selected: string;

limit = 100;
dbounce = 500;

form: FormGroup = this.fb.group({
search: [''],
entityId: ['']
});

constructor(
public activeModal: NgbActiveModal,
private store: Store<fromFilter.State>
private store: Store<fromFilter.State>,
private fb: FormBuilder
) {
// console.log(activeModal);
// this.query$ = this.store.select(fromFilter.getQuery);
this.matches$ = this.store.select(fromFilter.getEntityCollection);
}

ngOnChanges(): void {
ngOnInit(): void {
let search = this.form.get('search');
search.setValue(this.term);

search.valueChanges
.debounceTime(this.dbounce)
.subscribe(val =>
this.store.dispatch(
new QueryEntityIds({ term: val, limit: this.limit })
)
);
}

ngOnInit(): void {
ngAfterViewInit(): void {
const { term, limit } = this;
this.store.dispatch(new QueryEntityIds({ term, limit }));
}

select($event: MouseEvent, id: string): void {
$event.preventDefault();
this.selected = id;
}
} /* istanbul ignore next */
10 changes: 3 additions & 7 deletions ui/src/app/metadata-filter/container/new-filter.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
<span>
<ng-container i18n="@@label--search-entity-id">Search Entity ID</ng-container>
<i class="fa fa-asterisk text-danger" aria-hidden="true"></i>
<i class="fa fa-spinner fa-pulse fa-fw" *ngIf="loading$ | async"></i>
<i class="fa fa-spinner fa-pulse fa-fw" *ngIf="processing$ | async"></i>
</span>
</label>
<span class="text-right col-sm-2">
Expand All @@ -67,9 +67,9 @@
[matches]="entityIds$ | async"
[required]="true"
limit="10"
[processing]="loading$ | async"
[processing]="(processing$ | async)"
(onChange)="searchEntityIds($event)"
(more)="onViewMore()">
(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')">
Expand Down Expand Up @@ -100,10 +100,6 @@ <h2>TESTING: </h2>
Form Errors:
<pre>{{ form.errors | json }}</pre>
</div>
<div>
Test Options:
<pre>{{ entityIds$ | async | json }}</pre>
</div>
<div>
Current Form Values:
<pre>{{ form.value | json }}</pre>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ describe('New Metadata Filter Page', () => {
describe('onViewMore method', () => {
it('should dispatch a viewMoreEntityIds action', () => {
fixture.detectChanges();
instance.onViewMore();
instance.onViewMore('foo');
expect(store.dispatch).toHaveBeenCalled();
});
});
Expand Down
23 changes: 13 additions & 10 deletions ui/src/app/metadata-filter/container/new-filter.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ import { FormBuilder, Validators } from '@angular/forms';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';
import 'rxjs/add/operator/takeWhile';

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 { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { SearchDialogComponent } from '../component/search-dialog.component';
import { ViewMoreIds, CancelCreateFilter, LoadEntityIds } from '../action/filter.action';
import { ViewMoreIds, CancelCreateFilter, QueryEntityIds } from '../action/filter.action';
import { EntityValidators } from '../../metadata-provider/service/entity-validators.service';


Expand All @@ -19,12 +20,12 @@ import { EntityValidators } from '../../metadata-provider/service/entity-validat
})
export class NewFilterComponent extends ProviderFormFragmentComponent implements OnInit, OnChanges, OnDestroy {

entityIds$: Observable<string[]>;
ids: string[];

entityIds$: Observable<string[]>;
showMore$: Observable<boolean>;
selected$: Observable<string>;
loading$: Observable<boolean>;
processing$: Observable<boolean>;

constructor(
private store: Store<fromFilter.State>,
Expand All @@ -34,12 +35,11 @@ export class NewFilterComponent extends ProviderFormFragmentComponent implements
) {
super(fb, statusEmitter, valueEmitter);

// this.form.statusChanges.subscribe(status => console.log(status));

this.showMore$ = this.store.select(fromFilter.getViewingMore);
this.selected$ = this.store.select(fromFilter.getSelected);
this.entityIds$ = this.store.select(fromFilter.getEntityCollection);
this.loading$ = this.store.select(fromFilter.getIsLoading);
this.processing$ = this.loading$.withLatestFrom(this.showMore$, (l, s) => !s && l);

this.entityIds$.subscribe(ids => this.ids = ids);

Expand Down Expand Up @@ -67,14 +67,17 @@ export class NewFilterComponent extends ProviderFormFragmentComponent implements

ngOnDestroy(): void {}

searchEntityIds(query: string): void {
if (query.length >= 4) {
this.store.dispatch(new LoadEntityIds(query));
searchEntityIds(term: string): void {
if (term.length >= 4 && this.ids.indexOf(term) < 0) {
this.store.dispatch(new QueryEntityIds({
term,
limit: 10
}));
}
}

onViewMore(): void {
this.store.dispatch(new ViewMoreIds(this.ids));
onViewMore(query: string): void {
this.store.dispatch(new ViewMoreIds(query));
}

save(): void {
Expand Down
35 changes: 27 additions & 8 deletions ui/src/app/metadata-filter/effect/filter.effect.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import { Injectable } from '@angular/core';
import { Effect, Actions } from '@ngrx/effects';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs/Observable';
import { Router } from '@angular/router';
import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';

import 'rxjs/add/observable/fromPromise';
import 'rxjs/add/observable/of';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/switchMap';
import 'rxjs/add/operator/withLatestFrom';

import * as filter from '../action/filter.action';
import * as fromFilter from '../reducer';

import { Router } from '@angular/router';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { SearchDialogComponent } from '../component/search-dialog.component';
import { EntityIdService } from '../../metadata-provider/service/entity-id.service';

Expand All @@ -21,7 +24,7 @@ export class FilterEffects {

@Effect()
loadEntityIds$ = this.actions$
.ofType<filter.LoadEntityIds>(filter.LOAD_ENTITY_IDS)
.ofType<filter.QueryEntityIds>(filter.QUERY_ENTITY_IDS)
.map(action => action.payload)
.debounceTime(this.dbounce)
.switchMap(query =>
Expand All @@ -40,17 +43,33 @@ export class FilterEffects {
viewMore$ = this.actions$
.ofType<filter.ViewMoreIds>(filter.VIEW_MORE_IDS)
.map(action => action.payload)
.switchMap(() =>
Observable
.fromPromise(this.modalService.open(SearchDialogComponent).result)
.switchMap(q => {
const modal = this.modalService.open(SearchDialogComponent) as NgbModalRef;
const res = modal.result;
modal.componentInstance.term = q;
return Observable
.fromPromise(res)
.map(id => new filter.SelectId(id))
.catch(() => Observable.of(new filter.CancelViewMore()))
.catch(() => Observable.of(new filter.CancelViewMore()));
});
/*
@Effect()
viewMoreQuery$ = this.actions$
.ofType<filter.ViewMoreIds>(filter.VIEW_MORE_IDS)
.map(action => action.payload)
.switchMap(query =>
this.idService
.query(query)
.map(ids => new filter.LoadEntityIdsSuccess(ids))
.catch(error => Observable.of(new filter.LoadEntityIdsError(error)))
);
*/

constructor(
private actions$: Actions,
private router: Router,
private modalService: NgbModal,
private idService: EntityIdService
private idService: EntityIdService,
private store: Store<fromFilter.State>
) { }
}
Loading

0 comments on commit 142cca6

Please sign in to comment.