Skip to content
This repository was archived by the owner on May 14, 2025. It is now read-only.

Commit 311c1d0

Browse files
ghillertcppwfs
authored andcommitted
gh-610 Make sure spinner is consistently applied
* Add cleanup for all Subscriptions inside Components gh-610 Code review changes
1 parent 6e82739 commit 311c1d0

File tree

54 files changed

+725
-193
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+725
-193
lines changed

ui/src/app/about/about.service.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { Observable } from 'rxjs/Observable';
33
import { ErrorHandler } from '../shared/model/error-handler';
44
import { Response, ResponseOptions } from '@angular/http';
55
import { SharedAboutService } from '../shared/services/shared-about.service';
6+
import { BusyService } from '../shared/services/busy.service';
67

78
describe('AboutService', () => {
89

@@ -106,9 +107,8 @@ describe('AboutService', () => {
106107
body: JSON.stringify(jsonData)
107108
}));
108109
this.mockHttp.get.and.returnValue(Observable.of(mockResponse));
109-
110110
const errorHandler = new ErrorHandler();
111-
this.sharedAboutService = new SharedAboutService(this.mockHttp, errorHandler);
111+
this.sharedAboutService = new SharedAboutService(new BusyService(), this.mockHttp, errorHandler);
112112
this.aboutService = new AboutService(this.sharedAboutService, this.mockHttp, errorHandler);
113113
});
114114

ui/src/app/analytics/dashboard/dashboard.component.html

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
<div [ngBusy]="busy"></div>
21
<button type="button" (click)="resetDashboard()"
32
class="btn btn-default">Reset <span class="glyphicon glyphicon-trash"></span></button>
43
<form #dashboardForm="ngForm" name="dashboardForm" role="form" novalidate>

ui/src/app/analytics/dashboard/dashboard.component.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import { Component, OnInit, OnDestroy } from '@angular/core';
2-
import { Subscription } from 'rxjs/Subscription';
3-
42
import { ToastyService } from 'ng2-toasty';
53
import { AnalyticsService } from '../analytics.service';
64

75
import {
86
AggregateCounter, AggregateCounterResolutionType, BaseCounter,
97
DashboardItem, FieldValueCounterValue, MetricType
108
} from '../model';
9+
import { takeUntil } from 'rxjs/operators';
10+
import { Subject } from 'rxjs/Subject';
1111

1212
/**
1313
* The dashboard component provides
@@ -20,8 +20,8 @@ import {
2020
})
2121
export class DashboardComponent implements OnInit, OnDestroy {
2222

23-
busy: Subscription;
24-
busyCounters: Subscription;
23+
private ngUnsubscribe$: Subject<any> = new Subject();
24+
2525
/**
2626
* Returns the {@link DashboardItem}s from the
2727
* {@link AnalyticsService}.
@@ -54,10 +54,13 @@ export class DashboardComponent implements OnInit, OnDestroy {
5454

5555
/**
5656
* When the component is destroyed, make sure all pollers are
57-
* stopped also.
57+
* stopped also. Will also cleanup any {@link Subscription}s to prevent
58+
* memory leaks.
5859
*/
5960
ngOnDestroy() {
6061
this.analyticsService.stopAllDashboardPollers();
62+
this.ngUnsubscribe$.next();
63+
this.ngUnsubscribe$.complete();
6164
}
6265

