Skip to content

Commit

Permalink
Blitz - Add actions to app service table, add delete org button to or…
Browse files Browse the repository at this point in the history
…g summary (#4063)

* Ensure stratosEndpointGuidKey is not lost in mergeEntity after entity is updated

* Show edit/unbind actions in apps service instance table

* Add delete org button to org summary page

* Fix failing unit tests

* Fixes following review
  • Loading branch information
richard-cox authored and nwmac committed Jan 7, 2020
1 parent 0270198 commit 570b2aa
Show file tree
Hide file tree
Showing 11 changed files with 213 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { APIResource } from '../../../../../../store/src/types/api.types';
import {
AppServiceBindingListConfigService,
} from '../../../../shared/components/list/list-types/app-sevice-bindings/app-service-binding-list-config.service';
import { ServiceActionHelperService } from '../../../../shared/data-services/service-action-helper.service';
import { ApplicationService } from '../../application.service';

@Injectable()
Expand All @@ -49,9 +50,10 @@ export class AppDeleteServiceInstancesListConfigService extends AppServiceBindin
appService: ApplicationService,
datePipe: DatePipe,
currentUserPermissionService: CurrentUserPermissionsService,
private paginationMonitorFactory: PaginationMonitorFactory
private paginationMonitorFactory: PaginationMonitorFactory,
serviceActionHelperService: ServiceActionHelperService
) {
super(store, appService, datePipe, currentUserPermissionService);
super(store, appService, datePipe, currentUserPermissionService, serviceActionHelperService);

this.getGlobalActions = () => null;
this.getMultiActions = () => null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { generateTestApplicationServiceProvider } from '../../../../../../core/t
import { generateTestEntityServiceProvider } from '../../../../../../core/test-framework/entity-service.helper';
import { generateCfBaseTestModules } from '../../../../../test-framework/cloud-foundry-endpoint-service.helper';
import { applicationEntityType } from '../../../../cf-entity-types';
import { ServiceActionHelperService } from '../../../../shared/data-services/service-action-helper.service';
import {
ApplicationEnvVarsHelper,
} from '../../application/application-tabs-base/tabs/build-tab/application-env-vars.service';
Expand All @@ -29,7 +30,8 @@ describe('DeleteAppInstancesComponent', () => {
),
generateTestApplicationServiceProvider(cfId, appId),
ApplicationEnvVarsHelper,
DatePipe
DatePipe,
ServiceActionHelperService
]
})
.compileComponents();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,8 @@ import { PaginationMonitorFactory } from '../../../../../../../../core/src/share
import {
generateTestApplicationServiceProvider,
} from '../../../../../../../../core/test-framework/application-service-helper';
import {
generateCfBaseTestModules,
} from '../../../../../../../test-framework/cloud-foundry-endpoint-service.helper';
import { generateCfBaseTestModules } from '../../../../../../../test-framework/cloud-foundry-endpoint-service.helper';
import { ServiceActionHelperService } from '../../../../../../shared/data-services/service-action-helper.service';
import { ApplicationEnvVarsHelper } from '../build-tab/application-env-vars.service';
import { ServicesTabComponent } from './services-tab.component';

Expand All @@ -29,7 +28,8 @@ describe('ServicesTabComponent', () => {
ApplicationEnvVarsHelper,
ApplicationStateService,
PaginationMonitorFactory,
DatePipe
DatePipe,
ServiceActionHelperService
]
})
.compileComponents();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
matTooltip="Edit Organization">
<mat-icon>mode_edit</mat-icon>
</button>
<button mat-icon-button name="delete"
*appUserPermission="permsOrgDelete;endpointGuid:cfOrgService.cfGuid;organizationGuid:cfOrgService.orgGuid;"
(click)="deleteOrgWarn()" matTooltip="Delete Organization">
<mat-icon>delete</mat-icon>
</button>
<button mat-icon-button name="cli"
routerLink="/cloud-foundry/{{cfEndpointService.cfGuid}}/organizations/{{cfOrgService.orgGuid}}/cli"
matTooltip="CLI Info">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
import { Component } from '@angular/core';
import { MatSnackBar } from '@angular/material';
import { Store } from '@ngrx/store';
import { combineLatest, Observable } from 'rxjs';
import { filter, map, startWith } from 'rxjs/operators';
import { filter, first, map, pairwise, startWith, tap } from 'rxjs/operators';

