Résolution de conflits entre develop et rh

develop
jboinembalome 4 years ago
commit ca628f3e5f
  1. 8
      src/app/app.module.ts
  2. 40
      src/app/formations/formations.component.html
  3. 105
      src/app/formations/formations.component.ts
  4. 2
      src/app/formations/formations.module.ts
  5. 46
      src/app/home/home-rh/home-rh.component.html
  6. 116
      src/app/home/home-rh/home-rh.component.ts
  7. 2
      src/app/home/home.module.ts
  8. 5
      src/app/shared/angular-material/angular-material.module.ts
  9. 0
      src/app/shared/filter/checkbox-filter/checkbox-filter.css
  10. 14
      src/app/shared/filter/checkbox-filter/checkbox-filter.html
  11. 120
      src/app/shared/filter/checkbox-filter/checkbox-filter.ts
  12. 28
      src/app/shared/filter/filter.module.ts
  13. 4
      src/app/shared/filter/select-filter/select-filter.css
  14. 11
      src/app/shared/filter/select-filter/select-filter.html
  15. 116
      src/app/shared/filter/select-filter/select-filter.ts
  16. 11
      src/app/shared/filter/selected-element.ts
  17. 0
      src/app/shared/mat-tables/formations-table/formations.table.css
  18. 84
      src/app/shared/mat-tables/formations-table/formations.table.html
  19. 256
      src/app/shared/mat-tables/formations-table/formations.table.ts
  20. 18
      src/app/shared/mat-tables/mat-tables.module.ts
  21. 2
      src/environments/environment.ts

@ -27,6 +27,7 @@ import { AuthModule } from '@shared/auth/auth.module';
import { MatTablesModule } from "@shared/mat-tables/mat-tables.module"; import { MatTablesModule } from "@shared/mat-tables/mat-tables.module";
import { EngagementsModule } from './engagements'; import { EngagementsModule } from './engagements';
import { NotesModule } from './notes'; import { NotesModule } from './notes';
import { FilterModule } from "@shared/filter/filter.module";
@NgModule({ @NgModule({
declarations: [ declarations: [
@ -39,10 +40,9 @@ import { NotesModule } from './notes';
HomeModule, CollaborateursModule, HomeModule, CollaborateursModule,
ReferentsModule, FormationsModule, ReferentsModule, FormationsModule,
DemandesFormationModule, DemandesDelegationModule, DemandesFormationModule, DemandesDelegationModule,
EpSaisieModule, EpModule, MatTablesModule, EpSaisieModule, NotesModule, EpModule,
AffichageDetailsCollaborateurModule, EngagementsModule, MatTablesModule, FilterModule,
NotesModule AffichageDetailsCollaborateurModule, EngagementsModule
], ],
providers: [], providers: [],
bootstrap: [AppComponent] bootstrap: [AppComponent]

@ -1,42 +1,4 @@
<app-nav-menu></app-nav-menu> <app-nav-menu></app-nav-menu>
<h1>Liste des formations </h1> <h1>Liste des formations </h1>
<!-- Affichage de la liste des formations--> <formations-table [rechercherParStatutFormation]="rechercherParStatutFormation" [displayedColumns]="displayedColumns"></formations-table>
<mat-table [dataSource]="this.dataSource">
<ng-container matColumnDef="intitule">
<mat-header-cell *matHeaderCellDef>Intitulé</mat-header-cell>
<mat-cell *matCellDef="let row">{{ row.intitule }}</mat-cell>
</ng-container>
<ng-container matColumnDef=participants>
<mat-header-cell *matHeaderCellDef>Nb participants</mat-header-cell>
<mat-cell *matCellDef="let row">{{ row.nbParticipants }}</mat-cell>
</ng-container>
<ng-container matColumnDef="date">
<mat-header-cell *matHeaderCellDef>Date prévisionnelle</mat-header-cell>
<mat-cell *matCellDef="let row">{{ row.dateDebut | date:'dd/MM/yy à hh:mm' }}</mat-cell>
</ng-container>
<ng-container matColumnDef="origine">
<mat-header-cell *matHeaderCellDef>Origine</mat-header-cell>
<mat-cell *matCellDef="let row"> {{ row.origine.libelle}}</mat-cell>
</ng-container>
<ng-container matColumnDef="statut">
<mat-header-cell *matHeaderCellDef>Statut</mat-header-cell>
<mat-cell *matCellDef="let row">{{row.statut.libelle}}</mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<!-- Lien vers les détails d'une formation-->
<mat-row *matRowDef="let row; columns: displayedColumns;" [routerLink]="['/formations',row.id]"></mat-row>
</mat-table>
<mat-paginator #paginator
[length] = "taille"
[pageIndex]="numPage-1"
[pageSize]="parPage"
[pageSizeOptions]="pageOption"
(page)="pageEvent = updatePageInfo($event)"
>
</mat-paginator>

@ -1,13 +1,4 @@
import { Component, OnInit, ViewChild } from '@angular/core'; import { Component } from '@angular/core';
import { Observable, Subscription } from 'rxjs';
import {MatTableDataSource} from '@angular/material/table';
import {MatPaginator, PageEvent} from '@angular/material/paginator';
import {MatSort} from '@angular/material/sort';
import { FormationDetailsDTO } from "@shared/api-swagger/model/models";
import { FormationsService } from "@shared/api-swagger/api/api";
/** /**
*/ */
@ -15,96 +6,16 @@ import { FormationsService } from "@shared/api-swagger/api/api";
selector: 'app-formations', selector: 'app-formations',
templateUrl: './formations.component.html' templateUrl: './formations.component.html'
}) })
export class FormationsComponent implements OnInit { export class FormationsComponent {
/** /**
* Ordre de tri à envoyer au serveur (true : croissant, false : décroissantà). * Liste des colonnes du tableau à afficher.
*/ */
asc = true; displayedColumns: string[] = ["intitule", "origine", "participants", "date", "statut","certification"];
/**
* Numéro de la page à afficher dans le tableau.
*/
numPage = 1;
/**
* Nombre d'élément du tableau à affiche en une page.
*/
parPage = 5;
etat = 0;
/**
* Observable permettant de faire des requêtes sur le service formation.
*/
private formationsDisponiblesSubscription : Subscription;
//displayedColumns: string[] = ["intitule", "participants", "date", "origine", "statut"]
/**
* Les colonnes à afficher dans le Mat Table
*/
displayedColumns: string[] = ["intitule", "origine", "participants", "date", "statut"]
/**
* source pour l'affichage des formations dans le tableau qui est affichée.
*/
dataSource : MatTableDataSource<FormationDetailsDTO>;
/** /**
* contenu de la recherche. * Indique si la recherche par statut de formation est activée ou non
*/ */
search = ""; rechercherParStatutFormation: boolean = true;
tri = "";
taille = 100;
pageOption = [ 5, 15, 20, 30, 50];
pageEvent: PageEvent;
/**
* Pagination du tableau.
*/
@ViewChild(MatPaginator) paginator: MatPaginator;
/**
* Tri par les éléments du tableau selon la colonne choisie.
*/
@ViewChild(MatSort) sort: MatSort;
/**
* Spécifie si la liste des EP est en cours de chargement et d'écriture dans le tableau.
*/
chargement = true;
constructor(private service:FormationsService) {
}
ngOnInit() {
this.updateDataSource();
}
updateDataSource() {
this.formationsDisponiblesSubscription = this.service.getFormations(1,[1,2,3,4], this.asc,this.numPage, this.parPage, this.search, this.tri).subscribe(
formations => this.dataSource = new MatTableDataSource(formations),
err => console.log(err)
);
//this.dataSource.paginator = this.paginator;
//this.dataSource.sort = this.sort;
}
updatePageInfo(event) : PageEvent{
console.log("update")
console.log(event);
this.parPage = event.pageSize;
this.numPage = event.pageIndex+1;
this.updateDataSource();
return event;
}
ngOnDestroy() {
if(this.formationsDisponiblesSubscription != undefined) {
this.formationsDisponiblesSubscription.unsubscribe();
}
}
} }