6366
/**
@@ -115,6 +118,7 @@ export class DashboardComponent implements OnInit, OnDestroy {
115118
dashBoardItem.counter = undefined;
116119

117120
dashBoardItem.countersIsLoading = this.analyticsService.getCountersForMetricType(metricType)
121+
.pipe(takeUntil(this.ngUnsubscribe$))
118122
.subscribe(result => {
119123
dashBoardItem.counters = result.items;
120124
},

ui/src/app/app.component.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
<div class="container dataflow-main-container">
3737
<div class='row'>
3838
<div class='col-sm-24'><ng2-toasty></ng2-toasty>
39+
<ng-template [ngBusy]="{busy: busy, minDuration: 500}"></ng-template>
3940
<router-outlet></router-outlet>
4041
</div>
4142
</div>

ui/src/app/app.component.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { SecurityInfo } from './shared/model/about/security-info.model';
88
import { SharedAboutService } from './shared/services/shared-about.service';
99
import { Observable } from 'rxjs/Observable';
1010
import { AboutInfo } from './shared/model/about/about-info.model';
11+
import { BusyService } from './shared/services/busy.service';
1112

1213
@Component({
1314
selector: 'app-root',
@@ -19,10 +20,12 @@ export class AppComponent implements DoCheck, OnInit {
1920
public dataflowVersionInfo$: Observable<AboutInfo>;
2021

2122
public isCollapsed = true;
23+
public busy: any = [];
2224

2325
constructor(private toastyConfig: ToastyConfig,
2426
private renderer: Renderer2,
2527
private authService: AuthService,
28+
private busyService: BusyService,
2629
private sharedAboutService: SharedAboutService) {
2730
this.toastyConfig.theme = 'bootstrap';
2831
this.toastyConfig.limit = 5;
@@ -46,6 +49,26 @@ export class AppComponent implements DoCheck, OnInit {
4649
this.updateToasty();
4750
});
4851
this.updateToasty();
52+
53+
this.busyService.busyObjects$.forEach(busyObject => {
54+
if (busyObject) {
55+
while(busyObject.length > 0) {
56+
/*
57+
* Unfortunately, Angular2 Busy does not support
58+
* "Overlapping Subscriptions" and does not work
59+
* with mutable arrays. Ideally, good Spinner solution
60+
* would be able to accept a BehaviorSubject<boolean> as input,
61+
* so that we could manage the on/off state of the spinner on
62+
* our end.
63+
*
64+
* see: https://github.com/devyumao/angular2-busy/issues/77
65+
*/
66+
this.busy = [];
67+
this.busy.push(busyObject.pop());
68+
}
69+
}
70+
});
71+
4972
}
5073

5174
private updateToasty() {

ui/src/app/apps/app-details/app-details.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<h1 [ngBusy]="busy">Application Details</h1>
1+
<h1>Application Details</h1>
22

33
<table class="table table-striped table-hover table-fixed" *ngIf="detailedAppRegistration">
44
<tbody>

ui/src/app/apps/app-details/app-details.component.ts

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Component, OnInit } from '@angular/core';
1+
import { Component, OnInit, OnDestroy } from '@angular/core';
22
import { Router, ActivatedRoute, Params } from '@angular/router';
33

44
import { AppsService } from '../apps.service';
@@ -8,6 +8,9 @@ import { ApplicationType, DetailedAppRegistration } from '../../shared/model';
88

99
import { Subscription } from 'rxjs/Subscription';
1010
import 'rxjs/add/observable/of';
11+
import { Subject } from 'rxjs/Subject';
12+
import { BusyService } from '../../shared/services/busy.service';
13+
import { takeUntil } from 'rxjs/operators';
1114

