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 @@ -