Skip to content

Commit

Permalink
Merge pull request #3213 from cloudfoundry-incubator/refresh-latest-apps
Browse files Browse the repository at this point in the history
Show refresh button for latest modified application lists
  • Loading branch information
nwmac authored Jan 9, 2019
2 parents 158687b + e8da9af commit eee461e
Show file tree
Hide file tree
Showing 9 changed files with 85 additions and 37 deletions.
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

0 comments on commit eee461e

Please sign in to comment.