1215
/**
1316
* Provides details for an App Registration
@@ -17,13 +20,14 @@ import 'rxjs/add/observable/of';
1720
@Component({
1821
templateUrl: './app-details.component.html'
1922
})
20-
export class AppDetailsComponent implements OnInit {
23+
export class AppDetailsComponent implements OnInit, OnDestroy {
2124

22-
public detailedAppRegistration: DetailedAppRegistration;
25+
private ngUnsubscribe$: Subject<any> = new Subject();
2326

24-
busy: Subscription;
27+
public detailedAppRegistration: DetailedAppRegistration;
2528

2629
constructor(
30+
private busyService: BusyService,
2731
private route: ActivatedRoute,
2832
private appsService: AppsService,
2933
private toastyService: ToastyService,
@@ -39,15 +43,29 @@ export class AppDetailsComponent implements OnInit {
3943
const appType: ApplicationType = params['appType'] as ApplicationType;
4044

4145
console.log(`Retrieving app registration details for ${appName} (${appType}).`);
42-
this.busy = this.appsService.getAppInfo(appType, appName).subscribe(data => {
46+
const busy = this.appsService.getAppInfo(appType, appName)
47+
.pipe(takeUntil(this.ngUnsubscribe$))
48+
.subscribe(data => {
4349
this.detailedAppRegistration = data;
4450
},
4551
error => {
4652
this.toastyService.error(error);
4753
});
54+
setTimeout(()=>{
55+
this.busyService.addSubscription(busy);
56+
});
4857
});
4958
}
5059

60+
/**
61+
* Will cleanup any {@link Subscription}s to prevent
62+
* memory leaks.
63+
*/
64+
ngOnDestroy() {
65+
this.ngUnsubscribe$.next();
66+
this.ngUnsubscribe$.complete();
67+
}
68+
5169
goBack() {
5270
console.log('Back to apps page ...');
5371
this.router.navigate(['apps']);

ui/src/app/apps/apps-bulk-import.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<h1 [ngBusy]="busy">Bulk Import Applications</h1>
1+
<h1>Bulk Import Applications</h1>
22
<p>
33
Import and register applications in bulk. Simply provide a URI that points to
44
the location of the <strong>properties file</strong> where the keys are formatted as

ui/src/app/apps/apps-bulk-import.component.ts

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,36 @@
1-
import { Component, OnInit, OnChanges, ViewChild, ElementRef } from '@angular/core';
1+
import { Component, OnInit, OnChanges, ViewChild, ElementRef, OnDestroy } from '@angular/core';
22
import { Subscription} from 'rxjs/Subscription';
33
import { AppsService } from './apps.service';
44
import { ToastyService } from 'ng2-toasty';
55
import { Router } from '@angular/router';
66

77
import { AppRegistrationImport } from './model/app-registration-import';
88
import { PopoverDirective } from 'ngx-bootstrap/popover';
9+
import { Subject } from 'rxjs/Subject';
10+
import { BusyService } from '../shared/services/busy.service';
11+
import { takeUntil } from 'rxjs/operators';
912

1013
@Component({
1114
selector: 'app-apps',
1215
templateUrl: './apps-bulk-import.component.html'
1316
})
14-
export class AppsBulkImportComponent implements OnInit, OnChanges {
17+
export class AppsBulkImportComponent implements OnInit, OnChanges, OnDestroy {
18+
19+
private ngUnsubscribe$: Subject<any> = new Subject();
1520

1621
@ViewChild('childPopover')
1722
public childPopover: PopoverDirective;
1823

1924
public model = new AppRegistrationImport(false, [], '');
2025

2126
apps: any;
22-
busy: Subscription;
2327

2428
contents: any;
2529
uriPattern = '^([a-z0-9-]+:\/\/)([\\w\\.:-]+)(\/[\\w\\.:-]+)*$';
2630

2731
constructor(
2832
private appsService: AppsService,
33+
private busyService: BusyService,
2934
private toastyService: ToastyService,
3035
private router: Router,
3136
private elementRef: ElementRef) { }
@@ -35,6 +40,15 @@ export class AppsBulkImportComponent implements OnInit, OnChanges {
3540
console.log(this.appsService.appRegistrations);
3641
}
3742

43+
/**
44+
* Will cleanup any {@link Subscription}s to prevent
45+
* memory leaks.
46+
*/
47+
ngOnDestroy() {
48+
this.ngUnsubscribe$.next();
49+
this.ngUnsubscribe$.complete();
50+
}
51+
3852
goBack() {
3953
console.log('Back to apps page ...');
4054
this.router.navigate(['apps']);
@@ -86,17 +100,21 @@ export class AppsBulkImportComponent implements OnInit, OnChanges {
86100
console.log('Importing apps using textarea values:\n' + this.model.appsProperties + ' (force: ' + this.model.force + ')');
87101
}
88102

89-
this.busy = this.appsService.bulkImportApps(this.model).subscribe(
103+
const busy = this.appsService.bulkImportApps(this.model).subscribe(
90104
data => {
91105
console.log(data);
92106
this.toastyService.success('Apps Imported.');
93-
this.busy = this.appsService.getApps(true).subscribe(
107+
this.busyService.addSubscription(
108+
this.appsService.getApps(true)
109+
.pipe(takeUntil(this.ngUnsubscribe$))
110+
.subscribe(
94111
appRegistrations => {
95112
console.log('Back to about page ...');
96113
this.router.navigate(['apps']);
97114
}
98-
);
115+
));
99116
}
100117
);
118+
this.busyService.addSubscription(busy);
101119
}
102120
}

ui/src/app/apps/apps-register/apps-register.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<h1 [ngBusy]="busy">Register Applications</h1>
1+
<h1>Register Applications</h1>
22
<p>
33
Register one or more applications by entering a <strong>Name</strong>,
44
<strong>Type</strong> and <strong>App URI</strong> of the application Jar.

0 commit comments

Comments
 (0)