Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show refresh button for latest modified application lists #3213

Merged
merged 9 commits into from
Jan 9, 2019
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export class CloudFoundryEndpointService {
paginationSubscription: any;
allApps$: Observable<APIResource<IApp>[]>;
hasAllApps$: Observable<boolean>;
loadingApps$: Observable<boolean>;
totalApps$: Observable<number>;
users$: Observable<APIResource<CfUser>[]>;
orgs$: Observable<APIResource<IOrganization>[]>;
Expand All @@ -73,6 +74,8 @@ export class CloudFoundryEndpointService {

getAllOrgsAction: GetAllOrganizations;

private getAllAppsAction: GetAllApplications;

static createGetAllOrganizations(cfGuid: string) {
const paginationKey = cfGuid ?
createEntityRelationPaginationKey(endpointSchemaKey, cfGuid)
Expand Down Expand Up @@ -100,12 +103,7 @@ export class CloudFoundryEndpointService {
]);
}

public static fetchAppCount(
store: Store<AppState>,
pmf: PaginationMonitorFactory,
cfGuid: string,
orgGuid?: string,
spaceGuid?: string)
public static fetchAppCount(store: Store<AppState>, pmf: PaginationMonitorFactory, cfGuid: string, orgGuid?: string, spaceGuid?: string)
: Observable<number> {
const parentSchemaKey = spaceGuid ? spaceSchemaKey : orgGuid ? organizationSchemaKey : 'cf';
const uniqueKey = spaceGuid || orgGuid || cfGuid;
Expand All @@ -127,11 +125,11 @@ export class CloudFoundryEndpointService {
private store: Store<AppState>,
private entityServiceFactory: EntityServiceFactory,
private cfUserService: CfUserService,
private paginationMonitorFactory: PaginationMonitorFactory,
private pmf: PaginationMonitorFactory
) {
this.cfGuid = activeRouteCfOrgSpace.cfGuid;
this.getAllOrgsAction = CloudFoundryEndpointService.createGetAllOrganizations(this.cfGuid);
this.getAllAppsAction = new GetAllApplications(createEntityRelationPaginationKey('cf', this.cfGuid), this.cfGuid);

this.cfEndpointEntityService = this.entityServiceFactory.create(
endpointSchemaKey,
Expand All @@ -150,7 +148,6 @@ export class CloudFoundryEndpointService {
);
this.constructCoreObservables();
this.constructSecondaryObservable();

}

private constructCoreObservables() {
Expand All @@ -159,7 +156,7 @@ export class CloudFoundryEndpointService {
this.orgs$ = getPaginationObservables<APIResource<IOrganization>>({
store: this.store,
action: this.getAllOrgsAction,
paginationMonitor: this.paginationMonitorFactory.create(
paginationMonitor: this.pmf.create(
this.getAllOrgsAction.paginationKey,
entityFactory(organizationSchemaKey)
)
Expand All @@ -175,12 +172,11 @@ export class CloudFoundryEndpointService {
}

constructAppObservables() {
const action = new GetAllApplications(createEntityRelationPaginationKey('cf', this.cfGuid), this.cfGuid);

const pagObs = getPaginationObservables<APIResource<IApp>>({
store: this.store,
action,
paginationMonitor: this.pmf.create(action.paginationKey, entityFactory(action.entityKey))
action: this.getAllAppsAction,
paginationMonitor: this.pmf.create(this.getAllAppsAction.paginationKey, entityFactory(this.getAllAppsAction.entityKey))
});

this.allApps$ = pagObs.entities$.pipe(// Ensure we sub to entities to kick off fetch process
Expand All @@ -189,6 +185,12 @@ export class CloudFoundryEndpointService {
switchMap(pagination => pagination.maxedResults ? observableOf(null) : pagObs.entities$)
);

this.loadingApps$ = pagObs.entities$.pipe(// Ensure we sub to entities to kick off fetch process
switchMap(() => pagObs.pagination$),
filter(pagination => !!pagination && !!pagination.pageRequests && !!pagination.pageRequests[pagination.currentPage]),
map(pagination => pagination.pageRequests[pagination.currentPage].busy)
);

this.hasAllApps$ = this.allApps$.pipe(
map((allApps: APIResource<IApp>[]) => !!allApps)
);
Expand All @@ -199,7 +201,6 @@ export class CloudFoundryEndpointService {
}

private constructSecondaryObservable() {

this.hasSSHAccess$ = this.info$.pipe(
map(p => !!(p.entity.entity &&
p.entity.entity.app_ssh_endpoint &&
Expand All @@ -213,12 +214,9 @@ export class CloudFoundryEndpointService {
);

this.currentUser$ = this.endpoint$.pipe(map(e => e.entity.user), first(), publishReplay(1), refCount());

}

public getAppsInOrgViaAllApps(
org: APIResource<IOrganization>
): Observable<APIResource<IApp>[]> {
public getAppsInOrgViaAllApps(org: APIResource<IOrganization>): Observable<APIResource<IApp>[]> {
return this.allApps$.pipe(
filter(allApps => !!allApps),
map(allApps => {
Expand All @@ -228,9 +226,7 @@ export class CloudFoundryEndpointService {
);
}

public getAppsInSpaceViaAllApps(
space: APIResource<ISpace>
): Observable<APIResource<IApp>[]> {
public getAppsInSpaceViaAllApps(space: APIResource<ISpace>): Observable<APIResource<IApp>[]> {
return this.allApps$.pipe(
filter(allApps => !!allApps),
map(apps => {
Expand All @@ -239,10 +235,7 @@ export class CloudFoundryEndpointService {
);
}

public getMetricFromApps(
apps: APIResource<IApp>[],
statMetric: string
): number {
public getMetricFromApps(apps: APIResource<IApp>[], statMetric: string): number {
return apps ? apps
.filter(a => a.entity && a.entity.state !== CfApplicationState.STOPPED)
.map(a => a.entity[statMetric] * a.entity.instances)
Expand All @@ -255,7 +248,7 @@ export class CloudFoundryEndpointService {
{
store: this.store,
action,
paginationMonitor: this.paginationMonitorFactory.create(
paginationMonitor: this.pmf.create(
action.paginationKey,
entityFactory(domainSchemaKey)
)
Expand All @@ -267,4 +260,8 @@ export class CloudFoundryEndpointService {
public deleteOrg(orgGuid: string, endpointGuid: string) {
this.store.dispatch(new DeleteOrganization(orgGuid, endpointGuid));
}

fetchApps() {
this.store.dispatch(this.getAllAppsAction);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Injectable } from '@angular/core';
import { Route } from '@angular/router';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs';
import { filter, map, publishReplay, refCount, switchMap } from 'rxjs/operators';
import { filter, map, publishReplay, refCount, switchMap, startWith } from 'rxjs/operators';

import { IServiceInstance } from '../../../core/cf-api-svc.types';
import { IApp, IOrganization, IPrivateDomain, IQuotaDefinition, ISpace } from '../../../core/cf-api.types';
Expand Down Expand Up @@ -62,6 +62,7 @@ export class CloudFoundryOrganizationService {
appInstances$: Observable<number>;
apps$: Observable<APIResource<IApp>[]>;
appCount$: Observable<number>;
loadingApps$: Observable<boolean>;
org$: Observable<EntityInfo<APIResource<IOrganization>>>;
allOrgUsers$: Observable<APIResource<CfUser>[]>;
usersPaginationKey: string;
Expand All @@ -85,6 +86,10 @@ export class CloudFoundryOrganizationService {
this.store.dispatch(new DeleteSpace(spaceGuid, orgGuid, endpointGuid));
}

public fetchApps() {
this.cfEndpointService.fetchApps();
}

private initialiseObservables() {
this.org$ = this.cfUserService.isConnectedUserAdmin(this.cfGuid).pipe(
switchMap(isAdmin => {
Expand Down Expand Up @@ -151,6 +156,8 @@ export class CloudFoundryOrganizationService {
this.appCount$ = this.cfEndpointService.hasAllApps$.pipe(
switchMap(hasAllApps => hasAllApps ? this.countExistingApps() : this.fetchAppCount()),
);

this.loadingApps$ = this.cfEndpointService.loadingApps$;
}

private countExistingApps(): Observable<number> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export class CloudFoundrySpaceService {
appInstances$: Observable<number>;
apps$: Observable<APIResource<IApp>[]>;
appCount$: Observable<number>;
loadingApps$: Observable<boolean>;
space$: Observable<EntityInfo<APIResource<ISpace>>>;
allSpaceUsers$: Observable<APIResource<CfUser>[]>;
usersPaginationKey: string;
Expand All @@ -70,6 +71,10 @@ export class CloudFoundrySpaceService {
this.initialiseObservables();
}

public fetchApps() {
this.cfEndpointService.fetchApps();
}

private initialiseObservables() {
this.initialiseSpaceObservables();
this.initialiseAppObservables();
Expand Down Expand Up @@ -158,10 +163,11 @@ export class CloudFoundrySpaceService {
map(a => this.cfEndpointService.getMetricFromApps(a, 'memory'))
);


this.appCount$ = this.cfEndpointService.hasAllApps$.pipe(
switchMap(hasAllApps => hasAllApps ? this.countExistingApps() : this.fetchAppCount()),
);

this.loadingApps$ = this.cfEndpointService.loadingApps$;
}

private countExistingApps(): Observable<number> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@

<app-tile-group>
<app-tile>
<app-card-cf-recent-apps *ngIf="!(detailsLoading$ | async)" [allApps$]="cfSpaceService.apps$"></app-card-cf-recent-apps>
<app-card-cf-recent-apps *ngIf="!(detailsLoading$ | async)" [allApps$]="cfSpaceService.apps$" [loading$]="cfSpaceService.loadingApps$" (refresh)="cfSpaceService.fetchApps()"></app-card-cf-recent-apps>
</app-tile>
</app-tile-group>
</app-loading-page>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
</app-tile-group>
<app-tile-group>
<app-tile>
<app-card-cf-recent-apps *ngIf="!(detailsLoading$ | async)" [allApps$]="cfOrgService.apps$"></app-card-cf-recent-apps>
<app-card-cf-recent-apps *ngIf="!(detailsLoading$ | async)" [allApps$]="cfOrgService.apps$" [loading$]="cfOrgService.loadingApps$" (refresh)="cfOrgService.fetchApps()"></app-card-cf-recent-apps>
</app-tile>
</app-tile-group>
</app-loading-page>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
</app-tile-group>
<app-tile-group>
<app-tile>
<app-card-cf-recent-apps *ngIf="!(detailsLoading$ | async)" [allApps$]="cfEndpointService.allApps$"></app-card-cf-recent-apps>
<app-card-cf-recent-apps *ngIf="!(detailsLoading$ | async)" [allApps$]="cfEndpointService.allApps$" [loading$]="cfEndpointService.loadingApps$" (refresh)="cfEndpointService.fetchApps()"></app-card-cf-recent-apps>
</app-tile>
</app-tile-group>
</app-loading-page>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
<mat-card class="recent-apps-card">
<mat-card-header class="recent-apps-card__header">
<mat-card-title>Recently updated applications</mat-card-title>
<app-stateful-icon *ngIf="!(apps$ | async)" [state]="'busy'"></app-stateful-icon>
<button mat-icon-button [disabled]="loading$ | async" (click)="refresh.emit()">
<mat-icon class="refresh-icon" [ngClass]="{refreshing: (loading$ | async)}" aria-label="Refresh list data">refresh</mat-icon>
</button>
</mat-card-header>
<mat-card-content class="recent-apps-card__content" *ngIf="apps$ | async as apps">
<div *ngIf="apps.length === 0">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,54 @@
flex-direction: column;
height: 100%;
width: 100%;
app-stateful-icon {
padding-left: 12px;
}

&__content {
display: flex;
overflow-y: auto;
}

&__header {
flex: 0 0 auto;
display: flex;
flex: 1;
height: 40px;
justify-content: space-between;
padding-top: 0;

mat-card-title {
margin-bottom: 0;
}

.refresh-icon {
animation: spin .4s infinite linear;
animation-play-state: paused;
transform: rotate(0deg);
transition: transform 1s linear;
}

.refreshing {
animation-play-state: running;
}

@keyframes spin {
from {
transform: rotate(0deg);
}

to {
transform: rotate(359deg);
}
}

button {
margin-right: -10px;
margin-top: -10px;
}
}

&__scroller {
height: 100%;
overflow-y: auto;
width: 100%;
}

}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, Input, OnInit } from '@angular/core';
import { Component, Input, OnInit, EventEmitter, Output } from '@angular/core';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs';
import { first, map } from 'rxjs/operators';
Expand All @@ -22,6 +22,8 @@ const RECENT_ITEMS_COUNT = 10;
export class CardCfRecentAppsComponent implements OnInit {

@Input() allApps$: Observable<APIResource<IApp>[]>;
@Input() loading$: Observable<boolean>;
@Output() refresh = new EventEmitter<any>();

constructor(
private store: Store<AppState>,
Expand All @@ -32,7 +34,6 @@ export class CardCfRecentAppsComponent implements OnInit {

ngOnInit() {
this.apps$ = this.allApps$.pipe(
first(),
map(allApps => this.processApps(allApps))
);
}
Expand Down