From 9439153e77aa9b599a564659b41aff7a2b67cac6 Mon Sep 17 00:00:00 2001 From: Richard Cox Date: Fri, 1 Mar 2019 16:52:31 +0000 Subject: [PATCH 01/20] WIP --- .../core/src/core/endpoints.service.ts | 10 +++++++- .../list/list-cards/card/card.component.ts | 8 +++--- ...t.html => cf-endpoint-card.component.html} | 0 ...t.scss => cf-endpoint-card.component.scss} | 0 ....ts => cf-endpoint-card.component.spec.ts} | 10 ++++---- ...onent.ts => cf-endpoint-card.component.ts} | 8 +++--- .../cf-endpoints-list-config.service.ts | 4 +-- .../cf-stacks-list-config.service.ts | 2 +- .../endpoint-card.component.html | 19 ++++++++++++++ .../endpoint-card.component.scss | 6 +++++ .../endpoint-card.component.spec.ts | 25 +++++++++++++++++++ .../endpoint-card/endpoint-card.component.ts | 22 ++++++++++++++++ .../endpoint/endpoints-list-config.service.ts | 7 +++++- .../table-cell-endpoint-name.component.ts | 20 +++++++++------ .../components/list/list.component.spec.ts | 8 +++--- .../packages/core/src/shared/shared.module.ts | 4 ++- 16 files changed, 123 insertions(+), 30 deletions(-) rename src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/{endpoint-card.component.html => cf-endpoint-card.component.html} (100%) rename src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/{endpoint-card.component.scss => cf-endpoint-card.component.scss} (100%) rename src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/{endpoint-card.component.spec.ts => cf-endpoint-card.component.spec.ts} (82%) rename src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/{endpoint-card.component.ts => cf-endpoint-card.component.ts} (87%) create mode 100644 src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.html create mode 100644 src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.scss create mode 100644 src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.spec.ts create mode 100644 src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.ts diff --git a/src/frontend/packages/core/src/core/endpoints.service.ts b/src/frontend/packages/core/src/core/endpoints.service.ts index 9af41000bd..b0b3516e60 100644 --- a/src/frontend/packages/core/src/core/endpoints.service.ts +++ b/src/frontend/packages/core/src/core/endpoints.service.ts @@ -16,6 +16,7 @@ import { UserService } from './user.service'; import { AuthState } from '../../../store/src/reducers/auth.reducer'; import { RouterNav } from '../../../store/src/actions/router.actions'; import { endpointHealthChecks, EndpointHealthCheck } from '../../endpoints-health-checks'; +import { getEndpointTypes } from '../features/endpoints/endpoint-helpers'; @Injectable() @@ -25,6 +26,14 @@ export class EndpointsService implements CanActivate { haveRegistered$: Observable; haveConnected$: Observable; + static getLinkForEndpoint(endpoint: EndpointModel): string { + const ext = getEndpointTypes().find(ep => ep.value === endpoint.cnsi_type); + if (ext && ext.homeLink) { + return ext.homeLink(endpoint.guid).join('/'); + } + return ''; + } + constructor( private store: Store, private userService: UserService @@ -101,5 +110,4 @@ export class EndpointsService implements CanActivate { ); } - } diff --git a/src/frontend/packages/core/src/shared/components/list/list-cards/card/card.component.ts b/src/frontend/packages/core/src/shared/components/list/list-cards/card/card.component.ts index 4d2071fa2a..3065cf4cd1 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-cards/card/card.component.ts +++ b/src/frontend/packages/core/src/shared/components/list/list-cards/card/card.component.ts @@ -15,7 +15,7 @@ import { IListDataSource } from '../../data-sources-controllers/list-data-source import { CardCell } from '../../list.types'; import { CardAppComponent } from '../../list-types/app/card/card-app.component'; -import { EndpointCardComponent } from '../../list-types/cf-endpoints/cf-endpoint-card/endpoint-card.component'; +import { CfEndpointCardComponent } from '../../list-types/cf-endpoints/cf-endpoint-card/cf-endpoint-card.component'; import { CfOrgCardComponent } from '../../list-types/cf-orgs/cf-org-card/cf-org-card.component'; import { CfSpaceCardComponent } from '../../list-types/cf-spaces/cf-space-card/cf-space-card.component'; import { CfBuildpackCardComponent } from '../../list-types/cf-buildpacks/cf-buildpack-card/cf-buildpack-card.component'; @@ -28,10 +28,11 @@ import { AppServiceBindingCardComponent } from '../../list-types/app-sevice-bindings/app-service-binding-card/app-service-binding-card.component'; import { ServiceInstanceCardComponent } from '../../list-types/services-wall/service-instance-card/service-instance-card.component'; +import { EndpointCardComponent } from '../../list-types/endpoint/endpoint-card/endpoint-card.component'; export const listCards = [ CardAppComponent, - EndpointCardComponent, + CfEndpointCardComponent, CfOrgCardComponent, CfSpaceCardComponent, CfBuildpackCardComponent, @@ -39,7 +40,8 @@ export const listCards = [ CfStacksCardComponent, CfServiceCardComponent, AppServiceBindingCardComponent, - ServiceInstanceCardComponent + ServiceInstanceCardComponent, + EndpointCardComponent ]; @Component({ selector: 'app-card', diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/endpoint-card.component.html b/src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/cf-endpoint-card.component.html similarity index 100% rename from src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/endpoint-card.component.html rename to src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/cf-endpoint-card.component.html diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/endpoint-card.component.scss b/src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/cf-endpoint-card.component.scss similarity index 100% rename from src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/endpoint-card.component.scss rename to src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/cf-endpoint-card.component.scss diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/endpoint-card.component.spec.ts b/src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/cf-endpoint-card.component.spec.ts similarity index 82% rename from src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/endpoint-card.component.spec.ts rename to src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/cf-endpoint-card.component.spec.ts index 3b7851addf..b2a9ba4397 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/endpoint-card.component.spec.ts +++ b/src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/cf-endpoint-card.component.spec.ts @@ -6,11 +6,11 @@ import { EntityMonitorFactory } from '../../../../../monitors/entity-monitor.fac import { createBasicStoreModule } from '../../../../../../../test-framework/store-test-helper'; import { BaseTestModules } from '../../../../../../../test-framework/cloud-foundry-endpoint-service.helper'; import { ServiceActionHelperService } from '../../../../../data-services/service-action-helper.service'; -import { EndpointCardComponent } from './endpoint-card.component'; +import { CfEndpointCardComponent } from './cf-endpoint-card.component'; -describe('EndpointCardComponent', () => { - let component: EndpointCardComponent; - let fixture: ComponentFixture; +describe('CfEndpointCardComponent', () => { + let component: CfEndpointCardComponent; + let fixture: ComponentFixture; beforeEach(async(() => { TestBed.configureTestingModule({ @@ -29,7 +29,7 @@ describe('EndpointCardComponent', () => { })); beforeEach(() => { - fixture = TestBed.createComponent(EndpointCardComponent); + fixture = TestBed.createComponent(CfEndpointCardComponent); component = fixture.componentInstance; component.row = { name: 'test', diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/endpoint-card.component.ts b/src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/cf-endpoint-card.component.ts similarity index 87% rename from src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/endpoint-card.component.ts rename to src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/cf-endpoint-card.component.ts index e227b35d2a..251817764e 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/endpoint-card.component.ts +++ b/src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/cf-endpoint-card.component.ts @@ -10,11 +10,11 @@ import { CardCell } from '../../../list.types'; @Component({ - selector: 'app-endpoint-card', - templateUrl: './endpoint-card.component.html', - styleUrls: ['./endpoint-card.component.scss'] + selector: 'app-cf-endpoint-card', + templateUrl: './cf-endpoint-card.component.html', + styleUrls: ['./cf-endpoint-card.component.scss'] }) -export class EndpointCardComponent extends CardCell implements OnInit, OnChanges { +export class CfEndpointCardComponent extends CardCell implements OnInit, OnChanges { static columns = 2; diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/cf-endpoints-list-config.service.ts b/src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/cf-endpoints-list-config.service.ts index 71caa96f1b..d502af23e4 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/cf-endpoints-list-config.service.ts +++ b/src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/cf-endpoints-list-config.service.ts @@ -12,7 +12,7 @@ import { AppState } from '../../../../../../../store/src/app-state'; import { BaseEndpointsDataSource } from './base-endpoints-data-source'; -import { EndpointCardComponent } from './cf-endpoint-card/endpoint-card.component'; +import { CfEndpointCardComponent } from './cf-endpoint-card/cf-endpoint-card.component'; @Injectable() export class CFEndpointsListConfigService implements IListConfig { @@ -20,7 +20,7 @@ export class CFEndpointsListConfigService implements IListConfig isLocal = true; dataSource: BaseEndpointsDataSource; viewType = ListViewTypes.CARD_ONLY; - cardComponent = EndpointCardComponent; + cardComponent = CfEndpointCardComponent; text = { title: '', filter: 'Filter Endpoints', diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/cf-stacks/cf-stacks-list-config.service.ts b/src/frontend/packages/core/src/shared/components/list/list-types/cf-stacks/cf-stacks-list-config.service.ts index 0120d6cba0..15acc02ddf 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/cf-stacks/cf-stacks-list-config.service.ts +++ b/src/frontend/packages/core/src/shared/components/list/list-types/cf-stacks/cf-stacks-list-config.service.ts @@ -36,7 +36,7 @@ export class CfStacksListConfigService extends BaseCfListConfig { }, }]; - constructor(private store: Store, private activeRouteCfOrgSpace: ActiveRouteCfOrgSpace) { + constructor(private store: Store, activeRouteCfOrgSpace: ActiveRouteCfOrgSpace) { super(); this.dataSource = new CfStacksDataSource(this.store, activeRouteCfOrgSpace.cfGuid, this); } diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.html b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.html new file mode 100644 index 0000000000..8616ea8311 --- /dev/null +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.html @@ -0,0 +1,19 @@ + + + + {{ row.name }} + // TODO: RC fav + + + Status + + + + Type + + + + Address + + + \ No newline at end of file diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.scss b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.scss new file mode 100644 index 0000000000..ce7d1d2449 --- /dev/null +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.scss @@ -0,0 +1,6 @@ +.endpoint-card { + cursor: pointer; + &:focus { + outline: 0; + } +} diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.spec.ts b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.spec.ts new file mode 100644 index 0000000000..0a561e4625 --- /dev/null +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { EndpointCardComponent } from './endpoint-card.component'; + +describe('EndpointCardComponent', () => { + let component: EndpointCardComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ EndpointCardComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(EndpointCardComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.ts b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.ts new file mode 100644 index 0000000000..70ed0cf6a7 --- /dev/null +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.ts @@ -0,0 +1,22 @@ +import { Component, OnInit } from '@angular/core'; +import { CardCell } from '../../../list.types'; +import { EndpointModel } from '../../../../../../../../store/src/types/endpoint.types'; +import { EndpointsService } from '../../../../../../core/endpoints.service'; + +@Component({ + selector: 'app-endpoint-card', + templateUrl: './endpoint-card.component.html', + styleUrls: ['./endpoint-card.component.scss'] +}) +export class EndpointCardComponent extends CardCell { + + constructor() { + super(); + } + + // ngOnInit() { + // } + getLinkForEndpoint() { + return EndpointsService.getLinkForEndpoint(this.row); + } +} diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoints-list-config.service.ts b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoints-list-config.service.ts index d78dfb64a7..212ad1e91b 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoints-list-config.service.ts +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoints-list-config.service.ts @@ -34,6 +34,8 @@ import { EndpointsDataSource } from './endpoints-data-source'; import { TableCellEndpointIsAdminComponent } from './table-cell-endpoint-is-admin/table-cell-endpoint-is-admin.component'; import { TableCellEndpointNameComponent } from './table-cell-endpoint-name/table-cell-endpoint-name.component'; import { TableCellEndpointStatusComponent } from './table-cell-endpoint-status/table-cell-endpoint-status.component'; +import { EndpointCardComponent } from './endpoint-card/endpoint-card.component'; +import { ListView } from '../../../../../../../store/src/actions/list.actions'; function getEndpointTypeString(endpoint: EndpointModel): string { return getNameForEndpointType(endpoint.cnsi_type); @@ -116,6 +118,8 @@ export const endpointColumns: ITableColumn[] = [ @Injectable() export class EndpointsListConfigService implements IListConfig { + cardComponent = EndpointCardComponent; + private listActionDelete: IListAction = { action: (item) => { const confirmation = new ConfirmationDialogConfig( @@ -195,7 +199,8 @@ export class EndpointsListConfigService implements IListConfig { ]; isLocal = true; dataSource: EndpointsDataSource; - viewType = ListViewTypes.TABLE_ONLY; + viewType = ListViewTypes.BOTH; + defaultView = 'cards' as ListView; text = { title: '', filter: 'Filter Endpoints' diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-name/table-cell-endpoint-name.component.ts b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-name/table-cell-endpoint-name.component.ts index f81ab00962..8d9297f968 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-name/table-cell-endpoint-name.component.ts +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-name/table-cell-endpoint-name.component.ts @@ -1,20 +1,24 @@ -import { Component } from '@angular/core'; +import { Component, Input } from '@angular/core'; import { TableCellCustom } from '../../../list.types'; import { getEndpointTypes } from '../../../../../../features/endpoints/endpoint-helpers'; +import { EndpointModel } from '../../../../../../../../store/src/types/endpoint.types'; +import { EndpointsService } from '../../../../../../core/endpoints.service'; @Component({ selector: 'app-table-cell-endpoint-name', templateUrl: './table-cell-endpoint-name.component.html', styleUrls: ['./table-cell-endpoint-name.component.scss'] }) -export class TableCellEndpointNameComponent extends TableCellCustom { +export class TableCellEndpointNameComponent extends TableCellCustom { - getLinkForEndpoint(row) { - const ext = getEndpointTypes().find(ep => ep.value === row.cnsi_type); - if (ext && ext.homeLink) { - return ext.homeLink(row.guid).join('/'); - } - return ''; + private _row: EndpointModel; + @Input('row') + set row(row: EndpointModel) { + this._row = row; + } + + getLinkForEndpoint(row = this._row) { + return EndpointsService.getLinkForEndpoint(row); } } diff --git a/src/frontend/packages/core/src/shared/components/list/list.component.spec.ts b/src/frontend/packages/core/src/shared/components/list/list.component.spec.ts index 79f5c519b1..1ca6a21d49 100644 --- a/src/frontend/packages/core/src/shared/components/list/list.component.spec.ts +++ b/src/frontend/packages/core/src/shared/components/list/list.component.spec.ts @@ -11,7 +11,7 @@ import { EntityMonitorFactory } from '../../monitors/entity-monitor.factory.serv import { PaginationMonitorFactory } from '../../monitors/pagination-monitor.factory'; import { SharedModule } from '../../shared.module'; import { ApplicationStateService } from '../application-state/application-state.service'; -import { EndpointCardComponent } from './list-types/cf-endpoints/cf-endpoint-card/endpoint-card.component'; +import { CfEndpointCardComponent } from './list-types/cf-endpoints/cf-endpoint-card/cf-endpoint-card.component'; import { EndpointsListConfigService } from './list-types/endpoint/endpoints-list-config.service'; import { ListComponent } from './list.component'; import { ListConfig, ListViewTypes } from './list.component.types'; @@ -149,7 +149,7 @@ describe('ListComponent', () => { component.config.enableTextFilter = false; component.config.viewType = ListViewTypes.CARD_ONLY; component.config.defaultView = 'card' as ListView; - component.config.cardComponent = EndpointCardComponent; + component.config.cardComponent = CfEndpointCardComponent; component.config.text.title = null; const columns = component.config.getColumns(); columns.forEach(column => column.sort = false); @@ -206,7 +206,7 @@ describe('ListComponent', () => { component.config.enableTextFilter = true; component.config.viewType = ListViewTypes.CARD_ONLY; component.config.defaultView = 'card' as ListView; - component.config.cardComponent = EndpointCardComponent; + component.config.cardComponent = CfEndpointCardComponent; component.config.getColumns = () => [ { columnId: 'filterTestKey', @@ -258,7 +258,7 @@ describe('ListComponent', () => { component.config.enableTextFilter = true; component.config.viewType = ListViewTypes.CARD_ONLY; component.config.defaultView = 'card' as ListView; - component.config.cardComponent = EndpointCardComponent; + component.config.cardComponent = CfEndpointCardComponent; component.config.getColumns = () => [ { columnId: 'filterTestKey', diff --git a/src/frontend/packages/core/src/shared/shared.module.ts b/src/frontend/packages/core/src/shared/shared.module.ts index b050afab19..ddc70555b7 100644 --- a/src/frontend/packages/core/src/shared/shared.module.ts +++ b/src/frontend/packages/core/src/shared/shared.module.ts @@ -149,6 +149,7 @@ import { UsageBytesPipe } from './pipes/usage-bytes.pipe'; import { ValuesPipe } from './pipes/values.pipe'; import { MetricsRangeSelectorService } from './services/metrics-range-selector.service'; import { UserPermissionDirective } from './user-permission.directive'; +import { EndpointCardComponent } from './components/list/list-types/endpoint/endpoint-card/endpoint-card.component'; @NgModule({ @@ -264,7 +265,8 @@ import { UserPermissionDirective } from './user-permission.directive'; FavoritesGlobalListComponent, FavoritesMetaCardComponent, FavoritesEntityListComponent, - MultilineTitleComponent + MultilineTitleComponent, + EndpointCardComponent ], exports: [ FormsModule, From db6fc077c23c6af95531af13548c5e6a1a703e2c Mon Sep 17 00:00:00 2001 From: Richard Cox Date: Fri, 1 Mar 2019 17:29:04 +0000 Subject: [PATCH 02/20] WIP --- .../core/src/core/endpoints.service.ts | 3 + .../endpoint-card.component.html | 17 ++--- .../endpoint-card/endpoint-card.component.ts | 66 +++++++++++++++++-- ...able-cell-endpoint-is-admin.component.html | 2 +- .../table-cell-endpoint-name.component.html | 6 +- 5 files changed, 74 insertions(+), 20 deletions(-) diff --git a/src/frontend/packages/core/src/core/endpoints.service.ts b/src/frontend/packages/core/src/core/endpoints.service.ts index b0b3516e60..eae3d2ec5e 100644 --- a/src/frontend/packages/core/src/core/endpoints.service.ts +++ b/src/frontend/packages/core/src/core/endpoints.service.ts @@ -27,6 +27,9 @@ export class EndpointsService implements CanActivate { haveConnected$: Observable; static getLinkForEndpoint(endpoint: EndpointModel): string { + if (!endpoint) { + return ''; + } const ext = getEndpointTypes().find(ep => ep.value === endpoint.cnsi_type); if (ext && ext.homeLink) { return ext.homeLink(endpoint.guid).join('/'); diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.html b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.html index 8616ea8311..538abfbc13 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.html +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.html @@ -1,19 +1,14 @@ - - + - {{ row.name }} - // TODO: RC fav + {{ row?.name }} - - Status - - Type - + {{ type }} Address - + {{ address }} - \ No newline at end of file + +// TODO: RC actions \ No newline at end of file diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.ts b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.ts index 70ed0cf6a7..6356bcd1b1 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.ts +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.ts @@ -1,22 +1,78 @@ -import { Component, OnInit } from '@angular/core'; -import { CardCell } from '../../../list.types'; +import { Component, Input, OnInit } from '@angular/core'; +import { ReplaySubject, of as observableOf } from 'rxjs'; import { EndpointModel } from '../../../../../../../../store/src/types/endpoint.types'; import { EndpointsService } from '../../../../../../core/endpoints.service'; +import { CardStatus } from '../../../../../shared.types'; +import { CardCell } from '../../../list.types'; +import { UserFavoriteEndpoint } from '../../../../../../../../store/src/types/user-favorites.types'; +import { getFavoriteFromEndpointEntity } from '../../../../../../core/user-favorite-helpers'; +import { getNameForEndpointType, getFullEndpointApiUrl } from '../../../../../../features/endpoints/endpoint-helpers'; +import { MetaCardMenuItem } from '../../../list-cards/meta-card/meta-card-base/meta-card.component'; @Component({ selector: 'app-endpoint-card', templateUrl: './endpoint-card.component.html', styleUrls: ['./endpoint-card.component.scss'] }) -export class EndpointCardComponent extends CardCell { +export class EndpointCardComponent extends CardCell implements OnInit { + + public status$ = new ReplaySubject(); + public favorite: UserFavoriteEndpoint; + public type: string; + public address: string; + public cardMenu: MetaCardMenuItem[]; + + private pRow: EndpointModel; + @Input('row') + set row(row: EndpointModel) { + this.pRow = row; + this.type = row ? getNameForEndpointType(row.cnsi_type) : ''; + this.address = row ? getFullEndpointApiUrl(row) : ''; + this.status$.next(this.determineEndpointStatus(row)); + } + get row(): EndpointModel { + return this.pRow; + } constructor() { super(); + this.cardMenu = [ + { + label: 'Delete', + action: null, + can: observableOf(true) + }, + { + label: 'Connect', + action: null, + can: observableOf(true) + }, + { + label: 'Disconnect', + action: null, + can: observableOf(true) + } + ]; + } + + ngOnInit() { + this.favorite = getFavoriteFromEndpointEntity(this.row); } - // ngOnInit() { - // } getLinkForEndpoint() { return EndpointsService.getLinkForEndpoint(this.row); } + + determineEndpointStatus(row: EndpointModel): CardStatus { + switch (row.connectionStatus) { + case 'connected': + return CardStatus.OK; + case 'disconnected': + return CardStatus.TENTATIVE; + case 'checking': + return CardStatus.BUSY; + default: + return CardStatus.INCOMPLETE; + } + } } diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-is-admin/table-cell-endpoint-is-admin.component.html b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-is-admin/table-cell-endpoint-is-admin.component.html index 6de3185e88..781b48907b 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-is-admin/table-cell-endpoint-is-admin.component.html +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-is-admin/table-cell-endpoint-is-admin.component.html @@ -1,3 +1,3 @@ - + - \ No newline at end of file diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-name/table-cell-endpoint-name.component.html b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-name/table-cell-endpoint-name.component.html index 7bac8d5932..5dfcc28a93 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-name/table-cell-endpoint-name.component.html +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-name/table-cell-endpoint-name.component.html @@ -1,5 +1,5 @@
- {{ row.name }} - {{ row.name }} - share + {{ row.name }} + {{ row.name }} + share
\ No newline at end of file From ff9a923191823460f13ce3d1765078735d8515fd Mon Sep 17 00:00:00 2001 From: Richard Cox Date: Tue, 5 Mar 2019 13:57:26 +0000 Subject: [PATCH 03/20] Actions --- .../cloud-foundry/cloud-foundry.module.ts | 4 +- .../endpoints-page.component.ts | 25 ++-- .../endpoint-card.component.html | 6 +- .../endpoint-card/endpoint-card.component.ts | 56 ++++---- .../endpoint/endpoint-list.helpers.ts | 128 ++++++++++++++++++ .../endpoint/endpoints-list-config.service.ts | 126 +---------------- 6 files changed, 181 insertions(+), 164 deletions(-) create mode 100644 src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-list.helpers.ts diff --git a/src/frontend/packages/core/src/features/cloud-foundry/cloud-foundry.module.ts b/src/frontend/packages/core/src/features/cloud-foundry/cloud-foundry.module.ts index da0a0d0416..5ac649661b 100644 --- a/src/frontend/packages/core/src/features/cloud-foundry/cloud-foundry.module.ts +++ b/src/frontend/packages/core/src/features/cloud-foundry/cloud-foundry.module.ts @@ -8,6 +8,7 @@ import { CustomImportModule } from '../../custom-import.module'; import { CFEndpointsListConfigService, } from '../../shared/components/list/list-types/cf-endpoints/cf-endpoints-list-config.service'; +import { EndpointListHelper } from '../../shared/components/list/list-types/endpoint/endpoint-list.helpers'; import { EndpointsListConfigService } from '../../shared/components/list/list-types/endpoint/endpoints-list-config.service'; import { SharedModule } from '../../shared/shared.module'; import { AddOrganizationComponent } from './add-organization/add-organization.component'; @@ -162,6 +163,7 @@ import { UsersRolesComponent } from './users/manage-users/manage-users.component CfAdminAddUserWarningComponent, ], providers: [ + EndpointListHelper, CFEndpointsListConfigService, EndpointsListConfigService, { @@ -176,7 +178,7 @@ import { UsersRolesComponent } from './users/manage-users/manage-users.component CloudFoundryEndpointService, CfRolesService, CloudFoundryCellService, - UserInviteService, + UserInviteService ], entryComponents: [ UserInviteConfigurationDialogComponent diff --git a/src/frontend/packages/core/src/features/endpoints/endpoints-page/endpoints-page.component.ts b/src/frontend/packages/core/src/features/endpoints/endpoints-page/endpoints-page.component.ts index de54b5231a..a119ff80e5 100644 --- a/src/frontend/packages/core/src/features/endpoints/endpoints-page/endpoints-page.component.ts +++ b/src/frontend/packages/core/src/features/endpoints/endpoints-page/endpoints-page.component.ts @@ -1,18 +1,23 @@ -import { Component, OnDestroy, OnInit, NgZone } from '@angular/core'; +import { Component, NgZone, OnDestroy, OnInit } from '@angular/core'; +import { Store } from '@ngrx/store'; +import { Subscription } from 'rxjs'; +import { delay, filter, first, map } from 'rxjs/operators'; +import { ShowSnackBar } from '../../../../../store/src/actions/snackBar.actions'; +import { AppState } from '../../../../../store/src/app-state'; +import { queryParamMap } from '../../../core/auth-guard.service'; +import { CurrentUserPermissions } from '../../../core/current-user-permissions.config'; import { EndpointsService } from '../../../core/endpoints.service'; +import { + getActionsFromExtensions, + StratosActionMetadata, + StratosActionType, +} from '../../../core/extension/extension-service'; +import { EndpointListHelper } from '../../../shared/components/list/list-types/endpoint/endpoint-list.helpers'; import { EndpointsListConfigService, } from '../../../shared/components/list/list-types/endpoint/endpoints-list-config.service'; import { ListConfig } from '../../../shared/components/list/list.component.types'; -import { CurrentUserPermissions } from '../../../core/current-user-permissions.config'; -import { Subscription, } from 'rxjs'; -import { queryParamMap } from '../../../core/auth-guard.service'; -import { delay, first, map, filter } from 'rxjs/operators'; -import { Store } from '@ngrx/store'; -import { StratosActionType, getActionsFromExtensions, StratosActionMetadata } from '../../../core/extension/extension-service'; -import { AppState } from '../../../../../store/src/app-state'; -import { ShowSnackBar } from '../../../../../store/src/actions/snackBar.actions'; @Component({ selector: 'app-endpoints-page', @@ -21,7 +26,7 @@ import { ShowSnackBar } from '../../../../../store/src/actions/snackBar.actions' providers: [{ provide: ListConfig, useClass: EndpointsListConfigService, - }] + }, EndpointListHelper] }) export class EndpointsPageComponent implements OnDestroy, OnInit { diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.html b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.html index 538abfbc13..cc8b120c26 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.html +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.html @@ -1,4 +1,5 @@ - + {{ row?.name }} @@ -10,5 +11,4 @@ Address {{ address }} - -// TODO: RC actions \ No newline at end of file + \ No newline at end of file diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.ts b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.ts index 6356bcd1b1..0dcc487906 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.ts +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.ts @@ -1,13 +1,15 @@ import { Component, Input, OnInit } from '@angular/core'; -import { ReplaySubject, of as observableOf } from 'rxjs'; +import { ReplaySubject } from 'rxjs'; + import { EndpointModel } from '../../../../../../../../store/src/types/endpoint.types'; -import { EndpointsService } from '../../../../../../core/endpoints.service'; -import { CardStatus } from '../../../../../shared.types'; -import { CardCell } from '../../../list.types'; import { UserFavoriteEndpoint } from '../../../../../../../../store/src/types/user-favorites.types'; +import { EndpointsService } from '../../../../../../core/endpoints.service'; import { getFavoriteFromEndpointEntity } from '../../../../../../core/user-favorite-helpers'; -import { getNameForEndpointType, getFullEndpointApiUrl } from '../../../../../../features/endpoints/endpoint-helpers'; +import { getFullEndpointApiUrl, getNameForEndpointType } from '../../../../../../features/endpoints/endpoint-helpers'; +import { CardStatus } from '../../../../../shared.types'; import { MetaCardMenuItem } from '../../../list-cards/meta-card/meta-card-base/meta-card.component'; +import { CardCell } from '../../../list.types'; +import { EndpointListHelper } from '../endpoint-list.helpers'; @Component({ selector: 'app-endpoint-card', @@ -17,8 +19,9 @@ import { MetaCardMenuItem } from '../../../list-cards/meta-card/meta-card-base/m export class EndpointCardComponent extends CardCell implements OnInit { public status$ = new ReplaySubject(); + public rowObs = new ReplaySubject(); public favorite: UserFavoriteEndpoint; - public type: string; + public type: string; public address: string; public cardMenu: MetaCardMenuItem[]; @@ -29,35 +32,26 @@ export class EndpointCardComponent extends CardCell implements On this.type = row ? getNameForEndpointType(row.cnsi_type) : ''; this.address = row ? getFullEndpointApiUrl(row) : ''; this.status$.next(this.determineEndpointStatus(row)); + this.rowObs.next(row); } get row(): EndpointModel { return this.pRow; } - constructor() { + constructor( + endpointListHelper: EndpointListHelper + ) { super(); - this.cardMenu = [ - { - label: 'Delete', - action: null, - can: observableOf(true) - }, - { - label: 'Connect', - action: null, - can: observableOf(true) - }, - { - label: 'Disconnect', - action: null, - can: observableOf(true) - } - ]; - } + this.cardMenu = endpointListHelper.endpointActions().map(endpointAction => ({ + label: endpointAction.label, + action: () => endpointAction.action(this.pRow), + can: endpointAction.createVisible(this.rowObs) + })); + } - ngOnInit() { + ngOnInit() { this.favorite = getFavoriteFromEndpointEntity(this.row); - } + } getLinkForEndpoint() { return EndpointsService.getLinkForEndpoint(this.row); @@ -66,13 +60,13 @@ export class EndpointCardComponent extends CardCell implements On determineEndpointStatus(row: EndpointModel): CardStatus { switch (row.connectionStatus) { case 'connected': - return CardStatus.OK; + return CardStatus.OK; case 'disconnected': - return CardStatus.TENTATIVE; + return CardStatus.TENTATIVE; case 'checking': - return CardStatus.BUSY; + return CardStatus.BUSY; default: - return CardStatus.INCOMPLETE; + return CardStatus.INCOMPLETE; } } } diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-list.helpers.ts b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-list.helpers.ts new file mode 100644 index 0000000000..81dd321453 --- /dev/null +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-list.helpers.ts @@ -0,0 +1,128 @@ +import { Injectable } from '@angular/core'; +import { MatDialog } from '@angular/material'; +import { Store } from '@ngrx/store'; +import { combineLatest, Observable } from 'rxjs'; +import { map, pairwise } from 'rxjs/operators'; + +import { DisconnectEndpoint, UnregisterEndpoint } from '../../../../../../../store/src/actions/endpoint.actions'; +import { ShowSnackBar } from '../../../../../../../store/src/actions/snackBar.actions'; +import { GetSystemInfo } from '../../../../../../../store/src/actions/system.actions'; +import { AppState } from '../../../../../../../store/src/app-state'; +import { EndpointsEffect } from '../../../../../../../store/src/effects/endpoint.effects'; +import { selectDeletionInfo, selectUpdateInfo } from '../../../../../../../store/src/selectors/api.selectors'; +import { EndpointModel, endpointStoreNames } from '../../../../../../../store/src/types/endpoint.types'; +import { CurrentUserPermissions } from '../../../../../core/current-user-permissions.config'; +import { CurrentUserPermissionsService } from '../../../../../core/current-user-permissions.service'; +import { + ConnectEndpointDialogComponent, +} from '../../../../../features/endpoints/connect-endpoint-dialog/connect-endpoint-dialog.component'; +import { ConfirmationDialogConfig } from '../../../confirmation-dialog.config'; +import { ConfirmationDialogService } from '../../../confirmation-dialog.service'; +import { IListAction } from '../../list.component.types'; + +@Injectable() +export class EndpointListHelper { + + constructor( + private store: Store, + private dialog: MatDialog, + private currentUserPermissionsService: CurrentUserPermissionsService, + private confirmDialog: ConfirmationDialogService) { + + } + + endpointActions(): IListAction[] { + return [ + { + action: (item) => { + const confirmation = new ConfirmationDialogConfig( + 'Unregister Endpoint', + `Are you sure you want to unregister endpoint '${item.name}'?`, + 'Unregister', + true + ); + this.confirmDialog.open(confirmation, () => { + this.store.dispatch(new UnregisterEndpoint(item.guid, item.cnsi_type)); + this.handleDeleteAction(item, ([oldVal, newVal]) => { + this.store.dispatch(new ShowSnackBar(`Unregistered ${item.name}`)); + }); + }); + }, + label: 'Unregister', + description: 'Remove the endpoint', + createVisible: () => this.currentUserPermissionsService.can(CurrentUserPermissions.ENDPOINT_REGISTER) + }, + { + action: (item) => { + const confirmation = new ConfirmationDialogConfig( + 'Disconnect Endpoint', + `Are you sure you want to disconnect endpoint '${item.name}'?`, + 'Disconnect', + false + ); + this.confirmDialog.open(confirmation, () => { + this.store.dispatch(new DisconnectEndpoint(item.guid, item.cnsi_type)); + this.handleUpdateAction(item, EndpointsEffect.disconnectingKey, ([oldVal, newVal]) => { + this.store.dispatch(new ShowSnackBar(`Disconnected endpoint '${item.name}'`)); + this.store.dispatch(new GetSystemInfo()); + }); + }); + }, + label: 'Disconnect', + description: ``, // Description depends on console user permission + createVisible: (row$: Observable) => combineLatest( + this.currentUserPermissionsService.can(CurrentUserPermissions.ENDPOINT_REGISTER), + row$ + ).pipe( + map(([isAdmin, row]) => { + const isConnected = row.connectionStatus === 'connected'; + return isConnected && (!row.system_shared_token || row.system_shared_token && isAdmin); + }) + ) + }, + { + action: (item) => { + this.dialog.open(ConnectEndpointDialogComponent, { + data: { + name: item.name, + guid: item.guid, + type: item.cnsi_type, + ssoAllowed: item.sso_allowed + }, + disableClose: true + }); + }, + label: 'Connect', + description: '', + createVisible: (row$: Observable) => row$.pipe(map(row => row.connectionStatus === 'disconnected')) + } + ]; + } + + private handleUpdateAction(item, effectKey, handleChange) { + this.handleAction(selectUpdateInfo( + endpointStoreNames.type, + item.guid, + effectKey, + ), handleChange); + } + + private handleDeleteAction(item, handleChange) { + this.handleAction(selectDeletionInfo( + endpointStoreNames.type, + item.guid, + ), handleChange); + } + + private handleAction(storeSelect, handleChange) { + const disSub = this.store.select(storeSelect).pipe( + pairwise()) + .subscribe(([oldVal, newVal]) => { + // https://github.com/SUSE/stratos/issues/29 Generic way to handle errors ('Failed to disconnect X') + if (!newVal.error && (oldVal.busy && !newVal.busy)) { + handleChange([oldVal, newVal]); + disSub.unsubscribe(); + } + }); + } +} diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoints-list-config.service.ts b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoints-list-config.service.ts index 212ad1e91b..c78d164e5b 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoints-list-config.service.ts +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoints-list-config.service.ts @@ -1,22 +1,10 @@ import { Injectable } from '@angular/core'; -import { MatDialog } from '@angular/material'; import { Store } from '@ngrx/store'; -import { combineLatest, Observable } from 'rxjs'; -import { map, pairwise } from 'rxjs/operators'; -import { DisconnectEndpoint, UnregisterEndpoint } from '../../../../../../../store/src/actions/endpoint.actions'; -import { ShowSnackBar } from '../../../../../../../store/src/actions/snackBar.actions'; -import { GetSystemInfo } from '../../../../../../../store/src/actions/system.actions'; +import { ListView } from '../../../../../../../store/src/actions/list.actions'; import { AppState } from '../../../../../../../store/src/app-state'; -import { EndpointsEffect } from '../../../../../../../store/src/effects/endpoint.effects'; -import { selectDeletionInfo, selectUpdateInfo } from '../../../../../../../store/src/selectors/api.selectors'; -import { EndpointModel, endpointStoreNames } from '../../../../../../../store/src/types/endpoint.types'; +import { EndpointModel } from '../../../../../../../store/src/types/endpoint.types'; import { UserFavoriteEndpoint } from '../../../../../../../store/src/types/user-favorites.types'; -import { CurrentUserPermissions } from '../../../../../core/current-user-permissions.config'; -import { CurrentUserPermissionsService } from '../../../../../core/current-user-permissions.service'; -import { - ConnectEndpointDialogComponent, -} from '../../../../../features/endpoints/connect-endpoint-dialog/connect-endpoint-dialog.component'; import { getEndpointUsername, getFullEndpointApiUrl, @@ -25,17 +13,15 @@ import { import { EntityMonitorFactory } from '../../../../monitors/entity-monitor.factory.service'; import { InternalEventMonitorFactory } from '../../../../monitors/internal-event-monitor.factory'; import { PaginationMonitorFactory } from '../../../../monitors/pagination-monitor.factory'; -import { ConfirmationDialogConfig } from '../../../confirmation-dialog.config'; -import { ConfirmationDialogService } from '../../../confirmation-dialog.service'; import { createTableColumnFavorite } from '../../list-table/table-cell-favorite/table-cell-favorite.component'; import { ITableColumn } from '../../list-table/table.types'; import { IListAction, IListConfig, ListViewTypes } from '../../list.component.types'; +import { EndpointCardComponent } from './endpoint-card/endpoint-card.component'; +import { EndpointListHelper } from './endpoint-list.helpers'; import { EndpointsDataSource } from './endpoints-data-source'; import { TableCellEndpointIsAdminComponent } from './table-cell-endpoint-is-admin/table-cell-endpoint-is-admin.component'; import { TableCellEndpointNameComponent } from './table-cell-endpoint-name/table-cell-endpoint-name.component'; import { TableCellEndpointStatusComponent } from './table-cell-endpoint-status/table-cell-endpoint-status.component'; -import { EndpointCardComponent } from './endpoint-card/endpoint-card.component'; -import { ListView } from '../../../../../../../store/src/actions/list.actions'; function getEndpointTypeString(endpoint: EndpointModel): string { return getNameForEndpointType(endpoint.cnsi_type); @@ -120,77 +106,7 @@ export const endpointColumns: ITableColumn[] = [ export class EndpointsListConfigService implements IListConfig { cardComponent = EndpointCardComponent; - private listActionDelete: IListAction = { - action: (item) => { - const confirmation = new ConfirmationDialogConfig( - 'Unregister Endpoint', - `Are you sure you want to unregister endpoint '${item.name}'?`, - 'Unregister', - true - ); - this.confirmDialog.open(confirmation, () => { - this.store.dispatch(new UnregisterEndpoint(item.guid, item.cnsi_type)); - this.handleDeleteAction(item, ([oldVal, newVal]) => { - this.store.dispatch(new ShowSnackBar(`Unregistered ${item.name}`)); - }); - }); - }, - label: 'Unregister', - description: 'Remove the endpoint', - createVisible: () => this.currentUserPermissionsService.can(CurrentUserPermissions.ENDPOINT_REGISTER) - }; - - private listActionDisconnect: IListAction = { - action: (item) => { - const confirmation = new ConfirmationDialogConfig( - 'Disconnect Endpoint', - `Are you sure you want to disconnect endpoint '${item.name}'?`, - 'Disconnect', - false - ); - this.confirmDialog.open(confirmation, () => { - this.store.dispatch(new DisconnectEndpoint(item.guid, item.cnsi_type)); - this.handleUpdateAction(item, EndpointsEffect.disconnectingKey, ([oldVal, newVal]) => { - this.store.dispatch(new ShowSnackBar(`Disconnected endpoint '${item.name}'`)); - this.store.dispatch(new GetSystemInfo()); - }); - }); - }, - label: 'Disconnect', - description: ``, // Description depends on console user permission - createVisible: (row$: Observable) => combineLatest( - this.currentUserPermissionsService.can(CurrentUserPermissions.ENDPOINT_REGISTER), - row$ - ).pipe( - map(([isAdmin, row]) => { - const isConnected = row.connectionStatus === 'connected'; - return isConnected && (!row.system_shared_token || row.system_shared_token && isAdmin); - }) - ) - }; - - private listActionConnect: IListAction = { - action: (item) => { - this.dialog.open(ConnectEndpointDialogComponent, { - data: { - name: item.name, - guid: item.guid, - type: item.cnsi_type, - ssoAllowed: item.sso_allowed - }, - disableClose: true - }); - }, - label: 'Connect', - description: '', - createVisible: (row$: Observable) => row$.pipe(map(row => row.connectionStatus === 'disconnected')) - }; - - private singleActions = [ - this.listActionDisconnect, - this.listActionConnect, - this.listActionDelete - ]; + private singleActions: IListAction[]; private globalActions = []; @@ -208,42 +124,14 @@ export class EndpointsListConfigService implements IListConfig { enableTextFilter = true; tableFixedRowHeight = true; - private handleUpdateAction(item, effectKey, handleChange) { - this.handleAction(selectUpdateInfo( - endpointStoreNames.type, - item.guid, - effectKey, - ), handleChange); - } - - private handleDeleteAction(item, handleChange) { - this.handleAction(selectDeletionInfo( - endpointStoreNames.type, - item.guid, - ), handleChange); - } - - private handleAction(storeSelect, handleChange) { - const disSub = this.store.select(storeSelect).pipe( - pairwise()) - .subscribe(([oldVal, newVal]) => { - // https://github.com/SUSE/stratos/issues/29 Generic way to handle errors ('Failed to disconnect X') - if (!newVal.error && (oldVal.busy && !newVal.busy)) { - handleChange([oldVal, newVal]); - disSub.unsubscribe(); - } - }); - } - constructor( private store: Store, - private dialog: MatDialog, paginationMonitorFactory: PaginationMonitorFactory, entityMonitorFactory: EntityMonitorFactory, internalEventMonitorFactory: InternalEventMonitorFactory, - private currentUserPermissionsService: CurrentUserPermissionsService, - private confirmDialog: ConfirmationDialogService + endpointListHelper: EndpointListHelper ) { + this.singleActions = endpointListHelper.endpointActions(); const favoriteCell = createTableColumnFavorite( (row: EndpointModel) => new UserFavoriteEndpoint( row.guid, From 4dc7876b55c48ff7cc3daa652f8799f98c8d79dc Mon Sep 17 00:00:00 2001 From: Richard Cox Date: Tue, 5 Mar 2019 16:37:55 +0000 Subject: [PATCH 04/20] Add endpoint type icons & custom endpoint details table column/card section --- .../src/core/extension/extension-types.ts | 15 +++++- .../features/endpoints/endpoint-helpers.ts | 31 ++++++++---- .../table-cell/table-cell.component.ts | 11 +++-- .../components/list/list-table/table.types.ts | 2 +- .../cf-endpoint-details.component.html | 7 +++ .../cf-endpoint-details.component.scss | 14 ++++++ .../cf-endpoint-details.component.spec.ts | 25 ++++++++++ .../cf-endpoint-details.component.ts | 14 ++++++ .../endpoint-card.component.html | 16 +++++-- .../endpoint-card.component.scss | 8 ++++ .../endpoint-card/endpoint-card.component.ts | 48 +++++++++++++++++-- .../endpoint/endpoints-list-config.service.ts | 38 ++++----------- ...table-cell-endpoint-details.component.html | 1 + ...table-cell-endpoint-details.component.scss | 0 ...le-cell-endpoint-details.component.spec.ts | 25 ++++++++++ .../table-cell-endpoint-details.component.ts | 42 ++++++++++++++++ ...able-cell-endpoint-is-admin.component.html | 3 -- ...able-cell-endpoint-is-admin.component.scss | 1 - ...e-cell-endpoint-is-admin.component.spec.ts | 33 ------------- .../table-cell-endpoint-is-admin.component.ts | 11 ----- .../table-cell-endpoint-name.component.html | 5 +- .../table-cell-endpoint-name.component.ts | 6 ++- .../packages/core/src/shared/shared.module.ts | 6 +-- 23 files changed, 253 insertions(+), 109 deletions(-) create mode 100644 src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.html create mode 100644 src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.scss create mode 100644 src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.spec.ts create mode 100644 src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.ts create mode 100644 src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-details/table-cell-endpoint-details.component.html create mode 100644 src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-details/table-cell-endpoint-details.component.scss create mode 100644 src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-details/table-cell-endpoint-details.component.spec.ts create mode 100644 src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-details/table-cell-endpoint-details.component.ts delete mode 100644 src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-is-admin/table-cell-endpoint-is-admin.component.html delete mode 100644 src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-is-admin/table-cell-endpoint-is-admin.component.scss delete mode 100644 src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-is-admin/table-cell-endpoint-is-admin.component.spec.ts delete mode 100644 src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-is-admin/table-cell-endpoint-is-admin.component.ts diff --git a/src/frontend/packages/core/src/core/extension/extension-types.ts b/src/frontend/packages/core/src/core/extension/extension-types.ts index 8fb372c0ac..d3a3900b3d 100644 --- a/src/frontend/packages/core/src/core/extension/extension-types.ts +++ b/src/frontend/packages/core/src/core/extension/extension-types.ts @@ -2,6 +2,9 @@ import { Type } from '@angular/core'; import { FormGroup } from '@angular/forms'; import { Schema, schema } from 'normalizr'; +import { EndpointModel } from '../../../../store/src/types/endpoint.types'; +import { TableCellCustom } from '../../shared/components/list/list.types'; + // Allowable endpoint types export type EndpointType = 'cf' | 'metrics' | string; @@ -13,10 +16,18 @@ export interface EndpointTypeConfig { icon?: string; iconFont?: string; authTypes?: string[]; - // Get the link to the home page for the given endpoint GUID + /** + * Get the link to the home page for the given endpoint GUID + */ homeLink?: (string) => string[]; - // Schema keys associated with this endpoint type (used when clearing pagination) + /** + * Schema keys associated with this endpoint type (used when clearing pagination) + */ entitySchemaKeys?: string[]; + /** + * Show custom content in the endpoints list + */ + listDetailsComponent?: Type>; } export interface EndpointAuthTypeConfig { diff --git a/src/frontend/packages/core/src/features/endpoints/endpoint-helpers.ts b/src/frontend/packages/core/src/features/endpoints/endpoint-helpers.ts index d7e8b5c54d..93302fcbe3 100644 --- a/src/frontend/packages/core/src/features/endpoints/endpoint-helpers.ts +++ b/src/frontend/packages/core/src/features/endpoints/endpoint-helpers.ts @@ -1,19 +1,23 @@ +import { Type } from '@angular/core'; +import { Validators } from '@angular/forms'; import { Store } from '@ngrx/store'; import { Observable } from 'rxjs'; import { first, map } from 'rxjs/operators'; -import { Validators } from '@angular/forms'; - -import { urlValidationExpression } from '../../core/utils.service'; -import { EndpointModel } from '../../../../store/src/types/endpoint.types'; -import { EndpointTypeConfig, EndpointAuthTypeConfig, EndpointType } from '../../core/extension/extension-types'; import { AppState } from '../../../../store/src/app-state'; -import { selectEntities } from '../../../../store/src/selectors/api.selectors'; import { endpointSchemaKey } from '../../../../store/src/helpers/entity-factory'; +import { selectEntities } from '../../../../store/src/selectors/api.selectors'; +import { EndpointModel } from '../../../../store/src/types/endpoint.types'; import { ExtensionService } from '../../core/extension/extension-service'; +import { EndpointAuthTypeConfig, EndpointType, EndpointTypeConfig } from '../../core/extension/extension-types'; +import { urlValidationExpression } from '../../core/utils.service'; +import { + CfEndpointDetailsComponent, +} from '../../shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component'; +import { TableCellCustom } from '../../shared/components/list/list.types'; import { CredentialsAuthFormComponent } from './connect-endpoint-dialog/auth-forms/credentials-auth-form.component'; -import { SSOAuthFormComponent } from './connect-endpoint-dialog/auth-forms/sso-auth-form.component'; import { NoneAuthFormComponent } from './connect-endpoint-dialog/auth-forms/none-auth-form.component'; +import { SSOAuthFormComponent } from './connect-endpoint-dialog/auth-forms/sso-auth-form.component'; export function getFullEndpointApiUrl(endpoint: EndpointModel) { return endpoint && endpoint.api_endpoint ? `${endpoint.api_endpoint.Scheme}://${endpoint.api_endpoint.Host}` : 'Unknown'; @@ -37,7 +41,8 @@ const endpointTypes: EndpointTypeConfig[] = [ urlValidation: urlValidationExpression, icon: 'cloud_foundry', iconFont: 'stratos-icons', - homeLink: (guid) => ['/cloud-foundry', guid] + homeLink: (guid) => ['/cloud-foundry', guid], + listDetailsComponent: CfEndpointDetailsComponent }, { value: 'metrics', @@ -76,6 +81,8 @@ let endpointAuthTypes: EndpointAuthTypeConfig[] = [ const endpointTypesMap = {}; +export const endpointListDetailsComponents: Type>[] = [CfEndpointDetailsComponent]; + export function initEndpointTypes(epTypes: EndpointTypeConfig[]) { epTypes.forEach(epType => { endpointTypes.push(epType); @@ -89,6 +96,10 @@ export function initEndpointTypes(epTypes: EndpointTypeConfig[]) { } }); } + + if (epType.listDetailsComponent) { + endpointListDetailsComponents.push(epType.listDetailsComponent); + } }); endpointTypes.forEach(ept => { @@ -114,6 +125,10 @@ export function getEndpointTypes() { return endpointTypes; } +export function getEndpointType(type: string): EndpointTypeConfig { + return getEndpointTypes().find(ep => ep.value === type); +} + export function getIconForEndpoint(type: string): EndpointIcon { const icon = { name: 'settings_ethernet', diff --git a/src/frontend/packages/core/src/shared/components/list/list-table/table-cell/table-cell.component.ts b/src/frontend/packages/core/src/shared/components/list/list-table/table-cell/table-cell.component.ts index 5adb3debd4..e4239af22c 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-table/table-cell/table-cell.component.ts +++ b/src/frontend/packages/core/src/shared/components/list/list-table/table-cell/table-cell.component.ts @@ -13,6 +13,7 @@ import { ViewEncapsulation, } from '@angular/core'; +import { endpointListDetailsComponents } from '../../../../../features/endpoints/endpoint-helpers'; import { IListDataSource } from '../../data-sources-controllers/list-data-source-types'; import { TableCellEventActionComponent, @@ -84,8 +85,8 @@ import { CfSpacePermissionCellComponent, } from '../../list-types/cf-users/cf-space-permission-cell/cf-space-permission-cell.component'; import { - TableCellEndpointIsAdminComponent, -} from '../../list-types/endpoint/table-cell-endpoint-is-admin/table-cell-endpoint-is-admin.component'; + TableCellEndpointDetailsComponent, +} from '../../list-types/endpoint/table-cell-endpoint-details/table-cell-endpoint-details.component'; import { TableCellEndpointNameComponent, } from '../../list-types/endpoint/table-cell-endpoint-name/table-cell-endpoint-name.component'; @@ -118,7 +119,6 @@ import { TableCellSelectComponent } from '../table-cell-select/table-cell-select import { TableHeaderSelectComponent } from '../table-header-select/table-header-select.component'; import { ICellDefinition } from '../table.types'; - /* tslint:enable:max-line-length */ export const listTableCells = [ TableCellDefaultComponent, @@ -160,11 +160,12 @@ export const listTableCells = [ TableCellSpaceNameComponent, TableCellAppCfOrgSpaceHeaderComponent, TableCellAppCfOrgSpaceComponent, - TableCellEndpointIsAdminComponent, TableCellAServicePlanPublicComponent, TableCellAServicePlanPriceComponent, TableCellAServicePlanExtrasComponent, - TableCellFavoriteComponent + TableCellFavoriteComponent, + TableCellEndpointDetailsComponent, + ...endpointListDetailsComponents ]; @Component({ diff --git a/src/frontend/packages/core/src/shared/components/list/list-table/table.types.ts b/src/frontend/packages/core/src/shared/components/list/list-table/table.types.ts index 7c3d49c504..9b67e6d6e6 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-table/table.types.ts +++ b/src/frontend/packages/core/src/shared/components/list/list-table/table.types.ts @@ -57,5 +57,5 @@ export const listTableComponents = [ TableRowComponent, TableCellDefaultComponent, ...listTableCells, - TableCellStatusDirective, + TableCellStatusDirective ]; diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.html b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.html new file mode 100644 index 0000000000..8fb19c8f88 --- /dev/null +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.html @@ -0,0 +1,7 @@ +
+
Username: {{ row.user.name}}
+
Admin: + +
+
+- \ No newline at end of file diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.scss b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.scss new file mode 100644 index 0000000000..a10efefd13 --- /dev/null +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.scss @@ -0,0 +1,14 @@ +.cf-details { + padding: 2px 0; + text-align: end; + + &__row { + display: flex; + &-space { + justify-content: space-between; + } + } + &__title { + padding-right: 5px; + } +} diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.spec.ts b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.spec.ts new file mode 100644 index 0000000000..0449dfb894 --- /dev/null +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CfEndpointDetailsComponent } from './cf-endpoint-details.component'; + +describe('CfEndpointDetailsComponent', () => { + let component: CfEndpointDetailsComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ CfEndpointDetailsComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(CfEndpointDetailsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.ts b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.ts new file mode 100644 index 0000000000..ee55d42fcc --- /dev/null +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.ts @@ -0,0 +1,14 @@ +import { Component, Input } from '@angular/core'; + +import { EndpointModel } from '../../../../../../../../store/src/types/endpoint.types'; +import { TableCellCustom } from '../../../list.types'; + +@Component({ + selector: 'app-cf-endpoint-details', + templateUrl: './cf-endpoint-details.component.html', + styleUrls: ['./cf-endpoint-details.component.scss'] +}) +export class CfEndpointDetailsComponent extends TableCellCustom { + + @Input() spaceBetween = false; +} diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.html b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.html index cc8b120c26..bd58371675 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.html +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.html @@ -1,7 +1,9 @@ - - - {{ row?.name }} + + +
+ {{icon.name}} + {{ row?.name }} +
Type @@ -11,4 +13,10 @@ Address {{ address }} + + Details + +
+
+
\ No newline at end of file diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.scss b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.scss index ce7d1d2449..14abfa84fc 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.scss +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.scss @@ -3,4 +3,12 @@ &:focus { outline: 0; } + + &__title { + align-items: center; + display: flex; + mat-icon { + padding-right: 10px; + } + } } diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.ts b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.ts index 0dcc487906..e0a6d92bab 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.ts +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.ts @@ -1,20 +1,29 @@ -import { Component, Input, OnInit } from '@angular/core'; +import { Component, ComponentFactoryResolver, Input, OnInit, ViewChild, ViewContainerRef } from '@angular/core'; import { ReplaySubject } from 'rxjs'; import { EndpointModel } from '../../../../../../../../store/src/types/endpoint.types'; import { UserFavoriteEndpoint } from '../../../../../../../../store/src/types/user-favorites.types'; import { EndpointsService } from '../../../../../../core/endpoints.service'; import { getFavoriteFromEndpointEntity } from '../../../../../../core/user-favorite-helpers'; -import { getFullEndpointApiUrl, getNameForEndpointType } from '../../../../../../features/endpoints/endpoint-helpers'; +import { + EndpointIcon, + endpointListDetailsComponents, + getEndpointType, + getFullEndpointApiUrl, + getIconForEndpoint, + getNameForEndpointType, +} from '../../../../../../features/endpoints/endpoint-helpers'; import { CardStatus } from '../../../../../shared.types'; import { MetaCardMenuItem } from '../../../list-cards/meta-card/meta-card-base/meta-card.component'; import { CardCell } from '../../../list.types'; +import { CfEndpointDetailsComponent } from '../cf-endpoint-details/cf-endpoint-details.component'; import { EndpointListHelper } from '../endpoint-list.helpers'; @Component({ selector: 'app-endpoint-card', templateUrl: './endpoint-card.component.html', - styleUrls: ['./endpoint-card.component.scss'] + styleUrls: ['./endpoint-card.component.scss'], + entryComponents: [...endpointListDetailsComponents] }) export class EndpointCardComponent extends CardCell implements OnInit { @@ -24,22 +33,34 @@ export class EndpointCardComponent extends CardCell implements On public type: string; public address: string; public cardMenu: MetaCardMenuItem[]; + public icon: EndpointIcon; + public hasDetails = true; + + @Input() component: CfEndpointDetailsComponent; + private endpointDetails: ViewContainerRef; + @ViewChild('endpointDetails', { read: ViewContainerRef }) set content(content: ViewContainerRef) { + this.endpointDetails = content; + this.updateDetails(); + } private pRow: EndpointModel; @Input('row') set row(row: EndpointModel) { this.pRow = row; this.type = row ? getNameForEndpointType(row.cnsi_type) : ''; + this.icon = row ? getIconForEndpoint(row.cnsi_type) : null; this.address = row ? getFullEndpointApiUrl(row) : ''; this.status$.next(this.determineEndpointStatus(row)); this.rowObs.next(row); + this.updateDetails(); } get row(): EndpointModel { return this.pRow; } constructor( - endpointListHelper: EndpointListHelper + endpointListHelper: EndpointListHelper, + private componentFactoryResolver: ComponentFactoryResolver ) { super(); this.cardMenu = endpointListHelper.endpointActions().map(endpointAction => ({ @@ -69,4 +90,23 @@ export class EndpointCardComponent extends CardCell implements On return CardStatus.INCOMPLETE; } } + + updateDetails() { + if (!this.endpointDetails) { + return; + } + const e = getEndpointType(this.pRow.cnsi_type); + if (!e.listDetailsComponent) { + this.hasDetails = false; + return; + } + + if (!this.component) { + const componentFactory = this.componentFactoryResolver.resolveComponentFactory(e.listDetailsComponent); + const componentRef = this.endpointDetails.createComponent(componentFactory); + this.component = componentRef.instance as CfEndpointDetailsComponent; + } + this.component.row = this.pRow; + this.component.spaceBetween = true; + } } diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoints-list-config.service.ts b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoints-list-config.service.ts index c78d164e5b..7b8b81b9ef 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoints-list-config.service.ts +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoints-list-config.service.ts @@ -5,11 +5,7 @@ import { ListView } from '../../../../../../../store/src/actions/list.actions'; import { AppState } from '../../../../../../../store/src/app-state'; import { EndpointModel } from '../../../../../../../store/src/types/endpoint.types'; import { UserFavoriteEndpoint } from '../../../../../../../store/src/types/user-favorites.types'; -import { - getEndpointUsername, - getFullEndpointApiUrl, - getNameForEndpointType, -} from '../../../../../features/endpoints/endpoint-helpers'; +import { getFullEndpointApiUrl, getNameForEndpointType } from '../../../../../features/endpoints/endpoint-helpers'; import { EntityMonitorFactory } from '../../../../monitors/entity-monitor.factory.service'; import { InternalEventMonitorFactory } from '../../../../monitors/internal-event-monitor.factory'; import { PaginationMonitorFactory } from '../../../../monitors/pagination-monitor.factory'; @@ -19,7 +15,7 @@ import { IListAction, IListConfig, ListViewTypes } from '../../list.component.ty import { EndpointCardComponent } from './endpoint-card/endpoint-card.component'; import { EndpointListHelper } from './endpoint-list.helpers'; import { EndpointsDataSource } from './endpoints-data-source'; -import { TableCellEndpointIsAdminComponent } from './table-cell-endpoint-is-admin/table-cell-endpoint-is-admin.component'; +import { TableCellEndpointDetailsComponent } from './table-cell-endpoint-details/table-cell-endpoint-details.component'; import { TableCellEndpointNameComponent } from './table-cell-endpoint-name/table-cell-endpoint-name.component'; import { TableCellEndpointStatusComponent } from './table-cell-endpoint-status/table-cell-endpoint-status.component'; @@ -63,30 +59,6 @@ export const endpointColumns: ITableColumn[] = [ }, cellFlex: '2' }, - { - columnId: 'username', - headerCell: () => 'Username', - cellDefinition: { - getValue: getEndpointUsername - }, - sort: { - type: 'sort', - orderKey: 'username', - field: 'user.name' - }, - cellFlex: '2' - }, - { - columnId: 'user-type', - headerCell: () => 'Admin', - cellComponent: TableCellEndpointIsAdminComponent, - sort: { - type: 'sort', - orderKey: 'user-type', - field: 'user.admin' - }, - cellFlex: '2' - }, { columnId: 'address', headerCell: () => 'Address', @@ -100,6 +72,12 @@ export const endpointColumns: ITableColumn[] = [ }, cellFlex: '5' }, + { + columnId: 'details', + headerCell: () => 'Details', + cellComponent: TableCellEndpointDetailsComponent, + cellFlex: '4' + } ]; @Injectable() diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-details/table-cell-endpoint-details.component.html b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-details/table-cell-endpoint-details.component.html new file mode 100644 index 0000000000..6e81826a58 --- /dev/null +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-details/table-cell-endpoint-details.component.html @@ -0,0 +1 @@ +
\ No newline at end of file diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-details/table-cell-endpoint-details.component.scss b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-details/table-cell-endpoint-details.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-details/table-cell-endpoint-details.component.spec.ts b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-details/table-cell-endpoint-details.component.spec.ts new file mode 100644 index 0000000000..80261f1af7 --- /dev/null +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-details/table-cell-endpoint-details.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TableCellEndpointDetailsComponent } from './table-cell-endpoint-details.component'; + +describe('TableCellEndpointDetailsComponent', () => { + let component: TableCellEndpointDetailsComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ TableCellEndpointDetailsComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(TableCellEndpointDetailsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-details/table-cell-endpoint-details.component.ts b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-details/table-cell-endpoint-details.component.ts new file mode 100644 index 0000000000..36fd4834d0 --- /dev/null +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-details/table-cell-endpoint-details.component.ts @@ -0,0 +1,42 @@ +import { Component, ComponentFactoryResolver, Input, Type, ViewChild, ViewContainerRef } from '@angular/core'; + +import { EndpointModel } from '../../../../../../../../store/src/types/endpoint.types'; +import { getEndpointType } from '../../../../../../features/endpoints/endpoint-helpers'; +import { TableCellCustom } from '../../../list.types'; + +@Component({ + selector: 'app-table-cell-endpoint-details', + templateUrl: './table-cell-endpoint-details.component.html', + styleUrls: ['./table-cell-endpoint-details.component.scss'] +}) +export class TableCellEndpointDetailsComponent extends TableCellCustom { + + @Input() component: Type>; + @ViewChild('target', { read: ViewContainerRef }) target; + + cell: TableCellCustom; + + constructor(private componentFactoryResolver: ComponentFactoryResolver) { + super(); + } + + private pRow: EndpointModel; + @Input('row') + set row(row: EndpointModel) { + this.pRow = row; + + const e = getEndpointType(row.cnsi_type); + if (e.listDetailsComponent) { + if (!this.cell) { + const componentFactory = this.componentFactoryResolver.resolveComponentFactory(e.listDetailsComponent); + const componentRef = this.target.createComponent(componentFactory); + this.cell = componentRef.instance as TableCellCustom; + } + this.cell.row = this.pRow; + } + + } + get row(): EndpointModel { + return this.pRow; + } +} diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-is-admin/table-cell-endpoint-is-admin.component.html b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-is-admin/table-cell-endpoint-is-admin.component.html deleted file mode 100644 index 781b48907b..0000000000 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-is-admin/table-cell-endpoint-is-admin.component.html +++ /dev/null @@ -1,3 +0,0 @@ - - -- \ No newline at end of file diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-is-admin/table-cell-endpoint-is-admin.component.scss b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-is-admin/table-cell-endpoint-is-admin.component.scss deleted file mode 100644 index 8b13789179..0000000000 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-is-admin/table-cell-endpoint-is-admin.component.scss +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-is-admin/table-cell-endpoint-is-admin.component.spec.ts b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-is-admin/table-cell-endpoint-is-admin.component.spec.ts deleted file mode 100644 index d9ba633383..0000000000 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-is-admin/table-cell-endpoint-is-admin.component.spec.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; - -import { CoreModule } from '../../../../../../core/core.module'; -import { BooleanIndicatorComponent } from '../../../../boolean-indicator/boolean-indicator.component'; -import { TableCellEndpointIsAdminComponent } from './table-cell-endpoint-is-admin.component'; -import { EndpointModel } from '../../../../../../../../store/src/types/endpoint.types'; - - -describe('TableCellEndpointIsAdminComponent', () => { - let component: TableCellEndpointIsAdminComponent<{}>; - let fixture: ComponentFixture>; - - beforeEach(async(() => { - TestBed.configureTestingModule({ - declarations: [TableCellEndpointIsAdminComponent, BooleanIndicatorComponent], - imports: [ - CoreModule - ] - }) - .compileComponents(); - })); - - beforeEach(() => { - fixture = TestBed.createComponent(TableCellEndpointIsAdminComponent); - component = fixture.componentInstance; - component.row = {} as EndpointModel; - fixture.detectChanges(); - }); - - it('should be created', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-is-admin/table-cell-endpoint-is-admin.component.ts b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-is-admin/table-cell-endpoint-is-admin.component.ts deleted file mode 100644 index 0624a37b3d..0000000000 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-is-admin/table-cell-endpoint-is-admin.component.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Component } from '@angular/core'; - -import { TableCellCustom } from '../../../list.types'; - -/* tslint:disable:no-access-missing-member https://github.com/mgechev/codelyzer/issues/191*/ -@Component({ - selector: 'app-table-cell-endpoint-is-admin', - templateUrl: './table-cell-endpoint-is-admin.component.html', - styleUrls: ['./table-cell-endpoint-is-admin.component.scss'] -}) -export class TableCellEndpointIsAdminComponent extends TableCellCustom { } diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-name/table-cell-endpoint-name.component.html b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-name/table-cell-endpoint-name.component.html index 5dfcc28a93..a4f26dd73a 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-name/table-cell-endpoint-name.component.html +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-name/table-cell-endpoint-name.component.html @@ -1,5 +1,6 @@
- {{ row.name }} + {{ row.name }} {{ row.name }} - share + share
\ No newline at end of file diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-name/table-cell-endpoint-name.component.ts b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-name/table-cell-endpoint-name.component.ts index 8d9297f968..5476df6f49 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-name/table-cell-endpoint-name.component.ts +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-name/table-cell-endpoint-name.component.ts @@ -1,9 +1,8 @@ import { Component, Input } from '@angular/core'; -import { TableCellCustom } from '../../../list.types'; -import { getEndpointTypes } from '../../../../../../features/endpoints/endpoint-helpers'; import { EndpointModel } from '../../../../../../../../store/src/types/endpoint.types'; import { EndpointsService } from '../../../../../../core/endpoints.service'; +import { TableCellCustom } from '../../../list.types'; @Component({ selector: 'app-table-cell-endpoint-name', @@ -17,6 +16,9 @@ export class TableCellEndpointNameComponent extends TableCellCustom Date: Tue, 5 Mar 2019 17:26:14 +0000 Subject: [PATCH 05/20] Fix unit tests --- .../cf-endpoint-details.component.spec.ts | 10 ++++++++-- .../endpoint-card/endpoint-card.component.spec.ts | 14 +++++++++++--- .../endpoint-card/endpoint-card.component.ts | 3 ++- .../endpoints-list-config.service.spec.ts | 12 ++++++------ .../table-cell-endpoint-name.component.spec.ts | 12 +++++------- .../shared/components/list/list.component.spec.ts | 15 +++++++++------ 6 files changed, 41 insertions(+), 25 deletions(-) diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.spec.ts b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.spec.ts index 0449dfb894..e361a7fff5 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.spec.ts +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.spec.ts @@ -1,5 +1,7 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { CoreModule } from '../../../../../../core/core.module'; +import { SharedModule } from '../../../../../shared.module'; import { CfEndpointDetailsComponent } from './cf-endpoint-details.component'; describe('CfEndpointDetailsComponent', () => { @@ -8,9 +10,13 @@ describe('CfEndpointDetailsComponent', () => { beforeEach(async(() => { TestBed.configureTestingModule({ - declarations: [ CfEndpointDetailsComponent ] + declarations: [], + imports: [ + CoreModule, + SharedModule + ] }) - .compileComponents(); + .compileComponents(); })); beforeEach(() => { diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.spec.ts b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.spec.ts index 0a561e4625..9d5b445fdf 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.spec.ts +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.spec.ts @@ -1,21 +1,29 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { EndpointModel } from '../../../../../../../../store/src/types/endpoint.types'; +import { BaseTestModules } from '../../../../../../../test-framework/cloud-foundry-endpoint-service.helper'; +import { EndpointListHelper } from '../endpoint-list.helpers'; import { EndpointCardComponent } from './endpoint-card.component'; -describe('EndpointCardComponent', () => { +fdescribe('EndpointCardComponent', () => { let component: EndpointCardComponent; let fixture: ComponentFixture; beforeEach(async(() => { TestBed.configureTestingModule({ - declarations: [ EndpointCardComponent ] + declarations: [], + imports: [...BaseTestModules], + providers: [EndpointListHelper] }) - .compileComponents(); + .compileComponents(); })); beforeEach(() => { fixture = TestBed.createComponent(EndpointCardComponent); component = fixture.componentInstance; + component.row = { + cnsi_type: 'metrics', + } as EndpointModel; fixture.detectChanges(); }); diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.ts b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.ts index e0a6d92bab..740f27921b 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.ts +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.ts @@ -72,6 +72,8 @@ export class EndpointCardComponent extends CardCell implements On ngOnInit() { this.favorite = getFavoriteFromEndpointEntity(this.row); + const e = getEndpointType(this.pRow.cnsi_type); + this.hasDetails = !!e.listDetailsComponent; } getLinkForEndpoint() { @@ -97,7 +99,6 @@ export class EndpointCardComponent extends CardCell implements On } const e = getEndpointType(this.pRow.cnsi_type); if (!e.listDetailsComponent) { - this.hasDetails = false; return; } diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoints-list-config.service.spec.ts b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoints-list-config.service.spec.ts index 6c3f9e6e02..9187046806 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoints-list-config.service.spec.ts +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoints-list-config.service.spec.ts @@ -1,22 +1,22 @@ -import { createBasicStoreModule } from '../../../../../../test-framework/store-test-helper'; -import { StoreModule } from '@ngrx/store'; import { CommonModule } from '@angular/common'; +import { inject, TestBed } from '@angular/core/testing'; + +import { createBasicStoreModule } from '../../../../../../test-framework/store-test-helper'; import { CoreModule } from '../../../../../core/core.module'; import { SharedModule } from '../../../../shared.module'; -import { TestBed, inject } from '@angular/core/testing'; - +import { EndpointListHelper } from './endpoint-list.helpers'; import { EndpointsListConfigService } from './endpoints-list-config.service'; describe('EndpointsListConfigService', () => { beforeEach(() => { TestBed.configureTestingModule({ - providers: [EndpointsListConfigService], + providers: [EndpointsListConfigService, EndpointListHelper], imports: [ CommonModule, CoreModule, SharedModule, createBasicStoreModule() - ] + ], }); }); diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-name/table-cell-endpoint-name.component.spec.ts b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-name/table-cell-endpoint-name.component.spec.ts index 0c79d6d652..0526d50a15 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-name/table-cell-endpoint-name.component.spec.ts +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-name/table-cell-endpoint-name.component.spec.ts @@ -1,19 +1,17 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { TableCellEndpointNameComponent } from './table-cell-endpoint-name.component'; -import { CoreModule } from '../../../../../../core/core.module'; import { EndpointModel } from '../../../../../../../../store/src/types/endpoint.types'; +import { CoreModule } from '../../../../../../core/core.module'; +import { TableCellEndpointNameComponent } from './table-cell-endpoint-name.component'; describe('TableCellEndpointNameComponent', () => { - let component: TableCellEndpointNameComponent<{}>; - let fixture: ComponentFixture>; + let component: TableCellEndpointNameComponent; + let fixture: ComponentFixture; beforeEach(async(() => { TestBed.configureTestingModule({ declarations: [TableCellEndpointNameComponent], - imports: [ - CoreModule - ] + imports: [CoreModule] }) .compileComponents(); })); diff --git a/src/frontend/packages/core/src/shared/components/list/list.component.spec.ts b/src/frontend/packages/core/src/shared/components/list/list.component.spec.ts index 1ca6a21d49..2a4e9ee933 100644 --- a/src/frontend/packages/core/src/shared/components/list/list.component.spec.ts +++ b/src/frontend/packages/core/src/shared/components/list/list.component.spec.ts @@ -5,20 +5,21 @@ import { Store } from '@ngrx/store'; import { BehaviorSubject, of as observableOf } from 'rxjs'; import { switchMap } from 'rxjs/operators'; -import { CoreModule } from '../../../core/core.module'; +import { ListView } from '../../../../../store/src/actions/list.actions'; +import { AppState } from '../../../../../store/src/app-state'; +import { APIResource } from '../../../../../store/src/types/api.types'; +import { EndpointModel } from '../../../../../store/src/types/endpoint.types'; import { createBasicStoreModule, getInitialTestStoreState } from '../../../../test-framework/store-test-helper'; +import { CoreModule } from '../../../core/core.module'; import { EntityMonitorFactory } from '../../monitors/entity-monitor.factory.service'; import { PaginationMonitorFactory } from '../../monitors/pagination-monitor.factory'; import { SharedModule } from '../../shared.module'; import { ApplicationStateService } from '../application-state/application-state.service'; import { CfEndpointCardComponent } from './list-types/cf-endpoints/cf-endpoint-card/cf-endpoint-card.component'; +import { EndpointListHelper } from './list-types/endpoint/endpoint-list.helpers'; import { EndpointsListConfigService } from './list-types/endpoint/endpoints-list-config.service'; import { ListComponent } from './list.component'; import { ListConfig, ListViewTypes } from './list.component.types'; -import { APIResource } from '../../../../../store/src/types/api.types'; -import { ListView } from '../../../../../store/src/actions/list.actions'; -import { AppState } from '../../../../../store/src/app-state'; -import { EndpointModel } from '../../../../../store/src/types/endpoint.types'; class MockedNgZone { run = fn => fn(); @@ -58,6 +59,7 @@ describe('ListComponent', () => { { provide: ChangeDetectorRef, useValue: { detectChanges: () => { } } }, // Fun fact, NgZone will execute something on import which causes an undefined error { provide: MockedNgZone, useValue: new MockedNgZone }, + EndpointListHelper ] }); inject([Store, ChangeDetectorRef, NgZone], (iStore: Store, cd: ChangeDetectorRef, ngZone: MockedNgZone) => { @@ -119,7 +121,8 @@ describe('ListComponent', () => { { provide: ListConfig, useClass: EndpointsListConfigService }, ApplicationStateService, PaginationMonitorFactory, - EntityMonitorFactory + EntityMonitorFactory, + EndpointListHelper ], imports: [ CoreModule, From df782df2d42c1fe66a9bfe961a000837d8a1cf5d Mon Sep 17 00:00:00 2001 From: Richard Cox Date: Wed, 6 Mar 2019 17:10:58 +0000 Subject: [PATCH 06/20] WIP --- .../src/core/extension/extension-types.ts | 1 + .../features/endpoints/endpoint-helpers.ts | 2 + .../list/list-cards/card/card.component.ts | 23 ++++--- .../meta-card-item.component.html | 2 +- .../meta-card-item.component.ts | 5 +- .../base-endpoints-data-source.ts | 11 ++-- .../cf-endpoint-card.component.html | 17 ----- .../cf-endpoint-card.component.scss | 6 -- .../cf-endpoint-card.component.spec.ts | 51 --------------- .../cf-endpoint-card.component.ts | 65 ------------------- .../cf-endpoints-list-config.service.ts | 31 ++------- .../cf-endpoint-details.component.html | 6 +- .../cf-endpoint-details.component.scss | 15 ++--- .../cf-endpoint-details.component.ts | 2 +- .../endpoint-card.component.html | 19 ++++-- .../endpoint-card.component.scss | 21 +++++- .../endpoint-card.component.spec.ts | 2 +- .../endpoint-card/endpoint-card.component.ts | 57 +++++++--------- .../endpoint/endpoint-list.helpers.ts | 38 +++++------ .../table-cell-endpoint-status.component.html | 6 +- .../table-cell-endpoint-status.component.ts | 7 +- .../components/list/list.component.spec.ts | 8 +-- 22 files changed, 123 insertions(+), 272 deletions(-) delete mode 100644 src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/cf-endpoint-card.component.html delete mode 100644 src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/cf-endpoint-card.component.scss delete mode 100644 src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/cf-endpoint-card.component.spec.ts delete mode 100644 src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/cf-endpoint-card.component.ts diff --git a/src/frontend/packages/core/src/core/extension/extension-types.ts b/src/frontend/packages/core/src/core/extension/extension-types.ts index d3a3900b3d..d0d0e8f848 100644 --- a/src/frontend/packages/core/src/core/extension/extension-types.ts +++ b/src/frontend/packages/core/src/core/extension/extension-types.ts @@ -15,6 +15,7 @@ export interface EndpointTypeConfig { allowTokenSharing?: boolean; icon?: string; iconFont?: string; + imagePath?: string; authTypes?: string[]; /** * Get the link to the home page for the given endpoint GUID diff --git a/src/frontend/packages/core/src/features/endpoints/endpoint-helpers.ts b/src/frontend/packages/core/src/features/endpoints/endpoint-helpers.ts index 93302fcbe3..45262f7f82 100644 --- a/src/frontend/packages/core/src/features/endpoints/endpoint-helpers.ts +++ b/src/frontend/packages/core/src/features/endpoints/endpoint-helpers.ts @@ -41,6 +41,7 @@ const endpointTypes: EndpointTypeConfig[] = [ urlValidation: urlValidationExpression, icon: 'cloud_foundry', iconFont: 'stratos-icons', + imagePath: '/core/assets/endpoint-icons/cloudfoundry.png', homeLink: (guid) => ['/cloud-foundry', guid], listDetailsComponent: CfEndpointDetailsComponent }, @@ -48,6 +49,7 @@ const endpointTypes: EndpointTypeConfig[] = [ value: 'metrics', label: 'Metrics', allowTokenSharing: true, + imagePath: '/core/assets/endpoint-icons/metrics.svg', homeLink: (guid) => ['/endpoints/metrics', guid] }, ]; diff --git a/src/frontend/packages/core/src/shared/components/list/list-cards/card/card.component.ts b/src/frontend/packages/core/src/shared/components/list/list-cards/card/card.component.ts index 3065cf4cd1..ac4f2f7e93 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-cards/card/card.component.ts +++ b/src/frontend/packages/core/src/shared/components/list/list-cards/card/card.component.ts @@ -12,27 +12,26 @@ import { } from '@angular/core'; import { IListDataSource } from '../../data-sources-controllers/list-data-source-types'; - -import { CardCell } from '../../list.types'; +import { + AppServiceBindingCardComponent, +} from '../../list-types/app-sevice-bindings/app-service-binding-card/app-service-binding-card.component'; import { CardAppComponent } from '../../list-types/app/card/card-app.component'; -import { CfEndpointCardComponent } from '../../list-types/cf-endpoints/cf-endpoint-card/cf-endpoint-card.component'; -import { CfOrgCardComponent } from '../../list-types/cf-orgs/cf-org-card/cf-org-card.component'; -import { CfSpaceCardComponent } from '../../list-types/cf-spaces/cf-space-card/cf-space-card.component'; import { CfBuildpackCardComponent } from '../../list-types/cf-buildpacks/cf-buildpack-card/cf-buildpack-card.component'; +import { CfOrgCardComponent } from '../../list-types/cf-orgs/cf-org-card/cf-org-card.component'; import { - CfSecurityGroupsCardComponent + CfSecurityGroupsCardComponent, } from '../../list-types/cf-security-groups/cf-security-groups-card/cf-security-groups-card.component'; -import { CfStacksCardComponent } from '../../list-types/cf-stacks/cf-stacks-card/cf-stacks-card.component'; import { CfServiceCardComponent } from '../../list-types/cf-services/cf-service-card/cf-service-card.component'; -import { - AppServiceBindingCardComponent -} from '../../list-types/app-sevice-bindings/app-service-binding-card/app-service-binding-card.component'; -import { ServiceInstanceCardComponent } from '../../list-types/services-wall/service-instance-card/service-instance-card.component'; +import { CfSpaceCardComponent } from '../../list-types/cf-spaces/cf-space-card/cf-space-card.component'; +import { CfStacksCardComponent } from '../../list-types/cf-stacks/cf-stacks-card/cf-stacks-card.component'; import { EndpointCardComponent } from '../../list-types/endpoint/endpoint-card/endpoint-card.component'; +import { + ServiceInstanceCardComponent, +} from '../../list-types/services-wall/service-instance-card/service-instance-card.component'; +import { CardCell } from '../../list.types'; export const listCards = [ CardAppComponent, - CfEndpointCardComponent, CfOrgCardComponent, CfSpaceCardComponent, CfBuildpackCardComponent, diff --git a/src/frontend/packages/core/src/shared/components/list/list-cards/meta-card/meta-card-item/meta-card-item.component.html b/src/frontend/packages/core/src/shared/components/list/list-cards/meta-card/meta-card-item/meta-card-item.component.html index 716f13842f..85d8279293 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-cards/meta-card/meta-card-item/meta-card-item.component.html +++ b/src/frontend/packages/core/src/shared/components/list/list-cards/meta-card/meta-card-item/meta-card-item.component.html @@ -9,4 +9,4 @@ - + \ No newline at end of file diff --git a/src/frontend/packages/core/src/shared/components/list/list-cards/meta-card/meta-card-item/meta-card-item.component.ts b/src/frontend/packages/core/src/shared/components/list/list-cards/meta-card/meta-card-item/meta-card-item.component.ts index a37275c7a0..b69e8d33b5 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-cards/meta-card/meta-card-item/meta-card-item.component.ts +++ b/src/frontend/packages/core/src/shared/components/list/list-cards/meta-card/meta-card-item/meta-card-item.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectionStrategy, Component, ContentChild, OnInit, TemplateRef, ViewChild, Input } from '@angular/core'; +import { ChangeDetectionStrategy, Component, ContentChild, Input, OnInit, TemplateRef, ViewChild } from '@angular/core'; import { MetaCardKeyComponent } from '../meta-card-key/meta-card-key.component'; import { MetaCardValueComponent } from '../meta-card-value/meta-card-value.component'; @@ -29,9 +29,6 @@ export class MetaCardItemComponent implements OnInit { @Input() customStyle = 'row'; - constructor() { - } - ngOnInit() { this.itemStyle = this.styles[this.customStyle]; } diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/base-endpoints-data-source.ts b/src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/base-endpoints-data-source.ts index c6827dcb8f..3925a7cd75 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/base-endpoints-data-source.ts +++ b/src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/base-endpoints-data-source.ts @@ -1,12 +1,13 @@ import { Store } from '@ngrx/store'; -import { AppState } from '../../../../../../../store/src/app-state'; + import { GetAllEndpoints } from '../../../../../../../store/src/actions/endpoint.actions'; import { CreatePagination } from '../../../../../../../store/src/actions/pagination.actions'; -import { ListDataSource } from '../../data-sources-controllers/list-data-source'; +import { GetSystemInfo } from '../../../../../../../store/src/actions/system.actions'; +import { AppState } from '../../../../../../../store/src/app-state'; +import { endpointSchemaKey, entityFactory } from '../../../../../../../store/src/helpers/entity-factory'; import { EndpointModel } from '../../../../../../../store/src/types/endpoint.types'; +import { ListDataSource } from '../../data-sources-controllers/list-data-source'; import { IListConfig } from '../../list.component.types'; -import { entityFactory, endpointSchemaKey } from '../../../../../../../store/src/helpers/entity-factory'; -import { GetSystemInfo } from '../../../../../../../store/src/actions/system.actions'; function syncPaginationSection( @@ -22,6 +23,7 @@ function syncPaginationSection( } export class BaseEndpointsDataSource extends ListDataSource { store: Store; + endpointType: string; constructor( store: Store, @@ -54,5 +56,6 @@ export class BaseEndpointsDataSource extends ListDataSource { listConfig, refresh: () => this.store.dispatch(new GetSystemInfo(false, action)) }); + this.endpointType = endpointType; } } diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/cf-endpoint-card.component.html b/src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/cf-endpoint-card.component.html deleted file mode 100644 index 6b87693173..0000000000 --- a/src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/cf-endpoint-card.component.html +++ /dev/null @@ -1,17 +0,0 @@ - - {{ row.name }} - - Address - {{ getEndpointUrl(row) }} - - - Account Username - {{ row.user.name }} - - - Administrator - - - - - \ No newline at end of file diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/cf-endpoint-card.component.scss b/src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/cf-endpoint-card.component.scss deleted file mode 100644 index ce7d1d2449..0000000000 --- a/src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/cf-endpoint-card.component.scss +++ /dev/null @@ -1,6 +0,0 @@ -.endpoint-card { - cursor: pointer; - &:focus { - outline: 0; - } -} diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/cf-endpoint-card.component.spec.ts b/src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/cf-endpoint-card.component.spec.ts deleted file mode 100644 index b2a9ba4397..0000000000 --- a/src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/cf-endpoint-card.component.spec.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { RouterTestingModule } from '@angular/router/testing'; - -import { SharedModule } from '../../../../../shared.module'; -import { EntityMonitorFactory } from '../../../../../monitors/entity-monitor.factory.service'; -import { createBasicStoreModule } from '../../../../../../../test-framework/store-test-helper'; -import { BaseTestModules } from '../../../../../../../test-framework/cloud-foundry-endpoint-service.helper'; -import { ServiceActionHelperService } from '../../../../../data-services/service-action-helper.service'; -import { CfEndpointCardComponent } from './cf-endpoint-card.component'; - -describe('CfEndpointCardComponent', () => { - let component: CfEndpointCardComponent; - let fixture: ComponentFixture; - - beforeEach(async(() => { - TestBed.configureTestingModule({ - imports: [ - createBasicStoreModule(), - SharedModule, - RouterTestingModule, - BaseTestModules, - ], - providers: [ - EntityMonitorFactory, - ServiceActionHelperService - ] - }) - .compileComponents(); - })); - - beforeEach(() => { - fixture = TestBed.createComponent(CfEndpointCardComponent); - component = fixture.componentInstance; - component.row = { - name: 'test', - user: { - admin: false, - name: '', - guid: '', - }, - metricsAvailable: false, - system_shared_token: false, - sso_allowed: false, - }; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/cf-endpoint-card.component.ts b/src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/cf-endpoint-card.component.ts deleted file mode 100644 index 251817764e..0000000000 --- a/src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/cf-endpoint-card.component.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core'; -import { ReplaySubject } from 'rxjs'; - -import { EndpointModel } from '../../../../../../../../store/src/types/endpoint.types'; -import { UserFavoriteEndpoint } from '../../../../../../../../store/src/types/user-favorites.types'; -import { getFavoriteFromEndpointEntity } from '../../../../../../core/user-favorite-helpers'; -import { getEndpointTypes, getFullEndpointApiUrl } from '../../../../../../features/endpoints/endpoint-helpers'; -import { CardStatus } from '../../../../../shared.types'; -import { CardCell } from '../../../list.types'; - - -@Component({ - selector: 'app-cf-endpoint-card', - templateUrl: './cf-endpoint-card.component.html', - styleUrls: ['./cf-endpoint-card.component.scss'] -}) -export class CfEndpointCardComponent extends CardCell implements OnInit, OnChanges { - - static columns = 2; - - public status$ = new ReplaySubject(); - - @Input() - public row: EndpointModel; - public favorite: UserFavoriteEndpoint; - - constructor() { - super(); - } - - ngOnInit() { - this.favorite = getFavoriteFromEndpointEntity(this.row); - this.status$.next(this.mapStatus(this.row)); - } - - ngOnChanges(changes: SimpleChanges) { - const row = changes['row'].currentValue; - this.status$.next(this.mapStatus(row)); - } - - public getEndpointUrl(row: EndpointModel) { - return getFullEndpointApiUrl(row); - } - - public getRouterPath(row: EndpointModel) { - const ext = getEndpointTypes().find(ep => ep.value === row.cnsi_type); - if (ext && ext.homeLink) { - return ext.homeLink(row.guid); - } - return ''; - } - - private mapStatus(endpoint: EndpointModel) { - const connectionStatus = endpoint ? endpoint.connectionStatus : ''; - switch (connectionStatus) { - case 'connected': - return CardStatus.OK; - case 'disconnected': - return CardStatus.INCOMPLETE; - default: - return CardStatus.TENTATIVE; - } - } - -} diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/cf-endpoints-list-config.service.ts b/src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/cf-endpoints-list-config.service.ts index d502af23e4..3289f66c4c 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/cf-endpoints-list-config.service.ts +++ b/src/frontend/packages/core/src/shared/components/list/list-types/cf-endpoints/cf-endpoints-list-config.service.ts @@ -1,18 +1,14 @@ - -import { pairwise } from 'rxjs/operators'; import { Injectable } from '@angular/core'; import { Store } from '@ngrx/store'; +import { AppState } from '../../../../../../../store/src/app-state'; +import { EndpointModel } from '../../../../../../../store/src/types/endpoint.types'; import { ITableColumn } from '../../list-table/table.types'; import { IListConfig, ListViewTypes } from '../../list.component.types'; +import { EndpointCardComponent } from '../endpoint/endpoint-card/endpoint-card.component'; import { endpointColumns } from '../endpoint/endpoints-list-config.service'; -import { EndpointModel, endpointStoreNames } from '../../../../../../../store/src/types/endpoint.types'; -import { selectUpdateInfo } from '../../../../../../../store/src/selectors/api.selectors'; -import { AppState } from '../../../../../../../store/src/app-state'; -import { - BaseEndpointsDataSource -} from './base-endpoints-data-source'; -import { CfEndpointCardComponent } from './cf-endpoint-card/cf-endpoint-card.component'; +import { BaseEndpointsDataSource } from './base-endpoints-data-source'; + @Injectable() export class CFEndpointsListConfigService implements IListConfig { @@ -20,7 +16,7 @@ export class CFEndpointsListConfigService implements IListConfig isLocal = true; dataSource: BaseEndpointsDataSource; viewType = ListViewTypes.CARD_ONLY; - cardComponent = CfEndpointCardComponent; + cardComponent = EndpointCardComponent; text = { title: '', filter: 'Filter Endpoints', @@ -29,21 +25,6 @@ export class CFEndpointsListConfigService implements IListConfig enableTextFilter = true; tableFixedRowHeight = true; - private handleAction(item, effectKey, handleChange) { - const disSub = this.store.select(selectUpdateInfo( - endpointStoreNames.type, - item.guid, - effectKey, - )).pipe( - pairwise()) - .subscribe(([oldVal, newVal]) => { - if (!newVal.error && (oldVal.busy && !newVal.busy)) { - handleChange([oldVal, newVal]); - disSub.unsubscribe(); - } - }); - } - constructor( private store: Store ) { diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.html b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.html index 8fb19c8f88..149988cf4e 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.html +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.html @@ -1,7 +1,5 @@
-
Username: {{ row.user.name}}
-
Admin: - -
+ {{ user.name}} + admin
- \ No newline at end of file diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.scss b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.scss index a10efefd13..4ab451d684 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.scss +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.scss @@ -1,14 +1,7 @@ .cf-details { - padding: 2px 0; - text-align: end; - - &__row { - display: flex; - &-space { - justify-content: space-between; - } - } - &__title { - padding-right: 5px; + align-items: center; + display: flex; + &__admin { + padding-left: 5px; } } diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.ts b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.ts index ee55d42fcc..4696ce448e 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.ts +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.ts @@ -10,5 +10,5 @@ import { TableCellCustom } from '../../../list.types'; }) export class CfEndpointDetailsComponent extends TableCellCustom { - @Input() spaceBetween = false; + @Input() spaceBetween = true; } diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.html b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.html index bd58371675..be5cc29757 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.html +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.html @@ -1,19 +1,26 @@ - +
- {{icon.name}} - {{ row?.name }} +
+ +
+
+ {{ row?.name }} +
{{endpointConfig.label}}
+
- Type - {{ type }} + Status + + + Address {{ address }} - + Details
diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.scss b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.scss index 14abfa84fc..b2b1608beb 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.scss +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.scss @@ -4,11 +4,26 @@ outline: 0; } + &__image { + height: 48px; + margin-right: 10px; + width: 48px; + + &--img { + height: 100%; + width: auto; + } + } + &__title { - align-items: center; display: flex; - mat-icon { - padding-right: 10px; + &__text { + display: flex; + flex-direction: column; + &--subtext { + font-size: 13px; + opacity: .6; + } } } } diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.spec.ts b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.spec.ts index 9d5b445fdf..4fd4b60e59 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.spec.ts +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.spec.ts @@ -5,7 +5,7 @@ import { BaseTestModules } from '../../../../../../../test-framework/cloud-found import { EndpointListHelper } from '../endpoint-list.helpers'; import { EndpointCardComponent } from './endpoint-card.component'; -fdescribe('EndpointCardComponent', () => { +describe('EndpointCardComponent', () => { let component: EndpointCardComponent; let fixture: ComponentFixture; diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.ts b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.ts index 740f27921b..a1f6fb5596 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.ts +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.ts @@ -4,18 +4,16 @@ import { ReplaySubject } from 'rxjs'; import { EndpointModel } from '../../../../../../../../store/src/types/endpoint.types'; import { UserFavoriteEndpoint } from '../../../../../../../../store/src/types/user-favorites.types'; import { EndpointsService } from '../../../../../../core/endpoints.service'; +import { EndpointTypeConfig } from '../../../../../../core/extension/extension-types'; import { getFavoriteFromEndpointEntity } from '../../../../../../core/user-favorite-helpers'; import { - EndpointIcon, endpointListDetailsComponents, getEndpointType, getFullEndpointApiUrl, - getIconForEndpoint, - getNameForEndpointType, } from '../../../../../../features/endpoints/endpoint-helpers'; -import { CardStatus } from '../../../../../shared.types'; import { MetaCardMenuItem } from '../../../list-cards/meta-card/meta-card-base/meta-card.component'; import { CardCell } from '../../../list.types'; +import { BaseEndpointsDataSource } from '../../cf-endpoints/base-endpoints-data-source'; import { CfEndpointDetailsComponent } from '../cf-endpoint-details/cf-endpoint-details.component'; import { EndpointListHelper } from '../endpoint-list.helpers'; @@ -27,13 +25,11 @@ import { EndpointListHelper } from '../endpoint-list.helpers'; }) export class EndpointCardComponent extends CardCell implements OnInit { - public status$ = new ReplaySubject(); public rowObs = new ReplaySubject(); public favorite: UserFavoriteEndpoint; - public type: string; public address: string; public cardMenu: MetaCardMenuItem[]; - public icon: EndpointIcon; + public endpointConfig: EndpointTypeConfig; public hasDetails = true; @Input() component: CfEndpointDetailsComponent; @@ -46,32 +42,40 @@ export class EndpointCardComponent extends CardCell implements On private pRow: EndpointModel; @Input('row') set row(row: EndpointModel) { + if (!row) { + return; + } this.pRow = row; - this.type = row ? getNameForEndpointType(row.cnsi_type) : ''; - this.icon = row ? getIconForEndpoint(row.cnsi_type) : null; - this.address = row ? getFullEndpointApiUrl(row) : ''; - this.status$.next(this.determineEndpointStatus(row)); + this.endpointConfig = getEndpointType(row.cnsi_type); + this.address = getFullEndpointApiUrl(row); this.rowObs.next(row); this.updateDetails(); + } get row(): EndpointModel { return this.pRow; } + @Input('dataSource') + set dataSource(ds: BaseEndpointsDataSource) { + if (ds.endpointType !== 'cf' && !this.cardMenu) { + this.cardMenu = this.endpointListHelper.endpointActions().map(endpointAction => ({ + label: endpointAction.label, + action: () => endpointAction.action(this.pRow), + can: endpointAction.createVisible(this.rowObs) + })); + } + } + constructor( - endpointListHelper: EndpointListHelper, + private endpointListHelper: EndpointListHelper, private componentFactoryResolver: ComponentFactoryResolver ) { super(); - this.cardMenu = endpointListHelper.endpointActions().map(endpointAction => ({ - label: endpointAction.label, - action: () => endpointAction.action(this.pRow), - can: endpointAction.createVisible(this.rowObs) - })); } ngOnInit() { - this.favorite = getFavoriteFromEndpointEntity(this.row); + this.favorite = this.pRow.cnsi_type === 'cf' ? getFavoriteFromEndpointEntity(this.row) : null; const e = getEndpointType(this.pRow.cnsi_type); this.hasDetails = !!e.listDetailsComponent; } @@ -80,21 +84,8 @@ export class EndpointCardComponent extends CardCell implements On return EndpointsService.getLinkForEndpoint(this.row); } - determineEndpointStatus(row: EndpointModel): CardStatus { - switch (row.connectionStatus) { - case 'connected': - return CardStatus.OK; - case 'disconnected': - return CardStatus.TENTATIVE; - case 'checking': - return CardStatus.BUSY; - default: - return CardStatus.INCOMPLETE; - } - } - updateDetails() { - if (!this.endpointDetails) { + if (!this.endpointDetails || !this.pRow) { return; } const e = getEndpointType(this.pRow.cnsi_type); @@ -108,6 +99,6 @@ export class EndpointCardComponent extends CardCell implements On this.component = componentRef.instance as CfEndpointDetailsComponent; } this.component.row = this.pRow; - this.component.spaceBetween = true; + this.component.spaceBetween = false; } } diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-list.helpers.ts b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-list.helpers.ts index 81dd321453..0b2b7a1093 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-list.helpers.ts +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-list.helpers.ts @@ -33,25 +33,6 @@ export class EndpointListHelper { endpointActions(): IListAction[] { return [ - { - action: (item) => { - const confirmation = new ConfirmationDialogConfig( - 'Unregister Endpoint', - `Are you sure you want to unregister endpoint '${item.name}'?`, - 'Unregister', - true - ); - this.confirmDialog.open(confirmation, () => { - this.store.dispatch(new UnregisterEndpoint(item.guid, item.cnsi_type)); - this.handleDeleteAction(item, ([oldVal, newVal]) => { - this.store.dispatch(new ShowSnackBar(`Unregistered ${item.name}`)); - }); - }); - }, - label: 'Unregister', - description: 'Remove the endpoint', - createVisible: () => this.currentUserPermissionsService.can(CurrentUserPermissions.ENDPOINT_REGISTER) - }, { action: (item) => { const confirmation = new ConfirmationDialogConfig( @@ -95,6 +76,25 @@ export class EndpointListHelper { label: 'Connect', description: '', createVisible: (row$: Observable) => row$.pipe(map(row => row.connectionStatus === 'disconnected')) + }, + { + action: (item) => { + const confirmation = new ConfirmationDialogConfig( + 'Unregister Endpoint', + `Are you sure you want to unregister endpoint '${item.name}'?`, + 'Unregister', + true + ); + this.confirmDialog.open(confirmation, () => { + this.store.dispatch(new UnregisterEndpoint(item.guid, item.cnsi_type)); + this.handleDeleteAction(item, ([oldVal, newVal]) => { + this.store.dispatch(new ShowSnackBar(`Unregistered ${item.name}`)); + }); + }); + }, + label: 'Unregister', + description: 'Remove the endpoint', + createVisible: () => this.currentUserPermissionsService.can(CurrentUserPermissions.ENDPOINT_REGISTER) } ]; } diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-status/table-cell-endpoint-status.component.html b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-status/table-cell-endpoint-status.component.html index 4229b14f87..c18d5dd67b 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-status/table-cell-endpoint-status.component.html +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-status/table-cell-endpoint-status.component.html @@ -1,6 +1,6 @@
- cloud_done - cloud_off + cloud_done + cloud_off help_outline -
+ \ No newline at end of file diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-status/table-cell-endpoint-status.component.ts b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-status/table-cell-endpoint-status.component.ts index 883dcfdfe1..74fe3d4bb3 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-status/table-cell-endpoint-status.component.ts +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-status/table-cell-endpoint-status.component.ts @@ -1,5 +1,6 @@ -import { Component } from '@angular/core'; +import { Component, Input } from '@angular/core'; +import { EndpointModel } from '../../../../../../../../store/src/types/endpoint.types'; import { TableCellCustom } from '../../../list.types'; /* tslint:disable:no-access-missing-member https://github.com/mgechev/codelyzer/issues/191*/ @@ -8,4 +9,6 @@ import { TableCellCustom } from '../../../list.types'; templateUrl: './table-cell-endpoint-status.component.html', styleUrls: ['./table-cell-endpoint-status.component.scss'] }) -export class TableCellEndpointStatusComponent extends TableCellCustom { } +export class TableCellEndpointStatusComponent extends TableCellCustom { + @Input() row: EndpointModel; +} diff --git a/src/frontend/packages/core/src/shared/components/list/list.component.spec.ts b/src/frontend/packages/core/src/shared/components/list/list.component.spec.ts index 2a4e9ee933..5a52a6e949 100644 --- a/src/frontend/packages/core/src/shared/components/list/list.component.spec.ts +++ b/src/frontend/packages/core/src/shared/components/list/list.component.spec.ts @@ -15,7 +15,7 @@ import { EntityMonitorFactory } from '../../monitors/entity-monitor.factory.serv import { PaginationMonitorFactory } from '../../monitors/pagination-monitor.factory'; import { SharedModule } from '../../shared.module'; import { ApplicationStateService } from '../application-state/application-state.service'; -import { CfEndpointCardComponent } from './list-types/cf-endpoints/cf-endpoint-card/cf-endpoint-card.component'; +import { EndpointCardComponent } from './list-types/endpoint/endpoint-card/endpoint-card.component'; import { EndpointListHelper } from './list-types/endpoint/endpoint-list.helpers'; import { EndpointsListConfigService } from './list-types/endpoint/endpoints-list-config.service'; import { ListComponent } from './list.component'; @@ -152,7 +152,7 @@ describe('ListComponent', () => { component.config.enableTextFilter = false; component.config.viewType = ListViewTypes.CARD_ONLY; component.config.defaultView = 'card' as ListView; - component.config.cardComponent = CfEndpointCardComponent; + component.config.cardComponent = EndpointCardComponent; component.config.text.title = null; const columns = component.config.getColumns(); columns.forEach(column => column.sort = false); @@ -209,7 +209,7 @@ describe('ListComponent', () => { component.config.enableTextFilter = true; component.config.viewType = ListViewTypes.CARD_ONLY; component.config.defaultView = 'card' as ListView; - component.config.cardComponent = CfEndpointCardComponent; + component.config.cardComponent = EndpointCardComponent; component.config.getColumns = () => [ { columnId: 'filterTestKey', @@ -261,7 +261,7 @@ describe('ListComponent', () => { component.config.enableTextFilter = true; component.config.viewType = ListViewTypes.CARD_ONLY; component.config.defaultView = 'card' as ListView; - component.config.cardComponent = CfEndpointCardComponent; + component.config.cardComponent = EndpointCardComponent; component.config.getColumns = () => [ { columnId: 'filterTestKey', From 9896a961f905b34e6a4836b65bb06e6908141c86 Mon Sep 17 00:00:00 2001 From: Richard Cox Date: Thu, 7 Mar 2019 11:15:19 +0000 Subject: [PATCH 07/20] WIP --- .../cf-endpoint-details.component.html | 14 +++++++++++-- .../cf-endpoint-details.component.scss | 20 ++++++++++++++++--- .../endpoint-card.component.html | 4 ++-- .../endpoint-card.component.scss | 4 +++- .../endpoint-card/endpoint-card.component.ts | 6 ++---- 5 files changed, 36 insertions(+), 12 deletions(-) diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.html b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.html index 149988cf4e..2cc442cef8 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.html +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.html @@ -1,5 +1,15 @@
- {{ user.name}} - admin +
+ + person + + {{ user.name}} +
+
+ + admin + + Administrator +
- \ No newline at end of file diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.scss b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.scss index 4ab451d684..120a562387 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.scss +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.scss @@ -1,7 +1,21 @@ .cf-details { - align-items: center; + align-items: start; display: flex; - &__admin { - padding-left: 5px; + flex-direction: column; + + &__line { + align-items: center; + display: flex; + } + + &__icon { + align-items: center; + display: flex; + justify-content: center; + width: 32px; + + &--admin { + width: 19px; + } } } diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.html b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.html index be5cc29757..77e7396f82 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.html +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.html @@ -1,7 +1,7 @@ - +
-
+
diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.scss b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.scss index b2b1608beb..d9f81e670f 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.scss +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.scss @@ -1,5 +1,8 @@ .endpoint-card { cursor: pointer; + &.no-link { + cursor: default; + } &:focus { outline: 0; } @@ -7,7 +10,6 @@ &__image { height: 48px; margin-right: 10px; - width: 48px; &--img { height: 100%; diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.ts b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.ts index a1f6fb5596..ba3d6e2a39 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.ts +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.ts @@ -31,6 +31,7 @@ export class EndpointCardComponent extends CardCell implements On public cardMenu: MetaCardMenuItem[]; public endpointConfig: EndpointTypeConfig; public hasDetails = true; + public endpointLink: string = null; @Input() component: CfEndpointDetailsComponent; private endpointDetails: ViewContainerRef; @@ -49,6 +50,7 @@ export class EndpointCardComponent extends CardCell implements On this.endpointConfig = getEndpointType(row.cnsi_type); this.address = getFullEndpointApiUrl(row); this.rowObs.next(row); + this.endpointLink = row.connectionStatus === 'connected' ? EndpointsService.getLinkForEndpoint(row) : null this.updateDetails(); } @@ -80,10 +82,6 @@ export class EndpointCardComponent extends CardCell implements On this.hasDetails = !!e.listDetailsComponent; } - getLinkForEndpoint() { - return EndpointsService.getLinkForEndpoint(this.row); - } - updateDetails() { if (!this.endpointDetails || !this.pRow) { return; From 170b3c544922b07c418a07a5b011f531632976d0 Mon Sep 17 00:00:00 2001 From: Richard Cox Date: Thu, 7 Mar 2019 14:05:20 +0000 Subject: [PATCH 08/20] Fix tests --- .../cf-endpoint-details.component.html | 4 +- ...ble-cell-endpoint-status.component.spec.ts | 8 +- .../endpoints/endpoints-connect-e2e.spec.ts | 29 +++-- src/test-e2e/endpoints/endpoints-e2e.spec.ts | 100 ++++++++---------- .../endpoints/endpoints-register-e2e.spec.ts | 6 +- .../endpoints-unregister-e2e.spec.ts | 26 +++-- src/test-e2e/endpoints/endpoints.po.ts | 46 +++++++- .../metrics/metrics-registration-e2e.spec.ts | 6 +- src/test-e2e/po/list.po.ts | 4 +- src/test-e2e/po/meta-card.po.ts | 16 ++- src/test-e2e/po/page-header.po.ts | 12 +-- src/test-e2e/po/snackbar.po.ts | 7 +- 12 files changed, 149 insertions(+), 115 deletions(-) diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.html b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.html index 2cc442cef8..ca3b86a1ff 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.html +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.html @@ -1,13 +1,13 @@
- person + person {{ user.name}}
- admin + admin Administrator
diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-status/table-cell-endpoint-status.component.spec.ts b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-status/table-cell-endpoint-status.component.spec.ts index 37b8fe49dc..2bceee6209 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-status/table-cell-endpoint-status.component.spec.ts +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-status/table-cell-endpoint-status.component.spec.ts @@ -1,12 +1,12 @@ -import { CoreModule } from '../../../../../../core/core.module'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { TableCellEndpointStatusComponent } from './table-cell-endpoint-status.component'; import { EndpointModel } from '../../../../../../../../store/src/types/endpoint.types'; +import { CoreModule } from '../../../../../../core/core.module'; +import { TableCellEndpointStatusComponent } from './table-cell-endpoint-status.component'; describe('TableCellEndpointStatusComponent', () => { - let component: TableCellEndpointStatusComponent<{}>; - let fixture: ComponentFixture>; + let component: TableCellEndpointStatusComponent; + let fixture: ComponentFixture; beforeEach(async(() => { TestBed.configureTestingModule({ diff --git a/src/test-e2e/endpoints/endpoints-connect-e2e.spec.ts b/src/test-e2e/endpoints/endpoints-connect-e2e.spec.ts index 58cf8d0843..25f6ca63ce 100644 --- a/src/test-e2e/endpoints/endpoints-connect-e2e.spec.ts +++ b/src/test-e2e/endpoints/endpoints-connect-e2e.spec.ts @@ -32,20 +32,18 @@ describe('Endpoints', () => { connectDialog.snackBar.waitForMessage('There are no connected endpoints, connect with your personal credentials to get started.'); connectDialog.snackBar.safeClose(); - // Get the row in the table for this endpoint - endpointsPage.table.getRowForEndpoint(toConnect.name).then(row => { - endpointsPage.table.openRowActionMenuByRow(row); - const menu = new MenuComponent(); - menu.waitUntilShown(); - return menu.getItemMap().then(items => { - expect(items['connect']).toBeDefined(); - items['connect'].click(); + + endpointsPage.cards.findCardByTitle(toConnect.name) + .then(card => card.openActionMenu()) + .then(actionMenu => actionMenu.getItem('Connect')) + .then(connect => { + expect(connect).toBeDefined(); + connect.click(); connectDialog.waitUntilShown(); // Connect dialog should be shown expect(connectDialog.isPresent()).toBeTruthy(); expect(connectDialog.isDisplayed()).toBeTruthy(); }); - }); }); it('should have empty username and password fields in the form', () => { @@ -75,13 +73,14 @@ describe('Endpoints', () => { connectDialog.connect(); // Wait for snackbar connectDialog.snackBar.waitForMessage(`Connected endpoint '${toConnect.name}'`); - endpointsPage.table.getEndpointDataForEndpoint(toConnect.name).then((ep: EndpointMetadata) => { + endpointsPage.cards.getEndpointDataForEndpoint(toConnect.name).then((ep: EndpointMetadata) => { + console.log('EP: ', ep); expect(ep).toBeDefined(); expect(ep.connected).toBeTruthy(); }); connectDialog.waitUntilNotShown(); - endpointsPage.table.getRowForEndpoint(toConnect.name).then(row => { - endpointsPage.table.openRowActionMenuByRow(row); + endpointsPage.cards.findCardByTitle(toConnect.name).then(card => { + card.openActionMenu(); const menu = new MenuComponent(); menu.waitUntilShown('Endpoint Action Menu'); return menu.getItemMap().then(items => { @@ -126,8 +125,8 @@ describe('Endpoints', () => { it('should update row in table when disconnected', () => { endpointsPage.navigateTo(); - endpointsPage.table.getRowForEndpoint(toDisconnect.name).then(row => { - endpointsPage.table.openRowActionMenuByRow(row); + endpointsPage.cards.findCardByTitle(toDisconnect.name).then(card => { + card.openActionMenu(); const menu = new MenuComponent(); menu.waitUntilShown(); return menu.getItemMap().then(items => { @@ -140,7 +139,7 @@ describe('Endpoints', () => { const snackBar = new SnackBarComponent(); snackBar.waitUntilShown(); expect(endpointsPage.isNoneConnectedSnackBar(snackBar)).toBeTruthy(); - endpointsPage.table.getEndpointDataForEndpoint(toDisconnect.name).then((data: EndpointMetadata) => { + endpointsPage.cards.getEndpointDataForEndpoint(toDisconnect.name).then((data: EndpointMetadata) => { expect(data.connected).toBeFalsy(); }); }); diff --git a/src/test-e2e/endpoints/endpoints-e2e.spec.ts b/src/test-e2e/endpoints/endpoints-e2e.spec.ts index 5dd9a01cd3..9821680a10 100644 --- a/src/test-e2e/endpoints/endpoints-e2e.spec.ts +++ b/src/test-e2e/endpoints/endpoints-e2e.spec.ts @@ -2,19 +2,17 @@ import { ApplicationsPage } from '../applications/applications.po'; import { CfTopLevelPage } from '../cloud-foundry/cf-level/cf-top-level-page.po'; import { e2e } from '../e2e'; import { ConsoleUserType } from '../helpers/e2e-helpers'; -import { LoginPage } from '../login/login.po'; import { MenuComponent } from '../po/menu.po'; import { SideNavMenuItem } from '../po/side-nav.po'; import { SnackBarComponent } from '../po/snackbar.po'; import { ServicesPage } from '../services/services.po'; -import { EndpointMetadata, EndpointsPage } from './endpoints.po'; +import { EndpointsPage } from './endpoints.po'; describe('Endpoints', () => { const endpointsPage = new EndpointsPage(); const applications = new ApplicationsPage(); const services = new ServicesPage(); const cloudFoundry = new CfTopLevelPage(); - const login = new LoginPage(); describe('Workflow on log in (admin/non-admin + no endpoints/some endpoints) -', () => { describe('As Admin -', () => { @@ -90,63 +88,53 @@ describe('Endpoints', () => { describe('Some registered endpoints -', () => { beforeAll(() => { - beforeAll(() => { - e2e.setup(ConsoleUserType.user) - .clearAllEndpoints() - .registerDefaultCloudFoundry(); + e2e.setup(ConsoleUserType.user) + .clearAllEndpoints() + .registerDefaultCloudFoundry(); + }); + + describe('endpoints table -', () => { + it('should be displayed', () => { + expect(endpointsPage.isActivePage()).toBeTruthy(); }); - describe('endpoints table -', () => { - it('should be displayed', () => { - expect(endpointsPage.isActivePage()).toBeTruthy(); - }); - - it('should not show register button', () => { - expect(endpointsPage.header.hasIconButton('add')).toBeFalsy(); - }); - - it('should show at least one endpoint', () => { - expect(endpointsPage.list.isDisplayed).toBeTruthy(); - expect(endpointsPage.list.isTableView()).toBeTruthy(); - expect(endpointsPage.list.table.getRows().count()).toBeGreaterThan(0); - }); - - it('should show correct table content', () => { - // For each endpoint - // 1) we show the correct type - // 2) the icon is the correct 'disconnected' one - // 3) the address is correct - // 4) the 'connect' button is available in the action menu - - const endpointsTable = endpointsPage.table; - endpointsTable.getRows().map(row => endpointsTable.getEndpointData(row)).then(data => { - data.forEach((ep: EndpointMetadata) => { - const endpointConfig = e2e.secrets.getEndpointByName(ep.name); - expect(endpointConfig).not.toBeNull(); - expect(endpointConfig.url).toEqual(ep.url); - expect(endpointConfig.typeLabel).toEqual(ep.type); - - endpointsPage.table.getRowForEndpoint(ep.name).then(row => { - endpointsPage.table.openRowActionMenuByRow(row); - const menu = new MenuComponent(); - menu.waitUntilShown(); - menu.getItemMap().then(items => { - expect(items['connect']).toBeDefined(); - expect(items['disconnect']).not.toBeDefined(); - }); - menu.close(); - }); + it('should not show register button', () => { + expect(endpointsPage.header.hasIconButton('add')).toBeFalsy(); + }); + + it('should show at least one endpoint', () => { + expect(endpointsPage.list.isDisplayed).toBeTruthy(); + expect(endpointsPage.list.isCardsView()).toBeTruthy(); + expect(endpointsPage.list.cards.getCardCount()).toBe(1); + }); + + it('should show correct cards content', () => { + const cf = e2e.secrets.getDefaultCFEndpoint().name; + return endpointsPage.cards.getEndpointDataForEndpoint(cf).then(ep => { + const endpointConfig = e2e.secrets.getEndpointByName(ep.name); + expect(endpointConfig).not.toBeNull(); + expect(endpointConfig.url).toEqual(ep.url); + expect(endpointConfig.typeLabel).toEqual(ep.type); + + return endpointsPage.cards.findCardByTitle(ep.name).then(card => { + card.openActionMenu(); + const menu = new MenuComponent(); + menu.waitUntilShown(); + menu.getItemMap().then(items => { + expect(items['connect']).toBeDefined(); + expect(items['disconnect']).not.toBeDefined(); }); + return menu.close(); }); - }); - - it('Welcome snackbar message should be displayed', () => { - endpointsPage.sideNav.goto(SideNavMenuItem.Endpoints); - const snackBar = new SnackBarComponent(); - expect(snackBar.isDisplayed()).toBeTruthy(); - expect(endpointsPage.isNoneConnectedSnackBar(snackBar)).toBeTruthy(); - snackBar.close(); - }); + }) + }); + + it('Welcome snackbar message should be displayed', () => { + endpointsPage.sideNav.goto(SideNavMenuItem.Endpoints); + const snackBar = new SnackBarComponent(); + expect(snackBar.isDisplayed()).toBeTruthy(); + expect(endpointsPage.isNoneConnectedSnackBar(snackBar)).toBeTruthy(); + snackBar.close(); }); }); }); diff --git a/src/test-e2e/endpoints/endpoints-register-e2e.spec.ts b/src/test-e2e/endpoints/endpoints-register-e2e.spec.ts index 7dfbb283b6..ae7f2130b8 100644 --- a/src/test-e2e/endpoints/endpoints-register-e2e.spec.ts +++ b/src/test-e2e/endpoints/endpoints-register-e2e.spec.ts @@ -155,7 +155,7 @@ describe('Endpoints', () => { expect(snackBar.hasMessage('SSL error - x509: certificate')).toBeTruthy(); /* tslint:disable-line:max-line-length*/ expect(snackBar.messageContains('Please check "Skip SSL validation for the endpoint" if the certificate issuer is trusted"')) - .toBeTruthy(); + .toBeTruthy(); }); it('Successful register', () => { @@ -169,9 +169,9 @@ describe('Endpoints', () => { register.stepper.next(); expect(endpointsPage.isActivePage()).toBeTruthy(); - expect(endpointsPage.table.isPresent()).toBeTruthy(); + expect(endpointsPage.cards.isPresent()).toBeTruthy(); - endpointsPage.table.getEndpointDataForEndpoint(validEndpoint.name).then((data: EndpointMetadata) => { + endpointsPage.cards.getEndpointDataForEndpoint(validEndpoint.name).then((data: EndpointMetadata) => { expect(data.name).toEqual(validEndpoint.name); expect(data.url).toEqual(validEndpoint.url); expect(data.connected).toBeFalsy(); diff --git a/src/test-e2e/endpoints/endpoints-unregister-e2e.spec.ts b/src/test-e2e/endpoints/endpoints-unregister-e2e.spec.ts index 683f4df46c..2362f6773f 100644 --- a/src/test-e2e/endpoints/endpoints-unregister-e2e.spec.ts +++ b/src/test-e2e/endpoints/endpoints-unregister-e2e.spec.ts @@ -26,16 +26,16 @@ describe('Endpoints', () => { expect(endpointsPage.isActivePage()).toBeTruthy(); // Should have a single row initially - endpointsPage.table.getRows().then(rows => { expect(rows.length).toBe(1); }); + expect(endpointsPage.cards.getCardCount()).toBe(1); // Get the row in the table for this endpoint - endpointsPage.table.getRowForEndpoint(toUnregister.name).then(row => { - endpointsPage.table.openRowActionMenuByRow(row); + endpointsPage.cards.findCardByTitle(toUnregister.name).then(card => { + card.openActionMenu(); const menu = new MenuComponent(); menu.waitUntilShown(); menu.clickItem('Unregister'); ConfirmDialogComponent.expectDialogAndConfirm('Unregister', 'Unregister Endpoint'); - endpointsPage.table.waitUntilNotBusy(); + endpointsPage.list.waitForNoLoadingIndicator(); // Should have removed the only row, so we should see welcome message again expect(endpointsPage.isWelcomeMessageAdmin()).toBeTruthy(); }); @@ -56,19 +56,17 @@ describe('Endpoints', () => { // Current number of rows let endpointCount = 0; - endpointsPage.table.getRows().then(rows => endpointCount = rows.length); + endpointsPage.cards.getCardCount().then(count => endpointCount = count); // Get the row in the table for this endpoint - endpointsPage.table.getRowForEndpoint(toUnregister.name).then(row => { - endpointsPage.table.openRowActionMenuByRow(row); + endpointsPage.cards.findCardByTitle(toUnregister.name).then(card => { + card.openActionMenu(); const menu = new MenuComponent(); menu.waitUntilShown(); menu.clickItem('Unregister'); ConfirmDialogComponent.expectDialogAndConfirm('Unregister', 'Unregister Endpoint'); - endpointsPage.table.waitUntilNotBusy(); - endpointsPage.table.getRows().then(rows => { - expect(rows.length).toBe(endpointCount - 1); - }); + endpointsPage.list.waitForNoLoadingIndicator(); + expect(endpointsPage.cards.getCardCount()).toBe(endpointCount - 1); }); }); }); @@ -86,11 +84,11 @@ describe('Endpoints', () => { expect(endpointsPage.isActivePage()).toBeTruthy(); // Should have a single row initially - endpointsPage.table.getRows().then(rows => { expect(rows.length).toBe(1); }); + expect(endpointsPage.cards.getCardCount()).toBe(1); // Get the row in the table for this endpoint - endpointsPage.table.getRowForEndpoint(toUnregister.name).then(row => { - endpointsPage.table.openRowActionMenuByRow(row); + endpointsPage.cards.findCardByTitle(toUnregister.name).then(card => { + card.openActionMenu(); const menu = new MenuComponent(); menu.waitUntilShown(); menu.getItemMap().then(items => { diff --git a/src/test-e2e/endpoints/endpoints.po.ts b/src/test-e2e/endpoints/endpoints.po.ts index a39d2cbda7..d57a0a9070 100644 --- a/src/test-e2e/endpoints/endpoints.po.ts +++ b/src/test-e2e/endpoints/endpoints.po.ts @@ -1,19 +1,58 @@ -import { browser, by, element } from 'protractor'; +import { browser, by, element, promise, protractor } from 'protractor'; import { ElementFinder } from 'protractor/built'; import { E2EEndpointConfig } from '../e2e.types'; import { ConsoleUserType, E2EHelpers } from '../helpers/e2e-helpers'; -import { ListComponent, ListTableComponent } from '../po/list.po'; +import { ListCardComponent, ListComponent, ListHeaderComponent, ListTableComponent } from '../po/list.po'; +import { MetaCard, MetaCardItem } from '../po/meta-card.po'; import { Page } from '../po/page.po'; import { SnackBarComponent } from '../po/snackbar.po'; +const until = protractor.ExpectedConditions; + +export class EndpointCards extends ListCardComponent { + constructor(locator: ElementFinder, header: ListHeaderComponent) { + super(locator, header); + } + + findCardByTitle(title: string, subtitle = 'Cloud Foundry'): promise.Promise { + return super.findCardByTitle(`${title}\n${subtitle}`); + } + + getEndpointDataForEndpoint(title: string, subtitle = 'Cloud Foundry'): promise.Promise { + return this.findCardByTitle(title, subtitle).then(card => this.getEndpointData(card)) + } + + getEndpointData(card: MetaCard): promise.Promise { + const title = card.getTitle(); + const metaCardItems = card.getMetaCardItemsAsText() + return promise.all[]>([ + title, + metaCardItems + ]).then(([t, m]: [string, MetaCardItem[]]) => { + const details = m.find(item => item.key === 'Details'); + const safeDetails = details ? details.value : ''; + const cleanDetails = safeDetails.split('\n'); + return { + name: t.substring(0, t.indexOf('\n')), + connected: m.find(item => item.key === 'Status').value === 'cloud_done', + type: t.substring(t.indexOf('\n') + 1, t.length), + user: cleanDetails[1], + isAdmin: safeDetails.length > 2, + url: m.find(item => item.key === 'Address').value, + // favorite: data[6] + } as EndpointMetadata; + }) + } +} + export class EndpointsTable extends ListTableComponent { constructor(locator: ElementFinder) { super(locator); } - getEndpointData(row: ElementFinder) { + getEndpointData(row: ElementFinder): promise.Promise { // Get all of the columns return row.all(by.tagName('app-table-cell')).map(col => col.getText()).then((data: string[]) => { return { @@ -65,6 +104,7 @@ export class EndpointsPage extends Page { // Endpoints table (as opposed to generic list.table) public table = new EndpointsTable(this.list.getComponent()); + public cards = new EndpointCards(this.list.locator, this.list.header); constructor() { super('/endpoints'); diff --git a/src/test-e2e/metrics/metrics-registration-e2e.spec.ts b/src/test-e2e/metrics/metrics-registration-e2e.spec.ts index 3bead4f90a..0536aa7ded 100644 --- a/src/test-e2e/metrics/metrics-registration-e2e.spec.ts +++ b/src/test-e2e/metrics/metrics-registration-e2e.spec.ts @@ -45,10 +45,10 @@ describe('Metrics', () => { // Check that we have one row expect(endpointsPage.isActivePage()).toBeTruthy(); - expect(endpointsPage.table.isPresent()).toBeTruthy(); + expect(endpointsPage.cards.isPresent()).toBeTruthy(); - expect(endpointsPage.table.getRows().count()).toBe(1); - endpointsPage.table.getEndpointDataForEndpoint('MetricsTest').then((data: EndpointMetadata) => { + expect(endpointsPage.cards.getCardCount()).toBe(1); + endpointsPage.cards.getEndpointDataForEndpoint('MetricsTest', 'Metrics').then((data: EndpointMetadata) => { expect(data.name).toEqual('MetricsTest'); expect(data.url).toEqual('https://www.google.com'); expect(data.connected).toBeFalsy(); diff --git a/src/test-e2e/po/list.po.ts b/src/test-e2e/po/list.po.ts index 002b4dcb30..b8963e0a99 100644 --- a/src/test-e2e/po/list.po.ts +++ b/src/test-e2e/po/list.po.ts @@ -142,7 +142,7 @@ export class ListCardComponent extends Component { } private findCardElementByTitle(title: string, metaType = MetaCardTitleType.CUSTOM): ElementFinder { - const card = this.locator.all(by.cssContainingText(`${ListCardComponent.cardsCss} ${metaType}`, title)).filter(elem => + const card = this.locator.all(by.css(`${ListCardComponent.cardsCss} ${metaType}`)).filter(elem => elem.getText().then(text => text === title) ).first(); browser.wait(until.presenceOf(card)); @@ -426,7 +426,7 @@ export class ListComponent extends Component { public empty: ListEmptyComponent; - constructor(locator: ElementFinder = element(by.tagName('app-list'))) { + constructor(public locator: ElementFinder = element(by.tagName('app-list'))) { super(locator); this.table = new ListTableComponent(locator); this.header = new ListHeaderComponent(locator); diff --git a/src/test-e2e/po/meta-card.po.ts b/src/test-e2e/po/meta-card.po.ts index 5f4bcaaf03..59e6b80a3e 100644 --- a/src/test-e2e/po/meta-card.po.ts +++ b/src/test-e2e/po/meta-card.po.ts @@ -17,9 +17,9 @@ export enum MetaCardTitleType { CUSTOM = '.meta-card__title' } -export interface MetaCardItem { - key: promise.Promise; - value: promise.Promise; +export interface MetaCardItem> { + key: T; + value: T; } export class MetaCard extends Component { @@ -64,6 +64,16 @@ export class MetaCard extends Component { }))); } + getMetaCardItemsAsText(): promise.Promise[]> { + return this.getMetaCardItems() + .then((rows: MetaCardItem[]) => rows.map(row => promise.all([row.key, row.value]))) + .then(promises => promise.all(promises)) + .then(res => res.map(a => ({ + key: a[0].replace(':', ''), + value: a[1] + }))); + } + click() { return this.elementFinder.click(); } diff --git a/src/test-e2e/po/page-header.po.ts b/src/test-e2e/po/page-header.po.ts index dbebc4420f..dea1f3713e 100644 --- a/src/test-e2e/po/page-header.po.ts +++ b/src/test-e2e/po/page-header.po.ts @@ -20,12 +20,12 @@ export class PageHeader extends Component { } getIconButton(iconName: string) { - return this.getIconButtons().map(button => { - return button.getText(); - }).then(icons => { - const index = icons.findIndex(name => name === iconName); - return this.getIconButtons().get(index); - }); + return this.getIconButtons() + .map(button => button.getText()) + .then(icons => { + const index = icons.findIndex(name => name === iconName); + return index >= 0 ? this.getIconButtons().get(index) : null; + }); } clickIconButton(iconName: string): promise.Promise { diff --git a/src/test-e2e/po/snackbar.po.ts b/src/test-e2e/po/snackbar.po.ts index dd80cd0525..6482a5f1f7 100644 --- a/src/test-e2e/po/snackbar.po.ts +++ b/src/test-e2e/po/snackbar.po.ts @@ -1,5 +1,4 @@ -import { by, element, ElementFinder } from 'protractor'; -import { browser, promise } from 'protractor'; +import { browser, by, element, ElementFinder, promise } from 'protractor'; import { protractor } from 'protractor/built'; import { Component } from './component.po'; @@ -55,8 +54,8 @@ export class SnackBarComponent extends Component { // Wait for snackbar with given message waitForMessage(message): promise.Promise { const mesgElm = element(by.cssContainingText('.mat-simple-snackbar', message)); - return browser.wait(until.presenceOf(mesgElm), 5000, - 'Snackbar: ' + message + ' taking too long to appear in the DOM').then(() => { + return browser.wait(until.presenceOf(mesgElm), 10000, + 'Snackbar: "' + message + '" taking too long to appear in the DOM').then(() => { return browser.driver.sleep(100); }); } From dccb9fc4e50ada9032532ee2cb10dbb4709a0133 Mon Sep 17 00:00:00 2001 From: Richard Cox Date: Thu, 7 Mar 2019 14:30:46 +0000 Subject: [PATCH 09/20] Tweak cf details --- .../cf-endpoint-details.component.html | 6 +++--- .../cf-endpoint-details.component.scss | 6 +++--- src/test-e2e/endpoints/endpoints.po.ts | 8 ++++++-- src/test-e2e/po/page-header.po.ts | 4 ++-- 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.html b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.html index ca3b86a1ff..b8387d2f7b 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.html +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.html @@ -3,13 +3,13 @@ person - {{ user.name}} + {{ user.name}} (Administrator)
-
+
- \ No newline at end of file diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.scss b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.scss index 120a562387..3c48fcd8b3 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.scss +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.scss @@ -14,8 +14,8 @@ justify-content: center; width: 32px; - &--admin { - width: 19px; - } + // &--admin { + // width: 19px; + // } } } diff --git a/src/test-e2e/endpoints/endpoints.po.ts b/src/test-e2e/endpoints/endpoints.po.ts index d57a0a9070..7ee8a6d608 100644 --- a/src/test-e2e/endpoints/endpoints.po.ts +++ b/src/test-e2e/endpoints/endpoints.po.ts @@ -31,14 +31,18 @@ export class EndpointCards extends ListCardComponent { metaCardItems ]).then(([t, m]: [string, MetaCardItem[]]) => { const details = m.find(item => item.key === 'Details'); + // Protect against zero details const safeDetails = details ? details.value : ''; + // If we have details, assume they're cf details const cleanDetails = safeDetails.split('\n'); + const user = cleanDetails[1] ? cleanDetails[1].replace(' (Administrator)', '') : '' + const isAdmin = safeDetails.endsWith(' (Administrator)') return { name: t.substring(0, t.indexOf('\n')), connected: m.find(item => item.key === 'Status').value === 'cloud_done', type: t.substring(t.indexOf('\n') + 1, t.length), - user: cleanDetails[1], - isAdmin: safeDetails.length > 2, + user, + isAdmin, url: m.find(item => item.key === 'Address').value, // favorite: data[6] } as EndpointMetadata; diff --git a/src/test-e2e/po/page-header.po.ts b/src/test-e2e/po/page-header.po.ts index dea1f3713e..ac697fdbb9 100644 --- a/src/test-e2e/po/page-header.po.ts +++ b/src/test-e2e/po/page-header.po.ts @@ -19,12 +19,12 @@ export class PageHeader extends Component { return this.locator.all(by.css('.page-header button.mat-icon-button')); } - getIconButton(iconName: string) { + getIconButton(iconName: string): promise.Promise { return this.getIconButtons() .map(button => button.getText()) .then(icons => { const index = icons.findIndex(name => name === iconName); - return index >= 0 ? this.getIconButtons().get(index) : null; + return this.getIconButtons().get(index); }); } From 9f9bcea825e194d347baafb946fc0ad3dca46ff1 Mon Sep 17 00:00:00 2001 From: Richard Cox Date: Thu, 7 Mar 2019 14:41:30 +0000 Subject: [PATCH 10/20] Fix linting --- .../endpoint/endpoint-card/endpoint-card.component.ts | 2 +- src/test-e2e/endpoints/endpoints-connect-e2e.spec.ts | 1 - src/test-e2e/endpoints/endpoints-e2e.spec.ts | 2 +- src/test-e2e/endpoints/endpoints.po.ts | 10 +++++----- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.ts b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.ts index ba3d6e2a39..c05cced76d 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.ts +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.ts @@ -50,7 +50,7 @@ export class EndpointCardComponent extends CardCell implements On this.endpointConfig = getEndpointType(row.cnsi_type); this.address = getFullEndpointApiUrl(row); this.rowObs.next(row); - this.endpointLink = row.connectionStatus === 'connected' ? EndpointsService.getLinkForEndpoint(row) : null + this.endpointLink = row.connectionStatus === 'connected' ? EndpointsService.getLinkForEndpoint(row) : null; this.updateDetails(); } diff --git a/src/test-e2e/endpoints/endpoints-connect-e2e.spec.ts b/src/test-e2e/endpoints/endpoints-connect-e2e.spec.ts index 25f6ca63ce..37da1f3b3a 100644 --- a/src/test-e2e/endpoints/endpoints-connect-e2e.spec.ts +++ b/src/test-e2e/endpoints/endpoints-connect-e2e.spec.ts @@ -74,7 +74,6 @@ describe('Endpoints', () => { // Wait for snackbar connectDialog.snackBar.waitForMessage(`Connected endpoint '${toConnect.name}'`); endpointsPage.cards.getEndpointDataForEndpoint(toConnect.name).then((ep: EndpointMetadata) => { - console.log('EP: ', ep); expect(ep).toBeDefined(); expect(ep.connected).toBeTruthy(); }); diff --git a/src/test-e2e/endpoints/endpoints-e2e.spec.ts b/src/test-e2e/endpoints/endpoints-e2e.spec.ts index 9821680a10..4211654685 100644 --- a/src/test-e2e/endpoints/endpoints-e2e.spec.ts +++ b/src/test-e2e/endpoints/endpoints-e2e.spec.ts @@ -126,7 +126,7 @@ describe('Endpoints', () => { }); return menu.close(); }); - }) + }); }); it('Welcome snackbar message should be displayed', () => { diff --git a/src/test-e2e/endpoints/endpoints.po.ts b/src/test-e2e/endpoints/endpoints.po.ts index 7ee8a6d608..be031e9085 100644 --- a/src/test-e2e/endpoints/endpoints.po.ts +++ b/src/test-e2e/endpoints/endpoints.po.ts @@ -20,12 +20,12 @@ export class EndpointCards extends ListCardComponent { } getEndpointDataForEndpoint(title: string, subtitle = 'Cloud Foundry'): promise.Promise { - return this.findCardByTitle(title, subtitle).then(card => this.getEndpointData(card)) + return this.findCardByTitle(title, subtitle).then(card => this.getEndpointData(card)); } getEndpointData(card: MetaCard): promise.Promise { const title = card.getTitle(); - const metaCardItems = card.getMetaCardItemsAsText() + const metaCardItems = card.getMetaCardItemsAsText(); return promise.all[]>([ title, metaCardItems @@ -35,8 +35,8 @@ export class EndpointCards extends ListCardComponent { const safeDetails = details ? details.value : ''; // If we have details, assume they're cf details const cleanDetails = safeDetails.split('\n'); - const user = cleanDetails[1] ? cleanDetails[1].replace(' (Administrator)', '') : '' - const isAdmin = safeDetails.endsWith(' (Administrator)') + const user = cleanDetails[1] ? cleanDetails[1].replace(' (Administrator)', '') : ''; + const isAdmin = safeDetails.endsWith(' (Administrator)'); return { name: t.substring(0, t.indexOf('\n')), connected: m.find(item => item.key === 'Status').value === 'cloud_done', @@ -46,7 +46,7 @@ export class EndpointCards extends ListCardComponent { url: m.find(item => item.key === 'Address').value, // favorite: data[6] } as EndpointMetadata; - }) + }); } } From cfa88910cf30ead0960f5549b1eadc3849be90ae Mon Sep 17 00:00:00 2001 From: Richard Cox Date: Thu, 7 Mar 2019 16:09:16 +0000 Subject: [PATCH 11/20] Fix existing getIconButton bug - There may be other places where this magically worked and now correctly won't --- .../page-header/page-header.component.html | 5 ++-- .../endpoints/endpoints-connect-e2e.spec.ts | 25 +++++++++---------- src/test-e2e/endpoints/endpoints.po.ts | 4 +-- src/test-e2e/po/page-header.po.ts | 20 ++++++++------- 4 files changed, 26 insertions(+), 28 deletions(-) diff --git a/src/frontend/packages/core/src/shared/components/page-header/page-header.component.html b/src/frontend/packages/core/src/shared/components/page-header/page-header.component.html index c399540a19..ac481e1c18 100644 --- a/src/frontend/packages/core/src/shared/components/page-header/page-header.component.html +++ b/src/frontend/packages/core/src/shared/components/page-header/page-header.component.html @@ -9,8 +9,7 @@
- {{ breadcrumbDef.value }} + {{ breadcrumbDef.value }} {{ breadcrumbDef.value }} chevron_right @@ -40,7 +39,7 @@

Recent

- diff --git a/src/test-e2e/endpoints/endpoints-connect-e2e.spec.ts b/src/test-e2e/endpoints/endpoints-connect-e2e.spec.ts index 37da1f3b3a..24c9811c8c 100644 --- a/src/test-e2e/endpoints/endpoints-connect-e2e.spec.ts +++ b/src/test-e2e/endpoints/endpoints-connect-e2e.spec.ts @@ -69,7 +69,7 @@ describe('Endpoints', () => { expect(connectDialog.canConnect()).toBeTruthy(); }); - it('should update service instance data on register', () => { + it('should update endpoints data on register', () => { connectDialog.connect(); // Wait for snackbar connectDialog.snackBar.waitForMessage(`Connected endpoint '${toConnect.name}'`); @@ -78,19 +78,18 @@ describe('Endpoints', () => { expect(ep.connected).toBeTruthy(); }); connectDialog.waitUntilNotShown(); - endpointsPage.cards.findCardByTitle(toConnect.name).then(card => { - card.openActionMenu(); - const menu = new MenuComponent(); - menu.waitUntilShown('Endpoint Action Menu'); - return menu.getItemMap().then(items => { - expect(items['connect']).not.toBeDefined(); - expect(items['disconnect']).toBeDefined(); - // Only admins can unregister - expect(items['unregister']).not.toBeDefined(); - return menu.close(); + endpointsPage.cards.findCardByTitle(toConnect.name) + .then(card => card.openActionMenu()) + .then(menu => { + menu.waitUntilShown('Endpoint Action Menu'); + return menu.getItemMap().then(items => { + expect(items['connect']).not.toBeDefined(); + expect(items['disconnect']).toBeDefined(); + // Only admins can unregister + expect(items['unregister']).not.toBeDefined(); + return menu.close(); + }); }); - - }); }); // NOTE: We connected as the User not the Admin, so logging in as admin will NOT have the endpoint connected diff --git a/src/test-e2e/endpoints/endpoints.po.ts b/src/test-e2e/endpoints/endpoints.po.ts index be031e9085..e53a61b6d3 100644 --- a/src/test-e2e/endpoints/endpoints.po.ts +++ b/src/test-e2e/endpoints/endpoints.po.ts @@ -1,4 +1,4 @@ -import { browser, by, element, promise, protractor } from 'protractor'; +import { browser, by, element, promise } from 'protractor'; import { ElementFinder } from 'protractor/built'; import { E2EEndpointConfig } from '../e2e.types'; @@ -8,8 +8,6 @@ import { MetaCard, MetaCardItem } from '../po/meta-card.po'; import { Page } from '../po/page.po'; import { SnackBarComponent } from '../po/snackbar.po'; -const until = protractor.ExpectedConditions; - export class EndpointCards extends ListCardComponent { constructor(locator: ElementFinder, header: ListHeaderComponent) { super(locator, header); diff --git a/src/test-e2e/po/page-header.po.ts b/src/test-e2e/po/page-header.po.ts index ac697fdbb9..6ba30f26ad 100644 --- a/src/test-e2e/po/page-header.po.ts +++ b/src/test-e2e/po/page-header.po.ts @@ -24,7 +24,7 @@ export class PageHeader extends Component { .map(button => button.getText()) .then(icons => { const index = icons.findIndex(name => name === iconName); - return this.getIconButtons().get(index); + return index >= 0 ? this.getIconButtons().get(index) : null; }); } @@ -51,14 +51,16 @@ export class PageHeader extends Component { } logout(): promise.Promise { - return this.clickIconButton('more_vert').then(() => { - browser.driver.sleep(2000); - const menu = new MenuComponent(); - menu.waitUntilShown(); - menu.clickItem('Logout'); - browser.driver.sleep(2000); - return browser.waitForAngular(); - }); + return this.locator.element(by.id('userMenu')) + .click() + .then(() => { + // browser.driver.sleep(2000); + const menu = new MenuComponent(); + menu.waitUntilShown(); + menu.clickItem('Logout'); + // browser.driver.sleep(2000); + return browser.waitForAngular(); + }); } } From e9cd91dbbe2e433e44caaf8986511b2559198d49 Mon Sep 17 00:00:00 2001 From: Richard Cox Date: Thu, 7 Mar 2019 16:55:35 +0000 Subject: [PATCH 12/20] Missing images --- .../assets/endpoint-icons/cloudfoundry.png | Bin 0 -> 3881 bytes .../core/assets/endpoint-icons/metrics.svg | 50 ++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 src/frontend/packages/core/assets/endpoint-icons/cloudfoundry.png create mode 100644 src/frontend/packages/core/assets/endpoint-icons/metrics.svg diff --git a/src/frontend/packages/core/assets/endpoint-icons/cloudfoundry.png b/src/frontend/packages/core/assets/endpoint-icons/cloudfoundry.png new file mode 100644 index 0000000000000000000000000000000000000000..cc022705d57e03d8be5b63d52343da6337982482 GIT binary patch literal 3881 zcmV+^57zLBP)WFU8GbZ8()Nlj2>E@cM*01k~wL_t(|+U=WrlvKr? z$3Imwz%V=nm8Z@|6JUKMnvi9g0*!(ZBCczKh$bc>3c>XmjJk`<9v^3s<6;1jL{W~$ zH75sM!ChV0tV(BZYQ-UF#u!8-{eM@W2T%p{0=@wB0W6RQ-UmJgazK-a>@U^V!8CQSpn$?; zj4>wyV}LV&lYpT>w~Q{{1Kt4ycwR(S9ZHbu5J~PdU^Xxs=n3dfbaMdM49pRc2M+~6 zbucPuj5!9l4Y-^`+g=Bz0k4XP?QAC%9etp_zCHnVIq(bMOb&e;5Ww}Tsi~3r`uZkg zOkwQ9BDr8=3b;2&tCGXt-U3b+k!>ASQ{55b0J;D_2c~xdSQIYb!RP)Gc-I&+q@(ty zIv}-fz%PMsg$cIz>^9(cz?(olunTa(HS`OUJ_R_jT#Eq4iO7a>C8)}jng-?p*Of7e zcLT|+1R8)w5%DD!s|pwb%mOYbqwkHt34kjHoGz0Y$Cm+Y2QX7aJ})8<2gw~M1}yl- z9I!`3UKNpV0;dQ2%4$P_r&4U)Ikp@)zx8)xf8f4V|uefR8(>?RR*w1-~nJtM!57P z5!qynVZ+&1vTxWIi7q{ro^v0s&J7xNk+1A>p0B7l0T|*H-3r4gwF%gyZ1ha!-rfJ6 zn>zB309}^|<`*}U%jFV)j{ujJ7=Je~FxYPS;DUPf2i^#;#o9y>S>BeGyDq7l=&E}! zKvxVxs|t^bNAU`DYB;6wc#l%MRa3+LBftH{nQMX%O!_p&91pAljxRBXt3>2yrCdXn zU@bx>hYz*2NRF79xu(Tn-&sbQA+t)}fq3`S5CE>1i9GBL^^{>VdVR+l;w5V?JLl z#h9fcl&pB~1%TSx*e3FWPqHyEr3=wR?P&g ziY&@A&h_Y>j-Ivy%_Zj3JJf8-2G=74-0tK}^XE?OR^it2hM|av3gnu&Y^`C0{Mr4$|&Jc0_J z5!^!JhZL>chK~J&@=g~?`#M|_DFv=E3d0ox1f{)Z$HL6pCUL798qFE`EZr3mfJGG9hXq=jytDEI*MLb);Z-p$|Y*)!8r&_ zsGLQ4i*|uvTnpjgVzPBQMV}7PES*>YHWByTidJx z-D_*nF8DU*&^qh^QAKe6ZLzp*LbH7a91TROy+BJy&U#05;_cq82xhy0k4sDO*&o z@x1N-eDS)YZe7N%+b&ARyE?;sJ{FPJJ5xhh3G6HJ-5B5;5n+fd=IEJ^ux-wFKT-#F zk0qb4ivdRHB=T^vn(9>em8d8&@U1%6^oqLw(7-I$l-^*|V_h!{n zvcPQ(xm2n4s4?aU5nMcZOM_T_7a=#p7x%KqE(6Q z;T+m~l=rb~aDJn1YFJ&QuRBAzJ!^ZboXU50#W`iDi-Bbsw{}mMYwg;#48A(#mQnsL zf?LqR2NtM5idJu4bj6-F1)9qrY3+n%XBcBf0Bl|~9e@uP zO?yc>8zpgP;qo43o1ZGOhzm0M-xn%wTg%-DDSHb`M0SO^^2HLj^#R5hV-&zKSImz; zweHzMX(7q?oTa&G=c+bi90#0MqVFbPiikYdk&1S?l1l(?1O68Hw-UFGBW&=0c;Aee zSiJuo-p8O42}W+~)+PVYHmy1{!`}`Uk>%xVesmaIdbLDkw}@O6RH&)QMq#TQQ91i@ zK^4P=ciW2$F`~`Jj0M&Lr-;b<&g?^U_|!pakQqTzE85gvDq0Vq8?*=QJ=(`0wP!m( z&Gbd-TaQk?e>?cj(Vf{Y?lidc-k6BI2uuuHPOCzHtpfvVErl$gkTrOK`o&kL_a*v< z-0X+IND;YDMC`#F*U)sbr3TE2$XXFOJ7nptf^8L~g(rRaB30}wMP!hOJdn@lca0h~ zs?*zHhonH%c5o4SzesrNA=sM&?-gFTwtcv;C45MaM;-Q~7TW8IR&hKYmHsSau|D(Q za89KwUFsms;WGtJ*{CPFvNbes`+OSUK8+RZrdsKxFI2QoA931eTXLzOw=%edzXk>Y z_ld|x?NwF0fvQ@}E{wbSH?Lugxg|t3|1BafwC(p(kzA>;CjjdW{C$W!=Y|w%SWv{C z+EK{qwD)MI(goI8z)WD3G3Huh%%Ch{=}7ohw&Vhcej(S&hiK$D;_c(F0|VPc@Y{o^ zdKY$xTNtxCb?o$Po5 zFkVFFiO8#eb-_QT)JFAh?Zk<$v<7ke?<*D;_`bG>Z;=9VV}9Q9#;qcYkydJZ9e5Y4cVLh`9NTAhcwA& z*<3H;LoMG2jwSmy0j)y&=3lMz3cpLCoGPLas>olfG{~_X7q38S_1il#+$Gd*MuhrK zaY6|O+8g+4nPhZ|F{U$N!i~YY;3uq%sHM7oE75AoyM3~fZqgP_)%ar zAI9tp`~~qz^IGDA**(cV+|#yFb}aDwtT?kA$=y?iiu_-+jlif-DDIf#j4>6#-(AIL zvke8FEXI=M#Fm!$Fq!&{f_n{^+-aK=k%x>iYeQ^#YH*qd!nH3HQMU)@KR7tlUX(t~ zp4FO(cT8Uix!jguqt(H_&JN}JF2p~(nIR(0owm6)0rbToseC?!ULO>>zkgu8ONe)5 z%gyxP4ynw4q>u3z>3c;vE0n rtRkhJ9&k!2o18iMbNh4qf7JdLE_1EWn8_vn00000NkvXXu0mjf+ + + +image/svg+xml \ No newline at end of file From 590fa9efe78cefbe29c956f4e3a2dfc1f009aeaa Mon Sep 17 00:00:00 2001 From: Richard Cox Date: Fri, 8 Mar 2019 11:00:22 +0000 Subject: [PATCH 13/20] Disable endpoint card routerLink using new directive --- .../packages/core/src/core/core.module.ts | 7 ++-- .../src/core/disable-router-link.directive.ts | 32 +++++++++++++++++++ .../endpoint-card.component.html | 2 +- 3 files changed, 38 insertions(+), 3 deletions(-) create mode 100644 src/frontend/packages/core/src/core/disable-router-link.directive.ts diff --git a/src/frontend/packages/core/src/core/core.module.ts b/src/frontend/packages/core/src/core/core.module.ts index 63958dc505..0a3757a28d 100644 --- a/src/frontend/packages/core/src/core/core.module.ts +++ b/src/frontend/packages/core/src/core/core.module.ts @@ -10,6 +10,7 @@ import { BytesToHumanSize, MegaBytesToHumanSize } from './byte-formatters.pipe'; import { ClickStopPropagationDirective } from './click-stop-propagation.directive'; import { CurrentUserPermissionsService } from './current-user-permissions.service'; import { Customizations } from './customizations.types'; +import { DisableRouterLinkDirective } from './disable-router-link.directive'; import { DotContentComponent } from './dot-content/dot-content.component'; import { EndpointsService } from './endpoints.service'; import { EntityFavoriteStarComponent } from './entity-favorite-star/entity-favorite-star.component'; @@ -51,7 +52,8 @@ import { WindowRef } from './window-ref/window-ref.service'; ButtonBlurOnClickDirective, PageNotFoundComponentComponent, EntityFavoriteStarComponent, - RecentEntitiesComponent + RecentEntitiesComponent, + DisableRouterLinkDirective ], providers: [ AuthGuardService, @@ -78,7 +80,8 @@ import { WindowRef } from './window-ref/window-ref.service'; ButtonBlurOnClickDirective, PageNotFoundComponentComponent, EntityFavoriteStarComponent, - RecentEntitiesComponent + RecentEntitiesComponent, + DisableRouterLinkDirective ], entryComponents: [ LogOutDialogComponent diff --git a/src/frontend/packages/core/src/core/disable-router-link.directive.ts b/src/frontend/packages/core/src/core/disable-router-link.directive.ts new file mode 100644 index 0000000000..dd3f54a69a --- /dev/null +++ b/src/frontend/packages/core/src/core/disable-router-link.directive.ts @@ -0,0 +1,32 @@ +import { Directive, Input, Optional } from '@angular/core'; +import { RouterLink, RouterLinkWithHref } from '@angular/router'; + +@Directive({ + selector: '[routerLink][disableRouterLink]' +}) +export class DisableRouterLinkDirective { + + @Input() disableRouterLink: boolean; + + constructor( + // Inject routerLink + @Optional() routerLink: RouterLink, + @Optional() routerLinkWithHref: RouterLinkWithHref + ) { + + const link = routerLink || routerLinkWithHref; + + // Save original method + const onClick = link.onClick; + + // Replace method + link.onClick = (...args) => { + if (this.disableRouterLink) { + return routerLinkWithHref ? false : true; + } else { + return onClick.apply(link, args); + } + }; + } + +} \ No newline at end of file diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.html b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.html index 77e7396f82..b4d5feb4a5 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.html +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.html @@ -1,4 +1,4 @@ - +
From a9d6fd6cd401e1d496076ca97291e412611fa14a Mon Sep 17 00:00:00 2001 From: Richard Cox Date: Fri, 8 Mar 2019 11:18:58 +0000 Subject: [PATCH 14/20] Fix linting, don't show image if no image --- .../packages/core/src/core/disable-router-link.directive.ts | 6 +++--- .../endpoint/endpoint-card/endpoint-card.component.html | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/frontend/packages/core/src/core/disable-router-link.directive.ts b/src/frontend/packages/core/src/core/disable-router-link.directive.ts index dd3f54a69a..aab1ad788c 100644 --- a/src/frontend/packages/core/src/core/disable-router-link.directive.ts +++ b/src/frontend/packages/core/src/core/disable-router-link.directive.ts @@ -2,11 +2,11 @@ import { Directive, Input, Optional } from '@angular/core'; import { RouterLink, RouterLinkWithHref } from '@angular/router'; @Directive({ - selector: '[routerLink][disableRouterLink]' + selector: '[routerLink][appDisableRouterLink]' }) export class DisableRouterLinkDirective { - @Input() disableRouterLink: boolean; + @Input() appDisableRouterLink: boolean; constructor( // Inject routerLink @@ -21,7 +21,7 @@ export class DisableRouterLinkDirective { // Replace method link.onClick = (...args) => { - if (this.disableRouterLink) { + if (this.appDisableRouterLink) { return routerLinkWithHref ? false : true; } else { return onClick.apply(link, args); diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.html b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.html index b4d5feb4a5..fba8e0bb1e 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.html +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.html @@ -1,7 +1,7 @@ - +
-
+
From 828ec171b4833bf25c920b495038011c2aa2e091 Mon Sep 17 00:00:00 2001 From: Richard Cox Date: Fri, 8 Mar 2019 11:24:32 +0000 Subject: [PATCH 15/20] Another lint fix --- .../packages/core/src/core/disable-router-link.directive.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/frontend/packages/core/src/core/disable-router-link.directive.ts b/src/frontend/packages/core/src/core/disable-router-link.directive.ts index aab1ad788c..3a24c8ecfc 100644 --- a/src/frontend/packages/core/src/core/disable-router-link.directive.ts +++ b/src/frontend/packages/core/src/core/disable-router-link.directive.ts @@ -29,4 +29,4 @@ export class DisableRouterLinkDirective { }; } -} \ No newline at end of file +} From d59ac521fb9746937bf62b8c150e34fa21de7427 Mon Sep 17 00:00:00 2001 From: Neil MacDougall Date: Wed, 13 Mar 2019 11:50:29 +0000 Subject: [PATCH 16/20] Fix lint issues --- .../packages/core/src/core/extension/extension-types.ts | 4 ++-- .../table-cell-endpoint-name.component.ts | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/frontend/packages/core/src/core/extension/extension-types.ts b/src/frontend/packages/core/src/core/extension/extension-types.ts index d0d0e8f848..97850d0137 100644 --- a/src/frontend/packages/core/src/core/extension/extension-types.ts +++ b/src/frontend/packages/core/src/core/extension/extension-types.ts @@ -20,7 +20,7 @@ export interface EndpointTypeConfig { /** * Get the link to the home page for the given endpoint GUID */ - homeLink?: (string) => string[]; + homeLink?: (s) => string[]; /** * Schema keys associated with this endpoint type (used when clearing pagination) */ @@ -54,7 +54,7 @@ export interface EndpointAuthValues { [key: string]: string; } * Optional interface that an Endpoint Auth Form Component can implement * if it needs to supply content in the request body when connecting an endppoint * e.g. if it needs to send a config file - **/ + */ export interface IEndpointAuthComponent extends IAuthForm { // Allows auth type to override which values are sent to the backend when connecting getValues(values: EndpointAuthValues): EndpointAuthValues; // Map of values to send diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-name/table-cell-endpoint-name.component.ts b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-name/table-cell-endpoint-name.component.ts index 5476df6f49..90f64c2ca7 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-name/table-cell-endpoint-name.component.ts +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-name/table-cell-endpoint-name.component.ts @@ -11,16 +11,16 @@ import { TableCellCustom } from '../../../list.types'; }) export class TableCellEndpointNameComponent extends TableCellCustom { - private _row: EndpointModel; + private tableRow: EndpointModel; @Input('row') set row(row: EndpointModel) { - this._row = row; + this.tableRow = row; } get row(): EndpointModel { - return this._row; + return this.tableRow; } - getLinkForEndpoint(row = this._row) { + getLinkForEndpoint(row = this.tableRow) { return EndpointsService.getLinkForEndpoint(row); } } From 58a8bd9ec3c3c3d25a1a01ec3e710fde780a7e57 Mon Sep 17 00:00:00 2001 From: Neil MacDougall Date: Wed, 13 Mar 2019 14:06:21 +0000 Subject: [PATCH 17/20] Fix merge issue --- .../core/src/shared/components/list/list.component.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/frontend/packages/core/src/shared/components/list/list.component.spec.ts b/src/frontend/packages/core/src/shared/components/list/list.component.spec.ts index 3b4b8f0a14..1b4c1b892a 100644 --- a/src/frontend/packages/core/src/shared/components/list/list.component.spec.ts +++ b/src/frontend/packages/core/src/shared/components/list/list.component.spec.ts @@ -15,10 +15,10 @@ import { EntityMonitorFactory } from '../../monitors/entity-monitor.factory.serv import { PaginationMonitorFactory } from '../../monitors/pagination-monitor.factory'; import { SharedModule } from '../../shared.module'; import { ApplicationStateService } from '../application-state/application-state.service'; -import { EndpointCardComponent } from './list-types/cf-endpoints/cf-endpoint-card/endpoint-card.component'; import { EndpointsListConfigService } from './list-types/endpoint/endpoints-list-config.service'; import { ListComponent } from './list.component'; import { ListConfig, ListViewTypes } from './list.component.types'; +import { EndpointListHelper } from './list-types/endpoint/endpoint-list.helpers'; class MockedNgZone { run = fn => fn(); From d6b52504cbdd6ed4694582ec21c93c94c6f12853 Mon Sep 17 00:00:00 2001 From: Neil MacDougall Date: Wed, 13 Mar 2019 14:37:25 +0000 Subject: [PATCH 18/20] Fix merge issue --- .../core/src/shared/components/list/list.component.spec.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/frontend/packages/core/src/shared/components/list/list.component.spec.ts b/src/frontend/packages/core/src/shared/components/list/list.component.spec.ts index 1b4c1b892a..939407b770 100644 --- a/src/frontend/packages/core/src/shared/components/list/list.component.spec.ts +++ b/src/frontend/packages/core/src/shared/components/list/list.component.spec.ts @@ -19,6 +19,7 @@ import { EndpointsListConfigService } from './list-types/endpoint/endpoints-list import { ListComponent } from './list.component'; import { ListConfig, ListViewTypes } from './list.component.types'; import { EndpointListHelper } from './list-types/endpoint/endpoint-list.helpers'; +import { EndpointCardComponent } from './list-types/endpoint/endpoint-card/endpoint-card.component'; class MockedNgZone { run = fn => fn(); From 0b457fb4de4ffd062133c9c5bcde7fc1772a99f2 Mon Sep 17 00:00:00 2001 From: Richard Cox Date: Thu, 14 Mar 2019 12:07:38 +0000 Subject: [PATCH 19/20] Fix issues from review - Ensure extensions/extension-types.ts remains free from other imports - Now check endpoint detail type is correct at runtime - Cf Endpoint Type is now registered in cf package - Ensure cf package tests & lint execute correctly - Ensure endpoint details components are destroyed correctly --- package.json | 1 + .../cloud-foundry/src/cloud-foundry.module.ts | 28 +++++++++++ .../packages/cloud-foundry/src/public_api.ts | 2 +- .../cf-endpoint-details.component.html | 0 .../cf-endpoint-details.component.scss | 0 .../cf-endpoint-details.component.spec.ts | 6 +-- .../cf-endpoint-details.component.ts | 13 +++++ .../shared/components/components.module.ts | 20 ++++++++ .../packages/cloud-foundry/src/test.ts | 9 ++-- .../packages/cloud-foundry/tsconfig.spec.json | 7 +-- src/frontend/packages/core/src/app.module.ts | 6 ++- .../src/core/extension/extension-types.ts | 7 +-- .../features/endpoints/endpoint-helpers.ts | 23 ++------- .../table-cell/table-cell.component.ts | 4 +- .../cf-endpoint-details.component.ts | 14 ------ .../endpoint-card/endpoint-card.component.ts | 49 ++++++++++++++----- .../endpoint/endpoint-list.helpers.ts | 48 +++++++++++++++++- .../table-cell-endpoint-details.component.ts | 39 ++++++++++----- .../src/shared/components/list/list.types.ts | 3 +- 19 files changed, 195 insertions(+), 84 deletions(-) create mode 100644 src/frontend/packages/cloud-foundry/src/cloud-foundry.module.ts rename src/frontend/packages/{core/src/shared/components/list/list-types/endpoint => cloud-foundry/src/shared/components}/cf-endpoint-details/cf-endpoint-details.component.html (100%) rename src/frontend/packages/{core/src/shared/components/list/list-types/endpoint => cloud-foundry/src/shared/components}/cf-endpoint-details/cf-endpoint-details.component.scss (100%) rename src/frontend/packages/{core/src/shared/components/list/list-types/endpoint => cloud-foundry/src/shared/components}/cf-endpoint-details/cf-endpoint-details.component.spec.ts (78%) create mode 100644 src/frontend/packages/cloud-foundry/src/shared/components/cf-endpoint-details/cf-endpoint-details.component.ts create mode 100644 src/frontend/packages/cloud-foundry/src/shared/components/components.module.ts delete mode 100644 src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.ts diff --git a/package.json b/package.json index 44cf74c1b4..f9d93a56c6 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "test": "run-s test-frontend:* --continue-on-error", "test-frontend:core": "ng test core --code-coverage --watch=false", "test-frontend:store": "ng test store --code-coverage --watch=false", + "test-frontend:cloud-foundry": "ng test cloud-foundry --code-coverage --watch=false", "posttest": "istanbul report json && node build/combine-coverage.js", "codecov": "codecov -f coverage/coverage-final.json", "lint": "ng lint --format stylish", diff --git a/src/frontend/packages/cloud-foundry/src/cloud-foundry.module.ts b/src/frontend/packages/cloud-foundry/src/cloud-foundry.module.ts new file mode 100644 index 0000000000..e8429cf42d --- /dev/null +++ b/src/frontend/packages/cloud-foundry/src/cloud-foundry.module.ts @@ -0,0 +1,28 @@ +import { NgModule } from '@angular/core'; + +import { StratosExtension } from '../../core/src/core/extension/extension-service'; +import { EndpointTypeConfig } from '../../core/src/core/extension/extension-types'; +import { urlValidationExpression } from '../../core/src/core/utils.service'; +import { CfEndpointDetailsComponent } from './shared/components/cf-endpoint-details/cf-endpoint-details.component'; +import { CloudFoundryComponentsModule } from './shared/components/components.module'; + +const cloudFoundryEndpointTypes: EndpointTypeConfig[] = [{ + value: 'cf', + label: 'Cloud Foundry', + urlValidation: urlValidationExpression, + icon: 'cloud_foundry', + iconFont: 'stratos-icons', + imagePath: '/core/assets/endpoint-icons/cloudfoundry.png', + homeLink: (guid) => ['/cloud-foundry', guid], + listDetailsComponent: CfEndpointDetailsComponent +}]; + +@StratosExtension({ + endpointTypes: cloudFoundryEndpointTypes, +}) +@NgModule({ + imports: [ + CloudFoundryComponentsModule + ], +}) +export class CloudFoundryModule { } diff --git a/src/frontend/packages/cloud-foundry/src/public_api.ts b/src/frontend/packages/cloud-foundry/src/public_api.ts index ef11c82c31..eef53f2d79 100644 --- a/src/frontend/packages/cloud-foundry/src/public_api.ts +++ b/src/frontend/packages/cloud-foundry/src/public_api.ts @@ -2,6 +2,6 @@ * Public API Surface of cloud-foundry */ -export * from './lib/cloud-foundry.service'; +// export * from './lib/cloud-foundry.service'; export * from './lib/cloud-foundry.component'; export * from './lib/cloud-foundry.module'; diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.html b/src/frontend/packages/cloud-foundry/src/shared/components/cf-endpoint-details/cf-endpoint-details.component.html similarity index 100% rename from src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.html rename to src/frontend/packages/cloud-foundry/src/shared/components/cf-endpoint-details/cf-endpoint-details.component.html diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.scss b/src/frontend/packages/cloud-foundry/src/shared/components/cf-endpoint-details/cf-endpoint-details.component.scss similarity index 100% rename from src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.scss rename to src/frontend/packages/cloud-foundry/src/shared/components/cf-endpoint-details/cf-endpoint-details.component.scss diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.spec.ts b/src/frontend/packages/cloud-foundry/src/shared/components/cf-endpoint-details/cf-endpoint-details.component.spec.ts similarity index 78% rename from src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.spec.ts rename to src/frontend/packages/cloud-foundry/src/shared/components/cf-endpoint-details/cf-endpoint-details.component.spec.ts index e361a7fff5..c6cf04c3a1 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.spec.ts +++ b/src/frontend/packages/cloud-foundry/src/shared/components/cf-endpoint-details/cf-endpoint-details.component.spec.ts @@ -1,7 +1,7 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { CoreModule } from '../../../../../../core/core.module'; -import { SharedModule } from '../../../../../shared.module'; +import { CoreModule } from '../../../../../core/src/core/core.module'; +import { SharedModule } from '../../../../../core/src/shared/shared.module'; import { CfEndpointDetailsComponent } from './cf-endpoint-details.component'; describe('CfEndpointDetailsComponent', () => { @@ -10,7 +10,7 @@ describe('CfEndpointDetailsComponent', () => { beforeEach(async(() => { TestBed.configureTestingModule({ - declarations: [], + declarations: [CfEndpointDetailsComponent], imports: [ CoreModule, SharedModule diff --git a/src/frontend/packages/cloud-foundry/src/shared/components/cf-endpoint-details/cf-endpoint-details.component.ts b/src/frontend/packages/cloud-foundry/src/shared/components/cf-endpoint-details/cf-endpoint-details.component.ts new file mode 100644 index 0000000000..0012fef5d0 --- /dev/null +++ b/src/frontend/packages/cloud-foundry/src/shared/components/cf-endpoint-details/cf-endpoint-details.component.ts @@ -0,0 +1,13 @@ +import { Component } from '@angular/core'; + +import { + EndpointListDetailsComponent, +} from '../../../../../core/src/shared/components/list/list-types/endpoint/endpoint-list.helpers'; + + +@Component({ + selector: 'lib-cf-endpoint-details', + templateUrl: './cf-endpoint-details.component.html', + styleUrls: ['./cf-endpoint-details.component.scss'] +}) +export class CfEndpointDetailsComponent extends EndpointListDetailsComponent { } diff --git a/src/frontend/packages/cloud-foundry/src/shared/components/components.module.ts b/src/frontend/packages/cloud-foundry/src/shared/components/components.module.ts new file mode 100644 index 0000000000..3ec2e28d4e --- /dev/null +++ b/src/frontend/packages/cloud-foundry/src/shared/components/components.module.ts @@ -0,0 +1,20 @@ +import { NgModule } from '@angular/core'; + +import { CoreModule } from '../../../../core/src/core/core.module'; +import { CfEndpointDetailsComponent } from './cf-endpoint-details/cf-endpoint-details.component'; + +@NgModule({ + imports: [ + CoreModule + ], + declarations: [ + CfEndpointDetailsComponent + ], + exports: [ + CfEndpointDetailsComponent + ], + entryComponents: [ + CfEndpointDetailsComponent + ] +}) +export class CloudFoundryComponentsModule { } diff --git a/src/frontend/packages/cloud-foundry/src/test.ts b/src/frontend/packages/cloud-foundry/src/test.ts index d0b441ad3d..18653a67a2 100644 --- a/src/frontend/packages/cloud-foundry/src/test.ts +++ b/src/frontend/packages/cloud-foundry/src/test.ts @@ -1,10 +1,7 @@ // This file is required by karma.conf.js and loads recursively all the .spec and framework files -import 'zone.js/dist/long-stack-trace-zone'; -import 'zone.js/dist/proxy'; -import 'zone.js/dist/sync-test'; -import 'zone.js/dist/jasmine-patch'; -import 'zone.js/dist/async-test'; -import 'zone.js/dist/fake-async-test'; +import 'core-js/es7/reflect'; +import 'zone.js/dist/zone'; +import 'zone.js/dist/zone-testing'; import { APP_BASE_HREF } from '@angular/common'; import { getTestBed } from '@angular/core/testing'; diff --git a/src/frontend/packages/cloud-foundry/tsconfig.spec.json b/src/frontend/packages/cloud-foundry/tsconfig.spec.json index 1fe1c34b80..cb4a7be918 100644 --- a/src/frontend/packages/cloud-foundry/tsconfig.spec.json +++ b/src/frontend/packages/cloud-foundry/tsconfig.spec.json @@ -2,6 +2,10 @@ "extends": "../../../tsconfig.spec.json", "compilerOptions": { "outDir": "../../../../out-tsc/spec", + "types": [ + "jasmine", + "node" + ] }, "files": [ "src/test.ts" @@ -9,8 +13,5 @@ "include": [ "**/*.spec.ts", "**/*.d.ts" - ], - "exclude": [ - "**/node_modules/**" ] } diff --git a/src/frontend/packages/core/src/app.module.ts b/src/frontend/packages/core/src/app.module.ts index e69c22a32e..b2ddb80e3b 100644 --- a/src/frontend/packages/core/src/app.module.ts +++ b/src/frontend/packages/core/src/app.module.ts @@ -6,6 +6,7 @@ import { RouterStateSerializer, StoreRouterConnectingModule } from '@ngrx/router import { Store } from '@ngrx/store'; import { debounceTime, withLatestFrom } from 'rxjs/operators'; +import { CloudFoundryModule } from '../../cloud-foundry/src/cloud-foundry.module'; import { GetAllEndpoints } from '../../store/src/actions/endpoint.actions'; import { GetOrganization } from '../../store/src/actions/organization.actions'; import { SetRecentlyVisitedEntityAction } from '../../store/src/actions/recently-visited.actions'; @@ -38,6 +39,7 @@ import { CurrentUserPermissionsService } from './core/current-user-permissions.s import { DynamicExtensionRoutes } from './core/extension/dynamic-extension-routes'; import { ExtensionService } from './core/extension/extension-service'; import { getGitHubAPIURL, GITHUB_API_URL } from './core/github.helpers'; +import { LoggerService } from './core/logger.service'; import { UserFavoriteManager } from './core/user-favorite-manager'; import { CustomImportModule } from './custom-import.module'; import { AboutModule } from './features/about/about.module'; @@ -56,7 +58,6 @@ import { ApplicationStateService } from './shared/components/application-state/a import { favoritesConfigMapper } from './shared/components/favorites-meta-card/favorite-config-mapper'; import { SharedModule } from './shared/shared.module'; import { XSRFModule } from './xsrf.module'; -import { LoggerService } from './core/logger.service'; // Create action for router navigation. See // - https://github.com/ngrx/platform/issues/68 @@ -113,6 +114,7 @@ export class CustomRouterStateSerializer AboutModule, CustomImportModule, XSRFModule, + CloudFoundryModule ], providers: [ LoggedInService, @@ -138,7 +140,7 @@ export class AppModule { initEndpointExtensions(ext); // Once the CF modules become an extension point, these should be moved to a CF specific module this.registerCfFavoriteMappers(); - this.userFavoriteManager = new UserFavoriteManager(store, logger); + this.userFavoriteManager = new UserFavoriteManager(store, logger); const allFavs$ = this.userFavoriteManager.getAllFavorites(); const recents$ = this.store.select(recentlyVisitedSelector); const debouncedApiRequestData$ = this.store.select(getAPIRequestDataState).pipe(debounceTime(2000)); diff --git a/src/frontend/packages/core/src/core/extension/extension-types.ts b/src/frontend/packages/core/src/core/extension/extension-types.ts index 97850d0137..74f30c9d52 100644 --- a/src/frontend/packages/core/src/core/extension/extension-types.ts +++ b/src/frontend/packages/core/src/core/extension/extension-types.ts @@ -2,9 +2,6 @@ import { Type } from '@angular/core'; import { FormGroup } from '@angular/forms'; import { Schema, schema } from 'normalizr'; -import { EndpointModel } from '../../../../store/src/types/endpoint.types'; -import { TableCellCustom } from '../../shared/components/list/list.types'; - // Allowable endpoint types export type EndpointType = 'cf' | 'metrics' | string; @@ -26,9 +23,9 @@ export interface EndpointTypeConfig { */ entitySchemaKeys?: string[]; /** - * Show custom content in the endpoints list + * Show custom content in the endpoints list. Should be Type */ - listDetailsComponent?: Type>; + listDetailsComponent?: any; } export interface EndpointAuthTypeConfig { diff --git a/src/frontend/packages/core/src/features/endpoints/endpoint-helpers.ts b/src/frontend/packages/core/src/features/endpoints/endpoint-helpers.ts index 45262f7f82..35f6f9a867 100644 --- a/src/frontend/packages/core/src/features/endpoints/endpoint-helpers.ts +++ b/src/frontend/packages/core/src/features/endpoints/endpoint-helpers.ts @@ -10,11 +10,7 @@ import { selectEntities } from '../../../../store/src/selectors/api.selectors'; import { EndpointModel } from '../../../../store/src/types/endpoint.types'; import { ExtensionService } from '../../core/extension/extension-service'; import { EndpointAuthTypeConfig, EndpointType, EndpointTypeConfig } from '../../core/extension/extension-types'; -import { urlValidationExpression } from '../../core/utils.service'; -import { - CfEndpointDetailsComponent, -} from '../../shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component'; -import { TableCellCustom } from '../../shared/components/list/list.types'; +import { EndpointListDetailsComponent } from '../../shared/components/list/list-types/endpoint/endpoint-list.helpers'; import { CredentialsAuthFormComponent } from './connect-endpoint-dialog/auth-forms/credentials-auth-form.component'; import { NoneAuthFormComponent } from './connect-endpoint-dialog/auth-forms/none-auth-form.component'; import { SSOAuthFormComponent } from './connect-endpoint-dialog/auth-forms/sso-auth-form.component'; @@ -35,16 +31,6 @@ export interface EndpointIcon { } const endpointTypes: EndpointTypeConfig[] = [ - { - value: 'cf', - label: 'Cloud Foundry', - urlValidation: urlValidationExpression, - icon: 'cloud_foundry', - iconFont: 'stratos-icons', - imagePath: '/core/assets/endpoint-icons/cloudfoundry.png', - homeLink: (guid) => ['/cloud-foundry', guid], - listDetailsComponent: CfEndpointDetailsComponent - }, { value: 'metrics', label: 'Metrics', @@ -83,7 +69,8 @@ let endpointAuthTypes: EndpointAuthTypeConfig[] = [ const endpointTypesMap = {}; -export const endpointListDetailsComponents: Type>[] = [CfEndpointDetailsComponent]; +// Any initial endpointTypes listDetailsComponent should be added here +export const coreEndpointListDetailsComponents: Type[] = []; export function initEndpointTypes(epTypes: EndpointTypeConfig[]) { epTypes.forEach(epType => { @@ -98,10 +85,6 @@ export function initEndpointTypes(epTypes: EndpointTypeConfig[]) { } }); } - - if (epType.listDetailsComponent) { - endpointListDetailsComponents.push(epType.listDetailsComponent); - } }); endpointTypes.forEach(ept => { diff --git a/src/frontend/packages/core/src/shared/components/list/list-table/table-cell/table-cell.component.ts b/src/frontend/packages/core/src/shared/components/list/list-table/table-cell/table-cell.component.ts index 79918dc344..2e0a6232bb 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-table/table-cell/table-cell.component.ts +++ b/src/frontend/packages/core/src/shared/components/list/list-table/table-cell/table-cell.component.ts @@ -13,7 +13,7 @@ import { ViewEncapsulation, } from '@angular/core'; -import { endpointListDetailsComponents } from '../../../../../features/endpoints/endpoint-helpers'; +import { coreEndpointListDetailsComponents } from '../../../../../features/endpoints/endpoint-helpers'; import { IListDataSource } from '../../data-sources-controllers/list-data-source-types'; import { TableCellEventActionComponent, @@ -165,7 +165,7 @@ export const listTableCells = [ TableCellAServicePlanExtrasComponent, TableCellFavoriteComponent, TableCellEndpointDetailsComponent, - ...endpointListDetailsComponents + ...coreEndpointListDetailsComponents ]; @Component({ diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.ts b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.ts deleted file mode 100644 index 4696ce448e..0000000000 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/cf-endpoint-details/cf-endpoint-details.component.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { Component, Input } from '@angular/core'; - -import { EndpointModel } from '../../../../../../../../store/src/types/endpoint.types'; -import { TableCellCustom } from '../../../list.types'; - -@Component({ - selector: 'app-cf-endpoint-details', - templateUrl: './cf-endpoint-details.component.html', - styleUrls: ['./cf-endpoint-details.component.scss'] -}) -export class CfEndpointDetailsComponent extends TableCellCustom { - - @Input() spaceBetween = true; -} diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.ts b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.ts index c05cced76d..44961170ae 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.ts +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-card/endpoint-card.component.ts @@ -1,4 +1,13 @@ -import { Component, ComponentFactoryResolver, Input, OnInit, ViewChild, ViewContainerRef } from '@angular/core'; +import { + Component, + ComponentFactoryResolver, + ComponentRef, + Input, + OnDestroy, + OnInit, + ViewChild, + ViewContainerRef, +} from '@angular/core'; import { ReplaySubject } from 'rxjs'; import { EndpointModel } from '../../../../../../../../store/src/types/endpoint.types'; @@ -7,23 +16,22 @@ import { EndpointsService } from '../../../../../../core/endpoints.service'; import { EndpointTypeConfig } from '../../../../../../core/extension/extension-types'; import { getFavoriteFromEndpointEntity } from '../../../../../../core/user-favorite-helpers'; import { - endpointListDetailsComponents, + coreEndpointListDetailsComponents, getEndpointType, getFullEndpointApiUrl, } from '../../../../../../features/endpoints/endpoint-helpers'; import { MetaCardMenuItem } from '../../../list-cards/meta-card/meta-card-base/meta-card.component'; import { CardCell } from '../../../list.types'; import { BaseEndpointsDataSource } from '../../cf-endpoints/base-endpoints-data-source'; -import { CfEndpointDetailsComponent } from '../cf-endpoint-details/cf-endpoint-details.component'; -import { EndpointListHelper } from '../endpoint-list.helpers'; +import { EndpointListDetailsComponent, EndpointListHelper } from '../endpoint-list.helpers'; @Component({ selector: 'app-endpoint-card', templateUrl: './endpoint-card.component.html', styleUrls: ['./endpoint-card.component.scss'], - entryComponents: [...endpointListDetailsComponents] + entryComponents: [...coreEndpointListDetailsComponents] }) -export class EndpointCardComponent extends CardCell implements OnInit { +export class EndpointCardComponent extends CardCell implements OnInit, OnDestroy { public rowObs = new ReplaySubject(); public favorite: UserFavoriteEndpoint; @@ -33,7 +41,9 @@ export class EndpointCardComponent extends CardCell implements On public hasDetails = true; public endpointLink: string = null; - @Input() component: CfEndpointDetailsComponent; + private componentRef: ComponentRef; + + @Input() component: EndpointListDetailsComponent; private endpointDetails: ViewContainerRef; @ViewChild('endpointDetails', { read: ViewContainerRef }) set content(content: ViewContainerRef) { this.endpointDetails = content; @@ -60,7 +70,7 @@ export class EndpointCardComponent extends CardCell implements On @Input('dataSource') set dataSource(ds: BaseEndpointsDataSource) { - if (ds.endpointType !== 'cf' && !this.cardMenu) { + if (ds && ds.endpointType !== 'cf' && !this.cardMenu) { this.cardMenu = this.endpointListHelper.endpointActions().map(endpointAction => ({ label: endpointAction.label, action: () => endpointAction.action(this.pRow), @@ -82,6 +92,14 @@ export class EndpointCardComponent extends CardCell implements On this.hasDetails = !!e.listDetailsComponent; } + ngOnDestroy(): void { + this.endpointListHelper.destroyEndpointDetails({ + componentRef: this.componentRef, + component: this.component, + endpointDetails: this.endpointDetails + }); + } + updateDetails() { if (!this.endpointDetails || !this.pRow) { return; @@ -92,11 +110,16 @@ export class EndpointCardComponent extends CardCell implements On } if (!this.component) { - const componentFactory = this.componentFactoryResolver.resolveComponentFactory(e.listDetailsComponent); - const componentRef = this.endpointDetails.createComponent(componentFactory); - this.component = componentRef.instance as CfEndpointDetailsComponent; + const res = + this.endpointListHelper.createEndpointDetails(e.listDetailsComponent, this.endpointDetails, this.componentFactoryResolver); + this.componentRef = res.componentRef; + this.component = res.component; + } + + if (this.component) { + this.component.row = this.pRow; + this.component.isTable = false; } - this.component.row = this.pRow; - this.component.spaceBetween = false; } + } diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-list.helpers.ts b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-list.helpers.ts index 0b2b7a1093..a2e5ce482f 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-list.helpers.ts +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/endpoint-list.helpers.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { ComponentFactoryResolver, ComponentRef, Injectable, ViewContainerRef } from '@angular/core'; import { MatDialog } from '@angular/material'; import { Store } from '@ngrx/store'; import { combineLatest, Observable } from 'rxjs'; @@ -13,12 +13,29 @@ import { selectDeletionInfo, selectUpdateInfo } from '../../../../../../../store import { EndpointModel, endpointStoreNames } from '../../../../../../../store/src/types/endpoint.types'; import { CurrentUserPermissions } from '../../../../../core/current-user-permissions.config'; import { CurrentUserPermissionsService } from '../../../../../core/current-user-permissions.service'; +import { LoggerService } from '../../../../../core/logger.service'; import { ConnectEndpointDialogComponent, } from '../../../../../features/endpoints/connect-endpoint-dialog/connect-endpoint-dialog.component'; import { ConfirmationDialogConfig } from '../../../confirmation-dialog.config'; import { ConfirmationDialogService } from '../../../confirmation-dialog.service'; import { IListAction } from '../../list.component.types'; +import { TableCellCustom } from '../../list.types'; + +interface EndpointDetailsContainerRefs { + componentRef: ComponentRef; + component: EndpointListDetailsComponent; + endpointDetails: ViewContainerRef; +} + +export abstract class EndpointListDetailsComponent extends TableCellCustom { + isEndpointListDetailsComponent = true; + isTable = true; +} + +function isEndpointListDetailsComponent(obj: any): EndpointListDetailsComponent { + return obj ? obj.isEndpointListDetailsComponent ? obj as EndpointListDetailsComponent : null : null; +} @Injectable() export class EndpointListHelper { @@ -27,7 +44,8 @@ export class EndpointListHelper { private store: Store, private dialog: MatDialog, private currentUserPermissionsService: CurrentUserPermissionsService, - private confirmDialog: ConfirmationDialogService) { + private confirmDialog: ConfirmationDialogService, + private log: LoggerService) { } @@ -125,4 +143,30 @@ export class EndpointListHelper { } }); } + + createEndpointDetails(listDetailsComponent: any, container: ViewContainerRef, componentFactoryResolver: ComponentFactoryResolver): + EndpointDetailsContainerRefs { + const componentFactory = componentFactoryResolver.resolveComponentFactory(listDetailsComponent); + const componentRef = container.createComponent(componentFactory); + const component = isEndpointListDetailsComponent(componentRef.instance); + const refs = { + componentRef, + component, + endpointDetails: container + }; + if (!component) { + this.log.warn(`Attempted to create a non-endpoint list details component "${listDetailsComponent}"`); + this.destroyEndpointDetails(refs); + } + return refs; + } + + destroyEndpointDetails(refs: EndpointDetailsContainerRefs) { + if (refs.componentRef) { + refs.componentRef.destroy(); + } + if (refs.endpointDetails) { + refs.endpointDetails.clear(); + } + } } diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-details/table-cell-endpoint-details.component.ts b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-details/table-cell-endpoint-details.component.ts index 36fd4834d0..2bb2f65cb5 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-details/table-cell-endpoint-details.component.ts +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-details/table-cell-endpoint-details.component.ts @@ -1,22 +1,23 @@ -import { Component, ComponentFactoryResolver, Input, Type, ViewChild, ViewContainerRef } from '@angular/core'; +import { Component, ComponentFactoryResolver, Input, OnDestroy, Type, ViewChild, ViewContainerRef } from '@angular/core'; import { EndpointModel } from '../../../../../../../../store/src/types/endpoint.types'; import { getEndpointType } from '../../../../../../features/endpoints/endpoint-helpers'; import { TableCellCustom } from '../../../list.types'; +import { EndpointListDetailsComponent, EndpointListHelper } from '../endpoint-list.helpers'; @Component({ selector: 'app-table-cell-endpoint-details', templateUrl: './table-cell-endpoint-details.component.html', styleUrls: ['./table-cell-endpoint-details.component.scss'] }) -export class TableCellEndpointDetailsComponent extends TableCellCustom { +export class TableCellEndpointDetailsComponent extends TableCellCustom implements OnDestroy { - @Input() component: Type>; + @Input() component: Type; @ViewChild('target', { read: ViewContainerRef }) target; - cell: TableCellCustom; + cell: EndpointListDetailsComponent; - constructor(private componentFactoryResolver: ComponentFactoryResolver) { + constructor(private componentFactoryResolver: ComponentFactoryResolver, private endpointListHelper: EndpointListHelper) { super(); } @@ -26,17 +27,31 @@ export class TableCellEndpointDetailsComponent extends TableCellCustom; - } - this.cell.row = this.pRow; + if (!e.listDetailsComponent) { + return; + } + if (!this.cell) { + const res = + this.endpointListHelper.createEndpointDetails(e.listDetailsComponent, this.target, this.componentFactoryResolver); + this.target = res.componentRef; + this.cell = res.component; } + if (this.cell) { + this.cell.row = this.pRow; + this.cell.isTable = true; + } } + get row(): EndpointModel { return this.pRow; } + + ngOnDestroy(): void { + this.endpointListHelper.destroyEndpointDetails({ + componentRef: this.target, + component: this.cell, + endpointDetails: this.target + }); + } } diff --git a/src/frontend/packages/core/src/shared/components/list/list.types.ts b/src/frontend/packages/core/src/shared/components/list/list.types.ts index 46d07a59d7..84d009cf44 100644 --- a/src/frontend/packages/core/src/shared/components/list/list.types.ts +++ b/src/frontend/packages/core/src/shared/components/list/list.types.ts @@ -1,7 +1,8 @@ import { Component } from '@angular/core'; -import { IListDataSource, RowState } from './data-sources-controllers/list-data-source-types'; import { Observable } from 'rxjs'; +import { IListDataSource, RowState } from './data-sources-controllers/list-data-source-types'; + export abstract class TableCellCustom { dataSource: IListDataSource; row: T; From 2083cc80c471ba237df4cb756315dd72147fa204 Mon Sep 17 00:00:00 2001 From: Richard Cox Date: Thu, 14 Mar 2019 12:38:15 +0000 Subject: [PATCH 20/20] Fix unit test --- .../table-cell-endpoint-details.component.spec.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-details/table-cell-endpoint-details.component.spec.ts b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-details/table-cell-endpoint-details.component.spec.ts index 80261f1af7..338a1ce656 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-details/table-cell-endpoint-details.component.spec.ts +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/table-cell-endpoint-details/table-cell-endpoint-details.component.spec.ts @@ -1,16 +1,20 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { BaseTestModules } from '../../../../../../../test-framework/cloud-foundry-endpoint-service.helper'; +import { EndpointListHelper } from '../endpoint-list.helpers'; import { TableCellEndpointDetailsComponent } from './table-cell-endpoint-details.component'; -describe('TableCellEndpointDetailsComponent', () => { +fdescribe('TableCellEndpointDetailsComponent', () => { let component: TableCellEndpointDetailsComponent; let fixture: ComponentFixture; beforeEach(async(() => { TestBed.configureTestingModule({ - declarations: [ TableCellEndpointDetailsComponent ] + declarations: [], + imports: [...BaseTestModules], + providers: [EndpointListHelper] }) - .compileComponents(); + .compileComponents(); })); beforeEach(() => {