@ -5,6 +5,7 @@ import { RouterModule } from '@angular/router';
import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MaterialModule } from "@shared/angular-material/angular-material.module"; import { MaterialModule } from "@shared/angular-material/angular-material.module";
import { MatTablesModule } from "@shared/mat-tables/mat-tables.module";
import {NavMenuModule} from '@shared/nav-menu/nav-menu.module'; import {NavMenuModule} from '@shared/nav-menu/nav-menu.module';
@ -29,6 +30,7 @@ import { FormationsRoutingModule } from './formations.routing.module';
CommonModule, CommonModule,
MaterialModule, MaterialModule,
NavMenuModule, NavMenuModule,
MatTablesModule,
RouterModule, RouterModule,
FormationsRoutingModule, FormationsRoutingModule,
ReactiveFormsModule ReactiveFormsModule

@ -1,47 +1,3 @@
<h1> Page RH </h1> <h1> Page RH </h1>
<!-- Affichage de la liste des prochaines formation--> <formations-table [rechercherParStatutFormation]="rechercherParStatutFormation" [displayedColumns]="displayedColumns"></formations-table>
<mat-table [dataSource]="this.dataSource">
<ng-container matColumnDef="intitule">
<mat-header-cell *matHeaderCellDef>Intitulé</mat-header-cell>
<mat-cell *matCellDef="let row">{{ row.intitule }}</mat-cell>
</ng-container>
<ng-container matColumnDef=participants>
<mat-header-cell *matHeaderCellDef>Nb participants</mat-header-cell>
<mat-cell *matCellDef="let row">{{ row.nbParticipants }}</mat-cell>
</ng-container>
<ng-container matColumnDef="date">
<mat-header-cell *matHeaderCellDef>Date prévisionnelle</mat-header-cell>
<mat-cell *matCellDef="let row">{{ row.dateDebut | date:'dd/MM/yyyy à hh:mm' }}</mat-cell>
</ng-container>
<ng-container matColumnDef="origine">
<mat-header-cell *matHeaderCellDef>Origine</mat-header-cell>
<mat-cell *matCellDef="let row">{{row.origine.libelle}}</mat-cell>
</ng-container>
<ng-container matColumnDef="statut">
<mat-header-cell *matHeaderCellDef>Statut</mat-header-cell>
<mat-cell *matCellDef="let row">{{row.statut.libelle}}</mat-cell>
</ng-container>
<ng-container matColumnDef="certification">
<mat-header-cell *matHeaderCellDef>Certifiée</mat-header-cell>
<mat-cell *matCellDef="let row">{{estCertifiee(row.estCertifiee)}}</mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<!-- Lien vers les détails d'une formation-->
<mat-row *matRowDef="let row; columns: displayedColumns;" [routerLink]="['/formations',row.id]"></mat-row>
</mat-table>
<!--[length]="taille"-->
<mat-paginator #paginator
[length] = "taille"
[pageIndex]="numPage-1"
[pageSize]="parPage"
[pageSizeOptions]="pageOption"
(page)="pageEvent = updatePageInfo($event)"
>
</mat-paginator>

