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

Commit 8126c1f

Browse files
ghillertcppwfs
authored andcommitted
gh-474 Footer should include release specific links
* Change the way we retrieve AboutInfo to prevent multiple HTTP requests - Use a `BehaviorSubject` to propagate changes to the various subscribers * Create dedicated domain objects modeled after the `AboutResource` classes from the server * Create tests for each domain object * Fix and polish tests * Switch to Headless Chrome for tests * Add class documentation Some lint cleanup
1 parent 474c467 commit 8126c1f

36 files changed

+739
-262
lines changed

.travis.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ sudo: required
22
cache:
33
directories:
44
- $HOME/.m2
5-
language: java
5+
dist: trusty
6+
language: java
7+
addons:
8+
chrome: stable
69
jdk:
710
- oraclejdk8
811
install: true

ui/karma.conf.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ module.exports = function (config) {
3030
logLevel: config.LOG_INFO,
3131
autoWatch: true,
3232
browsers: ['Chrome'],
33-
singleRun: false
33+
singleRun: false,
34+
browserNoActivityTimeout: 100000
3435
});
3536
};

ui/package.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
"e2e": "ng e2e --proxy-config proxy.conf.json",
1212
"install": "napa pivotal-cf/pivotal-ui:pivotal-ui-git-clone",
1313
"doc": "./node_modules/.bin/compodoc -p tsconfig.json -n \"Spring Cloud Data Flow Dashboard Documentation\"",
14-
"mavenbuild": "node ./node_modules/@angular/cli/bin/ng test --code-coverage true --watch false --browsers PhantomJS && node ./node_modules/@angular/cli/bin/ng build --prod --output-path ./../src/main/resources/public/dashboard --base-href /dashboard/",
14+
"mavenbuild": "node ./node_modules/@angular/cli/bin/ng test --code-coverage true --watch false --browsers ChromeHeadless && node ./node_modules/@angular/cli/bin/ng build --prod --output-path ./../src/main/resources/public/dashboard --base-href /dashboard/",
1515
"bundle-report": "webpack-bundle-analyzer dist/stats.json"
1616
},
1717
"private": true,
@@ -38,7 +38,6 @@
3838
"rxjs": "5.5.2",
3939
"sockjs-client": "1.1.4",
4040
"spring-flo": "0.7.0",
41-
"stompjs": "2.3.3",
4241
"tixif-ngx-busy": "0.0.5",
4342
"web-animations-js": "2.3.1",
4443
"zone.js": "0.8.18",
@@ -57,7 +56,7 @@
5756
"jasmine-core": "2.8.0",
5857
"jasmine-spec-reporter": "4.1.1",
5958
"karma": "1.7.1",
60-
"karma-chrome-launcher": "2.1.1",
59+
"karma-chrome-launcher": "2.2.0",
6160
"karma-cli": "1.0.1",
6261
"karma-coverage-istanbul-reporter": "1.3.0",
6362
"karma-jasmine": "1.1.0",

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

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
<h1 [ngBusy]="busy">About Details</h1>
1+
<h1>About Details</h1>
22
<h2>Data Flow Server Implementation</h2>
33

4-
<h2 *ngIf="!dataflowVersionInfo" class="text-warning" id="serverWarningError">Obtaining about info from server.</h2>
4+
<ng-container *ngIf="dataflowVersionInfo$ | async as dataflowVersionInfo; else loading">
55

