Resultat du cours n°8
This commit is contained in:
24
package-lock.json
generated
24
package-lock.json
generated
@@ -1679,6 +1679,30 @@
|
||||
"@jridgewell/sourcemap-codec": "^1.4.10"
|
||||
}
|
||||
},
|
||||
"@ngrx/effects": {
|
||||
"version": "13.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@ngrx/effects/-/effects-13.1.0.tgz",
|
||||
"integrity": "sha512-b0kaC1yly1WawtQils3Bxy2FhE9OwlQD/bptVd3s+bskdZ+iw9VlAMH9Spk2mfX+MyOEOk2FyrWlrOePtkw+7Q==",
|
||||
"requires": {
|
||||
"tslib": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"@ngrx/store": {
|
||||
"version": "13.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@ngrx/store/-/store-13.1.0.tgz",
|
||||
"integrity": "sha512-2Phsd/CC5FcoS2VgC+Fo5VgfAUK3m7bjWTc8d6+h3UcoQpS3xyPnybGYifa/JYN1CFYmqypVDRWSMAgML2NU/A==",
|
||||
"requires": {
|
||||
"tslib": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"@ngrx/store-devtools": {
|
||||
"version": "13.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@ngrx/store-devtools/-/store-devtools-13.1.0.tgz",
|
||||
"integrity": "sha512-HAF2q1qk7n0Q3rkHncdXIokGXbPFKWwmfhGFS9pnq63FScgPgHjNXSlPmwgycb+LqDvDR4C8f1HSbPhOb6I29w==",
|
||||
"requires": {
|
||||
"tslib": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"@ngtools/webpack": {
|
||||
"version": "13.2.6",
|
||||
"resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-13.2.6.tgz",
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
"@angular/platform-browser": "~13.2.0",
|
||||
"@angular/platform-browser-dynamic": "~13.2.0",
|
||||
"@angular/router": "~13.2.0",
|
||||
"@ngrx/effects": "^13.1.0",
|
||||
"@ngrx/store": "^13.1.0",
|
||||
"@ngrx/store-devtools": "^13.1.0",
|
||||
"bootstrap": "^5.1.3",
|
||||
"concurrently": "^7.0.0",
|
||||
"font-awesome": "^4.7.0",
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { EmployeesComponent } from './components/employees/employees.component';
|
||||
|
||||
const routes: Routes = [];
|
||||
const routes: Routes = [{
|
||||
path:"employees", component:EmployeesComponent
|
||||
}];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forRoot(routes)],
|
||||
exports: [RouterModule]
|
||||
imports: [RouterModule.forRoot(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class AppRoutingModule { }
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<!-- Links -->
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#">Link 1</a>
|
||||
<a class="nav-link" routerLink="/employees">Employees</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#">Link 2</a>
|
||||
|
||||
@@ -1,19 +1,30 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
import { StoreModule } from '@ngrx/store';
|
||||
import { EffectsModule } from '@ngrx/effects';
|
||||
import { StoreDevtoolsModule } from '@ngrx/store-devtools';
|
||||
|
||||
import { AppRoutingModule } from './app-routing.module';
|
||||
import { AppComponent } from './app.component';
|
||||
import { EmployeesComponent } from './components/employees/employees.component';
|
||||
import { NavBarComponent } from './components/employees/nav-bar/nav-bar.component';
|
||||
import { employeesReducer } from './ngrx/employees.reducer';
|
||||
import { EmployeesEffects } from './ngrx/employees.effects';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
AppComponent
|
||||
AppComponent,
|
||||
EmployeesComponent,
|
||||
NavBarComponent
|
||||
],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
AppRoutingModule,
|
||||
HttpClientModule
|
||||
|
||||
HttpClientModule,
|
||||
StoreModule.forRoot({catalogState:employeesReducer}),
|
||||
EffectsModule.forRoot([EmployeesEffects]),
|
||||
StoreDevtoolsModule.instrument()
|
||||
],
|
||||
providers: [],
|
||||
bootstrap: [AppComponent]
|
||||
|
||||
27
src/app/components/employees/employees.component.html
Normal file
27
src/app/components/employees/employees.component.html
Normal file
@@ -0,0 +1,27 @@
|
||||
<div class="p-4">
|
||||
<app-nav-bar></app-nav-bar>
|
||||
<ng-container *ngIf="employeesState$ | async as state" [ngSwitch]="state.dataState">
|
||||
<ng-container *ngSwitchCase="EmployeesStateEnum.INITIAL">
|
||||
<div class="p-2">Initial State</div>
|
||||
</ng-container>
|
||||
<ng-container *ngSwitchCase="EmployeesStateEnum.LOADING">
|
||||
<div class="p-2">Loading ...</div>
|
||||
</ng-container>
|
||||
<ng-container *ngSwitchCase="EmployeesStateEnum.ERROR">
|
||||
<div class="p-2">{{state.errorMessage | json}}</div>
|
||||
</ng-container>
|
||||
<ng-container *ngSwitchCase="EmployeesStateEnum.LOADED" class="p-4">
|
||||
<table class="table">
|
||||
<tr>
|
||||
<th>ID</th><th>Nom</th><th>Prénom</th><th>Role</th>
|
||||
</tr>
|
||||
<tr *ngFor="let employee of state.employees">
|
||||
<td>{{employee.id}}</td>
|
||||
<td>{{employee.nom}}</td>
|
||||
<td>{{employee.prenom}}</td>
|
||||
<td>{{employee.role}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
</div>
|
||||
25
src/app/components/employees/employees.component.spec.ts
Normal file
25
src/app/components/employees/employees.component.spec.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { EmployeesComponent } from './employees.component';
|
||||
|
||||
describe('EmployeesComponent', () => {
|
||||
let component: EmployeesComponent;
|
||||
let fixture: ComponentFixture<EmployeesComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ EmployeesComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(EmployeesComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
24
src/app/components/employees/employees.component.ts
Normal file
24
src/app/components/employees/employees.component.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { EmployeesState, EmployeesStateEnum } from '../../ngrx/employees.reducer';
|
||||
|
||||
@Component({
|
||||
selector: 'app-employees',
|
||||
templateUrl: './employees.component.html',
|
||||
styleUrls: ['./employees.component.css']
|
||||
})
|
||||
export class EmployeesComponent implements OnInit {
|
||||
employeesState$:Observable<EmployeesState>|null=null;
|
||||
readonly EmployeesStateEnum=EmployeesStateEnum;
|
||||
|
||||
constructor(private store:Store<any>) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
this.employeesState$=this.store.pipe(
|
||||
map((state) => state.catalogState)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<ul class="nav nav-pills">
|
||||
<li>
|
||||
<button class="btn btn-outline-info" (click)="onGetAllEmployees()">All</button>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { NavBarComponent } from './nav-bar.component';
|
||||
|
||||
describe('NavBarComponent', () => {
|
||||
let component: NavBarComponent;
|
||||
let fixture: ComponentFixture<NavBarComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ NavBarComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(NavBarComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
20
src/app/components/employees/nav-bar/nav-bar.component.ts
Normal file
20
src/app/components/employees/nav-bar/nav-bar.component.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { GetAllEmployeesAction } from '../../../ngrx/employees.actions';
|
||||
|
||||
@Component({
|
||||
selector: 'app-nav-bar',
|
||||
templateUrl: './nav-bar.component.html',
|
||||
styleUrls: ['./nav-bar.component.css']
|
||||
})
|
||||
export class NavBarComponent implements OnInit {
|
||||
|
||||
constructor(private store:Store<any>) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
onGetAllEmployees() {
|
||||
this.store.dispatch(new GetAllEmployeesAction({}))
|
||||
}
|
||||
}
|
||||
31
src/app/ngrx/employees.actions.ts
Normal file
31
src/app/ngrx/employees.actions.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import { Action } from '@ngrx/store';
|
||||
import { Employee } from '../model/employee.model';
|
||||
|
||||
export enum EmployeesActionsTypes {
|
||||
GET_ALL_EMPLOYEES="[Employees] Get All Employees",
|
||||
GET_ALL_EMPLOYEES_SUCCESS="[Employees] Get All Employees Success",
|
||||
GET_ALL_EMPLOYEES_ERROR="[Employees] Get All Employees Error",
|
||||
}
|
||||
|
||||
export class GetAllEmployeesAction implements Action {
|
||||
type: EmployeesActionsTypes=EmployeesActionsTypes.GET_ALL_EMPLOYEES;
|
||||
constructor(public payload:any) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class GetAllEmployeesActionSuccess implements Action {
|
||||
type: EmployeesActionsTypes=EmployeesActionsTypes.GET_ALL_EMPLOYEES_SUCCESS;
|
||||
constructor(public payload:Employee[]) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class GetAllEmployeesActionError implements Action {
|
||||
type: EmployeesActionsTypes=EmployeesActionsTypes.GET_ALL_EMPLOYEES_ERROR;
|
||||
constructor(public payload:string) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export type EmployeesActions=GetAllEmployeesAction | GetAllEmployeesActionSuccess | GetAllEmployeesActionError;
|
||||
26
src/app/ngrx/employees.effects.ts
Normal file
26
src/app/ngrx/employees.effects.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { EmployeesService } from '../services/employees.service';
|
||||
import { createEffect, Actions, ofType } from '@ngrx/effects';
|
||||
import { Observable, of, EMPTY } from 'rxjs';
|
||||
import { Action } from '@ngrx/store';
|
||||
import { EmployeesActionsTypes } from './employees.actions';
|
||||
import { mergeMap, map, catchError } from 'rxjs/operators';
|
||||
import { GetAllEmployeesActionSuccess, GetAllEmployeesActionError } from './employees.actions';
|
||||
|
||||
@Injectable()
|
||||
export class EmployeesEffects {
|
||||
getAllEmployeesEffect$:Observable<Action> = createEffect(() => this.actions$.pipe(
|
||||
ofType(EmployeesActionsTypes.GET_ALL_EMPLOYEES),
|
||||
mergeMap((action) => {
|
||||
return this.employeesService.getAllEmployees().pipe(
|
||||
map(employees => new GetAllEmployeesActionSuccess(employees)),
|
||||
catchError((err) => of(new GetAllEmployeesActionError(err.message)))
|
||||
)
|
||||
})
|
||||
));
|
||||
|
||||
constructor(
|
||||
private employeesService:EmployeesService,
|
||||
private actions$:Actions
|
||||
) {}
|
||||
}
|
||||
35
src/app/ngrx/employees.reducer.ts
Normal file
35
src/app/ngrx/employees.reducer.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { Employee } from '../model/employee.model';
|
||||
import { EmployeesActions, EmployeesActionsTypes } from './employees.actions';
|
||||
import { Action } from '@ngrx/store';
|
||||
|
||||
export enum EmployeesStateEnum {
|
||||
LOADING="Loading",
|
||||
LOADED="Loaded",
|
||||
ERROR="Error",
|
||||
INITIAL="Initial"
|
||||
}
|
||||
|
||||
export interface EmployeesState {
|
||||
employees:Employee[],
|
||||
errorMessage:string,
|
||||
dataState:EmployeesStateEnum
|
||||
}
|
||||
|
||||
const initState:EmployeesState = {
|
||||
employees:[],
|
||||
errorMessage:"",
|
||||
dataState:EmployeesStateEnum.INITIAL
|
||||
}
|
||||
|
||||
export function employeesReducer(state:EmployeesState=initState, action:Action):EmployeesState {
|
||||
switch(action.type) {
|
||||
case EmployeesActionsTypes.GET_ALL_EMPLOYEES:
|
||||
return {...state, dataState:EmployeesStateEnum.LOADING};
|
||||
case EmployeesActionsTypes.GET_ALL_EMPLOYEES_SUCCESS:
|
||||
return {...state, dataState:EmployeesStateEnum.LOADED, employees:(<EmployeesActions>action).payload};
|
||||
case EmployeesActionsTypes.GET_ALL_EMPLOYEES_ERROR:
|
||||
return {...state, dataState:EmployeesStateEnum.ERROR, errorMessage:(<EmployeesActions>action).payload};
|
||||
default:
|
||||
return {...state}
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@ export class EmployeesService {
|
||||
constructor(private http:HttpClient) {}
|
||||
|
||||
getAllEmployees():Observable<Employee[]> {
|
||||
let host=environment.host;
|
||||
let host=Math.random()>0.2?environment.host:environment.unreachableHost;
|
||||
return this.http.get<Employee[]>(host+"/employees");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user