@ -1,12 +1,4 @@
import { Component, OnInit, ViewChild } from '@angular/core'; import { Component } from '@angular/core';
import { Observable, Subscription } from 'rxjs';
import {MatTableDataSource} from '@angular/material/table';
import {MatPaginator, PageEvent} from '@angular/material/paginator';
import {MatSort} from '@angular/material/sort';
import { FormationDetailsDTO } from "@shared/api-swagger/model/models";
import { FormationsService } from "@shared/api-swagger/api/api";
/** /**
@ -19,107 +11,19 @@ import { FormationsService } from "@shared/api-swagger/api/api";
selector : 'home-rh', selector : 'home-rh',
templateUrl : 'home-rh.component.html' templateUrl : 'home-rh.component.html'
}) })
export class HomeRHComponent implements OnInit { export class HomeRHComponent {
/** /**
* Ordre de tri à envoyer au serveur (true : croissant, false : décroissantà). * Liste des colonnes du tableau à afficher.
*/
asc = true;
/**
* Numéro de la page à afficher dans le tableau.
*/
numPage = 1;
/**
* Nombre d'élément du tableau à affiche en une page.
*/
parPage = 15;
/**
* Permet d'indiquer au serveur sur quel attribut de l'objet CollaborateurDTO on souhaite faire le tri
*/ */
tri = ""; displayedColumns: string[] = ["intitule", "origine", "participants", "date", "statut","certification"];
taille = 100;
pageOption = [ 5, 15, 20, 30, 50];
pageEvent: PageEvent;
/**
* Observable pour faire des requêtes sur le service formation.
*/
private formationsDisponiblesSubscription : Subscription;
/** /**
* Colonnes du tableau à afficher * Indique si la recherche par statut de formation est activée ou non
*/ */
displayedColumns: string[] = ["intitule", "origine", "participants", "date", "statut","certification"]; rechercherParStatutFormation: boolean = true;
//displayedColumns: string[] = ["intitule", "participants", "date", "origine", "statut"]
//displayedColumns: string[] = ["intitule", "participants", "date", "statut","certification"]; constructor() {}
/**
* source pour l'affichage des formations dans le tableau Mat Table.
*/
dataSource : MatTableDataSource<FormationDetailsDTO>;
/**
* contenu de la recherche.
*/
search = "";
/**
* Pagination du tableau.
*/
@ViewChild(MatPaginator) paginator: MatPaginator;
/**
* Tri par les éléments du tableau selon la colonne choisie.
*/
@ViewChild(MatSort) sort: MatSort;
/**
* Spécifie si la liste des EP est en cours de chargement et d'écriture dans le tableau.
*/
chargement = true;
constructor(private service:FormationsService) {
}
ngOnInit() {
this.updateFormations();
}
/**
* Mettre à jour les informations à afficher dans la tableau.
* Devra se faire à l'ouverture de la page, au changement de page ou du nombre d'éléments à afficher, au moment d'un tri ou encore lors de l'utilisation de la barre de recherche.
*/
updateFormations() {
console.log(this.numPage);
console.log(this.parPage);
this.formationsDisponiblesSubscription = this.service.getFormations(1,[1,2],this.asc, this.numPage, this.parPage, this.search, this.tri).subscribe(
formations => this.dataSource = new MatTableDataSource(formations),
err => console.log(err)
)
}
estCertifiee(certifiee: boolean) {
if(certifiee)
return "Oui";
return "Non";
}
updatePageInfo(event) : PageEvent{
console.log("update")
console.log(event);
this.parPage = event.pageSize;
this.numPage = event.pageIndex+1;
this.updateFormations();
return event;
}
/**
* Une fois la page fermée, il est nécessaire de se désabonner des Oberservable afin d'éviter les fuites mémoires.
*/
ngOnDestroy() {
if(this.formationsDisponiblesSubscription != undefined) {
this.formationsDisponiblesSubscription.unsubscribe();
}
}
} }

