From 4108c009fb198de0475a42543c25a8015741f1e3 Mon Sep 17 00:00:00 2001 From: Jean-Pascal AUBRY <jean-pascal.aubry@inrae.fr> Date: Fri, 11 Oct 2024 08:06:05 +0000 Subject: [PATCH 01/16] fix: init translation fr/en Refs #6 --- package-lock.json | 29 ++++++++++++++++++++++++ package.json | 2 ++ src/app/app.component.html | 45 +++++++++++++++++++++++--------------- src/app/app.component.ts | 11 +++++++--- src/app/app.config.ts | 20 +++++++++++++++-- src/assets/i18n/en.json | 25 +++++++++++++++++++++ src/assets/i18n/fr.json | 25 +++++++++++++++++++++ 7 files changed, 134 insertions(+), 23 deletions(-) create mode 100644 src/assets/i18n/en.json create mode 100644 src/assets/i18n/fr.json diff --git a/package-lock.json b/package-lock.json index 9b7fde0..b55cac4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,6 +20,8 @@ "@angular/platform-server": "^17.3.0", "@angular/router": "^17.3.0", "@angular/ssr": "^17.3.3", + "@ngx-translate/core": "^15.0.0", + "@ngx-translate/http-loader": "^8.0.0", "base64-js": "^1.5.1", "chart.js": "^4.4.4", "express": "^4.18.2", @@ -4051,6 +4053,33 @@ "webpack": "^5.54.0" } }, + "node_modules/@ngx-translate/core": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/@ngx-translate/core/-/core-15.0.0.tgz", + "integrity": "sha512-Am5uiuR0bOOxyoercDnAA3rJVizo4RRqJHo8N3RqJ+XfzVP/I845yEnMADykOHvM6HkVm4SZSnJBOiz0Anx5BA==", + "engines": { + "node": "^16.13.0 || >=18.10.0" + }, + "peerDependencies": { + "@angular/common": ">=16.0.0", + "@angular/core": ">=16.0.0", + "rxjs": "^6.5.5 || ^7.4.0" + } + }, + "node_modules/@ngx-translate/http-loader": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@ngx-translate/http-loader/-/http-loader-8.0.0.tgz", + "integrity": "sha512-SFMsdUcmHF5OdZkL1CHEoSAwbP5EbAOPTLLboOCRRoOg21P4GJx+51jxGdJeGve6LSKLf4Pay7BkTwmE6vxYlg==", + "engines": { + "node": "^16.13.0 || >=18.10.0" + }, + "peerDependencies": { + "@angular/common": ">=16.0.0", + "@angular/core": ">=16.0.0", + "@ngx-translate/core": ">=15.0.0", + "rxjs": "^6.5.5 || ^7.4.0" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", diff --git a/package.json b/package.json index 6779e75..72b7e54 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,8 @@ "@angular/platform-server": "^17.3.0", "@angular/router": "^17.3.0", "@angular/ssr": "^17.3.3", + "@ngx-translate/core": "^15.0.0", + "@ngx-translate/http-loader": "^8.0.0", "base64-js": "^1.5.1", "chart.js": "^4.4.4", "express": "^4.18.2", diff --git a/src/app/app.component.html b/src/app/app.component.html index e142919..ccd3108 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -1,13 +1,13 @@ <mat-toolbar> - <button mat-icon-button class="app-sidenav-toggle-button" (click)="sidenav.toggle()" matTooltip="Menu"> + <button mat-icon-button class="app-sidenav-toggle-button" (click)="sidenav.toggle()" matTooltip="{{ 'TOOLBAR.MENU' | translate }}"> <mat-icon>menu</mat-icon> </button> - <span>Moulinet</span> + <span>{{ 'TOOLBAR.TITLE' | translate }}</span> <span class="toolbar-item-spacer"></span> - <button mat-icon-button matTooltip="Search"> + <button mat-icon-button matTooltip="{{ 'TOOLBAR.SEARCH' | translate }}"> <mat-icon>search</mat-icon> </button> - <button mat-icon-button matTooltip="Help"> + <button mat-icon-button matTooltip="{{ 'TOOLBAR.HELP' | translate }}"> <mat-icon>help</mat-icon> </button> </mat-toolbar> @@ -16,37 +16,46 @@ <mat-sidenav #sidenav mode="over" [class.mat-elevation-z4]="true" class="app-sidenav"> <mat-nav-list> <mat-list-item routerLink="equipment" (click)="sidenav.close()"> - <mat-icon class="icon-list-item">construction</mat-icon><span>Matériel</span> + <mat-icon class="icon-list-item">construction</mat-icon> + <span>{{ 'SIDENAV.MATERIAL' | translate }}</span> </mat-list-item> <mat-list-item routerLink="list" (click)="sidenav.close()"> - <mat-icon class="icon-list-item">waves icon</mat-icon><span>Liste des jaugeages</span> + <mat-icon class="icon-list-item">waves</mat-icon> + <span>{{ 'SIDENAV.GAUGING_LIST' | translate }}</span> </mat-list-item> <mat-list-item (click)="sidenav.close()"> - <button (click)="createNewGauging()"> <mat-icon - class="icon-list-item">waves icon</mat-icon><span>Nouveau jaugeage</span> + <button (click)="createNewGauging()"> + <mat-icon class="icon-list-item">waves</mat-icon> + <span>{{ 'SIDENAV.NEW_GAUGING' | translate }}</span> </button> </mat-list-item> <mat-list-item (click)="sidenav.close()"> - <button [disabled]="(materialList$ | async)?.length! === 0" (click)="newSession()"> <mat-icon - class="icon-list-item">insert_drive_file</mat-icon><span>Réinitialiser la session</span></button> + <button [disabled]="(materialList$ | async)?.length! === 0" (click)="newSession()"> + <mat-icon class="icon-list-item">insert_drive_file</mat-icon> + <span>{{ 'SIDENAV.RESET_SESSION' | translate }}</span> + </button> </mat-list-item> <mat-list-item (click)="loadSession(); sidenav.close()"> - <mat-icon class="icon-list-item">folder_open</mat-icon><span>Charger une session</span> + <mat-icon class="icon-list-item">folder_open</mat-icon> + <span>{{ 'SIDENAV.LOAD_SESSION' | translate }}</span> </mat-list-item> <mat-list-item (click)="sidenav.close()"> - <button [disabled]="(materialList$ | async)?.length! === 0 && (gaugingList$ | async)?.length! === 0" (click)="saveSession()"> <mat-icon - class="icon-list-item">file_download</mat-icon><span>Enregistrer la session</span></button> + <button [disabled]="(materialList$ | async)?.length! === 0 && (gaugingList$ | async)?.length! === 0" (click)="saveSession()"> + <mat-icon class="icon-list-item">file_download</mat-icon> + <span>{{ 'SIDENAV.SAVE_SESSION' | translate }}</span> + </button> </mat-list-item> <mat-list-item (click)="sidenav.close()"> - <mat-icon class="icon-list-item">settings</mat-icon><span>Configuration</span> + <mat-icon class="icon-list-item">settings</mat-icon> + <span>{{ 'SIDENAV.CONFIGURATION' | translate }}</span> </mat-list-item> <mat-list-item (click)="sidenav.close()"> - <mat-icon class="icon-list-item">help</mat-icon><span>Documentation</span> + <mat-icon class="icon-list-item">help</mat-icon> + <span>{{ 'SIDENAV.DOCUMENTATION' | translate }}</span> </mat-list-item> </mat-nav-list> </mat-sidenav> <mat-sidenav-content> - <router-outlet> - </router-outlet> + <router-outlet></router-outlet> </mat-sidenav-content> -</mat-sidenav-container> \ No newline at end of file +</mat-sidenav-container> diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 5afb4af..234d7d0 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -22,11 +22,14 @@ import { GaugingService } from './services/gauging.service'; import { Gauging } from './models/gauging'; import { DialogConfirmNewGaugingComponent } from './components/dialog/dialog-confirm-new-gauging/dialog-confirm-new-gauging.component'; import { GaugingFormService } from './services/forms/gauging-form.service'; +import { TranslateModule, TranslateService } from '@ngx-translate/core'; +import { MatTooltipModule } from '@angular/material/tooltip'; + @Component({ selector: 'app-root', standalone: true, - imports: [AsyncPipe, RouterOutlet, RouterModule, RouterLink, MatButtonModule, MatToolbarModule, MatSidenavModule, MatListModule, MatExpansionModule, MatIconModule, MatMenuModule], + imports: [MatTooltipModule,AsyncPipe, RouterOutlet, RouterModule, RouterLink, MatButtonModule, MatToolbarModule, MatSidenavModule, MatListModule, MatExpansionModule, MatIconModule, MatMenuModule, TranslateModule], templateUrl: './app.component.html', styleUrl: './app.component.scss' }) @@ -38,15 +41,17 @@ export class AppComponent { gaugingList$: Observable<Gauging[]>; materialList: Material[] = []; - constructor(private dialog: MatDialog, private equipmentService: EquipmentService, private gaugingService: GaugingService, private gaugingFormService: GaugingFormService, private router: Router) { + constructor(private translate: TranslateService,private dialog: MatDialog, private equipmentService: EquipmentService, private gaugingService: GaugingService, private gaugingFormService: GaugingFormService, private router: Router) { this.materialList$ = this.equipmentService.materialList$; this.gaugingList$ = this.gaugingService.gaugingList$; + this.translate.addLangs(['fr', 'en']); + this.translate.setDefaultLang('fr'); + this.translate.use('fr'); } ngOnInit(): void { // Charger les données de session depuis le localStorage this.session.loadFromLocalStorage(); - // localStorage.removeItem("currentSessionMoulinet") if (typeof window !== 'undefined' && typeof sessionStorage !== 'undefined') { const wasPageRefreshed = sessionStorage.getItem('pageRefreshed'); if (wasPageRefreshed) { diff --git a/src/app/app.config.ts b/src/app/app.config.ts index cfa828c..495ff54 100644 --- a/src/app/app.config.ts +++ b/src/app/app.config.ts @@ -1,11 +1,27 @@ -import { ApplicationConfig } from '@angular/core'; +import { ApplicationConfig, importProvidersFrom, provideZoneChangeDetection } from '@angular/core'; import { provideRouter, PreloadAllModules, withPreloading } from '@angular/router'; import { routes } from './app.routes'; import { provideClientHydration } from '@angular/platform-browser'; import { provideAnimationsAsync } from '@angular/platform-browser/animations/async'; import { MAT_DATE_LOCALE } from '@angular/material/core'; +import { HttpClient, provideHttpClient } from '@angular/common/http'; +import { TranslateHttpLoader } from '@ngx-translate/http-loader'; +import { TranslateModule, TranslateLoader } from '@ngx-translate/core'; + +const httpLoaderFactory: (http: HttpClient) => TranslateHttpLoader = (http: HttpClient) => + new TranslateHttpLoader(http, './assets/i18n/', '.json'); export const appConfig: ApplicationConfig = { providers: [ - provideRouter(routes, withPreloading(PreloadAllModules)), provideClientHydration(), provideAnimationsAsync(), {provide: MAT_DATE_LOCALE, useValue: 'en-GB'}] + provideRouter(routes, withPreloading(PreloadAllModules)), provideClientHydration(), provideAnimationsAsync(), {provide: MAT_DATE_LOCALE, useValue: 'en-GB'}, + provideZoneChangeDetection({ eventCoalescing: true }), + provideHttpClient(), + importProvidersFrom([TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useFactory: httpLoaderFactory, + deps: [HttpClient], + }, + })]) + ] }; diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json new file mode 100644 index 0000000..e085fa2 --- /dev/null +++ b/src/assets/i18n/en.json @@ -0,0 +1,25 @@ +{ + "TOOLBAR": { + "MENU": "Menu", + "TITLE": "Moulinet", + "SEARCH": "Search", + "HELP": "Help" + }, + "SIDENAV": { + "MATERIAL": "Equipment", + "GAUGING_LIST": "List of Gaugings", + "NEW_GAUGING": "New Gauging", + "RESET_SESSION": "Reset Session", + "LOAD_SESSION": "Load Session", + "SAVE_SESSION": "Save Session", + "CONFIGURATION": "Configuration", + "DOCUMENTATION": "Documentation" + }, + "BUTTONS": { + "CREATE_NEW_GAUGING": "Create New Gauging", + "RESET_SESSION": "Reset Session", + "LOAD_SESSION": "Load Session", + "SAVE_SESSION": "Save Session" + } + } + \ No newline at end of file diff --git a/src/assets/i18n/fr.json b/src/assets/i18n/fr.json new file mode 100644 index 0000000..c97906d --- /dev/null +++ b/src/assets/i18n/fr.json @@ -0,0 +1,25 @@ +{ + "TOOLBAR": { + "MENU": "Menu", + "TITLE": "Moulinet", + "SEARCH": "Rechercher", + "HELP": "Aide" + }, + "SIDENAV": { + "MATERIAL": "Matériel", + "GAUGING_LIST": "Liste des jaugeages", + "NEW_GAUGING": "Nouveau jaugeage", + "RESET_SESSION": "Réinitialiser la session", + "LOAD_SESSION": "Charger une session", + "SAVE_SESSION": "Enregistrer la session", + "CONFIGURATION": "Configuration", + "DOCUMENTATION": "Documentation" + }, + "BUTTONS": { + "CREATE_NEW_GAUGING": "Créer un nouveau jaugeage", + "RESET_SESSION": "Réinitialiser la session", + "LOAD_SESSION": "Charger une session", + "SAVE_SESSION": "Enregistrer la session" + } + } + \ No newline at end of file -- GitLab From 38a3c6aa6fb43699b9898c4b7e25444ef83a1c74 Mon Sep 17 00:00:00 2001 From: Jean-Pascal AUBRY <jean-pascal.aubry@inrae.fr> Date: Fri, 11 Oct 2024 08:15:57 +0000 Subject: [PATCH 02/16] fix: translate gauging list component Refs #6 --- src/app/app.component.ts | 2 +- .../gauging-list/gauging-list.component.html | 34 ++++++++++--------- .../gauging-list/gauging-list.component.ts | 3 +- src/assets/i18n/en.json | 15 ++++++++ src/assets/i18n/fr.json | 15 ++++++++ 5 files changed, 51 insertions(+), 18 deletions(-) diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 234d7d0..a51cede 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -46,7 +46,7 @@ export class AppComponent { this.gaugingList$ = this.gaugingService.gaugingList$; this.translate.addLangs(['fr', 'en']); this.translate.setDefaultLang('fr'); - this.translate.use('fr'); + this.translate.use('en'); } ngOnInit(): void { diff --git a/src/app/views/gauging-list/gauging-list.component.html b/src/app/views/gauging-list/gauging-list.component.html index baa0574..a4dd044 100644 --- a/src/app/views/gauging-list/gauging-list.component.html +++ b/src/app/views/gauging-list/gauging-list.component.html @@ -1,53 +1,54 @@ -<!-- template.html --> <div class="container"> <div class="gauging-list-container"> <div class="gauging-list"> @if((gaugingsList$ | async)?.length! > 0){ <div class="gauging-list-title"> - <h1>Liste des Jaugeages</h1> - <button mat-raised-button color="primary" (click)="addGauging()" class="gauging-list-title-add">Ajouter un jaugeage</button> + <h1>{{ 'GAUGING.LIST_TITLE' | translate }}</h1> + <button mat-raised-button color="primary" (click)="addGauging()" class="gauging-list-title-add"> + {{ 'GAUGING.ADD_GAUGING' | translate }} + </button> </div> <table mat-table [dataSource]="(gaugingsList$ | async)!" cdkDropList> <!-- Watercourse Column --> <ng-container matColumnDef="watercourse"> - <th mat-header-cell *matHeaderCellDef> Cours d'eau </th> + <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.COLUMNS.WATERCOURSE' | translate }} </th> <td mat-cell *matCellDef="let gauging" (click)="editGauging(gauging)" > {{ gauging.watercourse || '-' }} </td> </ng-container> <!-- Department Column --> <ng-container matColumnDef="department"> - <th mat-header-cell *matHeaderCellDef> Département </th> + <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.COLUMNS.DEPARTMENT' | translate }} </th> <td mat-cell *matCellDef="let gauging"(click)="editGauging(gauging)" > {{ gauging.department || '-' }} </td> </ng-container> <!-- Municipality Column --> <ng-container matColumnDef="municipality"> - <th mat-header-cell *matHeaderCellDef> Commune </th> + <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.COLUMNS.MUNICIPALITY' | translate }} </th> <td mat-cell *matCellDef="let gauging" (click)="editGauging(gauging)"> {{ gauging.municipality || '-' }} </td> </ng-container> <!-- Locality Column --> <ng-container matColumnDef="locality"> - <th mat-header-cell *matHeaderCellDef> Lieu-dit </th> + <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.COLUMNS.LOCALITY' | translate }} </th> <td mat-cell *matCellDef="let gauging" (click)="editGauging(gauging)"> {{ gauging.locality || '-' }} </td> </ng-container> <!-- Date Column --> <ng-container matColumnDef="date"> - <th mat-header-cell *matHeaderCellDef> Date </th> - <td mat-cell *matCellDef="let gauging" (click)="editGauging(gauging)"> {{ gauging.date | date: 'dd/MM/yyyy' }}</td> + <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.COLUMNS.DATE' | translate }} </th> + <td mat-cell *matCellDef="let gauging" (click)="editGauging(gauging)"> {{ gauging.date | date: 'dd/MM/yyyy' }}</td> </ng-container> <!-- State Column --> <ng-container matColumnDef="state"> - <th mat-header-cell *matHeaderCellDef> Etat </th> - <td mat-cell *matCellDef="let gauging" (click)="editGauging(gauging)"> Validé </td> + <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.COLUMNS.STATE' | translate }} </th> + <td mat-cell *matCellDef="let gauging" (click)="editGauging(gauging)"> {{ 'GAUGING.VALIDATED' | translate }} </td> </ng-container> <!-- Actions Column --> <ng-container matColumnDef="actions"> - <th mat-header-cell *matHeaderCellDef> Actions </th> + <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.COLUMNS.ACTIONS' | translate }} </th> <td mat-cell *matCellDef="let gauging, , let i =index"> <button mat-icon-button color="primary" (click)="editGauging(gauging)"> <mat-icon class="edit-button">edit</mat-icon> @@ -67,12 +68,13 @@ @else{ <!-- if no created gauging --> <div class="no-gauging-title"> - <h1>Liste des jaugeages</h1> - <p>Aucun jaugeage réalisé ou en cours de réalisation.</p> - <button mat-raised-button color="primary" (click)="addGauging()" class="add-button">Ajouter</button> + <h1>{{ 'GAUGING.LIST_TITLE' | translate }}</h1> + <p>{{ 'GAUGING.NO_GAUGING' | translate }}</p> + <button mat-raised-button color="primary" (click)="addGauging()" class="add-button"> + {{ 'GAUGING.ADD_GAUGING' | translate }} + </button> </div> } </div> </div> </div> - \ No newline at end of file diff --git a/src/app/views/gauging-list/gauging-list.component.ts b/src/app/views/gauging-list/gauging-list.component.ts index 33056f1..1a9f622 100644 --- a/src/app/views/gauging-list/gauging-list.component.ts +++ b/src/app/views/gauging-list/gauging-list.component.ts @@ -13,11 +13,12 @@ import { Router} from '@angular/router'; import { subscribeOnce } from '../../tools/ObservableHelper'; import { DialogConfirmDeleteGaugingComponent } from '../../components/dialog/dialog-confirm-delete-gauging/dialog-confirm-delete-gauging.component'; import { MatDialog } from '@angular/material/dialog'; +import { TranslateModule } from '@ngx-translate/core'; @Component({ selector: 'app-gauging-list', standalone: true, - imports: [ReactiveFormsModule, FormsModule, CommonModule, MatButtonModule, MatTableModule, DragDropModule, MatIconModule, ErrorMessageComponent], + imports: [TranslateModule, ReactiveFormsModule, FormsModule, CommonModule, MatButtonModule, MatTableModule, DragDropModule, MatIconModule, ErrorMessageComponent], templateUrl: './gauging-list.component.html', styleUrl: './gauging-list.component.scss', providers: [DatePipe] diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index e085fa2..89561fa 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -20,6 +20,21 @@ "RESET_SESSION": "Reset Session", "LOAD_SESSION": "Load Session", "SAVE_SESSION": "Save Session" + }, + "GAUGING": { + "LIST_TITLE": "Gauging List", + "ADD_GAUGING": "Add Gauging", + "COLUMNS": { + "WATERCOURSE": "Watercourse", + "DEPARTMENT": "Department", + "MUNICIPALITY": "Municipality", + "LOCALITY": "Locality", + "DATE": "Date", + "STATE": "State", + "ACTIONS": "Actions" + }, + "VALIDATED": "Validated", + "NO_GAUGING": "No gauging has been carried out or is in progress." } } \ No newline at end of file diff --git a/src/assets/i18n/fr.json b/src/assets/i18n/fr.json index c97906d..1997953 100644 --- a/src/assets/i18n/fr.json +++ b/src/assets/i18n/fr.json @@ -20,6 +20,21 @@ "RESET_SESSION": "Réinitialiser la session", "LOAD_SESSION": "Charger une session", "SAVE_SESSION": "Enregistrer la session" + }, + "GAUGING": { + "LIST_TITLE": "Liste des Jaugeages", + "ADD_GAUGING": "Ajouter un jaugeage", + "COLUMNS": { + "WATERCOURSE": "Cours d'eau", + "DEPARTMENT": "Département", + "MUNICIPALITY": "Commune", + "LOCALITY": "Lieu-dit", + "DATE": "Date", + "STATE": "État", + "ACTIONS": "Actions" + }, + "VALIDATED": "Validé", + "NO_GAUGING": "Aucun jaugeage réalisé ou en cours de réalisation." } } \ No newline at end of file -- GitLab From f32ee41f3ac9b838d0c1b68cfc039abdbc94ce80 Mon Sep 17 00:00:00 2001 From: Jean-Pascal AUBRY <jean-pascal.aubry@inrae.fr> Date: Fri, 11 Oct 2024 10:09:29 +0000 Subject: [PATCH 03/16] fix: translate equipment component Refs #6 --- src/app/models/equipment.model.ts | 7 +- src/app/services/equipment.service.ts | 19 +- .../views/equipment/equipment.component.html | 238 +++++++++--------- .../views/equipment/equipment.component.ts | 3 +- src/assets/i18n/en.json | 108 +++++--- src/assets/i18n/fr.json | 108 +++++--- 6 files changed, 278 insertions(+), 205 deletions(-) diff --git a/src/app/models/equipment.model.ts b/src/app/models/equipment.model.ts index 26d5b16..d71f899 100644 --- a/src/app/models/equipment.model.ts +++ b/src/app/models/equipment.model.ts @@ -1,5 +1,6 @@ export enum MaterialType { - ElectromagneticFlowMeter = 'courantomètre électromagnétique', - PropellerFlowMeter = 'moulinet', - VelocityHeadRod = 'perche à charge dynamique transparente' + ElectromagneticFlowMeter = 'EQUIPMENT.materialTypes.ElectromagneticFlowMeter', + PropellerFlowMeter = 'EQUIPMENT.materialTypes.PropellerFlowMeter', + VelocityHeadRod = 'EQUIPMENT.materialTypes.VelocityHeadRod' } + diff --git a/src/app/services/equipment.service.ts b/src/app/services/equipment.service.ts index 7784394..f28e9f3 100644 --- a/src/app/services/equipment.service.ts +++ b/src/app/services/equipment.service.ts @@ -6,6 +6,7 @@ import { MaterialPropeller } from '../models/material_propeller'; import { MaterialHeadRod } from '../models/material_headRod'; import { Gauging } from '../models/gauging'; import { GaugingService } from './gauging.service'; +import { MaterialType } from '../models/equipment.model'; @Injectable({ providedIn: 'root' @@ -66,18 +67,18 @@ export class EquipmentService { public createInstanceofMaterial(materialType: string, ...args: any[]): any { const MaterialTypeDictionary: { [key: string]: any } = { - 'courantomètre électromagnétique': MaterialCouranto, - 'moulinet': MaterialPropeller, - 'perche à charge dynamique transparente': MaterialHeadRod + [MaterialType.ElectromagneticFlowMeter]: MaterialCouranto, + [MaterialType.PropellerFlowMeter]: MaterialPropeller, + [MaterialType.VelocityHeadRod]: MaterialHeadRod }; - const SelectedMaterialTypeClass = MaterialTypeDictionary[materialType]; - if (SelectedMaterialTypeClass) { - return new SelectedMaterialTypeClass(...args); - } else { - throw new Error(`La classe ${materialType} n'existe pas.`); + const MaterialClass = MaterialTypeDictionary[materialType]; + if (MaterialClass) { + return new MaterialClass(...args); } - } + throw new Error(`Unknown material type: ${materialType}`); +} + // Nouvelle méthode pour vérifier si un matériel est associé à un gauging isMaterialAssociatedWithGauging(materialId: string): boolean { diff --git a/src/app/views/equipment/equipment.component.html b/src/app/views/equipment/equipment.component.html index 80366f6..2e0d6b4 100644 --- a/src/app/views/equipment/equipment.component.html +++ b/src/app/views/equipment/equipment.component.html @@ -4,17 +4,19 @@ <div class="equipment-list"> @if((materialList$ | async)?.length! > 0){ <div class="equipment-list-title"> - <h1>Liste du Matériel</h1> + <h1>{{ 'EQUIPMENT.materialListTitle' | translate }}</h1> <button mat-raised-button color="primary" [disabled]="showEditMaterialForm" class="equipment-list-title-add" - [disabled]="needMaterial" (click)="addMaterial()"><span>Ajouter</span><mat-icon - class="icon-list-item">add</mat-icon></button> + [disabled]="needMaterial" (click)="addMaterial()"> + <span>{{ 'EQUIPMENT.addMaterialButton' | translate }}</span> + <mat-icon class="icon-list-item">add</mat-icon> + </button> </div> <table mat-table [dataSource]="(materialList$ | async)!" cdkDropList [cdkDropListDisabled]="!enableDragFunctionality" (cdkDropListDropped)="dropTable($event)" [cdkDropListLockAxis]="'y'"> <!-- Reorder column --> <ng-container matColumnDef="reorder"> - <th mat-header-cell *matHeaderCellDef style="width:5%"></th>> <th> + <th mat-header-cell *matHeaderCellDef style="width:5%"></th> <td mat-cell *matCellDef="let material" style="text-overflow: unset !important;"> <!-- draggable button --> <mat-icon (click)="toggleDragFunctionality()" class="drag-icon">drag_indicator</mat-icon> @@ -23,7 +25,7 @@ <!-- Name Column --> <ng-container matColumnDef="name"> - <th mat-header-cell *matHeaderCellDef>Nom</th> + <th mat-header-cell *matHeaderCellDef>{{ 'EQUIPMENT.nameColumn' | translate }}</th> <td mat-cell *matCellDef="let materiel, let i=index" (click)="editMaterial(materiel, i)" id="name-row">{{ materiel.name }} </td> @@ -31,27 +33,27 @@ <!-- Type Column --> <ng-container matColumnDef="type"> - <th mat-header-cell *matHeaderCellDef>Type</th> - <td mat-cell *matCellDef="let materiel, let i=index" (click)="editMaterial(materiel, i)">{{ materiel.type }} + <th mat-header-cell *matHeaderCellDef>{{ 'EQUIPMENT.typeColumn' | translate }}</th> + <td mat-cell *matCellDef="let materiel, let i=index" (click)="editMaterial(materiel, i)">{{ materiel.type | translate}} </td> </ng-container> <!-- Serial Number Column --> <ng-container matColumnDef="serialNumber"> - <th mat-header-cell *matHeaderCellDef>Numéro de série</th> + <th mat-header-cell *matHeaderCellDef>{{ 'EQUIPMENT.serialNumberColumn' | translate }}</th> <td mat-cell *matCellDef="let materiel, let i=index" (click)="editMaterial(materiel, i)">{{ materiel.serialNumber || '-' }}</td> </ng-container> <!-- Description Column --> <ng-container matColumnDef="description"> - <th class="equipment-list-description" mat-header-cell *matHeaderCellDef>Description</th> + <th class="equipment-list-description" mat-header-cell *matHeaderCellDef>{{ 'EQUIPMENT.descriptionColumn' | translate }}</th> <td mat-cell *matCellDef="let materiel, let i=index" (click)="editMaterial(materiel, i)">{{ materiel.description || '-' }}</td> </ng-container> <!-- Edit/Remove Column --> <ng-container matColumnDef="edit"> - <th class="equipment-list-action" mat-header-cell *matHeaderCellDef style=" text-align: center">Actions</th> + <th class="equipment-list-action" mat-header-cell *matHeaderCellDef style=" text-align: center">{{ 'EQUIPMENT.actionsColumn' | translate }}</th> <td mat-cell *matCellDef="let materiel, let i =index" style="text-overflow: unset; text-align: center;"> <button mat-icon-button color="primary" (click)="editMaterial(materiel, i)" [disabled]="needMaterial || showEditMaterialForm" id="edit"> @@ -75,10 +77,10 @@ @else{ <!-- if no created material --> <div class="equipment-form-title"> - <h1>Liste du Matériel</h1> - <p>Aucun matériel disponible.</p> + <h1>{{ 'EQUIPMENT.materialListTitle' | translate }}</h1> + <p>{{ 'EQUIPMENT.noMaterialAvailable' | translate }}</p> @if(!needMaterial) { - <button mat-raised-button color="primary" (click)="addMaterial()" class="add-button">Ajouter</button> + <button mat-raised-button color="primary" (click)="addMaterial()" class="add-button">{{ 'EQUIPMENT.addMaterialButton' | translate }}</button> } </div> } @@ -86,112 +88,108 @@ </div> <!-- Creation/Edition form --> @if(needMaterial || showEditMaterialForm ){ - <div class="equipment-form-container"> - <form class="equipment-form" [formGroup]="form" (submit)="onSubmit()"> - <h1 class="equipment-form-title">{{needMaterial ? 'Nouveau matériel' : 'Modifier le matériel'}}</h1> - <!-- Material Type Section --> - <section class="form-section"> - <h2>Type de matériel</h2> - <mat-form-field appearance="outline"> - <mat-label>Type de matériel</mat-label> - <mat-select formControlName="type" placeholder="Type" (selectionChange)="onMaterialTypeChange()"> - @for (type of materielTypes; track type) { - <mat-option [value]="type"> - {{type}} - </mat-option> - } - </mat-select> - </mat-form-field> - </section> - - <!-- Model Section --> - <section class="form-section"> - <h2>Modèle</h2> - <mat-form-field appearance="outline"> - <mat-label>Nom</mat-label> - <input matInput placeholder="Nom" formControlName="name" autocomplete="name"> - </mat-form-field> - @if(hasError('name', 'required')){ - <app-error-message [displayed]="hasError('name', 'required')">Le nom est - requis</app-error-message> - } - <mat-form-field appearance="outline"> - <mat-label>Numéro de série - </mat-label> - <input matInput placeholder="Numéro de série" formControlName="serialNumber" autocomplete="off"> - </mat-form-field> - @if(isPropeller) { - <!-- Numéro de l'hélice --> - <mat-form-field appearance="outline"> - <mat-label>Numéro de l'hélice</mat-label> - <input matInput placeholder="Numéro de l'hélice" formControlName="propellerNumber" autocomplete="off"> - </mat-form-field> - - <!-- Numéro de série de l'hélice --> - <mat-form-field appearance="outline"> - <mat-label>Numéro de série de l'hélice</mat-label> - <input matInput placeholder="Numéro de série de l'hélice" formControlName="propellerSerialNumber" - autocomplete="off"> - </mat-form-field> - - <!-- Nombre de formules de vitesse --> - <mat-form-field appearance="outline"> - <mat-label>Nombre de formules de vitesse</mat-label> - <mat-select formControlName="velocityFormulaCount" placeholder="Nombre de formules de vitesse" - (selectionChange)="onVelocityFormulaCountChange($event.value)"> - <mat-option *ngFor="let count of [1, 2, 3, 4, 5]" [value]="count"> - {{count}} - </mat-option> - </mat-select> - </mat-form-field> - <div formArrayName="velocityFormulas" [ngClass]="{'formulas-section': velocityFormulas.controls.length > 0}"> - @for(formula of velocityFormulas.controls; track formula; let i = $index ) { - <div [formGroupName]="i"> - <h3>Formule de vitesse n°{{ i + 1 }}</h3> - <div class="form-field-row"> - <mat-form-field appearance="outline" class="form-field-inline"> - <mat-label>Borne inférieure</mat-label> - <input matInput placeholder="n >" formControlName="lowerBound"> - </mat-form-field> - <!-- Message d'erreur --> - <mat-form-field appearance="outline" class="form-field-inline"> - <mat-label>Borne supérieure</mat-label> - <input matInput placeholder="n <" formControlName="upperBound"> - </mat-form-field> - </div> - @if(formula.errors?.invalidBounds) { - <mat-error>Les bornes spécifiées ne sont pas correctes. La borne inférieure doit être strictement inférieure - à la borne supérieure.</mat-error> - } - - <!-- Deuxième ligne : Coef a et Coef b --> - <div class="form-field-row"> - <mat-form-field appearance="outline" class="form-field-inline"> - <mat-label>Coefficient A</mat-label> - <input matInput placeholder="Coef a" formControlName="coefA"> - </mat-form-field> - <mat-form-field appearance="outline" class="form-field-inline"> - <mat-label>Constante B</mat-label> - <input matInput placeholder="Constante b" formControlName="constantB"> - </mat-form-field> + <div class="equipment-form-container"> + <form class="equipment-form" [formGroup]="form" (submit)="onSubmit()"> + <h1 class="equipment-form-title">{{needMaterial ? ('EQUIPMENT.newMaterialTitle' | translate) : ('EQUIPMENT.editMaterialTitle' | translate)}}</h1> + + <!-- Material Type Section --> + <section class="form-section"> + <h2>{{ 'EQUIPMENT.materialTypeLabel' | translate }}</h2> + <mat-form-field appearance="outline"> + <mat-label>{{ 'EQUIPMENT.materialTypeLabel' | translate }}</mat-label> + <mat-select formControlName="type" placeholder="{{ 'EQUIPMENT.materialTypeLabel' | translate }}" (selectionChange)="onMaterialTypeChange()"> + @for (type of materielTypes; track type) { + <mat-option [value]="type"> + {{ type | translate }} + </mat-option> + } + </mat-select> + </mat-form-field> + </section> + + <!-- Model Section --> + <section class="form-section"> + <h2>{{ 'EQUIPMENT.modelSectionTitle' | translate }}</h2> + <mat-form-field appearance="outline"> + <mat-label>{{ 'EQUIPMENT.nameLabel' | translate }}</mat-label> + <input matInput placeholder="{{ 'EQUIPMENT.nameLabel' | translate }}" formControlName="name" autocomplete="name"> + </mat-form-field> + @if(hasError('name', 'required')){ + <app-error-message [displayed]="hasError('name', 'required')">{{ 'EQUIPMENT.requiredNameError' | translate }}</app-error-message> + } + <mat-form-field appearance="outline"> + <mat-label>{{ 'EQUIPMENT.serialNumberLabel' | translate }}</mat-label> + <input matInput placeholder="{{ 'EQUIPMENT.serialNumberLabel' | translate }}" formControlName="serialNumber" autocomplete="off"> + </mat-form-field> + @if(isPropeller) { + <!-- Propeller Number --> + <mat-form-field appearance="outline"> + <mat-label>{{ 'EQUIPMENT.propellerNumberLabel' | translate }}</mat-label> + <input matInput placeholder="{{ 'EQUIPMENT.propellerNumberLabel' | translate }}" formControlName="propellerNumber" autocomplete="off"> + </mat-form-field> + + <!-- Propeller Serial Number --> + <mat-form-field appearance="outline"> + <mat-label>{{ 'EQUIPMENT.propellerSerialNumberLabel' | translate }}</mat-label> + <input matInput placeholder="{{ 'EQUIPMENT.propellerSerialNumberLabel' | translate }}" formControlName="propellerSerialNumber" autocomplete="off"> + </mat-form-field> + + <!-- Number of Velocity Formulas --> + <mat-form-field appearance="outline"> + <mat-label>{{ 'EQUIPMENT.velocityFormulaCountLabel' | translate }}</mat-label> + <mat-select formControlName="velocityFormulaCount" placeholder="{{ 'EQUIPMENT.velocityFormulaCountLabel' | translate }}" (selectionChange)="onVelocityFormulaCountChange($event.value)"> + <mat-option *ngFor="let count of [1, 2, 3, 4, 5]" [value]="count"> + {{count}} + </mat-option> + </mat-select> + </mat-form-field> + <div formArrayName="velocityFormulas" [ngClass]="{'formulas-section': velocityFormulas.controls.length > 0}"> + @for(formula of velocityFormulas.controls; track formula; let i = $index ) { + <div [formGroupName]="i"> + <h3>{{ 'EQUIPMENT.velocityFormulaTitle' | translate }} {{ i + 1 }}</h3> + <div class="form-field-row"> + <mat-form-field appearance="outline" class="form-field-inline"> + <mat-label>{{ 'EQUIPMENT.lowerBoundLabel' | translate }}</mat-label> + <input matInput placeholder="{{ 'EQUIPMENT.lowerBoundLabel' | translate }}" formControlName="lowerBound"> + </mat-form-field> + <!-- Error Message --> + <mat-form-field appearance="outline" class="form-field-inline"> + <mat-label>{{ 'EQUIPMENT.upperBoundLabel' | translate }}</mat-label> + <input matInput placeholder="{{ 'EQUIPMENT.upperBoundLabel' | translate }}" formControlName="upperBound"> + </mat-form-field> + </div> + @if(formula.errors?.invalidBounds) { + <mat-error>{{ 'EQUIPMENT.invalidBoundsError' | translate }}</mat-error> + } + + <!-- Second row: Coefficient A and B --> + <div class="form-field-row"> + <mat-form-field appearance="outline" class="form-field-inline"> + <mat-label>{{ 'EQUIPMENT.coefALabel' | translate }}</mat-label> + <input matInput placeholder="{{ 'EQUIPMENT.coefALabel' | translate }}" formControlName="coefA"> + </mat-form-field> + <mat-form-field appearance="outline" class="form-field-inline"> + <mat-label>{{ 'EQUIPMENT.constantBLabel' | translate }}</mat-label> + <input matInput placeholder="{{ 'EQUIPMENT.constantBLabel' | translate }}" formControlName="constantB"> + </mat-form-field> + </div> + </div> + } </div> - </div> } - </div> - } - </section> - <section class="form-section"> - <h2>Infomations complémentaires</h2> - <mat-form-field class="equipment-description" appearance="outline"> - <mat-label>Description</mat-label> - <textarea matInput placeholder="Description" formControlName="description" rows="4" - autocomplete="off"></textarea> - </mat-form-field> - </section> - - <button style="margin-right: 4%;" mat-flat-button color="primary" class="submit-button" - [disabled]="!form.valid">Valider</button> - <button mat-flat-button color="warn" (click)="closeMaterialForm()" class="submit-button">Annuler</button> - </form> - </div> - } \ No newline at end of file + </section> + + <section class="form-section"> + <h2>{{ 'EQUIPMENT.additionalInfoTitle' | translate }}</h2> + <mat-form-field class="equipment-description" appearance="outline"> + <mat-label>{{ 'EQUIPMENT.descriptionLabel' | translate }}</mat-label> + <textarea matInput placeholder="{{ 'EQUIPMENT.descriptionLabel' | translate }}" formControlName="description" rows="4" autocomplete="off"></textarea> + </mat-form-field> + </section> + + <button style="margin-right: 4%;" mat-flat-button color="primary" class="submit-button" [disabled]="!form.valid">{{ 'EQUIPMENT.submitButton' | translate }}</button> + <button mat-flat-button color="warn" (click)="closeMaterialForm()" class="submit-button">{{ 'EQUIPMENT.cancelButton' | translate }}</button> + </form> + </div> + } + \ No newline at end of file diff --git a/src/app/views/equipment/equipment.component.ts b/src/app/views/equipment/equipment.component.ts index c944ab1..ee043ab 100644 --- a/src/app/views/equipment/equipment.component.ts +++ b/src/app/views/equipment/equipment.component.ts @@ -25,13 +25,14 @@ import { boundsValidator } from '../../tools/Vallidators/propellerFormulaBoundsV import { ActivatedRoute, Router } from '@angular/router'; import { Session } from '../../models/session'; import { DialogWarningMaterialAssociatedToGaugingComponent } from '../../components/dialog/dialog-warning-material-associated-to-gauging/dialog-warning-material-associated-to-gauging.component'; +import { TranslateModule } from '@ngx-translate/core'; @Component({ selector: 'app-equipment', standalone: true, templateUrl: './equipment.component.html', styleUrl: './equipment.component.scss', - imports: [ReactiveFormsModule, FormsModule, CommonModule, MatFormFieldModule, MatSelectModule, MatRadioModule, MatInputModule, MatButtonModule, MatTableModule, DragDropModule, MatIconModule, ErrorMessageComponent] + imports: [TranslateModule, ReactiveFormsModule, FormsModule, CommonModule, MatFormFieldModule, MatSelectModule, MatRadioModule, MatInputModule, MatButtonModule, MatTableModule, DragDropModule, MatIconModule, ErrorMessageComponent] }) export class EquipmentComponent extends AbstractFormComponent { diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 89561fa..97b37ed 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -1,40 +1,76 @@ { - "TOOLBAR": { - "MENU": "Menu", - "TITLE": "Moulinet", - "SEARCH": "Search", - "HELP": "Help" + "TOOLBAR": { + "MENU": "Menu", + "TITLE": "Moulinet", + "SEARCH": "Search", + "HELP": "Help" + }, + "SIDENAV": { + "MATERIAL": "Equipment", + "GAUGING_LIST": "List of Gaugings", + "NEW_GAUGING": "New Gauging", + "RESET_SESSION": "Reset Session", + "LOAD_SESSION": "Load Session", + "SAVE_SESSION": "Save Session", + "CONFIGURATION": "Configuration", + "DOCUMENTATION": "Documentation" + }, + "BUTTONS": { + "CREATE_NEW_GAUGING": "Create New Gauging", + "RESET_SESSION": "Reset Session", + "LOAD_SESSION": "Load Session", + "SAVE_SESSION": "Save Session" + }, + "GAUGING": { + "LIST_TITLE": "Gauging List", + "ADD_GAUGING": "Add Gauging", + "COLUMNS": { + "WATERCOURSE": "Watercourse", + "DEPARTMENT": "Department", + "MUNICIPALITY": "Municipality", + "LOCALITY": "Locality", + "DATE": "Date", + "STATE": "State", + "ACTIONS": "Actions" }, - "SIDENAV": { - "MATERIAL": "Equipment", - "GAUGING_LIST": "List of Gaugings", - "NEW_GAUGING": "New Gauging", - "RESET_SESSION": "Reset Session", - "LOAD_SESSION": "Load Session", - "SAVE_SESSION": "Save Session", - "CONFIGURATION": "Configuration", - "DOCUMENTATION": "Documentation" + "VALIDATED": "Validated", + "NO_GAUGING": "No gauging has been carried out or is in progress." + }, + "EQUIPMENT": { + "materialListTitle": "Material List", + "addMaterialButton": "Add", + "noMaterialAvailable": "No material available.", + "actionsColumn": "Actions", + "nameColumn": "Name", + "typeColumn": "Type", + "serialNumberColumn": "Serial Number", + "descriptionColumn": "Description", + "editButton": "Edit", + "deleteButton": "Delete", + "newMaterialTitle": "New Material", + "editMaterialTitle": "Edit Material", + "materialTypeLabel": "Material Type", + "materialTypes": { + "ElectromagneticFlowMeter": "Electromagnetic Flow Meter", + "PropellerFlowMeter": "Propeller Flow Meter", + "VelocityHeadRod": "Velocity Head Rod" }, - "BUTTONS": { - "CREATE_NEW_GAUGING": "Create New Gauging", - "RESET_SESSION": "Reset Session", - "LOAD_SESSION": "Load Session", - "SAVE_SESSION": "Save Session" - }, - "GAUGING": { - "LIST_TITLE": "Gauging List", - "ADD_GAUGING": "Add Gauging", - "COLUMNS": { - "WATERCOURSE": "Watercourse", - "DEPARTMENT": "Department", - "MUNICIPALITY": "Municipality", - "LOCALITY": "Locality", - "DATE": "Date", - "STATE": "State", - "ACTIONS": "Actions" - }, - "VALIDATED": "Validated", - "NO_GAUGING": "No gauging has been carried out or is in progress." - } + "modelSectionTitle": "Model", + "nameLabel": "Name", + "serialNumberLabel": "Serial Number", + "propellerNumberLabel": "Propeller Number", + "propellerSerialNumberLabel": "Propeller Serial Number", + "velocityFormulaCountLabel": "Number of Velocity Formulas", + "velocityFormulaTitle": "Velocity Formula n°", + "lowerBoundLabel": "Lower Bound", + "upperBoundLabel": "Upper Bound", + "coefALabel": "Coefficient A", + "constantBLabel": "Constant B", + "invalidBoundsError": "The specified bounds are incorrect. The lower bound must be strictly less than the upper bound.", + "requiredNameError": "The name is required.", + "additionalInfoTitle": "Additional information", + "descriptionLabel": "Description", + "submitButton": "Submit", + "cancelButton": "Cancel" } - \ No newline at end of file +} \ No newline at end of file diff --git a/src/assets/i18n/fr.json b/src/assets/i18n/fr.json index 1997953..ea92bc4 100644 --- a/src/assets/i18n/fr.json +++ b/src/assets/i18n/fr.json @@ -1,40 +1,76 @@ { - "TOOLBAR": { - "MENU": "Menu", - "TITLE": "Moulinet", - "SEARCH": "Rechercher", - "HELP": "Aide" + "TOOLBAR": { + "MENU": "Menu", + "TITLE": "Moulinet", + "SEARCH": "Rechercher", + "HELP": "Aide" + }, + "SIDENAV": { + "MATERIAL": "Matériel", + "GAUGING_LIST": "Liste des jaugeages", + "NEW_GAUGING": "Nouveau jaugeage", + "RESET_SESSION": "Réinitialiser la session", + "LOAD_SESSION": "Charger une session", + "SAVE_SESSION": "Enregistrer la session", + "CONFIGURATION": "Configuration", + "DOCUMENTATION": "Documentation" + }, + "BUTTONS": { + "CREATE_NEW_GAUGING": "Créer un nouveau jaugeage", + "RESET_SESSION": "Réinitialiser la session", + "LOAD_SESSION": "Charger une session", + "SAVE_SESSION": "Enregistrer la session" + }, + "GAUGING": { + "LIST_TITLE": "Liste des Jaugeages", + "ADD_GAUGING": "Ajouter un jaugeage", + "COLUMNS": { + "WATERCOURSE": "Cours d'eau", + "DEPARTMENT": "Département", + "MUNICIPALITY": "Commune", + "LOCALITY": "Lieu-dit", + "DATE": "Date", + "STATE": "État", + "ACTIONS": "Actions" }, - "SIDENAV": { - "MATERIAL": "Matériel", - "GAUGING_LIST": "Liste des jaugeages", - "NEW_GAUGING": "Nouveau jaugeage", - "RESET_SESSION": "Réinitialiser la session", - "LOAD_SESSION": "Charger une session", - "SAVE_SESSION": "Enregistrer la session", - "CONFIGURATION": "Configuration", - "DOCUMENTATION": "Documentation" + "VALIDATED": "Validé", + "NO_GAUGING": "Aucun jaugeage réalisé ou en cours de réalisation." + }, + "EQUIPMENT": { + "materialListTitle": "Liste de Matériel", + "addMaterialButton": "Ajouter", + "noMaterialAvailable": "Aucun matériel disponible.", + "actionsColumn": "Actions", + "nameColumn": "Nom", + "typeColumn": "Type", + "serialNumberColumn": "Numéro de Série", + "descriptionColumn": "Description", + "editButton": "Modifier", + "deleteButton": "Supprimer", + "newMaterialTitle": "Nouveau Matériel", + "editMaterialTitle": "Modifier Matériel", + "materialTypeLabel": "Type de Matériel", + "materialTypes": { + "ElectromagneticFlowMeter": "Courantomètre Électromagnétique", + "PropellerFlowMeter": "Moulinet", + "VelocityHeadRod": "Perche à Charge Dynamique Transparente" }, - "BUTTONS": { - "CREATE_NEW_GAUGING": "Créer un nouveau jaugeage", - "RESET_SESSION": "Réinitialiser la session", - "LOAD_SESSION": "Charger une session", - "SAVE_SESSION": "Enregistrer la session" - }, - "GAUGING": { - "LIST_TITLE": "Liste des Jaugeages", - "ADD_GAUGING": "Ajouter un jaugeage", - "COLUMNS": { - "WATERCOURSE": "Cours d'eau", - "DEPARTMENT": "Département", - "MUNICIPALITY": "Commune", - "LOCALITY": "Lieu-dit", - "DATE": "Date", - "STATE": "État", - "ACTIONS": "Actions" - }, - "VALIDATED": "Validé", - "NO_GAUGING": "Aucun jaugeage réalisé ou en cours de réalisation." - } + "modelSectionTitle": "Modèle", + "nameLabel": "Nom", + "serialNumberLabel": "Numéro de Série", + "propellerNumberLabel": "Numéro de Moulinet", + "propellerSerialNumberLabel": "Numéro de Série du Moulinet", + "velocityFormulaCountLabel": "Nombre de Formules de Vitesse", + "velocityFormulaTitle": "Formule de Vitesse n°", + "lowerBoundLabel": "Limite Inférieure", + "upperBoundLabel": "Limite Supérieure", + "coefALabel": "Coefficient A", + "constantBLabel": "Constante B", + "invalidBoundsError": "Les limites spécifiées sont incorrectes. La limite inférieure doit être strictement inférieure à la limite supérieure.", + "requiredNameError": "Le nom est requis.", + "additionalInfoTitle": "Informations complémentaires", + "descriptionLabel": "Description", + "submitButton": "Valider", + "cancelButton": "Annuler" } - \ No newline at end of file +} \ No newline at end of file -- GitLab From 81c76ac1df27c882f7f25ba5ea681defd7ed95ff Mon Sep 17 00:00:00 2001 From: Jean-Pascal AUBRY <jean-pascal.aubry@inrae.fr> Date: Fri, 11 Oct 2024 15:37:33 +0000 Subject: [PATCH 04/16] fix: translate gauging component in progress Refs #6 --- src/app/app.component.ts | 2 +- .../gauging-list/gauging-list.component.html | 14 +- src/app/views/gauging/gauging.component.html | 143 +++++++++--------- src/app/views/gauging/gauging.component.ts | 3 +- src/assets/i18n/en.json | 143 ++++++++++++------ src/assets/i18n/fr.json | 70 +++++++-- 6 files changed, 236 insertions(+), 139 deletions(-) diff --git a/src/app/app.component.ts b/src/app/app.component.ts index a51cede..234d7d0 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -46,7 +46,7 @@ export class AppComponent { this.gaugingList$ = this.gaugingService.gaugingList$; this.translate.addLangs(['fr', 'en']); this.translate.setDefaultLang('fr'); - this.translate.use('en'); + this.translate.use('fr'); } ngOnInit(): void { diff --git a/src/app/views/gauging-list/gauging-list.component.html b/src/app/views/gauging-list/gauging-list.component.html index a4dd044..1b55a0b 100644 --- a/src/app/views/gauging-list/gauging-list.component.html +++ b/src/app/views/gauging-list/gauging-list.component.html @@ -12,43 +12,43 @@ <!-- Watercourse Column --> <ng-container matColumnDef="watercourse"> - <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.COLUMNS.WATERCOURSE' | translate }} </th> + <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.WATERCOURSE' | translate }} </th> <td mat-cell *matCellDef="let gauging" (click)="editGauging(gauging)" > {{ gauging.watercourse || '-' }} </td> </ng-container> <!-- Department Column --> <ng-container matColumnDef="department"> - <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.COLUMNS.DEPARTMENT' | translate }} </th> + <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.DEPARTMENT' | translate }} </th> <td mat-cell *matCellDef="let gauging"(click)="editGauging(gauging)" > {{ gauging.department || '-' }} </td> </ng-container> <!-- Municipality Column --> <ng-container matColumnDef="municipality"> - <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.COLUMNS.MUNICIPALITY' | translate }} </th> + <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.MUNICIPALITY' | translate }} </th> <td mat-cell *matCellDef="let gauging" (click)="editGauging(gauging)"> {{ gauging.municipality || '-' }} </td> </ng-container> <!-- Locality Column --> <ng-container matColumnDef="locality"> - <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.COLUMNS.LOCALITY' | translate }} </th> + <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.LOCALITY' | translate }} </th> <td mat-cell *matCellDef="let gauging" (click)="editGauging(gauging)"> {{ gauging.locality || '-' }} </td> </ng-container> <!-- Date Column --> <ng-container matColumnDef="date"> - <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.COLUMNS.DATE' | translate }} </th> + <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.DATE' | translate }} </th> <td mat-cell *matCellDef="let gauging" (click)="editGauging(gauging)"> {{ gauging.date | date: 'dd/MM/yyyy' }}</td> </ng-container> <!-- State Column --> <ng-container matColumnDef="state"> - <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.COLUMNS.STATE' | translate }} </th> + <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.STATE' | translate }} </th> <td mat-cell *matCellDef="let gauging" (click)="editGauging(gauging)"> {{ 'GAUGING.VALIDATED' | translate }} </td> </ng-container> <!-- Actions Column --> <ng-container matColumnDef="actions"> - <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.COLUMNS.ACTIONS' | translate }} </th> + <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.ACTIONS' | translate }} </th> <td mat-cell *matCellDef="let gauging, , let i =index"> <button mat-icon-button color="primary" (click)="editGauging(gauging)"> <mat-icon class="edit-button">edit</mat-icon> diff --git a/src/app/views/gauging/gauging.component.html b/src/app/views/gauging/gauging.component.html index 5d00a06..0c016fe 100644 --- a/src/app/views/gauging/gauging.component.html +++ b/src/app/views/gauging/gauging.component.html @@ -1,31 +1,31 @@ <mat-tab-group #tabGroup animationDuration="0ms"> <!-- Tab1: Création/édition d'un jaugeage --> - <mat-tab label="Description du jaugeage"> + <mat-tab label="{{ 'GAUGING.DESCRIPTION' | translate }}"> <div class="tab-content"> - <h2>Description du jaugeage</h2> + <h2><mat-label>{{ 'GAUGING.DESCRIPTION' | translate }}</mat-label></h2> <form [formGroup]="descriptionForm"> <!-- Localisation Section --> <mat-card class="form-section"> - <mat-card-title class="card-title"><mat-icon>location_on</mat-icon>Localisation</mat-card-title> + <mat-card-title class="card-title"><mat-icon>location_on</mat-icon>{{ 'GAUGING.LOCATION' | translate }}</mat-card-title> <mat-card-content> <div class="form-row"> <mat-form-field appearance="outline"> - <mat-label>Cours d'eau</mat-label> + <mat-label>{{ 'GAUGING.WATERCOURSE' | translate }}</mat-label> <input matInput formControlName="watercourse"> </mat-form-field> <mat-form-field appearance="outline"> - <mat-label>Lieu-dit</mat-label> + <mat-label>{{ 'GAUGING.LOCALITY' | translate }}</mat-label> <input matInput formControlName="locality"> </mat-form-field> </div> <div class="form-row"> <mat-form-field appearance="outline"> - <mat-label>Commune</mat-label> + <mat-label>{{ 'GAUGING.MUNICIPALITY' | translate }}</mat-label> <input matInput formControlName="municipality"> </mat-form-field> <mat-form-field appearance="outline"> - <mat-label>Département</mat-label> + <mat-label>{{ 'GAUGING.DEPARTMENT' | translate }}</mat-label> <input matInput formControlName="department"> </mat-form-field> </div> @@ -34,7 +34,7 @@ <!-- Géolocalisation Section --> <mat-card class="form-section"> - <mat-card-title class="card-title"><mat-icon>my_location</mat-icon>Géolocalisation</mat-card-title> + <mat-card-title class="card-title"><mat-icon>my_location</mat-icon>{{ 'GAUGING.GEOLOCATION' | translate }}</mat-card-title> <mat-card-content> <div class="form-row"> <mat-form-field appearance="outline"> @@ -47,11 +47,11 @@ </mat-select> </mat-form-field> <mat-form-field appearance="outline"> - <mat-label>Point X</mat-label> + <mat-label>{{ 'GAUGING.X_LOCATION' | translate }}</mat-label> <input matInput formControlName="locationX" type="number" step="0.01"> </mat-form-field> <mat-form-field appearance="outline"> - <mat-label>Point Y</mat-label> + <mat-label>{{ 'GAUGING.Y_LOCATION' | translate }}</mat-label> <input matInput formControlName="locationY" type="number" step="0.01"> </mat-form-field> </div> @@ -61,24 +61,24 @@ <!-- Date/time section --> <mat-card class="form-section"> <mat-card-title class="card-title"> - <mat-icon>access_time</mat-icon> Date/Heure + <mat-icon>access_time</mat-icon> {{ 'GAUGING.DATE_TIME' | translate }} </mat-card-title> <mat-card-content> <div class="form-row"> <mat-form-field appearance="outline"> - <mat-label>Date</mat-label> + <mat-label>{{ 'GAUGING.DATE' | translate }}</mat-label> <input matInput [matDatepicker]="picker" formControlName="date"> <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle> <mat-datepicker #picker></mat-datepicker> </mat-form-field> <mat-form-field appearance="outline"> - <mat-label>Heure de début</mat-label> + <mat-label>{{ 'GAUGING.START_TIME' | translate }}</mat-label> <input matInput formControlName="timeStart" [format]="24" [max]="getMaxTimeStart()" [ngxTimepicker]="startTimePicker"> <ngx-material-timepicker #startTimePicker></ngx-material-timepicker> </mat-form-field> <mat-form-field appearance="outline"> - <mat-label>Heure de fin</mat-label> + <mat-label>{{ 'GAUGING.END_TIME' | translate }}</mat-label> <input matInput formControlName="timeEnd" [format]="24" [min]="descriptionForm.get('timeStart')?.value" [ngxTimepicker]="endTimePicker"> <ngx-material-timepicker #endTimePicker></ngx-material-timepicker> @@ -91,7 +91,7 @@ <mat-card class="form-section"> <mat-card-title class="card-title"> <div class="card-title-with-button"> - <mat-icon>person</mat-icon> Opérateurs + <mat-icon>person</mat-icon> {{ 'GAUGING.OPERATORS' | translate }} <button mat-mini-fab color="primary" (click)="addOperatorField()" class="add-button"><mat-icon>add</mat-icon></button> @if(operatorNames.length > 2) { @@ -106,7 +106,7 @@ @for (operator of operatorNames.controls; track operator; let i = $index) { <div [formGroupName]="i" class="operator-form-field"> <mat-form-field appearance="outline"> - <mat-label>Opérateur {{i + 1}}</mat-label> + <mat-label>{{ 'GAUGING.OPERATOR' | translate }} {{i + 1}}</mat-label> <input matInput formControlName="name"> </mat-form-field> </div> @@ -118,12 +118,12 @@ <!-- Observations section --> <mat-card class="form-section"> <mat-card-title class="card-title"> - <mat-icon>book</mat-icon> Observations + <mat-icon>book</mat-icon> {{ 'GAUGING.OBSERVATIONS' | translate }} </mat-card-title> <mat-card-content> <div class="form-row"> <mat-form-field appearance="outline" class="full-width"> - <mat-label>Observation</mat-label> + <mat-label>{{ 'GAUGING.OBSERVATION' | translate }}</mat-label> <textarea matInput formControlName="observations" rows="4"></textarea> </mat-form-field> </div> @@ -134,7 +134,7 @@ <mat-card class="form-section"> <mat-card-title class="card-title"> <div class="card-title-with-button"> - <mat-icon>brightness_1</mat-icon> Granulométrie Représentative + <mat-icon>brightness_1</mat-icon> {{ 'GAUGING.REPRESENTATIVE_GRAIN_SIZE' | translate }} <button mat-mini-fab color="primary" (click)="addGrainSizeField()" class="add-button"><mat-icon>add</mat-icon> </button> @@ -149,8 +149,8 @@ <div class="grainSize-container"> @for (grainsize of grainSizesArray.controls; track grainsize; let i = $index) { <div [formGroupName]="i" class="grainSize-form-field"> - <mat-form-field appearance="outline" class="full-width" placeholder="Granulométrie"> - <mat-label>{{ i === 0 ? 'Dominante' : 'Accessoire ' + i }}</mat-label> + <mat-form-field appearance="outline" class="full-width"> + <mat-label>{{ i === 0 ? ('GAUGING.DOMINANT_GRAIN_SIZE' | translate) : ('GAUGING.ACCESSORY_GRAIN_SIZE' | translate) + ' ' + i }}</mat-label> <mat-select formControlName="size" disableRipple> @for (size of grainSizes; track size) { <mat-option [value]="size"> @@ -167,25 +167,24 @@ <!-- Boutons Précédent et Suivant --> <div class="form-buttons"> - <button mat-raised-button color="primary" type="button" (click)="selectNextTab()">Suivant</button> + <button mat-raised-button color="primary" type="button" (click)="selectNextTab()">{{ 'NEXT' | translate }}</button> </div> </form> </div> </mat-tab> <!-- Paramètres --> - <mat-tab label="Paramètres du jaugeage"> + <mat-tab label="{{ 'GAUGING.PARAMETERS' | translate }}"> <div class="tab-content"> - <h2>Paramètres du jaugeage</h2> + <h2>{{ 'GAUGING.PARAMETERS' | translate }}</h2> <form [formGroup]="parametersForm"> <!-- Largeur de la section --> <mat-card class="form-section"> - <mat-card-title class="card-title"><mat-icon>aspect_ratio</mat-icon>Largeur de la - section</mat-card-title> + <mat-card-title class="card-title"><mat-icon>aspect_ratio</mat-icon>{{ 'GAUGING.SECTION_WIDTH' | translate }}</mat-card-title> <mat-card-content class="form-row"> <mat-form-field appearance="outline"> - <mat-label>Largeur (m)</mat-label> + <mat-label>{{ 'GAUGING.WIDTH' | translate }}(m)</mat-label> <input matInput formControlName="sectionWidth" type="number" step="0.01"> </mat-form-field> </mat-card-content> @@ -193,14 +192,14 @@ <!-- Hauteur d'eau en rive --> <mat-card class="form-section"> - <mat-card-title class="card-title"><mat-icon>waves</mat-icon>Hauteur d'eau en rive</mat-card-title> + <mat-card-title class="card-title"><mat-icon>waves</mat-icon>{{ 'GAUGING.HEIGHT_BANK_WATER' | translate }}</mat-card-title> <mat-card-content class="form-row"> <mat-form-field appearance="outline"> - <mat-label>Hauteur d'eau rive gauche (m)</mat-label> + <mat-label>{{ 'GAUGING.HEIGHT_BANK_LEFT' | translate }} (m)</mat-label> <input matInput formControlName="heightBankLeft" type="number" step="0.01"> </mat-form-field> <mat-form-field appearance="outline"> - <mat-label>Hauteur d'eau rive droite (m)</mat-label> + <mat-label>{{ 'GAUGING.HEIGHT_BANK_RIGHT' | translate }} (m)</mat-label> <input matInput formControlName="heightBankRight" type="number" step="0.01"> </mat-form-field> </mat-card-content> @@ -208,8 +207,7 @@ <!-- Origine des mesures --> <mat-card class="form-section"> - <mat-card-title class="card-title"><mat-icon>gps_fixed</mat-icon>Origine des - mesures</mat-card-title> + <mat-card-title class="card-title"><mat-icon>gps_fixed</mat-icon>{{ 'GAUGING.ORIGIN_MEASURES' | translate }}</mat-card-title> <mat-card-content class="form-row"> <div> <mat-radio-group formControlName="originMeasures"> @@ -226,19 +224,19 @@ <!-- Type de matériel --> <mat-card class="form-section"> <mat-card-title class="card-title"><mat-icon>construction</mat-icon> - Type de matériel</mat-card-title> + {{ 'GAUGING.ORIGIN_MEASURES' | translate }}</mat-card-title> <mat-card-content class="form-row"> @if((materialList$ | async)?.length! > 0){ <mat-radio-group formControlName="materialType" (change)="onChangeMaterialType()" style="width: 50%;"> @for (type of materielTypes; track type) { <mat-radio-button [value]="type" color="primary"> - {{type}} + {{type | translate}} </mat-radio-button> } </mat-radio-group> @if(filteredMaterials?.length) { <mat-form-field appearance="outline" class="full-width"> - <mat-label>Choix du matériel</mat-label> + <mat-label>{{ 'GAUGING.MATERIAL_CHOICE' | translate }}</mat-label> <mat-select formControlName="materialId" (selectionChange)="onChangeMaterial()"> @for (material of filteredMaterials ; track material.id) { <mat-option [value]="material.id">{{material.name}} ( n°{{material.serialNumber}} )</mat-option> @@ -249,14 +247,14 @@ } @else { <div class="no-material-message" (click)="openMaterialForm()"> - <p>Aucun matériel de ce type</p> + <p>{{ 'NO_AVALAIBLE_MATERIAL' | translate }}</p> <button mat-mini-fab color="primary"><mat-icon>add</mat-icon></button> </div> } } @else { <div class="no-material-message" (click)="openMaterialForm()"> - <p>Veuillez ajouter d'abord le matériel</p> + <p>{{ 'NEED_MATERIAL' | translate }}</p> <button mat-mini-fab color="primary"><mat-icon>add</mat-icon></button> </div> } @@ -266,23 +264,23 @@ <div class="form-buttons"> - <button mat-raised-button color="primary" type="button" (click)="selectPreviousTab()">Précédent</button> - <button mat-raised-button color="primary" type="button" (click)="selectNextTab()">Suivant</button> + <button mat-raised-button color="primary" type="button" (click)="selectPreviousTab()">{{ 'PREVIOUS' | translate }}</button> + <button mat-raised-button color="primary" type="button" (click)="selectNextTab()">{{ 'NEXT' | translate }}</button> </div> </form> </div> </mat-tab> <!-- Saisies des mesures --> - <mat-tab label="Saisie des mesures" ngSkipHydration [disabled]="!this.selectedMaterialId"> + <mat-tab label="{{ 'GAUGING.TAB_MEASUREMENTS' | translate }}" ngSkipHydration [disabled]="!this.selectedMaterialId"> <div class="tab-content"> - <h2>Saisie des mesures</h2> + <h2>{{ 'GAUGING.TAB_MEASUREMENTS' | translate }}</h2> <div class="vertical-section-container"> <!-- Verticales --> <mat-card class="form-section"> <mat-card-title class="vertical-card-title"> <mat-icon> vertical_align_bottom</mat-icon> - Verticales + {{ 'GAUGING.VERTICALS' | translate }} <button mat-mini-fab color="primary" (click)="addVertical()" class="add-button"> <mat-icon>add</mat-icon> </button> @@ -291,7 +289,8 @@ <div formArrayName="verticals"> <table mat-table [dataSource]="verticals.controls" #verticalsTable class="mat-elevation-z2"> <ng-container matColumnDef="verticalNumber"> - <th mat-header-cell *matHeaderCellDef class="vertical-number"> Verticales n° </th> + <th mat-header-cell *matHeaderCellDef class="vertical-number"> {{ 'GAUGING.VERTICAL_NUMBER' | translate }} + </th> <td mat-cell *matCellDef="let vertical; let i = index" (click)="onVerticalUpdate(i)" class="vertical-number" [ngClass]="{ 'selected-vertical': i === selectedVerticalIndex && i !== deletingRowIndex, @@ -303,17 +302,17 @@ <!-- Repeat for other columns --> <ng-container matColumnDef="distanceFromBank"> - <th mat-header-cell *matHeaderCellDef> Distance à la rive (m) </th> + <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.DISTANCE_FROM_BANK' | translate }} </th> <td mat-cell *matCellDef="let vertical; let i = index" (click)="onVerticalUpdate(i)" [ngClass]="{ 'selected-vertical': i === selectedVerticalIndex && i !== deletingRowIndex, 'deleting': i === deletingRowIndex }" (focusin)="onRowFocusIn(i)" (focusout)="onRowFocusOut(i)"> <div [formGroupName]="i"> <mat-form-field appearance="outline" class="vertical-table-field"> - <input matInput formControlName="distanceFromBank" placeholder="Distance" type="number" + <input matInput formControlName="distanceFromBank" placeholder="{{ 'GAUGING.DISTANCE' | translate }}" type="number" min="0"> @if(vertical.get('distanceFromBank')?.hasError('invalidDistanceFromBank')) { - <mat-error>Distance invalide</mat-error> + <mat-error>{{ 'GAUGING.INVALID_DISTANCE' | translate }}</mat-error> } </mat-form-field> @@ -323,14 +322,14 @@ <!-- Repeat for other columns --> <ng-container matColumnDef="depth"> - <th mat-header-cell *matHeaderCellDef> Profondeur (m) </th> + <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.DEPTH' | translate }}</th> <td mat-cell *matCellDef="let vertical; let i = index" (click)="onVerticalUpdate(i)" [ngClass]="{ 'selected-vertical': i === selectedVerticalIndex && i !== deletingRowIndex, 'deleting': i === deletingRowIndex }" (focusin)="onRowFocusIn(i)" (focusout)="onRowFocusOut(i)"> <div [formGroupName]="i"> <mat-form-field appearance="outline" class="vertical-table-field"> - <input matInput formControlName="depth" placeholder="Profondeur" type="number" step="1" min="0"> + <input matInput formControlName="depth" placeholder="{{ 'GAUGING.DEPTH' | translate }}" type="number" step="1" min="0"> </mat-form-field> </div> </td> @@ -338,14 +337,14 @@ <!-- Repeat for other columns --> <ng-container matColumnDef="duration"> - <th mat-header-cell *matHeaderCellDef> Durée(s) </th> + <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.DURATION' | translate }} </th> <td mat-cell *matCellDef="let vertical; let i = index" (click)="onVerticalUpdate(i)" [ngClass]="{ 'selected-vertical': i === selectedVerticalIndex && i !== deletingRowIndex, 'deleting': i === deletingRowIndex }" (focusin)="onRowFocusIn(i)" (focusout)="onRowFocusOut(i)"> <div [formGroupName]="i"> <mat-form-field appearance="outline" class="vertical-table-field"> - <input matInput formControlName="duration" placeholder="Durée" type="number" step="1" min="0"> + <input matInput formControlName="duration" placeholder="{{ 'GAUGING.DURATION' | translate }}" type="number" step="1" min="0"> </mat-form-field> </div> </td> @@ -353,7 +352,7 @@ <!-- Repeat for other columns --> <ng-container matColumnDef="numberOfPoint"> - <th mat-header-cell *matHeaderCellDef> Nombre de points </th> + <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.NUMBER_OF_POINTS' | translate }} </th> <td mat-cell *matCellDef="let vertical; let i = index" (click)="onVerticalUpdate(i)" [ngClass]="{ 'selected-vertical': i === selectedVerticalIndex && i !== deletingRowIndex, 'deleting': i === deletingRowIndex @@ -368,7 +367,7 @@ </ng-container> <ng-container matColumnDef="delete"> - <th mat-header-cell *matHeaderCellDef> Actions </th> + <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.ACTIONS' | translate }} </th> <td mat-cell *matCellDef="let vertical; let i = index" [ngClass]="{ 'selected-vertical': i === selectedVerticalIndex && i !== deletingRowIndex, 'deleting': i === deletingRowIndex @@ -397,7 +396,7 @@ <mat-card class="form-section"> <mat-card-title class="vertical-card-title"> <mat-icon>gps_fixed</mat-icon> - Mesures sur la verticale n°{{ selectedVerticalIndex + 1 }} + {{ 'GAUGING.MEASUREMENTS_ON_VERTICAL' | translate }} {{ selectedVerticalIndex + 1 }} </mat-card-title> <mat-card-content [formGroup]="verticalsForm"> <div formArrayName="verticals"> @@ -407,12 +406,12 @@ class="mat-elevation-z2" #verticalMeasurementsTable> <!-- Distance From Bottom Column --> <ng-container matColumnDef="distanceFromBottom"> - <th mat-header-cell *matHeaderCellDef> Distance du fond (m) </th> + <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.DISTANCE_FROM_BOTTOM' | translate }} </th> <td mat-cell *matCellDef="let measurement; let i = index" (click)="onVerticalMeasurementUpdate(i)"> <div [formGroupName]="i"> <mat-form-field appearance="outline" class="vertical-table-field"> - <input matInput formControlName="distanceFromBottom" placeholder="Distance" min="0" + <input matInput formControlName="distanceFromBottom" placeholder="{{ 'GAUGING.DISTANCE' | translate }}" min="0" readonly="readonly"> </mat-form-field> </div> @@ -421,12 +420,12 @@ <!-- Speed Column --> <ng-container matColumnDef="speed"> - <th mat-header-cell *matHeaderCellDef> Vitesse (m/s) </th> + <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.SPEED' | translate }} </th> <td mat-cell *matCellDef="let measurement; let i = index" (click)="onVerticalMeasurementUpdate(i)"> <div [formGroupName]="i"> <mat-form-field appearance="outline" class="vertical-table-field"> - <input matInput formControlName="speed" placeholder="Vitesse" type="number" step="0.01" + <input matInput formControlName="speed" placeholder="{{ 'GAUGING.SPEED' | translate }}" type="number" step="0.01" min="0"> </mat-form-field> </div> @@ -435,7 +434,7 @@ <!-- Rotation Column (Conditionnelle) --> <ng-container matColumnDef="rotations"> - <th mat-header-cell *matHeaderCellDef> Rotations </th> + <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.ROTATIONS' | translate }} </th> <td mat-cell *matCellDef="let measurement; let i = index" (click)="onVerticalMeasurementUpdate(i)"> <div [formGroupName]="i"> @@ -463,18 +462,18 @@ <!-- Résultats --> - <mat-tab label="Résultats" ngSkipHydration [disabled]="!this.selectedMaterialId"> + <mat-tab label="{{ 'GAUGING.TAB_RESULTS' | translate }}" ngSkipHydration [disabled]="!this.selectedMaterialId"> <div class="tab-content"> - <h2>Résultats</h2> + <h2>{{ 'RESULTS.TAB_RESULTS' | translate }}</h2> <!-- Résultats par verticale --> <mat-card class="form-section"> <mat-card-title class="vertical-card-title"> - <mat-icon>equalizer</mat-icon> Résultats par verticale + <mat-icon>equalizer</mat-icon> {{ 'GAUGING.RESULTS_PER_VERTICAL' | translate }} </mat-card-title> <mat-card-content> <table mat-table [dataSource]="verticalResults" class="mat-elevation-z2"> <ng-container matColumnDef="verticalNumber"> - <th mat-header-cell *matHeaderCellDef class="vertical-number"> Verticales n° </th> + <th mat-header-cell *matHeaderCellDef class="vertical-number"> {{ 'GAUGING.VERTICAL_NUMBER' | translate }} </th> <td mat-cell *matCellDef="let vertical; let i = index" class="vertical-number"> {{i+1}} </td> @@ -482,33 +481,33 @@ <!-- Distance from Bank Column --> <ng-container matColumnDef="distanceFromBank"> - <th mat-header-cell *matHeaderCellDef> Distance à la rive (m) </th> + <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.DISTANCE_FROM_BANK' | translate }} </th> <td mat-cell *matCellDef="let vertical"> {{vertical.distanceFromBank}} </td> </ng-container> <!-- Depth Column --> <ng-container matColumnDef="depth"> - <th mat-header-cell *matHeaderCellDef> Profondeur (m) </th> + <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.DEPTH' | translate }} </th> <td mat-cell *matCellDef="let vertical"> {{vertical.depth}} </td> </ng-container> <!-- Speed Column --> <ng-container matColumnDef="speed"> - <th mat-header-cell *matHeaderCellDef> Vitesse moyenne (m/s) </th> + <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.AVERAGE_SPEED' | translate }} </th> <td mat-cell *matCellDef="let vertical" style="font-weight: bold; color:#735fff "> {{vertical.averageSpeed.toFixed(3)}} </td> </ng-container> <!-- Surface Column --> <ng-container matColumnDef="surface"> - <th mat-header-cell *matHeaderCellDef> Surface (m²) </th> + <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.SURFACE' | translate }} </th> <td mat-cell *matCellDef="let vertical; let i = index" class="surface-cell" style="font-weight: bold; color:#00a3a6;"> {{ vertical.surface.toFixed(3) }}</td> </ng-container> <!-- Flow Column --> <ng-container matColumnDef="flow"> - <th mat-header-cell *matHeaderCellDef> Débit (m³/s) </th> + <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.FLOW' | translate }} </th> <td mat-cell *matCellDef="let vertical; let i = index" style="font-weight: bold; color:#ff6347;"> {{vertical.flow.toFixed(3)}}</td> </ng-container> @@ -525,23 +524,23 @@ <!-- Résultats globaux --> <mat-card class="form-section"> <mat-card-title class="vertical-card-title"> - <mat-icon>assessment</mat-icon> Résultats globaux du jaugeage + <mat-icon>assessment</mat-icon>{{ 'GAUGING.OVERALL_GAUGING_RESULTS' | translate }} </mat-card-title> <mat-card-content> <div class="global-results-grid"> <div class="global-result-card"> <mat-icon class="result-icon">crop_square</mat-icon> - <h3>Surface totale</h3> + <h3>{{ 'GAUGING.TOTAL_SURFACE' | translate }}</h3> <div class="result-value">{{ calculateTotalSurface(verticalResults).toFixed(3) }} m²</div> </div> <div class="global-result-card"> <mat-icon class="result-icon">speed</mat-icon> - <h3>Vitesse moyenne</h3> + <h3>{{ 'GAUGING.AVERAGE_SPEED' | translate }}</h3> <div class="result-value">{{calculateAverageSpeedSection().toFixed(3)}} m/s</div> </div> <div class="global-result-card"> <mat-icon class="result-icon">waves</mat-icon> - <h3>Débit total</h3> + <h3>{{ 'GAUGING.TOTAL_FLOW' | translate }}</h3> <div class="result-value">{{ calculateTotalFlow(verticalResults).toFixed(3) }} m³/s</div> </div> </div> @@ -551,7 +550,7 @@ <!-- Représentation graphique des champs de vitesse --> <mat-card class="form-section"> <mat-card-title class="vertical-card-title"> - <mat-icon>show_chart</mat-icon> Représentation des champs de vitesse + <mat-icon>show_chart</mat-icon> {{ 'GAUGING.GRAPHICAL_REPRESENTATION' | translate }} </mat-card-title> <mat-card-content> <!-- Placeholder for the graph --> diff --git a/src/app/views/gauging/gauging.component.ts b/src/app/views/gauging/gauging.component.ts index 9ef2c47..27b952e 100644 --- a/src/app/views/gauging/gauging.component.ts +++ b/src/app/views/gauging/gauging.component.ts @@ -34,12 +34,13 @@ import { Vertical } from '../../models/vertical'; import { MaterialPropeller } from '../../models/material_propeller'; import { rowsAnimation } from '../../tools/Animations/table-row-animation'; import { animate, state, style, transition, trigger } from '@angular/animations'; +import { TranslateModule } from '@ngx-translate/core'; Chart.register(...registerables) @Component({ selector: 'app-gauging', standalone: true, - imports: [MatNativeDateModule, MatDatepickerModule, NgxMaterialTimepickerModule, MatTabsModule, ReactiveFormsModule, FormsModule, CommonModule, MatCardModule, MatFormFieldModule, MatSelectModule, MatRadioModule, MatInputModule, MatButtonModule, MatTableModule, MatIconModule, ErrorMessageComponent, BaseChartDirective,], + imports: [TranslateModule, MatNativeDateModule, MatDatepickerModule, NgxMaterialTimepickerModule, MatTabsModule, ReactiveFormsModule, FormsModule, CommonModule, MatCardModule, MatFormFieldModule, MatSelectModule, MatRadioModule, MatInputModule, MatButtonModule, MatTableModule, MatIconModule, ErrorMessageComponent, BaseChartDirective,], templateUrl: './gauging.component.html', styleUrls: ['./gauging.component.scss'], providers: [DatePipe], diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 97b37ed..75b1c9f 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -24,53 +24,102 @@ "GAUGING": { "LIST_TITLE": "Gauging List", "ADD_GAUGING": "Add Gauging", - "COLUMNS": { - "WATERCOURSE": "Watercourse", - "DEPARTMENT": "Department", - "MUNICIPALITY": "Municipality", - "LOCALITY": "Locality", - "DATE": "Date", - "STATE": "State", - "ACTIONS": "Actions" - }, + "WATERCOURSE": "Watercourse", + "DEPARTMENT": "Department", + "MUNICIPALITY": "Municipality", + "LOCALITY": "Locality", + "DATE": "Date", + "STATE": "State", + "ACTIONS": "Actions", "VALIDATED": "Validated", - "NO_GAUGING": "No gauging has been carried out or is in progress." + "NO_GAUGING": "No gauging has been carried out or is in progress.", + "DESCRIPTION": "Gauging description", + "LOCATION": "Location", + "GEOLOCATION": "Geolocation", + "X_LOCATION": "Point X", + "Y_LOCATION": "Point Y", + "DATE_TIME": "Date/Time", + "START_TIME": "Start time", + "END_TIME": "End time", + "OPERATORS": "Operators", + "OPERATOR": "Operator", + "OBSERVATIONS": "Observations", + "OBSERVATION": "Observation", + "REPRESENTATIVE_GRAIN_SIZE": "Representative grain size", + "DOMINANT_GRAIN_SIZE": "Dominant", + "ACCESSORY_GRAIN_SIZE": "Accessory", + "PARAMETERS": "Gauging parameters", + "SECTION_WIDTH": "Section width", + "WIDTH": "Width", + "HEIGHT_BANK_WATER": "Height of water on bank", + "HEIGHT_BANK_LEFT": "Height bank left", + "HEIGHT_BANK_RIGHT": "Height bank right", + "ORIGIN_MEASURES": "Origin of measures", + "MATERIAL_CHOICE": "Material choice", + "TAB_MEASUREMENTS": "Measurement entries", + "VERTICALS": "Verticals", + "VERTICAL_NUMBER": "Vertical n°", + "DISTANCE_FROM_BANK": "Distance from bank (m)", + "DEPTH": "Depth (m)", + "DURATION": "Duration (s)", + "NUMBER_OF_POINTS": "Number of points", + "INVALID_DISTANCE": "Distance from bank must be less than or equal to section width", + "MEASUREMENTS_ON_VERTICAL": "Measurements on vertical n°", + "DISTANCE_FROM_BOTTOM": "Distance from bottom (m)", + "SPEED": "Speed (m/s)", + "ROTATIONS": "Number of rotations", + "ROTATION_NUMBER": "Rotations", + "DISTANCE": "Distance", + "TAB_RESULTS": "Results", + "RESULTS_PER_VERTICAL": "Results by Vertical", + "AVERAGE_SPEED": "Average Speed (m/s)", + "SURFACE": "Surface Area (m²)", + "FLOW": "Flow Rate (m³/s)", + "OVERALL_GAUGING_RESULTS": "Overall gauging results", + "TOTAL_SURFACE": "Total Surface (m²)", + "AVERAGE_SPEED_GLOBAL": "Average Speed", + "TOTAL_FLOW": "Total Flow Rate (m³/s)", + "GRAPHICAL_REPRESENTATION": "Graphical representation" +}, +"EQUIPMENT": { + "materialListTitle": "Material List", + "addMaterialButton": "Add", + "noMaterialAvailable": "No material available.", + "actionsColumn": "Actions", + "nameColumn": "Name", + "typeColumn": "Type", + "serialNumberColumn": "Serial Number", + "descriptionColumn": "Description", + "editButton": "Edit", + "deleteButton": "Delete", + "newMaterialTitle": "New Material", + "editMaterialTitle": "Edit Material", + "materialTypeLabel": "Material Type", + "materialTypes": { + "ElectromagneticFlowMeter": "Electromagnetic Flow Meter", + "PropellerFlowMeter": "Propeller Flow Meter", + "VelocityHeadRod": "Velocity Head Rod" }, - "EQUIPMENT": { - "materialListTitle": "Material List", - "addMaterialButton": "Add", - "noMaterialAvailable": "No material available.", - "actionsColumn": "Actions", - "nameColumn": "Name", - "typeColumn": "Type", - "serialNumberColumn": "Serial Number", - "descriptionColumn": "Description", - "editButton": "Edit", - "deleteButton": "Delete", - "newMaterialTitle": "New Material", - "editMaterialTitle": "Edit Material", - "materialTypeLabel": "Material Type", - "materialTypes": { - "ElectromagneticFlowMeter": "Electromagnetic Flow Meter", - "PropellerFlowMeter": "Propeller Flow Meter", - "VelocityHeadRod": "Velocity Head Rod" - }, - "modelSectionTitle": "Model", - "nameLabel": "Name", - "serialNumberLabel": "Serial Number", - "propellerNumberLabel": "Propeller Number", - "propellerSerialNumberLabel": "Propeller Serial Number", - "velocityFormulaCountLabel": "Number of Velocity Formulas", - "velocityFormulaTitle": "Velocity Formula n°", - "lowerBoundLabel": "Lower Bound", - "upperBoundLabel": "Upper Bound", - "coefALabel": "Coefficient A", - "constantBLabel": "Constant B", - "invalidBoundsError": "The specified bounds are incorrect. The lower bound must be strictly less than the upper bound.", - "requiredNameError": "The name is required.", - "additionalInfoTitle": "Additional information", - "descriptionLabel": "Description", - "submitButton": "Submit", - "cancelButton": "Cancel" - } + "modelSectionTitle": "Model", + "nameLabel": "Name", + "serialNumberLabel": "Serial Number", + "propellerNumberLabel": "Propeller Number", + "propellerSerialNumberLabel": "Propeller Serial Number", + "velocityFormulaCountLabel": "Number of Velocity Formulas", + "velocityFormulaTitle": "Velocity Formula n°", + "lowerBoundLabel": "Lower Bound", + "upperBoundLabel": "Upper Bound", + "coefALabel": "Coefficient A", + "constantBLabel": "Constant B", + "invalidBoundsError": "The specified bounds are incorrect. The lower bound must be strictly less than the upper bound.", + "requiredNameError": "The name is required.", + "additionalInfoTitle": "Additional information", + "descriptionLabel": "Description", + "submitButton": "Submit", + "cancelButton": "Cancel" +}, +"NEXT": "Next", +"PREVIOUS": "Previous", +"NO_AVALAIBLE_MATERIAL": "No material of this type", +"NEED_MATERIAL": "Please add the equipment first" } \ No newline at end of file diff --git a/src/assets/i18n/fr.json b/src/assets/i18n/fr.json index ea92bc4..13a20fd 100644 --- a/src/assets/i18n/fr.json +++ b/src/assets/i18n/fr.json @@ -24,17 +24,61 @@ "GAUGING": { "LIST_TITLE": "Liste des Jaugeages", "ADD_GAUGING": "Ajouter un jaugeage", - "COLUMNS": { - "WATERCOURSE": "Cours d'eau", - "DEPARTMENT": "Département", - "MUNICIPALITY": "Commune", - "LOCALITY": "Lieu-dit", - "DATE": "Date", - "STATE": "État", - "ACTIONS": "Actions" - }, + "WATERCOURSE": "Cours d'eau", + "DEPARTMENT": "Département", + "MUNICIPALITY": "Commune", + "LOCALITY": "Lieu-dit", + "DATE": "Date", + "STATE": "État", + "ACTIONS": "Actions", "VALIDATED": "Validé", - "NO_GAUGING": "Aucun jaugeage réalisé ou en cours de réalisation." + "NO_GAUGING": "Aucun jaugeage réalisé ou en cours de réalisation.", + "DESCRIPTION": "Description du jaugeage", + "LOCATION": "Localisation", + "GEOLOCATION": "Géolcalisation", + "X_LOCATION": "Point X", + "Y_LOCATION": "Point Y", + "DATE_TIME": "Date/Heure", + "START_TIME": "Heure de début", + "END_TIME": "End time", + "OPERATORS": "Operators", + "OPERATOR": "Operator", + "OBSERVATIONS": "Observations", + "OBSERVATION": "Observation", + "DOMINANT_GRAIN_SIZE": "Dominante", + "ACCESSORY_GRAIN_SIZE": "Accessoire", + "PARAMETERS": "Paramètres du jaugeage", + "SECTION_WIDTH": "Largeur de la section", + "WIDTH": "Largeur", + "HEIGHT_BANK_WATER": "Hauteur d'eau en rive", + "HEIGHT_BANK_LEFT": "Hauteur rive gauche", + "HEIGHT_BANK_RIGHT": "Hauteur rive droite", + "ORIGIN_MEASURES": "Origine des mesures", + "MATERIAL_TYPE": "Type de matériel", + "MATERIAL_CHOICE": "Choix du matériel", + "TAB_MEASUREMENTS": "Saisies des mesures", + "VERTICALS": "Verticales", + "VERTICAL_NUMBER": "Verticale n°", + "DISTANCE_FROM_BANK": "Distance à la rive (m)", + "DEPTH": "Profondeur (m)", + "DURATION": "Durée (s)", + "NUMBER_OF_POINTS": "Nombre de points", + "INVALID_DISTANCE": "La distance à la rive doit être inférieure ou égale à la largeur de la section", + "MEASUREMENTS_ON_VERTICAL": "Mesures sur la verticale n°", + "DISTANCE_FROM_BOTTOM": "Distance au fond (m)", + "SPEED": "Vitesse (m/s)", + "ROTATIONS": "Rotations", + "ROTATION_NUMBER": "Tours", + "DISTANCE": "Distance", + "TAB_RESULTS": "Résultats", + "RESULTS_PER_VERTICAL": "Résultats par verticale", + "AVERAGE_SPEED": "Vitesse moyenne (m/s)", + "SURFACE": "Surface (m²)", + "FLOW": "Débit (m³/s)", + "OVERALL_GAUGING_RESULTS": "Résultats globaux du jaugeage", + "TOTAL_SURFACE": "Surface totale (m²)", + "TOTAL_FLOW": "Débit total (m³/s)", + "GRAPHICAL_REPRESENTATION": "Représentation graphique" }, "EQUIPMENT": { "materialListTitle": "Liste de Matériel", @@ -72,5 +116,9 @@ "descriptionLabel": "Description", "submitButton": "Valider", "cancelButton": "Annuler" - } + }, + "NEXT": "Suivant", + "PREVIOUS": "Précédent", + "NO_AVALAIBLE_MATERIAL": "Aucun matériel de ce type", + "NEED_MATERIAL": "Veuillez ajouter d'abord le matériel" } \ No newline at end of file -- GitLab From e4f6661429a4bd02abb71dae48baebdf9c7bb414 Mon Sep 17 00:00:00 2001 From: Jean-Pascal AUBRY <jean-pascal.aubry@inrae.fr> Date: Mon, 14 Oct 2024 07:48:27 +0000 Subject: [PATCH 05/16] fix: translate dialog new session Refs #6 --- src/app/app.component.ts | 2 +- .../dialog-new-session.component.html | 25 +++++++++++-------- .../dialog-new-session.component.ts | 3 ++- src/assets/i18n/en.json | 6 +++++ src/assets/i18n/fr.json | 6 +++++ 5 files changed, 29 insertions(+), 13 deletions(-) diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 234d7d0..a51cede 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -46,7 +46,7 @@ export class AppComponent { this.gaugingList$ = this.gaugingService.gaugingList$; this.translate.addLangs(['fr', 'en']); this.translate.setDefaultLang('fr'); - this.translate.use('fr'); + this.translate.use('en'); } ngOnInit(): void { diff --git a/src/app/components/dialog/dialog-new-session/dialog-new-session/dialog-new-session.component.html b/src/app/components/dialog/dialog-new-session/dialog-new-session/dialog-new-session.component.html index b2fdb62..5b6aa91 100644 --- a/src/app/components/dialog/dialog-new-session/dialog-new-session/dialog-new-session.component.html +++ b/src/app/components/dialog/dialog-new-session/dialog-new-session/dialog-new-session.component.html @@ -1,11 +1,14 @@ -<h2 mat-dialog-title class="dialog-title"><mat-icon color="warn">warning</mat-icon> Réinitialiser la session</h2> - <mat-dialog-content> - Attention! La session actuelle sera perdue. - <mat-dialog-actions> - <button mat-raised-button [mat-dialog-close]="'confirm'" color="primary" cdkFocusInitial>Confirmer</button> - <button mat-raised-button mat-dialog-close color="warn">Annuler</button> - </mat-dialog-actions> - - - - +<h2 mat-dialog-title class="dialog-title"> + <mat-icon color="warn">warning</mat-icon> {{ 'DIALOG.RESET_SESSION_TITLE' | translate }} +</h2> +<mat-dialog-content> + {{ 'DIALOG.RESET_SESSION_WARNING' | translate }} +</mat-dialog-content> +<mat-dialog-actions> + <button mat-raised-button [mat-dialog-close]="'confirm'" color="primary" cdkFocusInitial> + {{ 'DIALOG.CONFIRM_BUTTON' | translate }} + </button> + <button mat-raised-button mat-dialog-close color="warn"> + {{ 'DIALOG.CANCEL_BUTTON' | translate }} + </button> +</mat-dialog-actions> diff --git a/src/app/components/dialog/dialog-new-session/dialog-new-session/dialog-new-session.component.ts b/src/app/components/dialog/dialog-new-session/dialog-new-session/dialog-new-session.component.ts index dd42cd6..c09f03b 100644 --- a/src/app/components/dialog/dialog-new-session/dialog-new-session/dialog-new-session.component.ts +++ b/src/app/components/dialog/dialog-new-session/dialog-new-session/dialog-new-session.component.ts @@ -2,11 +2,12 @@ import { Component } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; import { MatDialogActions, MatDialogClose, MatDialogContent } from '@angular/material/dialog'; import { MatIcon } from '@angular/material/icon'; +import { TranslateModule } from '@ngx-translate/core'; @Component({ selector: 'app-dialog-new-session', standalone: true, - imports: [MatIcon, MatDialogActions, MatDialogClose, MatDialogContent, MatButtonModule], + imports: [MatIcon, MatDialogActions, MatDialogClose, MatDialogContent, MatButtonModule, TranslateModule], templateUrl: './dialog-new-session.component.html', styleUrl: './dialog-new-session.component.scss' }) diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 75b1c9f..b45d645 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -21,6 +21,12 @@ "LOAD_SESSION": "Load Session", "SAVE_SESSION": "Save Session" }, + "DIALOG": { + "RESET_SESSION_TITLE": "Reset Session", + "RESET_SESSION_WARNING": "Warning! The current session will be lost.", + "CONFIRM_BUTTON": "Confirm", + "CANCEL_BUTTON": "Cancel" + }, "GAUGING": { "LIST_TITLE": "Gauging List", "ADD_GAUGING": "Add Gauging", diff --git a/src/assets/i18n/fr.json b/src/assets/i18n/fr.json index 13a20fd..155f488 100644 --- a/src/assets/i18n/fr.json +++ b/src/assets/i18n/fr.json @@ -21,6 +21,12 @@ "LOAD_SESSION": "Charger une session", "SAVE_SESSION": "Enregistrer la session" }, + "DIALOG": { + "RESET_SESSION_TITLE": "Réinitialiser la session", + "RESET_SESSION_WARNING": "Attention! La session actuelle sera perdue.", + "CONFIRM_BUTTON": "Confirmer", + "CANCEL_BUTTON": "Annuler" + }, "GAUGING": { "LIST_TITLE": "Liste des Jaugeages", "ADD_GAUGING": "Ajouter un jaugeage", -- GitLab From 7c6e3b0f0f4dbc1cdce5e04ea7eef2914de53f9f Mon Sep 17 00:00:00 2001 From: Jean-Pascal AUBRY <jean-pascal.aubry@inrae.fr> Date: Mon, 14 Oct 2024 08:57:07 +0000 Subject: [PATCH 06/16] fix: translate dialog load session and mat-expanson-panel Refs #6 --- .../dialog-load-session.component.html | 20 +++++++++---------- .../dialog-load-session.component.ts | 3 ++- .../mat-expansion-panel.component.ts | 12 +++++++---- src/assets/i18n/en.json | 14 ++++++++++++- src/assets/i18n/fr.json | 14 ++++++++++++- 5 files changed, 46 insertions(+), 17 deletions(-) diff --git a/src/app/components/dialog/dialog-load-session/dialog-load-session/dialog-load-session.component.html b/src/app/components/dialog/dialog-load-session/dialog-load-session/dialog-load-session.component.html index 6c3ff1f..c180176 100644 --- a/src/app/components/dialog/dialog-load-session/dialog-load-session/dialog-load-session.component.html +++ b/src/app/components/dialog/dialog-load-session/dialog-load-session/dialog-load-session.component.html @@ -1,7 +1,7 @@ -<h2 mat-dialog-title class="dialog-title">Charger une session</h2> +<h2 mat-dialog-title class="dialog-title">{{ 'DIALOG.LOAD_SESSION_TITLE' | translate }}</h2> <mat-dialog-content> <mat-form-field class="file-input-field" [formGroup]="loadingForm" appearance="outline"> - <mat-label>Choisir un fichier</mat-label> + <mat-label>{{ 'DIALOG.CHOOSE_FILE_LABEL' | translate }}</mat-label> <ngx-mat-file-input id="session-file-input" formControlName="file" (change)="onFileSelected($event)" #sessionFile> </ngx-mat-file-input> @if(!sessionFile.empty) { @@ -12,31 +12,31 @@ </mat-form-field> @if(!sessionFile.empty) { @if(materialList.length > 0 && !notJSONfile && !invalidJSONFile) { - <app-mat-expansion-panel [panelTitle]="panelEquipmentTitle" [panelItems]="materialList" [panelItems]="materialList"></app-mat-expansion-panel> + <app-mat-expansion-panel [panelTitle]="'DIALOG.PANEL_EQUIPMENT_TITLE' | translate" [panelItems]="materialList" [panelItems]="materialList"></app-mat-expansion-panel> } @if(gaugingsList.length > 0 && !notJSONfile && !invalidJSONFile) { - <app-mat-expansion-panel [panelTitle]="panelGaugingTitle" [panelItems]="gaugingsList"></app-mat-expansion-panel> + <app-mat-expansion-panel [panelTitle]="'DIALOG.PANEL_GAUGING_TITLE' | translate" [panelItems]="gaugingsList"></app-mat-expansion-panel> } @if(notJSONfile) { - <p><mat-icon color="warn">error_outline</mat-icon>Le fichier téléchargé est invalide</p> + <p><mat-icon color="warn">error_outline</mat-icon>{{ 'DIALOG.INVALID_FILE' | translate }}</p> } @if(invalidJSONFile) { - <p><mat-icon color="warn">error_outline</mat-icon>Le fichier JSON contient des données incorrectes</p> + <p><mat-icon color="warn">error_outline</mat-icon>{{ 'DIALOG.INVALID_JSON_FILE' | translate }}</p> } <!-- @if(duplicatedEquipment) { <p><mat-icon color="warn">error_outline</mat-icon>Impossible d'ajouter un équipement déjà existant</p> } --> } @else { - <p style="color: red">Veuillez télécharger un fichier</p> + <p style="color: red">{{ 'DIALOG.UPLOAD_PROMPT' | translate }}</p> } @if(equipmentService.getAllEquipment().length || gaugingService.getAllGauging().length) { <mat-checkbox color="primary" [(ngModel)]="clearCurrentSession" (ngModelChange)="onClearCurrentSessionChange($event)"> - <span>Vider la session en cours</span> + <span>{{ 'DIALOG.CLEAR_SESSION_CHECKBOX' | translate }}</span> </mat-checkbox> } <mat-dialog-actions> <button mat-raised-button mat-dialog-close color="primary" (click)="loadSession()" - [disabled]="sessionFile.empty||notJSONfile || invalidJSONFile" [mat-dialog-close]="'confirm'">Confirmer</button> - <button mat-raised-button color="warn" cdkFocusInitial mat-dialog-close>Annuler</button> + [disabled]="sessionFile.empty||notJSONfile || invalidJSONFile" [mat-dialog-close]="'confirm'">{{ 'DIALOG.CONFIRM_BUTTON' | translate }}</button> + <button mat-raised-button color="warn" cdkFocusInitial mat-dialog-close>{{ 'DIALOG.CANCEL_BUTTON' | translate }}</button> </mat-dialog-actions> \ No newline at end of file diff --git a/src/app/components/dialog/dialog-load-session/dialog-load-session/dialog-load-session.component.ts b/src/app/components/dialog/dialog-load-session/dialog-load-session/dialog-load-session.component.ts index 57cb7d0..e6827fe 100644 --- a/src/app/components/dialog/dialog-load-session/dialog-load-session/dialog-load-session.component.ts +++ b/src/app/components/dialog/dialog-load-session/dialog-load-session/dialog-load-session.component.ts @@ -18,12 +18,13 @@ import { Session } from '../../../../models/session'; import { Gauging } from '../../../../models/gauging'; import { GaugingService } from '../../../../services/gauging.service'; import { MaterialPropeller } from '../../../../models/material_propeller'; +import { TranslateModule, TranslateService } from '@ngx-translate/core'; @Component({ selector: 'app-dialog-load-session', standalone: true, templateUrl: './dialog-load-session.component.html', styleUrl: './dialog-load-session.component.scss', - imports: [MatExpansionPanelComponent, MatListModule, MatCheckboxModule, MatExpansionModule, MaterialFileInputModule, MatDialogClose, MatDialogActions, MatDialogContent, ReactiveFormsModule, FormsModule, MatFormFieldModule, MatIconModule, MatButtonModule, ErrorMessageComponent] + imports: [MatExpansionPanelComponent, MatListModule, MatCheckboxModule, MatExpansionModule, MaterialFileInputModule, MatDialogClose, MatDialogActions, MatDialogContent, ReactiveFormsModule, FormsModule, MatFormFieldModule, MatIconModule, MatButtonModule, ErrorMessageComponent, TranslateModule] }) export class DialogLoadSessionComponent { private fileReader = new FileReader(); diff --git a/src/app/components/mat-expansion-panel/mat-expansion-panel.component.ts b/src/app/components/mat-expansion-panel/mat-expansion-panel.component.ts index ce9cac3..18f75da 100644 --- a/src/app/components/mat-expansion-panel/mat-expansion-panel.component.ts +++ b/src/app/components/mat-expansion-panel/mat-expansion-panel.component.ts @@ -4,18 +4,22 @@ import { MatButtonModule } from '@angular/material/button'; import { MatCheckboxModule } from '@angular/material/checkbox'; import { MatExpansionModule } from '@angular/material/expansion'; import { MatDividerModule } from '@angular/material/divider'; +import { TranslateModule } from '@ngx-translate/core'; +import { TranslateService } from '@ngx-translate/core'; @Component({ selector: 'app-mat-expansion-panel', standalone: true, - imports: [MatCheckboxModule, MatExpansionModule, FormsModule, MatButtonModule, MatDividerModule], + imports: [MatCheckboxModule, MatExpansionModule, FormsModule, MatButtonModule, MatDividerModule, TranslateModule,], templateUrl: './mat-expansion-panel.component.html', styleUrl: './mat-expansion-panel.component.scss' }) export class MatExpansionPanelComponent { @Input() panelTitle: string = ""; @Input() panelItems: any[] = []; - selectButtonTitle: string = 'Aucun'; + selectButtonTitle: string = this.translate.instant('PANEL.SELECT_NONE'); + + constructor(private translate: TranslateService) { } ngOnInit(): void { this.selectAll(); @@ -45,9 +49,9 @@ export class MatExpansionPanelComponent { } selectNoneOrAll() { - this.selectButtonTitle = (this.selectButtonTitle === 'Aucun') ? 'Tous' : 'Aucun'; + this.selectButtonTitle = (this.selectButtonTitle === this.translate.instant('PANEL.SELECT_NONE')) ? this.translate.instant('PANEL.SELECT_ALL') : this.translate.instant('PANEL.SELECT_NONE'); - if (this.selectButtonTitle === 'Aucun') { + if (this.selectButtonTitle === this.translate.instant('PANEL.SELECT_NONE')) { this.panelItems.forEach(item => item.selected = true); } else { this.panelItems.forEach(item => item.selected = false); diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index b45d645..aab61b3 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -25,7 +25,19 @@ "RESET_SESSION_TITLE": "Reset Session", "RESET_SESSION_WARNING": "Warning! The current session will be lost.", "CONFIRM_BUTTON": "Confirm", - "CANCEL_BUTTON": "Cancel" + "CANCEL_BUTTON": "Cancel", + "LOAD_SESSION_TITLE": "Load a session", + "CHOOSE_FILE_LABEL": "Choose a file", + "INVALID_FILE": "The uploaded file is invalid", + "INVALID_JSON_FILE": "The JSON file contains incorrect data", + "UPLOAD_PROMPT": "Please upload a file", + "CLEAR_SESSION_CHECKBOX": "Clear current session", + "PANEL_GAUGING_TITLE": "Gaugings", + "PANEL_EQUIPMENT_TITLE": "Equipment" + }, + "PANEL": { + "SELECT_ALL": "All", + "SELECT_NONE": "None" }, "GAUGING": { "LIST_TITLE": "Gauging List", diff --git a/src/assets/i18n/fr.json b/src/assets/i18n/fr.json index 155f488..a9e61b0 100644 --- a/src/assets/i18n/fr.json +++ b/src/assets/i18n/fr.json @@ -25,7 +25,19 @@ "RESET_SESSION_TITLE": "Réinitialiser la session", "RESET_SESSION_WARNING": "Attention! La session actuelle sera perdue.", "CONFIRM_BUTTON": "Confirmer", - "CANCEL_BUTTON": "Annuler" + "CANCEL_BUTTON": "Annuler", + "LOAD_SESSION_TITLE": "Charger une session", + "CHOOSE_FILE_LABEL": "Choisir un fichier", + "INVALID_FILE": "Le fichier téléchargé est invalide", + "INVALID_JSON_FILE": "Le fichier JSON contient des données incorrectes", + "UPLOAD_PROMPT": "Veuillez télécharger un fichier", + "CLEAR_SESSION_CHECKBOX": "Vider la session en cours", + "PANEL_GAUGING_TITLE": "Jaugeages", + "PANEL_EQUIPMENT_TITLE": "Matériel" + }, + "PANEL": { + "SELECT_ALL": "Tous", + "SELECT_NONE": "Aucun" }, "GAUGING": { "LIST_TITLE": "Liste des Jaugeages", -- GitLab From 7fd42a3900839f1f89a5fee0e29cea3ffcc64aeb Mon Sep 17 00:00:00 2001 From: Jean-Pascal AUBRY <jean-pascal.aubry@inrae.fr> Date: Mon, 14 Oct 2024 09:25:51 +0000 Subject: [PATCH 07/16] fix: translate dialog save session Refs #6 --- .../dialog-new-session.component.spec.ts | 23 ------------------- .../dialog-save-session.component.html | 10 ++++---- .../dialog-save-session.component.ts | 3 ++- src/assets/i18n/en.json | 5 +++- src/assets/i18n/fr.json | 5 +++- 5 files changed, 15 insertions(+), 31 deletions(-) delete mode 100644 src/app/components/dialog/dialog-new-session/dialog-new-session/dialog-new-session.component.spec.ts diff --git a/src/app/components/dialog/dialog-new-session/dialog-new-session/dialog-new-session.component.spec.ts b/src/app/components/dialog/dialog-new-session/dialog-new-session/dialog-new-session.component.spec.ts deleted file mode 100644 index 0dc2581..0000000 --- a/src/app/components/dialog/dialog-new-session/dialog-new-session/dialog-new-session.component.spec.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { DialogNewSessionComponent } from './dialog-new-session.component'; - -describe('DialogNewSessionComponent', () => { - let component: DialogNewSessionComponent; - let fixture: ComponentFixture<DialogNewSessionComponent>; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - imports: [DialogNewSessionComponent] - }) - .compileComponents(); - - fixture = TestBed.createComponent(DialogNewSessionComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/src/app/components/dialog/dialog-save-session/dialog-save-session/dialog-save-session.component.html b/src/app/components/dialog/dialog-save-session/dialog-save-session/dialog-save-session.component.html index e4569cb..5eb9f5f 100644 --- a/src/app/components/dialog/dialog-save-session/dialog-save-session/dialog-save-session.component.html +++ b/src/app/components/dialog/dialog-save-session/dialog-save-session/dialog-save-session.component.html @@ -1,13 +1,13 @@ -<h2 mat-dialog-title class="dialog-title">Sauvegarder la session</h2> +<h2 mat-dialog-title class="dialog-title">{{ 'DIALOG.SAVE_TITLE' | translate }}</h2> <mat-dialog-content> @if(equipment.length > 0){ - <app-mat-expansion-panel [panelTitle]="panelEquipmentTitle" [panelItems]="equipment"></app-mat-expansion-panel> + <app-mat-expansion-panel [panelTitle]="'DIALOG.PANEL_EQUIPMENT_TITLE' | translate" [panelItems]="equipment"></app-mat-expansion-panel> } @if(gaugings.length > 0 ){ - <app-mat-expansion-panel [panelTitle]="panelGaugingTitle" [panelItems]="gaugings"></app-mat-expansion-panel> + <app-mat-expansion-panel [panelTitle]="'DIALOG.PANEL_GAUGING_TITLE' | translate" [panelItems]="gaugings"></app-mat-expansion-panel> } <mat-form-field class="file-input-field" appearance="outline"> - <mat-label>Nom du fichier</mat-label> + <mat-label>{{ 'DIALOG.FILE_NAME_LABEL' | translate }}</mat-label> <input matInput [(ngModel)]="fileName" #sessionFile> @if(fileName !== "") { <button mat-icon-button matSuffix (click)="fileName = ''" class="clear-button"> @@ -16,7 +16,7 @@ } </mat-form-field> @if(fileName === "") { - <p style="color: red">Veuillez nommer le fichier</p> + <p style="color: red">{{ 'DIALOG.NO_FILE_NAME_ERROR' | translate }}</p> } <mat-dialog-actions> <button mat-raised-button mat-dialog-close color="primary" [disabled]="fileName === ''" (click)="saveSession()">Confirmer</button> diff --git a/src/app/components/dialog/dialog-save-session/dialog-save-session/dialog-save-session.component.ts b/src/app/components/dialog/dialog-save-session/dialog-save-session/dialog-save-session.component.ts index 8cb7f61..16b5363 100644 --- a/src/app/components/dialog/dialog-save-session/dialog-save-session/dialog-save-session.component.ts +++ b/src/app/components/dialog/dialog-save-session/dialog-save-session/dialog-save-session.component.ts @@ -14,6 +14,7 @@ import { Material } from '../../../../models/material'; import { GaugingService } from '../../../../services/gauging.service'; import { Gauging } from '../../../../models/gauging'; import { MaterialType } from '../../../../models/equipment.model'; +import { TranslateModule } from '@ngx-translate/core'; interface SelectableMaterial extends Material { selected?: boolean; @@ -26,7 +27,7 @@ interface SelectableGauging extends Gauging { @Component({ selector: 'app-dialog-save-session', standalone: true, - imports: [MatExpansionPanelComponent, MatIconModule, MatCheckboxModule, MatExpansionModule, MatFormField, MatInputModule, MatDialogClose, FormsModule, MatButtonModule, MatDialogContent, MatDialogActions], + imports: [MatExpansionPanelComponent, MatIconModule, MatCheckboxModule, MatExpansionModule, MatFormField, MatInputModule, MatDialogClose, FormsModule, MatButtonModule, MatDialogContent, MatDialogActions, TranslateModule], templateUrl: './dialog-save-session.component.html', styleUrl: './dialog-save-session.component.scss' }) diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index aab61b3..47dce71 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -32,6 +32,9 @@ "INVALID_JSON_FILE": "The JSON file contains incorrect data", "UPLOAD_PROMPT": "Please upload a file", "CLEAR_SESSION_CHECKBOX": "Clear current session", + "SAVE_TITLE": "Save session", + "FILE_NAME_LABEL": "File name", + "NO_FILE_NAME_ERROR": "Please name the file", "PANEL_GAUGING_TITLE": "Gaugings", "PANEL_EQUIPMENT_TITLE": "Equipment" }, @@ -81,7 +84,7 @@ "DEPTH": "Depth (m)", "DURATION": "Duration (s)", "NUMBER_OF_POINTS": "Number of points", - "INVALID_DISTANCE": "Distance from bank must be less than or equal to section width", + "INVALID_DISTANCE": "Invalid distance", "MEASUREMENTS_ON_VERTICAL": "Measurements on vertical n°", "DISTANCE_FROM_BOTTOM": "Distance from bottom (m)", "SPEED": "Speed (m/s)", diff --git a/src/assets/i18n/fr.json b/src/assets/i18n/fr.json index a9e61b0..37e80d3 100644 --- a/src/assets/i18n/fr.json +++ b/src/assets/i18n/fr.json @@ -32,6 +32,9 @@ "INVALID_JSON_FILE": "Le fichier JSON contient des données incorrectes", "UPLOAD_PROMPT": "Veuillez télécharger un fichier", "CLEAR_SESSION_CHECKBOX": "Vider la session en cours", + "SAVE_TITLE": "Sauvegarder la session", + "FILE_NAME_LABEL": "Nom du fichier", + "NO_FILE_NAME_ERROR": "Veuillez nommer le fichier", "PANEL_GAUGING_TITLE": "Jaugeages", "PANEL_EQUIPMENT_TITLE": "Matériel" }, @@ -81,7 +84,7 @@ "DEPTH": "Profondeur (m)", "DURATION": "Durée (s)", "NUMBER_OF_POINTS": "Nombre de points", - "INVALID_DISTANCE": "La distance à la rive doit être inférieure ou égale à la largeur de la section", + "INVALID_DISTANCE": "Distance invalide", "MEASUREMENTS_ON_VERTICAL": "Mesures sur la verticale n°", "DISTANCE_FROM_BOTTOM": "Distance au fond (m)", "SPEED": "Vitesse (m/s)", -- GitLab From 5874659039d12983fbbe20956c2a9ab79fca0a68 Mon Sep 17 00:00:00 2001 From: Jean-Pascal AUBRY <jean-pascal.aubry@inrae.fr> Date: Mon, 14 Oct 2024 10:10:30 +0000 Subject: [PATCH 08/16] fix: translate dialog confirm delete equipment Refs #6 --- .../dialog-confirm-delete-equipment.component.html | 8 ++++---- .../dialog-confirm-delete-equipment.component.ts | 8 +++++--- src/assets/i18n/en.json | 4 +++- src/assets/i18n/fr.json | 4 +++- 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/app/components/dialog/dialog-confirm-delete-equipment/dialog-confirm-delete-equipment.component.html b/src/app/components/dialog/dialog-confirm-delete-equipment/dialog-confirm-delete-equipment.component.html index f872405..5c29c4f 100644 --- a/src/app/components/dialog/dialog-confirm-delete-equipment/dialog-confirm-delete-equipment.component.html +++ b/src/app/components/dialog/dialog-confirm-delete-equipment/dialog-confirm-delete-equipment.component.html @@ -1,10 +1,10 @@ -<h2 mat-dialog-title><mat-icon color="warn">warning</mat-icon> Suppression du matériel</h2> +<h2 mat-dialog-title><mat-icon color="warn">warning</mat-icon> {{ 'DIALOG.DELETE_MATERIAL_TITLE' | translate }}</h2> <mat-dialog-content> - Attention! Le <strong>{{ data.materialType }} {{ data.materialName }}</strong> sera supprimé de la liste. + <span [innerHTML]="'DIALOG.WARNING_DELETE_MATERIAL_MESSAGE' | translate: { materialType: translate.instant(data.materialType), materialName: data.materialName }"></span> </mat-dialog-content> <mat-dialog-actions> - <button mat-raised-button mat-dialog-close color="primary">Annuler</button> - <button mat-raised-button [mat-dialog-close]="'confirm'" color="warn" cdkFocusInitial>Supprimer</button> + <button mat-raised-button mat-dialog-close color="primary">{{ 'DIALOG.CANCEL_BUTTON' | translate }}</button> + <button mat-raised-button [mat-dialog-close]="'confirm'" color="warn" cdkFocusInitial>{{ 'DIALOG.CONFIRM_BUTTON' | translate }}</button> </mat-dialog-actions> diff --git a/src/app/components/dialog/dialog-confirm-delete-equipment/dialog-confirm-delete-equipment.component.ts b/src/app/components/dialog/dialog-confirm-delete-equipment/dialog-confirm-delete-equipment.component.ts index 01c4c0b..0a450eb 100644 --- a/src/app/components/dialog/dialog-confirm-delete-equipment/dialog-confirm-delete-equipment.component.ts +++ b/src/app/components/dialog/dialog-confirm-delete-equipment/dialog-confirm-delete-equipment.component.ts @@ -8,16 +8,18 @@ import { import { MatIconModule } from '@angular/material/icon'; import {MatButtonModule} from '@angular/material/button' import { MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { TranslateModule, TranslateService } from '@ngx-translate/core'; @Component({ selector: 'app-dialog-confirm-delete-equipment', standalone: true, - imports: [MatButtonModule, MatDialogActions, MatDialogClose, MatDialogTitle, MatDialogContent, MatIconModule], + imports: [MatButtonModule, MatDialogActions, MatDialogClose, MatDialogTitle, MatDialogContent, MatIconModule, TranslateModule], templateUrl: './dialog-confirm-delete-equipment.component.html', styleUrl: './dialog-confirm-delete-equipment.component.scss' }) export class DialogConfirmDeleteEquipmentComponent { - constructor(@Inject(MAT_DIALOG_DATA) public data: any) {} - + constructor(@Inject(MAT_DIALOG_DATA) public data: any, protected translate: TranslateService) { + } + } diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 47dce71..637bfe2 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -36,7 +36,9 @@ "FILE_NAME_LABEL": "File name", "NO_FILE_NAME_ERROR": "Please name the file", "PANEL_GAUGING_TITLE": "Gaugings", - "PANEL_EQUIPMENT_TITLE": "Equipment" + "PANEL_EQUIPMENT_TITLE": "Equipment", + "DELETE_MATERIAL_TITLE": "Delete material", + "WARNING_DELETE_MATERIAL_MESSAGE": "Warning! The <strong>{{ materialType }} {{ materialName }}</strong> will be removed from the list." }, "PANEL": { "SELECT_ALL": "All", diff --git a/src/assets/i18n/fr.json b/src/assets/i18n/fr.json index 37e80d3..da35c8f 100644 --- a/src/assets/i18n/fr.json +++ b/src/assets/i18n/fr.json @@ -36,7 +36,9 @@ "FILE_NAME_LABEL": "Nom du fichier", "NO_FILE_NAME_ERROR": "Veuillez nommer le fichier", "PANEL_GAUGING_TITLE": "Jaugeages", - "PANEL_EQUIPMENT_TITLE": "Matériel" + "PANEL_EQUIPMENT_TITLE": "Matériel", + "DELETE_MATERIAL_TITLE": "Suppression du matériel", + "WARNING_DELETE_MATERIAL_MESSAGE": "Attention! Le <strong>{{ materialType }} {{ materialName }}</strong> sera supprimé de la liste." }, "PANEL": { "SELECT_ALL": "Tous", -- GitLab From 356a16ed814043498e2a0f1900840c66401110df Mon Sep 17 00:00:00 2001 From: Jean-Pascal AUBRY <jean-pascal.aubry@inrae.fr> Date: Mon, 14 Oct 2024 10:31:24 +0000 Subject: [PATCH 09/16] fix: translate dialog warning material associated to jauging Refs #6 --- ...alog-confirm-delete-gauging.component.html | 2 +- ...erial-associated-to-gauging.component.html | 21 ++++++++----------- ...aterial-associated-to-gauging.component.ts | 5 +++-- src/assets/i18n/en.json | 6 +++++- src/assets/i18n/fr.json | 6 +++++- 5 files changed, 23 insertions(+), 17 deletions(-) diff --git a/src/app/components/dialog/dialog-confirm-delete-gauging/dialog-confirm-delete-gauging.component.html b/src/app/components/dialog/dialog-confirm-delete-gauging/dialog-confirm-delete-gauging.component.html index 36ff451..455657d 100644 --- a/src/app/components/dialog/dialog-confirm-delete-gauging/dialog-confirm-delete-gauging.component.html +++ b/src/app/components/dialog/dialog-confirm-delete-gauging/dialog-confirm-delete-gauging.component.html @@ -1,4 +1,4 @@ -<h2 mat-dialog-title><mat-icon color="warn">warning</mat-icon> Suppression du matériel</h2> +<h2 mat-dialog-title><mat-icon color="warn">warning</mat-icon> Suppression d'un jaugeage</h2> <mat-dialog-content> Attention! Le jaugeage réalisé sur le <strong>{{ data.watercourse }}</strong> à la date du <strong>{{ data.date | date: 'dd/MM/yyyy' }}</strong> sera supprimé de la liste. </mat-dialog-content> diff --git a/src/app/components/dialog/dialog-warning-material-associated-to-gauging/dialog-warning-material-associated-to-gauging.component.html b/src/app/components/dialog/dialog-warning-material-associated-to-gauging/dialog-warning-material-associated-to-gauging.component.html index a9487a9..f894a63 100644 --- a/src/app/components/dialog/dialog-warning-material-associated-to-gauging/dialog-warning-material-associated-to-gauging.component.html +++ b/src/app/components/dialog/dialog-warning-material-associated-to-gauging/dialog-warning-material-associated-to-gauging.component.html @@ -1,12 +1,9 @@ -<h2 mat-dialog-title><mat-icon color="warn">warning</mat-icon> Suppression du matériel impossible</h2> - <mat-dialog-content> - Attention! Le <strong>{{ data.materialType }} {{ data.materialName }}</strong> est associé à un ou plusieurs jaugeages existants.<br> - Supprimer d'abord le ou les jaugeages associés pour supprimer ce matériel. - </mat-dialog-content> - <mat-dialog-actions> - <button mat-raised-button [mat-dialog-close]="'confirm'" color="primary" cdkFocusInitial>Liste des jaugeages </button> - <button mat-raised-button mat-dialog-close color="warn">Annuler</button> - </mat-dialog-actions> - - - +<h2 mat-dialog-title><mat-icon color="warn">warning</mat-icon> {{ 'DIALOG.DELETE_IMPOSSIBLE_TITLE' | translate }}</h2> +<mat-dialog-content> + <span [innerHTML]="'DIALOG.DELETE_IMPOSSIBLE_MESSAGE' | translate: { materialType: translate.instant(data.materialType), materialName: data.materialName }"></span><br> + {{ 'DIALOG.DELETE_IMPOSSIBLE_INSTRUCTION' | translate }} +</mat-dialog-content> +<mat-dialog-actions> + <button mat-raised-button [mat-dialog-close]="'confirm'" color="primary" cdkFocusInitial>{{ 'DIALOG.GAUGING_LIST_BUTTON' | translate }}</button> + <button mat-raised-button mat-dialog-close color="warn">{{ 'DIALOG.CANCEL_BUTTON' | translate }}</button> +</mat-dialog-actions> diff --git a/src/app/components/dialog/dialog-warning-material-associated-to-gauging/dialog-warning-material-associated-to-gauging.component.ts b/src/app/components/dialog/dialog-warning-material-associated-to-gauging/dialog-warning-material-associated-to-gauging.component.ts index 9ec31f9..f77c33b 100644 --- a/src/app/components/dialog/dialog-warning-material-associated-to-gauging/dialog-warning-material-associated-to-gauging.component.ts +++ b/src/app/components/dialog/dialog-warning-material-associated-to-gauging/dialog-warning-material-associated-to-gauging.component.ts @@ -2,16 +2,17 @@ import { Component, Inject } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; import { MatDialogActions, MatDialogClose, MatDialogTitle, MatDialogContent, MAT_DIALOG_DATA } from '@angular/material/dialog'; import { MatIconModule } from '@angular/material/icon'; +import { TranslateModule, TranslateService } from '@ngx-translate/core'; @Component({ selector: 'app-dialog-warning-material-associated-to-gauging', standalone: true, - imports: [MatButtonModule, MatDialogActions, MatDialogClose, MatDialogTitle, MatDialogContent, MatIconModule], + imports: [MatButtonModule, MatDialogActions, MatDialogClose, MatDialogTitle, MatDialogContent, MatIconModule, TranslateModule], templateUrl: './dialog-warning-material-associated-to-gauging.component.html', styleUrl: './dialog-warning-material-associated-to-gauging.component.scss' }) export class DialogWarningMaterialAssociatedToGaugingComponent { - constructor(@Inject(MAT_DIALOG_DATA) public data: any) { + constructor(@Inject(MAT_DIALOG_DATA) public data: any, protected translate: TranslateService) { } } diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 637bfe2..8fc9f00 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -38,7 +38,11 @@ "PANEL_GAUGING_TITLE": "Gaugings", "PANEL_EQUIPMENT_TITLE": "Equipment", "DELETE_MATERIAL_TITLE": "Delete material", - "WARNING_DELETE_MATERIAL_MESSAGE": "Warning! The <strong>{{ materialType }} {{ materialName }}</strong> will be removed from the list." + "WARNING_DELETE_MATERIAL_MESSAGE": "Warning! The <strong>{{ materialType }} {{ materialName }}</strong> will be removed from the list.", + "DELETE_IMPOSSIBLE_TITLE": "Unable to delete material", + "DELETE_IMPOSSIBLE_MESSAGE": "Warning! The <strong>{{ materialType }} {{ materialName }}</strong> is associated with one or more existing gaugings.", + "DELETE_IMPOSSIBLE_INSTRUCTION": "Delete the associated gauging(s) first to remove this material.", + "GAUGING_LIST_BUTTON": "Gaugings list" }, "PANEL": { "SELECT_ALL": "All", diff --git a/src/assets/i18n/fr.json b/src/assets/i18n/fr.json index da35c8f..68e3ddb 100644 --- a/src/assets/i18n/fr.json +++ b/src/assets/i18n/fr.json @@ -38,7 +38,11 @@ "PANEL_GAUGING_TITLE": "Jaugeages", "PANEL_EQUIPMENT_TITLE": "Matériel", "DELETE_MATERIAL_TITLE": "Suppression du matériel", - "WARNING_DELETE_MATERIAL_MESSAGE": "Attention! Le <strong>{{ materialType }} {{ materialName }}</strong> sera supprimé de la liste." + "WARNING_DELETE_MATERIAL_MESSAGE": "Attention! Le <strong>{{ materialType }} {{ materialName }}</strong> sera supprimé de la liste.", + "DELETE_IMPOSSIBLE_TITLE": "Suppression du matériel impossible", + "DELETE_IMPOSSIBLE_MESSAGE": "Attention! Le <strong>{{ materialType }} {{ materialName }}</strong> est associé à un ou plusieurs jaugeages existants.", + "DELETE_IMPOSSIBLE_INSTRUCTION": "Supprimez d'abord le ou les jaugeages associés pour supprimer ce matériel.", + "GAUGING_LIST_BUTTON": "Liste des jaugeages" }, "PANEL": { "SELECT_ALL": "Tous", -- GitLab From 7504321809f5a5077d89682abc0c5a91b5d9db16 Mon Sep 17 00:00:00 2001 From: Jean-Pascal AUBRY <jean-pascal.aubry@inrae.fr> Date: Mon, 14 Oct 2024 10:38:53 +0000 Subject: [PATCH 10/16] fix: translate dialog confirm delete gauging Refs #6 --- ...alog-confirm-delete-gauging.component.html | 19 ++++++++----------- ...alog-confirm-delete-gauging.component.scss | 5 +++++ ...dialog-confirm-delete-gauging.component.ts | 3 ++- src/assets/i18n/en.json | 4 +++- src/assets/i18n/fr.json | 4 +++- 5 files changed, 21 insertions(+), 14 deletions(-) diff --git a/src/app/components/dialog/dialog-confirm-delete-gauging/dialog-confirm-delete-gauging.component.html b/src/app/components/dialog/dialog-confirm-delete-gauging/dialog-confirm-delete-gauging.component.html index 455657d..c2eb050 100644 --- a/src/app/components/dialog/dialog-confirm-delete-gauging/dialog-confirm-delete-gauging.component.html +++ b/src/app/components/dialog/dialog-confirm-delete-gauging/dialog-confirm-delete-gauging.component.html @@ -1,11 +1,8 @@ -<h2 mat-dialog-title><mat-icon color="warn">warning</mat-icon> Suppression d'un jaugeage</h2> - <mat-dialog-content> - Attention! Le jaugeage réalisé sur le <strong>{{ data.watercourse }}</strong> à la date du <strong>{{ data.date | date: 'dd/MM/yyyy' }}</strong> sera supprimé de la liste. - </mat-dialog-content> - <mat-dialog-actions> - <button mat-raised-button mat-dialog-close color="primary">Annuler</button> - <button mat-raised-button [mat-dialog-close]="'confirm'" color="warn" cdkFocusInitial>Supprimer</button> - </mat-dialog-actions> - - - +<h2 mat-dialog-title><mat-icon color="warn">warning</mat-icon> {{ 'DIALOG.DELETE_GAUGING_TITLE' | translate }}</h2> +<mat-dialog-content> + <span [innerHTML]="'DIALOG.DELETE_GAUGING_MESSAGE' | translate: { watercourse: data.watercourse, date: (data.date | date: 'dd/MM/yyyy') }"></span> +</mat-dialog-content> +<mat-dialog-actions> + <button mat-raised-button mat-dialog-close color="primary">{{ 'DIALOG.CANCEL_BUTTON' | translate }}</button> + <button mat-raised-button [mat-dialog-close]="'confirm'" color="warn" cdkFocusInitial>{{ 'DIALOG.CONFIRM_BUTTON' | translate }}</button> +</mat-dialog-actions> diff --git a/src/app/components/dialog/dialog-confirm-delete-gauging/dialog-confirm-delete-gauging.component.scss b/src/app/components/dialog/dialog-confirm-delete-gauging/dialog-confirm-delete-gauging.component.scss index e69de29..72fee1c 100644 --- a/src/app/components/dialog/dialog-confirm-delete-gauging/dialog-confirm-delete-gauging.component.scss +++ b/src/app/components/dialog/dialog-confirm-delete-gauging/dialog-confirm-delete-gauging.component.scss @@ -0,0 +1,5 @@ +mat-icon { + margin-right: 1%; + font-size: 25px; + vertical-align: middle; +} \ No newline at end of file diff --git a/src/app/components/dialog/dialog-confirm-delete-gauging/dialog-confirm-delete-gauging.component.ts b/src/app/components/dialog/dialog-confirm-delete-gauging/dialog-confirm-delete-gauging.component.ts index 8ecb641..7c38ccb 100644 --- a/src/app/components/dialog/dialog-confirm-delete-gauging/dialog-confirm-delete-gauging.component.ts +++ b/src/app/components/dialog/dialog-confirm-delete-gauging/dialog-confirm-delete-gauging.component.ts @@ -9,11 +9,12 @@ import { MatIconModule } from '@angular/material/icon'; import {MatButtonModule} from '@angular/material/button' import { MAT_DIALOG_DATA } from '@angular/material/dialog'; import { DatePipe } from '@angular/common'; +import { TranslateModule } from '@ngx-translate/core'; @Component({ selector: 'app-dialog-confirm-delete-gauging', standalone: true, - imports: [DatePipe,MatButtonModule, MatDialogActions, MatDialogClose, MatDialogTitle, MatDialogContent, MatIconModule], + imports: [DatePipe,MatButtonModule, MatDialogActions, MatDialogClose, MatDialogTitle, MatDialogContent, MatIconModule, TranslateModule], templateUrl: './dialog-confirm-delete-gauging.component.html', styleUrl: './dialog-confirm-delete-gauging.component.scss', }) diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 8fc9f00..584784f 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -42,7 +42,9 @@ "DELETE_IMPOSSIBLE_TITLE": "Unable to delete material", "DELETE_IMPOSSIBLE_MESSAGE": "Warning! The <strong>{{ materialType }} {{ materialName }}</strong> is associated with one or more existing gaugings.", "DELETE_IMPOSSIBLE_INSTRUCTION": "Delete the associated gauging(s) first to remove this material.", - "GAUGING_LIST_BUTTON": "Gaugings list" + "GAUGING_LIST_BUTTON": "Gaugings list", + "DELETE_GAUGING_TITLE": "Delete Gauging", + "DELETE_GAUGING_MESSAGE": "Warning! The gauging performed on the <strong>{{ watercourse }}</strong> on <strong>{{ date }}</strong> will be removed from the list." }, "PANEL": { "SELECT_ALL": "All", diff --git a/src/assets/i18n/fr.json b/src/assets/i18n/fr.json index 68e3ddb..e41ce9d 100644 --- a/src/assets/i18n/fr.json +++ b/src/assets/i18n/fr.json @@ -42,7 +42,9 @@ "DELETE_IMPOSSIBLE_TITLE": "Suppression du matériel impossible", "DELETE_IMPOSSIBLE_MESSAGE": "Attention! Le <strong>{{ materialType }} {{ materialName }}</strong> est associé à un ou plusieurs jaugeages existants.", "DELETE_IMPOSSIBLE_INSTRUCTION": "Supprimez d'abord le ou les jaugeages associés pour supprimer ce matériel.", - "GAUGING_LIST_BUTTON": "Liste des jaugeages" + "GAUGING_LIST_BUTTON": "Liste des jaugeages", + "DELETE_GAUGING_TITLE": "Suppression d'un jaugeage", + "DELETE__GAUGING_MESSAGE": "Attention! Le jaugeage réalisé sur le <strong>{{ watercourse }}</strong> à la date du <strong>{{ date }}</strong> sera supprimé de la liste." }, "PANEL": { "SELECT_ALL": "Tous", -- GitLab From d3366cc6abaa7e98697e30c1a369077660949949 Mon Sep 17 00:00:00 2001 From: Jean-Pascal AUBRY <jean-pascal.aubry@inrae.fr> Date: Mon, 14 Oct 2024 12:27:29 +0000 Subject: [PATCH 11/16] fix: translate dialog confirm delete vertical Refs #6 --- src/app/app.component.html | 2 +- src/app/app.component.ts | 1 + ...log-confirm-delete-vertical.component.html | 19 ++++++++----------- ...ialog-confirm-delete-vertical.component.ts | 3 ++- .../dialog-save-session.component.html | 4 ++-- src/app/views/gauging/gauging.component.html | 2 +- src/assets/i18n/en.json | 4 +++- src/assets/i18n/fr.json | 4 +++- 8 files changed, 21 insertions(+), 18 deletions(-) diff --git a/src/app/app.component.html b/src/app/app.component.html index ccd3108..2683604 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -30,7 +30,7 @@ </button> </mat-list-item> <mat-list-item (click)="sidenav.close()"> - <button [disabled]="(materialList$ | async)?.length! === 0" (click)="newSession()"> + <button [disabled]="(materialList$ | async)?.length! === 0 && (gaugingList$ | async)?.length! === 0" (click)="newSession()"> <mat-icon class="icon-list-item">insert_drive_file</mat-icon> <span>{{ 'SIDENAV.RESET_SESSION' | translate }}</span> </button> diff --git a/src/app/app.component.ts b/src/app/app.component.ts index a51cede..40580c6 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -44,6 +44,7 @@ export class AppComponent { constructor(private translate: TranslateService,private dialog: MatDialog, private equipmentService: EquipmentService, private gaugingService: GaugingService, private gaugingFormService: GaugingFormService, private router: Router) { this.materialList$ = this.equipmentService.materialList$; this.gaugingList$ = this.gaugingService.gaugingList$; + console.log("gauging list", this.gaugingList$ ) this.translate.addLangs(['fr', 'en']); this.translate.setDefaultLang('fr'); this.translate.use('en'); diff --git a/src/app/components/dialog/dialog-confirm-delete-vertical/dialog-confirm-delete-vertical.component.html b/src/app/components/dialog/dialog-confirm-delete-vertical/dialog-confirm-delete-vertical.component.html index c6b072c..c1b8a6a 100644 --- a/src/app/components/dialog/dialog-confirm-delete-vertical/dialog-confirm-delete-vertical.component.html +++ b/src/app/components/dialog/dialog-confirm-delete-vertical/dialog-confirm-delete-vertical.component.html @@ -1,11 +1,8 @@ -<h2 mat-dialog-title><mat-icon color="warn">warning</mat-icon> Suppression du matériel</h2> - <mat-dialog-content> - Attention! La verticale <strong> n°{{ data.selectedVerticalIndex}}</strong> sera supprimée de la liste. - </mat-dialog-content> - <mat-dialog-actions> - <button mat-raised-button mat-dialog-close color="primary">Annuler</button> - <button mat-raised-button [mat-dialog-close]="'confirm'" color="warn" cdkFocusInitial>Supprimer</button> - </mat-dialog-actions> - - - +<h2 mat-dialog-title><mat-icon color="warn">warning</mat-icon> {{ 'DIALOG.DELETE_VERTICAL_TITLE' | translate }}</h2> +<mat-dialog-content> + <span [innerHTML]="'DIALOG.DELETE_VERTICAL_MESSAGE' | translate: { verticalIndex: data.selectedVerticalIndex }"></span> +</mat-dialog-content> +<mat-dialog-actions> + <button mat-raised-button mat-dialog-close color="primary">{{ 'DIALOG.CANCEL_BUTTON' | translate }}</button> + <button mat-raised-button [mat-dialog-close]="'confirm'" color="warn" cdkFocusInitial>{{ 'DIALOG.CONFIRM_BUTTON' | translate }}</button> +</mat-dialog-actions> diff --git a/src/app/components/dialog/dialog-confirm-delete-vertical/dialog-confirm-delete-vertical.component.ts b/src/app/components/dialog/dialog-confirm-delete-vertical/dialog-confirm-delete-vertical.component.ts index 884280d..bb3ea09 100644 --- a/src/app/components/dialog/dialog-confirm-delete-vertical/dialog-confirm-delete-vertical.component.ts +++ b/src/app/components/dialog/dialog-confirm-delete-vertical/dialog-confirm-delete-vertical.component.ts @@ -8,11 +8,12 @@ import { import { MatIconModule } from '@angular/material/icon'; import {MatButtonModule} from '@angular/material/button' import { MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { TranslateModule } from '@ngx-translate/core'; @Component({ selector: 'app-dialog-confirm-delete-vertical', standalone: true, - imports: [MatButtonModule, MatDialogActions, MatDialogClose, MatDialogTitle, MatDialogContent, MatIconModule], + imports: [MatButtonModule, MatDialogActions, MatDialogClose, MatDialogTitle, MatDialogContent, MatIconModule, TranslateModule], templateUrl: './dialog-confirm-delete-vertical.component.html', styleUrl: './dialog-confirm-delete-vertical.component.scss' }) diff --git a/src/app/components/dialog/dialog-save-session/dialog-save-session/dialog-save-session.component.html b/src/app/components/dialog/dialog-save-session/dialog-save-session/dialog-save-session.component.html index 5eb9f5f..e3c24fd 100644 --- a/src/app/components/dialog/dialog-save-session/dialog-save-session/dialog-save-session.component.html +++ b/src/app/components/dialog/dialog-save-session/dialog-save-session/dialog-save-session.component.html @@ -19,7 +19,7 @@ <p style="color: red">{{ 'DIALOG.NO_FILE_NAME_ERROR' | translate }}</p> } <mat-dialog-actions> - <button mat-raised-button mat-dialog-close color="primary" [disabled]="fileName === ''" (click)="saveSession()">Confirmer</button> - <button mat-raised-button color="warn" cdkFocusInitial [mat-dialog-close]="'confirm'">Annuler</button> + <button mat-raised-button mat-dialog-close color="primary" [disabled]="fileName === ''" (click)="saveSession()">{{ 'DIALOG.CONFIRM_BUTTON' | translate }}</button> + <button mat-raised-button color="warn" cdkFocusInitial [mat-dialog-close]="'confirm'">{{ 'DIALOG.CANCEL_BUTTON' | translate }}</button> </mat-dialog-actions> diff --git a/src/app/views/gauging/gauging.component.html b/src/app/views/gauging/gauging.component.html index 0c016fe..c69c14d 100644 --- a/src/app/views/gauging/gauging.component.html +++ b/src/app/views/gauging/gauging.component.html @@ -464,7 +464,7 @@ <!-- Résultats --> <mat-tab label="{{ 'GAUGING.TAB_RESULTS' | translate }}" ngSkipHydration [disabled]="!this.selectedMaterialId"> <div class="tab-content"> - <h2>{{ 'RESULTS.TAB_RESULTS' | translate }}</h2> + <h2>{{ 'GAUGING.TAB_RESULTS' | translate }}</h2> <!-- Résultats par verticale --> <mat-card class="form-section"> <mat-card-title class="vertical-card-title"> diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 584784f..3174697 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -44,7 +44,9 @@ "DELETE_IMPOSSIBLE_INSTRUCTION": "Delete the associated gauging(s) first to remove this material.", "GAUGING_LIST_BUTTON": "Gaugings list", "DELETE_GAUGING_TITLE": "Delete Gauging", - "DELETE_GAUGING_MESSAGE": "Warning! The gauging performed on the <strong>{{ watercourse }}</strong> on <strong>{{ date }}</strong> will be removed from the list." + "DELETE_GAUGING_MESSAGE": "Warning! The gauging performed on the <strong>{{ watercourse }}</strong> on <strong>{{ date }}</strong> will be removed from the list.", + "DELETE_VERTICAL_TITLE": "Delete Vertical", + "DELETE_VERTICAL_MESSAGE": "Warning! The vertical <strong>number {{ verticalIndex }}</strong> will be removed from the list." }, "PANEL": { "SELECT_ALL": "All", diff --git a/src/assets/i18n/fr.json b/src/assets/i18n/fr.json index e41ce9d..f01bc2b 100644 --- a/src/assets/i18n/fr.json +++ b/src/assets/i18n/fr.json @@ -44,7 +44,9 @@ "DELETE_IMPOSSIBLE_INSTRUCTION": "Supprimez d'abord le ou les jaugeages associés pour supprimer ce matériel.", "GAUGING_LIST_BUTTON": "Liste des jaugeages", "DELETE_GAUGING_TITLE": "Suppression d'un jaugeage", - "DELETE__GAUGING_MESSAGE": "Attention! Le jaugeage réalisé sur le <strong>{{ watercourse }}</strong> à la date du <strong>{{ date }}</strong> sera supprimé de la liste." + "DELETE__GAUGING_MESSAGE": "Attention! Le jaugeage réalisé sur le <strong>{{ watercourse }}</strong> à la date du <strong>{{ date }}</strong> sera supprimé de la liste.", + "DELETE_VERTICAL_TITLE": "Suppression de la verticale", + "DELETE_VERTICAL_MESSAGE": "Attention! La verticale <strong>n°{{ verticalIndex }}</strong> sera supprimée de la liste." }, "PANEL": { "SELECT_ALL": "Tous", -- GitLab From 85d534175cb043a7a7a62ec4feb00f09deabc120 Mon Sep 17 00:00:00 2001 From: Jean-Pascal AUBRY <jean-pascal.aubry@inrae.fr> Date: Mon, 14 Oct 2024 12:46:12 +0000 Subject: [PATCH 12/16] fix: translate origin measures enum and grain size type enum Refs #6 --- src/app/app.component.ts | 1 - src/app/models/grain_size.ts | 26 ++++++++++---------- src/app/models/origin_measures.ts | 7 +++--- src/app/views/gauging/gauging.component.html | 4 +-- src/assets/i18n/en.json | 16 ++++++++++++ src/assets/i18n/fr.json | 17 +++++++++++++ 6 files changed, 52 insertions(+), 19 deletions(-) diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 40580c6..a51cede 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -44,7 +44,6 @@ export class AppComponent { constructor(private translate: TranslateService,private dialog: MatDialog, private equipmentService: EquipmentService, private gaugingService: GaugingService, private gaugingFormService: GaugingFormService, private router: Router) { this.materialList$ = this.equipmentService.materialList$; this.gaugingList$ = this.gaugingService.gaugingList$; - console.log("gauging list", this.gaugingList$ ) this.translate.addLangs(['fr', 'en']); this.translate.setDefaultLang('fr'); this.translate.use('en'); diff --git a/src/app/models/grain_size.ts b/src/app/models/grain_size.ts index 0038b8b..7952a90 100644 --- a/src/app/models/grain_size.ts +++ b/src/app/models/grain_size.ts @@ -1,14 +1,14 @@ export enum GrainSize { - CONCRETE = 'Béton', - ROCKS = 'Rochers', - BLOCSS = 'Blocs', - LARGE_STONES = 'Pierres grossières', - LARGE_PEBBLES = 'Cailloux grossiers', - FINE_PEBBLES = 'Cailloux fins', - LARGE_GRAVELS= 'Graviers grossiers', - FINE_GRAVELS = 'Graviers fins', - LARGE_SAND = 'Sable grossier', - FINE_SAND = 'Sable fin', - SILT = 'Limon', - CLAY = 'Argile' -} \ No newline at end of file + CONCRETE = 'GAUGING.GRAIN_SIZE.CONCRETE', + ROCKS = 'GAUGING.GRAIN_SIZE.ROCKS', + BLOCSS = 'GAUGING.GRAIN_SIZE.BLOCSS', + LARGE_STONES = 'GAUGING.GRAIN_SIZE.LARGE_STONES', + LARGE_PEBBLES = 'GAUGING.GRAIN_SIZE.LARGE_PEBBLES', + FINE_PEBBLES = 'GAUGING.GRAIN_SIZE.FINE_PEBBLES', + LARGE_GRAVELS = 'GAUGING.GRAIN_SIZE.LARGE_GRAVELS', + FINE_GRAVELS = 'GAUGING.GRAIN_SIZE.FINE_GRAVELS', + LARGE_SAND = 'GAUGING.GRAIN_SIZE.LARGE_SAND', + FINE_SAND = 'GAUGING.GRAIN_SIZE.FINE_SAND', + SILT = 'GAUGING.GRAIN_SIZE.SILT', + CLAY = 'GAUGING.GRAIN_SIZE.CLAY' +} diff --git a/src/app/models/origin_measures.ts b/src/app/models/origin_measures.ts index d75899e..5d51baf 100644 --- a/src/app/models/origin_measures.ts +++ b/src/app/models/origin_measures.ts @@ -1,7 +1,8 @@ export enum OriginMeasures { - BANK_LEFT = 'Rive gauche', - BANK_RIGHT = 'Rive droite' - } + BANK_LEFT = 'GAUGING.BANK_LEFT', + BANK_RIGHT = 'GAUGING.BANK_RIGHT' +} + // BOTTOM = 'Fond', // SURFACE = 'Surface', \ No newline at end of file diff --git a/src/app/views/gauging/gauging.component.html b/src/app/views/gauging/gauging.component.html index c69c14d..c91018d 100644 --- a/src/app/views/gauging/gauging.component.html +++ b/src/app/views/gauging/gauging.component.html @@ -154,7 +154,7 @@ <mat-select formControlName="size" disableRipple> @for (size of grainSizes; track size) { <mat-option [value]="size"> - {{size}} + {{size | translate}} </mat-option> } </mat-select> @@ -213,7 +213,7 @@ <mat-radio-group formControlName="originMeasures"> @for (origin of originMeasures; track origin) { <mat-radio-button color="primary" [value]="origin"> - {{origin}} + {{origin | translate}} </mat-radio-button> } </mat-radio-group> diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 3174697..0c16df3 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -77,6 +77,20 @@ "OBSERVATIONS": "Observations", "OBSERVATION": "Observation", "REPRESENTATIVE_GRAIN_SIZE": "Representative grain size", + "GRAIN_SIZE": { + "CONCRETE": "Concrete", + "ROCKS": "Rocks", + "BLOCSS": "Blocks", + "LARGE_STONES": "Large stones", + "LARGE_PEBBLES": "Large pebbles", + "FINE_PEBBLES": "Fine pebbles", + "LARGE_GRAVELS": "Large gravels", + "FINE_GRAVELS": "Fine gravels", + "LARGE_SAND": "Coarse sand", + "FINE_SAND": "Fine sand", + "SILT": "Silt", + "CLAY": "Clay" + }, "DOMINANT_GRAIN_SIZE": "Dominant", "ACCESSORY_GRAIN_SIZE": "Accessory", "PARAMETERS": "Gauging parameters", @@ -86,6 +100,8 @@ "HEIGHT_BANK_LEFT": "Height bank left", "HEIGHT_BANK_RIGHT": "Height bank right", "ORIGIN_MEASURES": "Origin of measures", + "BANK_LEFT": "Left bank", + "BANK_RIGHT": "Right bank", "MATERIAL_CHOICE": "Material choice", "TAB_MEASUREMENTS": "Measurement entries", "VERTICALS": "Verticals", diff --git a/src/assets/i18n/fr.json b/src/assets/i18n/fr.json index f01bc2b..817f5c3 100644 --- a/src/assets/i18n/fr.json +++ b/src/assets/i18n/fr.json @@ -76,6 +76,21 @@ "OPERATOR": "Operator", "OBSERVATIONS": "Observations", "OBSERVATION": "Observation", + "REPRESENTATIVE_GRAIN_SIZE": "Garunulométrie représentative", + "GRAIN_SIZE": { + "CONCRETE": "Béton", + "ROCKS": "Rochers", + "BLOCSS": "Blocs", + "LARGE_STONES": "Pierres grossières", + "LARGE_PEBBLES": "Cailloux grossiers", + "FINE_PEBBLES": "Cailloux fins", + "LARGE_GRAVELS": "Graviers grossiers", + "FINE_GRAVELS": "Graviers fins", + "LARGE_SAND": "Sable grossier", + "FINE_SAND": "Sable fin", + "SILT": "Limon", + "CLAY": "Argile" + }, "DOMINANT_GRAIN_SIZE": "Dominante", "ACCESSORY_GRAIN_SIZE": "Accessoire", "PARAMETERS": "Paramètres du jaugeage", @@ -85,6 +100,8 @@ "HEIGHT_BANK_LEFT": "Hauteur rive gauche", "HEIGHT_BANK_RIGHT": "Hauteur rive droite", "ORIGIN_MEASURES": "Origine des mesures", + "BANK_LEFT": "Rive gauche", + "BANK_RIGHT": "Rive droite", "MATERIAL_TYPE": "Type de matériel", "MATERIAL_CHOICE": "Choix du matériel", "TAB_MEASUREMENTS": "Saisies des mesures", -- GitLab From daf1c3418b858f871a16d73aff59b7d15260d518 Mon Sep 17 00:00:00 2001 From: Jean-Pascal AUBRY <jean-pascal.aubry@inrae.fr> Date: Mon, 14 Oct 2024 14:33:10 +0000 Subject: [PATCH 13/16] fix: avoid trigering of beforeunload event when material form is opened from gauging component Refs #6 --- src/app/app.config.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/app/app.config.ts b/src/app/app.config.ts index 495ff54..2115cd0 100644 --- a/src/app/app.config.ts +++ b/src/app/app.config.ts @@ -14,7 +14,6 @@ const httpLoaderFactory: (http: HttpClient) => TranslateHttpLoader = (http: Http export const appConfig: ApplicationConfig = { providers: [ provideRouter(routes, withPreloading(PreloadAllModules)), provideClientHydration(), provideAnimationsAsync(), {provide: MAT_DATE_LOCALE, useValue: 'en-GB'}, - provideZoneChangeDetection({ eventCoalescing: true }), provideHttpClient(), importProvidersFrom([TranslateModule.forRoot({ loader: { -- GitLab From edb5ec59255d2fffcebc5e25d58124a8988a7ded Mon Sep 17 00:00:00 2001 From: Jean-Pascal AUBRY <jean-pascal.aubry@inrae.fr> Date: Mon, 14 Oct 2024 15:07:55 +0000 Subject: [PATCH 14/16] fix: add settings component for language selection Refs #6 --- src/app/app.component.html | 2 +- src/app/app.routes.ts | 1 + .../views/settings/settings.component.html | 20 +++++++++++++ .../views/settings/settings.component.scss | 15 ++++++++++ src/app/views/settings/settings.component.ts | 30 +++++++++++++++++++ 5 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 src/app/views/settings/settings.component.html create mode 100644 src/app/views/settings/settings.component.scss create mode 100644 src/app/views/settings/settings.component.ts diff --git a/src/app/app.component.html b/src/app/app.component.html index 2683604..b063db6 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -45,7 +45,7 @@ <span>{{ 'SIDENAV.SAVE_SESSION' | translate }}</span> </button> </mat-list-item> - <mat-list-item (click)="sidenav.close()"> + <mat-list-item routerLink="settings" (click)="sidenav.close()"> <mat-icon class="icon-list-item">settings</mat-icon> <span>{{ 'SIDENAV.CONFIGURATION' | translate }}</span> </mat-list-item> diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts index 7b886d5..6362f7e 100644 --- a/src/app/app.routes.ts +++ b/src/app/app.routes.ts @@ -6,4 +6,5 @@ export const routes: Routes = [ { path: 'list', loadComponent: () => import('../app/views/gauging-list/gauging-list.component').then(m => m.GaugingListComponent)}, { path: 'gauging/:id', loadComponent: () => import('../app/views/gauging/gauging.component').then(m => m.GaugingComponent)}, { path: 'gauging/edit/:id', loadComponent: () => import('../app/views/gauging/gauging.component').then(m => m.GaugingComponent)}, + { path: 'settings', loadComponent: () => import('../app/views/settings/settings.component').then(m => m.SettingsComponent) }, ]; diff --git a/src/app/views/settings/settings.component.html b/src/app/views/settings/settings.component.html new file mode 100644 index 0000000..ee9dfd2 --- /dev/null +++ b/src/app/views/settings/settings.component.html @@ -0,0 +1,20 @@ +<div class="settings-container"> + <h2>Paramètres</h2> + <mat-card> + <mat-card-header> + <mat-card-title>Langue</mat-card-title> + <mat-card-subtitle>Choisissez votre langue</mat-card-subtitle> + </mat-card-header> + + <mat-card-content> + <mat-form-field appearance="fill"> + <mat-label>Langue</mat-label> + <mat-select (selectionChange)="changeLanguage($event.value)"> + <mat-option value="fr">Français</mat-option> + <mat-option value="en">English</mat-option> + </mat-select> + </mat-form-field> + </mat-card-content> + </mat-card> + </div> + \ No newline at end of file diff --git a/src/app/views/settings/settings.component.scss b/src/app/views/settings/settings.component.scss new file mode 100644 index 0000000..689480f --- /dev/null +++ b/src/app/views/settings/settings.component.scss @@ -0,0 +1,15 @@ +.settings-container { + margin: 20px; + padding: 20px; + } + + mat-card { + margin: 10px 0; + padding: 20px; + background-color: #f9f9f9; + } + + mat-form-field { + width: 100%; + } + \ No newline at end of file diff --git a/src/app/views/settings/settings.component.ts b/src/app/views/settings/settings.component.ts new file mode 100644 index 0000000..1e78dca --- /dev/null +++ b/src/app/views/settings/settings.component.ts @@ -0,0 +1,30 @@ +import { Component } from '@angular/core'; +import { TranslateService } from '@ngx-translate/core'; +import { MatCardModule } from '@angular/material/card'; +import { MatSelectModule } from '@angular/material/select'; + +@Component({ + selector: 'app-settings', + standalone: true, + imports: [MatSelectModule, MatCardModule], + templateUrl: './settings.component.html', + styleUrl: './settings.component.scss' +}) +export class SettingsComponent { + constructor(private translate: TranslateService) { + // Définir la langue par défaut + this.translate.setDefaultLang('fr'); + this.translate.use('fr'); // ou 'en' selon vos préférences + } + + changeLanguage(lang: string) { + this.translate.use(lang); + } + + saveSettings() { + // Logique pour enregistrer les paramètres (si nécessaire) + console.log('Paramètres enregistrés'); + } + + +} -- GitLab From 66e4c27d7c096df912459c19866c1f491ece2b16 Mon Sep 17 00:00:00 2001 From: Jean-Pascal AUBRY <jean-pascal.aubry@inrae.fr> Date: Mon, 14 Oct 2024 15:56:23 +0000 Subject: [PATCH 15/16] fix: refactor translation file for equipment component Refs #6 --- src/app/models/equipment.model.ts | 6 +- .../views/equipment/equipment.component.html | 82 +++++++++---------- src/assets/i18n/en.json | 68 +++++++-------- src/assets/i18n/fr.json | 68 +++++++-------- 4 files changed, 112 insertions(+), 112 deletions(-) diff --git a/src/app/models/equipment.model.ts b/src/app/models/equipment.model.ts index d71f899..f7770d6 100644 --- a/src/app/models/equipment.model.ts +++ b/src/app/models/equipment.model.ts @@ -1,6 +1,6 @@ export enum MaterialType { - ElectromagneticFlowMeter = 'EQUIPMENT.materialTypes.ElectromagneticFlowMeter', - PropellerFlowMeter = 'EQUIPMENT.materialTypes.PropellerFlowMeter', - VelocityHeadRod = 'EQUIPMENT.materialTypes.VelocityHeadRod' + ElectromagneticFlowMeter = 'EQUIPMENT.MATERIAL_TYPES.ELECTROMAGNETIC_FLOW_METER', + PropellerFlowMeter = 'EQUIPMENT.MATERIAL_TYPES.PROPELLER_FLOW_METER', + VelocityHeadRod = 'EQUIPMENT.MATERIAL_TYPES.VELOCITY_HEAD_ROAD' } diff --git a/src/app/views/equipment/equipment.component.html b/src/app/views/equipment/equipment.component.html index 2e0d6b4..355efbe 100644 --- a/src/app/views/equipment/equipment.component.html +++ b/src/app/views/equipment/equipment.component.html @@ -4,10 +4,10 @@ <div class="equipment-list"> @if((materialList$ | async)?.length! > 0){ <div class="equipment-list-title"> - <h1>{{ 'EQUIPMENT.materialListTitle' | translate }}</h1> + <h1>{{ 'EQUIPMENT.MATERIAL_LIST_TITLE' | translate }}</h1> <button mat-raised-button color="primary" [disabled]="showEditMaterialForm" class="equipment-list-title-add" [disabled]="needMaterial" (click)="addMaterial()"> - <span>{{ 'EQUIPMENT.addMaterialButton' | translate }}</span> + <span>{{ 'EQUIPMENT.ADD_MATERIAL_BUTTON' | translate }}</span> <mat-icon class="icon-list-item">add</mat-icon> </button> </div> @@ -25,7 +25,7 @@ <!-- Name Column --> <ng-container matColumnDef="name"> - <th mat-header-cell *matHeaderCellDef>{{ 'EQUIPMENT.nameColumn' | translate }}</th> + <th mat-header-cell *matHeaderCellDef>{{ 'EQUIPMENT.NAME' | translate }}</th> <td mat-cell *matCellDef="let materiel, let i=index" (click)="editMaterial(materiel, i)" id="name-row">{{ materiel.name }} </td> @@ -33,27 +33,27 @@ <!-- Type Column --> <ng-container matColumnDef="type"> - <th mat-header-cell *matHeaderCellDef>{{ 'EQUIPMENT.typeColumn' | translate }}</th> + <th mat-header-cell *matHeaderCellDef>{{ 'EQUIPMENT.TYPE' | translate }}</th> <td mat-cell *matCellDef="let materiel, let i=index" (click)="editMaterial(materiel, i)">{{ materiel.type | translate}} </td> </ng-container> <!-- Serial Number Column --> <ng-container matColumnDef="serialNumber"> - <th mat-header-cell *matHeaderCellDef>{{ 'EQUIPMENT.serialNumberColumn' | translate }}</th> + <th mat-header-cell *matHeaderCellDef>{{ 'EQUIPMENT.SERIALNUMBER' | translate }}</th> <td mat-cell *matCellDef="let materiel, let i=index" (click)="editMaterial(materiel, i)">{{ materiel.serialNumber || '-' }}</td> </ng-container> <!-- Description Column --> <ng-container matColumnDef="description"> - <th class="equipment-list-description" mat-header-cell *matHeaderCellDef>{{ 'EQUIPMENT.descriptionColumn' | translate }}</th> + <th class="equipment-list-description" mat-header-cell *matHeaderCellDef>{{ 'EQUIPMENT.DESCRIPTION' | translate }}</th> <td mat-cell *matCellDef="let materiel, let i=index" (click)="editMaterial(materiel, i)">{{ materiel.description || '-' }}</td> </ng-container> <!-- Edit/Remove Column --> <ng-container matColumnDef="edit"> - <th class="equipment-list-action" mat-header-cell *matHeaderCellDef style=" text-align: center">{{ 'EQUIPMENT.actionsColumn' | translate }}</th> + <th class="equipment-list-action" mat-header-cell *matHeaderCellDef style=" text-align: center">{{ 'EQUIPMENT.ACTIONS' | translate }}</th> <td mat-cell *matCellDef="let materiel, let i =index" style="text-overflow: unset; text-align: center;"> <button mat-icon-button color="primary" (click)="editMaterial(materiel, i)" [disabled]="needMaterial || showEditMaterialForm" id="edit"> @@ -77,10 +77,10 @@ @else{ <!-- if no created material --> <div class="equipment-form-title"> - <h1>{{ 'EQUIPMENT.materialListTitle' | translate }}</h1> - <p>{{ 'EQUIPMENT.noMaterialAvailable' | translate }}</p> + <h1>{{ 'EQUIPMENT.MATERIAL_LIST_TITLE' | translate }}</h1> + <p>{{ 'EQUIPMENT.NO_MATERIAL_AVAILABLE' | translate }}</p> @if(!needMaterial) { - <button mat-raised-button color="primary" (click)="addMaterial()" class="add-button">{{ 'EQUIPMENT.addMaterialButton' | translate }}</button> + <button mat-raised-button color="primary" (click)="addMaterial()" class="add-button">{{ 'EQUIPMENT.ADD_MATERIAL_BUTTON' | translate }}</button> } </div> } @@ -90,14 +90,14 @@ @if(needMaterial || showEditMaterialForm ){ <div class="equipment-form-container"> <form class="equipment-form" [formGroup]="form" (submit)="onSubmit()"> - <h1 class="equipment-form-title">{{needMaterial ? ('EQUIPMENT.newMaterialTitle' | translate) : ('EQUIPMENT.editMaterialTitle' | translate)}}</h1> + <h1 class="equipment-form-title">{{needMaterial ? ('EQUIPMENT.NEW_MATERIAL_TITLE' | translate) : ('EQUIPMENT.EDIT_MATERIAL_TITLE' | translate)}}</h1> <!-- Material Type Section --> <section class="form-section"> - <h2>{{ 'EQUIPMENT.materialTypeLabel' | translate }}</h2> + <h2>{{ 'EQUIPMENT.MATERIAL_TYPE_LABEL' | translate }}</h2> <mat-form-field appearance="outline"> - <mat-label>{{ 'EQUIPMENT.materialTypeLabel' | translate }}</mat-label> - <mat-select formControlName="type" placeholder="{{ 'EQUIPMENT.materialTypeLabel' | translate }}" (selectionChange)="onMaterialTypeChange()"> + <mat-label>{{ 'EQUIPMENT.MATERIAL_TYPE_LABEL' | translate }}</mat-label> + <mat-select formControlName="type" placeholder="{{ 'EQUIPMENT.MATERIAL_TYPE_LABEL' | translate }}" (selectionChange)="onMaterialTypeChange()"> @for (type of materielTypes; track type) { <mat-option [value]="type"> {{ type | translate }} @@ -109,35 +109,35 @@ <!-- Model Section --> <section class="form-section"> - <h2>{{ 'EQUIPMENT.modelSectionTitle' | translate }}</h2> + <h2>{{ 'EQUIPMENT.MODEL_SECTION_TITLE' | translate }}</h2> <mat-form-field appearance="outline"> - <mat-label>{{ 'EQUIPMENT.nameLabel' | translate }}</mat-label> - <input matInput placeholder="{{ 'EQUIPMENT.nameLabel' | translate }}" formControlName="name" autocomplete="name"> + <mat-label>{{ 'EQUIPMENT.NAME_LABEL' | translate }}</mat-label> + <input matInput placeholder="{{ 'EQUIPMENT.NAME_LABEL' | translate }}" formControlName="name" autocomplete="name"> </mat-form-field> @if(hasError('name', 'required')){ - <app-error-message [displayed]="hasError('name', 'required')">{{ 'EQUIPMENT.requiredNameError' | translate }}</app-error-message> + <app-error-message [displayed]="hasError('name', 'required')">{{ 'EQUIPMENT.REQUIRED_NAME_ERROR' | translate }}</app-error-message> } <mat-form-field appearance="outline"> - <mat-label>{{ 'EQUIPMENT.serialNumberLabel' | translate }}</mat-label> - <input matInput placeholder="{{ 'EQUIPMENT.serialNumberLabel' | translate }}" formControlName="serialNumber" autocomplete="off"> + <mat-label>{{ 'EQUIPMENT.SERIALNUMBER_LABEL' | translate }}</mat-label> + <input matInput placeholder="{{ 'EQUIPMENT.SERIALNUMBER_LABEL' | translate }}" formControlName="serialNumber" autocomplete="off"> </mat-form-field> @if(isPropeller) { <!-- Propeller Number --> <mat-form-field appearance="outline"> - <mat-label>{{ 'EQUIPMENT.propellerNumberLabel' | translate }}</mat-label> - <input matInput placeholder="{{ 'EQUIPMENT.propellerNumberLabel' | translate }}" formControlName="propellerNumber" autocomplete="off"> + <mat-label>{{ 'EQUIPMENT.PROPELLERNUMBER_LABEL' | translate }}</mat-label> + <input matInput placeholder="{{ 'EQUIPMENT.PROPELLERNUMBER_LABEL' | translate }}" formControlName="propellerNumber" autocomplete="off"> </mat-form-field> <!-- Propeller Serial Number --> <mat-form-field appearance="outline"> - <mat-label>{{ 'EQUIPMENT.propellerSerialNumberLabel' | translate }}</mat-label> - <input matInput placeholder="{{ 'EQUIPMENT.propellerSerialNumberLabel' | translate }}" formControlName="propellerSerialNumber" autocomplete="off"> + <mat-label>{{ 'EQUIPMENT.PROPELLERSERIALNUMBER_LABEL' | translate }}</mat-label> + <input matInput placeholder="{{ 'EQUIPMENT.PROPELLERSERIALNUMBER_LABEL' | translate }}" formControlName="propellerSerialNumber" autocomplete="off"> </mat-form-field> <!-- Number of Velocity Formulas --> <mat-form-field appearance="outline"> - <mat-label>{{ 'EQUIPMENT.velocityFormulaCountLabel' | translate }}</mat-label> - <mat-select formControlName="velocityFormulaCount" placeholder="{{ 'EQUIPMENT.velocityFormulaCountLabel' | translate }}" (selectionChange)="onVelocityFormulaCountChange($event.value)"> + <mat-label>{{ 'EQUIPMENT.VELOCITY_FORMULA_COUNT_LABEL' | translate }}</mat-label> + <mat-select formControlName="velocityFormulaCount" placeholder="{{ 'EQUIPMENT.VELOCITY_FORMULA_COUNT_LABEL' | translate }}" (selectionChange)="onVelocityFormulaCountChange($event.value)"> <mat-option *ngFor="let count of [1, 2, 3, 4, 5]" [value]="count"> {{count}} </mat-option> @@ -146,31 +146,31 @@ <div formArrayName="velocityFormulas" [ngClass]="{'formulas-section': velocityFormulas.controls.length > 0}"> @for(formula of velocityFormulas.controls; track formula; let i = $index ) { <div [formGroupName]="i"> - <h3>{{ 'EQUIPMENT.velocityFormulaTitle' | translate }} {{ i + 1 }}</h3> + <h3>{{ 'EQUIPMENT.VELOCITY_FORMULA_TITLE_LABEL' | translate }} {{ i + 1 }}</h3> <div class="form-field-row"> <mat-form-field appearance="outline" class="form-field-inline"> - <mat-label>{{ 'EQUIPMENT.lowerBoundLabel' | translate }}</mat-label> - <input matInput placeholder="{{ 'EQUIPMENT.lowerBoundLabel' | translate }}" formControlName="lowerBound"> + <mat-label>{{ 'EQUIPMENT.LOWER_BOUND_LABEL' | translate }}</mat-label> + <input matInput placeholder="{{ 'EQUIPMENT.LOWER_BOUND_LABEL' | translate }}" formControlName="lowerBound"> </mat-form-field> <!-- Error Message --> <mat-form-field appearance="outline" class="form-field-inline"> - <mat-label>{{ 'EQUIPMENT.upperBoundLabel' | translate }}</mat-label> - <input matInput placeholder="{{ 'EQUIPMENT.upperBoundLabel' | translate }}" formControlName="upperBound"> + <mat-label>{{ 'EQUIPMENT.UPPER_BOUND_LABEL' | translate }}</mat-label> + <input matInput placeholder="{{ 'EQUIPMENT.UPPER_BOUND_LABEL' | translate }}" formControlName="upperBound"> </mat-form-field> </div> @if(formula.errors?.invalidBounds) { - <mat-error>{{ 'EQUIPMENT.invalidBoundsError' | translate }}</mat-error> + <mat-error>{{ 'EQUIPMENT.INVALID_BOUNDS_ERROR' | translate }}</mat-error> } <!-- Second row: Coefficient A and B --> <div class="form-field-row"> <mat-form-field appearance="outline" class="form-field-inline"> - <mat-label>{{ 'EQUIPMENT.coefALabel' | translate }}</mat-label> - <input matInput placeholder="{{ 'EQUIPMENT.coefALabel' | translate }}" formControlName="coefA"> + <mat-label>{{ 'EQUIPMENT.COEF_A_LABEL' | translate }}</mat-label> + <input matInput placeholder="{{ 'EQUIPMENT.COEF_A_LABEL' | translate }}" formControlName="coefA"> </mat-form-field> <mat-form-field appearance="outline" class="form-field-inline"> - <mat-label>{{ 'EQUIPMENT.constantBLabel' | translate }}</mat-label> - <input matInput placeholder="{{ 'EQUIPMENT.constantBLabel' | translate }}" formControlName="constantB"> + <mat-label>{{ 'EQUIPMENT.CONSTANT_B_LABEL' | translate }}</mat-label> + <input matInput placeholder="{{ 'EQUIPMENT.CONSTANT_B_LABEL' | translate }}" formControlName="constantB"> </mat-form-field> </div> </div> @@ -180,15 +180,15 @@ </section> <section class="form-section"> - <h2>{{ 'EQUIPMENT.additionalInfoTitle' | translate }}</h2> + <h2>{{ 'EQUIPMENT.ADDITIONAL_INFO_TITLE' | translate }}</h2> <mat-form-field class="equipment-description" appearance="outline"> - <mat-label>{{ 'EQUIPMENT.descriptionLabel' | translate }}</mat-label> - <textarea matInput placeholder="{{ 'EQUIPMENT.descriptionLabel' | translate }}" formControlName="description" rows="4" autocomplete="off"></textarea> + <mat-label>{{ 'EQUIPMENT.DESCRIPTION_LABEL' | translate }}</mat-label> + <textarea matInput placeholder="{{ 'EQUIPMENT.DESCRIPTION_LABEL' | translate }}" formControlName="description" rows="4" autocomplete="off"></textarea> </mat-form-field> </section> - <button style="margin-right: 4%;" mat-flat-button color="primary" class="submit-button" [disabled]="!form.valid">{{ 'EQUIPMENT.submitButton' | translate }}</button> - <button mat-flat-button color="warn" (click)="closeMaterialForm()" class="submit-button">{{ 'EQUIPMENT.cancelButton' | translate }}</button> + <button style="margin-right: 4%;" mat-flat-button color="primary" class="submit-button" [disabled]="!form.valid">{{ 'EQUIPMENT.SUBMIT_BUTTON' | translate }}</button> + <button mat-flat-button color="warn" (click)="closeMaterialForm()" class="submit-button">{{ 'EQUIPMENT.CANCEL_BUTTON' | translate }}</button> </form> </div> } diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 0c16df3..ae2ddd6 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -129,41 +129,41 @@ "GRAPHICAL_REPRESENTATION": "Graphical representation" }, "EQUIPMENT": { - "materialListTitle": "Material List", - "addMaterialButton": "Add", - "noMaterialAvailable": "No material available.", - "actionsColumn": "Actions", - "nameColumn": "Name", - "typeColumn": "Type", - "serialNumberColumn": "Serial Number", - "descriptionColumn": "Description", - "editButton": "Edit", - "deleteButton": "Delete", - "newMaterialTitle": "New Material", - "editMaterialTitle": "Edit Material", - "materialTypeLabel": "Material Type", - "materialTypes": { - "ElectromagneticFlowMeter": "Electromagnetic Flow Meter", - "PropellerFlowMeter": "Propeller Flow Meter", - "VelocityHeadRod": "Velocity Head Rod" + "MATERIAL_LIST_TITLE": "Material List", + "ADD_MATERIAL_BUTTON": "Add", + "NO_MATERIAL_AVAILABLE": "No material available.", + "ACTIONS": "Actions", + "NAME": "Name", + "TYPE": "Type", + "SERIALNUMBER": "Serial Number", + "DESCRIPTION": "Description", + "EDIT_BUTTON": "Edit", + "DELETE_BUTTON": "Delete", + "NEW_MATERIAL_TITLE": "New Material", + "EDIT_MATERIAL_TITLE": "Edit Material", + "MATERIAL_TYPE_LABEL": "Material Type", + "MATERIAL_TYPES": { + "ELECTROMAGNETIC_FLOW_METER": "Electromagnetic flow meter", + "PROPELLER_FLOW_METER": "Propeller flow meter", + "VELOCITY_HEAD_ROAD": "Velocity head road" }, - "modelSectionTitle": "Model", - "nameLabel": "Name", - "serialNumberLabel": "Serial Number", - "propellerNumberLabel": "Propeller Number", - "propellerSerialNumberLabel": "Propeller Serial Number", - "velocityFormulaCountLabel": "Number of Velocity Formulas", - "velocityFormulaTitle": "Velocity Formula n°", - "lowerBoundLabel": "Lower Bound", - "upperBoundLabel": "Upper Bound", - "coefALabel": "Coefficient A", - "constantBLabel": "Constant B", - "invalidBoundsError": "The specified bounds are incorrect. The lower bound must be strictly less than the upper bound.", - "requiredNameError": "The name is required.", - "additionalInfoTitle": "Additional information", - "descriptionLabel": "Description", - "submitButton": "Submit", - "cancelButton": "Cancel" + "MODEL_SECTION_TITLE": "Model", + "NAME_LABEL": "Name", + "SERIALNUMBER_LABEL": "Serial Number", + "PROPELLERNUMBER_LABEL": "Propeller Number", + "PROPELLERSERIALNUMBER_LABEL": "Propeller Serial Number", + "VELOCITY_FORMULA_COUNT_LABEL": "Number of Velocity Formulas", + "VELOCITY_FORMULA_TITLE_LABEL": "Velocity Formula n°", + "LOWER_BOUND_LABEL": "Lower Bound", + "UPPER_BOUND_LABEL": "Upper Bound", + "COEF_A_LABEL": "Coefficient A", + "CONSTANT_B_LABEL": "Constant B", + "INVALID_BOUNDS_ERROR": "The specified bounds are incorrect. The lower bound must be strictly less than the upper bound.", + "REQUIRED_NAME_ERROR": "The name is required.", + "ADDITIONAL_INFO_TITLE": "Additional information", + "DESCRIPTION_LABEL": "Description", + "SUBMIT_BUTTON": "Submit", + "CANCEL_BUTTON": "Cancel" }, "NEXT": "Next", "PREVIOUS": "Previous", diff --git a/src/assets/i18n/fr.json b/src/assets/i18n/fr.json index 817f5c3..467cbb4 100644 --- a/src/assets/i18n/fr.json +++ b/src/assets/i18n/fr.json @@ -129,41 +129,41 @@ "GRAPHICAL_REPRESENTATION": "Représentation graphique" }, "EQUIPMENT": { - "materialListTitle": "Liste de Matériel", - "addMaterialButton": "Ajouter", - "noMaterialAvailable": "Aucun matériel disponible.", - "actionsColumn": "Actions", - "nameColumn": "Nom", - "typeColumn": "Type", - "serialNumberColumn": "Numéro de Série", - "descriptionColumn": "Description", - "editButton": "Modifier", - "deleteButton": "Supprimer", - "newMaterialTitle": "Nouveau Matériel", - "editMaterialTitle": "Modifier Matériel", - "materialTypeLabel": "Type de Matériel", - "materialTypes": { - "ElectromagneticFlowMeter": "Courantomètre Électromagnétique", - "PropellerFlowMeter": "Moulinet", - "VelocityHeadRod": "Perche à Charge Dynamique Transparente" + "MATERIAL_LIST_TITLE": "Liste de Matériel", + "ADD_MATERIAL_BUTTON": "Ajouter", + "NO_MATERIAL_AVAILABLE": "Aucun matériel disponible.", + "ACTIONS": "Actions", + "NAME": "Nom", + "TYPE": "Type", + "SERIALNUMBER": "Numéro de Série", + "DESCRIPTION": "Description", + "EDIT_BUTTON": "Modifier", + "DELETE_BUTTON": "Supprimer", + "NEW_MATERIAL_TITLE": "Nouveau Matériel", + "EDIT_MATERIAL_TITLE": "Modifier Matériel", + "MATERIAL_TYPE_LABEL": "Type de Matériel", + "MATERIAL_TYPES": { + "ELECTROMAGNETIC_FLOW_METER": "Courantomètre Électromagnétique", + "PROPELLER_FLOW_METER": "Moulinet", + "VELOCITY_HEAD_ROAD": "Perche à Charge Dynamique Transparente" }, - "modelSectionTitle": "Modèle", - "nameLabel": "Nom", - "serialNumberLabel": "Numéro de Série", - "propellerNumberLabel": "Numéro de Moulinet", - "propellerSerialNumberLabel": "Numéro de Série du Moulinet", - "velocityFormulaCountLabel": "Nombre de Formules de Vitesse", - "velocityFormulaTitle": "Formule de Vitesse n°", - "lowerBoundLabel": "Limite Inférieure", - "upperBoundLabel": "Limite Supérieure", - "coefALabel": "Coefficient A", - "constantBLabel": "Constante B", - "invalidBoundsError": "Les limites spécifiées sont incorrectes. La limite inférieure doit être strictement inférieure à la limite supérieure.", - "requiredNameError": "Le nom est requis.", - "additionalInfoTitle": "Informations complémentaires", - "descriptionLabel": "Description", - "submitButton": "Valider", - "cancelButton": "Annuler" + "MODEL_SECTION_TITLE": "Modèle", + "NAME_LABEL": "Nom", + "SERIALNUMBER_LABEL": "Numéro de Série", + "PROPELLERNUMBER_LABEL": "Numéro de Moulinet", + "PROPELLERSERIALNUMBER_LABEL": "Numéro de Série du Moulinet", + "VELOCITY_FORMULA_COUNT_LABEL": "Nombre de Formules de Vitesse", + "VELOCITY_FORMULA_TITLE_LABEL": "Formule de Vitesse n°", + "LOWER_BOUND_LABEL": "Limite Inférieure", + "UPPER_BOUND_LABEL": "Limite Supérieure", + "COEF_A_LABEL": "Coefficient A", + "CONSTANT_B_LABEL": "Constante B", + "INVALID_BOUNDS_ERROR": "Les limites spécifiées sont incorrectes. La limite inférieure doit être strictement inférieure à la limite supérieure.", + "REQUIRED_NAME_ERROR": "Le nom est requis.", + "ADDITIONAL_INFO_TITLE": "Informations complémentaires", + "DESCRIPTION_LABEL": "Description", + "SUBMIT_BUTTON": "Valider", + "CANCEL_BUTTON": "Annuler" }, "NEXT": "Suivant", "PREVIOUS": "Précédent", -- GitLab From 7427477aa7d3a57f32919bb00f039e197088a2ed Mon Sep 17 00:00:00 2001 From: Jean-Pascal AUBRY <jean-pascal.aubry@inrae.fr> Date: Tue, 15 Oct 2024 09:30:33 +0000 Subject: [PATCH 16/16] fix: add LanguageService for handling language settings Refs #6 --- src/app/app.component.ts | 9 +- src/app/services/language/language.service.ts | 28 ++++++ .../views/settings/settings.component.html | 43 +++++---- .../views/settings/settings.component.scss | 95 ++++++++++++++++--- src/app/views/settings/settings.component.ts | 33 ++++--- 5 files changed, 156 insertions(+), 52 deletions(-) create mode 100644 src/app/services/language/language.service.ts diff --git a/src/app/app.component.ts b/src/app/app.component.ts index a51cede..6f77559 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -24,6 +24,7 @@ import { DialogConfirmNewGaugingComponent } from './components/dialog/dialog-con import { GaugingFormService } from './services/forms/gauging-form.service'; import { TranslateModule, TranslateService } from '@ngx-translate/core'; import { MatTooltipModule } from '@angular/material/tooltip'; +import { LanguageService } from './services/language/language.service'; @Component({ @@ -41,16 +42,16 @@ export class AppComponent { gaugingList$: Observable<Gauging[]>; materialList: Material[] = []; - constructor(private translate: TranslateService,private dialog: MatDialog, private equipmentService: EquipmentService, private gaugingService: GaugingService, private gaugingFormService: GaugingFormService, private router: Router) { + constructor(private languageService: LanguageService, private dialog: MatDialog, private equipmentService: EquipmentService, private gaugingService: GaugingService, private gaugingFormService: GaugingFormService, private router: Router) { this.materialList$ = this.equipmentService.materialList$; this.gaugingList$ = this.gaugingService.gaugingList$; - this.translate.addLangs(['fr', 'en']); - this.translate.setDefaultLang('fr'); - this.translate.use('en'); } ngOnInit(): void { // Charger les données de session depuis le localStorage + // Détecter et appliquer la langue par défaut via le LanguageService + const browserLang = this.languageService.detectBrowserLanguage(); + this.languageService.setDefaultLanguage(browserLang); this.session.loadFromLocalStorage(); if (typeof window !== 'undefined' && typeof sessionStorage !== 'undefined') { const wasPageRefreshed = sessionStorage.getItem('pageRefreshed'); diff --git a/src/app/services/language/language.service.ts b/src/app/services/language/language.service.ts new file mode 100644 index 0000000..a1802bb --- /dev/null +++ b/src/app/services/language/language.service.ts @@ -0,0 +1,28 @@ +import { Injectable } from '@angular/core'; +import { TranslateService } from '@ngx-translate/core'; + +@Injectable({ + providedIn: 'root' +}) +export class LanguageService { + supportedLanguages = ['fr', 'en']; + constructor(private translate: TranslateService) {} + + // Détecter la langue du navigateur et retourner l'anglais par défaut si elle n'est pas supportée + detectBrowserLanguage(): string { + const browserLang = navigator.language.split('-')[0]; + // Si la langue du navigateur est supportée, on l'utilise, sinon on met 'en' (anglais) par défaut + return this.supportedLanguages.includes(browserLang) ? browserLang : 'en'; + } + + // Changer la langue + changeLanguage(lang: string) { + this.translate.use(lang); + } + + // Définir la langue par défaut + setDefaultLanguage(lang: string) { + this.translate.setDefaultLang(lang); + this.translate.use(lang); + } +} diff --git a/src/app/views/settings/settings.component.html b/src/app/views/settings/settings.component.html index ee9dfd2..7ecbe97 100644 --- a/src/app/views/settings/settings.component.html +++ b/src/app/views/settings/settings.component.html @@ -1,20 +1,23 @@ -<div class="settings-container"> - <h2>Paramètres</h2> - <mat-card> - <mat-card-header> - <mat-card-title>Langue</mat-card-title> - <mat-card-subtitle>Choisissez votre langue</mat-card-subtitle> - </mat-card-header> - - <mat-card-content> - <mat-form-field appearance="fill"> - <mat-label>Langue</mat-label> - <mat-select (selectionChange)="changeLanguage($event.value)"> - <mat-option value="fr">Français</mat-option> - <mat-option value="en">English</mat-option> - </mat-select> - </mat-form-field> - </mat-card-content> - </mat-card> - </div> - \ No newline at end of file +<div class="container"> + <h1> + <mat-label> + <mat-icon class="icon-list-item">settings</mat-icon> Paramètres + </mat-label> + </h1> + <mat-card class="form-section"> + <mat-card-header> + <mat-card-title> + <mat-icon>public</mat-icon> Langue + </mat-card-title> + </mat-card-header> + <mat-card-content> + <mat-form-field appearance="fill"> + <mat-label>Langue</mat-label> + <mat-select [(value)]="selectedLanguage" (selectionChange)="changeLanguage($event.value)"> + <mat-option value="fr">Français</mat-option> + <mat-option value="en">English</mat-option> + </mat-select> + </mat-form-field> + </mat-card-content> + </mat-card> +</div> diff --git a/src/app/views/settings/settings.component.scss b/src/app/views/settings/settings.component.scss index 689480f..05f5ead 100644 --- a/src/app/views/settings/settings.component.scss +++ b/src/app/views/settings/settings.component.scss @@ -1,15 +1,88 @@ +$primary: #00a3a6; +$light-primary: #b3e3e4; +$warn: #ff6347; +$light-warn: #FBE9E7; +$accent: #735fff; +$light-accent: #c6c1dc; +$sub-container-background: #f5f5f5; +$table-header-background: #797870; +$border-color: #ccc; +$odd-row-color: rgba(0, 0, 0, 0.028); +$pair-row-color: #ffffff; +$card-shadow-color: rgba(0, 0, 0, 0.1); + +.container { + display: flex; + flex-direction: column; + height: 95%; + margin: 20px; + border: 1px solid $border-color; + border-radius: 12px; + box-shadow: 0 4px 8px $card-shadow-color; + background-color: $sub-container-background; + padding: 20px; +} + .settings-container { - margin: 20px; - padding: 20px; - } + flex: 1; + margin: 10px; + padding: 15px; + border: 1px solid $border-color; + border-radius: 10px; + background-color: #ffffff; + box-shadow: 0 2px 5px $card-shadow-color; +} + +h1 { + font-size: 24px; + text-align: center; + margin-bottom: 20px; +} + +mat-icon { + vertical-align: middle; +} + +.form-section { + margin-bottom: 30px; + padding: 25px; + border: 1px solid $border-color; + border-radius: 10px; + background-color: #ffffff; + box-shadow: 0 2px 4px $card-shadow-color; + transition: box-shadow 0.3s ease; - mat-card { - margin: 10px 0; - padding: 20px; - background-color: #f9f9f9; + &:hover { + box-shadow: 0 4px 10px $card-shadow-color; } - - mat-form-field { - width: 100%; +} + +mat-card-header { + border-radius: 8px 8px 0 0; +} + +mat-card-title { + font-size: 20px; + color: $primary; + font-weight: 500; +} + +mat-form-field { + width: 100%; + margin-top: 15px; +} + +mat-select { + border-radius: 5px; +} + +mat-option { + &:hover { + background-color: $light-accent; } - \ No newline at end of file +} + +mat-card-content { + padding: 20px; + font-size: 16px; +} diff --git a/src/app/views/settings/settings.component.ts b/src/app/views/settings/settings.component.ts index 1e78dca..19c6e8f 100644 --- a/src/app/views/settings/settings.component.ts +++ b/src/app/views/settings/settings.component.ts @@ -1,30 +1,29 @@ -import { Component } from '@angular/core'; -import { TranslateService } from '@ngx-translate/core'; +import { Component, OnInit } from '@angular/core'; import { MatCardModule } from '@angular/material/card'; import { MatSelectModule } from '@angular/material/select'; +import { MatIconModule } from '@angular/material/icon'; +import { LanguageService } from '../../services/language/language.service'; @Component({ selector: 'app-settings', standalone: true, - imports: [MatSelectModule, MatCardModule], + imports: [MatSelectModule, MatCardModule, MatIconModule], templateUrl: './settings.component.html', - styleUrl: './settings.component.scss' + styleUrls: ['./settings.component.scss'] }) -export class SettingsComponent { - constructor(private translate: TranslateService) { - // Définir la langue par défaut - this.translate.setDefaultLang('fr'); - this.translate.use('fr'); // ou 'en' selon vos préférences - } +export class SettingsComponent implements OnInit { + selectedLanguage: string | undefined; - changeLanguage(lang: string) { - this.translate.use(lang); - } + constructor(private languageService: LanguageService) {} - saveSettings() { - // Logique pour enregistrer les paramètres (si nécessaire) - console.log('Paramètres enregistrés'); + ngOnInit(): void { + // Utiliser le service pour détecter la langue du navigateur et définir la langue par défaut (anglais si aucune n'est supportée) + this.selectedLanguage = this.languageService.detectBrowserLanguage(); + this.languageService.setDefaultLanguage(this.selectedLanguage); } - + changeLanguage(lang: string) { + this.languageService.changeLanguage(lang); + this.selectedLanguage = lang; + } } -- GitLab