66
<div *ngIf="dataflowVersionInfo">
77
<table class="table table-hover" id="dataFlowVersionTable">
@@ -57,29 +57,29 @@ <h2>Security Information</h2>
5757
<tr>
5858
<td class="col-xs-6">Authentication Enabled</td>
5959
<td>
60-
<span *ngIf="dataflowVersionInfo.securityInfo.authenticationEnabled" class="glyphicon glyphicon-ok text-success" aria-label="true" id="authenticationEnabled"></span>
61-
<span *ngIf="!dataflowVersionInfo.securityInfo.authenticationEnabled" class="glyphicon glyphicon-remove text-danger" aria-label="false" id="authenticationDisabled"></span>
60+
<span *ngIf="dataflowVersionInfo.securityInfo.isAuthenticationEnabled" class="glyphicon glyphicon-ok text-success" aria-label="true" id="authenticationEnabled"></span>
61+
<span *ngIf="!dataflowVersionInfo.securityInfo.isAuthenticationEnabled" class="glyphicon glyphicon-remove text-danger" aria-label="false" id="authenticationDisabled"></span>
6262
</td>
6363
</tr>
6464
<tr>
6565
<td class="col-xs-6">Authorization Enabled</td>
6666
<td>
67-
<span *ngIf="dataflowVersionInfo.securityInfo.authorizationEnabled" class="glyphicon glyphicon-ok text-success" aria-label="true" id="authorizationEnabled"></span>
68-
<span *ngIf="!dataflowVersionInfo.securityInfo.authorizationEnabled" class="glyphicon glyphicon-remove text-danger" aria-label="false" id="authorizationDisabled"></span>
67+
<span *ngIf="dataflowVersionInfo.securityInfo.isAuthorizationEnabled" class="glyphicon glyphicon-ok text-success" aria-label="true" id="authorizationEnabled"></span>
68+
<span *ngIf="!dataflowVersionInfo.securityInfo.isAuthorizationEnabled" class="glyphicon glyphicon-remove text-danger" aria-label="false" id="authorizationDisabled"></span>
6969
</td>
7070
</tr>
7171
<tr>
7272
<td class="col-xs-6">Form Login</td>
7373
<td>
74-
<span *ngIf="dataflowVersionInfo.securityInfo.formLogin" class="glyphicon glyphicon-ok text-success" aria-label="true" id="formLoginEnabled"></span>
75-
<span *ngIf="!dataflowVersionInfo.securityInfo.formLogin" class="glyphicon glyphicon-remove text-danger" aria-label="false" id="formLoginDisabled"></span>
74+
<span *ngIf="dataflowVersionInfo.securityInfo.isFormLogin" class="glyphicon glyphicon-ok text-success" aria-label="true" id="formLoginEnabled"></span>
75+
<span *ngIf="!dataflowVersionInfo.securityInfo.isFormLogin" class="glyphicon glyphicon-remove text-danger" aria-label="false" id="formLoginDisabled"></span>
7676
</td>
7777
</tr>
7878
<tr>
7979
<td class="col-xs-6">Authenticated</td>
8080
<td>
81-
<span *ngIf="dataflowVersionInfo.securityInfo.authenticated" class="glyphicon glyphicon-ok text-success" aria-label="true" id="authenticateEnabled"></span>
82-
<span *ngIf="!dataflowVersionInfo.securityInfo.authenticated" class="glyphicon glyphicon-remove text-danger" aria-label="false"id="authenticateDisabled"></span>
81+
<span *ngIf="dataflowVersionInfo.securityInfo.isAuthenticated" class="glyphicon glyphicon-ok text-success" aria-label="true" id="authenticateEnabled"></span>
82+
<span *ngIf="!dataflowVersionInfo.securityInfo.isAuthenticated" class="glyphicon glyphicon-remove text-danger" aria-label="false"id="authenticateDisabled"></span>
8383
</td>
8484
</tr>
8585
<tr>
@@ -164,13 +164,13 @@ <h2 *ngIf="!dataflowVersionInfo.featureInfo.skipperEnabled">Platform-specific In
164164