@ -4,6 +4,7 @@ import { RouterModule } from '@angular/router';
import { FormsModule } from '@angular/forms'; import { FormsModule } from '@angular/forms';
import { MaterialModule } from "@shared/angular-material/angular-material.module"; import { MaterialModule } from "@shared/angular-material/angular-material.module";
import { MatTablesModule } from "@shared/mat-tables/mat-tables.module";
import {HomeAssistanteComponent} from './home-assistante/home-assistante.component'; import {HomeAssistanteComponent} from './home-assistante/home-assistante.component';
import {HomeRHComponent} from './home-rh/home-rh.component'; import {HomeRHComponent} from './home-rh/home-rh.component';
@ -30,6 +31,7 @@ import {NavMenuModule} from '@shared/nav-menu/nav-menu.module';
FormsModule, FormsModule,
MaterialModule, MaterialModule,
NavMenuModule, NavMenuModule,
MatTablesModule,
RouterModule RouterModule
], ],
}) })

@ -9,6 +9,7 @@ import {MatMenuModule} from '@angular/material/menu';
import {MatPaginatorModule} from '@angular/material/paginator'; import {MatPaginatorModule} from '@angular/material/paginator';
import {MatTableModule} from '@angular/material/table'; import {MatTableModule} from '@angular/material/table';
import {MatSortModule} from '@angular/material/sort'; import {MatSortModule} from '@angular/material/sort';
import {MatListModule} from '@angular/material/list';
import {MatProgressSpinnerModule} from '@angular/material/progress-spinner'; import {MatProgressSpinnerModule} from '@angular/material/progress-spinner';
import {MatTabsModule} from '@angular/material/tabs'; import {MatTabsModule} from '@angular/material/tabs';
import {MatFormFieldModule} from '@angular/material/form-field'; import {MatFormFieldModule} from '@angular/material/form-field';
@ -36,7 +37,7 @@ import { NgxMatDatetimePickerModule, NgxMatTimepickerModule, NgxMatNativeDateMod
MatInputModule, MatProgressSpinnerModule, MatInputModule, MatProgressSpinnerModule,
MatTabsModule, MatFormFieldModule, MatTabsModule, MatFormFieldModule,
NgxMatDatetimePickerModule, MatDatepickerModule, NgxMatDatetimePickerModule, MatDatepickerModule,
NgxMatNativeDateModule, MatNativeDateModule, NgxMatNativeDateModule, MatNativeDateModule, MatListModule,
MatCheckboxModule, MatSelectModule, MatStepperModule, MatCheckboxModule, MatSelectModule, MatStepperModule,
MatChipsModule, MatSnackBarModule, MatSlideToggleModule MatChipsModule, MatSnackBarModule, MatSlideToggleModule
], ],
@ -47,7 +48,7 @@ import { NgxMatDatetimePickerModule, NgxMatTimepickerModule, NgxMatNativeDateMod
MatInputModule, MatProgressSpinnerModule, MatInputModule, MatProgressSpinnerModule,
MatTabsModule, MatFormFieldModule, MatTabsModule, MatFormFieldModule,
NgxMatDatetimePickerModule, MatDatepickerModule, NgxMatDatetimePickerModule, MatDatepickerModule,
NgxMatNativeDateModule, MatNativeDateModule, NgxMatNativeDateModule, MatNativeDateModule, MatListModule,
MatCheckboxModule, MatSelectModule, MatStepperModule, MatCheckboxModule, MatSelectModule, MatStepperModule,
MatChipsModule, MatSnackBarModule, MatSlideToggleModule MatChipsModule, MatSnackBarModule, MatSlideToggleModule
] ]

@ -0,0 +1,14 @@
<button (click)="$event.stopPropagation();" mat-icon-button [matMenuTriggerFor]="menu" aria-label="filter-button avec menu">
<mat-icon>filter_alt</mat-icon>
</button>
<mat-menu #menu="matMenu">
<mat-list role="list" (click)="$event.stopPropagation();">
<mat-list-item role="listitem">
<mat-checkbox (change)="selectedAllChecked($event.checked)" [checked]="checkedAll"> Tout sélectionner</mat-checkbox>
</mat-list-item>
<mat-list-item *ngFor="let data of dataSource" role="listitem">
<mat-checkbox *ngIf="isPropertyValueName" (change)="selectedChecked($event.checked,data)" [checked]="exists(data)"> {{data[propertyValueName]}}</mat-checkbox>
<mat-checkbox *ngIf="!isPropertyValueName" (change)="selectedChecked($event.checked,data)" [checked]="exists(data)"> {{data}}</mat-checkbox>
</mat-list-item>
</mat-list>
</mat-menu>