import { CFAppState } from '../../../../../../../cloud-foundry/src/cf-app-state';
import { CurrentUserPermissions } from '../../../../../../../core/src/core/current-user-permissions.config';
import { entityCatalogue } from '../../../../../../../core/src/core/entity-catalogue/entity-catalogue.service';
import { ConfirmationDialogConfig } from '../../../../../../../core/src/shared/components/confirmation-dialog.config';
import { ConfirmationDialogService } from '../../../../../../../core/src/shared/components/confirmation-dialog.service';
import { RouterNav } from '../../../../../../../store/src/actions/router.actions';
import { selectDeletionInfo } from '../../../../../../../store/src/selectors/api.selectors';
import { CF_ENDPOINT_TYPE } from '../../../../../../cf-types';
import { organizationEntityType } from '../../../../../cf-entity-types';
import { goToAppWall } from '../../../cf.helpers';
import { CloudFoundryEndpointService } from '../../../services/cloud-foundry-endpoint.service';
import { CloudFoundryOrganizationService } from '../../../services/cloud-foundry-organization.service';
Expand All @@ -19,11 +27,14 @@ export class CloudFoundryOrganizationSummaryComponent {
appLink: () => void;
detailsLoading$: Observable<boolean>;
public permsOrgEdit = CurrentUserPermissions.ORGANIZATION_EDIT;
public permsOrgDelete = CurrentUserPermissions.ORGANIZATION_DELETE;

constructor(
store: Store<CFAppState>,
private store: Store<CFAppState>,
public cfEndpointService: CloudFoundryEndpointService,
public cfOrgService: CloudFoundryOrganizationService
public cfOrgService: CloudFoundryOrganizationService,
private confirmDialog: ConfirmationDialogService,
private snackBar: MatSnackBar
) {
this.appLink = () => {
goToAppWall(store, cfOrgService.cfGuid, cfOrgService.orgGuid);
Expand All @@ -38,6 +49,46 @@ export class CloudFoundryOrganizationSummaryComponent {
map(() => false),
startWith(true)
);
}

deleteOrgWarn() {
this.cfOrgService.org$.pipe(
map(org => org.entity.entity.name),
first()
).subscribe(name => {
const confirmation = new ConfirmationDialogConfig(
'Delete Organization',
{
textToMatch: name
},
'Delete',
true,
);
this.confirmDialog.open(confirmation, () => {
this.cfEndpointService.deleteOrg(
this.cfOrgService.orgGuid,
this.cfEndpointService.cfGuid
);

const orgEntity = entityCatalogue.getEntity(CF_ENDPOINT_TYPE, organizationEntityType);
this.store.select(selectDeletionInfo(orgEntity.entityKey, this.cfOrgService.orgGuid)).pipe(
pairwise(),
filter(([oldV, newV]) => (oldV.busy && !newV.busy) || newV.error),
tap(([, newV]) => {
if (newV.deleted) {
this.store.dispatch(new RouterNav({
path: [
'cloud-foundry',
this.cfOrgService.cfGuid,
'organizations'
]
}));
} else if (newV.error) {
this.snackBar.open(`Failed to delete space: ${newV.message}`, 'Close');
}
})
).subscribe();
});
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@ export class AppServiceBindingCardComponent extends CardCell<APIResource<IServic
)))
}];
}
ngOnInit(): void {

ngOnInit() {
this.entityConfig = new ComponentEntityMonitorConfig(this.row.metadata.guid, cfEntityFactory(serviceBindingEntityType));

this.isUserProvidedServiceInstance = !!isUserProvidedServiceInstance(this.row.entity.service_instance.entity);
Expand All @@ -125,8 +126,8 @@ export class AppServiceBindingCardComponent extends CardCell<APIResource<IServic
}

private setupAsServiceInstance() {
const serviceIntanceEntity = entityCatalogue.getEntity(CF_ENDPOINT_TYPE, serviceInstancesEntityType);
const actionBuilder = serviceIntanceEntity.actionOrchestrator.getActionBuilder('get');
const serviceInstanceEntity = entityCatalogue.getEntity(CF_ENDPOINT_TYPE, serviceInstancesEntityType);
const actionBuilder = serviceInstanceEntity.actionOrchestrator.getActionBuilder('get');
const getServiceInstanceAction = actionBuilder(this.row.entity.service_instance_guid, this.appService.cfGuid);
const serviceInstance$ = this.entityServiceFactory.create<APIResource<IServiceInstance>>(
this.row.entity.service_instance_guid,
Expand Down Expand Up @@ -237,7 +238,7 @@ export class AppServiceBindingCardComponent extends CardCell<APIResource<IServic
});
}