165165
<table class="table table-hover" id="appDeployerPlatformSpecificTable">
166166
<tbody>
167-
<ng-template *ngIf="!isEmpty(dataflowVersionInfo.runtimeEnvironment.appDeployer.platformSpecificInfo)"
168-
ngFor let-item [ngForOf]="dataflowVersionInfo.runtimeEnvironment.appDeployer.platformSpecificInfo | keyvalues">
167+
<ng-template *ngIf="dataflowVersionInfo.runtimeEnvironment.appDeployer.platformSpecificInfo && dataflowVersionInfo.runtimeEnvironment.appDeployer.platformSpecificInfo.size > 0"
168+
ngFor let-item [ngForOf]="dataflowVersionInfo.runtimeEnvironment.appDeployer.platformSpecificInfo | mapValuesPipe">
169169
<tr>
170170
<td class="col-xs-6">{{item.key}}</td><td>{{item.value}}</td>
171171
</tr>
172172
</ng-template>
173-
<tr *ngIf="isEmpty(dataflowVersionInfo.runtimeEnvironment.appDeployer.platformSpecificInfo)">
173+
<tr *ngIf="!dataflowVersionInfo.runtimeEnvironment.appDeployer.platformSpecificInfo || dataflowVersionInfo.runtimeEnvironment.appDeployer.platformSpecificInfo.size == 0">
174174
<td class="col-xs-12 text-center" colspan="2" id="noAppDeployerPlatformMessage">No platform-specific app deployer information available.</td>
175175
</tr>
176176
</tbody>
@@ -219,13 +219,13 @@ <h2>Platform-specific Information of the Task Launcher</h2>
219219

220220
<table class="table table-hover" id="appTaskLauncherPlatformSpecificTable">
221221
<tbody>
222-
<ng-template *ngIf="!isEmpty(dataflowVersionInfo.runtimeEnvironment.taskLauncher.platformSpecificInfo)"
223-
ngFor let-item [ngForOf]="dataflowVersionInfo.runtimeEnvironment.taskLauncher.platformSpecificInfo | keyvalues">
222+
<ng-template *ngIf="dataflowVersionInfo.runtimeEnvironment.taskLauncher.platformSpecificInfo && dataflowVersionInfo.runtimeEnvironment.taskLauncher.platformSpecificInfo.size > 0"
223+
ngFor let-item [ngForOf]="dataflowVersionInfo.runtimeEnvironment.taskLauncher.platformSpecificInfo | mapValuesPipe">
224224
<tr>
225225
<td class="col-xs-6">{{item.key}}</td><td>{{item.value}}</td>
226226
</tr>
227227
</ng-template>
228-
<tr *ngIf="isEmpty(dataflowVersionInfo.runtimeEnvironment.taskLauncher.platformSpecificInfo)">
228+
<tr *ngIf="!dataflowVersionInfo.runtimeEnvironment.taskLauncher.platformSpecificInfo || dataflowVersionInfo.runtimeEnvironment.taskLauncher.platformSpecificInfo.size == 0">
229229
<td colspan="2" class="col-xs-6 text-center" id="noTaskLauncherPlatformMessage">No platform-specific task launcher information available.</td>
230230
</tr>
231231
</tbody>
@@ -238,3 +238,8 @@ <h2>Platform-specific Information of the Task Launcher</h2>
238238
type="button" class="btn btn-default"><span class="glyphicon glyphicon-copy"></span> <span class="hidden-xs">Copy Details to Clipboard</span></button></div>
239239
</div>
240240
</div>
241+
</ng-container>
242+
243+
<ng-template #loading>
244+
<h2 class="text-warning" id="serverWarningError">Obtaining about info from server.</h2>
245+
</ng-template>

ui/src/app/about/about-details.component.spec.ts

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,19 @@ import {DebugElement} from '@angular/core';
1010
import {By} from '@angular/platform-browser';
1111
import {RouterTestingModule} from '@angular/router/testing';
1212
import {AboutDetailsComponent} from './about-details.component';
13-
import {StompService} from 'ng2-stomp-service';
14-
import {KeyValuePipe} from '../shared/pipes/key-value-filter.pipe';
1513
import {ClipboardModule} from 'ngx-clipboard/dist';
14+
import { MapValuesPipe } from '../shared/pipes/map-values-pipe.pipe';
1615