@ -0,0 +1,120 @@
import { Component, Input, Output, EventEmitter, OnInit, OnChanges } from "@angular/core";
import { SelectedElement } from "@shared/filter/selected-element";
@Component({
selector: "checkbox-filter",
templateUrl: "./checkbox-filter.html",
styleUrls: ["./checkbox-filter.css"]
})
export class CheckboxFilterComponent<T> implements OnInit, OnChanges {
/**
* Liste des éléments sélectionnés
*/
elementsSelected: Array<T> = [];
/**
* Booléen permettant de determiner si la propriété "propertyValueName" contient une valeur ou non
*/
isPropertyValueName: boolean;
/**
* Coche toutes les cases à cocher
*/
@Input() checkedAll: boolean;
/**
* Source de données
*/
@Input() dataSource : Array<T>;
/**
* Nom de la propriété contenant la valeur à afficher
*/
@Input() propertyValueName: string;
/**
* Booléen permettant de savoir si toutes les cases sont cochées ou non
*/
@Output() isSelectedAllEvent = new EventEmitter<boolean>();
/**
* Elément sélectionné
*/
@Output() isSelectedEvent = new EventEmitter<SelectedElement<T>>();
constructor() {}
ngOnInit() {
this.isPropertyValueName = !this.propertyValueName ? false : true;
}
ngOnChanges() {
if (this.dataSource.length > 0) {
this.checkElementhasProperty();
this.selectedAllChecked(this.checkedAll);
}
}
/**
* Vérifie que tous les éléments de source de données possède la propriété "propertyValueName" lorsque cette dernière
* contient une valeur.
*/
checkElementhasProperty() {
if(this.propertyValueName && !this.dataSource.every(e => e.hasOwnProperty(this.propertyValueName)))
throw new Error("Il existe au moins un élément dans la source de données qui ne possède pas la propriété '"+this.propertyValueName+"'.");
}
/**
* Détermine si l'élément est présent dans la liste des éléments sélectionnés
* @param element
*/
exists(element) {
return this.elementsSelected.indexOf(element) > -1;
};
/**
* Met à jour la liste des éléments sélectionnés et met à jour l'EventEmitter "isSelectedAllEvent"
* @param event case "Tout Sélectionner" cochée ou décochée
*/
selectedAllChecked(event) {
this.isSelectedAllEvent.emit(event);
this.checkedAll = event;
this.elementsSelected = [];
if(event)
this.dataSource.map(data => this.elementsSelected.push(data));
}
/**
* Met à jour la liste des éléments sélectionnés et met à jour l'EventEmitter "isSelectedEvent"
* @param event case cochée ou décochée par l'utilisateur
* @param data Valeur de la case cochée ou décochée
*/
selectedChecked = (event: any, data: T) => {
this.isSelectedEvent.emit({isSelected: event, selectedElement: data});
// si la checkbox a été cochée
if(event)
this.elementsSelected.push(data);
else
this.elementsSelected = this.elementsSelected.filter(element => element != data);
// coche la case "Tout sélectionner" si tous les éléments sont cochés
this.elementsSelected.length == this.dataSource.length ? this.checkedAll = true: this.checkedAll = false;
}
/**
* Une fois la page fermée, il est nécessaire de se désabonner des Oberservable afin d'éviter les fuites mémoires.
*/
ngOnDestroy() {
}
}

@ -0,0 +1,28 @@
import { NgModule } from "@angular/core";
import { CommonModule } from '@angular/common';
import { FormsModule, ReactiveFormsModule} from '@angular/forms';
import { RouterModule } from '@angular/router';
import { MaterialModule } from "../angular-material/angular-material.module";
import { CheckboxFilterComponent } from "@shared/filter/checkbox-filter/checkbox-filter";
import { SelectFilterComponent } from "@shared/filter/select-filter/select-filter";
@NgModule({
declarations: [
CheckboxFilterComponent,
SelectFilterComponent
],
imports: [
MaterialModule,
CommonModule,
FormsModule,
ReactiveFormsModule,
RouterModule
],
exports: [
CheckboxFilterComponent,
SelectFilterComponent
]
})
export class FilterModule {}

@ -0,0 +1,4 @@
mat-select .mat-checkbox-layout,
mat-select .mat-checkbox-label {
width:100% !important;
}

@ -0,0 +1,11 @@
<mat-form-field appearance="fill">
<mat-label>{{label}}</mat-label>
<mat-select [(value)]="elementsSelected" multiple>
<mat-checkbox class="mat-option" (change)="selectedAllChecked($event.checked)" [checked]="checkedAll"> Tout sélectionner</mat-checkbox>
<ng-container *ngFor="let data of dataSource">
<mat-option #matOption *ngIf="isPropertyValueName" (click)="selectedChecked(matOption.selected, data)" [value]="data">{{data[propertyValueName]}}</mat-option>
<mat-option #matOption *ngIf="!isPropertyValueName" (click)="selectedChecked(matOption.selected, data)" [value]="data">{{data}}</mat-option>
</ng-container>
</mat-select>
</mat-form-field>

