Skip to content

Commit

Permalink
Merge pull request #3436 from cloudfoundry-incubator/cf-org-space-values
Browse files Browse the repository at this point in the history
Add cf/org/space links to service instance table using common components
  • Loading branch information
richard-cox authored Apr 3, 2019
2 parents e6f06f9 + c2e01b9 commit c34ee7e
Show file tree
Hide file tree
Showing 35 changed files with 461 additions and 240 deletions.
Original file line number Diff line number Diff line change
@@ -1,23 +1,20 @@
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 { EndpointListHelper } from '../../../shared/components/list/list-types/endpoint/endpoint-list.helpers';

@Component({
selector: 'app-endpoints-page',
Expand Down Expand Up @@ -55,24 +52,25 @@ export class EndpointsPageComponent implements OnDestroy, OnInit {

ngOnInit() {
this.startEndpointHealthCheckPulse();
const params = queryParamMap();
if (params.cnsi_guid) {
const guid = params.cnsi_guid;
window.history.pushState({}, '', '/endpoints');
this.sub = this.endpointsService.endpoints$.pipe(
delay(0),
filter(ep => !!ep[guid]),
map(ep => {
const endpoint = ep[guid];
if (endpoint.connectionStatus === 'connected') {
this.store.dispatch(new ShowSnackBar(`Connected endpoint '${endpoint.name}'`));
} else {
this.store.dispatch(new ShowSnackBar(`A problem occurred connecting endpoint ${endpoint.name}`));
}
}),
first(),
).subscribe();
}
// Doesn't look like this is used (see connect-endpoint-dialog.component for actual handler)
// const params = queryParamMap();
// if (params.cnsi_guid) {
// const guid = params.cnsi_guid;
// window.history.pushState({}, '', '/endpoints');
// this.sub = this.endpointsService.endpoints$.pipe(
// delay(0),
// filter(ep => !!ep[guid]),
// map(ep => {
// const endpoint = ep[guid];
// if (endpoint.connectionStatus === 'connected') {
// this.store.dispatch(new ShowSnackBar(`Connected endpoint '${endpoint.name}'`));
// } else {
// this.store.dispatch(new ShowSnackBar(`A problem occurred connecting endpoint ${endpoint.name}`));
// }
// }),
// first(),
// ).subscribe();
// }
}

ngOnDestroy() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<ng-container *ngIf="service?.multipleConnectedEndpoints$ | async">
<a [routerLink]="service?.getCfURL()">{{ service?.getCfName() | async }}</a> /
</ng-container>
<a [routerLink]="service?.getOrgURL()">{{ service?.getOrgName() | async}}</a> /
<a [routerLink]="service?.getSpaceURL()" [queryParams]="spaceBreadCrumbs">{{ service?.getSpaceName() | async}}</a>
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';

import { createBasicStoreModule } from '../../../../test-framework/store-test-helper';
import { CfOrgSpaceLinksComponent } from './cf-org-space-links.component';


describe('CfOrgSpaceLinksComponent', () => {
let component: CfOrgSpaceLinksComponent;
let fixture: ComponentFixture<CfOrgSpaceLinksComponent>;

beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [CfOrgSpaceLinksComponent],
imports: [
RouterTestingModule,
createBasicStoreModule()
]
})
.compileComponents();
}));

