chore(deps): upgrade Angular 18 → 19
- ng update @angular/core@19 @angular/cli@19 @angular/material@19 @angular-eslint/schematics@19 - Migration: remove standalone:true (now default in v19) from 60 components - Migration: zone.js 0.14 → 0.15 - Fix pre-existing build budget error: raise initial bundle limit to 5mb (app ships large static JSON assets)
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { NgForOf, NgIf } from "@angular/common";
|
||||
import { NgForOf, NgIf } from '@angular/common';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
|
||||
import { CardColors } from 'src/app/core';
|
||||
@@ -7,12 +7,11 @@ import { CardColors } from 'src/app/core';
|
||||
@Component({
|
||||
selector: 'app-card-container',
|
||||
templateUrl: './card-container.component.html',
|
||||
standalone: true,
|
||||
imports: [NgIf, NgForOf, MatCardModule]
|
||||
imports: [NgIf, NgForOf, MatCardModule],
|
||||
})
|
||||
export class CardContainerComponent {
|
||||
errorList: string[] = [];
|
||||
@Input() colors: CardColors = { background: 'bg-megna', text: 'text-bg-primary' };
|
||||
@Input() title: string = 'Title';
|
||||
@Input() subtitle: string = 'Subtitle';
|
||||
}
|
||||
}
|
||||
|
||||
+104
-95
@@ -1,95 +1,104 @@
|
||||
import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core';
|
||||
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { MatDividerModule } from '@angular/material/divider';
|
||||
import { MatExpansionModule } from '@angular/material/expansion';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatMenuModule } from '@angular/material/menu';
|
||||
import { Observable, Subscription } from 'rxjs';
|
||||
|
||||
import { MenuItems } from '@components/shared';
|
||||
import { BarHorizontalChartComponent } from '@components/shared/helpers-chart';
|
||||
import { HistoryTableComponent } from '@components/shared/helpers-jump';
|
||||
import { UtilitiesService, AeronefsService } from '@services';
|
||||
import { AeronefByImat, AeronefByYear } from '@models';
|
||||
|
||||
@Component({
|
||||
selector: 'app-aeronefs-bar',
|
||||
standalone: true,
|
||||
imports: [
|
||||
MatButtonModule, MatCardModule, MatDividerModule,
|
||||
MatExpansionModule, MatIconModule, MatMenuModule,
|
||||
BarHorizontalChartComponent, HistoryTableComponent
|
||||
],
|
||||
templateUrl: './aeronefs-bar.component.html'
|
||||
})
|
||||
export class AeronefsBarComponent implements OnInit, OnDestroy {
|
||||
private _aeronefByImat: Subscription = new Subscription();
|
||||
private _aeronefByYear: Subscription = new Subscription();
|
||||
private _aeronefsByImat!: Array<AeronefByImat>;
|
||||
private _aeronefsByYear!: Array<AeronefByYear>;
|
||||
public title: string = 'Aéronefs';
|
||||
public subtitle: string = 'Nombre total de sauts par aéronef';
|
||||
public seriesHeader: string[] = [];
|
||||
public seriesName: string[] = [];
|
||||
public seriesValue: number[] = [];
|
||||
public seriesRow: Array<Array<number>> = [];
|
||||
public seriesColor: {
|
||||
backgroundColor: string[],
|
||||
borderColor: string[]
|
||||
} = {
|
||||
backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'all'),
|
||||
borderColor: this._utilitiesService.getSeriesColors(1, 'all')
|
||||
};
|
||||
public seriesColorClass: string[] = this._utilitiesService.getChartColors();
|
||||
public displayCharts = false;
|
||||
public destroyRef = inject(DestroyRef);
|
||||
|
||||
constructor(
|
||||
private _aeronefsService: AeronefsService,
|
||||
private _utilitiesService: UtilitiesService,
|
||||
public menuItems: MenuItems
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
this._loadAeronefByImat();
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this._aeronefByImat.unsubscribe();
|
||||
this._aeronefByYear.unsubscribe();
|
||||
}
|
||||
|
||||
private _loadAeronefByImat(): void {
|
||||
const aeronefs$: Observable<Array<AeronefByImat>> = this._aeronefsService.getAllByImat().pipe(takeUntilDestroyed(this.destroyRef));
|
||||
this._aeronefByImat = aeronefs$.subscribe((aggregate: Array<AeronefByImat>) => {
|
||||
this._aeronefsByImat = aggregate.map((row: AeronefByImat) => {
|
||||
//this.chartConfig.barChartData.labels!.push(`${row.aeronef} ${row.imat}`);
|
||||
this.seriesName.push(`${row.aeronef} ${row.imat}`);
|
||||
this.seriesValue.push(row.count);
|
||||
return row;
|
||||
});
|
||||
this._loadAeronefByYear();
|
||||
});
|
||||
}
|
||||
|
||||
private _loadAeronefByYear(): void {
|
||||
this.seriesHeader = ['2018', '2019', '2020', '2021', '2022', '2023', '2024'];
|
||||
const values: Array<number> = this.seriesHeader.map(() => 0);
|
||||
this.seriesName.forEach(() => {
|
||||
this.seriesRow.push([...values]);
|
||||
});
|
||||
const dropzones$: Observable<Array<AeronefByYear>> = this._aeronefsService.getAllByImatByYear().pipe(takeUntilDestroyed(this.destroyRef));
|
||||
this._aeronefByYear = dropzones$.subscribe((aggregate: Array<AeronefByYear>) => {
|
||||
this._aeronefsByYear = aggregate.map((row: AeronefByYear) => {
|
||||
const aeronef: string = row.aeronef;
|
||||
const imat: string = row.imat;
|
||||
const year: string = row.year.toString();
|
||||
this.seriesRow[this.seriesName.indexOf(`${aeronef} ${imat}`)][this.seriesHeader.indexOf(year)] = row.count;
|
||||
return row;
|
||||
});
|
||||
this.displayCharts = true;
|
||||
});
|
||||
}
|
||||
}
|
||||
import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core';
|
||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { MatDividerModule } from '@angular/material/divider';
|
||||
import { MatExpansionModule } from '@angular/material/expansion';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatMenuModule } from '@angular/material/menu';
|
||||
import { Observable, Subscription } from 'rxjs';
|
||||
|
||||
import { MenuItems } from '@components/shared';
|
||||
import { BarHorizontalChartComponent } from '@components/shared/helpers-chart';
|
||||
import { HistoryTableComponent } from '@components/shared/helpers-jump';
|
||||
import { UtilitiesService, AeronefsService } from '@services';
|
||||
import { AeronefByImat, AeronefByYear } from '@models';
|
||||
|
||||
@Component({
|
||||
selector: 'app-aeronefs-bar',
|
||||
imports: [
|
||||
MatButtonModule,
|
||||
MatCardModule,
|
||||
MatDividerModule,
|
||||
MatExpansionModule,
|
||||
MatIconModule,
|
||||
MatMenuModule,
|
||||
BarHorizontalChartComponent,
|
||||
HistoryTableComponent,
|
||||
],
|
||||
templateUrl: './aeronefs-bar.component.html',
|
||||
})
|
||||
export class AeronefsBarComponent implements OnInit, OnDestroy {
|
||||
private _aeronefByImat: Subscription = new Subscription();
|
||||
private _aeronefByYear: Subscription = new Subscription();
|
||||
private _aeronefsByImat!: Array<AeronefByImat>;
|
||||
private _aeronefsByYear!: Array<AeronefByYear>;
|
||||
public title: string = 'Aéronefs';
|
||||
public subtitle: string = 'Nombre total de sauts par aéronef';
|
||||
public seriesHeader: string[] = [];
|
||||
public seriesName: string[] = [];
|
||||
public seriesValue: number[] = [];
|
||||
public seriesRow: Array<Array<number>> = [];
|
||||
public seriesColor: {
|
||||
backgroundColor: string[];
|
||||
borderColor: string[];
|
||||
} = {
|
||||
backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'all'),
|
||||
borderColor: this._utilitiesService.getSeriesColors(1, 'all'),
|
||||
};
|
||||
public seriesColorClass: string[] = this._utilitiesService.getChartColors();
|
||||
public displayCharts = false;
|
||||
public destroyRef = inject(DestroyRef);
|
||||
|
||||
constructor(
|
||||
private _aeronefsService: AeronefsService,
|
||||
private _utilitiesService: UtilitiesService,
|
||||
public menuItems: MenuItems,
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this._loadAeronefByImat();
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this._aeronefByImat.unsubscribe();
|
||||
this._aeronefByYear.unsubscribe();
|
||||
}
|
||||
|
||||
private _loadAeronefByImat(): void {
|
||||
const aeronefs$: Observable<Array<AeronefByImat>> = this._aeronefsService
|
||||
.getAllByImat()
|
||||
.pipe(takeUntilDestroyed(this.destroyRef));
|
||||
this._aeronefByImat = aeronefs$.subscribe((aggregate: Array<AeronefByImat>) => {
|
||||
this._aeronefsByImat = aggregate.map((row: AeronefByImat) => {
|
||||
//this.chartConfig.barChartData.labels!.push(`${row.aeronef} ${row.imat}`);
|
||||
this.seriesName.push(`${row.aeronef} ${row.imat}`);
|
||||
this.seriesValue.push(row.count);
|
||||
return row;
|
||||
});
|
||||
this._loadAeronefByYear();
|
||||
});
|
||||
}
|
||||
|
||||
private _loadAeronefByYear(): void {
|
||||
this.seriesHeader = ['2018', '2019', '2020', '2021', '2022', '2023', '2024'];
|
||||
const values: Array<number> = this.seriesHeader.map(() => 0);
|
||||
this.seriesName.forEach(() => {
|
||||
this.seriesRow.push([...values]);
|
||||
});
|
||||
const dropzones$: Observable<Array<AeronefByYear>> = this._aeronefsService
|
||||
.getAllByImatByYear()
|
||||
.pipe(takeUntilDestroyed(this.destroyRef));
|
||||
this._aeronefByYear = dropzones$.subscribe((aggregate: Array<AeronefByYear>) => {
|
||||
this._aeronefsByYear = aggregate.map((row: AeronefByYear) => {
|
||||
const aeronef: string = row.aeronef;
|
||||
const imat: string = row.imat;
|
||||
const year: string = row.year.toString();
|
||||
this.seriesRow[this.seriesName.indexOf(`${aeronef} ${imat}`)][this.seriesHeader.indexOf(year)] =
|
||||
row.count;
|
||||
return row;
|
||||
});
|
||||
this.displayCharts = true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+103
-93
@@ -1,93 +1,103 @@
|
||||
import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core';
|
||||
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
||||
import { MatBadgeModule } from '@angular/material/badge';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { MatDividerModule } from '@angular/material/divider';
|
||||
import { MatExpansionModule } from '@angular/material/expansion';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatMenuModule } from '@angular/material/menu';
|
||||
import { Observable, Subscription } from 'rxjs';
|
||||
|
||||
import { MenuItems } from '@components/shared';
|
||||
import { HistoryTableComponent } from '@components/shared/helpers-jump';
|
||||
import { PieChartComponent } from '@components/shared/helpers-chart';
|
||||
import { UtilitiesService, AeronefsService } from '@services';
|
||||
import { AeronefByImat, AeronefByYear } from '@models';
|
||||
|
||||
@Component({
|
||||
selector: 'app-aeronefs-pie',
|
||||
standalone: true,
|
||||
imports: [
|
||||
MatBadgeModule, MatButtonModule, MatCardModule, MatDividerModule,
|
||||
MatExpansionModule, MatIconModule, MatMenuModule,
|
||||
HistoryTableComponent, PieChartComponent
|
||||
],
|
||||
templateUrl: './aeronefs-pie.component.html'
|
||||
})
|
||||
export class AeronefsPieComponent implements OnInit, OnDestroy {
|
||||
private _aeronefByImat: Subscription = new Subscription();
|
||||
private _aeronefByYear: Subscription = new Subscription();
|
||||
private _aeronefsByImat!: Array<AeronefByImat>;
|
||||
private _aeronefsByYear!: Array<AeronefByYear>;
|
||||
public title: string = 'Aéronefs';
|
||||
public subtitle: string = 'Nombre total de sauts par aéronef';
|
||||
public seriesHeader: string[] = [];
|
||||
public seriesName: string[] = [];
|
||||
public seriesValue: number[] = [];
|
||||
public seriesRow: Array<Array<number>> = [];
|
||||
public seriesColor: {
|
||||
backgroundColor: string[],
|
||||
borderColor: string[]
|
||||
} = {
|
||||
backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'all'),
|
||||
borderColor: this._utilitiesService.getSeriesColors(1, 'all')
|
||||
};
|
||||
public seriesColorClass: string[] = this._utilitiesService.getChartColors();
|
||||
public destroyRef = inject(DestroyRef);
|
||||
|
||||
constructor(
|
||||
private _aeronefsService: AeronefsService,
|
||||
private _utilitiesService: UtilitiesService,
|
||||
public menuItems: MenuItems
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
this._loadAeronefByImat();
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this._aeronefByImat.unsubscribe();
|
||||
this._aeronefByYear.unsubscribe();
|
||||
}
|
||||
|
||||
private _loadAeronefByImat(): void {
|
||||
const aeronefs$: Observable<Array<AeronefByImat>> = this._aeronefsService.getAllByImat().pipe(takeUntilDestroyed(this.destroyRef));
|
||||
this._aeronefByImat = aeronefs$.subscribe((aggregate: Array<AeronefByImat>) => {
|
||||
this._aeronefsByImat = aggregate.map((row: AeronefByImat) => {
|
||||
this.seriesName.push(`${row.aeronef} ${row.imat}`);
|
||||
this.seriesValue.push(row.count);
|
||||
return row;
|
||||
});
|
||||
this._loadAeronefByYear();
|
||||
});
|
||||
}
|
||||
|
||||
private _loadAeronefByYear(): void {
|
||||
this.seriesHeader = ['2018', '2019', '2020', '2021', '2022', '2023', '2024'];
|
||||
const values: Array<number> = this.seriesHeader.map(() => 0);
|
||||
this.seriesName.forEach(() => {
|
||||
this.seriesRow.push([...values]);
|
||||
});
|
||||
const dropzones$: Observable<Array<AeronefByYear>> = this._aeronefsService.getAllByImatByYear().pipe(takeUntilDestroyed(this.destroyRef));
|
||||
this._aeronefByYear = dropzones$.subscribe((aggregate: Array<AeronefByYear>) => {
|
||||
this._aeronefsByYear = aggregate.map((row: AeronefByYear) => {
|
||||
const aeronef: string = row.aeronef;
|
||||
const imat: string = row.imat;
|
||||
const year: string = row.year.toString();
|
||||
this.seriesRow[this.seriesName.indexOf(`${aeronef} ${imat}`)][this.seriesHeader.indexOf(year)] = row.count;
|
||||
return row;
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core';
|
||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||
import { MatBadgeModule } from '@angular/material/badge';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { MatDividerModule } from '@angular/material/divider';
|
||||
import { MatExpansionModule } from '@angular/material/expansion';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatMenuModule } from '@angular/material/menu';
|
||||
import { Observable, Subscription } from 'rxjs';
|
||||
|
||||
import { MenuItems } from '@components/shared';
|
||||
import { HistoryTableComponent } from '@components/shared/helpers-jump';
|
||||
import { PieChartComponent } from '@components/shared/helpers-chart';
|
||||
import { UtilitiesService, AeronefsService } from '@services';
|
||||
import { AeronefByImat, AeronefByYear } from '@models';
|
||||
|
||||
@Component({
|
||||
selector: 'app-aeronefs-pie',
|
||||
imports: [
|
||||
MatBadgeModule,
|
||||
MatButtonModule,
|
||||
MatCardModule,
|
||||
MatDividerModule,
|
||||
MatExpansionModule,
|
||||
MatIconModule,
|
||||
MatMenuModule,
|
||||
HistoryTableComponent,
|
||||
PieChartComponent,
|
||||
],
|
||||
templateUrl: './aeronefs-pie.component.html',
|
||||
})
|
||||
export class AeronefsPieComponent implements OnInit, OnDestroy {
|
||||
private _aeronefByImat: Subscription = new Subscription();
|
||||
private _aeronefByYear: Subscription = new Subscription();
|
||||
private _aeronefsByImat!: Array<AeronefByImat>;
|
||||
private _aeronefsByYear!: Array<AeronefByYear>;
|
||||
public title: string = 'Aéronefs';
|
||||
public subtitle: string = 'Nombre total de sauts par aéronef';
|
||||
public seriesHeader: string[] = [];
|
||||
public seriesName: string[] = [];
|
||||
public seriesValue: number[] = [];
|
||||
public seriesRow: Array<Array<number>> = [];
|
||||
public seriesColor: {
|
||||
backgroundColor: string[];
|
||||
borderColor: string[];
|
||||
} = {
|
||||
backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'all'),
|
||||
borderColor: this._utilitiesService.getSeriesColors(1, 'all'),
|
||||
};
|
||||
public seriesColorClass: string[] = this._utilitiesService.getChartColors();
|
||||
public destroyRef = inject(DestroyRef);
|
||||
|
||||
constructor(
|
||||
private _aeronefsService: AeronefsService,
|
||||
private _utilitiesService: UtilitiesService,
|
||||
public menuItems: MenuItems,
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this._loadAeronefByImat();
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this._aeronefByImat.unsubscribe();
|
||||
this._aeronefByYear.unsubscribe();
|
||||
}
|
||||
|
||||
private _loadAeronefByImat(): void {
|
||||
const aeronefs$: Observable<Array<AeronefByImat>> = this._aeronefsService
|
||||
.getAllByImat()
|
||||
.pipe(takeUntilDestroyed(this.destroyRef));
|
||||
this._aeronefByImat = aeronefs$.subscribe((aggregate: Array<AeronefByImat>) => {
|
||||
this._aeronefsByImat = aggregate.map((row: AeronefByImat) => {
|
||||
this.seriesName.push(`${row.aeronef} ${row.imat}`);
|
||||
this.seriesValue.push(row.count);
|
||||
return row;
|
||||
});
|
||||
this._loadAeronefByYear();
|
||||
});
|
||||
}
|
||||
|
||||
private _loadAeronefByYear(): void {
|
||||
this.seriesHeader = ['2018', '2019', '2020', '2021', '2022', '2023', '2024'];
|
||||
const values: Array<number> = this.seriesHeader.map(() => 0);
|
||||
this.seriesName.forEach(() => {
|
||||
this.seriesRow.push([...values]);
|
||||
});
|
||||
const dropzones$: Observable<Array<AeronefByYear>> = this._aeronefsService
|
||||
.getAllByImatByYear()
|
||||
.pipe(takeUntilDestroyed(this.destroyRef));
|
||||
this._aeronefByYear = dropzones$.subscribe((aggregate: Array<AeronefByYear>) => {
|
||||
this._aeronefsByYear = aggregate.map((row: AeronefByYear) => {
|
||||
const aeronef: string = row.aeronef;
|
||||
const imat: string = row.imat;
|
||||
const year: string = row.year.toString();
|
||||
this.seriesRow[this.seriesName.indexOf(`${aeronef} ${imat}`)][this.seriesHeader.indexOf(year)] =
|
||||
row.count;
|
||||
return row;
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+101
-92
@@ -1,92 +1,101 @@
|
||||
import { Component, DestroyRef, inject, OnInit, OnDestroy} from '@angular/core';
|
||||
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { MatDividerModule } from '@angular/material/divider';
|
||||
import { MatExpansionModule } from '@angular/material/expansion';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatMenuModule } from '@angular/material/menu';
|
||||
import { Observable, Subscription } from 'rxjs';
|
||||
|
||||
import { MenuItems } from '@components/shared';
|
||||
import { PieChartComponent } from '@components/shared/helpers-chart';
|
||||
import { HistoryTableComponent } from '@components/shared/helpers-jump';
|
||||
import { UtilitiesService, CanopiesService } from '@services';
|
||||
import { CanopyModelBySize, CanopyModelByYear } from '@models';
|
||||
|
||||
@Component({
|
||||
selector: 'app-canopies-models',
|
||||
standalone: true,
|
||||
imports: [
|
||||
MatButtonModule, MatCardModule, MatDividerModule,
|
||||
MatExpansionModule, MatIconModule, MatMenuModule,
|
||||
PieChartComponent, HistoryTableComponent
|
||||
],
|
||||
templateUrl: './canopies-models.component.html'
|
||||
})
|
||||
export class CanopiesModelsComponent implements OnInit, OnDestroy {
|
||||
private _canopyBySize: Subscription = new Subscription();
|
||||
private _canopyByYear: Subscription = new Subscription();
|
||||
private _canopiesBySize!: Array<CanopyModelBySize>;
|
||||
private _canopiesByYear!: Array<CanopyModelByYear>;
|
||||
public title: string = 'Modèles de voile';
|
||||
public subtitle: string = 'Nombre total de sauts par modèle';
|
||||
public seriesHeader: string[] = [];
|
||||
public seriesName: string[] = [];
|
||||
public seriesValue: number[] = [];
|
||||
public seriesRow: Array<Array<number>> = [];
|
||||
public seriesColor: {
|
||||
backgroundColor: string[],
|
||||
borderColor: string[]
|
||||
} = {
|
||||
backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'all'),
|
||||
borderColor: this._utilitiesService.getSeriesColors(1, 'all')
|
||||
};
|
||||
public seriesColorClass: string[] = this._utilitiesService.getChartColors();
|
||||
public destroyRef = inject(DestroyRef);
|
||||
|
||||
constructor(
|
||||
private _canopiesService: CanopiesService,
|
||||
private _utilitiesService: UtilitiesService,
|
||||
public menuItems: MenuItems
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
this._loadCanopyModelBySize();
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this._canopyBySize.unsubscribe();
|
||||
this._canopyByYear.unsubscribe();
|
||||
}
|
||||
|
||||
private _loadCanopyModelBySize(): void {
|
||||
const canopies$: Observable<Array<CanopyModelBySize>> = this._canopiesService.getAllBySizeByModel().pipe(takeUntilDestroyed(this.destroyRef));
|
||||
this._canopyBySize = canopies$.subscribe((aggregate: Array<CanopyModelBySize>) => {
|
||||
this._canopiesBySize = aggregate.map((row: CanopyModelBySize) => {
|
||||
this.seriesName.push(`${row.taille.toString()} - ${row.voile}`);
|
||||
this.seriesValue.push(row.count);
|
||||
return row;
|
||||
});
|
||||
this._loadCanopyModelByYear();
|
||||
});
|
||||
}
|
||||
|
||||
private _loadCanopyModelByYear(): void {
|
||||
this.seriesHeader = ['2018', '2019', '2020', '2021', '2022', '2023', '2024'];
|
||||
const values: Array<number> = this.seriesHeader.map(() => 0);
|
||||
this.seriesName.forEach(() => {
|
||||
this.seriesRow.push([...values]);
|
||||
});
|
||||
const dropzones$: Observable<Array<CanopyModelByYear>> = this._canopiesService.getAllBySizeByModelByYear().pipe(takeUntilDestroyed(this.destroyRef));
|
||||
this._canopyByYear = dropzones$.subscribe((aggregate: Array<CanopyModelByYear>) => {
|
||||
this._canopiesByYear = aggregate.map((row: CanopyModelByYear) => {
|
||||
const voile: string = row.voile;
|
||||
const taille: string = row.taille.toString();
|
||||
const year: string = row.year.toString();
|
||||
this.seriesRow[this.seriesName.indexOf(`${taille} - ${voile}`)][this.seriesHeader.indexOf(year)] = row.count;
|
||||
return row;
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core';
|
||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { MatDividerModule } from '@angular/material/divider';
|
||||
import { MatExpansionModule } from '@angular/material/expansion';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatMenuModule } from '@angular/material/menu';
|
||||
import { Observable, Subscription } from 'rxjs';
|
||||
|
||||
import { MenuItems } from '@components/shared';
|
||||
import { PieChartComponent } from '@components/shared/helpers-chart';
|
||||
import { HistoryTableComponent } from '@components/shared/helpers-jump';
|
||||
import { UtilitiesService, CanopiesService } from '@services';
|
||||
import { CanopyModelBySize, CanopyModelByYear } from '@models';
|
||||
|
||||
@Component({
|
||||
selector: 'app-canopies-models',
|
||||
imports: [
|
||||
MatButtonModule,
|
||||
MatCardModule,
|
||||
MatDividerModule,
|
||||
MatExpansionModule,
|
||||
MatIconModule,
|
||||
MatMenuModule,
|
||||
PieChartComponent,
|
||||
HistoryTableComponent,
|
||||
],
|
||||
templateUrl: './canopies-models.component.html',
|
||||
})
|
||||
export class CanopiesModelsComponent implements OnInit, OnDestroy {
|
||||
private _canopyBySize: Subscription = new Subscription();
|
||||
private _canopyByYear: Subscription = new Subscription();
|
||||
private _canopiesBySize!: Array<CanopyModelBySize>;
|
||||
private _canopiesByYear!: Array<CanopyModelByYear>;
|
||||
public title: string = 'Modèles de voile';
|
||||
public subtitle: string = 'Nombre total de sauts par modèle';
|
||||
public seriesHeader: string[] = [];
|
||||
public seriesName: string[] = [];
|
||||
public seriesValue: number[] = [];
|
||||
public seriesRow: Array<Array<number>> = [];
|
||||
public seriesColor: {
|
||||
backgroundColor: string[];
|
||||
borderColor: string[];
|
||||
} = {
|
||||
backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'all'),
|
||||
borderColor: this._utilitiesService.getSeriesColors(1, 'all'),
|
||||
};
|
||||
public seriesColorClass: string[] = this._utilitiesService.getChartColors();
|
||||
public destroyRef = inject(DestroyRef);
|
||||
|
||||
constructor(
|
||||
private _canopiesService: CanopiesService,
|
||||
private _utilitiesService: UtilitiesService,
|
||||
public menuItems: MenuItems,
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this._loadCanopyModelBySize();
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this._canopyBySize.unsubscribe();
|
||||
this._canopyByYear.unsubscribe();
|
||||
}
|
||||
|
||||
private _loadCanopyModelBySize(): void {
|
||||
const canopies$: Observable<Array<CanopyModelBySize>> = this._canopiesService
|
||||
.getAllBySizeByModel()
|
||||
.pipe(takeUntilDestroyed(this.destroyRef));
|
||||
this._canopyBySize = canopies$.subscribe((aggregate: Array<CanopyModelBySize>) => {
|
||||
this._canopiesBySize = aggregate.map((row: CanopyModelBySize) => {
|
||||
this.seriesName.push(`${row.taille.toString()} - ${row.voile}`);
|
||||
this.seriesValue.push(row.count);
|
||||
return row;
|
||||
});
|
||||
this._loadCanopyModelByYear();
|
||||
});
|
||||
}
|
||||
|
||||
private _loadCanopyModelByYear(): void {
|
||||
this.seriesHeader = ['2018', '2019', '2020', '2021', '2022', '2023', '2024'];
|
||||
const values: Array<number> = this.seriesHeader.map(() => 0);
|
||||
this.seriesName.forEach(() => {
|
||||
this.seriesRow.push([...values]);
|
||||
});
|
||||
const dropzones$: Observable<Array<CanopyModelByYear>> = this._canopiesService
|
||||
.getAllBySizeByModelByYear()
|
||||
.pipe(takeUntilDestroyed(this.destroyRef));
|
||||
this._canopyByYear = dropzones$.subscribe((aggregate: Array<CanopyModelByYear>) => {
|
||||
this._canopiesByYear = aggregate.map((row: CanopyModelByYear) => {
|
||||
const voile: string = row.voile;
|
||||
const taille: string = row.taille.toString();
|
||||
const year: string = row.year.toString();
|
||||
this.seriesRow[this.seriesName.indexOf(`${taille} - ${voile}`)][this.seriesHeader.indexOf(year)] =
|
||||
row.count;
|
||||
return row;
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+100
-92
@@ -1,92 +1,100 @@
|
||||
import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core';
|
||||
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { MatDividerModule } from '@angular/material/divider';
|
||||
import { MatExpansionModule } from '@angular/material/expansion';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatMenuModule } from '@angular/material/menu';
|
||||
|
||||
import { Observable, Subscription } from 'rxjs';
|
||||
|
||||
import { MenuItems } from '@components/shared';
|
||||
import { PieChartComponent } from '@components/shared/helpers-chart';
|
||||
import { HistoryTableComponent } from '@components/shared/helpers-jump';
|
||||
import { UtilitiesService, CanopiesService } from '@services';
|
||||
import { CanopyBySize, CanopyByYear } from '@models';
|
||||
|
||||
@Component({
|
||||
selector: 'app-canopies-sizes',
|
||||
standalone: true,
|
||||
imports: [
|
||||
MatButtonModule, MatCardModule, MatDividerModule,
|
||||
MatExpansionModule, MatIconModule, MatMenuModule,
|
||||
PieChartComponent, HistoryTableComponent
|
||||
],
|
||||
templateUrl: './canopies-sizes.component.html'
|
||||
})
|
||||
export class CanopiesSizesComponent implements OnInit, OnDestroy {
|
||||
private _canopyBySize: Subscription = new Subscription();
|
||||
private _canopyByYear: Subscription = new Subscription();
|
||||
private _canopiesBySize!: Array<CanopyBySize>;
|
||||
private _canopiesByYear!: Array<CanopyByYear>;
|
||||
public title: string = 'Tailles de voile';
|
||||
public subtitle: string = 'Nombre total de sauts par taille';
|
||||
public seriesHeader: string[] = [];
|
||||
public seriesName: string[] = [];
|
||||
public seriesValue: number[] = [];
|
||||
public seriesRow: Array<Array<number>> = [];
|
||||
public seriesColor: {
|
||||
backgroundColor: string[],
|
||||
borderColor: string[]
|
||||
} = {
|
||||
backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'all'),
|
||||
borderColor: this._utilitiesService.getSeriesColors(1, 'all')
|
||||
};
|
||||
public seriesColorClass: string[] = this._utilitiesService.getChartColors();
|
||||
public destroyRef = inject(DestroyRef);
|
||||
|
||||
constructor(
|
||||
private _canopiesService: CanopiesService,
|
||||
private _utilitiesService: UtilitiesService,
|
||||
public menuItems: MenuItems
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
this._loadCanopyBySize();
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this._canopyBySize.unsubscribe();
|
||||
this._canopyByYear.unsubscribe();
|
||||
}
|
||||
|
||||
private _loadCanopyBySize(): void {
|
||||
const canopies$: Observable<Array<CanopyBySize>> = this._canopiesService.getAllBySize().pipe(takeUntilDestroyed(this.destroyRef));
|
||||
this._canopyBySize = canopies$.subscribe((aggregate: Array<CanopyBySize>) => {
|
||||
this._canopiesBySize = aggregate.map((row: CanopyBySize) => {
|
||||
this.seriesName.push(row.taille.toString());
|
||||
this.seriesValue.push(row.count);
|
||||
return row;
|
||||
});
|
||||
this._loadCanopyByYear();
|
||||
});
|
||||
}
|
||||
|
||||
private _loadCanopyByYear(): void {
|
||||
this.seriesHeader = ['2018', '2019', '2020', '2021', '2022', '2023', '2024'];
|
||||
const values: Array<number> = this.seriesHeader.map(() => 0);
|
||||
this.seriesName.forEach(() => {
|
||||
this.seriesRow.push([...values]);
|
||||
});
|
||||
const dropzones$: Observable<Array<CanopyByYear>> = this._canopiesService.getAllBySizeByYear().pipe(takeUntilDestroyed(this.destroyRef));
|
||||
this._canopyByYear = dropzones$.subscribe((aggregate: Array<CanopyByYear>) => {
|
||||
this._canopiesByYear = aggregate.map((row: CanopyByYear) => {
|
||||
const taille: string = row.taille.toString();
|
||||
const year: string = row.year.toString();
|
||||
this.seriesRow[this.seriesName.indexOf(taille)][this.seriesHeader.indexOf(year)] = row.count;
|
||||
return row;
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core';
|
||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { MatDividerModule } from '@angular/material/divider';
|
||||
import { MatExpansionModule } from '@angular/material/expansion';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatMenuModule } from '@angular/material/menu';
|
||||
|
||||
import { Observable, Subscription } from 'rxjs';
|
||||
|
||||
import { MenuItems } from '@components/shared';
|
||||
import { PieChartComponent } from '@components/shared/helpers-chart';
|
||||
import { HistoryTableComponent } from '@components/shared/helpers-jump';
|
||||
import { UtilitiesService, CanopiesService } from '@services';
|
||||
import { CanopyBySize, CanopyByYear } from '@models';
|
||||
|
||||
@Component({
|
||||
selector: 'app-canopies-sizes',
|
||||
imports: [
|
||||
MatButtonModule,
|
||||
MatCardModule,
|
||||
MatDividerModule,
|
||||
MatExpansionModule,
|
||||
MatIconModule,
|
||||
MatMenuModule,
|
||||
PieChartComponent,
|
||||
HistoryTableComponent,
|
||||
],
|
||||
templateUrl: './canopies-sizes.component.html',
|
||||
})
|
||||
export class CanopiesSizesComponent implements OnInit, OnDestroy {
|
||||
private _canopyBySize: Subscription = new Subscription();
|
||||
private _canopyByYear: Subscription = new Subscription();
|
||||
private _canopiesBySize!: Array<CanopyBySize>;
|
||||
private _canopiesByYear!: Array<CanopyByYear>;
|
||||
public title: string = 'Tailles de voile';
|
||||
public subtitle: string = 'Nombre total de sauts par taille';
|
||||
public seriesHeader: string[] = [];
|
||||
public seriesName: string[] = [];
|
||||
public seriesValue: number[] = [];
|
||||
public seriesRow: Array<Array<number>> = [];
|
||||
public seriesColor: {
|
||||
backgroundColor: string[];
|
||||
borderColor: string[];
|
||||
} = {
|
||||
backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'all'),
|
||||
borderColor: this._utilitiesService.getSeriesColors(1, 'all'),
|
||||
};
|
||||
public seriesColorClass: string[] = this._utilitiesService.getChartColors();
|
||||
public destroyRef = inject(DestroyRef);
|
||||
|
||||
constructor(
|
||||
private _canopiesService: CanopiesService,
|
||||
private _utilitiesService: UtilitiesService,
|
||||
public menuItems: MenuItems,
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this._loadCanopyBySize();
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this._canopyBySize.unsubscribe();
|
||||
this._canopyByYear.unsubscribe();
|
||||
}
|
||||
|
||||
private _loadCanopyBySize(): void {
|
||||
const canopies$: Observable<Array<CanopyBySize>> = this._canopiesService
|
||||
.getAllBySize()
|
||||
.pipe(takeUntilDestroyed(this.destroyRef));
|
||||
this._canopyBySize = canopies$.subscribe((aggregate: Array<CanopyBySize>) => {
|
||||
this._canopiesBySize = aggregate.map((row: CanopyBySize) => {
|
||||
this.seriesName.push(row.taille.toString());
|
||||
this.seriesValue.push(row.count);
|
||||
return row;
|
||||
});
|
||||
this._loadCanopyByYear();
|
||||
});
|
||||
}
|
||||
|
||||
private _loadCanopyByYear(): void {
|
||||
this.seriesHeader = ['2018', '2019', '2020', '2021', '2022', '2023', '2024'];
|
||||
const values: Array<number> = this.seriesHeader.map(() => 0);
|
||||
this.seriesName.forEach(() => {
|
||||
this.seriesRow.push([...values]);
|
||||
});
|
||||
const dropzones$: Observable<Array<CanopyByYear>> = this._canopiesService
|
||||
.getAllBySizeByYear()
|
||||
.pipe(takeUntilDestroyed(this.destroyRef));
|
||||
this._canopyByYear = dropzones$.subscribe((aggregate: Array<CanopyByYear>) => {
|
||||
this._canopiesByYear = aggregate.map((row: CanopyByYear) => {
|
||||
const taille: string = row.taille.toString();
|
||||
const year: string = row.year.toString();
|
||||
this.seriesRow[this.seriesName.indexOf(taille)][this.seriesHeader.indexOf(year)] = row.count;
|
||||
return row;
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+161
-143
@@ -1,143 +1,161 @@
|
||||
import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core';
|
||||
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { MatDividerModule } from '@angular/material/divider';
|
||||
import { MatExpansionModule } from '@angular/material/expansion';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatMenuModule } from '@angular/material/menu';
|
||||
import { BaseChartDirective } from 'ng2-charts';
|
||||
import { ChartistModule, Configuration } from 'ng-chartist';
|
||||
import { AxisOptions, Label } from 'chartist';
|
||||
import { Observable, Subscription } from 'rxjs';
|
||||
|
||||
import { MenuItems } from '@components/shared';
|
||||
import { HistoryTableComponent } from '@components/shared/helpers-jump';
|
||||
import { UtilitiesService, DropZonesService } from '@services';
|
||||
import { DropZoneByOaci, DropZoneByYear } from '@models';
|
||||
|
||||
@Component({
|
||||
selector: 'app-dropzones-bar',
|
||||
standalone: true,
|
||||
imports: [
|
||||
MatButtonModule, MatCardModule, MatDividerModule,
|
||||
MatExpansionModule, MatIconModule, MatMenuModule,
|
||||
BaseChartDirective, ChartistModule,
|
||||
HistoryTableComponent
|
||||
],
|
||||
templateUrl: './dropzones-bar.component.html'
|
||||
})
|
||||
export class DropzonesBarComponent implements OnInit, OnDestroy {
|
||||
private _dropzoneByOaci: Subscription = new Subscription();
|
||||
private _dropzoneByYear: Subscription = new Subscription();
|
||||
private _dropzonesByOaci!: Array<DropZoneByOaci>;
|
||||
private _dropzonesByYear!: Array<DropZoneByYear>;
|
||||
public title: string = 'Les dropzones';
|
||||
public subtitle: string = 'Nombre total de sauts par dropzone';
|
||||
public seriesHeader: string[] = [];
|
||||
public seriesName: string[] = [];
|
||||
public seriesValue: number[] = [];
|
||||
public seriesRow: Array<Array<number>> = [];
|
||||
public seriesColor: {
|
||||
backgroundColor: string[],
|
||||
borderColor: string[]
|
||||
} = {
|
||||
backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'all'),
|
||||
borderColor: this._utilitiesService.getSeriesColors(1, 'all')
|
||||
};
|
||||
public seriesColorClass: string[] = this._utilitiesService.getChartColors();
|
||||
public displayCharts = false;
|
||||
public barChartDropZones: Configuration = this._utilitiesService.getBarConfig();
|
||||
public destroyRef = inject(DestroyRef);
|
||||
|
||||
constructor(
|
||||
private _dropzonesService: DropZonesService,
|
||||
private _utilitiesService: UtilitiesService,
|
||||
public menuItems: MenuItems
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
this._loadDropZoneByOaci();
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this._dropzoneByOaci.unsubscribe();
|
||||
this._dropzoneByYear.unsubscribe();
|
||||
}
|
||||
|
||||
private _loadDropZoneByOaci(): void {
|
||||
const dropzones$: Observable<Array<DropZoneByOaci>> = this._dropzonesService.getAllByOaci().pipe(takeUntilDestroyed(this.destroyRef));
|
||||
this._dropzoneByOaci = dropzones$.subscribe((aggregate: Array<DropZoneByOaci>) => {
|
||||
this._dropzonesByOaci = aggregate.map((row: DropZoneByOaci) => {
|
||||
this.seriesName.push(`${row.oaci} - ${row.lieu}`);
|
||||
this.seriesValue.push(row.count);
|
||||
return row;
|
||||
});
|
||||
this._loadDropZoneByYear();
|
||||
});
|
||||
}
|
||||
|
||||
private _loadDropZoneByYear(): void {
|
||||
this.seriesHeader = ['2018', '2019', '2020', '2021', '2022', '2023', '2024'];
|
||||
const values: Array<number> = this.seriesHeader.map(() => 0);
|
||||
this.seriesName.forEach(() => {
|
||||
this.seriesRow.push([...values]);
|
||||
});
|
||||
const dropzones$: Observable<Array<DropZoneByYear>> = this._dropzonesService.getAllByOaciByYear().pipe(takeUntilDestroyed(this.destroyRef));
|
||||
this._dropzoneByYear = dropzones$.subscribe((aggregate: Array<DropZoneByYear>) => {
|
||||
this._dropzonesByYear = aggregate.map((row: DropZoneByYear) => {
|
||||
const lieu: string = row.lieu;
|
||||
const oaci: string = row.oaci;
|
||||
const year: string = row.year.toString();
|
||||
this.seriesRow[this.seriesName.indexOf(`${oaci} - ${lieu}`)][this.seriesHeader.indexOf(year)] = row.count;
|
||||
return row;
|
||||
});
|
||||
const axisX: AxisOptions = {
|
||||
labelInterpolationFnc: function(value: Label, index: number): string {
|
||||
return index % 1 === 0 ? `${value.toString()}` : '';
|
||||
}
|
||||
}
|
||||
this.barChartDropZones = {
|
||||
type: 'Bar',
|
||||
data: {
|
||||
'labels': this.seriesHeader,
|
||||
'series': this.seriesRow
|
||||
},
|
||||
options: {
|
||||
seriesBarDistance: 15,
|
||||
horizontalBars: false,
|
||||
high: 180,
|
||||
axisX: {
|
||||
showGrid: false,
|
||||
offset: 20
|
||||
},
|
||||
axisY: {
|
||||
showGrid: true,
|
||||
offset: 40
|
||||
},
|
||||
height: 300
|
||||
},
|
||||
responsiveOptions: [
|
||||
['screen and (min-width: 1024px)', {
|
||||
axisX: axisX
|
||||
}],
|
||||
['screen and (min-width: 641px) and (max-width: 1024px)', {
|
||||
seriesBarDistance: 7,
|
||||
axisY: {
|
||||
offset: 30
|
||||
},
|
||||
axisX: axisX
|
||||
}],
|
||||
['screen and (max-width: 640px)', {
|
||||
seriesBarDistance: 5,
|
||||
axisY: {
|
||||
offset: 20
|
||||
},
|
||||
axisX: axisX
|
||||
}]
|
||||
]
|
||||
};
|
||||
this.displayCharts = true;
|
||||
});
|
||||
}
|
||||
}
|
||||
import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core';
|
||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { MatDividerModule } from '@angular/material/divider';
|
||||
import { MatExpansionModule } from '@angular/material/expansion';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatMenuModule } from '@angular/material/menu';
|
||||
import { BaseChartDirective } from 'ng2-charts';
|
||||
import { ChartistModule, Configuration } from 'ng-chartist';
|
||||
import { AxisOptions, Label } from 'chartist';
|
||||
import { Observable, Subscription } from 'rxjs';
|
||||
|
||||
import { MenuItems } from '@components/shared';
|
||||
import { HistoryTableComponent } from '@components/shared/helpers-jump';
|
||||
import { UtilitiesService, DropZonesService } from '@services';
|
||||
import { DropZoneByOaci, DropZoneByYear } from '@models';
|
||||
|
||||
@Component({
|
||||
selector: 'app-dropzones-bar',
|
||||
imports: [
|
||||
MatButtonModule,
|
||||
MatCardModule,
|
||||
MatDividerModule,
|
||||
MatExpansionModule,
|
||||
MatIconModule,
|
||||
MatMenuModule,
|
||||
BaseChartDirective,
|
||||
ChartistModule,
|
||||
HistoryTableComponent,
|
||||
],
|
||||
templateUrl: './dropzones-bar.component.html',
|
||||
})
|
||||
export class DropzonesBarComponent implements OnInit, OnDestroy {
|
||||
private _dropzoneByOaci: Subscription = new Subscription();
|
||||
private _dropzoneByYear: Subscription = new Subscription();
|
||||
private _dropzonesByOaci!: Array<DropZoneByOaci>;
|
||||
private _dropzonesByYear!: Array<DropZoneByYear>;
|
||||
public title: string = 'Les dropzones';
|
||||
public subtitle: string = 'Nombre total de sauts par dropzone';
|
||||
public seriesHeader: string[] = [];
|
||||
public seriesName: string[] = [];
|
||||
public seriesValue: number[] = [];
|
||||
public seriesRow: Array<Array<number>> = [];
|
||||
public seriesColor: {
|
||||
backgroundColor: string[];
|
||||
borderColor: string[];
|
||||
} = {
|
||||
backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'all'),
|
||||
borderColor: this._utilitiesService.getSeriesColors(1, 'all'),
|
||||
};
|
||||
public seriesColorClass: string[] = this._utilitiesService.getChartColors();
|
||||
public displayCharts = false;
|
||||
public barChartDropZones: Configuration = this._utilitiesService.getBarConfig();
|
||||
public destroyRef = inject(DestroyRef);
|
||||
|
||||
constructor(
|
||||
private _dropzonesService: DropZonesService,
|
||||
private _utilitiesService: UtilitiesService,
|
||||
public menuItems: MenuItems,
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this._loadDropZoneByOaci();
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this._dropzoneByOaci.unsubscribe();
|
||||
this._dropzoneByYear.unsubscribe();
|
||||
}
|
||||
|
||||
private _loadDropZoneByOaci(): void {
|
||||
const dropzones$: Observable<Array<DropZoneByOaci>> = this._dropzonesService
|
||||
.getAllByOaci()
|
||||
.pipe(takeUntilDestroyed(this.destroyRef));
|
||||
this._dropzoneByOaci = dropzones$.subscribe((aggregate: Array<DropZoneByOaci>) => {
|
||||
this._dropzonesByOaci = aggregate.map((row: DropZoneByOaci) => {
|
||||
this.seriesName.push(`${row.oaci} - ${row.lieu}`);
|
||||
this.seriesValue.push(row.count);
|
||||
return row;
|
||||
});
|
||||
this._loadDropZoneByYear();
|
||||
});
|
||||
}
|
||||
|
||||
private _loadDropZoneByYear(): void {
|
||||
this.seriesHeader = ['2018', '2019', '2020', '2021', '2022', '2023', '2024'];
|
||||
const values: Array<number> = this.seriesHeader.map(() => 0);
|
||||
this.seriesName.forEach(() => {
|
||||
this.seriesRow.push([...values]);
|
||||
});
|
||||
const dropzones$: Observable<Array<DropZoneByYear>> = this._dropzonesService
|
||||
.getAllByOaciByYear()
|
||||
.pipe(takeUntilDestroyed(this.destroyRef));
|
||||
this._dropzoneByYear = dropzones$.subscribe((aggregate: Array<DropZoneByYear>) => {
|
||||
this._dropzonesByYear = aggregate.map((row: DropZoneByYear) => {
|
||||
const lieu: string = row.lieu;
|
||||
const oaci: string = row.oaci;
|
||||
const year: string = row.year.toString();
|
||||
this.seriesRow[this.seriesName.indexOf(`${oaci} - ${lieu}`)][this.seriesHeader.indexOf(year)] =
|
||||
row.count;
|
||||
return row;
|
||||
});
|
||||
const axisX: AxisOptions = {
|
||||
labelInterpolationFnc: function (value: Label, index: number): string {
|
||||
return index % 1 === 0 ? `${value.toString()}` : '';
|
||||
},
|
||||
};
|
||||
this.barChartDropZones = {
|
||||
type: 'Bar',
|
||||
data: {
|
||||
labels: this.seriesHeader,
|
||||
series: this.seriesRow,
|
||||
},
|
||||
options: {
|
||||
seriesBarDistance: 15,
|
||||
horizontalBars: false,
|
||||
high: 180,
|
||||
axisX: {
|
||||
showGrid: false,
|
||||
offset: 20,
|
||||
},
|
||||
axisY: {
|
||||
showGrid: true,
|
||||
offset: 40,
|
||||
},
|
||||
height: 300,
|
||||
},
|
||||
responsiveOptions: [
|
||||
[
|
||||
'screen and (min-width: 1024px)',
|
||||
{
|
||||
axisX: axisX,
|
||||
},
|
||||
],
|
||||
[
|
||||
'screen and (min-width: 641px) and (max-width: 1024px)',
|
||||
{
|
||||
seriesBarDistance: 7,
|
||||
axisY: {
|
||||
offset: 30,
|
||||
},
|
||||
axisX: axisX,
|
||||
},
|
||||
],
|
||||
[
|
||||
'screen and (max-width: 640px)',
|
||||
{
|
||||
seriesBarDistance: 5,
|
||||
axisY: {
|
||||
offset: 20,
|
||||
},
|
||||
axisX: axisX,
|
||||
},
|
||||
],
|
||||
],
|
||||
};
|
||||
this.displayCharts = true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+102
-93
@@ -1,93 +1,102 @@
|
||||
import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core';
|
||||
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { MatDividerModule } from '@angular/material/divider';
|
||||
import { MatExpansionModule } from '@angular/material/expansion';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatMenuModule } from '@angular/material/menu';
|
||||
//import { ChartConfiguration } from 'chart.js';
|
||||
import { Observable, Subscription } from 'rxjs';
|
||||
|
||||
import { MenuItems } from '@components/shared';
|
||||
import { PieChartComponent } from '@components/shared/helpers-chart';
|
||||
import { HistoryTableComponent } from '@components/shared/helpers-jump';
|
||||
import { UtilitiesService, DropZonesService } from '@services';
|
||||
import { DropZoneByOaci, DropZoneByYear } from '@models';
|
||||
|
||||
@Component({
|
||||
selector: 'app-dropzones-pie',
|
||||
standalone: true,
|
||||
imports: [
|
||||
MatButtonModule, MatCardModule, MatDividerModule,
|
||||
MatExpansionModule, MatIconModule, MatMenuModule,
|
||||
PieChartComponent, HistoryTableComponent
|
||||
],
|
||||
templateUrl: './dropzones-pie.component.html'
|
||||
})
|
||||
export class DropzonesPieComponent implements OnInit, OnDestroy {
|
||||
private _dropzoneByOaci: Subscription = new Subscription();
|
||||
private _dropzoneByYear: Subscription = new Subscription();
|
||||
private _dropzonesByOaci!: Array<DropZoneByOaci>;
|
||||
private _dropzonesByYear!: Array<DropZoneByYear>;
|
||||
public title: string = 'Les dropzones';
|
||||
public subtitle: string = 'Nombre total de sauts par dropzone';
|
||||
public seriesHeader: string[] = [];
|
||||
public seriesName: string[] = [];
|
||||
public seriesValue: number[] = [];
|
||||
public seriesRow: Array<Array<number>> = [];
|
||||
public seriesColor: {
|
||||
backgroundColor: string[],
|
||||
borderColor: string[]
|
||||
} = {
|
||||
backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'all'),
|
||||
borderColor: this._utilitiesService.getSeriesColors(1, 'all')
|
||||
};
|
||||
public seriesColorClass: string[] = this._utilitiesService.getChartColors();
|
||||
public destroyRef = inject(DestroyRef);
|
||||
|
||||
constructor(
|
||||
private _dropzonesService: DropZonesService,
|
||||
private _utilitiesService: UtilitiesService,
|
||||
public menuItems: MenuItems
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
this._loadDropZoneByOaci();
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this._dropzoneByOaci.unsubscribe();
|
||||
this._dropzoneByYear.unsubscribe();
|
||||
}
|
||||
|
||||
private _loadDropZoneByOaci(): void {
|
||||
const dropzones$: Observable<Array<DropZoneByOaci>> = this._dropzonesService.getAllByOaci().pipe(takeUntilDestroyed(this.destroyRef));
|
||||
this._dropzoneByOaci = dropzones$.subscribe((aggregate: Array<DropZoneByOaci>) => {
|
||||
this._dropzonesByOaci = aggregate.map((row: DropZoneByOaci) => {
|
||||
this.seriesName.push(`${row.oaci} - ${row.lieu}`);
|
||||
this.seriesValue.push(row.count);
|
||||
return row;
|
||||
});
|
||||
this._loadDropZoneByYear();
|
||||
});
|
||||
}
|
||||
|
||||
private _loadDropZoneByYear(): void {
|
||||
this.seriesHeader = ['2018', '2019', '2020', '2021', '2022', '2023', '2024'];
|
||||
const values: Array<number> = this.seriesHeader.map(() => 0);
|
||||
this.seriesName.forEach(() => {
|
||||
this.seriesRow.push([...values]);
|
||||
});
|
||||
const dropzones$: Observable<Array<DropZoneByYear>> = this._dropzonesService.getAllByOaciByYear().pipe(takeUntilDestroyed(this.destroyRef));
|
||||
this._dropzoneByYear = dropzones$.subscribe((aggregate: Array<DropZoneByYear>) => {
|
||||
this._dropzonesByYear = aggregate.map((row: DropZoneByYear) => {
|
||||
const lieu: string = row.lieu;
|
||||
const oaci: string = row.oaci;
|
||||
const year: string = row.year.toString();
|
||||
this.seriesRow[this.seriesName.indexOf(`${oaci} - ${lieu}`)][this.seriesHeader.indexOf(year)] = row.count;
|
||||
return row;
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core';
|
||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { MatDividerModule } from '@angular/material/divider';
|
||||
import { MatExpansionModule } from '@angular/material/expansion';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatMenuModule } from '@angular/material/menu';
|
||||
//import { ChartConfiguration } from 'chart.js';
|
||||
import { Observable, Subscription } from 'rxjs';
|
||||
|
||||
import { MenuItems } from '@components/shared';
|
||||
import { PieChartComponent } from '@components/shared/helpers-chart';
|
||||
import { HistoryTableComponent } from '@components/shared/helpers-jump';
|
||||
import { UtilitiesService, DropZonesService } from '@services';
|
||||
import { DropZoneByOaci, DropZoneByYear } from '@models';
|
||||
|
||||
@Component({
|
||||
selector: 'app-dropzones-pie',
|
||||
imports: [
|
||||
MatButtonModule,
|
||||
MatCardModule,
|
||||
MatDividerModule,
|
||||
MatExpansionModule,
|
||||
MatIconModule,
|
||||
MatMenuModule,
|
||||
PieChartComponent,
|
||||
HistoryTableComponent,
|
||||
],
|
||||
templateUrl: './dropzones-pie.component.html',
|
||||
})
|
||||
export class DropzonesPieComponent implements OnInit, OnDestroy {
|
||||
private _dropzoneByOaci: Subscription = new Subscription();
|
||||
private _dropzoneByYear: Subscription = new Subscription();
|
||||
private _dropzonesByOaci!: Array<DropZoneByOaci>;
|
||||
private _dropzonesByYear!: Array<DropZoneByYear>;
|
||||
public title: string = 'Les dropzones';
|
||||
public subtitle: string = 'Nombre total de sauts par dropzone';
|
||||
public seriesHeader: string[] = [];
|
||||
public seriesName: string[] = [];
|
||||
public seriesValue: number[] = [];
|
||||
public seriesRow: Array<Array<number>> = [];
|
||||
public seriesColor: {
|
||||
backgroundColor: string[];
|
||||
borderColor: string[];
|
||||
} = {
|
||||
backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'all'),
|
||||
borderColor: this._utilitiesService.getSeriesColors(1, 'all'),
|
||||
};
|
||||
public seriesColorClass: string[] = this._utilitiesService.getChartColors();
|
||||
public destroyRef = inject(DestroyRef);
|
||||
|
||||
constructor(
|
||||
private _dropzonesService: DropZonesService,
|
||||
private _utilitiesService: UtilitiesService,
|
||||
public menuItems: MenuItems,
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this._loadDropZoneByOaci();
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this._dropzoneByOaci.unsubscribe();
|
||||
this._dropzoneByYear.unsubscribe();
|
||||
}
|
||||
|
||||
private _loadDropZoneByOaci(): void {
|
||||
const dropzones$: Observable<Array<DropZoneByOaci>> = this._dropzonesService
|
||||
.getAllByOaci()
|
||||
.pipe(takeUntilDestroyed(this.destroyRef));
|
||||
this._dropzoneByOaci = dropzones$.subscribe((aggregate: Array<DropZoneByOaci>) => {
|
||||
this._dropzonesByOaci = aggregate.map((row: DropZoneByOaci) => {
|
||||
this.seriesName.push(`${row.oaci} - ${row.lieu}`);
|
||||
this.seriesValue.push(row.count);
|
||||
return row;
|
||||
});
|
||||
this._loadDropZoneByYear();
|
||||
});
|
||||
}
|
||||
|
||||
private _loadDropZoneByYear(): void {
|
||||
this.seriesHeader = ['2018', '2019', '2020', '2021', '2022', '2023', '2024'];
|
||||
const values: Array<number> = this.seriesHeader.map(() => 0);
|
||||
this.seriesName.forEach(() => {
|
||||
this.seriesRow.push([...values]);
|
||||
});
|
||||
const dropzones$: Observable<Array<DropZoneByYear>> = this._dropzonesService
|
||||
.getAllByOaciByYear()
|
||||
.pipe(takeUntilDestroyed(this.destroyRef));
|
||||
this._dropzoneByYear = dropzones$.subscribe((aggregate: Array<DropZoneByYear>) => {
|
||||
this._dropzonesByYear = aggregate.map((row: DropZoneByYear) => {
|
||||
const lieu: string = row.lieu;
|
||||
const oaci: string = row.oaci;
|
||||
const year: string = row.year.toString();
|
||||
this.seriesRow[this.seriesName.indexOf(`${oaci} - ${lieu}`)][this.seriesHeader.indexOf(year)] =
|
||||
row.count;
|
||||
return row;
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+189
-172
@@ -1,172 +1,189 @@
|
||||
import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core';
|
||||
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { MatDividerModule } from '@angular/material/divider';
|
||||
import { MatExpansionModule } from '@angular/material/expansion';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatMenuModule } from '@angular/material/menu';
|
||||
import { ChartistModule, Configuration } from 'ng-chartist';
|
||||
import { AxisOptions, Label } from 'chartist';
|
||||
|
||||
import { Observable, Subscription } from 'rxjs';
|
||||
|
||||
import { MenuItems } from '@components/shared';
|
||||
import { UtilitiesService, JumpsService } from '@services';
|
||||
import { JumpByDate } from '@models';
|
||||
|
||||
@Component({
|
||||
selector: 'app-jumps-by-month',
|
||||
standalone: true,
|
||||
imports: [
|
||||
CommonModule,
|
||||
MatButtonModule, MatCardModule, MatDividerModule,
|
||||
MatExpansionModule, MatIconModule, MatMenuModule,
|
||||
ChartistModule
|
||||
],
|
||||
templateUrl: './jumps-by-month.component.html'
|
||||
})
|
||||
export class JumpsByMonthComponent implements OnInit, OnDestroy {
|
||||
private _jumpByDate: Subscription = new Subscription();
|
||||
private _jumpsByDate!: Array<JumpByDate>;
|
||||
private _jumpsByDateCount = 0;
|
||||
public title: string = 'Volume mensuel';
|
||||
public subtitle: string = 'Nombre total de sauts par mois';
|
||||
public min = 0;
|
||||
public max = 0;
|
||||
public grandAvg = 0;
|
||||
public grandAvgLastYears = 0;
|
||||
public grandTotal = 0;
|
||||
public seriesHeader: string[] = [];
|
||||
public seriesName: string[] = [];
|
||||
public seriesRow: Array<Array<number>> = [];
|
||||
public seriesColor: {
|
||||
backgroundColor: string[],
|
||||
borderColor: string[]
|
||||
} = {
|
||||
backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'all'),
|
||||
borderColor: this._utilitiesService.getSeriesColors(1, 'all')
|
||||
};
|
||||
public seriesColorClass: string[] = this._utilitiesService.getChartColors();
|
||||
public seriesRowTotal: number[] = [];
|
||||
public seriesRowAvg: number[] = [];
|
||||
public seriesRowAvgLastYears: number[] = [];
|
||||
public seriesColTotal: number[] = [];
|
||||
public seriesColTotalClosed: number[] = [];
|
||||
public seriesColTotalLastYears: number[] = [];
|
||||
public displayCharts = false;
|
||||
public barChartJumps: Configuration = this._utilitiesService.getBarConfig();
|
||||
public destroyRef = inject(DestroyRef);
|
||||
|
||||
constructor(
|
||||
private _jumpsService: JumpsService,
|
||||
private _utilitiesService: UtilitiesService,
|
||||
public menuItems: MenuItems
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
this._loadJumpByDate();
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this._jumpByDate.unsubscribe();
|
||||
}
|
||||
|
||||
private _loadJumpByDate() {
|
||||
const minoration = 2; // -2 pour ne pas compter la première année
|
||||
this.seriesHeader = this._utilitiesService.getMonthsList();
|
||||
const values: Array<number> = this.seriesHeader.map(() => 0);
|
||||
this.seriesColTotal = [...values];
|
||||
this.seriesColTotalClosed = [...values];
|
||||
this.seriesColTotalLastYears = [...values];
|
||||
const jumps$: Observable<Array<JumpByDate>> = this._jumpsService.getAllByDate().pipe(takeUntilDestroyed(this.destroyRef));
|
||||
this._jumpByDate = jumps$.subscribe((aggregate: Array<JumpByDate>) => {
|
||||
this._jumpsByDateCount = aggregate.length;
|
||||
this._jumpsByDate = aggregate.map((row: JumpByDate) => {
|
||||
const currentYear: number = new Date().getFullYear();
|
||||
const year = row.year.toString();
|
||||
const month = row.month;
|
||||
if (this.seriesName.indexOf(year) < 0) {
|
||||
this.seriesName.push(year);
|
||||
if (row.year < this.min || this.min == 0) {
|
||||
this.min = row.year;
|
||||
}
|
||||
if (row.year > this.max) {
|
||||
this.max = row.year;
|
||||
}
|
||||
this.seriesRow.push([...values]);
|
||||
}
|
||||
this.seriesRow[(this.seriesRow.length-1)][(month-1)] = row.count;
|
||||
this.seriesColTotal[(month-1)] += row.count;
|
||||
if (row.year < currentYear) {
|
||||
this.seriesColTotalClosed[(month-1)] += row.count;
|
||||
}
|
||||
if (row.year >= (currentYear-3) && row.year < currentYear) {
|
||||
this.seriesColTotalLastYears[(month-1)] += row.count;
|
||||
}
|
||||
return row;
|
||||
});
|
||||
this.seriesRow.forEach((row: number[]) => {
|
||||
const total = row.reduce((partialSum, a) => partialSum + a, 0);
|
||||
this.seriesRowTotal.push(total);
|
||||
});
|
||||
this.seriesColTotalClosed.forEach((row: number) => {
|
||||
const value: number = (row/(this.seriesName.length-minoration));
|
||||
this.seriesRowAvg.push(parseInt(value.toFixed(0)));
|
||||
});
|
||||
this.seriesColTotalLastYears.forEach((row: number) => {
|
||||
const value: number = (row/3); // Les 3 dernières années
|
||||
this.seriesRowAvgLastYears.push(parseInt(value.toFixed(0)));
|
||||
});
|
||||
this.grandAvg = this.seriesRowAvg.reduce((partialSum, accumulated) => partialSum + accumulated, 0);
|
||||
this.grandAvgLastYears = this.seriesRowAvgLastYears.reduce((partialSum, accumulated) => partialSum + accumulated, 0);
|
||||
this.grandTotal = this.seriesColTotal.reduce((partialSum, accumulated) => partialSum + accumulated, 0);
|
||||
const axisX: AxisOptions = {
|
||||
labelInterpolationFnc: function(value: Label, index: number): string {
|
||||
return index % 1 === 0 ? `${value.toString()}` : '';
|
||||
}
|
||||
}
|
||||
this.barChartJumps = {
|
||||
type: 'Bar',
|
||||
data: {
|
||||
'labels': this.seriesHeader,
|
||||
'series': this.seriesRow
|
||||
},
|
||||
options: {
|
||||
seriesBarDistance: 15,
|
||||
high: 70,
|
||||
axisX: {
|
||||
showGrid: false,
|
||||
offset: 20
|
||||
},
|
||||
axisY: {
|
||||
showGrid: true,
|
||||
offset: 40
|
||||
},
|
||||
height: 300
|
||||
},
|
||||
responsiveOptions: [
|
||||
['screen and (min-width: 1024px)', {
|
||||
axisX: axisX
|
||||
}],
|
||||
['screen and (min-width: 641px) and (max-width: 1024px)', {
|
||||
seriesBarDistance: 10,
|
||||
axisY: {
|
||||
offset: 30
|
||||
},
|
||||
axisX: axisX
|
||||
}],
|
||||
['screen and (max-width: 640px)', {
|
||||
seriesBarDistance: 5,
|
||||
axisY: {
|
||||
offset: 20
|
||||
},
|
||||
axisX: axisX
|
||||
}]
|
||||
]
|
||||
};
|
||||
this.displayCharts = true;
|
||||
});
|
||||
}
|
||||
}
|
||||
import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core';
|
||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { MatDividerModule } from '@angular/material/divider';
|
||||
import { MatExpansionModule } from '@angular/material/expansion';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatMenuModule } from '@angular/material/menu';
|
||||
import { ChartistModule, Configuration } from 'ng-chartist';
|
||||
import { AxisOptions, Label } from 'chartist';
|
||||
|
||||
import { Observable, Subscription } from 'rxjs';
|
||||
|
||||
import { MenuItems } from '@components/shared';
|
||||
import { UtilitiesService, JumpsService } from '@services';
|
||||
import { JumpByDate } from '@models';
|
||||
|
||||
@Component({
|
||||
selector: 'app-jumps-by-month',
|
||||
imports: [
|
||||
CommonModule,
|
||||
MatButtonModule,
|
||||
MatCardModule,
|
||||
MatDividerModule,
|
||||
MatExpansionModule,
|
||||
MatIconModule,
|
||||
MatMenuModule,
|
||||
ChartistModule,
|
||||
],
|
||||
templateUrl: './jumps-by-month.component.html',
|
||||
})
|
||||
export class JumpsByMonthComponent implements OnInit, OnDestroy {
|
||||
private _jumpByDate: Subscription = new Subscription();
|
||||
private _jumpsByDate!: Array<JumpByDate>;
|
||||
private _jumpsByDateCount = 0;
|
||||
public title: string = 'Volume mensuel';
|
||||
public subtitle: string = 'Nombre total de sauts par mois';
|
||||
public min = 0;
|
||||
public max = 0;
|
||||
public grandAvg = 0;
|
||||
public grandAvgLastYears = 0;
|
||||
public grandTotal = 0;
|
||||
public seriesHeader: string[] = [];
|
||||
public seriesName: string[] = [];
|
||||
public seriesRow: Array<Array<number>> = [];
|
||||
public seriesColor: {
|
||||
backgroundColor: string[];
|
||||
borderColor: string[];
|
||||
} = {
|
||||
backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'all'),
|
||||
borderColor: this._utilitiesService.getSeriesColors(1, 'all'),
|
||||
};
|
||||
public seriesColorClass: string[] = this._utilitiesService.getChartColors();
|
||||
public seriesRowTotal: number[] = [];
|
||||
public seriesRowAvg: number[] = [];
|
||||
public seriesRowAvgLastYears: number[] = [];
|
||||
public seriesColTotal: number[] = [];
|
||||
public seriesColTotalClosed: number[] = [];
|
||||
public seriesColTotalLastYears: number[] = [];
|
||||
public displayCharts = false;
|
||||
public barChartJumps: Configuration = this._utilitiesService.getBarConfig();
|
||||
public destroyRef = inject(DestroyRef);
|
||||
|
||||
constructor(
|
||||
private _jumpsService: JumpsService,
|
||||
private _utilitiesService: UtilitiesService,
|
||||
public menuItems: MenuItems,
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this._loadJumpByDate();
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this._jumpByDate.unsubscribe();
|
||||
}
|
||||
|
||||
private _loadJumpByDate() {
|
||||
const minoration = 2; // -2 pour ne pas compter la première année
|
||||
this.seriesHeader = this._utilitiesService.getMonthsList();
|
||||
const values: Array<number> = this.seriesHeader.map(() => 0);
|
||||
this.seriesColTotal = [...values];
|
||||
this.seriesColTotalClosed = [...values];
|
||||
this.seriesColTotalLastYears = [...values];
|
||||
const jumps$: Observable<Array<JumpByDate>> = this._jumpsService
|
||||
.getAllByDate()
|
||||
.pipe(takeUntilDestroyed(this.destroyRef));
|
||||
this._jumpByDate = jumps$.subscribe((aggregate: Array<JumpByDate>) => {
|
||||
this._jumpsByDateCount = aggregate.length;
|
||||
this._jumpsByDate = aggregate.map((row: JumpByDate) => {
|
||||
const currentYear: number = new Date().getFullYear();
|
||||
const year = row.year.toString();
|
||||
const month = row.month;
|
||||
if (this.seriesName.indexOf(year) < 0) {
|
||||
this.seriesName.push(year);
|
||||
if (row.year < this.min || this.min == 0) {
|
||||
this.min = row.year;
|
||||
}
|
||||
if (row.year > this.max) {
|
||||
this.max = row.year;
|
||||
}
|
||||
this.seriesRow.push([...values]);
|
||||
}
|
||||
this.seriesRow[this.seriesRow.length - 1][month - 1] = row.count;
|
||||
this.seriesColTotal[month - 1] += row.count;
|
||||
if (row.year < currentYear) {
|
||||
this.seriesColTotalClosed[month - 1] += row.count;
|
||||
}
|
||||
if (row.year >= currentYear - 3 && row.year < currentYear) {
|
||||
this.seriesColTotalLastYears[month - 1] += row.count;
|
||||
}
|
||||
return row;
|
||||
});
|
||||
this.seriesRow.forEach((row: number[]) => {
|
||||
const total = row.reduce((partialSum, a) => partialSum + a, 0);
|
||||
this.seriesRowTotal.push(total);
|
||||
});
|
||||
this.seriesColTotalClosed.forEach((row: number) => {
|
||||
const value: number = row / (this.seriesName.length - minoration);
|
||||
this.seriesRowAvg.push(parseInt(value.toFixed(0)));
|
||||
});
|
||||
this.seriesColTotalLastYears.forEach((row: number) => {
|
||||
const value: number = row / 3; // Les 3 dernières années
|
||||
this.seriesRowAvgLastYears.push(parseInt(value.toFixed(0)));
|
||||
});
|
||||
this.grandAvg = this.seriesRowAvg.reduce((partialSum, accumulated) => partialSum + accumulated, 0);
|
||||
this.grandAvgLastYears = this.seriesRowAvgLastYears.reduce(
|
||||
(partialSum, accumulated) => partialSum + accumulated,
|
||||
0,
|
||||
);
|
||||
this.grandTotal = this.seriesColTotal.reduce((partialSum, accumulated) => partialSum + accumulated, 0);
|
||||
const axisX: AxisOptions = {
|
||||
labelInterpolationFnc: function (value: Label, index: number): string {
|
||||
return index % 1 === 0 ? `${value.toString()}` : '';
|
||||
},
|
||||
};
|
||||
this.barChartJumps = {
|
||||
type: 'Bar',
|
||||
data: {
|
||||
labels: this.seriesHeader,
|
||||
series: this.seriesRow,
|
||||
},
|
||||
options: {
|
||||
seriesBarDistance: 15,
|
||||
high: 70,
|
||||
axisX: {
|
||||
showGrid: false,
|
||||
offset: 20,
|
||||
},
|
||||
axisY: {
|
||||
showGrid: true,
|
||||
offset: 40,
|
||||
},
|
||||
height: 300,
|
||||
},
|
||||
responsiveOptions: [
|
||||
[
|
||||
'screen and (min-width: 1024px)',
|
||||
{
|
||||
axisX: axisX,
|
||||
},
|
||||
],
|
||||
[
|
||||
'screen and (min-width: 641px) and (max-width: 1024px)',
|
||||
{
|
||||
seriesBarDistance: 10,
|
||||
axisY: {
|
||||
offset: 30,
|
||||
},
|
||||
axisX: axisX,
|
||||
},
|
||||
],
|
||||
[
|
||||
'screen and (max-width: 640px)',
|
||||
{
|
||||
seriesBarDistance: 5,
|
||||
axisY: {
|
||||
offset: 20,
|
||||
},
|
||||
axisX: axisX,
|
||||
},
|
||||
],
|
||||
],
|
||||
};
|
||||
this.displayCharts = true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,58 +1,53 @@
|
||||
import { Component, Input, OnChanges } from '@angular/core';
|
||||
import { ChartDataset } from 'chart.js';
|
||||
import { BaseChartDirective } from 'ng2-charts';
|
||||
|
||||
import { UtilitiesService } from '@services';
|
||||
import { BarConfig } from '@models';
|
||||
|
||||
@Component({
|
||||
selector: 'app-bar-chart',
|
||||
standalone: true,
|
||||
imports: [
|
||||
BaseChartDirective
|
||||
],
|
||||
templateUrl: './bar-chart.component.html'
|
||||
})
|
||||
export class BarChartComponent implements OnChanges {
|
||||
public displayCharts = false;
|
||||
public chartConfig: BarConfig = this._utilitiesService.getBarChartConfig();
|
||||
|
||||
constructor(
|
||||
private _utilitiesService: UtilitiesService
|
||||
) { }
|
||||
|
||||
@Input() names: string[] = [];
|
||||
@Input() values: number[] = [];
|
||||
@Input() headers: string[] = [];
|
||||
@Input() colors: {
|
||||
backgroundColor: string[],
|
||||
borderColor: string[]
|
||||
} = {
|
||||
backgroundColor: this._utilitiesService.getSeriesColors(0.8),
|
||||
borderColor: this._utilitiesService.getSeriesColors(1)
|
||||
};
|
||||
@Input() label: string = 'Nombre total de sauts';
|
||||
@Input() legend: boolean = false;
|
||||
|
||||
ngOnChanges() {
|
||||
this._loadBarChart();
|
||||
}
|
||||
|
||||
private _loadBarChart(): void {
|
||||
const dataset: ChartDataset<'bar'> = {
|
||||
data: [...this.values],
|
||||
label: this.label,
|
||||
backgroundColor: this.colors.backgroundColor,
|
||||
borderColor: this.colors.borderColor,
|
||||
borderWidth: 1
|
||||
};
|
||||
this.chartConfig.barChartData.labels = [...this.names];
|
||||
this.chartConfig.barChartData.datasets!.push(dataset);
|
||||
/*this.chartConfig.barChartOptions!.scales = {
|
||||
x: {display: false},
|
||||
y: {display: true}
|
||||
};*/
|
||||
this.chartConfig.barChartLegend = this.legend;
|
||||
this.displayCharts = true;
|
||||
}
|
||||
}
|
||||
import { Component, Input, OnChanges } from '@angular/core';
|
||||
import { ChartDataset } from 'chart.js';
|
||||
import { BaseChartDirective } from 'ng2-charts';
|
||||
|
||||
import { UtilitiesService } from '@services';
|
||||
import { BarConfig } from '@models';
|
||||
|
||||
@Component({
|
||||
selector: 'app-bar-chart',
|
||||
imports: [BaseChartDirective],
|
||||
templateUrl: './bar-chart.component.html',
|
||||
})
|
||||
export class BarChartComponent implements OnChanges {
|
||||
public displayCharts = false;
|
||||
public chartConfig: BarConfig = this._utilitiesService.getBarChartConfig();
|
||||
|
||||
constructor(private _utilitiesService: UtilitiesService) {}
|
||||
|
||||
@Input() names: string[] = [];
|
||||
@Input() values: number[] = [];
|
||||
@Input() headers: string[] = [];
|
||||
@Input() colors: {
|
||||
backgroundColor: string[];
|
||||
borderColor: string[];
|
||||
} = {
|
||||
backgroundColor: this._utilitiesService.getSeriesColors(0.8),
|
||||
borderColor: this._utilitiesService.getSeriesColors(1),
|
||||
};
|
||||
@Input() label: string = 'Nombre total de sauts';
|
||||
@Input() legend: boolean = false;
|
||||
|
||||
ngOnChanges() {
|
||||
this._loadBarChart();
|
||||
}
|
||||
|
||||
private _loadBarChart(): void {
|
||||
const dataset: ChartDataset<'bar'> = {
|
||||
data: [...this.values],
|
||||
label: this.label,
|
||||
backgroundColor: this.colors.backgroundColor,
|
||||
borderColor: this.colors.borderColor,
|
||||
borderWidth: 1,
|
||||
};
|
||||
this.chartConfig.barChartData.labels = [...this.names];
|
||||
this.chartConfig.barChartData.datasets!.push(dataset);
|
||||
/*this.chartConfig.barChartOptions!.scales = {
|
||||
x: {display: false},
|
||||
y: {display: true}
|
||||
};*/
|
||||
this.chartConfig.barChartLegend = this.legend;
|
||||
this.displayCharts = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,54 +1,49 @@
|
||||
import { Component, Input, OnChanges } from '@angular/core';
|
||||
import { ChartDataset } from 'chart.js';
|
||||
import { BaseChartDirective } from 'ng2-charts';
|
||||
|
||||
import { UtilitiesService } from '@services';
|
||||
import { BarConfig } from '@models';
|
||||
|
||||
@Component({
|
||||
selector: 'app-bar-horizontal-chart',
|
||||
standalone: true,
|
||||
imports: [
|
||||
BaseChartDirective
|
||||
],
|
||||
templateUrl: './bar-horizontal-chart.component.html'
|
||||
})
|
||||
export class BarHorizontalChartComponent implements OnChanges {
|
||||
public displayCharts = false;
|
||||
public chartConfig: BarConfig = this._utilitiesService.getHorizontalBarChartConfig();
|
||||
|
||||
constructor(
|
||||
private _utilitiesService: UtilitiesService
|
||||
) { }
|
||||
|
||||
@Input() names: string[] = [];
|
||||
@Input() values: number[] = [];
|
||||
@Input() headers: string[] = [];
|
||||
@Input() colors: {
|
||||
backgroundColor: string[],
|
||||
borderColor: string[]
|
||||
} = {
|
||||
backgroundColor: this._utilitiesService.getSeriesColors(0.8),
|
||||
borderColor: this._utilitiesService.getSeriesColors(1)
|
||||
};
|
||||
@Input() label: string = 'Nombre total de sauts';
|
||||
@Input() legend: boolean = false;
|
||||
|
||||
ngOnChanges() {
|
||||
this._loadBarChart();
|
||||
}
|
||||
|
||||
private _loadBarChart(): void {
|
||||
const dataset: ChartDataset<'bar'> = {
|
||||
data: [...this.values],
|
||||
label: this.label,
|
||||
backgroundColor: this.colors.backgroundColor,
|
||||
borderColor: this.colors.borderColor,
|
||||
borderWidth: 1
|
||||
};
|
||||
this.chartConfig.barChartData.labels = [...this.names];
|
||||
this.chartConfig.barChartData.datasets!.push(dataset);
|
||||
this.chartConfig.barChartLegend = this.legend;
|
||||
this.displayCharts = true;
|
||||
}
|
||||
}
|
||||
import { Component, Input, OnChanges } from '@angular/core';
|
||||
import { ChartDataset } from 'chart.js';
|
||||
import { BaseChartDirective } from 'ng2-charts';
|
||||
|
||||
import { UtilitiesService } from '@services';
|
||||
import { BarConfig } from '@models';
|
||||
|
||||
@Component({
|
||||
selector: 'app-bar-horizontal-chart',
|
||||
imports: [BaseChartDirective],
|
||||
templateUrl: './bar-horizontal-chart.component.html',
|
||||
})
|
||||
export class BarHorizontalChartComponent implements OnChanges {
|
||||
public displayCharts = false;
|
||||
public chartConfig: BarConfig = this._utilitiesService.getHorizontalBarChartConfig();
|
||||
|
||||
constructor(private _utilitiesService: UtilitiesService) {}
|
||||
|
||||
@Input() names: string[] = [];
|
||||
@Input() values: number[] = [];
|
||||
@Input() headers: string[] = [];
|
||||
@Input() colors: {
|
||||
backgroundColor: string[];
|
||||
borderColor: string[];
|
||||
} = {
|
||||
backgroundColor: this._utilitiesService.getSeriesColors(0.8),
|
||||
borderColor: this._utilitiesService.getSeriesColors(1),
|
||||
};
|
||||
@Input() label: string = 'Nombre total de sauts';
|
||||
@Input() legend: boolean = false;
|
||||
|
||||
ngOnChanges() {
|
||||
this._loadBarChart();
|
||||
}
|
||||
|
||||
private _loadBarChart(): void {
|
||||
const dataset: ChartDataset<'bar'> = {
|
||||
data: [...this.values],
|
||||
label: this.label,
|
||||
backgroundColor: this.colors.backgroundColor,
|
||||
borderColor: this.colors.borderColor,
|
||||
borderWidth: 1,
|
||||
};
|
||||
this.chartConfig.barChartData.labels = [...this.names];
|
||||
this.chartConfig.barChartData.datasets!.push(dataset);
|
||||
this.chartConfig.barChartLegend = this.legend;
|
||||
this.displayCharts = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,79 +1,84 @@
|
||||
import { Component, Input, OnChanges, AfterContentChecked } from '@angular/core';
|
||||
import { ChartDataset } from 'chart.js';
|
||||
import { BaseChartDirective } from 'ng2-charts';
|
||||
|
||||
import { UtilitiesService } from '@services';
|
||||
import { BarConfig } from '@models';
|
||||
|
||||
@Component({
|
||||
selector: 'app-bars-chart',
|
||||
standalone: true,
|
||||
imports: [
|
||||
BaseChartDirective
|
||||
],
|
||||
templateUrl: './bars-chart.component.html'
|
||||
})
|
||||
export class BarsChartComponent implements OnChanges, AfterContentChecked {
|
||||
public displayCharts = false;
|
||||
public chartConfig: BarConfig = this._utilitiesService.getBarChartConfig();
|
||||
|
||||
constructor(
|
||||
private _utilitiesService: UtilitiesService
|
||||
) { }
|
||||
|
||||
@Input() names: string[] = [];
|
||||
@Input() values: Array<Array<number>> = [];
|
||||
@Input() headers: string[] = [];
|
||||
@Input() colors: {
|
||||
backgroundColor: string[],
|
||||
borderColor: string[]
|
||||
} = {
|
||||
backgroundColor: this._utilitiesService.getSeriesColors(0.8),
|
||||
borderColor: this._utilitiesService.getSeriesColors(1)
|
||||
};
|
||||
@Input() legend: boolean = false;
|
||||
|
||||
ngOnChanges() {
|
||||
this._loadBarChart();
|
||||
}
|
||||
|
||||
ngAfterContentChecked() {
|
||||
this._loadBarChart();
|
||||
}
|
||||
|
||||
private _loadBarChart(): void {
|
||||
this.chartConfig = this._utilitiesService.getBarChartConfig();
|
||||
this.chartConfig.barChartData.labels = [...this.headers];
|
||||
this.chartConfig.barChartOptions!.maintainAspectRatio = false;
|
||||
//this.chartConfig.barChartOptions!.aspectRatio = 2.4;
|
||||
this.chartConfig.barChartOptions!.scales = {
|
||||
x: {
|
||||
display: true,
|
||||
//stacked: true,
|
||||
beginAtZero: true,
|
||||
ticks: { color: 'rgba(255,255,255,0.3)' },
|
||||
grid: { color: 'rgba(255,255,255,0.1)', display: true, tickBorderDash: [1,2], tickBorderDashOffset: 2 }
|
||||
},
|
||||
y: {
|
||||
display: true,
|
||||
//stacked: true,
|
||||
beginAtZero: true,
|
||||
ticks: { color: 'rgba(255,255,255,0.3)' },
|
||||
grid: { color: 'rgba(255,255,255,0.2)', tickBorderDash: [1,2], tickBorderDashOffset: 2, display: true }
|
||||
}
|
||||
};
|
||||
this.names.forEach((label: string, index: number) => {
|
||||
const dataset: ChartDataset<'bar'> = {
|
||||
data: [...this.values[index]],
|
||||
label: label,
|
||||
backgroundColor: this.colors.backgroundColor[index],
|
||||
borderColor: this.colors.borderColor[index],
|
||||
borderWidth: 1,
|
||||
//stack: 'Stack 0'
|
||||
};
|
||||
this.chartConfig.barChartData.datasets!.push(dataset);
|
||||
});
|
||||
this.chartConfig.barChartLegend = this.legend;
|
||||
this.displayCharts = true;
|
||||
}
|
||||
}
|
||||
import { Component, Input, OnChanges, AfterContentChecked } from '@angular/core';
|
||||
import { ChartDataset } from 'chart.js';
|
||||
import { BaseChartDirective } from 'ng2-charts';
|
||||
|
||||
import { UtilitiesService } from '@services';
|
||||
import { BarConfig } from '@models';
|
||||
|
||||
@Component({
|
||||
selector: 'app-bars-chart',
|
||||
imports: [BaseChartDirective],
|
||||
templateUrl: './bars-chart.component.html',
|
||||
})
|
||||
export class BarsChartComponent implements OnChanges, AfterContentChecked {
|
||||
public displayCharts = false;
|
||||
public chartConfig: BarConfig = this._utilitiesService.getBarChartConfig();
|
||||
|
||||
constructor(private _utilitiesService: UtilitiesService) {}
|
||||
|
||||
@Input() names: string[] = [];
|
||||
@Input() values: Array<Array<number>> = [];
|
||||
@Input() headers: string[] = [];
|
||||
@Input() colors: {
|
||||
backgroundColor: string[];
|
||||
borderColor: string[];
|
||||
} = {
|
||||
backgroundColor: this._utilitiesService.getSeriesColors(0.8),
|
||||
borderColor: this._utilitiesService.getSeriesColors(1),
|
||||
};
|
||||
@Input() legend: boolean = false;
|
||||
|
||||
ngOnChanges() {
|
||||
this._loadBarChart();
|
||||
}
|
||||
|
||||
ngAfterContentChecked() {
|
||||
this._loadBarChart();
|
||||
}
|
||||
|
||||
private _loadBarChart(): void {
|
||||
this.chartConfig = this._utilitiesService.getBarChartConfig();
|
||||
this.chartConfig.barChartData.labels = [...this.headers];
|
||||
this.chartConfig.barChartOptions!.maintainAspectRatio = false;
|
||||
//this.chartConfig.barChartOptions!.aspectRatio = 2.4;
|
||||
this.chartConfig.barChartOptions!.scales = {
|
||||
x: {
|
||||
display: true,
|
||||
//stacked: true,
|
||||
beginAtZero: true,
|
||||
ticks: { color: 'rgba(255,255,255,0.3)' },
|
||||
grid: {
|
||||
color: 'rgba(255,255,255,0.1)',
|
||||
display: true,
|
||||
tickBorderDash: [1, 2],
|
||||
tickBorderDashOffset: 2,
|
||||
},
|
||||
},
|
||||
y: {
|
||||
display: true,
|
||||
//stacked: true,
|
||||
beginAtZero: true,
|
||||
ticks: { color: 'rgba(255,255,255,0.3)' },
|
||||
grid: {
|
||||
color: 'rgba(255,255,255,0.2)',
|
||||
tickBorderDash: [1, 2],
|
||||
tickBorderDashOffset: 2,
|
||||
display: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
this.names.forEach((label: string, index: number) => {
|
||||
const dataset: ChartDataset<'bar'> = {
|
||||
data: [...this.values[index]],
|
||||
label: label,
|
||||
backgroundColor: this.colors.backgroundColor[index],
|
||||
borderColor: this.colors.borderColor[index],
|
||||
borderWidth: 1,
|
||||
//stack: 'Stack 0'
|
||||
};
|
||||
this.chartConfig.barChartData.datasets!.push(dataset);
|
||||
});
|
||||
this.chartConfig.barChartLegend = this.legend;
|
||||
this.displayCharts = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,64 +1,59 @@
|
||||
import { Component, Input, OnChanges } from '@angular/core';
|
||||
//import { ChartDataset } from 'chart.js';
|
||||
import { BaseChartDirective } from 'ng2-charts';
|
||||
|
||||
import { UtilitiesService } from '@services';
|
||||
import { CircleConfig } from '@models';
|
||||
|
||||
@Component({
|
||||
selector: 'app-circle-chart',
|
||||
standalone: true,
|
||||
imports: [
|
||||
BaseChartDirective
|
||||
],
|
||||
templateUrl: './circle-chart.component.html'
|
||||
})
|
||||
export class CircleChartComponent implements OnChanges {
|
||||
public displayCharts = false;
|
||||
public chartConfig: CircleConfig = this._utilitiesService.getCircleChartConfig();
|
||||
|
||||
constructor(
|
||||
private _utilitiesService: UtilitiesService
|
||||
) { }
|
||||
|
||||
@Input() names: string[] = [];
|
||||
@Input() values: number[] = [];
|
||||
@Input() headers: string[] = [];
|
||||
@Input() color: number = 0;
|
||||
@Input() label: string = 'Nombre total de sauts';
|
||||
@Input() legend: boolean = false;
|
||||
|
||||
ngOnChanges() {
|
||||
this._loadCircleChart();
|
||||
}
|
||||
|
||||
private _loadCircleChart(): void {
|
||||
this.chartConfig.circleChartLabels = [...this.names];
|
||||
this.chartConfig.circleChartDatasets[0].data = [...this.values];
|
||||
this.chartConfig.circleChartDatasets[0].label = this.label;
|
||||
this.chartConfig.circleChartDatasets[0].backgroundColor = [
|
||||
this._utilitiesService.getSeriesColors(0.9, 'pastels')[this.color],
|
||||
'rgba(255, 255, 255, 0.05)'
|
||||
];
|
||||
this.chartConfig.circleChartDatasets[0].borderColor = [
|
||||
this._utilitiesService.getSeriesColors(1, 'pastels')[this.color],
|
||||
'rgba(255, 255, 255, 0.05)'
|
||||
];
|
||||
this.chartConfig.circleChartDatasets[0].borderWidth = 0;
|
||||
this.chartConfig.circleChartLegend = this.legend;
|
||||
this.displayCharts = true;
|
||||
}
|
||||
|
||||
/*private _loadCircleChart(): void {
|
||||
const dataset: ChartDataset<'circle'> = {
|
||||
data: [...this.values],
|
||||
label: 'Nombre total de sauts',
|
||||
backgroundColor: this._utilitiesService.getSeriesColors(0.8),
|
||||
borderColor: this._utilitiesService.getSeriesColors(1),
|
||||
borderWidth: 1
|
||||
};
|
||||
this.chartConfig.circleChartLabels = [...this.names];
|
||||
this.chartConfig.circleChartDatasets!.push(dataset);
|
||||
this.displayCharts = true;
|
||||
}*/
|
||||
}
|
||||
import { Component, Input, OnChanges } from '@angular/core';
|
||||
//import { ChartDataset } from 'chart.js';
|
||||
import { BaseChartDirective } from 'ng2-charts';
|
||||
|
||||
import { UtilitiesService } from '@services';
|
||||
import { CircleConfig } from '@models';
|
||||
|
||||
@Component({
|
||||
selector: 'app-circle-chart',
|
||||
imports: [BaseChartDirective],
|
||||
templateUrl: './circle-chart.component.html',
|
||||
})
|
||||
export class CircleChartComponent implements OnChanges {
|
||||
public displayCharts = false;
|
||||
public chartConfig: CircleConfig = this._utilitiesService.getCircleChartConfig();
|
||||
|
||||
constructor(private _utilitiesService: UtilitiesService) {}
|
||||
|
||||
@Input() names: string[] = [];
|
||||
@Input() values: number[] = [];
|
||||
@Input() headers: string[] = [];
|
||||
@Input() color: number = 0;
|
||||
@Input() label: string = 'Nombre total de sauts';
|
||||
@Input() legend: boolean = false;
|
||||
|
||||
ngOnChanges() {
|
||||
this._loadCircleChart();
|
||||
}
|
||||
|
||||
private _loadCircleChart(): void {
|
||||
this.chartConfig.circleChartLabels = [...this.names];
|
||||
this.chartConfig.circleChartDatasets[0].data = [...this.values];
|
||||
this.chartConfig.circleChartDatasets[0].label = this.label;
|
||||
this.chartConfig.circleChartDatasets[0].backgroundColor = [
|
||||
this._utilitiesService.getSeriesColors(0.9, 'pastels')[this.color],
|
||||
'rgba(255, 255, 255, 0.05)',
|
||||
];
|
||||
this.chartConfig.circleChartDatasets[0].borderColor = [
|
||||
this._utilitiesService.getSeriesColors(1, 'pastels')[this.color],
|
||||
'rgba(255, 255, 255, 0.05)',
|
||||
];
|
||||
this.chartConfig.circleChartDatasets[0].borderWidth = 0;
|
||||
this.chartConfig.circleChartLegend = this.legend;
|
||||
this.displayCharts = true;
|
||||
}
|
||||
|
||||
/*private _loadCircleChart(): void {
|
||||
const dataset: ChartDataset<'circle'> = {
|
||||
data: [...this.values],
|
||||
label: 'Nombre total de sauts',
|
||||
backgroundColor: this._utilitiesService.getSeriesColors(0.8),
|
||||
borderColor: this._utilitiesService.getSeriesColors(1),
|
||||
borderWidth: 1
|
||||
};
|
||||
this.chartConfig.circleChartLabels = [...this.names];
|
||||
this.chartConfig.circleChartDatasets!.push(dataset);
|
||||
this.displayCharts = true;
|
||||
}*/
|
||||
}
|
||||
|
||||
@@ -1,64 +1,59 @@
|
||||
import { Component, Input, OnChanges } from '@angular/core';
|
||||
import { ChartDataset, Point } from 'chart.js';
|
||||
import { BaseChartDirective } from 'ng2-charts';
|
||||
|
||||
import { UtilitiesService } from '@services';
|
||||
import { LineConfig } from '@models';
|
||||
|
||||
@Component({
|
||||
selector: 'app-line-chart',
|
||||
standalone: true,
|
||||
imports: [
|
||||
BaseChartDirective
|
||||
],
|
||||
templateUrl: './line-chart.component.html'
|
||||
})
|
||||
export class LineChartComponent implements OnChanges {
|
||||
public displayCharts = false;
|
||||
public chartConfig: LineConfig = this._utilitiesService.getLineChartConfig();
|
||||
|
||||
constructor(
|
||||
private _utilitiesService: UtilitiesService
|
||||
) { }
|
||||
|
||||
@Input() headers: string[] = [];
|
||||
@Input() names: string[] = [];
|
||||
@Input() values: Array<Array<number>> = [];
|
||||
@Input() colors: {
|
||||
backgroundColor: string[],
|
||||
borderColor: string[]
|
||||
} = {
|
||||
backgroundColor: this._utilitiesService.getSeriesColors(0.8),
|
||||
borderColor: this._utilitiesService.getSeriesColors(1)
|
||||
};
|
||||
@Input() legend: boolean = false;
|
||||
@Input() hideZero: boolean = false;
|
||||
|
||||
ngOnChanges() {
|
||||
this._loadLineChart();
|
||||
}
|
||||
|
||||
private _loadLineChart(): void {
|
||||
this.chartConfig.lineChartData.labels = [...this.headers];
|
||||
this.names.forEach((label: string, index: number) => {
|
||||
let data: Array<(number | Point | null)> = [];
|
||||
if (this.hideZero) {
|
||||
data = [...this.values[index].map(value => value === 0 ? null : value)];
|
||||
} else {
|
||||
data = [...this.values[index]];
|
||||
}
|
||||
const dataset: ChartDataset<'line'> = {
|
||||
data: data,
|
||||
label: label,
|
||||
backgroundColor: this.colors.backgroundColor[index],
|
||||
borderColor: this.colors.borderColor[index],
|
||||
borderWidth: 2,
|
||||
cubicInterpolationMode: 'monotone',
|
||||
tension: 0
|
||||
};
|
||||
this.chartConfig.lineChartData.datasets!.push(dataset);
|
||||
});
|
||||
this.chartConfig.lineChartLegend = this.legend;
|
||||
this.displayCharts = true;
|
||||
}
|
||||
}
|
||||
import { Component, Input, OnChanges } from '@angular/core';
|
||||
import { ChartDataset, Point } from 'chart.js';
|
||||
import { BaseChartDirective } from 'ng2-charts';
|
||||
|
||||
import { UtilitiesService } from '@services';
|
||||
import { LineConfig } from '@models';
|
||||
|
||||
@Component({
|
||||
selector: 'app-line-chart',
|
||||
imports: [BaseChartDirective],
|
||||
templateUrl: './line-chart.component.html',
|
||||
})
|
||||
export class LineChartComponent implements OnChanges {
|
||||
public displayCharts = false;
|
||||
public chartConfig: LineConfig = this._utilitiesService.getLineChartConfig();
|
||||
|
||||
constructor(private _utilitiesService: UtilitiesService) {}
|
||||
|
||||
@Input() headers: string[] = [];
|
||||
@Input() names: string[] = [];
|
||||
@Input() values: Array<Array<number>> = [];
|
||||
@Input() colors: {
|
||||
backgroundColor: string[];
|
||||
borderColor: string[];
|
||||
} = {
|
||||
backgroundColor: this._utilitiesService.getSeriesColors(0.8),
|
||||
borderColor: this._utilitiesService.getSeriesColors(1),
|
||||
};
|
||||
@Input() legend: boolean = false;
|
||||
@Input() hideZero: boolean = false;
|
||||
|
||||
ngOnChanges() {
|
||||
this._loadLineChart();
|
||||
}
|
||||
|
||||
private _loadLineChart(): void {
|
||||
this.chartConfig.lineChartData.labels = [...this.headers];
|
||||
this.names.forEach((label: string, index: number) => {
|
||||
let data: Array<number | Point | null> = [];
|
||||
if (this.hideZero) {
|
||||
data = [...this.values[index].map((value) => (value === 0 ? null : value))];
|
||||
} else {
|
||||
data = [...this.values[index]];
|
||||
}
|
||||
const dataset: ChartDataset<'line'> = {
|
||||
data: data,
|
||||
label: label,
|
||||
backgroundColor: this.colors.backgroundColor[index],
|
||||
borderColor: this.colors.borderColor[index],
|
||||
borderWidth: 2,
|
||||
cubicInterpolationMode: 'monotone',
|
||||
tension: 0,
|
||||
};
|
||||
this.chartConfig.lineChartData.datasets!.push(dataset);
|
||||
});
|
||||
this.chartConfig.lineChartLegend = this.legend;
|
||||
this.displayCharts = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,63 +1,58 @@
|
||||
import { Component, Input, OnChanges } from '@angular/core';
|
||||
import { ChartDataset } from 'chart.js';
|
||||
import { BaseChartDirective } from 'ng2-charts';
|
||||
|
||||
import { UtilitiesService } from '@services';
|
||||
import { LineConfig } from '@models';
|
||||
|
||||
@Component({
|
||||
selector: 'app-linearea-chart',
|
||||
standalone: true,
|
||||
imports: [
|
||||
BaseChartDirective
|
||||
],
|
||||
templateUrl: './linearea-chart.component.html'
|
||||
})
|
||||
export class LineAreaChartComponent implements OnChanges {
|
||||
public displayCharts = false;
|
||||
public chartConfig: LineConfig = this._utilitiesService.getStackedLineAreaChartConfig();
|
||||
|
||||
constructor(
|
||||
private _utilitiesService: UtilitiesService
|
||||
) { }
|
||||
|
||||
@Input() headers: string[] = [];
|
||||
@Input() names: string[] = [];
|
||||
@Input() values: Array<Array<number>> = [];
|
||||
@Input() colors: {
|
||||
backgroundColor: string[],
|
||||
borderColor: string[]
|
||||
} = {
|
||||
backgroundColor: this._utilitiesService.getSeriesColors(0.8),
|
||||
borderColor: this._utilitiesService.getSeriesColors(1)
|
||||
};
|
||||
@Input() legend: boolean = false;
|
||||
|
||||
ngOnChanges() {
|
||||
this._loadLineChart();
|
||||
}
|
||||
|
||||
private _loadLineChart(): void {
|
||||
this.chartConfig.lineChartData.labels = [...this.headers];
|
||||
this.names.forEach((label: string, index: number) => {
|
||||
let fill: string | number | boolean = '-1';
|
||||
if (index === 0) {
|
||||
fill = true;
|
||||
}
|
||||
const dataset: ChartDataset<'line'> = {
|
||||
data: [...this.values[index]],
|
||||
label: label,
|
||||
backgroundColor: this.colors.backgroundColor[index],
|
||||
borderColor: this.colors.borderColor[index],
|
||||
borderWidth: 1,
|
||||
fill: fill,
|
||||
//stepped: true,
|
||||
cubicInterpolationMode: 'monotone',
|
||||
tension: 0
|
||||
};
|
||||
this.chartConfig.lineChartData.datasets!.push(dataset);
|
||||
});
|
||||
this.chartConfig.lineChartLegend = this.legend;
|
||||
this.displayCharts = true;
|
||||
}
|
||||
}
|
||||
import { Component, Input, OnChanges } from '@angular/core';
|
||||
import { ChartDataset } from 'chart.js';
|
||||
import { BaseChartDirective } from 'ng2-charts';
|
||||
|
||||
import { UtilitiesService } from '@services';
|
||||
import { LineConfig } from '@models';
|
||||
|
||||
@Component({
|
||||
selector: 'app-linearea-chart',
|
||||
imports: [BaseChartDirective],
|
||||
templateUrl: './linearea-chart.component.html',
|
||||
})
|
||||
export class LineAreaChartComponent implements OnChanges {
|
||||
public displayCharts = false;
|
||||
public chartConfig: LineConfig = this._utilitiesService.getStackedLineAreaChartConfig();
|
||||
|
||||
constructor(private _utilitiesService: UtilitiesService) {}
|
||||
|
||||
@Input() headers: string[] = [];
|
||||
@Input() names: string[] = [];
|
||||
@Input() values: Array<Array<number>> = [];
|
||||
@Input() colors: {
|
||||
backgroundColor: string[];
|
||||
borderColor: string[];
|
||||
} = {
|
||||
backgroundColor: this._utilitiesService.getSeriesColors(0.8),
|
||||
borderColor: this._utilitiesService.getSeriesColors(1),
|
||||
};
|
||||
@Input() legend: boolean = false;
|
||||
|
||||
ngOnChanges() {
|
||||
this._loadLineChart();
|
||||
}
|
||||
|
||||
private _loadLineChart(): void {
|
||||
this.chartConfig.lineChartData.labels = [...this.headers];
|
||||
this.names.forEach((label: string, index: number) => {
|
||||
let fill: string | number | boolean = '-1';
|
||||
if (index === 0) {
|
||||
fill = true;
|
||||
}
|
||||
const dataset: ChartDataset<'line'> = {
|
||||
data: [...this.values[index]],
|
||||
label: label,
|
||||
backgroundColor: this.colors.backgroundColor[index],
|
||||
borderColor: this.colors.borderColor[index],
|
||||
borderWidth: 1,
|
||||
fill: fill,
|
||||
//stepped: true,
|
||||
cubicInterpolationMode: 'monotone',
|
||||
tension: 0,
|
||||
};
|
||||
this.chartConfig.lineChartData.datasets!.push(dataset);
|
||||
});
|
||||
this.chartConfig.lineChartLegend = this.legend;
|
||||
this.displayCharts = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,63 +1,58 @@
|
||||
import { Component, Input, OnChanges } from '@angular/core';
|
||||
//import { ChartDataset } from 'chart.js';
|
||||
import { BaseChartDirective } from 'ng2-charts';
|
||||
|
||||
import { UtilitiesService } from '@services';
|
||||
import { DoughnutConfig } from '@models';
|
||||
|
||||
@Component({
|
||||
selector: 'app-pie-chart',
|
||||
standalone: true,
|
||||
imports: [
|
||||
BaseChartDirective
|
||||
],
|
||||
templateUrl: './pie-chart.component.html'
|
||||
})
|
||||
export class PieChartComponent implements OnChanges {
|
||||
public displayCharts = false;
|
||||
public chartConfig: DoughnutConfig = this._utilitiesService.getDoughnutChartConfig();
|
||||
|
||||
constructor(
|
||||
private _utilitiesService: UtilitiesService
|
||||
) { }
|
||||
|
||||
@Input() names: string[] = [];
|
||||
@Input() values: number[] = [];
|
||||
@Input() headers: string[] = [];
|
||||
@Input() colors: {
|
||||
backgroundColor: string[],
|
||||
borderColor: string[]
|
||||
} = {
|
||||
backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'all'),
|
||||
borderColor: this._utilitiesService.getSeriesColors(1, 'all')
|
||||
};
|
||||
@Input() legend: boolean = false;
|
||||
|
||||
ngOnChanges() {
|
||||
this._loadDoughnutChart();
|
||||
}
|
||||
|
||||
private _loadDoughnutChart(): void {
|
||||
this.chartConfig.doughnutChartLabels = [...this.names];
|
||||
this.chartConfig.doughnutChartDatasets[0].data = [...this.values];
|
||||
this.chartConfig.doughnutChartDatasets[0].label = 'Nombre total de sauts';
|
||||
this.chartConfig.doughnutChartDatasets[0].backgroundColor = this.colors.backgroundColor;
|
||||
this.chartConfig.doughnutChartDatasets[0].borderColor = this.colors.borderColor;
|
||||
this.chartConfig.doughnutChartDatasets[0].borderWidth = 2;
|
||||
this.chartConfig.doughnutChartLegend = this.legend;
|
||||
this.displayCharts = true;
|
||||
}
|
||||
|
||||
/*private _loadDoughnutChart(): void {
|
||||
const dataset: ChartDataset<'doughnut'> = {
|
||||
data: [...this.values],
|
||||
label: 'Nombre total de sauts',
|
||||
backgroundColor: this._utilitiesService.getSeriesColors(0.8),
|
||||
borderColor: this._utilitiesService.getSeriesColors(1),
|
||||
borderWidth: 1
|
||||
};
|
||||
this.chartConfig.doughnutChartLabels = [...this.names];
|
||||
this.chartConfig.doughnutChartDatasets!.push(dataset);
|
||||
this.displayCharts = true;
|
||||
}*/
|
||||
}
|
||||
import { Component, Input, OnChanges } from '@angular/core';
|
||||
//import { ChartDataset } from 'chart.js';
|
||||
import { BaseChartDirective } from 'ng2-charts';
|
||||
|
||||
import { UtilitiesService } from '@services';
|
||||
import { DoughnutConfig } from '@models';
|
||||
|
||||
@Component({
|
||||
selector: 'app-pie-chart',
|
||||
imports: [BaseChartDirective],
|
||||
templateUrl: './pie-chart.component.html',
|
||||
})
|
||||
export class PieChartComponent implements OnChanges {
|
||||
public displayCharts = false;
|
||||
public chartConfig: DoughnutConfig = this._utilitiesService.getDoughnutChartConfig();
|
||||
|
||||
constructor(private _utilitiesService: UtilitiesService) {}
|
||||
|
||||
@Input() names: string[] = [];
|
||||
@Input() values: number[] = [];
|
||||
@Input() headers: string[] = [];
|
||||
@Input() colors: {
|
||||
backgroundColor: string[];
|
||||
borderColor: string[];
|
||||
} = {
|
||||
backgroundColor: this._utilitiesService.getSeriesColors(0.8, 'all'),
|
||||
borderColor: this._utilitiesService.getSeriesColors(1, 'all'),
|
||||
};
|
||||
@Input() legend: boolean = false;
|
||||
|
||||
ngOnChanges() {
|
||||
this._loadDoughnutChart();
|
||||
}
|
||||
|
||||
private _loadDoughnutChart(): void {
|
||||
this.chartConfig.doughnutChartLabels = [...this.names];
|
||||
this.chartConfig.doughnutChartDatasets[0].data = [...this.values];
|
||||
this.chartConfig.doughnutChartDatasets[0].label = 'Nombre total de sauts';
|
||||
this.chartConfig.doughnutChartDatasets[0].backgroundColor = this.colors.backgroundColor;
|
||||
this.chartConfig.doughnutChartDatasets[0].borderColor = this.colors.borderColor;
|
||||
this.chartConfig.doughnutChartDatasets[0].borderWidth = 2;
|
||||
this.chartConfig.doughnutChartLegend = this.legend;
|
||||
this.displayCharts = true;
|
||||
}
|
||||
|
||||
/*private _loadDoughnutChart(): void {
|
||||
const dataset: ChartDataset<'doughnut'> = {
|
||||
data: [...this.values],
|
||||
label: 'Nombre total de sauts',
|
||||
backgroundColor: this._utilitiesService.getSeriesColors(0.8),
|
||||
borderColor: this._utilitiesService.getSeriesColors(1),
|
||||
borderWidth: 1
|
||||
};
|
||||
this.chartConfig.doughnutChartLabels = [...this.names];
|
||||
this.chartConfig.doughnutChartDatasets!.push(dataset);
|
||||
this.displayCharts = true;
|
||||
}*/
|
||||
}
|
||||
|
||||
@@ -2,13 +2,10 @@ import { Component, Input, AfterContentChecked } from '@angular/core';
|
||||
import { NgIf, NgFor } from '@angular/common';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
imports: [
|
||||
NgIf, NgFor
|
||||
],
|
||||
imports: [NgIf, NgFor],
|
||||
selector: 'app-history-table',
|
||||
templateUrl: './history-table.component.html',
|
||||
styleUrls: []
|
||||
styleUrls: [],
|
||||
})
|
||||
export class HistoryTableComponent implements AfterContentChecked {
|
||||
public seriesColTotal: number[] = [];
|
||||
@@ -38,7 +35,7 @@ export class HistoryTableComponent implements AfterContentChecked {
|
||||
this.seriesColTotal = [...values];
|
||||
this.rows.forEach((row: number[], rowIndex: number) => {
|
||||
row.forEach((value: number, index: number) => {
|
||||
this.seriesColTotal[index] = (this.seriesColTotal[index] + this.rows[rowIndex][index]);
|
||||
this.seriesColTotal[index] = this.seriesColTotal[index] + this.rows[rowIndex][index];
|
||||
});
|
||||
this.grandTotal = this.seriesColTotal.reduce((partialSum, a) => partialSum + a, 0);
|
||||
});
|
||||
|
||||
@@ -13,16 +13,15 @@ import { JumpPreviewComponent } from './jump-preview.component';
|
||||
@Component({
|
||||
selector: 'app-jump-list',
|
||||
templateUrl: './jump-list.component.html',
|
||||
standalone: true,
|
||||
imports: [
|
||||
NgClass,
|
||||
DatePipe,
|
||||
MatProgressSpinnerModule,
|
||||
MatButtonModule,
|
||||
RouterLink,
|
||||
MatIconModule,
|
||||
JumpPreviewComponent
|
||||
]
|
||||
NgClass,
|
||||
DatePipe,
|
||||
MatProgressSpinnerModule,
|
||||
MatButtonModule,
|
||||
RouterLink,
|
||||
MatIconModule,
|
||||
JumpPreviewComponent,
|
||||
],
|
||||
})
|
||||
export class JumpListComponent implements OnInit, OnDestroy {
|
||||
private _jumps: Subscription = new Subscription();
|
||||
@@ -35,9 +34,7 @@ export class JumpListComponent implements OnInit, OnDestroy {
|
||||
pages: Array<number> = [1];
|
||||
lastUpdate: Date = new Date();
|
||||
|
||||
constructor(
|
||||
private jumpsService: JumpsService
|
||||
) { }
|
||||
constructor(private jumpsService: JumpsService) {}
|
||||
|
||||
@Input() limit = 0;
|
||||
@Input() refresh = 30000;
|
||||
@@ -70,7 +67,7 @@ export class JumpListComponent implements OnInit, OnDestroy {
|
||||
runQuery() {
|
||||
if (this.limit) {
|
||||
this.query.filters.limit = this.limit;
|
||||
this.query.filters.offset = (this.limit * (this.currentPage - 1));
|
||||
this.query.filters.offset = this.limit * (this.currentPage - 1);
|
||||
}
|
||||
|
||||
const jumps$: Observable<JumpList> = this.jumpsService.query(this.query);
|
||||
@@ -85,7 +82,7 @@ export class JumpListComponent implements OnInit, OnDestroy {
|
||||
},
|
||||
error: (err) => {
|
||||
this.errors = err;
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -6,10 +6,9 @@ import { Jump } from '@models';
|
||||
|
||||
@Component({
|
||||
selector: 'app-jump-meta',
|
||||
standalone: true,
|
||||
imports: [ RouterLink, DatePipe ],
|
||||
imports: [RouterLink, DatePipe],
|
||||
styleUrl: './jump-meta.component.scss',
|
||||
templateUrl: './jump-meta.component.html'
|
||||
templateUrl: './jump-meta.component.html',
|
||||
})
|
||||
export class JumpMetaComponent {
|
||||
@Input() jump!: Jump;
|
||||
|
||||
@@ -12,14 +12,9 @@ import { JumpsService } from '@services';
|
||||
|
||||
@Component({
|
||||
selector: 'app-jump-preview',
|
||||
standalone: true,
|
||||
imports: [
|
||||
DecimalPipe, RouterLink,
|
||||
MatDividerModule, MatButtonModule, MatCardModule,
|
||||
JumpMetaComponent
|
||||
],
|
||||
imports: [DecimalPipe, RouterLink, MatDividerModule, MatButtonModule, MatCardModule, JumpMetaComponent],
|
||||
styleUrl: './jump-preview.component.scss',
|
||||
templateUrl: './jump-preview.component.html'
|
||||
templateUrl: './jump-preview.component.html',
|
||||
})
|
||||
export class JumpPreviewComponent implements OnDestroy {
|
||||
@Input() jump!: Jump;
|
||||
@@ -30,8 +25,8 @@ export class JumpPreviewComponent implements OnDestroy {
|
||||
|
||||
constructor(
|
||||
private router: Router,
|
||||
private jumpsService: JumpsService
|
||||
) { }
|
||||
private jumpsService: JumpsService,
|
||||
) {}
|
||||
|
||||
ngOnDestroy() {
|
||||
this._jump.unsubscribe();
|
||||
@@ -43,7 +38,7 @@ export class JumpPreviewComponent implements OnDestroy {
|
||||
this._jump = jump$.subscribe({
|
||||
next: () => {
|
||||
this.router.navigateByUrl('/');
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,13 @@
|
||||
import { AfterContentChecked, Component, EventEmitter, Input, Output, OnChanges, OnDestroy, ViewChild } from '@angular/core';
|
||||
import {
|
||||
AfterContentChecked,
|
||||
Component,
|
||||
EventEmitter,
|
||||
Input,
|
||||
Output,
|
||||
OnChanges,
|
||||
OnDestroy,
|
||||
ViewChild,
|
||||
} from '@angular/core';
|
||||
import { CommonModule, DecimalPipe, DatePipe } from '@angular/common';
|
||||
import { UntypedFormBuilder, UntypedFormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { Router, RouterLink } from '@angular/router';
|
||||
@@ -15,29 +24,68 @@ import { MatProgressBarModule } from '@angular/material/progress-bar';
|
||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||
import { MatSort, MatSortModule } from '@angular/material/sort';
|
||||
import { MatTableDataSource, MatTableModule } from '@angular/material/table';
|
||||
import { MatSnackBar, MatSnackBarHorizontalPosition, MatSnackBarModule, MatSnackBarVerticalPosition } from '@angular/material/snack-bar';
|
||||
import {
|
||||
MatSnackBar,
|
||||
MatSnackBarHorizontalPosition,
|
||||
MatSnackBarModule,
|
||||
MatSnackBarVerticalPosition,
|
||||
} from '@angular/material/snack-bar';
|
||||
import { Observable, Subscription } from 'rxjs';
|
||||
import { take } from 'rxjs/operators';
|
||||
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
|
||||
|
||||
import { FrenchPaginator } from '@components/shared/french-paginator.component';
|
||||
import { ColumnDefinition, Errors, Jump, JumpByDay, JumpFile, JumpFileType, JumpList, JumpListConfig, jumpColumns } from '@models';
|
||||
import {
|
||||
ColumnDefinition,
|
||||
Errors,
|
||||
Jump,
|
||||
JumpByDay,
|
||||
JumpFile,
|
||||
JumpFileType,
|
||||
JumpList,
|
||||
JumpListConfig,
|
||||
jumpColumns,
|
||||
} from '@models';
|
||||
import { JumpsService, JumpTableService } from '@services';
|
||||
import { JumpAddDialogComponent, JumpDeleteDialogComponent, JumpEditDialogComponent, JumpViewDialogComponent } from '@components/logbook/dialogs'
|
||||
import {
|
||||
JumpAddDialogComponent,
|
||||
JumpDeleteDialogComponent,
|
||||
JumpEditDialogComponent,
|
||||
JumpViewDialogComponent,
|
||||
} from '@components/logbook/dialogs';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
imports: [
|
||||
CommonModule, DecimalPipe, DatePipe, RouterLink, FormsModule, ReactiveFormsModule, NgxSkeletonLoaderModule,
|
||||
MatButtonModule, MatCardModule, MatDialogModule,
|
||||
MatFormFieldModule, MatIconModule, MatInputModule, MatNativeDateModule, MatMenuModule,
|
||||
MatPaginatorModule, MatProgressBarModule, MatProgressSpinnerModule, MatSnackBarModule, MatSortModule, MatTableModule,
|
||||
JumpAddDialogComponent, JumpDeleteDialogComponent, JumpEditDialogComponent, JumpViewDialogComponent
|
||||
CommonModule,
|
||||
DecimalPipe,
|
||||
DatePipe,
|
||||
RouterLink,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
NgxSkeletonLoaderModule,
|
||||
MatButtonModule,
|
||||
MatCardModule,
|
||||
MatDialogModule,
|
||||
MatFormFieldModule,
|
||||
MatIconModule,
|
||||
MatInputModule,
|
||||
MatNativeDateModule,
|
||||
MatMenuModule,
|
||||
MatPaginatorModule,
|
||||
MatProgressBarModule,
|
||||
MatProgressSpinnerModule,
|
||||
MatSnackBarModule,
|
||||
MatSortModule,
|
||||
MatTableModule,
|
||||
JumpAddDialogComponent,
|
||||
JumpDeleteDialogComponent,
|
||||
JumpEditDialogComponent,
|
||||
JumpViewDialogComponent,
|
||||
],
|
||||
selector: 'app-jump-table',
|
||||
styleUrl: './jump-table.component.scss',
|
||||
templateUrl: './jump-table.component.html',
|
||||
providers: [{provide: MatPaginatorIntl, useClass: FrenchPaginator}]
|
||||
providers: [{ provide: MatPaginatorIntl, useClass: FrenchPaginator }],
|
||||
})
|
||||
export class JumpTableComponent implements OnChanges, OnDestroy, AfterContentChecked {
|
||||
private _jumps: Subscription = new Subscription();
|
||||
@@ -57,10 +105,18 @@ export class JumpTableComponent implements OnChanges, OnDestroy, AfterContentChe
|
||||
'zone', 'files', 'actions'
|
||||
];*/
|
||||
public displayedColumns: string[] = [
|
||||
'numero', 'date', 'lieu', 'aeronef',
|
||||
'hauteur', 'voile', 'categorie',
|
||||
'participants', 'zone', 'accessoires',
|
||||
'files', 'actions'
|
||||
'numero',
|
||||
'date',
|
||||
'lieu',
|
||||
'aeronef',
|
||||
'hauteur',
|
||||
'voile',
|
||||
'categorie',
|
||||
'participants',
|
||||
'zone',
|
||||
'accessoires',
|
||||
'files',
|
||||
'actions',
|
||||
];
|
||||
//public displayedColumns: string[] = jumpColumns.map((col) => col.key)
|
||||
public columnsSchema: Array<ColumnDefinition> = jumpColumns;
|
||||
@@ -81,12 +137,12 @@ export class JumpTableComponent implements OnChanges, OnDestroy, AfterContentChe
|
||||
private _jumpTableService: JumpTableService,
|
||||
private dialog: MatDialog,
|
||||
private fb: UntypedFormBuilder,
|
||||
private snackBar: MatSnackBar
|
||||
private snackBar: MatSnackBar,
|
||||
) {
|
||||
this._resetErrors();
|
||||
this.searchForm = this.fb.group({
|
||||
//numero: ['', Validators.required]
|
||||
numero: ''
|
||||
numero: '',
|
||||
});
|
||||
}
|
||||
|
||||
@@ -116,7 +172,7 @@ export class JumpTableComponent implements OnChanges, OnDestroy, AfterContentChe
|
||||
|
||||
ngOnDestroy() {
|
||||
this._jumps.unsubscribe();
|
||||
this._subscriptions.forEach(subscription => {
|
||||
this._subscriptions.forEach((subscription) => {
|
||||
subscription.unsubscribe();
|
||||
});
|
||||
}
|
||||
@@ -139,7 +195,7 @@ export class JumpTableComponent implements OnChanges, OnDestroy, AfterContentChe
|
||||
|
||||
if (this.limit) {
|
||||
this._query.filters.limit = this.limit;
|
||||
this._query.filters.offset = (this.limit * (this._currentPage - 1));
|
||||
this._query.filters.offset = this.limit * (this._currentPage - 1);
|
||||
} else {
|
||||
this._query.filters.limit = 0;
|
||||
this._query.filters.offset = 0;
|
||||
@@ -172,7 +228,7 @@ export class JumpTableComponent implements OnChanges, OnDestroy, AfterContentChe
|
||||
},
|
||||
error: (err) => {
|
||||
this.errors = err;
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -185,97 +241,114 @@ export class JumpTableComponent implements OnChanges, OnDestroy, AfterContentChe
|
||||
//config.filters.dateRangeEnd = `${year}-12-31 23:59:59`;
|
||||
config.filters.dateRangeEnd = '2024-12-31 23:59:59';
|
||||
//console.log(config.filters);
|
||||
const subscription: Subscription = this._jumpsService.getAllByDay(config)
|
||||
.pipe(take(1))
|
||||
.subscribe({
|
||||
next: (days) => {
|
||||
this._resetErrors();
|
||||
//console.log('getAllByDay : ', days);
|
||||
days.forEach(day => {
|
||||
this.loadSkydiverIdJumps(day, config);
|
||||
});
|
||||
},
|
||||
error: (err) => {
|
||||
this.errors = err;
|
||||
}
|
||||
});
|
||||
const subscription: Subscription = this._jumpsService
|
||||
.getAllByDay(config)
|
||||
.pipe(take(1))
|
||||
.subscribe({
|
||||
next: (days) => {
|
||||
this._resetErrors();
|
||||
//console.log('getAllByDay : ', days);
|
||||
days.forEach((day) => {
|
||||
this.loadSkydiverIdJumps(day, config);
|
||||
});
|
||||
},
|
||||
error: (err) => {
|
||||
this.errors = err;
|
||||
},
|
||||
});
|
||||
this._subscriptions.push(subscription);
|
||||
}
|
||||
|
||||
loadSkydiverIdJumps(day: JumpByDay, config: JumpListConfig) {
|
||||
config.filters.dateRangeStart = `${day.jumps[0].date!.substring(0, 10)} 00:00:00`;
|
||||
config.filters.dateRangeEnd = `${day.jumps[0].date!.substring(0, 10)} 23:59:59`;
|
||||
const subscription: Subscription = this._jumpsService.getAllFromSkydiverIdApi(config)
|
||||
.pipe(take(1))
|
||||
.subscribe({
|
||||
next: (data) => {
|
||||
if (data.items.length) {
|
||||
const diff = day.count - data.items.length;
|
||||
if (diff < 0) {
|
||||
console.error(`${diff} ${diff > 1 ? 'données' : 'donnée'} altimètre de trop le ${day.jumps[0].date!.substring(0, 10)}`);
|
||||
} else {
|
||||
if (diff > 0) {
|
||||
console.error(`${diff}/${day.count} ${diff > 1 ? 'données altimètre manquantes' : 'donnée altimètre manquante'} le ${day.jumps[0].date!.substring(0, 10)}`, day.jumps, data.items);
|
||||
}
|
||||
console.log(`${day.count} ${day.count > 1 ? 'sauts' : 'saut'} le ${data.items[0].date!.substring(0, 10)}`, day.jumps.sort((a, b) => b.numero! - a.numero!), data.items);
|
||||
data.items.map((jump, index) => {
|
||||
const file: JumpFile = {
|
||||
name: jump.name,
|
||||
path: `/Volumes/Storage/Skydive/X2_Logs/${day.jumps[index].date!.substring(0, 4)}/`,
|
||||
type: JumpFileType.CSV
|
||||
} as JumpFile;
|
||||
this._subscriptions.push(
|
||||
this._jumpsService.saveX2Data(day.jumps[index].slug!, file, jump)
|
||||
.pipe(take(1))
|
||||
.subscribe({
|
||||
next: (jump) => {
|
||||
this._resetErrors();
|
||||
console.log(`Le fichier ${file.name} a été ajouté au saut n°${jump.numero} !`, 'OK');
|
||||
},
|
||||
error: (err) => {
|
||||
this.errors = err;
|
||||
}
|
||||
})
|
||||
const subscription: Subscription = this._jumpsService
|
||||
.getAllFromSkydiverIdApi(config)
|
||||
.pipe(take(1))
|
||||
.subscribe({
|
||||
next: (data) => {
|
||||
if (data.items.length) {
|
||||
const diff = day.count - data.items.length;
|
||||
if (diff < 0) {
|
||||
console.error(
|
||||
`${diff} ${diff > 1 ? 'données' : 'donnée'} altimètre de trop le ${day.jumps[0].date!.substring(0, 10)}`,
|
||||
);
|
||||
return jump;
|
||||
});
|
||||
} else {
|
||||
if (diff > 0) {
|
||||
console.error(
|
||||
`${diff}/${day.count} ${diff > 1 ? 'données altimètre manquantes' : 'donnée altimètre manquante'} le ${day.jumps[0].date!.substring(0, 10)}`,
|
||||
day.jumps,
|
||||
data.items,
|
||||
);
|
||||
}
|
||||
console.log(
|
||||
`${day.count} ${day.count > 1 ? 'sauts' : 'saut'} le ${data.items[0].date!.substring(0, 10)}`,
|
||||
day.jumps.sort((a, b) => b.numero! - a.numero!),
|
||||
data.items,
|
||||
);
|
||||
data.items.map((jump, index) => {
|
||||
const file: JumpFile = {
|
||||
name: jump.name,
|
||||
path: `/Volumes/Storage/Skydive/X2_Logs/${day.jumps[index].date!.substring(0, 4)}/`,
|
||||
type: JumpFileType.CSV,
|
||||
} as JumpFile;
|
||||
this._subscriptions.push(
|
||||
this._jumpsService
|
||||
.saveX2Data(day.jumps[index].slug!, file, jump)
|
||||
.pipe(take(1))
|
||||
.subscribe({
|
||||
next: (jump) => {
|
||||
this._resetErrors();
|
||||
console.log(
|
||||
`Le fichier ${file.name} a été ajouté au saut n°${jump.numero} !`,
|
||||
'OK',
|
||||
);
|
||||
},
|
||||
error: (err) => {
|
||||
this.errors = err;
|
||||
},
|
||||
}),
|
||||
);
|
||||
return jump;
|
||||
});
|
||||
}
|
||||
//console.log(`${day.count} ${day.count > 1 ? 'sauts' : 'saut'} le ${day.jumps[0].date!.substring(0, 10)}`);
|
||||
//console.log(`${data.items.length} ${data.items.length > 1 ? 'sauts' : 'saut'} le ${data.items[0].date!.substring(0, 10)}`, data);
|
||||
} else {
|
||||
console.info('Aucune données altimètre pour le ', day.jumps[0].date!.substring(0, 10));
|
||||
}
|
||||
//console.log(`${day.count} ${day.count > 1 ? 'sauts' : 'saut'} le ${day.jumps[0].date!.substring(0, 10)}`);
|
||||
//console.log(`${data.items.length} ${data.items.length > 1 ? 'sauts' : 'saut'} le ${data.items[0].date!.substring(0, 10)}`, data);
|
||||
} else {
|
||||
console.info('Aucune données altimètre pour le ', day.jumps[0].date!.substring(0, 10));
|
||||
}
|
||||
},
|
||||
error: (err) => {
|
||||
console.error('getAllFromSkydiverIdApi error');
|
||||
this.errors = err;
|
||||
}
|
||||
});
|
||||
},
|
||||
error: (err) => {
|
||||
console.error('getAllFromSkydiverIdApi error');
|
||||
this.errors = err;
|
||||
},
|
||||
});
|
||||
this._subscriptions.push(subscription);
|
||||
}
|
||||
|
||||
updateJumps(jumps: Array<Jump>) {
|
||||
jumps.map(jump => {
|
||||
jumps.map((jump) => {
|
||||
jump.files = [];
|
||||
if (jump.dossier !== "" && jump.video !== "") {
|
||||
if (jump.dossier !== '' && jump.video !== '') {
|
||||
const file: JumpFile = {
|
||||
name: jump.video!,
|
||||
path: jump.dossier!,
|
||||
type: JumpFileType.VIDEO
|
||||
type: JumpFileType.VIDEO,
|
||||
} as JumpFile;
|
||||
this._subscriptions.push(
|
||||
this._jumpsService.saveFile(jump.slug, file)
|
||||
.pipe(take(1))
|
||||
.subscribe({
|
||||
next: (file) => {
|
||||
this._resetErrors();
|
||||
jump.files.push(file);
|
||||
//console.log(`Le fichier ${file.name} a été ajouté au saut n°${jump.numero} !`, 'OK');
|
||||
},
|
||||
error: (err) => {
|
||||
this.errors = err;
|
||||
}
|
||||
})
|
||||
this._jumpsService
|
||||
.saveFile(jump.slug, file)
|
||||
.pipe(take(1))
|
||||
.subscribe({
|
||||
next: (file) => {
|
||||
this._resetErrors();
|
||||
jump.files.push(file);
|
||||
//console.log(`Le fichier ${file.name} a été ajouté au saut n°${jump.numero} !`, 'OK');
|
||||
},
|
||||
error: (err) => {
|
||||
this.errors = err;
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
return jump;
|
||||
@@ -283,26 +356,30 @@ export class JumpTableComponent implements OnChanges, OnDestroy, AfterContentChe
|
||||
}
|
||||
|
||||
getKmlJumpFiles(jumps: Array<Jump>) {
|
||||
jumps.map(jump => {
|
||||
jumps.map((jump) => {
|
||||
if (jump.x2data !== null) {
|
||||
//console.log(`Le fichier ${jump.x2data.name} existe pour le saut n°${jump.numero} !`, `https://skydiver.id/api/jump/${jump.x2data.id}/kml`);
|
||||
const file: JumpFile = {
|
||||
name: jump.x2data.name.substring(0, -4) + '.kml',
|
||||
path: `/X2_Kmls/${jump.date.substring(0, 4)}/`,
|
||||
type: JumpFileType.KML
|
||||
type: JumpFileType.KML,
|
||||
} as JumpFile;
|
||||
this._subscriptions.push(
|
||||
this._jumpsService.saveKml(jump.slug, file)
|
||||
.pipe(take(1))
|
||||
.subscribe({
|
||||
next: (file) => {
|
||||
this._resetErrors();
|
||||
console.log(`Le fichier ${file.path}${file.name} a été ajouté au saut n°${jump.numero} !`, 'OK');
|
||||
},
|
||||
error: (err) => {
|
||||
this.errors = err;
|
||||
}
|
||||
})
|
||||
this._jumpsService
|
||||
.saveKml(jump.slug, file)
|
||||
.pipe(take(1))
|
||||
.subscribe({
|
||||
next: (file) => {
|
||||
this._resetErrors();
|
||||
console.log(
|
||||
`Le fichier ${file.path}${file.name} a été ajouté au saut n°${jump.numero} !`,
|
||||
'OK',
|
||||
);
|
||||
},
|
||||
error: (err) => {
|
||||
this.errors = err;
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
return jump;
|
||||
@@ -312,50 +389,53 @@ export class JumpTableComponent implements OnChanges, OnDestroy, AfterContentChe
|
||||
deleteJump(slug: string) {
|
||||
this.isDeleting = true;
|
||||
this._subscriptions.push(
|
||||
this._jumpsService.destroy(slug)
|
||||
.pipe(take(1))
|
||||
.subscribe(() => {
|
||||
this.router.navigateByUrl('/');
|
||||
})
|
||||
this._jumpsService
|
||||
.destroy(slug)
|
||||
.pipe(take(1))
|
||||
.subscribe(() => {
|
||||
this.router.navigateByUrl('/');
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
openDeleteDialog(jump: Jump): void {
|
||||
const dialogRef = this.dialog.open(JumpDeleteDialogComponent, {
|
||||
width: '60vw',
|
||||
data: jump
|
||||
data: jump,
|
||||
});
|
||||
this._subscriptions.push(
|
||||
dialogRef.afterClosed()
|
||||
.pipe(take(1))
|
||||
.subscribe(result => {
|
||||
if (result != undefined) {
|
||||
this._onDelete(result.slug);
|
||||
}
|
||||
})
|
||||
dialogRef
|
||||
.afterClosed()
|
||||
.pipe(take(1))
|
||||
.subscribe((result) => {
|
||||
if (result != undefined) {
|
||||
this._onDelete(result.slug);
|
||||
}
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
openEditDialog(jump: Jump): void {
|
||||
const dialogRef = this.dialog.open(JumpEditDialogComponent, {
|
||||
width: '70vw',
|
||||
data: jump
|
||||
data: jump,
|
||||
});
|
||||
this._subscriptions.push(
|
||||
dialogRef.afterClosed()
|
||||
.pipe(take(1))
|
||||
.subscribe(result => {
|
||||
if (result != undefined) {
|
||||
this._onEdit(result);
|
||||
}
|
||||
})
|
||||
dialogRef
|
||||
.afterClosed()
|
||||
.pipe(take(1))
|
||||
.subscribe((result) => {
|
||||
if (result != undefined) {
|
||||
this._onEdit(result);
|
||||
}
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
openViewDialog(jump: Jump): void {
|
||||
const dialogRef = this.dialog.open(JumpViewDialogComponent, {
|
||||
width: '60vw',
|
||||
data: jump
|
||||
data: jump,
|
||||
});
|
||||
dialogRef.afterClosed();
|
||||
}
|
||||
@@ -379,20 +459,21 @@ export class JumpTableComponent implements OnChanges, OnDestroy, AfterContentChe
|
||||
try {
|
||||
this.isDeleting = true;
|
||||
this._subscriptions.push(
|
||||
this._jumpsService.destroy(slug)
|
||||
.pipe(take(1))
|
||||
.subscribe({
|
||||
next: () => {
|
||||
this._resetErrors();
|
||||
this._openSnackBar(`Le saut a été supprimé !`, 'OK');
|
||||
this.runQuery();
|
||||
this.tableRefresh = !this.tableRefresh;
|
||||
this._jumpTableService.updateTableRefresh(this.tableRefresh);
|
||||
},
|
||||
error: (err) => {
|
||||
this.errors = err;
|
||||
}
|
||||
})
|
||||
this._jumpsService
|
||||
.destroy(slug)
|
||||
.pipe(take(1))
|
||||
.subscribe({
|
||||
next: () => {
|
||||
this._resetErrors();
|
||||
this._openSnackBar(`Le saut a été supprimé !`, 'OK');
|
||||
this.runQuery();
|
||||
this.tableRefresh = !this.tableRefresh;
|
||||
this._jumpTableService.updateTableRefresh(this.tableRefresh);
|
||||
},
|
||||
error: (err) => {
|
||||
this.errors = err;
|
||||
},
|
||||
}),
|
||||
);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
@@ -403,21 +484,22 @@ export class JumpTableComponent implements OnChanges, OnDestroy, AfterContentChe
|
||||
try {
|
||||
this.isSubmitting = true;
|
||||
this._subscriptions.push(
|
||||
this._jumpsService.update(jump)
|
||||
.pipe(take(1))
|
||||
.subscribe({
|
||||
next: (jump) => {
|
||||
this._resetErrors();
|
||||
this._openSnackBar(`Le saut n°${jump.numero} a été mis à jour !`, 'OK');
|
||||
this.runQuery();
|
||||
this.tableRefresh = !this.tableRefresh;
|
||||
this._jumpTableService.updateTableRefresh(this.tableRefresh);
|
||||
},
|
||||
error: (err) => {
|
||||
this.errors = err;
|
||||
this.isSubmitting = false;
|
||||
}
|
||||
})
|
||||
this._jumpsService
|
||||
.update(jump)
|
||||
.pipe(take(1))
|
||||
.subscribe({
|
||||
next: (jump) => {
|
||||
this._resetErrors();
|
||||
this._openSnackBar(`Le saut n°${jump.numero} a été mis à jour !`, 'OK');
|
||||
this.runQuery();
|
||||
this.tableRefresh = !this.tableRefresh;
|
||||
this._jumpTableService.updateTableRefresh(this.tableRefresh);
|
||||
},
|
||||
error: (err) => {
|
||||
this.errors = err;
|
||||
this.isSubmitting = false;
|
||||
},
|
||||
}),
|
||||
);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
@@ -468,5 +550,4 @@ export class JumpTableComponent implements OnChanges, OnDestroy, AfterContentChe
|
||||
}))
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
+2
-6
@@ -12,11 +12,7 @@ import { HWGuildWarFortification, HWMember } from '@models';
|
||||
selector: 'app-fortification-card-content',
|
||||
templateUrl: './fortification-card-content.component.html',
|
||||
styleUrl: './fortification-card-content.component.scss',
|
||||
standalone: true,
|
||||
imports: [
|
||||
DecimalPipe,
|
||||
MatCardModule, MatChipsModule, MatIconModule
|
||||
]
|
||||
imports: [DecimalPipe, MatCardModule, MatChipsModule, MatIconModule],
|
||||
})
|
||||
export class FortificationCardContentComponent {
|
||||
public data: HWGuildWarFortification = {} as HWGuildWarFortification;
|
||||
@@ -80,4 +76,4 @@ export class FortificationCardContentComponent {
|
||||
: [];
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,13 +10,9 @@ import guildData from 'src/files-data/hw-guild-data.json'; // page Membres
|
||||
|
||||
@Component({
|
||||
selector: 'app-guild-card',
|
||||
standalone: true,
|
||||
imports: [
|
||||
DatePipe, DecimalPipe,
|
||||
MatCardModule, MatDividerModule, MatIconModule
|
||||
],
|
||||
imports: [DatePipe, DecimalPipe, MatCardModule, MatDividerModule, MatIconModule],
|
||||
templateUrl: './guild-card.component.html',
|
||||
styleUrl: './guild-card.component.scss'
|
||||
styleUrl: './guild-card.component.scss',
|
||||
})
|
||||
export class GuildCardComponent implements OnInit {
|
||||
public guildData: HWGuildData = {} as HWGuildData;
|
||||
|
||||
+49
-36
@@ -23,21 +23,29 @@ export class StepperIntl extends MatStepperIntl {
|
||||
}
|
||||
@Component({
|
||||
selector: 'app-guildraids-log',
|
||||
standalone: true,
|
||||
providers: [
|
||||
{
|
||||
provide: STEPPER_GLOBAL_OPTIONS,
|
||||
useValue: {displayDefaultIndicatorType: false},
|
||||
provide: STEPPER_GLOBAL_OPTIONS,
|
||||
useValue: { displayDefaultIndicatorType: false },
|
||||
},
|
||||
],
|
||||
imports: [
|
||||
DatePipe, DecimalPipe, FormsModule, ReactiveFormsModule,
|
||||
MatButtonModule, MatCardModule, MatDatepickerModule, MatDividerModule,
|
||||
MatFormFieldModule, MatIconModule, MatInputModule, MatTooltipModule,
|
||||
MatStepperModule
|
||||
DatePipe,
|
||||
DecimalPipe,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
MatButtonModule,
|
||||
MatCardModule,
|
||||
MatDatepickerModule,
|
||||
MatDividerModule,
|
||||
MatFormFieldModule,
|
||||
MatIconModule,
|
||||
MatInputModule,
|
||||
MatTooltipModule,
|
||||
MatStepperModule,
|
||||
],
|
||||
templateUrl: './guildraids-log.component.html',
|
||||
styleUrl: './guildraids-log.component.scss'
|
||||
styleUrl: './guildraids-log.component.scss',
|
||||
})
|
||||
export class GuildraidsLogComponent implements OnInit {
|
||||
public now: Date;
|
||||
@@ -49,18 +57,16 @@ export class GuildraidsLogComponent implements OnInit {
|
||||
private _matStepperIntl = inject(MatStepperIntl);
|
||||
private _guildRaids: HWGuildRaid[] = [];
|
||||
private _raidStages: HWGuildRaidStage[] = [
|
||||
{num: 1, name: 'Stage 1', maxPower: 350000, duration: 8, startTime: 0, endTime: 0},
|
||||
{num: 2, name: 'Stage 2', maxPower: 550000, duration: 8, startTime: 0, endTime: 0},
|
||||
{num: 3, name: 'Stage 3', maxPower: 0, duration: 0, startTime: 0, endTime: 0}
|
||||
{ num: 1, name: 'Stage 1', maxPower: 350000, duration: 8, startTime: 0, endTime: 0 },
|
||||
{ num: 2, name: 'Stage 2', maxPower: 550000, duration: 8, startTime: 0, endTime: 0 },
|
||||
{ num: 3, name: 'Stage 3', maxPower: 0, duration: 0, startTime: 0, endTime: 0 },
|
||||
];
|
||||
|
||||
@Input() set members(value: HWMember[]) {
|
||||
this.guildMembers = value;
|
||||
}
|
||||
|
||||
constructor(
|
||||
private fb: FormBuilder
|
||||
) {
|
||||
constructor(private fb: FormBuilder) {
|
||||
this.now = new Date();
|
||||
const raidsDate = new Date();
|
||||
const startHour = 4;
|
||||
@@ -71,7 +77,7 @@ export class GuildraidsLogComponent implements OnInit {
|
||||
maxPower: 350,
|
||||
duration: 8,
|
||||
startTime: [raidsDate.getTime(), Validators.required],
|
||||
endTime: 0
|
||||
endTime: 0,
|
||||
};
|
||||
this.raidsForm = this.fb.group(controlsConfig);
|
||||
}
|
||||
@@ -82,11 +88,11 @@ export class GuildraidsLogComponent implements OnInit {
|
||||
raidsDate.setHours(startHour, 0, 0, 0);
|
||||
this._raidStages[0].startTime = raidsDate.getTime();
|
||||
|
||||
raidsDate.setHours((startHour + this._raidStages[0].duration), 0, 0, 0);
|
||||
raidsDate.setHours(startHour + this._raidStages[0].duration, 0, 0, 0);
|
||||
this._raidStages[0].endTime = raidsDate.getTime();
|
||||
this._raidStages[1].startTime = raidsDate.getTime();
|
||||
|
||||
raidsDate.setHours((startHour + this._raidStages[0].duration + this._raidStages[1].duration), 0, 0, 0);
|
||||
raidsDate.setHours(startHour + this._raidStages[0].duration + this._raidStages[1].duration, 0, 0, 0);
|
||||
this._raidStages[1].endTime = raidsDate.getTime();
|
||||
this._raidStages[2].startTime = raidsDate.getTime();
|
||||
|
||||
@@ -101,19 +107,19 @@ export class GuildraidsLogComponent implements OnInit {
|
||||
data.raids = [];
|
||||
data.raidsInfo = {
|
||||
variationAvg: 0,
|
||||
variationSum: 0
|
||||
variationSum: 0,
|
||||
};
|
||||
return data;
|
||||
});
|
||||
|
||||
for (const member of Object.entries(guildRaids)) {
|
||||
const index = this.guildMembers.findIndex(item => item.id === member[0]);
|
||||
const index = this.guildMembers.findIndex((item) => item.id === member[0]);
|
||||
const memberRaids: HWGuildRaid[] = [];
|
||||
if (index !== -1) {
|
||||
for (const data of Object.entries(member[1])) {
|
||||
const raid: HWGuildRaid = {} as HWGuildRaid;
|
||||
Object.assign(raid, data[1]);
|
||||
const startTime: number = (parseInt(raid.startTime) * 1000);
|
||||
const startTime: number = parseInt(raid.startTime) * 1000;
|
||||
if (this._guildRaids.length === 0) {
|
||||
this._setStagesTime(startTime);
|
||||
}
|
||||
@@ -139,14 +145,14 @@ export class GuildraidsLogComponent implements OnInit {
|
||||
const attacker: HWGuildRaidAttacker = {
|
||||
id: item[1].id,
|
||||
power: item[1].power,
|
||||
type: item[1].type
|
||||
type: item[1].type,
|
||||
} as HWGuildRaidAttacker;
|
||||
raid.power += attacker.power;
|
||||
raid.attackers.push(attacker);
|
||||
}
|
||||
let percent = 0;
|
||||
if (raid.stage.maxPower > 0) {
|
||||
percent = (((raid.power / raid.stage.maxPower) - 1) * 100);
|
||||
percent = (raid.power / raid.stage.maxPower - 1) * 100;
|
||||
}
|
||||
let color = 'default';
|
||||
let value = 0;
|
||||
@@ -158,12 +164,12 @@ export class GuildraidsLogComponent implements OnInit {
|
||||
} else if (percent > 5) {
|
||||
color = 'orange';
|
||||
}
|
||||
value = (raid.power - raid.stage.maxPower)
|
||||
value = raid.power - raid.stage.maxPower;
|
||||
}
|
||||
raid.variation = {
|
||||
value: value,
|
||||
percent: percent,
|
||||
color: color
|
||||
color: color,
|
||||
};
|
||||
raid.tooltip = Math.floor(raid.variation.value / 1000) + 'k';
|
||||
//console.log(raid.attackers);
|
||||
@@ -172,17 +178,24 @@ export class GuildraidsLogComponent implements OnInit {
|
||||
this._guildRaids.push(raid);
|
||||
}
|
||||
this.guildMembers[index].raids = memberRaids;
|
||||
const varSum = memberRaids.reduce((accumulator, currentValue) => accumulator + currentValue.variation.percent, 0);
|
||||
const varSum = memberRaids.reduce(
|
||||
(accumulator, currentValue) => accumulator + currentValue.variation.percent,
|
||||
0,
|
||||
);
|
||||
this.guildMembers[index].raidsInfo = {
|
||||
variationAvg: (varSum / memberRaids.length),
|
||||
variationSum: varSum
|
||||
variationAvg: varSum / memberRaids.length,
|
||||
variationSum: varSum,
|
||||
};
|
||||
}
|
||||
}
|
||||
this._guildRaids.sort((a, b) => (a.startTime < b.startTime ? -1 : 1)).map((data) => {
|
||||
return data;
|
||||
});
|
||||
this.guildMembers.sort((a, b) => (a.raidsInfo.variationAvg > b.raidsInfo.variationAvg ? -1 : 1));/*.map((data) => {
|
||||
this._guildRaids
|
||||
.sort((a, b) => (a.startTime < b.startTime ? -1 : 1))
|
||||
.map((data) => {
|
||||
return data;
|
||||
});
|
||||
this.guildMembers.sort((a, b) =>
|
||||
a.raidsInfo.variationAvg > b.raidsInfo.variationAvg ? -1 : 1,
|
||||
); /*.map((data) => {
|
||||
console.log(data.name, data.raidsInfo.variationAvg, data.raids.length);
|
||||
return data;
|
||||
});*/
|
||||
@@ -190,11 +203,13 @@ export class GuildraidsLogComponent implements OnInit {
|
||||
|
||||
public getMembers(): HWMember[] {
|
||||
//return this.guildMembers;
|
||||
return this.minVarPct ? this.guildMembers.filter(member => (member.raidsInfo.variationAvg >= this.minVarPct) === true) : this.guildMembers;
|
||||
return this.minVarPct
|
||||
? this.guildMembers.filter((member) => member.raidsInfo.variationAvg >= this.minVarPct === true)
|
||||
: this.guildMembers;
|
||||
}
|
||||
|
||||
public getRaidsLog(stageNum: number): HWGuildRaid[] {
|
||||
return this._guildRaids.filter(raid => (raid.stage.num === stageNum) === true);
|
||||
return this._guildRaids.filter((raid) => (raid.stage.num === stageNum) === true);
|
||||
}
|
||||
|
||||
public getStagesTime(stageNum: number): HWGuildRaidStage {
|
||||
@@ -208,7 +223,5 @@ export class GuildraidsLogComponent implements OnInit {
|
||||
}
|
||||
}
|
||||
|
||||
submitForm(): void {
|
||||
}
|
||||
|
||||
submitForm(): void {}
|
||||
}
|
||||
|
||||
+44
-42
@@ -6,26 +6,26 @@ import { MatIconModule } from '@angular/material/icon';
|
||||
|
||||
import { FortificationCardContentComponent } from '../fortification-card-content/fortification-card-content.component';
|
||||
import {
|
||||
HWGuildWarEnemySlot, HWGuildWarEnemyTeam, HWGuildWarFortification,
|
||||
HWGuildWarHeroTeam, HWGuildWarTitanTeam, HWGuildWarSlots, HWMember
|
||||
HWGuildWarEnemySlot,
|
||||
HWGuildWarEnemyTeam,
|
||||
HWGuildWarFortification,
|
||||
HWGuildWarHeroTeam,
|
||||
HWGuildWarTitanTeam,
|
||||
HWGuildWarSlots,
|
||||
HWMember,
|
||||
} from '@models';
|
||||
|
||||
/* JSON data */
|
||||
import guildWarData from 'src/files-data/hw-guild-war.json'; // page Overview -> Statistics | page Guild War -> Guild War
|
||||
import guildWarInfo from 'src/files-data/hw-guild-war-info.json'; // page Guild War -> Guild War
|
||||
import guildWarData from 'src/files-data/hw-guild-war.json'; // page Overview -> Statistics | page Guild War -> Guild War
|
||||
import guildWarInfo from 'src/files-data/hw-guild-war-info.json'; // page Guild War -> Guild War
|
||||
//import guildWarLog from 'src/files-data/hw-guild-war-log.json'; // page Guild War -> Guild War
|
||||
import guildWarSlots from 'src/files-data/hw-guild-war-slots.json'; // no pages
|
||||
|
||||
@Component({
|
||||
selector: 'app-guildwar-attack',
|
||||
standalone: true,
|
||||
imports: [
|
||||
DatePipe, DecimalPipe,
|
||||
MatCardModule, MatDividerModule, MatIconModule,
|
||||
FortificationCardContentComponent
|
||||
],
|
||||
imports: [DatePipe, DecimalPipe, MatCardModule, MatDividerModule, MatIconModule, FortificationCardContentComponent],
|
||||
templateUrl: './guildwar-attack.component.html',
|
||||
styleUrl: './guildwar-attack.component.scss'
|
||||
styleUrl: './guildwar-attack.component.scss',
|
||||
})
|
||||
export class GuildwarAttackComponent implements OnInit {
|
||||
private _championsByPower: HWMember[] = [];
|
||||
@@ -35,13 +35,14 @@ export class GuildwarAttackComponent implements OnInit {
|
||||
public title = 'Fortifications';
|
||||
public subtitle = 'Guild War Attack';
|
||||
public now = new Date();
|
||||
public warInfo: { day: number, clanEnemyName: string, endTime: number, nextWarTime: number, nextLockTime: number } = {
|
||||
day: 0,
|
||||
clanEnemyName: '',
|
||||
endTime: 0,
|
||||
nextWarTime: 0,
|
||||
nextLockTime: 0
|
||||
};
|
||||
public warInfo: { day: number; clanEnemyName: string; endTime: number; nextWarTime: number; nextLockTime: number } =
|
||||
{
|
||||
day: 0,
|
||||
clanEnemyName: '',
|
||||
endTime: 0,
|
||||
nextWarTime: 0,
|
||||
nextLockTime: 0,
|
||||
};
|
||||
|
||||
@Input() set members(value: HWMember[]) {
|
||||
this.guildMembers = value;
|
||||
@@ -50,9 +51,9 @@ export class GuildwarAttackComponent implements OnInit {
|
||||
ngOnInit() {
|
||||
this.warInfo.day = parseInt(guildWarInfo.day);
|
||||
this.warInfo.clanEnemyName = guildWarInfo.enemyClan.title;
|
||||
this.warInfo.endTime = (guildWarInfo.endTime * 1000);
|
||||
this.warInfo.nextWarTime = (guildWarInfo.nextWarTime * 1000);
|
||||
this.warInfo.nextLockTime = (guildWarInfo.nextLockTime * 1000);
|
||||
this.warInfo.endTime = guildWarInfo.endTime * 1000;
|
||||
this.warInfo.nextWarTime = guildWarInfo.nextWarTime * 1000;
|
||||
this.warInfo.nextLockTime = guildWarInfo.nextLockTime * 1000;
|
||||
this._setChampionsByPower();
|
||||
this._setEnemies();
|
||||
}
|
||||
@@ -81,7 +82,7 @@ export class GuildwarAttackComponent implements OnInit {
|
||||
count: count,
|
||||
teams: teams,
|
||||
positions: this._enemySlots,
|
||||
slots: slots[name]
|
||||
slots: slots[name],
|
||||
};
|
||||
}
|
||||
|
||||
@@ -89,10 +90,10 @@ export class GuildwarAttackComponent implements OnInit {
|
||||
const teams: HWMember[] = [];
|
||||
const slots: HWGuildWarSlots = guildWarSlots.slots;
|
||||
let count = 0;
|
||||
slots[name].forEach(slot => {
|
||||
slots[name].forEach((slot) => {
|
||||
let enemies: HWMember[] = [];
|
||||
let team: HWMember = {} as HWMember;
|
||||
enemies = this.guildEnemies.filter(enemy => parseInt(enemy.id) === this._enemySlots[slot]);
|
||||
enemies = this.guildEnemies.filter((enemy) => parseInt(enemy.id) === this._enemySlots[slot]);
|
||||
if (enemies.length) {
|
||||
team = enemies[0];
|
||||
teams.push(team);
|
||||
@@ -115,7 +116,7 @@ export class GuildwarAttackComponent implements OnInit {
|
||||
count: count,
|
||||
teams: teams,
|
||||
positions: this._enemySlots,
|
||||
slots: slots[name]
|
||||
slots: slots[name],
|
||||
};
|
||||
}
|
||||
|
||||
@@ -125,21 +126,21 @@ export class GuildwarAttackComponent implements OnInit {
|
||||
warriors.push(parseInt(data[0]));
|
||||
}
|
||||
for (const data of Object.entries(guildWarInfo.enemyClanMembers)) {
|
||||
const enemy: HWMember = {} as HWMember;
|
||||
Object.assign(enemy, data[1]);
|
||||
if (warriors.indexOf(parseInt(enemy.id)) !== -1) {
|
||||
enemy.champion = true;
|
||||
} else {
|
||||
enemy.champion = false;
|
||||
}
|
||||
enemy.heroes = { power: 0, teams: []};
|
||||
enemy.titans = { power: 0, teams: []};
|
||||
const enemy: HWMember = {} as HWMember;
|
||||
Object.assign(enemy, data[1]);
|
||||
if (warriors.indexOf(parseInt(enemy.id)) !== -1) {
|
||||
enemy.champion = true;
|
||||
} else {
|
||||
enemy.champion = false;
|
||||
}
|
||||
enemy.heroes = { power: 0, teams: [] };
|
||||
enemy.titans = { power: 0, teams: [] };
|
||||
|
||||
//console.log(guildWarInfo.enemySlots);
|
||||
//console.log(guildWarInfo.enemySlots);
|
||||
|
||||
this.guildEnemies.push(enemy);
|
||||
this.guildEnemies.push(enemy);
|
||||
}
|
||||
|
||||
|
||||
for (const data of Object.entries(guildWarInfo.enemySlots)) {
|
||||
const ennemySlot: HWGuildWarEnemySlot = {} as HWGuildWarEnemySlot;
|
||||
Object.assign(ennemySlot, data[1]);
|
||||
@@ -187,13 +188,15 @@ export class GuildwarAttackComponent implements OnInit {
|
||||
return false;
|
||||
});
|
||||
}
|
||||
this.guildEnemies.sort((a, b) => ((a.heroes.power + a.titans.power) > (b.heroes.power + b.titans.power) ? -1 : 1)); // Descending
|
||||
this.guildEnemies.sort((a, b) =>
|
||||
a.heroes.power + a.titans.power > b.heroes.power + b.titans.power ? -1 : 1,
|
||||
); // Descending
|
||||
}
|
||||
}
|
||||
|
||||
private _setChampionsByPower(): void {
|
||||
for (const [teamId, teamValues] of Object.entries(guildWarData.teams)) {
|
||||
const index = this.guildMembers.findIndex(member => member.id === teamId);
|
||||
const index = this.guildMembers.findIndex((member) => member.id === teamId);
|
||||
if (index === -1) continue;
|
||||
let totalHeroPower = 0;
|
||||
let totalTitanPower = 0;
|
||||
@@ -211,8 +214,8 @@ export class GuildwarAttackComponent implements OnInit {
|
||||
this.guildMembers[index].heroes = { power: totalHeroPower, teams: heroes };
|
||||
this.guildMembers[index].titans = { power: totalTitanPower, teams: titans };
|
||||
}
|
||||
this.guildMembers.sort((a, b) => ((a.heroes.power + a.titans.power) > (b.heroes.power + b.titans.power) ? -1 : 1)); // Descending
|
||||
this._championsByPower = this.guildMembers.filter(member => member.champion === true);
|
||||
this.guildMembers.sort((a, b) => (a.heroes.power + a.titans.power > b.heroes.power + b.titans.power ? -1 : 1)); // Descending
|
||||
this._championsByPower = this.guildMembers.filter((member) => member.champion === true);
|
||||
}
|
||||
|
||||
getEnemies(): HWMember[] {
|
||||
@@ -282,5 +285,4 @@ export class GuildwarAttackComponent implements OnInit {
|
||||
//return this._getFortification(indexes, 'titans', 'Spring Of Elements');
|
||||
return this._getDefense('titans', 'Spring Of Elements');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+4
-8
@@ -9,13 +9,9 @@ import { HWMember } from '@models';
|
||||
|
||||
@Component({
|
||||
selector: 'app-guildwar-champions',
|
||||
standalone: true,
|
||||
imports: [
|
||||
DecimalPipe,
|
||||
MatCardModule, MatDividerModule, MatIconModule
|
||||
],
|
||||
imports: [DecimalPipe, MatCardModule, MatDividerModule, MatIconModule],
|
||||
templateUrl: './guildwar-champions.component.html',
|
||||
styleUrl: './guildwar-champions.component.scss'
|
||||
styleUrl: './guildwar-champions.component.scss',
|
||||
})
|
||||
export class GuildwarChampionsComponent implements OnInit {
|
||||
private _championsByPower: HWMember[] = [];
|
||||
@@ -39,13 +35,13 @@ export class GuildwarChampionsComponent implements OnInit {
|
||||
this.color = 'navy';
|
||||
this.subtitle = 'heroes power';
|
||||
this.guildMembers.sort((a, b) => (a.heroes.power > b.heroes.power ? -1 : 1)); // Descending
|
||||
this._championsByPower = this.guildMembers.filter(member => member.champion === true);
|
||||
this._championsByPower = this.guildMembers.filter((member) => member.champion === true);
|
||||
break;
|
||||
case 'titans':
|
||||
this.color = 'purple';
|
||||
this.subtitle = 'titans power';
|
||||
this.guildMembers.sort((a, b) => (a.titans.power > b.titans.power ? -1 : 1)); // Descending
|
||||
this._championsByPower = this.guildMembers.filter(member => member.champion === true);
|
||||
this._championsByPower = this.guildMembers.filter((member) => member.champion === true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
+6
-10
@@ -9,18 +9,14 @@ import { FortificationCardContentComponent } from '../fortification-card-content
|
||||
import { HWGuildWarFortification, HWGuildWarHeroTeam, HWGuildWarSlots, HWGuildWarTitanTeam, HWMember } from '@models';
|
||||
|
||||
/* JSON data */
|
||||
import guildWarData from 'src/files-data/hw-guild-war.json'; // page Overview -> Statistics | page Guild War -> Guild War
|
||||
import guildWarData from 'src/files-data/hw-guild-war.json'; // page Overview -> Statistics | page Guild War -> Guild War
|
||||
import guildWarSlots from 'src/files-data/hw-guild-war-slots.json'; // no pages
|
||||
|
||||
@Component({
|
||||
selector: 'app-guildwar-defence',
|
||||
standalone: true,
|
||||
imports: [
|
||||
MatCardModule, MatDividerModule, MatIconModule,
|
||||
FortificationCardContentComponent
|
||||
],
|
||||
imports: [MatCardModule, MatDividerModule, MatIconModule, FortificationCardContentComponent],
|
||||
templateUrl: './guildwar-defence.component.html',
|
||||
styleUrl: './guildwar-defence.component.scss'
|
||||
styleUrl: './guildwar-defence.component.scss',
|
||||
})
|
||||
export class GuildwarDefenceComponent implements OnInit {
|
||||
private _championsByPower: HWMember[] = [];
|
||||
@@ -40,7 +36,7 @@ export class GuildwarDefenceComponent implements OnInit {
|
||||
|
||||
ngOnInit() {
|
||||
for (const [teamId, teamValues] of Object.entries(guildWarData.teams)) {
|
||||
const index = this.guildMembers.findIndex(member => member.id === teamId);
|
||||
const index = this.guildMembers.findIndex((member) => member.id === teamId);
|
||||
if (index === -1) continue;
|
||||
let totalHeroPower = 0;
|
||||
let totalTitanPower = 0;
|
||||
@@ -75,7 +71,7 @@ export class GuildwarDefenceComponent implements OnInit {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
this._championsByPower = this.guildMembers.filter(member => member.champion === true);
|
||||
this._championsByPower = this.guildMembers.filter((member) => member.champion === true);
|
||||
}
|
||||
|
||||
private _getFortification(indexes: number[], type: string, name: string): HWGuildWarFortification {
|
||||
@@ -104,7 +100,7 @@ export class GuildwarDefenceComponent implements OnInit {
|
||||
count: count,
|
||||
teams: teams,
|
||||
positions: this._championSlots,
|
||||
slots: slots[name]
|
||||
slots: slots[name],
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
+10
-13
@@ -10,13 +10,9 @@ import guildWarData from 'src/files-data/hw-guild-war.json'; // page Overview ->
|
||||
|
||||
@Component({
|
||||
selector: 'app-guildwar-teams',
|
||||
standalone: true,
|
||||
imports: [
|
||||
DecimalPipe,
|
||||
MatCardModule, MatDividerModule, MatIconModule
|
||||
],
|
||||
imports: [DecimalPipe, MatCardModule, MatDividerModule, MatIconModule],
|
||||
templateUrl: './guildwar-teams.component.html',
|
||||
styleUrl: './guildwar-teams.component.scss'
|
||||
styleUrl: './guildwar-teams.component.scss',
|
||||
})
|
||||
export class GuildwarTeamsComponent implements OnInit {
|
||||
private _championsByPower: HWMember[] = [];
|
||||
@@ -33,8 +29,8 @@ export class GuildwarTeamsComponent implements OnInit {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
|
||||
this.guildMembers.sort((a, b) => (((a.heroes.power + a.titans.power) / 2) > ((b.heroes.power + b.titans.power) / 2) ? -1 : 1))
|
||||
this.guildMembers
|
||||
.sort((a, b) => ((a.heroes.power + a.titans.power) / 2 > (b.heroes.power + b.titans.power) / 2 ? -1 : 1))
|
||||
.map((data) => {
|
||||
/*
|
||||
this.guildTotalHeroesPower += data.heroes.power;
|
||||
@@ -47,7 +43,7 @@ export class GuildwarTeamsComponent implements OnInit {
|
||||
});
|
||||
|
||||
for (const [teamId, teamValues] of Object.entries(guildWarData.teams)) {
|
||||
const index = this._championsByPower.findIndex(member => member.id === teamId);
|
||||
const index = this._championsByPower.findIndex((member) => member.id === teamId);
|
||||
if (index === -1) continue;
|
||||
let totalHeroPower = 0;
|
||||
let totalTitanPower = 0;
|
||||
@@ -66,14 +62,15 @@ export class GuildwarTeamsComponent implements OnInit {
|
||||
this._championsByPower[index].titans = { power: totalTitanPower, teams: titans };
|
||||
this.guildTotalHeroesPower += totalHeroPower;
|
||||
this.guildTotalTitansPower += totalTitanPower;
|
||||
this._championsByPower[index].rewards = Math.floor((this._championsByPower[index].scoreGifts + this._championsByPower[index].warGifts));
|
||||
this._championsByPower[index].rewards = Math.floor(
|
||||
this._championsByPower[index].scoreGifts + this._championsByPower[index].warGifts,
|
||||
);
|
||||
}
|
||||
this.guildAverageHeroesPower = Math.floor((this.guildTotalHeroesPower / this._championsByPower.length));
|
||||
this.guildAverageTitansPower = Math.floor((this.guildTotalTitansPower / this._championsByPower.length));
|
||||
this.guildAverageHeroesPower = Math.floor(this.guildTotalHeroesPower / this._championsByPower.length);
|
||||
this.guildAverageTitansPower = Math.floor(this.guildTotalTitansPower / this._championsByPower.length);
|
||||
}
|
||||
|
||||
getChampionsByPower(): HWMember[] {
|
||||
return this._championsByPower;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+120
-62
@@ -7,76 +7,128 @@ import { MatIconModule } from '@angular/material/icon';
|
||||
import { HWActivityStat, HWGuildClan, HWGuildData, HWMember, HWMemberStat, HWWeekStat } from '@models/herowars';
|
||||
import { UtilitiesService } from '@services';
|
||||
|
||||
import guildData from 'src/files-data/hw-guild-data.json'; // page Membres
|
||||
import guildData from 'src/files-data/hw-guild-data.json'; // page Membres
|
||||
import guildStatistics from 'src/files-data/hw-guild-statistics.json'; // page Overview -> Statistics
|
||||
|
||||
@Component({
|
||||
selector: 'app-members-statistics',
|
||||
standalone: true,
|
||||
imports: [
|
||||
DatePipe, DecimalPipe,
|
||||
MatCardModule, MatDividerModule, MatIconModule
|
||||
],
|
||||
imports: [DatePipe, DecimalPipe, MatCardModule, MatDividerModule, MatIconModule],
|
||||
templateUrl: './members-statistics.component.html',
|
||||
styleUrl: './members-statistics.component.scss'
|
||||
styleUrl: './members-statistics.component.scss',
|
||||
})
|
||||
export class MembersStatisticsComponent implements OnInit {
|
||||
public guildMembers: HWMember[] = [];
|
||||
public title = 'Members';
|
||||
public subtitle = 'statistics';
|
||||
public daysToWarn = 1;
|
||||
public guildSumAverages: HWActivityStat = { activity: 0, prestige: 0, titanite: 0, war: 0, adventure: 0, gifts: 0, score: 0, scoreGifts: 0, warGifts: 0, rewards: 0 };
|
||||
public guildTodayAverages: HWActivityStat = { activity: 0, prestige: 0, titanite: 0, war: 0, adventure: 0, gifts: 0, score: 0, scoreGifts: 0, warGifts: 0, rewards: 0 };
|
||||
public guildSumTotal: HWActivityStat = { activity: 0, prestige: 0, titanite: 0, war: 0, adventure: 0, gifts: 0, score: 0, scoreGifts: 0, warGifts: 0, rewards: 0 };
|
||||
public guildTodayTotal: HWActivityStat = { activity: 0, prestige: 0, titanite: 0, war: 0, adventure: 0, gifts: 0, score: 0, scoreGifts: 0, warGifts: 0, rewards: 0 };
|
||||
public guildSumAverages: HWActivityStat = {
|
||||
activity: 0,
|
||||
prestige: 0,
|
||||
titanite: 0,
|
||||
war: 0,
|
||||
adventure: 0,
|
||||
gifts: 0,
|
||||
score: 0,
|
||||
scoreGifts: 0,
|
||||
warGifts: 0,
|
||||
rewards: 0,
|
||||
};
|
||||
public guildTodayAverages: HWActivityStat = {
|
||||
activity: 0,
|
||||
prestige: 0,
|
||||
titanite: 0,
|
||||
war: 0,
|
||||
adventure: 0,
|
||||
gifts: 0,
|
||||
score: 0,
|
||||
scoreGifts: 0,
|
||||
warGifts: 0,
|
||||
rewards: 0,
|
||||
};
|
||||
public guildSumTotal: HWActivityStat = {
|
||||
activity: 0,
|
||||
prestige: 0,
|
||||
titanite: 0,
|
||||
war: 0,
|
||||
adventure: 0,
|
||||
gifts: 0,
|
||||
score: 0,
|
||||
scoreGifts: 0,
|
||||
warGifts: 0,
|
||||
rewards: 0,
|
||||
};
|
||||
public guildTodayTotal: HWActivityStat = {
|
||||
activity: 0,
|
||||
prestige: 0,
|
||||
titanite: 0,
|
||||
war: 0,
|
||||
adventure: 0,
|
||||
gifts: 0,
|
||||
score: 0,
|
||||
scoreGifts: 0,
|
||||
warGifts: 0,
|
||||
rewards: 0,
|
||||
};
|
||||
public guildData: HWGuildData = {} as HWGuildData;
|
||||
private _guildClan: HWGuildClan = {} as HWGuildClan;
|
||||
private _membersByName: HWMember[] = [];
|
||||
private _deviations: { activity: number[], prestige: number[], titanite: number[] } = { activity: [], prestige: [], titanite: [] };
|
||||
private _deviations: { activity: number[]; prestige: number[]; titanite: number[] } = {
|
||||
activity: [],
|
||||
prestige: [],
|
||||
titanite: [],
|
||||
};
|
||||
|
||||
@Input() set members(value: HWMember[]) {
|
||||
this.guildMembers = value;
|
||||
}
|
||||
|
||||
constructor(
|
||||
private _utilitiesService: UtilitiesService
|
||||
) { }
|
||||
|
||||
constructor(private _utilitiesService: UtilitiesService) {}
|
||||
|
||||
ngOnInit() {
|
||||
|
||||
const oneDayInSec = (24 * 60 * 60);
|
||||
const oneDayInSec = 24 * 60 * 60;
|
||||
const today = new Date();
|
||||
const daysToKick = parseInt(guildData.clan.daysToKick);
|
||||
this.daysToWarn = (parseInt(guildData.clan.daysToKick) / 2);
|
||||
this.guildMembers.sort((a, b) => (a.name.toLowerCase() < b.name.toLowerCase() ? -1 : 1)).map((data) => {
|
||||
const last = new Date((parseInt(data.lastLoginTime) * 1000));
|
||||
const exp = new Date(last.getTime() + ((daysToKick * oneDayInSec) * 1000));
|
||||
const diff = Math.floor(((exp.getTime() - today.getTime()) / 1000));
|
||||
const daysLeft = Math.floor((diff / oneDayInSec));
|
||||
let timeLeft = diff;
|
||||
if (daysLeft >= 1) {
|
||||
timeLeft = (diff - (daysLeft * oneDayInSec));
|
||||
}
|
||||
data.inactivity = {
|
||||
daysLeft: daysLeft,
|
||||
timeLeft: timeLeft,
|
||||
dropDelay: `${daysLeft}d, ${this._utilitiesService.secondsToDuration(timeLeft)}`,
|
||||
dropDate: Math.floor((exp.getTime() / 1000))
|
||||
};
|
||||
this._membersByName.push(data);
|
||||
return data;
|
||||
});
|
||||
this.daysToWarn = parseInt(guildData.clan.daysToKick) / 2;
|
||||
this.guildMembers
|
||||
.sort((a, b) => (a.name.toLowerCase() < b.name.toLowerCase() ? -1 : 1))
|
||||
.map((data) => {
|
||||
const last = new Date(parseInt(data.lastLoginTime) * 1000);
|
||||
const exp = new Date(last.getTime() + daysToKick * oneDayInSec * 1000);
|
||||
const diff = Math.floor((exp.getTime() - today.getTime()) / 1000);
|
||||
const daysLeft = Math.floor(diff / oneDayInSec);
|
||||
let timeLeft = diff;
|
||||
if (daysLeft >= 1) {
|
||||
timeLeft = diff - daysLeft * oneDayInSec;
|
||||
}
|
||||
data.inactivity = {
|
||||
daysLeft: daysLeft,
|
||||
timeLeft: timeLeft,
|
||||
dropDelay: `${daysLeft}d, ${this._utilitiesService.secondsToDuration(timeLeft)}`,
|
||||
dropDate: Math.floor(exp.getTime() / 1000),
|
||||
};
|
||||
this._membersByName.push(data);
|
||||
return data;
|
||||
});
|
||||
|
||||
Object.assign(this._guildClan, guildData.clan);
|
||||
this.guildData.clan = this._guildClan;
|
||||
this.guildData.membersStat = guildData.membersStat;
|
||||
|
||||
for (const item of Object.entries(guildStatistics.stat)) {
|
||||
const index = this._membersByName.findIndex(member => member.id === item[1].id);
|
||||
const index = this._membersByName.findIndex((member) => member.id === item[1].id);
|
||||
if (index !== -1) {
|
||||
this._membersByName[index].adventureSum = item[1].adventureStat.reduce((accumulator, currentValue) => accumulator + currentValue, 0);
|
||||
this._membersByName[index].clanGiftsSum = item[1].clanGifts.reduce((accumulator, currentValue) => accumulator + currentValue, 0);
|
||||
this._membersByName[index].clanWarSum = item[1].clanWarStat.reduce((accumulator, currentValue) => accumulator + currentValue, 0);
|
||||
this._membersByName[index].adventureSum = item[1].adventureStat.reduce(
|
||||
(accumulator, currentValue) => accumulator + currentValue,
|
||||
0,
|
||||
);
|
||||
this._membersByName[index].clanGiftsSum = item[1].clanGifts.reduce(
|
||||
(accumulator, currentValue) => accumulator + currentValue,
|
||||
0,
|
||||
);
|
||||
this._membersByName[index].clanWarSum = item[1].clanWarStat.reduce(
|
||||
(accumulator, currentValue) => accumulator + currentValue,
|
||||
0,
|
||||
);
|
||||
this.guildSumTotal.adventure += this._membersByName[index].adventureSum;
|
||||
this.guildSumTotal.gifts += this._membersByName[index].clanGiftsSum;
|
||||
this.guildSumTotal.war += this._membersByName[index].clanWarSum;
|
||||
@@ -91,19 +143,26 @@ export class MembersStatisticsComponent implements OnInit {
|
||||
for (const data of Object.entries(guildData.membersStat)) {
|
||||
const stat: HWMemberStat = {} as HWMemberStat;
|
||||
Object.assign(stat, data[1]);
|
||||
const index = this._membersByName.findIndex(member => member.id === data[1].userId);
|
||||
const index = this._membersByName.findIndex((member) => member.id === data[1].userId);
|
||||
if (index !== -1) {
|
||||
this._membersByName[index].stat = stat;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
this._membersByName[index].score = (this._membersByName[index].stat.dungeonActivitySum + this._membersByName[index].stat.activitySum + this._membersByName[index].stat.prestigeSum);
|
||||
this._membersByName[index].warGifts = (((guildData.clan.giftsCount / 2) * ((this._membersByName[index].clanWarSum * 10) / 100)) / 20);
|
||||
this._membersByName[index].score =
|
||||
this._membersByName[index].stat.dungeonActivitySum +
|
||||
this._membersByName[index].stat.activitySum +
|
||||
this._membersByName[index].stat.prestigeSum;
|
||||
this._membersByName[index].warGifts =
|
||||
((guildData.clan.giftsCount / 2) * ((this._membersByName[index].clanWarSum * 10) / 100)) / 20;
|
||||
|
||||
this.guildTodayTotal.activity += stat.todayActivity;
|
||||
this.guildTodayTotal.prestige += stat.todayPrestige;
|
||||
this.guildTodayTotal.titanite += stat.todayDungeonActivity;
|
||||
this.guildTodayTotal.score += (this._membersByName[index].stat.todayDungeonActivity + this._membersByName[index].stat.todayActivity + this._membersByName[index].stat.todayPrestige);
|
||||
this.guildTodayTotal.score +=
|
||||
this._membersByName[index].stat.todayDungeonActivity +
|
||||
this._membersByName[index].stat.todayActivity +
|
||||
this._membersByName[index].stat.todayPrestige;
|
||||
this.guildSumTotal.activity += stat.activitySum;
|
||||
this.guildSumTotal.prestige += stat.prestigeSum;
|
||||
this.guildSumTotal.titanite += stat.dungeonActivitySum;
|
||||
@@ -114,26 +173,26 @@ export class MembersStatisticsComponent implements OnInit {
|
||||
this._deviations.titanite.push(stat.dungeonActivitySum);
|
||||
//this.guildSumTotal.warGifts += ((this._membersByName[index].score / this.guildSumTotal.score) * (guildData.clan.giftsCount / 2))
|
||||
}
|
||||
this.guildSumTotal.scoreGifts = (guildData.clan.giftsCount - Math.floor(this.guildSumTotal.warGifts));
|
||||
this.guildTodayAverages.activity = (this.guildTodayTotal.activity / this._membersByName.length);
|
||||
this.guildTodayAverages.prestige = (this.guildTodayTotal.prestige / this._membersByName.length);
|
||||
this.guildTodayAverages.titanite = (this.guildTodayTotal.titanite / this._membersByName.length);
|
||||
this.guildTodayAverages.score = (this.guildTodayTotal.score / this._membersByName.length);
|
||||
this.guildSumAverages.activity = (this.guildSumTotal.activity / this._membersByName.length);
|
||||
this.guildSumAverages.prestige = (this.guildSumTotal.prestige / this._membersByName.length);
|
||||
this.guildSumAverages.titanite = (this.guildSumTotal.titanite / this._membersByName.length);
|
||||
this.guildSumAverages.war = (this.guildSumTotal.war / 20);
|
||||
this.guildSumAverages.adventure = (this.guildSumTotal.adventure / this._membersByName.length);
|
||||
this.guildSumAverages.gifts = (this.guildSumTotal.gifts / this._membersByName.length);
|
||||
this.guildSumAverages.score = (this.guildSumTotal.score / this._membersByName.length);
|
||||
this.guildSumTotal.scoreGifts = guildData.clan.giftsCount - Math.floor(this.guildSumTotal.warGifts);
|
||||
this.guildTodayAverages.activity = this.guildTodayTotal.activity / this._membersByName.length;
|
||||
this.guildTodayAverages.prestige = this.guildTodayTotal.prestige / this._membersByName.length;
|
||||
this.guildTodayAverages.titanite = this.guildTodayTotal.titanite / this._membersByName.length;
|
||||
this.guildTodayAverages.score = this.guildTodayTotal.score / this._membersByName.length;
|
||||
this.guildSumAverages.activity = this.guildSumTotal.activity / this._membersByName.length;
|
||||
this.guildSumAverages.prestige = this.guildSumTotal.prestige / this._membersByName.length;
|
||||
this.guildSumAverages.titanite = this.guildSumTotal.titanite / this._membersByName.length;
|
||||
this.guildSumAverages.war = this.guildSumTotal.war / 20;
|
||||
this.guildSumAverages.adventure = this.guildSumTotal.adventure / this._membersByName.length;
|
||||
this.guildSumAverages.gifts = this.guildSumTotal.gifts / this._membersByName.length;
|
||||
this.guildSumAverages.score = this.guildSumTotal.score / this._membersByName.length;
|
||||
|
||||
this._membersByName.map((data) => {
|
||||
data.scoreGifts = ((data.score / this.guildSumTotal.score) * this.guildSumTotal.scoreGifts);
|
||||
data.rewards = Math.floor((data.scoreGifts + data.warGifts));
|
||||
data.scoreGifts = (data.score / this.guildSumTotal.score) * this.guildSumTotal.scoreGifts;
|
||||
data.rewards = Math.floor(data.scoreGifts + data.warGifts);
|
||||
this.guildSumTotal.rewards += data.rewards;
|
||||
return data;
|
||||
});
|
||||
this.guildSumAverages.rewards = (this.guildSumTotal.rewards / this._membersByName.length);
|
||||
this.guildSumAverages.rewards = this.guildSumTotal.rewards / this._membersByName.length;
|
||||
}
|
||||
|
||||
getMembersByName(): HWMember[] {
|
||||
@@ -143,7 +202,7 @@ export class MembersStatisticsComponent implements OnInit {
|
||||
private _standardDeviation(array: number[]): number {
|
||||
const n = array.length;
|
||||
const mean = array.reduce((a, b) => a + b) / n;
|
||||
return Math.sqrt(array.map(x => Math.pow(x - mean, 2)).reduce((a, b) => a + b) / n);
|
||||
return Math.sqrt(array.map((x) => Math.pow(x - mean, 2)).reduce((a, b) => a + b) / n);
|
||||
}
|
||||
|
||||
getStandardDeviationActivity(): number {
|
||||
@@ -157,5 +216,4 @@ export class MembersStatisticsComponent implements OnInit {
|
||||
getStandardDeviationTitanite(): number {
|
||||
return this._standardDeviation(this._deviations.titanite);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,8 +4,7 @@ import { DatePipe } from '@angular/common';
|
||||
@Component({
|
||||
selector: 'app-layout-footer',
|
||||
templateUrl: './footer.component.html',
|
||||
standalone: true,
|
||||
imports: [ DatePipe ]
|
||||
imports: [DatePipe],
|
||||
})
|
||||
export class FooterComponent {
|
||||
today: number = Date.now();
|
||||
|
||||
@@ -1,116 +1,126 @@
|
||||
import { Component, OnInit, OnDestroy, ChangeDetectorRef } from '@angular/core';
|
||||
import { Router, RouterOutlet, RouterModule } from '@angular/router';
|
||||
import { MediaMatcher } from '@angular/cdk/layout';
|
||||
import { MatBadgeModule } from '@angular/material/badge';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatDividerModule } from '@angular/material/divider';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatListModule } from '@angular/material/list';
|
||||
import { MatSidenavModule } from '@angular/material/sidenav';
|
||||
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||
import { MatMenuModule } from '@angular/material/menu';
|
||||
import { Observable, Subscription } from 'rxjs';
|
||||
|
||||
import { Menu, User } from '@models';
|
||||
import { UserService } from '@services';
|
||||
import { MenuItems, ShowAuthedDirective, AccordionAnchorDirective, AccordionLinkDirective, AccordionDirective } from '@components/shared';
|
||||
//import { SpinnerComponent } from '@components/shared';
|
||||
//import { HeaderComponent, FooterComponent } from '@components/shared/layout';
|
||||
import { FooterComponent } from '@components/shared/layout';
|
||||
|
||||
|
||||
/** @title Responsive sidenav */
|
||||
@Component({
|
||||
selector: 'app-full-layout',
|
||||
standalone: true,
|
||||
imports: [
|
||||
RouterModule, RouterOutlet,
|
||||
MatBadgeModule, MatButtonModule, MatDividerModule,
|
||||
MatIconModule, MatListModule, MatMenuModule,
|
||||
MatSidenavModule, MatToolbarModule,
|
||||
ShowAuthedDirective, AccordionAnchorDirective,
|
||||
AccordionLinkDirective, AccordionDirective,
|
||||
FooterComponent
|
||||
//HeaderComponent,
|
||||
//SpinnerComponent
|
||||
],
|
||||
providers: [ MenuItems ],
|
||||
templateUrl: 'full.component.html',
|
||||
styleUrls: []
|
||||
})
|
||||
export class FullComponent implements OnInit, OnDestroy {
|
||||
private _currentUser: Subscription = new Subscription();
|
||||
private _mobileQueryListener: () => void;
|
||||
mobileQuery: MediaQueryList;
|
||||
currentUser: User = {} as User;
|
||||
today: number = Date.now();
|
||||
siteLink = 'https://www.adastra-cbd.com';
|
||||
author = 'Ad Astra';
|
||||
links: Menu[] = [];
|
||||
visibleMenu: string[] = [];
|
||||
//visibleMenu: string[] = ['products', 'page'];
|
||||
//visibleMenu: string[] = ['products'];
|
||||
|
||||
constructor(
|
||||
private router: Router,
|
||||
private userService: UserService,
|
||||
changeDetectorRef: ChangeDetectorRef,
|
||||
media: MediaMatcher,
|
||||
public menuItems: MenuItems
|
||||
) {
|
||||
this.mobileQuery = media.matchMedia('(min-width: 768px)');
|
||||
this._mobileQueryListener = () => changeDetectorRef.detectChanges();
|
||||
this.mobileQuery.addListener(this._mobileQueryListener);
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
const user$: Observable<User> = this.userService.currentUser;
|
||||
this._currentUser = user$.subscribe(
|
||||
(userData) => {
|
||||
this.currentUser = userData;
|
||||
if (this.currentUser.role === 'Admin') {
|
||||
this.links = this.menuItems.getMenuItemsAdmin();
|
||||
//this.links = this.menuItems.getMenuItems();
|
||||
} else {
|
||||
this.links = this.menuItems.getMenuItems();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
getMenuItems(): Menu[] {
|
||||
return this.links;
|
||||
}
|
||||
|
||||
isVisibleMenu(state: string): boolean {
|
||||
const indexOf: number = this.visibleMenu.indexOf(state);
|
||||
if (indexOf !== -1) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this._currentUser.unsubscribe();
|
||||
this.mobileQuery.removeListener(this._mobileQueryListener);
|
||||
}
|
||||
|
||||
goToGitHub() {
|
||||
window.open('https://github.com/rampeur', '_blank');
|
||||
}
|
||||
|
||||
toggleShowMenu(state: string) {
|
||||
const indexOf: number = this.visibleMenu.indexOf(state);
|
||||
if (indexOf !== -1) {
|
||||
this.visibleMenu.splice(indexOf, 1);
|
||||
} else {
|
||||
this.visibleMenu.push(state);
|
||||
}
|
||||
}
|
||||
|
||||
logout() {
|
||||
this.userService.purgeAuth();
|
||||
this.router.navigateByUrl('/login');
|
||||
}
|
||||
}
|
||||
import { Component, OnInit, OnDestroy, ChangeDetectorRef } from '@angular/core';
|
||||
import { Router, RouterOutlet, RouterModule } from '@angular/router';
|
||||
import { MediaMatcher } from '@angular/cdk/layout';
|
||||
import { MatBadgeModule } from '@angular/material/badge';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatDividerModule } from '@angular/material/divider';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatListModule } from '@angular/material/list';
|
||||
import { MatSidenavModule } from '@angular/material/sidenav';
|
||||
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||
import { MatMenuModule } from '@angular/material/menu';
|
||||
import { Observable, Subscription } from 'rxjs';
|
||||
|
||||
import { Menu, User } from '@models';
|
||||
import { UserService } from '@services';
|
||||
import {
|
||||
MenuItems,
|
||||
ShowAuthedDirective,
|
||||
AccordionAnchorDirective,
|
||||
AccordionLinkDirective,
|
||||
AccordionDirective,
|
||||
} from '@components/shared';
|
||||
//import { SpinnerComponent } from '@components/shared';
|
||||
//import { HeaderComponent, FooterComponent } from '@components/shared/layout';
|
||||
import { FooterComponent } from '@components/shared/layout';
|
||||
|
||||
/** @title Responsive sidenav */
|
||||
@Component({
|
||||
selector: 'app-full-layout',
|
||||
imports: [
|
||||
RouterModule,
|
||||
RouterOutlet,
|
||||
MatBadgeModule,
|
||||
MatButtonModule,
|
||||
MatDividerModule,
|
||||
MatIconModule,
|
||||
MatListModule,
|
||||
MatMenuModule,
|
||||
MatSidenavModule,
|
||||
MatToolbarModule,
|
||||
ShowAuthedDirective,
|
||||
AccordionAnchorDirective,
|
||||
AccordionLinkDirective,
|
||||
AccordionDirective,
|
||||
FooterComponent,
|
||||
//HeaderComponent,
|
||||
//SpinnerComponent
|
||||
],
|
||||
providers: [MenuItems],
|
||||
templateUrl: 'full.component.html',
|
||||
styleUrls: [],
|
||||
})
|
||||
export class FullComponent implements OnInit, OnDestroy {
|
||||
private _currentUser: Subscription = new Subscription();
|
||||
private _mobileQueryListener: () => void;
|
||||
mobileQuery: MediaQueryList;
|
||||
currentUser: User = {} as User;
|
||||
today: number = Date.now();
|
||||
siteLink = 'https://www.adastra-cbd.com';
|
||||
author = 'Ad Astra';
|
||||
links: Menu[] = [];
|
||||
visibleMenu: string[] = [];
|
||||
//visibleMenu: string[] = ['products', 'page'];
|
||||
//visibleMenu: string[] = ['products'];
|
||||
|
||||
constructor(
|
||||
private router: Router,
|
||||
private userService: UserService,
|
||||
changeDetectorRef: ChangeDetectorRef,
|
||||
media: MediaMatcher,
|
||||
public menuItems: MenuItems,
|
||||
) {
|
||||
this.mobileQuery = media.matchMedia('(min-width: 768px)');
|
||||
this._mobileQueryListener = () => changeDetectorRef.detectChanges();
|
||||
this.mobileQuery.addListener(this._mobileQueryListener);
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
const user$: Observable<User> = this.userService.currentUser;
|
||||
this._currentUser = user$.subscribe((userData) => {
|
||||
this.currentUser = userData;
|
||||
if (this.currentUser.role === 'Admin') {
|
||||
this.links = this.menuItems.getMenuItemsAdmin();
|
||||
//this.links = this.menuItems.getMenuItems();
|
||||
} else {
|
||||
this.links = this.menuItems.getMenuItems();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
getMenuItems(): Menu[] {
|
||||
return this.links;
|
||||
}
|
||||
|
||||
isVisibleMenu(state: string): boolean {
|
||||
const indexOf: number = this.visibleMenu.indexOf(state);
|
||||
if (indexOf !== -1) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this._currentUser.unsubscribe();
|
||||
this.mobileQuery.removeListener(this._mobileQueryListener);
|
||||
}
|
||||
|
||||
goToGitHub() {
|
||||
window.open('https://github.com/rampeur', '_blank');
|
||||
}
|
||||
|
||||
toggleShowMenu(state: string) {
|
||||
const indexOf: number = this.visibleMenu.indexOf(state);
|
||||
if (indexOf !== -1) {
|
||||
this.visibleMenu.splice(indexOf, 1);
|
||||
} else {
|
||||
this.visibleMenu.push(state);
|
||||
}
|
||||
}
|
||||
|
||||
logout() {
|
||||
this.userService.purgeAuth();
|
||||
this.router.navigateByUrl('/login');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import { MatDividerModule } from '@angular/material/divider';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatMenuModule } from '@angular/material/menu';
|
||||
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||
import { Observable, Subscription } from 'rxjs';
|
||||
|
||||
import { User } from '@models';
|
||||
@@ -15,15 +15,17 @@ import { UserService } from '@services';
|
||||
@Component({
|
||||
selector: 'app-layout-header',
|
||||
templateUrl: './header.component.html',
|
||||
standalone: true,
|
||||
imports: [
|
||||
RouterLink, RouterLinkActive,
|
||||
MatToolbarModule, MatButtonModule, MatDividerModule,
|
||||
MatIconModule, MatMenuModule
|
||||
]
|
||||
RouterLink,
|
||||
RouterLinkActive,
|
||||
MatToolbarModule,
|
||||
MatButtonModule,
|
||||
MatDividerModule,
|
||||
MatIconModule,
|
||||
MatMenuModule,
|
||||
],
|
||||
})
|
||||
export class HeaderComponent implements OnInit {
|
||||
|
||||
private _currentUser: Subscription = new Subscription();
|
||||
private _isAuthenticated: Subscription = new Subscription();
|
||||
private isAuthenticated = false;
|
||||
@@ -32,22 +34,18 @@ export class HeaderComponent implements OnInit {
|
||||
|
||||
constructor(
|
||||
private router: Router,
|
||||
private userService: UserService
|
||||
) { }
|
||||
private userService: UserService,
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
const user$: Observable<User> = this.userService.currentUser.pipe(takeUntilDestroyed(this.destroyRef));
|
||||
this._currentUser = user$.subscribe(
|
||||
(userData) => {
|
||||
this.currentUser = userData;
|
||||
}
|
||||
);
|
||||
this._currentUser = user$.subscribe((userData) => {
|
||||
this.currentUser = userData;
|
||||
});
|
||||
const auth$: Observable<boolean> = this.userService.isAuthenticated.pipe(takeUntilDestroyed(this.destroyRef));
|
||||
this._isAuthenticated = auth$.subscribe(
|
||||
(value) => {
|
||||
this.isAuthenticated = value;
|
||||
}
|
||||
);
|
||||
this._isAuthenticated = auth$.subscribe((value) => {
|
||||
this.isAuthenticated = value;
|
||||
});
|
||||
}
|
||||
|
||||
goToGitHub() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { NgForOf, NgIf } from "@angular/common";
|
||||
import { NgForOf, NgIf } from '@angular/common';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
|
||||
import { Errors } from 'src/app/core';
|
||||
@@ -7,17 +7,14 @@ import { Errors } from 'src/app/core';
|
||||
@Component({
|
||||
selector: 'app-list-errors',
|
||||
templateUrl: './list-errors.component.html',
|
||||
standalone: true,
|
||||
imports: [NgIf, NgForOf, MatCardModule]
|
||||
imports: [NgIf, NgForOf, MatCardModule],
|
||||
})
|
||||
export class ListErrorsComponent {
|
||||
errorList: string[] = [];
|
||||
|
||||
@Input() set errors(errorList: Errors | null) {
|
||||
this.errorList = errorList
|
||||
? Object.keys(errorList.errors || {}).map(
|
||||
(key) => `${key} ${errorList.errors[key]}`,
|
||||
)
|
||||
? Object.keys(errorList.errors || {}).map((key) => `${key} ${errorList.errors[key]}`)
|
||||
: [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,44 +1,43 @@
|
||||
import { Component, Input, OnDestroy, Inject, ViewEncapsulation } from '@angular/core';
|
||||
|
||||
import { Router, NavigationStart, NavigationEnd, NavigationCancel, NavigationError } from '@angular/router';
|
||||
import { DOCUMENT } from '@angular/common';
|
||||
|
||||
@Component({
|
||||
selector: 'app-spinner',
|
||||
standalone: true,
|
||||
imports: [],
|
||||
templateUrl: './spinner.component.html',
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class SpinnerComponent implements OnDestroy {
|
||||
public isSpinnerVisible = true;
|
||||
|
||||
@Input()
|
||||
public backgroundColor = 'rgba(0, 115, 170, 0.69)';
|
||||
|
||||
constructor(
|
||||
private router: Router,
|
||||
@Inject(DOCUMENT) private document: Document
|
||||
) {
|
||||
this.router.events.subscribe(
|
||||
event => {
|
||||
if (event instanceof NavigationStart) {
|
||||
this.isSpinnerVisible = true;
|
||||
} else if (
|
||||
event instanceof NavigationEnd ||
|
||||
event instanceof NavigationCancel ||
|
||||
event instanceof NavigationError
|
||||
) {
|
||||
this.isSpinnerVisible = false;
|
||||
}
|
||||
},
|
||||
() => {
|
||||
this.isSpinnerVisible = false;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.isSpinnerVisible = false;
|
||||
}
|
||||
}
|
||||
import { Component, Input, OnDestroy, Inject, ViewEncapsulation } from '@angular/core';
|
||||
|
||||
import { Router, NavigationStart, NavigationEnd, NavigationCancel, NavigationError } from '@angular/router';
|
||||
import { DOCUMENT } from '@angular/common';
|
||||
|
||||
@Component({
|
||||
selector: 'app-spinner',
|
||||
imports: [],
|
||||
templateUrl: './spinner.component.html',
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
})
|
||||
export class SpinnerComponent implements OnDestroy {
|
||||
public isSpinnerVisible = true;
|
||||
|
||||
@Input()
|
||||
public backgroundColor = 'rgba(0, 115, 170, 0.69)';
|
||||
|
||||
constructor(
|
||||
private router: Router,
|
||||
@Inject(DOCUMENT) private document: Document,
|
||||
) {
|
||||
this.router.events.subscribe(
|
||||
(event) => {
|
||||
if (event instanceof NavigationStart) {
|
||||
this.isSpinnerVisible = true;
|
||||
} else if (
|
||||
event instanceof NavigationEnd ||
|
||||
event instanceof NavigationCancel ||
|
||||
event instanceof NavigationError
|
||||
) {
|
||||
this.isSpinnerVisible = false;
|
||||
}
|
||||
},
|
||||
() => {
|
||||
this.isSpinnerVisible = false;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.isSpinnerVisible = false;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user