@ -0,0 +1,116 @@
import { Component, Input, Output, EventEmitter, OnInit, OnChanges } from "@angular/core";
import { SelectedElement } from "@shared/filter/selected-element";
@Component({
selector: "select-filter",
templateUrl: "./select-filter.html",
styleUrls: ["./select-filter.css"]
})
export class SelectFilterComponent<T> implements OnInit, OnChanges {
/**
* Liste des éléments sélectionnés
*/
elementsSelected: Array<T> = [];
/**
* Booléen permettant de determiner si la propriété "propertyValueName" contient une valeur ou non
*/
isPropertyValueName: boolean;
/**
* Libellé qui est affiché dans la liste déroulante lorsqu'aucune valeur n'est sélectionnée
*/
@Input() label: string;
/**
* Cocher toutes les cases à cocher
*/
@Input() checkedAll: boolean;
/**
* Source de données
*/
@Input() dataSource : Array<T>;
/**
* Nom de la propriété contenant la valeur à afficher
*/
@Input() propertyValueName: string;
/**
* Booléen permettant de savoir si toutes les cases sont cochées ou non
*/
@Output() isSelectedAllEvent = new EventEmitter<boolean>();
/**
* Elément sélectionné
*/
@Output() isSelectedEvent = new EventEmitter<SelectedElement<T>>();
constructor() {}
ngOnInit() {
this.isPropertyValueName = !this.propertyValueName ? false : true;
}
ngOnChanges() {
if (this.dataSource.length > 0) {
this.checkElementhasProperty();
this.selectedAllChecked(this.checkedAll);
}
}
/**
* Vérifie que tous les éléments de source de données possède la propriété "propertyValueName" lorsque cette dernière
* contient une valeur.
*/
checkElementhasProperty() {
if(this.propertyValueName && !this.dataSource.every(e => e.hasOwnProperty(this.propertyValueName)))
throw new Error("Il existe au moins un élément dans la source de données qui ne possède pas la propriété '"+this.propertyValueName+"'.");
}
/**
* Met à jour la liste des éléments sélectionnés et met à jour l'EventEmitter "isSelectedAllEvent"
* @param event case "Tout Sélectionner" cochée ou décochée
*/
selectedAllChecked(event) {
this.isSelectedAllEvent.emit(event);
this.checkedAll = event;
this.elementsSelected = [];
if(event)
this.dataSource.map(data => this.elementsSelected.push(data));
}
/**
* Met à jour la liste des éléments sélectionnés et met à jour l'EventEmitter "isSelectedEvent"
* @param isChecked case cochée ou décochée par l'utilisateur
* @param data Valeur de la case cochée ou décochée
*/
selectedChecked = (isChecked: boolean, data: T) => {
this.isSelectedEvent.emit({isSelected: isChecked, selectedElement: data});
if(isChecked) {
var index = this.elementsSelected.findIndex(element => element == data);
if (index === -1)
this.elementsSelected.push(data);
}
else {
this.elementsSelected = this.elementsSelected.filter(element => element != data);
}
// coche la case "Tout sélectionner" si tous les éléments sont cochés
this.elementsSelected.length == this.dataSource.length ? this.checkedAll = true: this.checkedAll = false;
}
/**
* Une fois la page fermée, il est nécessaire de se désabonner des Oberservable afin d'éviter les fuites mémoires.
*/
ngOnDestroy() {
}
}

@ -0,0 +1,11 @@
export interface SelectedElement<T> {
/**
* Détermine si l'élément est sélectionné ou non
*/
isSelected: boolean;
/**
* Element sélectionné
*/
selectedElement: T;
}

@ -0,0 +1,84 @@
<ng-container *ngIf="chargement">
<mat-spinner></mat-spinner>
</ng-container>
<ng-container *ngIf="!chargement">
<!-- Barre de recherche -->
<mat-form-field>
<mat-label>Rechercher une formation</mat-label>
<input matInput type="text" [(ngModel)]="search" (keyup)="setSearch()">
<button mat-button *ngIf="search" matSuffix mat-icon-button aria-label="Clear" (click)="resetSearch()">
<mat-icon>close</mat-icon>
</button>
</mat-form-field>
<!--Checkboxes des statuts de formation-->
<select-filter
[dataSource]="statutsFormation"
[checkedAll]="false"
label="Statuts"
propertyValueName="libelle"
(isSelectedAllEvent)="updateAllCheckbox($event)"
(isSelectedEvent)="updateCheckbox($event.isSelected, $event.selectedElement)">
</select-filter>
<!-- Affichage de la liste des formations -->
<mat-table matSort [dataSource]="dataSource" (matSortChange)="triTableau($event)" matSortActive="{{this.tri}}" matSortDirection="asc" >
<ng-container matColumnDef="intitule">
<mat-header-cell *matHeaderCellDef mat-sort-header disableClear>Intitulé</mat-header-cell>
<mat-cell *matCellDef="let row">{{ row.intitule }}</mat-cell>
</ng-container>
<ng-container matColumnDef=participants>
<mat-header-cell *matHeaderCellDef mat-sort-header disableClear>Nb participants</mat-header-cell>
<mat-cell *matCellDef="let row">{{ row.nbParticipations }}</mat-cell>
</ng-container>
<ng-container matColumnDef="date">
<mat-header-cell *matHeaderCellDef mat-sort-header disableClear>Date prévisionnelle</mat-header-cell>
<mat-cell *matCellDef="let row">{{ row.dateDebut | date:'dd/MM/yyyy à hh:mm' }}</mat-cell>
</ng-container>
<ng-container matColumnDef="origine">
<mat-header-cell *matHeaderCellDef mat-sort-header disableClear>Origine</mat-header-cell>
<mat-cell *matCellDef="let row">{{row.origine.libelle}}</mat-cell>
</ng-container>
<ng-container matColumnDef="statut">
<!--Checkboxes des statuts de formation-->
<mat-header-cell *matHeaderCellDef mat-sort-header disableClear>Statut
<checkbox-filter
[dataSource]="statutsFormation"
[checkedAll]="false"
propertyValueName="libelle"
(isSelectedAllEvent)="updateAllCheckbox($event)"
(isSelectedEvent)="updateCheckbox($event.isSelected, $event.selectedElement)">
</checkbox-filter>
</mat-header-cell>
<mat-cell *matCellDef="let row">{{row.statut.libelle}}</mat-cell>
</ng-container>
<ng-container matColumnDef="certification">
<mat-header-cell *matHeaderCellDef mat-sort-header disableClear>Certifiée</mat-header-cell>
<mat-cell *matCellDef="let row">{{estCertifiee(row.estCertifiee)}}</mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<!-- Lien vers le détail d'une formation-->
<mat-row *matRowDef="let row; columns: displayedColumns;" [routerLink]="['/formations',row.id]"></mat-row>
</mat-table>
<!--[length]="taille"-->
<mat-paginator #paginator
[length] = "taille"
[pageIndex]="numPage-1"
[pageSize]="parPage"
[pageSizeOptions]="pageOption"
(page)="updatePageInfo($event)"
>
</mat-paginator>
</ng-container>