beforeEach(() => {
fixture = TestBed.createComponent(CfOrgSpaceLinksComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Component, Input } from '@angular/core';

import { CfOrgSpaceLabelService } from '../../services/cf-org-space-label.service';

@Component({
selector: 'app-cf-org-space-links',
templateUrl: './cf-org-space-links.component.html',
styleUrls: ['./cf-org-space-links.component.scss']
})
export class CfOrgSpaceLinksComponent {

@Input() service: CfOrgSpaceLabelService;
@Input() spaceBreadCrumbs: string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,16 @@ import { ApplicationStateIconPipe } from '../../../application-state/application
import { ApplicationStateComponent } from '../../../application-state/application-state.component';
import { ApplicationStateService } from '../../../application-state/application-state.service';
import { BooleanIndicatorComponent } from '../../../boolean-indicator/boolean-indicator.component';
import { CfOrgSpaceLinksComponent } from '../../../cf-org-space-links/cf-org-space-links.component';
import { CfRoleCheckboxComponent } from '../../../cf-role-checkbox/cf-role-checkbox.component';
import { AppChipsComponent } from '../../../chips/chips.component';
import { GithubCommitAuthorComponent } from '../../../github-commit-author/github-commit-author.component';
import { RunningInstancesComponent } from '../../../running-instances/running-instances.component';
import { ServicePlanPriceComponent } from '../../../service-plan-price/service-plan-price.component';
import { ServicePlanPublicComponent } from '../../../service-plan-public/service-plan-public.component';
import { UsageGaugeComponent } from '../../../usage-gauge/usage-gauge.component';
import { EventTabActorIconPipe } from '../../list-types/app-event/table-cell-event-action/event-tab-actor-icon.pipe';
import { listTableCells, TableCellComponent } from './table-cell.component';
import { ServicePlanPublicComponent } from '../../../service-plan-public/service-plan-public.component';
import { ServicePlanPriceComponent } from '../../../service-plan-price/service-plan-price.component';

describe('TableCellComponent', () => {
let component: TableCellComponent<any>;
Expand All @@ -45,7 +46,8 @@ describe('TableCellComponent', () => {
CfRoleCheckboxComponent,
GithubCommitAuthorComponent,
ServicePlanPriceComponent,
ServicePlanPublicComponent
ServicePlanPublicComponent,
CfOrgSpaceLinksComponent
],
imports: [
CoreModule
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,29 @@
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs';

import { AppState } from '../../../../../../../store/src/app-state';
import { APIResource } from '../../../../../../../store/src/types/api.types';
import { IApp } from '../../../../../core/cf-api.types';
import { haveMultiConnectedCfs } from '../../../../../features/cloud-foundry/cf.helpers';
import { CfOrgSpaceLabelService } from '../../../../services/cf-org-space-label.service';
import { TableCellCustom } from '../../list.types';
import { APIResource } from '../../../../../../../store/src/types/api.types';
import { AppState } from '../../../../../../../store/src/app-state';


export class TableCellAppCfOrgSpaceBase extends TableCellCustom<APIResource<IApp>> {

multipleConnectedEndpoints$: Observable<boolean>;
public cfOrgSpace: CfOrgSpaceLabelService;

constructor(store: Store<AppState>) {
constructor(private store: Store<AppState>) {
super();
this.multipleConnectedEndpoints$ = haveMultiConnectedCfs(store);
}

protected init(cfGuid?: string, orgGuid?: string, spaceGuid?: string) {
if (!this.cfOrgSpace) {
this.cfOrgSpace = new CfOrgSpaceLabelService(
this.store,
cfGuid,
orgGuid,
spaceGuid
);
}
}

}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<app-meta-card class="app-card" [routerLink]="['/applications', row.entity.cfGuid , row.metadata.guid]" [status$]="appStatus$" [entityConfig]="entityConfig" [favorite]="favorite" [statusIcon]="false">
<app-meta-card class="app-card" [routerLink]="['/applications', row.entity.cfGuid , row.metadata.guid]"
[status$]="appStatus$" [entityConfig]="entityConfig" [favorite]="favorite" [statusIcon]="false">
<app-meta-card-title>
<app-multiline-title>{{ row.entity.name }}</app-multiline-title>
</app-meta-card-title>
Expand All @@ -11,25 +12,17 @@
<app-meta-card-item>
<app-meta-card-key>Instances</app-meta-card-key>
<app-meta-card-value>
<app-running-instances [instances]="row.entity.instances" [cfGuid]="row.entity.cfGuid" [appGuid]="row.entity.guid">
<app-running-instances [instances]="row.entity.instances" [cfGuid]="row.entity.cfGuid"
[appGuid]="row.entity.guid">
</app-running-instances>
</app-meta-card-value>
</app-meta-card-item>
<app-meta-card-item *ngIf="multipleConnectedEndpoints$ | async; else singleEndpoint">
<app-meta-card-key>CF/Org/Space</app-meta-card-key>
<app-meta-card-item>
<app-meta-card-key>{{cfOrgSpace.getLabel() | async}}</app-meta-card-key>
<app-meta-card-value>
{{endpointName$ | async }}/{{ row.entity.space.entity.organization.entity.name }}/{{ row.entity.space.entity.name
}}
<app-cf-org-space-links [service]="cfOrgSpace"></app-cf-org-space-links>
</app-meta-card-value>
</app-meta-card-item>
<ng-template #singleEndpoint>
<app-meta-card-item>
<app-meta-card-key>Org/Space</app-meta-card-key>
<app-meta-card-value>
{{ row.entity.space.entity.organization.entity.name }}/{{ row.entity.space.entity.name }}
</app-meta-card-value>
</app-meta-card-item>
</ng-template>
<app-meta-card-item>
<app-meta-card-key>Created</app-meta-card-key>
<app-meta-card-value>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,14 @@ import { Observable } from 'rxjs';
import { map, startWith } from 'rxjs/operators';

import { AppState } from '../../../../../../../../store/src/app-state';
import {
applicationSchemaKey,
endpointSchemaKey,
entityFactory,
} from '../../../../../../../../store/src/helpers/entity-factory';
import { selectEntity } from '../../../../../../../../store/src/selectors/api.selectors';
import { applicationSchemaKey, entityFactory } from '../../../../../../../../store/src/helpers/entity-factory';
import { APIResource } from '../../../../../../../../store/src/types/api.types';
import { EndpointModel } from '../../../../../../../../store/src/types/endpoint.types';
import { UserFavorite } from '../../../../../../../../store/src/types/user-favorites.types';
import { IAppFavMetadata } from '../../../../../../cf-favourite-types';
import { IApp } from '../../../../../../core/cf-api.types';
import { IApp, ISpace } from '../../../../../../core/cf-api.types';
import { getFavoriteFromCfEntity } from '../../../../../../core/user-favorite-helpers';
import { ApplicationService } from '../../../../../../features/applications/application.service';
import { haveMultiConnectedCfs } from '../../../../../../features/cloud-foundry/cf.helpers';
import { CfOrgSpaceLabelService } from '../../../../../services/cf-org-space-label.service';
import { CardStatus, ComponentEntityMonitorConfig } from '../../../../../shared.types';
import { ApplicationStateData, ApplicationStateService } from '../../../../application-state/application-state.service';
import { CardCell } from '../../../list.types';
Expand All @@ -33,9 +27,8 @@ export class CardAppComponent extends CardCell<APIResource<IApp>> implements OnI
applicationState$: Observable<ApplicationStateData>;

appStatus$: Observable<CardStatus>;
endpointName$: Observable<string>;
multipleConnectedEndpoints$: Observable<boolean>;
entityConfig: ComponentEntityMonitorConfig;
cfOrgSpace: CfOrgSpaceLabelService;

public favorite: UserFavorite<IAppFavMetadata>;

Expand All @@ -48,10 +41,11 @@ export class CardAppComponent extends CardCell<APIResource<IApp>> implements OnI

ngOnInit() {
this.entityConfig = new ComponentEntityMonitorConfig(this.row.metadata.guid, entityFactory(applicationSchemaKey));
this.multipleConnectedEndpoints$ = haveMultiConnectedCfs(this.store);

this.endpointName$ = this.store.select<EndpointModel>(selectEntity(endpointSchemaKey, this.row.entity.cfGuid)).pipe(
map(endpoint => endpoint ? endpoint.name : '')
this.cfOrgSpace = new CfOrgSpaceLabelService(
this.store,
this.row.entity.cfGuid,
(this.row.entity.space as APIResource<ISpace>).entity.organization_guid,
this.row.entity.space_guid
);

this.favorite = getFavoriteFromCfEntity(this.row, applicationSchemaKey);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1 @@
<span *ngIf="multipleConnectedEndpoints$ | async; else singleEndpoint">
CF/Org/Space
</span>
<ng-template #singleEndpoint>
Org/Space
</ng-template>
{{ cfOrgSpace?.getLabel() | async}}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { AppState } from './../../../../../../../../store/src/app-state';
import { Component } from '@angular/core';
import { Store } from '@ngrx/store';

import { TableCellAppCfOrgSpaceBase } from '../TableCellAppCfOrgSpaceBase';
import { AppState } from './../../../../../../../../store/src/app-state';

@Component({
selector: 'app-table-cell-app-cforgspace-header',
Expand All @@ -13,6 +13,7 @@ export class TableCellAppCfOrgSpaceHeaderComponent extends TableCellAppCfOrgSpac

constructor(store: Store<AppState>) {
super(store);
this.init();
}

}
Original file line number Diff line number Diff line change
@@ -1,6 +1 @@
<span *ngIf="multipleConnectedEndpoints$ | async; else singleEndpoint">
{{endpointName$ | async }}/{{ row.entity.space.entity.organization.entity.name }}/{{ row.entity.space.entity.name }}
</span>
<ng-template #singleEndpoint>
{{ row.entity.space.entity.organization.entity.name }}/{{ row.entity.space.entity.name }}
</ng-template>
<app-cf-org-space-links [service]="cfOrgSpace"></app-cf-org-space-links>
Original file line number Diff line number Diff line change
@@ -1,30 +1,27 @@
import { Component, OnInit } from '@angular/core';
import { Component, Input } from '@angular/core';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';

import { TableCellAppCfOrgSpaceBase } from '../TableCellAppCfOrgSpaceBase';
import { AppState } from '../../../../../../../../store/src/app-state';
import { EndpointModel } from '../../../../../../../../store/src/types/endpoint.types';
import { selectEntity } from '../../../../../../../../store/src/selectors/api.selectors';
import { endpointSchemaKey } from '../../../../../../../../store/src/helpers/entity-factory';
import { APIResource } from '../../../../../../../../store/src/types/api.types';
import { IApp, ISpace } from '../../../../../../core/cf-api.types';
import { TableCellAppCfOrgSpaceBase } from '../TableCellAppCfOrgSpaceBase';

@Component({
selector: 'app-table-cell-app-cforgspace',
templateUrl: './table-cell-app-cforgspace.component.html',
styleUrls: ['./table-cell-app-cforgspace.component.scss'],
})
export class TableCellAppCfOrgSpaceComponent extends TableCellAppCfOrgSpaceBase implements OnInit {
export class TableCellAppCfOrgSpaceComponent extends TableCellAppCfOrgSpaceBase {

endpointName$: Observable<string>;
@Input('row')
set row(row: APIResource<IApp>) {
if (row) {
this.init(row.entity.cfGuid, (row.entity.space as APIResource<ISpace>).entity.organization_guid, row.entity.space_guid);
}
}

constructor(private store: Store<AppState>) {
constructor(store: Store<AppState>) {
super(store);
}

ngOnInit() {
this.endpointName$ = this.store.select<EndpointModel>(selectEntity(endpointSchemaKey, this.row.entity.cfGuid)).pipe(
map(endpoint => endpoint ? endpoint.name : '')
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ import { ServiceActionHelperService } from '../../../../data-services/service-ac
import { CANCEL_ORG_ID_PARAM, CANCEL_SPACE_ID_PARAM } from '../../../add-service-instance/csi-mode.service';
import { ITableColumn } from '../../list-table/table.types';
import { defaultPaginationPageSizeOptionsTable, IListAction, IListConfig, ListViewTypes } from '../../list.component.types';
import {
TableCellAppCfOrgSpaceHeaderComponent,
} from '../app/table-cell-app-cforgspace-header/table-cell-app-cforgspace-header.component';
import { TableCellAppCfOrgSpaceComponent } from '../app/table-cell-app-cforgspace/table-cell-app-cforgspace.component';
import {
TableCellServiceInstanceAppsAttachedComponent,
} from '../cf-spaces-service-instances/table-cell-service-instance-apps-attached/table-cell-service-instance-apps-attached.component';
Expand All @@ -27,9 +31,6 @@ import {
import {
TableCellServicePlanComponent,
} from '../cf-spaces-service-instances/table-cell-service-plan/table-cell-service-plan.component';
import {
TableCellSpaceNameComponent,
} from '../cf-spaces-service-instances/table-cell-space-name/table-cell-space-name.component';

interface CanCache {
[spaceGuid: string]: Observable<boolean>;
Expand Down Expand Up @@ -61,9 +62,9 @@ export class CfServiceInstancesListConfigBase implements IListConfig<APIResource
},
{
columnId: 'space',
headerCell: () => 'Space',
cellComponent: TableCellSpaceNameComponent,
cellFlex: '1'
headerCellComponent: TableCellAppCfOrgSpaceHeaderComponent,
cellComponent: TableCellAppCfOrgSpaceComponent,
cellFlex: '2'
},
{
columnId: 'service',
Expand Down
Loading

0 comments on commit c34ee7e

Please sign in to comment.