1716
describe('AboutDetailsComponent', () => {
1817
let component: AboutDetailsComponent;
1918
let fixture: ComponentFixture<AboutDetailsComponent>;
2019
const toastyService = new MockToastyService();
2120
let activeRoute: MockActivatedRoute;
2221
const aboutService = new MockAboutService();
23-
const stompService = new StompService();
2422

2523
beforeEach(async(() => {
2624
aboutService.isAboutInfoAvailable = true;
27-
aboutService.isFeatureEnabled = true;
25+
aboutService.featureEnabled = true;
2826
aboutService.isPlatformSpecificInformationAvailable = true;
2927
activeRoute = new MockActivatedRoute();
3028
TestBed.configureTestingModule({
@@ -33,12 +31,11 @@ describe('AboutDetailsComponent', () => {
3331
RouterTestingModule.withRoutes([]),
3432
ClipboardModule
3533
],
36-
declarations: [AboutDetailsComponent, KeyValuePipe],
34+
declarations: [AboutDetailsComponent, MapValuesPipe],
3735
providers: [
3836
{provide: AboutService, useValue: aboutService},
3937
{provide: ToastyService, useValue: toastyService},
40-
{provide: ActivatedRoute, useValue: activeRoute},
41-
{provide: StompService, useValue: stompService}
38+
{provide: ActivatedRoute, useValue: activeRoute}
4239
]
4340
})
4441
.compileComponents();
@@ -100,7 +97,7 @@ describe('AboutDetailsComponent', () => {
10097
});
10198

10299
it('Should display base information and services are disabled.', () => {
103-
aboutService.isFeatureEnabled = false;
100+
aboutService.featureEnabled = false;
104101
fixture.detectChanges();
105102
expect(component).toBeTruthy();
106103

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

Lines changed: 4 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,27 @@
11
import { Component, OnInit } from '@angular/core';
22

33
import { AboutService } from './about.service';
4-
import { Subscription } from 'rxjs/Subscription';
54
import { ToastyService } from 'ng2-toasty';
6-
import { StompService } from 'ng2-stomp-service';
75
import { Router } from '@angular/router';
6+
import { Observable } from 'rxjs/Observable';
7+
import { AboutInfo } from '../shared/model/about/about-info.model';
88

99
@Component({
1010
templateUrl: './about-details.component.html'
1111
})
1212
export class AboutDetailsComponent implements OnInit {
1313

14-
dataflowVersionInfo;
15-
busy: Subscription;
16-
websocketData;
17-
18-
private subscription: any;
14+
public dataflowVersionInfo$: Observable<AboutInfo>;
1915

2016
constructor(
2117
private aboutService: AboutService,
2218
private toastyService: ToastyService,
23-
private stomp: StompService,
2419
private router: Router) {
2520
}
2621

2722
ngOnInit() {
2823
console.log('Getting about details...');
29-
this.getAboutDetails();
30-
}
31-
32-
getAboutDetails(): void {
33-
this.busy = this.aboutService.getDetails().subscribe(
34-
data => {
35-
this.dataflowVersionInfo = data;
36-
this.toastyService.success('About details data loaded.');
37-
},
38-
error => {
39-
this.toastyService.error(error);
40-
}
41-
);
24+
this.dataflowVersionInfo$ = this.aboutService.getDetails();
4225
}
4326

4427
goBack() {

ui/src/app/about/about-info.model.ts

Lines changed: 0 additions & 8 deletions
This file was deleted.

ui/src/app/about/about.component.html

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
1-
<h1 [ngBusy]="busy">About</h1>
1+
<h1>About</h1>
22
<p>
33
Spring Cloud Data Flow is a unified, distributed, and extensible system for data ingestion,
44
real time analytics, batch processing, and data export. The project's goal is to
55
simplify the development of big data applications.
66
</p>
77

8-
<h2 *ngIf="dataflowVersionInfo">Data Flow Server Implementation</h2>
8+
<ng-container *ngIf="dataflowVersionInfo$ | async as dataflowVersionInfo else loading">
9+
<h2>Data Flow Server Implementation</h2>
910

10-
<h2 *ngIf="!dataflowVersionInfo" class="text-warning" id="serverWarningError">Obtaining about info from server.</h2>
11-
12-
<table id="dataFlowVersionTable" class="table table-hover" *ngIf="dataflowVersionInfo">
11+
<table id="dataFlowVersionTable" class="table table-hover">
1312
<tbody>
1413
<tr>
1514
<td>Name</td><td>{{dataflowVersionInfo ? dataflowVersionInfo.versionInfo.implementation.name : 'N/A'}}</td>
@@ -20,21 +19,21 @@ <h2 *ngIf="!dataflowVersionInfo" class="text-warning" id="serverWarningError">Ob
2019
</tbody>
2120
</table>
2221

23-
<button id="showAboutDetailsButton" type="button" (click)="goToDetails() " *ngIf="dataflowVersionInfo"
22+
<button id="showAboutDetailsButton" type="button" (click)="goToDetails() "
2423
class="btn btn-default"
2524
><span class="glyphicon glyphicon-search"></span>
2625
Show Details
2726
</button>
2827

2928
<h2 style="margin-top: 1em;" *ngIf="dataflowVersionInfo">Get the Spring Cloud Data Flow Shell</h2>
3029

31-
<p *ngIf="dataflowVersionInfo" class="index-page--subtitle">As an alternative to the Dashboard UI, you can also
30+
<p class="index-page--subtitle">As an alternative to the Dashboard UI, you can also
3231
<a href="{{dataflowVersionInfo.versionInfo.shell.url}}"
3332
target="_blank">download the compatible version of the Shell</a> ({{dataflowVersionInfo.versionInfo.shell.version}}).</p>
3433

35-
<h2 *ngIf="dataflowVersionInfo">Need Help or Found an Issue?</h2>
34+
<h2>Need Help or Found an Issue?</h2>
3635

37-
<table id="dataFlowVersionLinksTable" class="table table-hover" *ngIf="dataflowVersionInfo">
36+
<table id="dataFlowVersionLinksTable" class="table table-hover">
3837
<tbody>
3938
<tr>
4039
<td>Project Page</td><td><a target="_blank" href="http://cloud.spring.io/spring-cloud-dataflow/">http://cloud.spring.io/spring-cloud-dataflow/</a></td>
@@ -56,3 +55,9 @@ <h2 *ngIf="dataflowVersionInfo">Need Help or Found an Issue?</h2>
5655
</tr>
5756
</tbody>
5857
</table>
58+
59+
</ng-container>
60+
61+
<ng-template #loading>
62+
<h2 class="text-warning" id="serverWarningError">Obtaining about info from server.</h2>
63+
</ng-template>

ui/src/app/about/about.component.ts

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,22 @@
11
import { Component, OnInit } from '@angular/core';
22
import { AboutService } from './about.service';
3-
import { Subscription } from 'rxjs/Subscription';
4-
import { ToastyService} from 'ng2-toasty';
53
import { Router } from '@angular/router';
4+
import { Observable } from 'rxjs/Observable';
5+
import { AboutInfo } from '../shared/model/about/about-info.model';
66

77
@Component({
88
templateUrl: './about.component.html',
99
})
1010
export class AboutComponent implements OnInit {
1111

12-
dataflowVersionInfo;
13-
busy: Subscription;
12+
public dataflowVersionInfo$: Observable<AboutInfo>;
1413

15-
private subscription: any;
16-
17-
constructor(private aboutService: AboutService, private toastyService: ToastyService,
14+
constructor(private aboutService: AboutService,
1815
private router: Router) {
1916
}
2017

2118
ngOnInit() {
22-
this.getVersionInfo();
23-
}
24-
25-
getVersionInfo(): void {
26-
this.busy = this.aboutService.getAboutInfo().subscribe(
27-
data => {
28-
this.dataflowVersionInfo = data;
29-
this.toastyService.success('About data loaded.');
30-
},
31-
error => {
32-
this.toastyService.error(error);
33-
}
34-
);
19+
this.dataflowVersionInfo$ = this.aboutService.getAboutInfo();
3520
}
3621

3722
goToDetails() {

0 commit comments

Comments
 (0)