diff --git a/src/frontend/app/features/service-catalog/service-summary/service-summary.component.spec.ts b/src/frontend/app/features/service-catalog/service-summary/service-summary.component.spec.ts index 140d3f714b..4804bdfb63 100644 --- a/src/frontend/app/features/service-catalog/service-summary/service-summary.component.spec.ts +++ b/src/frontend/app/features/service-catalog/service-summary/service-summary.component.spec.ts @@ -1,23 +1,9 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; - -import { CardNumberMetricComponent } from '../../../shared/components/cards/card-number-metric/card-number-metric.component'; -import { - ServiceBrokerCardComponent, -} from '../../../shared/components/cards/service-broker-card/service-broker-card.component'; -import { - ServiceRecentInstancesCardComponent, -} from '../../../shared/components/cards/service-recent-instances-card/service-recent-instances-card.component'; -import { - ServiceSummaryCardComponent, -} from '../../../shared/components/cards/service-summary-card/service-summary-card.component'; -import { TileGridComponent } from '../../../shared/components/tile/tile-grid/tile-grid.component'; -import { TileGroupComponent } from '../../../shared/components/tile/tile-group/tile-group.component'; -import { TileComponent } from '../../../shared/components/tile/tile/tile.component'; -import { BaseTestModulesNoShared, BaseTestModules } from '../../../test-framework/cloud-foundry-endpoint-service.helper'; +import { BaseTestModules } from '../../../test-framework/cloud-foundry-endpoint-service.helper'; import { ServicesService } from '../services.service'; import { ServicesServiceMock } from '../services.service.mock'; import { ServiceSummaryComponent } from './service-summary.component'; -import { ServiceIconComponent } from '../../../shared/components/service-icon/service-icon.component'; + describe('ServiceSummaryComponent', () => { let component: ServiceSummaryComponent; diff --git a/src/frontend/app/shared/components/cards/card-cf-space-details/card-cf-space-details.component.spec.ts b/src/frontend/app/shared/components/cards/card-cf-space-details/card-cf-space-details.component.spec.ts index 50b7a0722b..1ddf955eaf 100644 --- a/src/frontend/app/shared/components/cards/card-cf-space-details/card-cf-space-details.component.spec.ts +++ b/src/frontend/app/shared/components/cards/card-cf-space-details/card-cf-space-details.component.spec.ts @@ -7,6 +7,7 @@ import { } from '../../../../test-framework/cloud-foundry-endpoint-service.helper'; import { CloudFoundrySpaceServiceMock } from '../../../../test-framework/cloud-foundry-space.service.mock'; import { CardCfSpaceDetailsComponent } from './card-cf-space-details.component'; +import { EntityMonitorFactory } from '../../../monitors/entity-monitor.factory.service'; describe('CardCfSpaceDetailsComponent', () => { let component: CardCfSpaceDetailsComponent; @@ -17,7 +18,8 @@ describe('CardCfSpaceDetailsComponent', () => { declarations: [CardCfSpaceDetailsComponent, MetadataCardTestComponents], imports: [...BaseTestModulesNoShared], providers: [ - { provide: CloudFoundrySpaceService, useClass: CloudFoundrySpaceServiceMock } + { provide: CloudFoundrySpaceService, useClass: CloudFoundrySpaceServiceMock }, + EntityMonitorFactory ] }) .compileComponents(); diff --git a/src/frontend/app/shared/components/cards/service-summary-card/service-summary-card.component.spec.ts b/src/frontend/app/shared/components/cards/service-summary-card/service-summary-card.component.spec.ts index ddedb3c97c..3c270920d9 100644 --- a/src/frontend/app/shared/components/cards/service-summary-card/service-summary-card.component.spec.ts +++ b/src/frontend/app/shared/components/cards/service-summary-card/service-summary-card.component.spec.ts @@ -1,12 +1,13 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; - -import { ServiceSummaryCardComponent } from './service-summary-card.component'; +import { ServicesService } from '../../../../features/service-catalog/services.service'; +import { ServicesServiceMock } from '../../../../features/service-catalog/services.service.mock'; import { BaseTestModulesNoShared, MetadataCardTestComponents } from '../../../../test-framework/cloud-foundry-endpoint-service.helper'; -import { ServiceIconComponent } from '../../service-icon/service-icon.component'; import { BooleanIndicatorComponent } from '../../boolean-indicator/boolean-indicator.component'; import { AppChipsComponent } from '../../chips/chips.component'; -import { ServicesService } from '../../../../features/service-catalog/services.service'; -import { ServicesServiceMock } from '../../../../features/service-catalog/services.service.mock'; +import { ServiceIconComponent } from '../../service-icon/service-icon.component'; +import { ServiceSummaryCardComponent } from './service-summary-card.component'; +import { EntityMonitorFactory } from '../../../monitors/entity-monitor.factory.service'; + describe('ServiceSummaryCardComponent', () => { let component: ServiceSummaryCardComponent; @@ -24,6 +25,7 @@ describe('ServiceSummaryCardComponent', () => { imports: [BaseTestModulesNoShared], providers: [ { provide: ServicesService, useClass: ServicesServiceMock }, + EntityMonitorFactory ] }) .compileComponents(); diff --git a/src/frontend/app/shared/components/list/data-sources-controllers/list-data-source-types.ts b/src/frontend/app/shared/components/list/data-sources-controllers/list-data-source-types.ts index 0356c5fdf9..00ad527cae 100644 --- a/src/frontend/app/shared/components/list/data-sources-controllers/list-data-source-types.ts +++ b/src/frontend/app/shared/components/list/data-sources-controllers/list-data-source-types.ts @@ -33,7 +33,7 @@ export class ListActionConfig { interface ICoreListDataSource extends DataSource { rowsState?: Observable; - getRowState?(row: T): Observable; + getRowState?(row: T): Observable; trackBy(index: number, item: T); } @@ -88,6 +88,7 @@ export interface RowState { message?: string; blocked?: boolean; highlighted?: boolean; + deleting?: boolean; [customState: string]: any; } @@ -95,5 +96,6 @@ export const getDefaultRowState = (): RowState => ({ busy: false, error: false, blocked: false, + deleting: false, message: null }); diff --git a/src/frontend/app/shared/components/list/data-sources-controllers/list-data-source.ts b/src/frontend/app/shared/components/list/data-sources-controllers/list-data-source.ts index deaf3698dc..99e5849bb4 100644 --- a/src/frontend/app/shared/components/list/data-sources-controllers/list-data-source.ts +++ b/src/frontend/app/shared/components/list/data-sources-controllers/list-data-source.ts @@ -158,9 +158,7 @@ export abstract class ListDataSource extends DataSource implements this.transformEntity = config.transformEntity; this.isLocal = config.isLocal || false; this.transformEntities = config.transformEntities; - this.rowsState = config.rowsState ? config.rowsState.pipe( - publishReplay(1), refCount() - ) : observableOf({}).pipe(first()); + this.rowsState = config.rowsState; this.externalDestroy = config.destroy || (() => { }); this.addItem = this.getEmptyType(); this.entityKey = this.sourceScheme.key; @@ -180,17 +178,6 @@ export abstract class ListDataSource extends DataSource implements this.store.dispatch(this.action); }; } - /** - * Will return the row state with default values filled in. - * @param row The data for the current row - */ - getRowState(row: T) { - return this.rowsState.pipe( - map(state => ({ ...getDefaultRowState(), ...(state[this.getRowUniqueId(row)] || {}) })), - distinctUntilChanged(), - publishReplay(1), refCount() - ); - } disconnect() { this.pageSubscription.unsubscribe(); diff --git a/src/frontend/app/shared/components/list/list-cards/meta-card/meta-card-base/meta-card.component.html b/src/frontend/app/shared/components/list/list-cards/meta-card/meta-card-base/meta-card.component.html index 843408f6a6..51fa7255cf 100644 --- a/src/frontend/app/shared/components/list/list-cards/meta-card/meta-card-base/meta-card.component.html +++ b/src/frontend/app/shared/components/list/list-cards/meta-card/meta-card-base/meta-card.component.html @@ -1,10 +1,16 @@ +
+
+
Deleting
+ +
+
- diff --git a/src/frontend/app/shared/components/list/list-cards/meta-card/meta-card-base/meta-card.component.scss b/src/frontend/app/shared/components/list/list-cards/meta-card/meta-card-base/meta-card.component.scss index ff3ec9fed9..553092b160 100644 --- a/src/frontend/app/shared/components/list/list-cards/meta-card/meta-card-base/meta-card.component.scss +++ b/src/frontend/app/shared/components/list/list-cards/meta-card/meta-card-base/meta-card.component.scss @@ -3,6 +3,23 @@ flex-direction: column; height: 100%; width: 100%; + &__deleting-overlay { + align-items: center; + bottom: 0; + display: flex; + justify-content: center; + left: 0; + position: absolute; + right: 0; + top: 0; + &-inner { + width: 50%; + } + } + &__deleting-text { + margin-bottom: 5px; + text-align: center; + } &__header { align-content: center; display: flex; diff --git a/src/frontend/app/shared/components/list/list-cards/meta-card/meta-card-base/meta-card.component.spec.ts b/src/frontend/app/shared/components/list/list-cards/meta-card/meta-card-base/meta-card.component.spec.ts index 83cf2ec05d..ae3a112506 100644 --- a/src/frontend/app/shared/components/list/list-cards/meta-card/meta-card-base/meta-card.component.spec.ts +++ b/src/frontend/app/shared/components/list/list-cards/meta-card/meta-card-base/meta-card.component.spec.ts @@ -2,6 +2,7 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { MetaCardComponent } from './meta-card.component'; import { SharedModule } from '../../../../../shared.module'; +import { createBasicStoreModule } from '../../../../../../test-framework/store-test-helper'; describe('MetaCardComponent', () => { let component: MetaCardComponent; @@ -10,7 +11,8 @@ describe('MetaCardComponent', () => { beforeEach(async(() => { TestBed.configureTestingModule({ imports: [ - SharedModule + SharedModule, + createBasicStoreModule() ] }) .compileComponents(); diff --git a/src/frontend/app/shared/components/list/list-cards/meta-card/meta-card-base/meta-card.component.theme.scss b/src/frontend/app/shared/components/list/list-cards/meta-card/meta-card-base/meta-card.component.theme.scss new file mode 100644 index 0000000000..0e94f1dc6f --- /dev/null +++ b/src/frontend/app/shared/components/list/list-cards/meta-card/meta-card-base/meta-card.component.theme.scss @@ -0,0 +1,7 @@ +@import '~@angular/material/theming'; +@mixin meta-card-component($theme, $app-theme) { + $background: map-get($theme, background); + .meta-card__deleting-overlay { + background: transparentize(mat-color($background, card), .2); + } +} diff --git a/src/frontend/app/shared/components/list/list-cards/meta-card/meta-card-base/meta-card.component.ts b/src/frontend/app/shared/components/list/list-cards/meta-card/meta-card-base/meta-card.component.ts index 7d020d686b..f83f9ac633 100644 --- a/src/frontend/app/shared/components/list/list-cards/meta-card/meta-card-base/meta-card.component.ts +++ b/src/frontend/app/shared/components/list/list-cards/meta-card/meta-card-base/meta-card.component.ts @@ -1,12 +1,13 @@ -import {of as observableOf, Observable , combineLatest } from 'rxjs'; import { Component, ContentChild, ContentChildren, Input, QueryList } from '@angular/core'; - +import { combineLatest, Observable, of as observableOf } from 'rxjs'; +import { map } from 'rxjs/operators'; +import { EntityMonitorFactory } from '../../../../../monitors/entity-monitor.factory.service'; +import { ComponentEntityMonitorConfig } from '../../../../../shared.types'; import { CardStatus } from '../../../../application-state/application-state.service'; import { MetaCardItemComponent } from '../meta-card-item/meta-card-item.component'; import { MetaCardTitleComponent } from '../meta-card-title/meta-card-title.component'; -import { IPermissionConfigs } from '../../../../../../core/current-user-permissions.config'; -import { map, tap } from 'rxjs/operators'; + export interface MetaCardMenuItem { icon?: string; @@ -31,6 +32,20 @@ export class MetaCardComponent { @Input('status$') status$: Observable; + @Input('entityConfig') + set entityConfig(entityConfig: ComponentEntityMonitorConfig) { + if (entityConfig) { + const entityMonitor = this.entityMonitorFactory.create( + entityConfig.guid, + entityConfig.schema.key, + entityConfig.schema + ); + this.isDeleting$ = entityMonitor.isDeletingEntity$; + } + } + + public isDeleting$: Observable = observableOf(false); + @Input('actionMenu') set actionMenu(actionMenu: MetaCardMenuItem[]) { this._actionMenu = actionMenu.map(menuItem => { @@ -50,7 +65,7 @@ export class MetaCardComponent { @Input('clickAction') clickAction: Function = null; - constructor() { + constructor(private entityMonitorFactory: EntityMonitorFactory) { if (this.actionMenu) { this.actionMenu = this.actionMenu.map(element => { if (!element.disabled) { diff --git a/src/frontend/app/shared/components/list/list-table/table-row/table-row.component.html b/src/frontend/app/shared/components/list/list-table/table-row/table-row.component.html index 0e6d332624..04539e6b78 100644 --- a/src/frontend/app/shared/components/list/list-table/table-row/table-row.component.html +++ b/src/frontend/app/shared/components/list/list-table/table-row/table-row.component.html @@ -1,4 +1,10 @@
+
+
+
Deleting
+ +
+
diff --git a/src/frontend/app/shared/components/list/list-table/table-row/table-row.component.scss b/src/frontend/app/shared/components/list/list-table/table-row/table-row.component.scss index 37048a2739..ff66f45959 100644 --- a/src/frontend/app/shared/components/list/list-table/table-row/table-row.component.scss +++ b/src/frontend/app/shared/components/list/list-table/table-row/table-row.component.scss @@ -4,7 +4,7 @@ cursor: not-allowed; &__inner { * { - opacity: .8; + opacity: .65; } } } @@ -32,6 +32,30 @@ border-width: 0 0 1px; display: flex; transition: opacity .25s; + &-wrapper { + position: relative; + } + &__deletion-bar { + &-inner { + flex: .5; + max-width: 200px; + } + &-text { + padding-bottom: 5px; + text-align: center; + } + &-wrapper { + align-items: center; + bottom: 0; + display: flex; + justify-content: center; + left: 0; + position: absolute; + right: 0; + top: 0; + z-index: 999; + } + } &__error { display: none; justify-content: middle; diff --git a/src/frontend/app/shared/components/list/list-table/table-row/table-row.component.spec.ts b/src/frontend/app/shared/components/list/list-table/table-row/table-row.component.spec.ts index 43a50ba54a..ae267059eb 100644 --- a/src/frontend/app/shared/components/list/list-table/table-row/table-row.component.spec.ts +++ b/src/frontend/app/shared/components/list/list-table/table-row/table-row.component.spec.ts @@ -1,13 +1,11 @@ -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; - -import { TableRowComponent } from './table-row.component'; -import { Observable, of as observableOf } from 'rxjs'; -import { CoreModule } from '../../../../../core/core.module'; -import { SharedModule } from '../../../../shared.module'; import { CdkTableModule } from '@angular/cdk/table'; -import { setTimeout } from 'timers'; import { Component } from '@angular/core'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { of as observableOf } from 'rxjs'; +import { CoreModule } from '../../../../../core/core.module'; +import { TableRowComponent } from './table-row.component'; + describe('TableRowComponent', () => { diff --git a/src/frontend/app/shared/components/list/list-table/table-row/table-row.component.ts b/src/frontend/app/shared/components/list/list-table/table-row/table-row.component.ts index 775da0743a..74ebbf6f8f 100644 --- a/src/frontend/app/shared/components/list/list-table/table-row/table-row.component.ts +++ b/src/frontend/app/shared/components/list/list-table/table-row/table-row.component.ts @@ -19,10 +19,11 @@ export class TableRowComponent extends CdkRow implements OnInit { @Input('rowState') rowState: Observable; - private inErrorState$: Observable; - private errorMessage$: Observable; - private isBlocked$: Observable; - private isHighlighted$: Observable; + public inErrorState$: Observable; + public errorMessage$: Observable; + public isBlocked$: Observable; + public isHighlighted$: Observable; + public isDeleting$: Observable; ngOnInit() { if (this.rowState) { @@ -33,11 +34,14 @@ export class TableRowComponent extends CdkRow implements OnInit { map(state => state.message) ); this.isBlocked$ = this.rowState.pipe( - map(state => state.blocked) + map(state => state.blocked || state.deleting) ); this.isHighlighted$ = this.rowState.pipe( map(state => state.highlighted) ); + this.isDeleting$ = this.rowState.pipe( + map(state => state.deleting) + ); } } diff --git a/src/frontend/app/shared/components/list/list-types/app-sevice-bindings/app-service-binding-card/app-service-binding-card.component.html b/src/frontend/app/shared/components/list/list-types/app-sevice-bindings/app-service-binding-card/app-service-binding-card.component.html index 6d575f1bc5..7d7893e4ed 100644 --- a/src/frontend/app/shared/components/list/list-types/app-sevice-bindings/app-service-binding-card/app-service-binding-card.component.html +++ b/src/frontend/app/shared/components/list/list-types/app-sevice-bindings/app-service-binding-card/app-service-binding-card.component.html @@ -1,4 +1,4 @@ - +
{{ (serviceInstance$ | async)?.entity.entity.name}} diff --git a/src/frontend/app/shared/components/list/list-types/app-sevice-bindings/app-service-binding-card/app-service-binding-card.component.ts b/src/frontend/app/shared/components/list/list-types/app-sevice-bindings/app-service-binding-card/app-service-binding-card.component.ts index 3aef684ef6..92cb1c3f9a 100644 --- a/src/frontend/app/shared/components/list/list-types/app-sevice-bindings/app-service-binding-card/app-service-binding-card.component.ts +++ b/src/frontend/app/shared/components/list/list-types/app-sevice-bindings/app-service-binding-card/app-service-binding-card.component.ts @@ -1,29 +1,32 @@ - -import { combineLatest as observableCombineLatest, of as observableOf, Observable } from 'rxjs'; +import { DatePipe } from '@angular/common'; import { Component, OnInit } from '@angular/core'; import { MatDialog } from '@angular/material'; -import { Store } from '@ngrx/store'; -import { first, map, switchMap, tap, withLatestFrom, filter } from 'rxjs/operators'; +import { combineLatest as observableCombineLatest, Observable, of as observableOf } from 'rxjs'; +import { filter, map, switchMap } from 'rxjs/operators'; import { IService, IServiceBinding, IServiceInstance } from '../../../../../../core/cf-api-svc.types'; +import { CurrentUserPermissions } from '../../../../../../core/current-user-permissions.config'; +import { CurrentUserPermissionsService } from '../../../../../../core/current-user-permissions.service'; import { EntityServiceFactory } from '../../../../../../core/entity-service-factory.service'; import { ApplicationService } from '../../../../../../features/applications/application.service'; import { GetServiceInstance } from '../../../../../../store/actions/service-instances.actions'; import { GetService } from '../../../../../../store/actions/service.actions'; -import { AppState } from '../../../../../../store/app-state'; -import { entityFactory, serviceInstancesSchemaKey, serviceSchemaKey } from '../../../../../../store/helpers/entity-factory'; +import { + entityFactory, + serviceBindingSchemaKey, + serviceInstancesSchemaKey, + serviceSchemaKey, +} from '../../../../../../store/helpers/entity-factory'; import { APIResource, EntityInfo } from '../../../../../../store/types/api.types'; import { AppEnvVarsState } from '../../../../../../store/types/app-metadata.types'; +import { ServiceActionHelperService } from '../../../../../data-services/service-action-helper.service'; +import { ComponentEntityMonitorConfig } from '../../../../../shared.types'; import { AppChip } from '../../../../chips/chips.component'; -import { ConfirmationDialogConfig } from '../../../../confirmation-dialog.config'; -import { ConfirmationDialogService } from '../../../../confirmation-dialog.service'; import { EnvVarViewComponent } from '../../../../env-var-view/env-var-view.component'; import { MetaCardMenuItem } from '../../../list-cards/meta-card/meta-card-base/meta-card.component'; import { CardCell, IListRowCell, IListRowCellData } from '../../../list.types'; -import { DatePipe } from '@angular/common'; -import { ServiceActionHelperService } from '../../../../../data-services/service-action-helper.service'; -import { CurrentUserPermissionsService } from '../../../../../../core/current-user-permissions.service'; -import { CurrentUserPermissions } from '../../../../../../core/current-user-permissions.config'; + + interface EnvVarData { key: string; @@ -43,12 +46,11 @@ export class AppServiceBindingCardComponent extends CardCell>>; serviceInstance$: Observable>>; tags$: Observable[]>; + entityConfig: ComponentEntityMonitorConfig; constructor( - private store: Store, private dialog: MatDialog, private datePipe: DatePipe, - private confirmDialog: ConfirmationDialogService, private entityServiceFactory: EntityServiceFactory, private appService: ApplicationService, private serviceActionHelperService: ServiceActionHelperService, @@ -78,6 +80,7 @@ export class AppServiceBindingCardComponent extends CardCell>( serviceInstancesSchemaKey, entityFactory(serviceInstancesSchemaKey), diff --git a/src/frontend/app/shared/components/list/list-types/cf-buildpacks/cf-buildpack-card/cf-buildpack-card.component.spec.ts b/src/frontend/app/shared/components/list/list-types/cf-buildpacks/cf-buildpack-card/cf-buildpack-card.component.spec.ts index 6b29a76e7c..082de7bb5e 100644 --- a/src/frontend/app/shared/components/list/list-types/cf-buildpacks/cf-buildpack-card/cf-buildpack-card.component.spec.ts +++ b/src/frontend/app/shared/components/list/list-types/cf-buildpacks/cf-buildpack-card/cf-buildpack-card.component.spec.ts @@ -6,6 +6,7 @@ import { } from '../../../../../../test-framework/cloud-foundry-endpoint-service.helper'; import { CfBuildpackCardComponent } from './cf-buildpack-card.component'; import { BooleanIndicatorComponent } from '../../../../boolean-indicator/boolean-indicator.component'; +import { EntityMonitorFactory } from '../../../../../monitors/entity-monitor.factory.service'; describe('CfBuildpackCardComponent', () => { let component: CfBuildpackCardComponent; @@ -14,7 +15,10 @@ describe('CfBuildpackCardComponent', () => { beforeEach(async(() => { TestBed.configureTestingModule({ declarations: [CfBuildpackCardComponent, ...MetadataCardTestComponents, BooleanIndicatorComponent], - imports: [...BaseTestModulesNoShared] + imports: [...BaseTestModulesNoShared], + providers: [ + EntityMonitorFactory + ] }) .compileComponents(); })); diff --git a/src/frontend/app/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/endpoint-card.component.spec.ts b/src/frontend/app/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/endpoint-card.component.spec.ts index 94478dfdcd..c636ae5a6c 100644 --- a/src/frontend/app/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/endpoint-card.component.spec.ts +++ b/src/frontend/app/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/endpoint-card.component.spec.ts @@ -3,6 +3,10 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { CfEndpointCardComponent } from './endpoint-card.component'; 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'; describe('EndpointCardComponent', () => { let component: CfEndpointCardComponent; @@ -11,8 +15,14 @@ describe('EndpointCardComponent', () => { beforeEach(async(() => { TestBed.configureTestingModule({ imports: [ + createBasicStoreModule(), SharedModule, RouterTestingModule, + BaseTestModules, + ], + providers: [ + EntityMonitorFactory, + ServiceActionHelperService ] }) .compileComponents(); diff --git a/src/frontend/app/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/endpoint-card.component.ts b/src/frontend/app/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/endpoint-card.component.ts index 6aa95e2e31..42442646ca 100644 --- a/src/frontend/app/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/endpoint-card.component.ts +++ b/src/frontend/app/shared/components/list/list-types/cf-endpoints/cf-endpoint-card/endpoint-card.component.ts @@ -1,10 +1,10 @@ import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core'; import { ReplaySubject } from 'rxjs'; - +import { getFullEndpointApiUrl } from '../../../../../../features/endpoints/endpoint-helpers'; import { EndpointModel } from '../../../../../../store/types/endpoint.types'; import { CardStatus } from '../../../../application-state/application-state.service'; -import { TableCellCustom, CardCell } from '../../../list.types'; -import { getFullEndpointApiUrl } from '../../../../../../features/endpoints/endpoint-helpers'; +import { CardCell } from '../../../list.types'; + @Component({ selector: 'app-endpoint-card', diff --git a/src/frontend/app/shared/components/list/list-types/cf-orgs/cf-org-card/cf-org-card.component.html b/src/frontend/app/shared/components/list/list-types/cf-orgs/cf-org-card/cf-org-card.component.html index 32a09ea790..0e666e1af9 100644 --- a/src/frontend/app/shared/components/list/list-types/cf-orgs/cf-org-card/cf-org-card.component.html +++ b/src/frontend/app/shared/components/list/list-types/cf-orgs/cf-org-card/cf-org-card.component.html @@ -1,4 +1,4 @@ - + diff --git a/src/frontend/app/shared/components/list/list-types/cf-orgs/cf-org-card/cf-org-card.component.ts b/src/frontend/app/shared/components/list/list-types/cf-orgs/cf-org-card/cf-org-card.component.ts index 92d339d33c..849b60f6ba 100644 --- a/src/frontend/app/shared/components/list/list-types/cf-orgs/cf-org-card/cf-org-card.component.ts +++ b/src/frontend/app/shared/components/list/list-types/cf-orgs/cf-org-card/cf-org-card.component.ts @@ -1,27 +1,28 @@ - -import { combineLatest as observableCombineLatest, of as observableOf, Observable, Subscription } from 'rxjs'; import { Component, OnDestroy, OnInit } from '@angular/core'; import { Store } from '@ngrx/store'; +import { combineLatest as observableCombineLatest, Observable, of as observableOf, Subscription } from 'rxjs'; import { map, switchMap, tap } from 'rxjs/operators'; import { IApp, IOrganization } from '../../../../../../core/cf-api.types'; import { CurrentUserPermissions } from '../../../../../../core/current-user-permissions.config'; import { CurrentUserPermissionsService } from '../../../../../../core/current-user-permissions.service'; -import { EntityServiceFactory } from '../../../../../../core/entity-service-factory.service'; import { getOrgRolesString } from '../../../../../../features/cloud-foundry/cf.helpers'; import { CloudFoundryEndpointService, } from '../../../../../../features/cloud-foundry/services/cloud-foundry-endpoint.service'; import { RouterNav } from '../../../../../../store/actions/router.actions'; import { AppState } from '../../../../../../store/app-state'; +import { entityFactory, organizationSchemaKey } from '../../../../../../store/helpers/entity-factory'; import { APIResource } from '../../../../../../store/types/api.types'; import { EndpointUser } from '../../../../../../store/types/endpoint.types'; import { createUserRoleInOrg } from '../../../../../../store/types/user.types'; import { CfUserService } from '../../../../../data-services/cf-user.service'; +import { ComponentEntityMonitorConfig } from '../../../../../shared.types'; +import { ConfirmationDialogConfig } from '../../../../confirmation-dialog.config'; +import { ConfirmationDialogService } from '../../../../confirmation-dialog.service'; import { MetaCardMenuItem } from '../../../list-cards/meta-card/meta-card-base/meta-card.component'; import { CardCell } from '../../../list.types'; -import { ConfirmationDialogService } from '../../../../confirmation-dialog.service'; -import { ConfirmationDialogConfig } from '../../../../confirmation-dialog.config'; + @Component({ selector: 'app-cf-org-card', @@ -41,11 +42,11 @@ export class CfOrgCardComponent extends CardCell> imp appCount: number; userRolesInOrg: string; currentUser$: Observable; + public entityConfig: ComponentEntityMonitorConfig; constructor( private cfUserService: CfUserService, private cfEndpointService: CloudFoundryEndpointService, - private entityServiceFactory: EntityServiceFactory, private store: Store, private currentUserPermissionsService: CurrentUserPermissionsService, private confirmDialog: ConfirmationDialogService @@ -64,6 +65,7 @@ export class CfOrgCardComponent extends CardCell> imp can: this.currentUserPermissionsService.can(CurrentUserPermissions.ORGANIZATION_DELETE, this.cfEndpointService.cfGuid) } ]; + } ngOnInit() { @@ -89,7 +91,7 @@ export class CfOrgCardComponent extends CardCell> imp this.subscriptions.push(fetchData$.subscribe()); this.orgGuid = this.row.metadata.guid; - + this.entityConfig = new ComponentEntityMonitorConfig(this.orgGuid, entityFactory(organizationSchemaKey)); } setCounts = (apps: APIResource[]) => { diff --git a/src/frontend/app/shared/components/list/list-types/cf-services/cf-service-card/cf-service-card.component.spec.ts b/src/frontend/app/shared/components/list/list-types/cf-services/cf-service-card/cf-service-card.component.spec.ts index 828d9a5f8a..6e488af6e4 100644 --- a/src/frontend/app/shared/components/list/list-types/cf-services/cf-service-card/cf-service-card.component.spec.ts +++ b/src/frontend/app/shared/components/list/list-types/cf-services/cf-service-card/cf-service-card.component.spec.ts @@ -8,6 +8,7 @@ import { BooleanIndicatorComponent } from '../../../../boolean-indicator/boolean import { AppChipsComponent } from '../../../../chips/chips.component'; import { ServiceIconComponent } from '../../../../service-icon/service-icon.component'; import { CfServiceCardComponent } from './cf-service-card.component'; +import { EntityMonitorFactory } from '../../../../../monitors/entity-monitor.factory.service'; describe('CfServiceCardComponent', () => { let component: CfServiceCardComponent; @@ -22,7 +23,10 @@ describe('CfServiceCardComponent', () => { AppChipsComponent, ServiceIconComponent ], - imports: [...BaseTestModulesNoShared] + imports: [...BaseTestModulesNoShared], + providers: [ + EntityMonitorFactory + ] }) .compileComponents(); })); diff --git a/src/frontend/app/shared/components/list/list-types/cf-spaces/cf-space-card/cf-space-card.component.html b/src/frontend/app/shared/components/list/list-types/cf-spaces/cf-space-card/cf-space-card.component.html index ea7e6ce454..c3a18296de 100644 --- a/src/frontend/app/shared/components/list/list-types/cf-spaces/cf-space-card/cf-space-card.component.html +++ b/src/frontend/app/shared/components/list/list-types/cf-spaces/cf-space-card/cf-space-card.component.html @@ -1,4 +1,4 @@ - + diff --git a/src/frontend/app/shared/components/list/list-types/cf-spaces/cf-space-card/cf-space-card.component.ts b/src/frontend/app/shared/components/list/list-types/cf-spaces/cf-space-card/cf-space-card.component.ts index efade70641..d65d0ff524 100644 --- a/src/frontend/app/shared/components/list/list-types/cf-spaces/cf-space-card/cf-space-card.component.ts +++ b/src/frontend/app/shared/components/list/list-types/cf-spaces/cf-space-card/cf-space-card.component.ts @@ -2,27 +2,24 @@ import { Component, OnDestroy, OnInit } from '@angular/core'; import { Store } from '@ngrx/store'; import { Observable, Subscription } from 'rxjs'; import { map, switchMap, tap } from 'rxjs/operators'; - import { ISpace } from '../../../../../../core/cf-api.types'; +import { CurrentUserPermissions } from '../../../../../../core/current-user-permissions.config'; import { CurrentUserPermissionsService } from '../../../../../../core/current-user-permissions.service'; -import { EntityServiceFactory } from '../../../../../../core/entity-service-factory.service'; import { getSpaceRolesString } from '../../../../../../features/cloud-foundry/cf.helpers'; -import { - CloudFoundryEndpointService, -} from '../../../../../../features/cloud-foundry/services/cloud-foundry-endpoint.service'; -import { - CloudFoundryOrganizationService, -} from '../../../../../../features/cloud-foundry/services/cloud-foundry-organization.service'; +import { CloudFoundryEndpointService } from '../../../../../../features/cloud-foundry/services/cloud-foundry-endpoint.service'; +import { CloudFoundryOrganizationService } from '../../../../../../features/cloud-foundry/services/cloud-foundry-organization.service'; import { RouterNav } from '../../../../../../store/actions/router.actions'; import { AppState } from '../../../../../../store/app-state'; +import { entityFactory, spaceSchemaKey } from '../../../../../../store/helpers/entity-factory'; import { APIResource } from '../../../../../../store/types/api.types'; import { EndpointUser } from '../../../../../../store/types/endpoint.types'; import { CfUserService } from '../../../../../data-services/cf-user.service'; +import { ComponentEntityMonitorConfig } from '../../../../../shared.types'; +import { ConfirmationDialogConfig } from '../../../../confirmation-dialog.config'; +import { ConfirmationDialogService } from '../../../../confirmation-dialog.service'; import { MetaCardMenuItem } from '../../../list-cards/meta-card/meta-card-base/meta-card.component'; import { CardCell } from '../../../list.types'; -import { CurrentUserPermissions } from '../../../../../../core/current-user-permissions.config'; -import { ConfirmationDialogService } from '../../../../confirmation-dialog.service'; -import { ConfirmationDialogConfig } from '../../../../confirmation-dialog.config'; + @Component({ selector: 'app-cf-space-card', @@ -46,11 +43,11 @@ export class CfSpaceCardComponent extends CardCell> implemen appCount: number; userRolesInSpace: string; currentUser$: Observable; + entityConfig: ComponentEntityMonitorConfig; constructor( private cfUserService: CfUserService, private cfEndpointService: CloudFoundryEndpointService, - private entityServiceFactory: EntityServiceFactory, private store: Store, private cfOrgService: CloudFoundryOrganizationService, private currentUserPermissionsService: CurrentUserPermissionsService, @@ -61,6 +58,7 @@ export class CfSpaceCardComponent extends CardCell> implemen ngOnInit() { this.spaceGuid = this.row.metadata.guid; + this.entityConfig = new ComponentEntityMonitorConfig(this.spaceGuid, entityFactory(spaceSchemaKey)); this.orgGuid = this.cfOrgService.orgGuid; this.cardMenu = [ { diff --git a/src/frontend/app/shared/components/list/list-types/cf-stacks/cf-stacks-card/cf-stacks-card.component.spec.ts b/src/frontend/app/shared/components/list/list-types/cf-stacks/cf-stacks-card/cf-stacks-card.component.spec.ts index cd95eeaa92..8bad725ffa 100644 --- a/src/frontend/app/shared/components/list/list-types/cf-stacks/cf-stacks-card/cf-stacks-card.component.spec.ts +++ b/src/frontend/app/shared/components/list/list-types/cf-stacks/cf-stacks-card/cf-stacks-card.component.spec.ts @@ -5,6 +5,7 @@ import { MetadataCardTestComponents, } from '../../../../../../test-framework/cloud-foundry-endpoint-service.helper'; import { CfStacksCardComponent } from './cf-stacks-card.component'; +import { EntityMonitorFactory } from '../../../../../monitors/entity-monitor.factory.service'; describe('CfStacksCardComponent', () => { let component: CfStacksCardComponent; @@ -14,6 +15,9 @@ describe('CfStacksCardComponent', () => { TestBed.configureTestingModule({ declarations: [CfStacksCardComponent, MetadataCardTestComponents], imports: [...BaseTestModulesNoShared], + providers: [ + EntityMonitorFactory + ] }) .compileComponents(); })); diff --git a/src/frontend/app/shared/components/list/list-types/services-wall/service-instance-card/service-instance-card.component.html b/src/frontend/app/shared/components/list/list-types/services-wall/service-instance-card/service-instance-card.component.html index 7852734af8..c2ed8d8574 100644 --- a/src/frontend/app/shared/components/list/list-types/services-wall/service-instance-card/service-instance-card.component.html +++ b/src/frontend/app/shared/components/list/list-types/services-wall/service-instance-card/service-instance-card.component.html @@ -1,4 +1,4 @@ - +
{{ serviceInstanceEntity?.entity.name }}
diff --git a/src/frontend/app/shared/components/list/list-types/services-wall/service-instance-card/service-instance-card.component.ts b/src/frontend/app/shared/components/list/list-types/services-wall/service-instance-card/service-instance-card.component.ts index 269ca222d9..dd90f7ef72 100644 --- a/src/frontend/app/shared/components/list/list-types/services-wall/service-instance-card/service-instance-card.component.ts +++ b/src/frontend/app/shared/components/list/list-types/services-wall/service-instance-card/service-instance-card.component.ts @@ -12,6 +12,8 @@ import { MetaCardMenuItem } from '../../../list-cards/meta-card/meta-card-base/m import { CardCell } from '../../../list.types'; import { CurrentUserPermissionsService } from '../../../../../../core/current-user-permissions.service'; import { CurrentUserPermissions } from '../../../../../../core/current-user-permissions.config'; +import { ComponentEntityMonitorConfig } from '../../../../../shared.types'; +import { entityFactory, serviceInstancesSchemaKey } from '../../../../../../store/helpers/entity-factory'; @Component({ selector: 'app-service-instance-card', @@ -28,10 +30,12 @@ export class ServiceInstanceCardComponent extends CardCell ({ value: t @@ -42,8 +46,6 @@ export class ServiceInstanceCardComponent extends CardCell, - private servicesWallService: ServicesWallService, private serviceActionHelperService: ServiceActionHelperService, private currentUserPermissionsService: CurrentUserPermissionsService ) { @@ -51,7 +53,6 @@ export class ServiceInstanceCardComponent extends CardCell ({ value: t })); @@ -109,7 +110,7 @@ export class ServiceInstanceCardComponent extends CardCell implements OnInit, OnDestroy, AfterViewInit { this.singleActions = this.config.getSingleActions(); this.columns = this.config.getColumns(); this.dataSource = this.config.getDataSource(); + if (!this.dataSource.getRowState) { + const schema = entityFactory(this.dataSource.entityKey); + this.dataSource.getRowState = this.getRowStateGeneratorFromEntityMonitor(schema, this.dataSource); + } this.multiFilterConfigs = this.config.getMultiFiltersConfigs(); // Create convenience observables that make the html clearer @@ -531,4 +538,21 @@ export class ListComponent implements OnInit, OnDestroy, AfterViewInit { } return actions; } + + private getRowStateGeneratorFromEntityMonitor(entitySchema: schema.Entity, dataSource: IListDataSource) { + return (row) => { + if (!entitySchema || !row) { + return observableOf(getDefaultRowState()); + } + const entityMonitor = new EntityMonitor(this.store, dataSource.getRowUniqueId(row), dataSource.entityKey, entitySchema); + return entityMonitor.entityRequest$.pipe( + distinctUntilChanged(), + map(requestInfor => ({ + deleting: requestInfor.deleting.busy, + error: requestInfor.deleting.error, + message: requestInfor.deleting.error ? `Sorry, deletion failed` : null + })) + ); + }; + } } diff --git a/src/frontend/app/shared/shared.types.ts b/src/frontend/app/shared/shared.types.ts new file mode 100644 index 0000000000..d30f45e142 --- /dev/null +++ b/src/frontend/app/shared/shared.types.ts @@ -0,0 +1,5 @@ +import { schema } from 'normalizr'; + +export class ComponentEntityMonitorConfig { + constructor(public guid: string, public schema: schema.Entity) { } +} diff --git a/src/frontend/sass/_all-theme.scss b/src/frontend/sass/_all-theme.scss index 5a0a5895e6..791937dfda 100644 --- a/src/frontend/sass/_all-theme.scss +++ b/src/frontend/sass/_all-theme.scss @@ -32,6 +32,7 @@ @import '../app/features/applications/deploy-application/deploy-application-step2/deploy-application-fs/deploy-application-fs.component.theme'; @import '../app/shared/components/app-action-monitor-icon/app-action-monitor-icon.component.theme'; @import '../app/shared/components/upload-progress-indicator/upload-progress-indicator.component.theme'; +@import '../app/shared/components/list/list-cards/meta-card/meta-card-base/meta-card.component.theme'; @import './components/mat-tabs.theme'; @import './components/text-status.theme'; @import './components/hyperlinks.theme'; @@ -103,6 +104,7 @@ $side-nav-light-active: #484848; @include app-upload-progress-indicator-component-theme($theme, $app-theme); @include page-404($theme, $app-theme); @include about-page-theme($theme, $app-theme); + @include meta-card-component($theme, $app-theme); } @function app-generate-nav-theme($theme, $nav-theme: null) {