detach = () => {
private detach = () => {
this.serviceActionHelperService.detachServiceBinding(
[this.row],
this.row.entity.service_instance_guid,
Expand All @@ -247,7 +248,7 @@ export class AppServiceBindingCardComponent extends CardCell<APIResource<IServic
);
}

edit = () => this.serviceActionHelperService.editServiceBinding(
private edit = () => this.serviceActionHelperService.editServiceBinding(
this.row.entity.service_instance_guid,
this.appService.cfGuid,
{ appId: this.appService.appGuid },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { generateCfBaseTestModules } from '../../../../../../test-framework/clou
import {
ApplicationEnvVarsHelper,
} from '../../../../../features/applications/application/application-tabs-base/tabs/build-tab/application-env-vars.service';
import { ServiceActionHelperService } from '../../../../data-services/service-action-helper.service';
import { AppServiceBindingListConfigService } from './app-service-binding-list-config.service';

describe('AppServiceBindingListConfigService', () => {
Expand All @@ -15,7 +16,8 @@ describe('AppServiceBindingListConfigService', () => {
AppServiceBindingListConfigService,
generateTestApplicationServiceProvider('1', '1'),
ApplicationEnvVarsHelper,
DatePipe
DatePipe,
ServiceActionHelperService
],
imports: generateCfBaseTestModules()
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,18 @@ import {
DataFunctionDefinition,
} from '../../../../../../../core/src/shared/components/list/data-sources-controllers/list-data-source';
import { ITableColumn } from '../../../../../../../core/src/shared/components/list/list-table/table.types';
import { IGlobalListAction, ListViewTypes } from '../../../../../../../core/src/shared/components/list/list.component.types';
import {
IGlobalListAction,
IListAction,
ListViewTypes,
} from '../../../../../../../core/src/shared/components/list/list.component.types';
import { ListView } from '../../../../../../../store/src/actions/list.actions';
import { RouterNav } from '../../../../../../../store/src/actions/router.actions';
import { APIResource } from '../../../../../../../store/src/types/api.types';
import { GetAppServiceBindings } from '../../../../../actions/application-service-routes.actions';
import { ApplicationService } from '../../../../../features/applications/application.service';
import { isServiceInstance } from '../../../../../features/cloud-foundry/cf.helpers';
import { isServiceInstance, isUserProvidedServiceInstance } from '../../../../../features/cloud-foundry/cf.helpers';
import { ServiceActionHelperService } from '../../../../data-services/service-action-helper.service';
import { BaseCfListConfig } from '../base-cf/base-cf-list-config';
import {
TableCellServiceInstanceTagsComponent,
Expand Down Expand Up @@ -47,7 +53,51 @@ export class AppServiceBindingListConfigService extends BaseCfListConfig<APIReso
)
};

getColumns = (): Array<ITableColumn<APIResource<IServiceBinding>>> => {
private listActionEdit: IListAction<APIResource<IServiceBinding>> = {
action: (item) => {
this.serviceActionHelperService.editServiceBinding(
item.entity.service_instance_guid,
this.appService.cfGuid,
{ appId: this.appService.appGuid },
!!isUserProvidedServiceInstance(item.entity.service_instance.entity)
).subscribe(res => {
if (!res.error) {
this.store.dispatch(new GetAppServiceBindings(this.appService.appGuid, this.appService.cfGuid));
}
});
},
label: 'Edit',
createVisible: () => this.appService.waitForAppEntity$.pipe(
switchMap(app => this.currentUserPermissionsService.can(
CurrentUserPermissions.SERVICE_BINDING_EDIT,
this.appService.cfGuid,
app.entity.entity.space_guid
))
)
};

private listActionUnbind: IListAction<APIResource<IServiceBinding>> = {
action: (item) => {
this.serviceActionHelperService.detachServiceBinding(
[item],
item.entity.service_instance_guid,
this.appService.cfGuid,
false,
!!isUserProvidedServiceInstance(item.entity.service_instance.entity)
);

},
label: 'Unbind',
createVisible: () => this.appService.waitForAppEntity$.pipe(
switchMap(app => this.currentUserPermissionsService.can(
CurrentUserPermissions.SERVICE_BINDING_EDIT,
this.appService.cfGuid,
app.entity.entity.space_guid
))
)
};

getColumns = (): ITableColumn<APIResource<IServiceBinding>>[] => {
return [
{
columnId: 'name',
Expand Down Expand Up @@ -106,14 +156,18 @@ export class AppServiceBindingListConfigService extends BaseCfListConfig<APIReso
private appService: ApplicationService,
private datePipe: DatePipe,
protected currentUserPermissionsService: CurrentUserPermissionsService,
private serviceActionHelperService: ServiceActionHelperService
) {
super();
this.dataSource = new AppServiceBindingDataSource(this.store, appService, this);
}

getGlobalActions = () => [this.listActionAdd];
getMultiActions = () => [];
getSingleActions = () => [];
getSingleActions = () => [
this.listActionEdit,
this.listActionUnbind,
]
getMultiFiltersConfigs = () => [];
getDataSource = () => this.dataSource;
}
Loading

0 comments on commit 570b2aa

Please sign in to comment.