@ -0,0 +1,256 @@
import { Component, Input, OnInit } from "@angular/core";
import { Subscription } from 'rxjs';
import {MatTableDataSource} from '@angular/material/table';
import { CollaborateurDTO, FormationDetailsDTO, StatutFormationDTO } from '@shared/api-swagger/model/models'
import { FormationsService } from "@shared/api-swagger/api/api";
import { cles } from "@shared/utils/cles";
@Component({
selector: "formations-table",
templateUrl: "./formations.table.html",
styleUrls: ["./formations.table.css"]
})
export class FormationsTableComponent implements OnInit {
/**
* Ordre de tri à envoyer au serveur (true : croissant, false : décroissantà).
*/
asc : boolean = true;
/**
* Numéro de la page à afficher dans le tableau.
*/
numPage: number = 1;
/**
* Nombre d'élément du tableau à affiche en une page.
*/
parPage: number = 15;
/**
* Observable pour faire des requêtes sur le service formation.
*/
private formationsDisponiblesSubscription : Subscription;
/**
* Observable pour faire des requêtes sur le service formation.
*/
private formationsDisponiblesCountSubscription : Subscription;
/**
* C'est dans cet objet que seront stockés les formations à afficher dans le Mat Table côté template.
*/
dataSource : MatTableDataSource<FormationDetailsDTO>;
/**
* contenu de la recherche pour trouver une formation.
*/
search: string = "";
/**
* Permet de savoir sur quelle attribut d'un FormationDetailsDTO doit être trié le tableau.
*/
tri: string = "intitule";
/**
* Id agence collaborateur connecté
*/
idAgence: number;
/**
* Liste des statuts de formation
*/
statutsFormation: Array<StatutFormationDTO> = [];
/**
* Liste des id statuts à afficher
*/
private idStatuts: Array<number> = [];
/**
* Spécifie si les checkbox des statuts de formation sont toutes cochées ou non.
*/
isStatutsSelectedAll: boolean = false;
/**
* Nombre total d'élément du tableau
*/
taille: number = 0;
/**
* Options pour choisir le nombre de page à affiche
*/
pageOption = [ 5, 15, 20, 30, 50];
/**
* Spécifie si la liste des formations est en cours de chargement dans le tableau.
*/
chargement: boolean = true;
/**
* Indique si la recherche par statut de formation est activée ou non
*/
@Input() rechercherParStatutFormation: boolean = false;
/**
* Liste des colonnes du tableau à afficher.
*/
@Input() displayedColumns : string[];
private collaborateurConnecte : CollaborateurDTO;
constructor(private formationsService: FormationsService) {}
ngOnInit() {
this.getStatutsFormation();
this.setCollaborateurConnecte();
}
/**
* Mettre à jour les informations à afficher dans la tableau.
* Devra se faire à l'ouverture de la page, au changement de page ou du nombre d'éléments à afficher, au moment d'un tri ou encore lors de l'utilisation de la barre de recherche.
*/
updateDataSource() {
this.updateFormations();
}
/**
* Récupère les statuts de formation
*/
getStatutsFormation()
{
this.formationsService.getStatutsFormation().subscribe(
statuts => this.statutsFormation = statuts,
err => console.log(err)
);
}
/**
* Mettre à jour les informations à afficher dans la tableau.
* Devra se faire à l'ouverture de la page, au changement de page ou du nombre d'éléments à afficher, au moment d'un tri ou encore lors de l'utilisation de la barre de recherche.
*/
updateFormations() {
this.formationsDisponiblesSubscription = this.formationsService.getFormations(this.idAgence,this.idStatuts,this.asc, this.numPage, this.parPage, this.search, this.tri).subscribe(
formations => this.dataSource = new MatTableDataSource(formations),
err => console.log(err)
)
this.formationsDisponiblesCountSubscription = this.formationsService.getFormationsCount(this.idAgence,this.idStatuts,this.asc, this.numPage, this.parPage, this.search, this.tri).subscribe(
count => this.taille=count,
err => console.log(err)
);
}
estCertifiee(certifiee: boolean) {
if(certifiee)
return "Oui";
return "Non";
}
setCollaborateurConnecte()
{
if(sessionStorage.getItem(cles.sessionKeyConnectee) == undefined){
setTimeout( () => this.setCollaborateurConnecte(), 1000);
}
else {
this.collaborateurConnecte = JSON.parse(sessionStorage.getItem(cles.sessionKeyConnectee));
this.idAgence = this.collaborateurConnecte.businessUnit.agence.id;
this.updateDataSource();
this.chargement = false;
}
}
/**
* Mettre à jour le nomre d'élément à afficher par page et le numéro de la page
* @param event évènement de la pagination
*/
updatePageInfo(event){
this.parPage = event.pageSize;
this.numPage = event.pageIndex+1;
this.updateDataSource();
}
/**
* Remettre au début la liste lors d'une recherche via la barre de recherche
*/
setSearch() {
this.numPage = 1;
this.updateDataSource();
}
/**
* Vider la barre de recherche et remettre le tableau à la première page
*/
resetSearch() {
this.search = "";
this.setSearch();
}
/**
* Trier le tableau en fonction de l'évènement de la colonne
* @param e évènement du tri
*/
triTableau(e) {
this.tri = e.active;
switch(e.direction) {
case "asc":
this.asc = true;
break;
case "desc":
this.asc = false;
break;
}
this.updateDataSource();
}
/**
* Mettre à jour toutes les checkox
* @param event case cochée ou décochée
*/
updateAllCheckbox(event) {
this.idStatuts = [];
// si la checkbox a été cochée
if(event)
this.statutsFormation.map(statut => this.idStatuts.push(statut.id));
else
this.idStatuts = [];
this.numPage = 1;
this.updateDataSource();
}
/**
* Mettre à jour la liste des checkox
* @param event case cochée ou décochée
* @param statut statut concerné par la checkbox cochée ou décochée
*/
updateCheckbox(event, statut) {
// si la checkbox a été cochée
if(event) {
this.idStatuts.push(statut.id)
}
else{
this.idStatuts = this.idStatuts.filter(id => id != statut.id);
}
this.numPage = 1;
this.updateDataSource();
}
/**
* Une fois la page fermée, il est nécessaire de se désabonner des Oberservable afin d'éviter les fuites mémoires.
*/
ngOnDestroy() {
if(this.formationsDisponiblesSubscription != undefined) {
this.formationsDisponiblesSubscription.unsubscribe();
}
if(this.formationsDisponiblesCountSubscription != undefined) {
this.formationsDisponiblesCountSubscription.unsubscribe();
}
}
}

