diff --git a/webui/.prettierrc b/webui/.prettierrc
new file mode 100644
index 000000000..544138be4
--- /dev/null
+++ b/webui/.prettierrc
@@ -0,0 +1,3 @@
+{
+ "singleQuote": true
+}
diff --git a/webui/Dockerfile b/webui/Dockerfile
index 0a1cf28d4..668318634 100644
--- a/webui/Dockerfile
+++ b/webui/Dockerfile
@@ -14,3 +14,4 @@ COPY . $WEBUI_DIR/
EXPOSE 8080
RUN yarn lint
+RUN yarn format --check
diff --git a/webui/package.json b/webui/package.json
index 7f48fdbca..7cee00f0b 100644
--- a/webui/package.json
+++ b/webui/package.json
@@ -13,6 +13,7 @@
"build": "ng build --prod --no-delete-output-path --output-path ../static/",
"test": "ng test",
"lint": "ng lint",
+ "format": "yarn prettier 'src/**/*.{js,ts,html}' '*.md'",
"e2e": "ng e2e"
},
"dependencies": {
@@ -34,9 +35,9 @@
"date-fns": "^1.29.0",
"lodash": "^4.17.5",
"rxjs": "^6.4.0",
+ "rxjs-compat": "^6.0.0-rc.0",
"tslib": "^1.9.0",
- "zone.js": "^0.8.19",
- "rxjs-compat": "^6.0.0-rc.0"
+ "zone.js": "^0.8.19"
},
"devDependencies": {
"@angular-devkit/build-angular": "~0.13.0",
@@ -54,9 +55,11 @@
"karma-coverage-istanbul-reporter": "^2.0.4",
"karma-jasmine": "~2.0.1",
"karma-jasmine-html-reporter": "^1.4.0",
+ "prettier": "^1.16.4",
"protractor": "~5.4.2",
"ts-node": "~8.0.2",
"tslint": "~5.12.1",
+ "tslint-config-prettier": "^1.18.0",
"typescript": "~3.2.4"
}
-}
\ No newline at end of file
+}
diff --git a/webui/readme.md b/webui/readme.md
index 6374851f2..372ada5dd 100644
--- a/webui/readme.md
+++ b/webui/readme.md
@@ -5,6 +5,7 @@ Access to Traefik Web UI, ex: http://localhost:8080
## Interface
Traefik Web UI provide 2 types of informations:
+
- Providers with their backends and frontends information.
- Health of the web server.
@@ -27,9 +28,11 @@ make generate-webui # Generate static contents in `traefik/static/` folder.
- Go to the directory `webui`
- To install dependencies, execute the following commands:
+
- `yarn install`
- Build static Web UI, execute the following command:
+
- `yarn run build`
- Static contents are build in the directory `static`
@@ -44,7 +47,6 @@ make generate-webui # Generate static contents in `traefik/static/` folder.
- all images will be optimized at build
- bundle JavaScript in one file
-
## How to edit (only for frontends developer)
**Don't change manually the files in the directory `static`**
diff --git a/webui/src/app/app.component.spec.ts b/webui/src/app/app.component.spec.ts
index 06e9c81d4..ccface19f 100644
--- a/webui/src/app/app.component.spec.ts
+++ b/webui/src/app/app.component.spec.ts
@@ -1,17 +1,12 @@
+import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { async, TestBed } from '@angular/core/testing';
import { AppComponent } from './app.component';
-import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
describe('AppComponent', () => {
-
beforeEach(async(() => {
TestBed.configureTestingModule({
- declarations: [
- AppComponent
- ],
- schemas: [
- CUSTOM_ELEMENTS_SCHEMA
- ]
+ declarations: [AppComponent],
+ schemas: [CUSTOM_ELEMENTS_SCHEMA]
}).compileComponents();
}));
diff --git a/webui/src/app/app.component.ts b/webui/src/app/app.component.ts
index cb45f66c4..5d475fee0 100644
--- a/webui/src/app/app.component.ts
+++ b/webui/src/app/app.component.ts
@@ -7,4 +7,4 @@ import { Component } from '@angular/core';
`
})
-export class AppComponent { }
+export class AppComponent {}
diff --git a/webui/src/app/app.module.ts b/webui/src/app/app.module.ts
index c9f573855..bf18dad04 100644
--- a/webui/src/app/app.module.ts
+++ b/webui/src/app/app.module.ts
@@ -38,14 +38,11 @@ import { WindowService } from './services/window.service';
HttpClientModule,
FormsModule,
RouterModule.forRoot([
- {path: '', component: ProvidersComponent, pathMatch: 'full'},
- {path: 'status', component: HealthComponent}
+ { path: '', component: ProvidersComponent, pathMatch: 'full' },
+ { path: 'status', component: HealthComponent }
])
],
- providers: [
- ApiService,
- WindowService
- ],
+ providers: [ApiService, WindowService],
bootstrap: [AppComponent]
})
-export class AppModule { }
+export class AppModule {}
diff --git a/webui/src/app/charts/bar-chart/bar-chart.component.html b/webui/src/app/charts/bar-chart/bar-chart.component.html
index 8467536ce..129efa0c2 100644
--- a/webui/src/app/charts/bar-chart/bar-chart.component.html
+++ b/webui/src/app/charts/bar-chart/bar-chart.component.html
@@ -2,6 +2,6 @@
Loading, please wait...
-
+
diff --git a/webui/src/app/charts/bar-chart/bar-chart.component.spec.ts b/webui/src/app/charts/bar-chart/bar-chart.component.spec.ts
index 5f467ff98..1b743e942 100644
--- a/webui/src/app/charts/bar-chart/bar-chart.component.spec.ts
+++ b/webui/src/app/charts/bar-chart/bar-chart.component.spec.ts
@@ -1,7 +1,7 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
-import { BarChartComponent } from './bar-chart.component';
import { WindowService } from '../../services/window.service';
+import { BarChartComponent } from './bar-chart.component';
describe('BarChartComponent', () => {
let component: BarChartComponent;
@@ -9,10 +9,9 @@ describe('BarChartComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
- declarations: [ BarChartComponent ],
- providers: [{provide: WindowService, useInstance: {}}]
- })
- .compileComponents();
+ declarations: [BarChartComponent],
+ providers: [{ provide: WindowService, useInstance: {} }]
+ }).compileComponents();
}));
beforeEach(() => {
@@ -27,5 +26,4 @@ describe('BarChartComponent', () => {
it('should initially go to loading state', () => {
expect(component.loading).toBeTruthy();
});
-
});
diff --git a/webui/src/app/charts/bar-chart/bar-chart.component.ts b/webui/src/app/charts/bar-chart/bar-chart.component.ts
index fb695fefb..47b6d2307 100644
--- a/webui/src/app/charts/bar-chart/bar-chart.component.ts
+++ b/webui/src/app/charts/bar-chart/bar-chart.component.ts
@@ -1,4 +1,11 @@
-import { Component, ElementRef, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core';
+import {
+ Component,
+ ElementRef,
+ Input,
+ OnChanges,
+ OnInit,
+ SimpleChanges
+} from '@angular/core';
import { axisBottom, axisLeft, max, scaleBand, scaleLinear, select } from 'd3';
import { format } from 'd3-format';
import * as _ from 'lodash';
@@ -18,19 +25,22 @@ export class BarChartComponent implements OnInit, OnChanges {
g: any;
width: number;
height: number;
- margin = {top: 40, right: 40, bottom: 40, left: 40};
+ margin = { top: 40, right: 40, bottom: 40, left: 40 };
loading: boolean;
data: any[];
previousData: any[];
- constructor(public elementRef: ElementRef, public windowService: WindowService) {
+ constructor(
+ public elementRef: ElementRef,
+ public windowService: WindowService
+ ) {
this.loading = true;
}
ngOnInit() {
this.barChartEl = this.elementRef.nativeElement.querySelector('.bar-chart');
this.setup();
- setTimeout(() => this.loading = false, 1000);
+ setTimeout(() => (this.loading = false), 1000);
this.windowService.resize.subscribe(w => this.draw());
}
@@ -49,39 +59,44 @@ export class BarChartComponent implements OnInit, OnChanges {
}
setup(): void {
- this.width = this.barChartEl.clientWidth - this.margin.left - this.margin.right;
- this.height = this.barChartEl.clientHeight - this.margin.top - this.margin.bottom;
+ this.width =
+ this.barChartEl.clientWidth - this.margin.left - this.margin.right;
+ this.height =
+ this.barChartEl.clientHeight - this.margin.top - this.margin.bottom;
this.svg = select(this.barChartEl)
.append('svg')
.attr('width', this.width + this.margin.left + this.margin.right)
.attr('height', this.height + this.margin.top + this.margin.bottom);
- this.g = this.svg.append('g')
+ this.g = this.svg
+ .append('g')
.attr('transform', `translate(${this.margin.left}, ${this.margin.top})`);
this.x = scaleBand().padding(0.05);
this.y = scaleLinear();
- this.g.append('g')
- .attr('class', 'axis axis--x');
+ this.g.append('g').attr('class', 'axis axis--x');
- this.g.append('g')
- .attr('class', 'axis axis--y');
+ this.g.append('g').attr('class', 'axis axis--y');
}
draw(): void {
- if (this.barChartEl.clientWidth === 0 || this.barChartEl.clientHeight === 0) {
+ if (
+ this.barChartEl.clientWidth === 0 ||
+ this.barChartEl.clientHeight === 0
+ ) {
this.previousData = [];
} else {
- this.width = this.barChartEl.clientWidth - this.margin.left - this.margin.right;
- this.height = this.barChartEl.clientHeight - this.margin.top - this.margin.bottom;
+ this.width =
+ this.barChartEl.clientWidth - this.margin.left - this.margin.right;
+ this.height =
+ this.barChartEl.clientHeight - this.margin.top - this.margin.bottom;
}
this.x.domain(this.data.map((d: any) => d.code));
this.y.domain([0, max(this.data, (d: any) => d.count)]);
-
this.svg
.attr('width', this.width + this.margin.left + this.margin.right)
.attr('height', this.height + this.margin.top + this.margin.bottom);
@@ -89,28 +104,38 @@ export class BarChartComponent implements OnInit, OnChanges {
this.x.rangeRound([0, this.width]);
this.y.rangeRound([this.height, 0]);
- this.g.select('.axis--x')
+ this.g
+ .select('.axis--x')
.attr('transform', `translate(0, ${this.height})`)
.call(axisBottom(this.x));
- this.g.select('.axis--y')
- .call(axisLeft(this.y).tickFormat(format('~s')).tickSize(-this.width));
+ this.g.select('.axis--y').call(
+ axisLeft(this.y)
+ .tickFormat(format('~s'))
+ .tickSize(-this.width)
+ );
// Clean previous graph
this.g.selectAll('.bar').remove();
const bars = this.g.selectAll('.bar').data(this.data);
- bars.enter()
+ bars
+ .enter()
.append('rect')
.attr('class', 'bar')
- .style('fill', (d: any) => 'hsl(' + Math.floor(((d.code - 100) * 310 / 427) + 50) + ', 50%, 50%)')
+ .style(
+ 'fill',
+ (d: any) =>
+ 'hsl(' + Math.floor(((d.code - 100) * 310) / 427 + 50) + ', 50%, 50%)'
+ )
.attr('x', (d: any) => this.x(d.code))
.attr('y', (d: any) => this.y(d.count))
.attr('width', this.x.bandwidth())
- .attr('height', (d: any) => (this.height - this.y(d.count)) < 0 ? 0 : this.height - this.y(d.count));
+ .attr('height', (d: any) =>
+ this.height - this.y(d.count) < 0 ? 0 : this.height - this.y(d.count)
+ );
bars.exit().remove();
}
-
}
diff --git a/webui/src/app/charts/line-chart/line-chart.component.html b/webui/src/app/charts/line-chart/line-chart.component.html
index f216459d8..99c13f597 100644
--- a/webui/src/app/charts/line-chart/line-chart.component.html
+++ b/webui/src/app/charts/line-chart/line-chart.component.html
@@ -2,6 +2,6 @@
Loading, please wait...
-
+
diff --git a/webui/src/app/charts/line-chart/line-chart.component.ts b/webui/src/app/charts/line-chart/line-chart.component.ts
index e07f132ea..0ecbb7067 100644
--- a/webui/src/app/charts/line-chart/line-chart.component.ts
+++ b/webui/src/app/charts/line-chart/line-chart.component.ts
@@ -1,4 +1,11 @@
-import { Component, ElementRef, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core';
+import {
+ Component,
+ ElementRef,
+ Input,
+ OnChanges,
+ OnInit,
+ SimpleChanges
+} from '@angular/core';
import {
axisBottom,
axisLeft,
@@ -21,7 +28,7 @@ import { WindowService } from '../../services/window.service';
templateUrl: 'line-chart.component.html'
})
export class LineChartComponent implements OnChanges, OnInit {
- @Input() value: { count: number, date: string };
+ @Input() value: { count: number; date: string };
firstDisplay: boolean;
dirty: boolean;
@@ -42,14 +49,21 @@ export class LineChartComponent implements OnChanges, OnInit {
yAxis: any;
height: number;
width: number;
- margin = {top: 40, right: 40, bottom: 60, left: 60};
+ margin = { top: 40, right: 40, bottom: 60, left: 60 };
loading = true;
- constructor(private elementRef: ElementRef, public windowService: WindowService) { }
+ constructor(
+ private elementRef: ElementRef,
+ public windowService: WindowService
+ ) {}
ngOnInit() {
- this.lineChartEl = this.elementRef.nativeElement.querySelector('.line-chart');
- this.loadingEl = this.elementRef.nativeElement.querySelector('.line-chart-loading');
+ this.lineChartEl = this.elementRef.nativeElement.querySelector(
+ '.line-chart'
+ );
+ this.loadingEl = this.elementRef.nativeElement.querySelector(
+ '.line-chart-loading'
+ );
this.limit = 40;
// related to the Observable.timer(0, 3000) in health component
@@ -77,7 +91,10 @@ export class LineChartComponent implements OnChanges, OnInit {
render() {
// When the lineChartEl is not displayed (is-hidden), width and length are equal to 0.
let elt;
- if (this.lineChartEl.clientWidth === 0 || this.lineChartEl.clientHeight === 0) {
+ if (
+ this.lineChartEl.clientWidth === 0 ||
+ this.lineChartEl.clientHeight === 0
+ ) {
elt = this.loadingEl;
} else {
elt = this.lineChartEl;
@@ -85,7 +102,6 @@ export class LineChartComponent implements OnChanges, OnInit {
this.width = elt.clientWidth - this.margin.left - this.margin.right;
this.height = elt.clientHeight - this.margin.top - this.margin.bottom;
-
const el = this.lineChartEl.querySelector('svg');
if (el) {
el.parentNode.removeChild(el);
@@ -105,11 +121,16 @@ export class LineChartComponent implements OnChanges, OnInit {
this.x = scaleTime().range([0, this.width - 10]);
this.y = scaleLinear().range([this.height, 0]);
- this.x.domain([this.now - (this.limit - 2), this.now - this.duration]);
+ this.x.domain([
+ (this.now as any) - (this.limit - 2),
+ (this.now as any) - this.duration
+ ]);
this.y.domain([0, max(this.data, (d: any) => d)]);
this.line = line()
- .x((d: any, i: number) => this.x(this.now - (this.limit - 1 - i) * this.duration))
+ .x((d: any, i: number) =>
+ this.x((this.now as any) - (this.limit - 1 - i) * this.duration)
+ )
.y((d: any) => this.y(d))
.curve(curveLinear);
@@ -121,16 +142,24 @@ export class LineChartComponent implements OnChanges, OnInit {
.attr('width', this.width)
.attr('height', this.height);
- this.xAxis = this.svg.append('g')
+ this.xAxis = this.svg
+ .append('g')
.attr('class', 'x axis')
.attr('transform', `translate(0, ${this.height})`)
- .call(axisBottom(this.x).tickSize(-this.height).ticks(timeSecond, 5).tickFormat(timeFormat('%H:%M:%S')));
+ .call(
+ axisBottom(this.x)
+ .tickSize(-this.height)
+ .ticks(timeSecond, 5)
+ .tickFormat(timeFormat('%H:%M:%S'))
+ );
- this.yAxis = this.svg.append('g')
+ this.yAxis = this.svg
+ .append('g')
.attr('class', 'y axis')
.call(axisLeft(this.y).tickSize(-this.width));
- this.path = this.svg.append('g')
+ this.path = this.svg
+ .append('g')
.attr('clip-path', 'url(#clip)')
.append('path')
.data([this.data])
@@ -149,8 +178,12 @@ export class LineChartComponent implements OnChanges, OnInit {
this.data.push(value * 1000000);
this.now = new Date();
- this.x.domain([this.now - (this.limit - 2) * this.duration, this.now - this.duration]);
- const minv = min(this.data, (d: any) => d) > 0 ? min(this.data, (d: any) => d) - 4 : 0;
+ this.x.domain([
+ (this.now as any) - (this.limit - 2) * this.duration,
+ (this.now as any) - this.duration
+ ]);
+ const minv =
+ min(this.data, (d: any) => d) > 0 ? min(this.data, (d: any) => d) - 4 : 0;
const maxv = max(this.data, (d: any) => d) + 4;
this.y.domain([minv, maxv]);
@@ -158,7 +191,12 @@ export class LineChartComponent implements OnChanges, OnInit {
.transition()
.duration(this.firstDisplay || this.dirty ? 0 : this.duration)
.ease(easeLinear)
- .call(axisBottom(this.x).tickSize(-this.height).ticks(timeSecond, 5).tickFormat(timeFormat('%H:%M:%S')));
+ .call(
+ axisBottom(this.x)
+ .tickSize(-this.height)
+ .ticks(timeSecond, 5)
+ .tickFormat(timeFormat('%H:%M:%S'))
+ );
this.xAxis
.transition()
@@ -183,7 +221,12 @@ export class LineChartComponent implements OnChanges, OnInit {
.transition()
.duration(this.duration)
.ease(easeLinear)
- .attr('transform', `translate(${this.x(this.now - (this.limit - 1) * this.duration)})`);
+ .attr(
+ 'transform',
+ `translate(${this.x(
+ (this.now as any) - (this.limit - 1) * this.duration
+ )})`
+ );
this.firstDisplay = false;
this.dirty = false;
diff --git a/webui/src/app/components/header/header.component.html b/webui/src/app/components/header/header.component.html
index 7254a8afb..f41266a64 100644
--- a/webui/src/app/components/header/header.component.html
+++ b/webui/src/app/components/header/header.component.html
@@ -1,11 +1,23 @@
-