Skip to content

Commit

Permalink
Merge pull request #2415 from cloudfoundry-incubator/table-card-deleting
Browse files Browse the repository at this point in the history
Show an overlay and deleting message when deleting from a card or table action.
  • Loading branch information
richard-cox authored Jun 18, 2018
2 parents bf6d5b6 + 9ba447e commit d547a8c
Show file tree
Hide file tree
Showing 30 changed files with 219 additions and 104 deletions.
Original file line number Diff line number Diff line change
@@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -17,7 +18,8 @@ describe('CardCfSpaceDetailsComponent', () => {
declarations: [CardCfSpaceDetailsComponent, MetadataCardTestComponents],
imports: [...BaseTestModulesNoShared],
providers: [
{ provide: CloudFoundrySpaceService, useClass: CloudFoundrySpaceServiceMock }
{ provide: CloudFoundrySpaceService, useClass: CloudFoundrySpaceServiceMock },
EntityMonitorFactory
]
})
.compileComponents();
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -24,6 +25,7 @@ describe('ServiceSummaryCardComponent', () => {
imports: [BaseTestModulesNoShared],
providers: [
{ provide: ServicesService, useClass: ServicesServiceMock },
EntityMonitorFactory
]
})
.compileComponents();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export class ListActionConfig<T> {

interface ICoreListDataSource<T> extends DataSource<T> {
rowsState?: Observable<RowsState>;
getRowState?(row: T): Observable<RowsState>;
getRowState?(row: T): Observable<RowState>;
trackBy(index: number, item: T);
}

Expand Down Expand Up @@ -88,12 +88,14 @@ export interface RowState {
message?: string;
blocked?: boolean;
highlighted?: boolean;
deleting?: boolean;
[customState: string]: any;
}

export const getDefaultRowState = (): RowState => ({
busy: false,
error: false,
blocked: false,
deleting: false,
message: null
});
Original file line number Diff line number Diff line change
Expand Up @@ -158,9 +158,7 @@ export abstract class ListDataSource<T, A = T> extends DataSource<T> 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;
Expand All @@ -180,17 +178,6 @@ export abstract class ListDataSource<T, A = T> extends DataSource<T> 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();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
<mat-card class="meta-card" [ngClass]="clickAction ? 'meta-card-pointer' : ''" (click)="clickAction ? clickAction() : null">
<div *ngIf="isDeleting$ | async" class="meta-card__deleting-overlay">
<div class="meta-card__deleting-overlay-inner">
<div class="meta-card__deleting-text">Deleting</div>
<mat-progress-bar mode="indeterminate"></mat-progress-bar>
</div>
</div>
<app-card-status *ngIf="status$" [status$]="status$">
</app-card-status>
<mat-card-header class="meta-card__header" *ngIf="title">
<ng-container *ngTemplateOutlet="title.content"></ng-container>
<div *ngIf="_actionMenu && (showMenu$ | async)" appClickStopPropagation>
<button mat-icon-button class="meta-card__header__button" color="basic" [matMenuTriggerFor]="menu">
<button mat-icon-button class="meta-card__header__button" color="basic" [matMenuTriggerFor]="menu" [disabled]="isDeleting$ | async">
<mat-icon>more_vert</mat-icon>
</button>
<mat-menu class="meta-card__header__popup" #menu="matMenu">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -10,7 +11,8 @@ describe('MetaCardComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
SharedModule
SharedModule,
createBasicStoreModule()
]
})
.compileComponents();
Expand Down
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -31,6 +32,20 @@ export class MetaCardComponent {
@Input('status$')
status$: Observable<CardStatus>;

@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<boolean> = observableOf(false);

@Input('actionMenu')
set actionMenu(actionMenu: MetaCardMenuItem[]) {
this._actionMenu = actionMenu.map(menuItem => {
Expand All @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
<div class="table-row-wrapper" [ngClass]="{'table-row-wrapper__blocked': isBlocked$ | async, 'table-row-wrapper__errored': inErrorState$ | async,'table-row-wrapper__highlighted': isHighlighted$ | async }">
<div *ngIf="isDeleting$ | async" class="table-row__deletion-bar-wrapper">
<div class="table-row__deletion-bar-inner">
<div class="table-row__deletion-bar-text">Deleting</div>
<mat-progress-bar class="table-row__deletion-bar" mode="indeterminate"></mat-progress-bar>
</div>
</div>
<div role="row" class="table-row">
<div class="mat-row table-row__inner">
<ng-container cdkCellOutlet></ng-container>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
cursor: not-allowed;
&__inner {
* {
opacity: .8;
opacity: .65;
}
}
}
Expand Down Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
@@ -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', () => {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@ export class TableRowComponent extends CdkRow implements OnInit {
@Input('rowState')
rowState: Observable<RowState>;

private inErrorState$: Observable<boolean>;
private errorMessage$: Observable<string>;
private isBlocked$: Observable<boolean>;
private isHighlighted$: Observable<boolean>;
public inErrorState$: Observable<boolean>;
public errorMessage$: Observable<string>;
public isBlocked$: Observable<boolean>;
public isHighlighted$: Observable<boolean>;
public isDeleting$: Observable<boolean>;

ngOnInit() {
if (this.rowState) {
Expand All @@ -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)
);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<app-meta-card class="app-service-card" [actionMenu]="cardMenu">
<app-meta-card class="app-service-card" [actionMenu]="cardMenu" [entityConfig]="entityConfig">
<app-meta-card-title>
<div class="app-service-card__title">
{{ (serviceInstance$ | async)?.entity.entity.name}}
Expand Down
Loading

0 comments on commit d547a8c

Please sign in to comment.