@ -1,20 +1,32 @@
import { NgModule } from "@angular/core"; import { NgModule } from "@angular/core";
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms'; import { FormsModule } from '@angular/forms';
import { RouterModule } from '@angular/router';
import { MaterialModule } from "../angular-material/angular-material.module"; import { MaterialModule } from "../angular-material/angular-material.module";
import { CollaborateursTableComponent } from "@shared/mat-tables/collaborateurs-table/collaborateurs.table"; import { CollaborateursTableComponent } from "@shared/mat-tables/collaborateurs-table/collaborateurs.table";
import { EngagementTableComponent } from "@shared/mat-tables/engagements-table/engagements-table" import { EngagementTableComponent } from "@shared/mat-tables/engagements-table/engagements-table"
import { FormationsTableComponent } from "@shared/mat-tables/formations-table/formations.table";
import { FilterModule } from "@shared/filter/filter.module";
@NgModule({ @NgModule({
declarations: [ declarations: [
CollaborateursTableComponent, EngagementTableComponent CollaborateursTableComponent,
EngagementTableComponent,
FormationsTableComponent
], ],
imports: [ imports: [
MaterialModule, MaterialModule,
FilterModule,
CommonModule, CommonModule,
FormsModule FormsModule,
RouterModule
], ],
exports: [CollaborateursTableComponent, EngagementTableComponent] exports: [
CollaborateursTableComponent,
EngagementTableComponent,
FormationsTableComponent
]
}) })
export class MatTablesModule {} export class MatTablesModule {}

@ -18,7 +18,7 @@ const keycloakConfig: AuthConfig = {
// is a sign that the auth server is not configured with SPAs in mind // is a sign that the auth server is not configured with SPAs in mind
// and it might not enforce further best practices vital for security // and it might not enforce further best practices vital for security
// such applications. // such applications.
//dummyClientSecret: 'f27746f4-e603-441e-a256-3ddd5b19ba54', //dummyClientSecret: 'b261c083-d8ba-4a7c-918e-9d13393f33bd',
dummyClientSecret: '201a3d53-7cd5-4613-bcb6-f2e98c1ba2ec', dummyClientSecret: '201a3d53-7cd5-4613-bcb6-f2e98c1ba2ec',
// To configure your solution for code flow + PKCE you have to set the responseType to code // To configure your solution for code flow + PKCE you have to set the responseType to code

Loading…
Cancel
Save