From 3d47c4bc1115099ddc632233cb6b0b53677fd006 Mon Sep 17 00:00:00 2001 From: Jodie Muramoto Date: Tue, 24 Jul 2018 19:53:19 +0000 Subject: [PATCH] Merged in feature/SHIBUI-574 (pull request #117) Feature/SHIBUI-574 * feature/SHIBUI-574: Adding provider item component and styling * feature/SHIBUI-574: Finished adding provider items with edit button (not working) into the UI * feature/SHIBUI-574: Removed JOSN list from UI (for development purposes only) * SHIBUI-574: Resolving merge conflict (accepting mine); * SHIBUI-574: Correcting status label; added enabled/disabled icons in provider list on the dashboard; * SHIBUI-574/SHIBUI-620: Refactored based on PR feedback; added reorder UI; * SHIBUI-574: Added filter button the provider item (dashboard); * SHIBUI-574 Updated Resolver Item list * SHIBUI-574 Fixed bad input * SHIBUI-574 Added tests to provider dashboard components * feature/SHIBUI-574: Added my code for unit testing (not complete) * SHIBUI-574 Fixed test Approved-by: Shibui Jenkins --- .../domain/model/metadata-provider.ts | 3 + .../component/entity-item.component.spec.ts | 3 - .../component/entity-item.component.ts | 18 ++-- .../component/provider-item.component.html | 79 ++++++++++++++++++ .../component/provider-item.component.scss | 44 ++++++++++ .../component/provider-item.component.ts | 15 ++++ ...nent.html => resolver-item.component.html} | 0 ...nent.scss => resolver-item.component.scss} | 0 .../component/resolver-item.component.spec.ts | 34 ++++++++ .../component/resolver-item.component.ts | 14 ++++ .../dashboard-providers-list.component.html | 18 ++-- ...dashboard-providers-list.component.spec.ts | 83 +++++++++++++++++++ .../dashboard-providers-list.component.ts | 18 +++- .../dashboard-resolvers-list.component.html | 18 ++-- ...dashboard-resolvers-list.component.spec.ts | 3 +- .../container/manager.component.spec.ts | 35 ++++++++ ui/src/app/metadata/manager/manager.module.ts | 4 + .../reducer/collection.reducer.spec.ts | 20 ++++- 18 files changed, 375 insertions(+), 34 deletions(-) create mode 100644 ui/src/app/metadata/manager/component/provider-item.component.html create mode 100644 ui/src/app/metadata/manager/component/provider-item.component.scss create mode 100644 ui/src/app/metadata/manager/component/provider-item.component.ts rename ui/src/app/metadata/manager/component/{entity-item.component.html => resolver-item.component.html} (100%) rename ui/src/app/metadata/manager/component/{entity-item.component.scss => resolver-item.component.scss} (100%) create mode 100644 ui/src/app/metadata/manager/component/resolver-item.component.spec.ts create mode 100644 ui/src/app/metadata/manager/component/resolver-item.component.ts create mode 100644 ui/src/app/metadata/manager/container/dashboard-providers-list.component.spec.ts create mode 100644 ui/src/app/metadata/manager/container/manager.component.spec.ts diff --git a/ui/src/app/metadata/domain/model/metadata-provider.ts b/ui/src/app/metadata/domain/model/metadata-provider.ts index 4dc283368..4b0a7bc46 100644 --- a/ui/src/app/metadata/domain/model/metadata-provider.ts +++ b/ui/src/app/metadata/domain/model/metadata-provider.ts @@ -1,10 +1,13 @@ import { MetadataBase, } from '../model'; +import { MetadataFilter } from './metadata-filter'; export interface MetadataProvider extends MetadataBase { name: string; '@type': string; enabled: boolean; resourceId: string; + sortKey: number; + metadataFilters: MetadataFilter[]; } diff --git a/ui/src/app/metadata/manager/component/entity-item.component.spec.ts b/ui/src/app/metadata/manager/component/entity-item.component.spec.ts index b71ce9f57..1de355104 100644 --- a/ui/src/app/metadata/manager/component/entity-item.component.spec.ts +++ b/ui/src/app/metadata/manager/component/entity-item.component.spec.ts @@ -7,8 +7,6 @@ describe('Resolver List item', () => { let fixture: ComponentFixture; let instance: EntityItemComponent; - let resolver = new FileBackedHttpMetadataResolver({ entityId: 'foo', serviceProviderName: 'bar' }); - beforeEach(() => { TestBed.configureTestingModule({ providers: [], @@ -20,7 +18,6 @@ describe('Resolver List item', () => { fixture = TestBed.createComponent(EntityItemComponent); instance = fixture.componentInstance; - instance.entity = resolver; }); it('should compile', () => { diff --git a/ui/src/app/metadata/manager/component/entity-item.component.ts b/ui/src/app/metadata/manager/component/entity-item.component.ts index b5aed3756..b2453c474 100644 --- a/ui/src/app/metadata/manager/component/entity-item.component.ts +++ b/ui/src/app/metadata/manager/component/entity-item.component.ts @@ -6,18 +6,14 @@ import { MetadataTypes } from '../../domain/domain.type'; @Component({ selector: 'entity-item', changeDetection: ChangeDetectionStrategy.OnPush, - templateUrl: './entity-item.component.html', - styleUrls: ['./entity-item.component.scss'] + template: '', + styleUrls: [] }) export class EntityItemComponent { - types = MetadataTypes; - - @Input() entity: MetadataEntity; @Input() isOpen: boolean; - @Output() select = new EventEmitter(); - @Output() toggle = new EventEmitter(); - @Output() preview = new EventEmitter(); - @Output() delete = new EventEmitter(); - -} /* istanbul ignore next */ + @Output() select = new EventEmitter(); + @Output() toggle = new EventEmitter(); + @Output() preview = new EventEmitter(); + @Output() delete = new EventEmitter(); +} diff --git a/ui/src/app/metadata/manager/component/provider-item.component.html b/ui/src/app/metadata/manager/component/provider-item.component.html new file mode 100644 index 000000000..32cfd1d21 --- /dev/null +++ b/ui/src/app/metadata/manager/component/provider-item.component.html @@ -0,0 +1,79 @@ +
+
+
+
+

1

+ + +
+
+
+ +   + + + +
+
+ {{ provider.name }} + + {{ provider['@type'] }} +
+
+
+ + +
+
+
+
+
+
+
+
+
+ Metadata Provider Name: +
+
{{ provider.name }}
+
+ Created Date: +
+
{{ provider.createdDate | date:'medium' }}
+
+
+
+ Metadata Provider Type: +
+
{{ provider['@type'] }}
+
+ Metadata Provider Status: +
+
+ + Enabled + Disabled +
+
+
+
+
+
+
+ + diff --git a/ui/src/app/metadata/manager/component/provider-item.component.scss b/ui/src/app/metadata/manager/component/provider-item.component.scss new file mode 100644 index 000000000..2ab451b75 --- /dev/null +++ b/ui/src/app/metadata/manager/component/provider-item.component.scss @@ -0,0 +1,44 @@ +@import '../../../../theme/palette'; + +.card { + background-color: rgba($light-grey, 0.5); + &:focus { + outline: -webkit-focus-ring-color auto 5px; + } + .btn-link { + &:focus { + outline: -webkit-focus-ring-color auto 5px; + } + } + + .label-icon { + display: inline-block; + min-width: 64px; + text-align: center; + } + + .reorder-card { + width: 65px; + margin-left: 20px; + background-color: $white; + border: 1px solid $gray-400; + border-radius: 4px; + + p { + margin-bottom: 0; + padding-top: 3px; + font-size: 1.40rem; + line-height: 1; + } + + .btn { + padding: 2px 5px; + } + } + + .btn-filter { + .label { + font-size: .90rem; + } + } +} diff --git a/ui/src/app/metadata/manager/component/provider-item.component.ts b/ui/src/app/metadata/manager/component/provider-item.component.ts new file mode 100644 index 000000000..26249d7ab --- /dev/null +++ b/ui/src/app/metadata/manager/component/provider-item.component.ts @@ -0,0 +1,15 @@ +import { Component, Input, ChangeDetectionStrategy } from '@angular/core'; + +import { MetadataProvider } from '../../domain/model'; +import { EntityItemComponent } from './entity-item.component'; + +@Component({ + selector: 'provider-item', + changeDetection: ChangeDetectionStrategy.OnPush, + templateUrl: './provider-item.component.html', + styleUrls: ['./provider-item.component.scss'] +}) + +export class ProviderItemComponent extends EntityItemComponent { + @Input() provider: MetadataProvider; +} diff --git a/ui/src/app/metadata/manager/component/entity-item.component.html b/ui/src/app/metadata/manager/component/resolver-item.component.html similarity index 100% rename from ui/src/app/metadata/manager/component/entity-item.component.html rename to ui/src/app/metadata/manager/component/resolver-item.component.html diff --git a/ui/src/app/metadata/manager/component/entity-item.component.scss b/ui/src/app/metadata/manager/component/resolver-item.component.scss similarity index 100% rename from ui/src/app/metadata/manager/component/entity-item.component.scss rename to ui/src/app/metadata/manager/component/resolver-item.component.scss diff --git a/ui/src/app/metadata/manager/component/resolver-item.component.spec.ts b/ui/src/app/metadata/manager/component/resolver-item.component.spec.ts new file mode 100644 index 000000000..ac0f2bf84 --- /dev/null +++ b/ui/src/app/metadata/manager/component/resolver-item.component.spec.ts @@ -0,0 +1,34 @@ +import { TestBed, ComponentFixture } from '@angular/core/testing'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { EntityItemComponent } from './entity-item.component'; +import { FileBackedHttpMetadataResolver } from '../../domain/entity'; +import { ResolverItemComponent } from './resolver-item.component'; + +describe('Resolver List item', () => { + let fixture: ComponentFixture; + let instance: ResolverItemComponent; + + let resolver = new FileBackedHttpMetadataResolver({ entityId: 'foo', serviceProviderName: 'bar' }); + + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [], + imports: [ + NoopAnimationsModule + ], + declarations: [ + ResolverItemComponent + ], + }); + + fixture = TestBed.createComponent(ResolverItemComponent); + instance = fixture.componentInstance; + instance.entity = resolver; + }); + + it('should compile', () => { + fixture.detectChanges(); + + expect(fixture).toBeDefined(); + }); +}); diff --git a/ui/src/app/metadata/manager/component/resolver-item.component.ts b/ui/src/app/metadata/manager/component/resolver-item.component.ts new file mode 100644 index 000000000..cb2f31adb --- /dev/null +++ b/ui/src/app/metadata/manager/component/resolver-item.component.ts @@ -0,0 +1,14 @@ +import { Component, ChangeDetectionStrategy, Input } from '@angular/core'; + +import { MetadataEntity } from '../../domain/model'; +import { EntityItemComponent } from './entity-item.component'; + +@Component({ + selector: 'resolver-item', + changeDetection: ChangeDetectionStrategy.OnPush, + templateUrl: './resolver-item.component.html', + styleUrls: ['./resolver-item.component.scss'] +}) +export class ResolverItemComponent extends EntityItemComponent { + @Input() entity: MetadataEntity; +} diff --git a/ui/src/app/metadata/manager/container/dashboard-providers-list.component.html b/ui/src/app/metadata/manager/container/dashboard-providers-list.component.html index 5690a336e..dd6319e6c 100644 --- a/ui/src/app/metadata/manager/container/dashboard-providers-list.component.html +++ b/ui/src/app/metadata/manager/container/dashboard-providers-list.component.html @@ -8,13 +8,17 @@ - - - diff --git a/ui/src/app/metadata/manager/container/dashboard-providers-list.component.spec.ts b/ui/src/app/metadata/manager/container/dashboard-providers-list.component.spec.ts new file mode 100644 index 000000000..b185dca02 --- /dev/null +++ b/ui/src/app/metadata/manager/container/dashboard-providers-list.component.spec.ts @@ -0,0 +1,83 @@ +import { TestBed, ComponentFixture } from '@angular/core/testing'; +import { ReactiveFormsModule } from '@angular/forms'; +import { Router } from '@angular/router'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { StoreModule, Store, combineReducers } from '@ngrx/store'; +import { NgbPaginationModule } from '@ng-bootstrap/ng-bootstrap/pagination/pagination.module'; +import { NgbModal, NgbModalModule } from '@ng-bootstrap/ng-bootstrap/modal/modal.module'; +import * as fromDashboard from '../reducer'; +import { ProviderSearchComponent } from '../component/provider-search.component'; +import { DeleteDialogComponent } from '../component/delete-dialog.component'; +import { RouterStub } from '../../../../testing/router.stub'; +import { NgbModalStub } from '../../../../testing/modal.stub'; +import { DashboardProvidersListComponent } from './dashboard-providers-list.component'; +import { MetadataProvider } from '../../domain/model'; +import { ProviderItemComponent } from '../component/provider-item.component'; +import { FileBackedHttpMetadataResolver } from '../../domain/entity'; + + +describe('Dashboard Providers List Page', () => { + let fixture: ComponentFixture; + let store: Store; + let router: Router; + let modal: NgbModal; + let instance: DashboardProvidersListComponent; + + let provider = { + resourceId: 'foo', + name: 'bar' + }; + + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [ + { provide: Router, useClass: RouterStub }, + { provide: NgbModal, useClass: NgbModalStub } + ], + imports: [ + NoopAnimationsModule, + StoreModule.forRoot({ + manager: combineReducers(fromDashboard.reducers), + }), + ReactiveFormsModule, + NgbPaginationModule, + NgbModalModule + ], + declarations: [ + DashboardProvidersListComponent, + ProviderSearchComponent, + ProviderItemComponent, + DeleteDialogComponent + ], + }); + + fixture = TestBed.createComponent(DashboardProvidersListComponent); + instance = fixture.componentInstance; + store = TestBed.get(Store); + router = TestBed.get(Router); + modal = TestBed.get(NgbModal); + + spyOn(store, 'dispatch').and.callThrough(); + }); + + it('should compile', () => { + fixture.detectChanges(); + + expect(fixture).toBeDefined(); + }); + + describe('toggleProvider method', () => { + it('should fire a redux action', () => { + instance.toggleEntity(provider); + expect(store.dispatch).toHaveBeenCalled(); + }); + }); + + describe('edit method', () => { + it('should route to the edit page', () => { + spyOn(router, 'navigate'); + instance.edit(provider); + expect(router.navigate).toHaveBeenCalledWith(['metadata', 'provider', provider.resourceId, 'edit']); + }); + }); +}); diff --git a/ui/src/app/metadata/manager/container/dashboard-providers-list.component.ts b/ui/src/app/metadata/manager/container/dashboard-providers-list.component.ts index fd43e20c6..2cdb60443 100644 --- a/ui/src/app/metadata/manager/container/dashboard-providers-list.component.ts +++ b/ui/src/app/metadata/manager/container/dashboard-providers-list.component.ts @@ -1,8 +1,13 @@ import { Component } from '@angular/core'; +import { Router } from '@angular/router'; import { MetadataProvider } from '../../domain/model'; import { Observable } from '../../../../../node_modules/rxjs'; import { Store } from '@ngrx/store'; + import { ProviderState, getAllProviders } from '../../provider/reducer'; +import * as fromDashboard from '../reducer'; +import { ToggleEntityDisplay } from '../action/manager.action'; +import { Meta } from '../../../../../node_modules/@angular/platform-browser'; @Component({ selector: 'dashboard-providers-list', @@ -12,10 +17,21 @@ import { ProviderState, getAllProviders } from '../../provider/reducer'; export class DashboardProvidersListComponent { providers$: Observable; + providersOpen$: Observable<{ [key: string]: boolean }>; constructor( - private store: Store + private store: Store, + private router: Router ) { this.providers$ = this.store.select(getAllProviders); + this.providersOpen$ = store.select(fromDashboard.getOpenProviders); + } + + edit(provider: MetadataProvider): void { + this.router.navigate(['metadata', 'provider', provider.resourceId, 'edit']); + } + + toggleEntity(provider: MetadataProvider): void { + this.store.dispatch(new ToggleEntityDisplay(provider.resourceId)); } } diff --git a/ui/src/app/metadata/manager/container/dashboard-resolvers-list.component.html b/ui/src/app/metadata/manager/container/dashboard-resolvers-list.component.html index 647b976a0..d771864ca 100644 --- a/ui/src/app/metadata/manager/container/dashboard-resolvers-list.component.html +++ b/ui/src/app/metadata/manager/container/dashboard-resolvers-list.component.html @@ -16,17 +16,17 @@
    -
  • - - + +
diff --git a/ui/src/app/metadata/manager/container/dashboard-resolvers-list.component.spec.ts b/ui/src/app/metadata/manager/container/dashboard-resolvers-list.component.spec.ts index 9a9a8150d..ca8d2b6ff 100644 --- a/ui/src/app/metadata/manager/container/dashboard-resolvers-list.component.spec.ts +++ b/ui/src/app/metadata/manager/container/dashboard-resolvers-list.component.spec.ts @@ -13,6 +13,7 @@ import { RouterStub } from '../../../../testing/router.stub'; import { NgbModalStub } from '../../../../testing/modal.stub'; import { FileBackedHttpMetadataResolver } from '../../domain/entity'; import { DashboardResolversListComponent } from './dashboard-resolvers-list.component'; +import { ResolverItemComponent } from '../component/resolver-item.component'; describe('Dashboard Resolvers List Page', () => { @@ -50,7 +51,7 @@ describe('Dashboard Resolvers List Page', () => { declarations: [ DashboardResolversListComponent, ProviderSearchComponent, - EntityItemComponent, + ResolverItemComponent, DeleteDialogComponent ], }); diff --git a/ui/src/app/metadata/manager/container/manager.component.spec.ts b/ui/src/app/metadata/manager/container/manager.component.spec.ts new file mode 100644 index 000000000..be02fd913 --- /dev/null +++ b/ui/src/app/metadata/manager/container/manager.component.spec.ts @@ -0,0 +1,35 @@ +import { TestBed, ComponentFixture } from '@angular/core/testing'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { ManagerComponent } from './manager.component'; +import { RouterModule, Router } from '@angular/router'; +import { RouterStub, RouterLinkStubDirective, RouterOutletStubComponent } from '../../../../testing/router.stub'; + +describe('Metadata Manager Parent Page', () => { + let fixture: ComponentFixture; + let instance: ManagerComponent; + + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [ + { provide: Router, useClass: RouterStub } + ], + imports: [ + NoopAnimationsModule, + ], + declarations: [ + ManagerComponent, + RouterLinkStubDirective, + RouterOutletStubComponent + ], + }); + + fixture = TestBed.createComponent(ManagerComponent); + instance = fixture.componentInstance; + }); + + it('should compile', () => { + fixture.detectChanges(); + + expect(fixture).toBeDefined(); + }); +}); diff --git a/ui/src/app/metadata/manager/manager.module.ts b/ui/src/app/metadata/manager/manager.module.ts index ed29e36c9..0f00569d1 100644 --- a/ui/src/app/metadata/manager/manager.module.ts +++ b/ui/src/app/metadata/manager/manager.module.ts @@ -9,6 +9,8 @@ import { EffectsModule } from '@ngrx/effects'; import { ManagerComponent } from './container/manager.component'; import { EntityItemComponent } from './component/entity-item.component'; +import { ProviderItemComponent } from './component/provider-item.component'; +import { ResolverItemComponent } from './component/resolver-item.component'; import { ProviderSearchComponent } from './component/provider-search.component'; import { DashboardResolversListComponent } from './container/dashboard-resolvers-list.component'; import { DashboardProvidersListComponent } from './container/dashboard-providers-list.component'; @@ -22,6 +24,8 @@ import { NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap'; declarations: [ ManagerComponent, EntityItemComponent, + ResolverItemComponent, + ProviderItemComponent, ProviderSearchComponent, DeleteDialogComponent, DashboardResolversListComponent, diff --git a/ui/src/app/metadata/provider/reducer/collection.reducer.spec.ts b/ui/src/app/metadata/provider/reducer/collection.reducer.spec.ts index 4204ebe65..700dd5a1e 100644 --- a/ui/src/app/metadata/provider/reducer/collection.reducer.spec.ts +++ b/ui/src/app/metadata/provider/reducer/collection.reducer.spec.ts @@ -26,8 +26,24 @@ describe('Provider Collection Reducer', () => { it('should add the loaded providers to the collection', () => { spyOn(fromProvider.adapter, 'addAll').and.callThrough(); const providers = [ - { resourceId: 'foo', name: 'foo', '@type': 'foo', enabled: true, createdDate: new Date().toLocaleDateString() }, - { resourceId: 'bar', name: 'bar', '@type': 'bar', enabled: false, createdDate: new Date().toLocaleDateString() } + { + resourceId: 'foo', + name: 'name', + '@type': 'foo', + enabled: true, + createdDate: new Date().toLocaleDateString(), + sortKey: 1, + metadataFilters: [] + }, + { + resourceId: 'bar', + name: 'bar', + '@type': 'bar', + enabled: false, + createdDate: new Date().toLocaleDateString(), + sortKey: 2, + metadataFilters: [] + } ]; const action = new LoadProviderSuccess(providers); const result = reducer(snapshot, action);