From 4b9e833756cc51a27a43f7f444e5c5185915bbf2 Mon Sep 17 00:00:00 2001 From: matthieuaudemard Date: Fri, 19 Nov 2021 10:13:45 +0100 Subject: [PATCH] =?UTF-8?q?RI-155:=20[admin/company]=20recharge=20le=20tab?= =?UTF-8?q?leau=20lors=20de=20la=20cr=C3=A9ation=20d'une=20nouvelle=20entr?= =?UTF-8?q?eprise=20(#186)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * modification du composant companies-table.component pour qu'il extends base-with-pagination.component * ajout d'un toaster lors de l'ajout ou maj d'une entreprise * ajout du company-context-service.service --- .../companies-form.component.ts | 19 ++++-- .../companies-table.component.html | 2 +- .../companies-table.component.ts | 57 +++++++++------- .../jobs-table/jobs-table.component.ts | 66 +++++++++---------- .../comment-list/comment-list.component.ts | 2 +- .../post-list/post-list.component.ts | 2 +- .../jobs-list/jobs-list.component.ts | 33 +++++----- .../base-with-pagination.component.spec.ts | 4 +- .../base-with-pagination.component.ts | 18 ++++- .../job-filter/job-filter.component.ts | 12 +++- .../base-context-service.service.spec.ts | 16 +++++ .../services/base-context-service.service.ts | 18 +++++ .../company-context-service.service.spec.ts | 16 +++++ .../company-context-service.service.ts | 13 ++++ .../src/app/shared/shared.module.ts | 2 +- 15 files changed, 192 insertions(+), 88 deletions(-) rename frontend-implicaction/src/app/shared/components/{base-with-pagination-component => base-with-pagination}/base-with-pagination.component.spec.ts (83%) rename frontend-implicaction/src/app/shared/components/{base-with-pagination-component => base-with-pagination}/base-with-pagination.component.ts (55%) create mode 100644 frontend-implicaction/src/app/shared/services/base-context-service.service.spec.ts create mode 100644 frontend-implicaction/src/app/shared/services/base-context-service.service.ts create mode 100644 frontend-implicaction/src/app/shared/services/company-context-service.service.spec.ts create mode 100644 frontend-implicaction/src/app/shared/services/company-context-service.service.ts diff --git a/frontend-implicaction/src/app/admin/companies/components/companies-form/companies-form.component.ts b/frontend-implicaction/src/app/admin/companies/components/companies-form/companies-form.component.ts index e2e6e657..b9989a1e 100644 --- a/frontend-implicaction/src/app/admin/companies/components/companies-form/companies-form.component.ts +++ b/frontend-implicaction/src/app/admin/companies/components/companies-form/companies-form.component.ts @@ -8,6 +8,7 @@ import {Pageable} from '../../../../shared/models/pageable'; import {Constants} from '../../../../config/constants'; import {Company} from '../../../../shared/models/company'; import {CompanyService} from '../../../../company/services/company.service'; +import {CompanyContextServiceService} from '../../../../shared/services/company-context-service.service'; @Component({ selector: 'app-companies-form', @@ -28,6 +29,7 @@ export class CompaniesFormComponent extends SidebarContentComponent implements O private companyService: CompanyService, private toasterService: ToasterService, private sidebarService: SidebarService, + private companyContextService: CompanyContextServiceService ) { super(); } @@ -53,13 +55,22 @@ export class CompaniesFormComponent extends SidebarContentComponent implements O company$ = this.companyService.createCompany(company); } company$.subscribe( - (companyUpdate) => { + companySave => { if (this.isUpdate) { - this.updateFields(companyUpdate); + this.updateFields(companySave); + } else { + this.companyContextService.notify(companySave); } }, - () => this.toasterService.error('Oops', `Une erreur est survenue lors de ${this.isUpdate ? 'la mise à jour' : `l'ajout`} de votre entreprise.`), - () => this.sidebarService.close() + () => { + const actionType = this.isUpdate ? 'la mise à jour' : `l'ajout`; + this.toasterService.error('Oops', `Une erreur est survenue lors de ${actionType} de votre entreprise.`); + }, + () => { + const actionType = this.isUpdate ? 'mise à jour' : `ajoutée`; + this.toasterService.success('Succès', `L'entreprise ${company.name} a été ${actionType} avec succès.`); + this.sidebarService.close(); + } ); } diff --git a/frontend-implicaction/src/app/admin/companies/components/companies-table/companies-table.component.html b/frontend-implicaction/src/app/admin/companies/components/companies-table/companies-table.component.html index e1a490b9..f0ab1948 100644 --- a/frontend-implicaction/src/app/admin/companies/components/companies-table/companies-table.component.html +++ b/frontend-implicaction/src/app/admin/companies/components/companies-table/companies-table.component.html @@ -11,7 +11,7 @@

Toutes les entreprises

implements OnInit { readonly ROWS_PER_PAGE_OPTIONS = Constants.ROWS_PER_PAGE_OPTIONS; loading = true; // indique si les données sont en chargement @@ -26,28 +27,19 @@ export class CompaniesTableComponent { private companyService: CompanyService, private toastService: ToasterService, private sidebarService: SidebarService, + private companyContextService: CompanyContextServiceService ) { + super(); } - loadCompanies(event: LazyLoadEvent): void { - this.loading = true; - const page = event.first / event.rows; - - this.companyService - .getAll({page, rows: event.rows}) - .pipe( - take(1), - finalize(() => this.loading = false) - ) - .subscribe( - data => { - this.pageable.totalPages = data.totalPages; - this.pageable.rows = data.size; - this.pageable.totalElements = data.totalElements; - this.pageable.content = data.content; - }, - () => this.toastService.error('Oops', 'Une erreur est survenue lors de la récupération des données'), - ); + ngOnInit(): void { + this.companyContextService + .observe$ + .subscribe(company => { + if (company) { + this.paginate(); + } + }); } onEditCompany(company: Company): void { @@ -68,5 +60,26 @@ export class CompaniesTableComponent { width: 650 }); } + + protected innerPaginate(): void { + // FIXME: il faut forcer les paramètres de tri car ils restent définis avec les valeurs du dernier composant visité + this.pageable.sortBy = 'id'; + this.pageable.sortOrder = 'ASC'; + this.companyService + .getAll(this.pageable) + .pipe( + take(1), + finalize(() => this.loading = false) + ) + .subscribe( + data => { + this.pageable.totalPages = data.totalPages; + this.pageable.rows = data.size; + this.pageable.totalElements = data.totalElements; + this.pageable.content = data.content; + }, + () => this.toastService.error('Oops', 'Une erreur est survenue lors de la récupération des données'), + ); + } } diff --git a/frontend-implicaction/src/app/admin/jobs/components/jobs-table/jobs-table.component.ts b/frontend-implicaction/src/app/admin/jobs/components/jobs-table/jobs-table.component.ts index 6f20d87b..4717c191 100644 --- a/frontend-implicaction/src/app/admin/jobs/components/jobs-table/jobs-table.component.ts +++ b/frontend-implicaction/src/app/admin/jobs/components/jobs-table/jobs-table.component.ts @@ -42,10 +42,6 @@ export class JobsTableComponent implements OnInit { } ngOnInit(): void { - this.pageable.sortOrder = JobSortEnum.DATE_DESC.sortDirection; - this.pageable.sortBy = JobSortEnum.DATE_DESC.sortBy; - this.selectedOrderCode = JobSortEnum.DATE_DESC.code; - this.filterService .observeFilter() .subscribe(criteria => { @@ -88,6 +84,37 @@ export class JobsTableComponent implements OnInit { this.filterService.setFilter(this.criteria); } + loadJobs(event: LazyLoadEvent): void { + this.loading = true; + const page = event.first / event.rows; + + this.jobService + .getAllByCriteria({page, rows: event.rows}, this.criteria) + .pipe( + take(1), + finalize(() => this.loading = false) + ) + .subscribe( + data => { + this.pageable.totalPages = data.totalPages; + this.pageable.rows = data.size; + this.pageable.totalElements = data.totalElements; + this.pageable.content = data.content; + }, + () => this.toastService.error('Oops', 'Une erreur est survenue lors de la récupération des données'), + ); + } + + editJob(job: JobPosting): void { + this.sidebarService + .open({ + title: `Editer une nouvelle offre d'emploi`, + input: {job}, + component: JobPostingFormComponent, + width: 650 + }); + } + private async getFilterFromQueryParams(): Promise { // TODO: voir si y'a un moyen plus élégant avec typeof const filterKeys = ['search', 'contractType']; @@ -121,35 +148,4 @@ export class JobsTableComponent implements OnInit { sortOrder: this.pageable.sortOrder }; } - - loadJobs(event: LazyLoadEvent): void { - this.loading = true; - const page = event.first / event.rows; - - this.jobService - .getAllByCriteria({page, rows: event.rows}, this.criteria) - .pipe( - take(1), - finalize(() => this.loading = false) - ) - .subscribe( - data => { - this.pageable.totalPages = data.totalPages; - this.pageable.rows = data.size; - this.pageable.totalElements = data.totalElements; - this.pageable.content = data.content; - }, - () => this.toastService.error('Oops', 'Une erreur est survenue lors de la récupération des données'), - ); - } - - editJob(job: JobPosting): void { - this.sidebarService - .open({ - title: `Editer une nouvelle offre d'emploi`, - input: {job}, - component: JobPostingFormComponent, - width: 650 - }); - } } diff --git a/frontend-implicaction/src/app/discussion/components/comment-list/comment-list.component.ts b/frontend-implicaction/src/app/discussion/components/comment-list/comment-list.component.ts index bb3f85f0..760582b5 100644 --- a/frontend-implicaction/src/app/discussion/components/comment-list/comment-list.component.ts +++ b/frontend-implicaction/src/app/discussion/components/comment-list/comment-list.component.ts @@ -7,7 +7,7 @@ import {Subscription} from 'rxjs'; import {ActivatedRoute} from '@angular/router'; import {finalize} from 'rxjs/operators'; import {Comment} from '../../model/comment'; -import {BaseWithPaginationComponent} from '../../../shared/components/base-with-pagination-component/base-with-pagination.component'; +import {BaseWithPaginationComponent} from '../../../shared/components/base-with-pagination/base-with-pagination.component'; import {CommentPayload} from '../../model/comment-payload'; import {FormControl, FormGroup, Validators} from '@angular/forms'; import {CommentService} from '../../services/comment.service'; diff --git a/frontend-implicaction/src/app/discussion/components/post-list/post-list.component.ts b/frontend-implicaction/src/app/discussion/components/post-list/post-list.component.ts index 90faee98..a46794f7 100644 --- a/frontend-implicaction/src/app/discussion/components/post-list/post-list.component.ts +++ b/frontend-implicaction/src/app/discussion/components/post-list/post-list.component.ts @@ -1,6 +1,6 @@ import {Component, OnInit} from '@angular/core'; import {Post} from '../../model/post'; -import {BaseWithPaginationComponent} from '../../../shared/components/base-with-pagination-component/base-with-pagination.component'; +import {BaseWithPaginationComponent} from '../../../shared/components/base-with-pagination/base-with-pagination.component'; import {PostService} from '../../services/post.service'; import {ToasterService} from '../../../core/services/toaster.service'; import {finalize} from 'rxjs/operators'; diff --git a/frontend-implicaction/src/app/job/components/jobs-list/jobs-list.component.ts b/frontend-implicaction/src/app/job/components/jobs-list/jobs-list.component.ts index f946a790..93e33a7e 100644 --- a/frontend-implicaction/src/app/job/components/jobs-list/jobs-list.component.ts +++ b/frontend-implicaction/src/app/job/components/jobs-list/jobs-list.component.ts @@ -8,13 +8,15 @@ import {JobCriteriaFilter} from '../../models/job-criteria-filter'; import {JobFilterContextService} from '../../services/job-filter-context.service'; import {ActivatedRoute} from '@angular/router'; import {SortDirectionEnum} from '../../../shared/enums/sort-direction.enum'; +import {BaseWithPaginationComponent} from '../../../shared/components/base-with-pagination/base-with-pagination.component'; +import {JobPosting} from '../../../shared/models/job-posting'; @Component({ selector: 'app-jobs-list', templateUrl: './jobs-list.component.html', styleUrls: ['./jobs-list.component.scss'] }) -export class JobsListComponent implements OnInit { +export class JobsListComponent extends BaseWithPaginationComponent implements OnInit { readonly ROWS_PER_PAGE_OPTIONS = Constants.ROWS_PER_PAGE_OPTIONS; @@ -33,6 +35,7 @@ export class JobsListComponent implements OnInit { private filterService: JobFilterContextService, private route: ActivatedRoute ) { + super(); } ngOnInit(): void { @@ -53,11 +56,18 @@ export class JobsListComponent implements OnInit { .then(() => this.filterService.setFilter(this.criteria)); } - paginate({page, first, rows} = this.pageable): void { - this.isLoading = true; - this.pageable.page = page; - this.pageable.first = first; - this.pageable.rows = rows; + onSortChange({value}): void { + const selectedOrderField = JobSortEnum.from(value); + this.pageable.sortBy = selectedOrderField.sortBy; + this.pageable.sortOrder = selectedOrderField.sortDirection; + this.filterService.setFilter(this.criteria); // on relance la recherche en updatant le filtre + } + + onSearchChange(): void { + this.filterService.setFilter(this.criteria); + } + + protected innerPaginate(): void { this.jobsService .getAllByCriteria(this.pageable, this.criteria) .pipe(finalize(() => this.isLoading = false)) @@ -71,17 +81,6 @@ export class JobsListComponent implements OnInit { ); } - onSortChange({value}): void { - const selectedOrderField = JobSortEnum.from(value); - this.pageable.sortBy = selectedOrderField.sortBy; - this.pageable.sortOrder = selectedOrderField.sortDirection; - this.filterService.setFilter(this.criteria); // on relance la recherche en updatant le filtre - } - - onSearchChange(): void { - this.filterService.setFilter(this.criteria); - } - private async getFilterFromQueryParams(): Promise { // TODO: voir si y'a un moyen plus élégant avec typeof const filterKeys = ['search', 'contractType']; diff --git a/frontend-implicaction/src/app/shared/components/base-with-pagination-component/base-with-pagination.component.spec.ts b/frontend-implicaction/src/app/shared/components/base-with-pagination/base-with-pagination.component.spec.ts similarity index 83% rename from frontend-implicaction/src/app/shared/components/base-with-pagination-component/base-with-pagination.component.spec.ts rename to frontend-implicaction/src/app/shared/components/base-with-pagination/base-with-pagination.component.spec.ts index 4669e9bb..dc2c8019 100644 --- a/frontend-implicaction/src/app/shared/components/base-with-pagination-component/base-with-pagination.component.spec.ts +++ b/frontend-implicaction/src/app/shared/components/base-with-pagination/base-with-pagination.component.spec.ts @@ -3,8 +3,8 @@ import {ComponentFixture, TestBed} from '@angular/core/testing'; import {BaseWithPaginationComponent} from './base-with-pagination.component'; describe('AbstractPaginationComponentComponent', () => { - let component: BaseWithPaginationComponent; - let fixture: ComponentFixture; + let component: BaseWithPaginationComponent; + let fixture: ComponentFixture>; beforeEach(async () => { await TestBed.configureTestingModule({ diff --git a/frontend-implicaction/src/app/shared/components/base-with-pagination-component/base-with-pagination.component.ts b/frontend-implicaction/src/app/shared/components/base-with-pagination/base-with-pagination.component.ts similarity index 55% rename from frontend-implicaction/src/app/shared/components/base-with-pagination-component/base-with-pagination.component.ts rename to frontend-implicaction/src/app/shared/components/base-with-pagination/base-with-pagination.component.ts index 0d75132f..80a7ae3f 100644 --- a/frontend-implicaction/src/app/shared/components/base-with-pagination-component/base-with-pagination.component.ts +++ b/frontend-implicaction/src/app/shared/components/base-with-pagination/base-with-pagination.component.ts @@ -11,15 +11,31 @@ export class BaseWithPaginationComponent { // Pagination pageable: Pageable = Constants.PAGEABLE_DEFAULT; + /** + * Lance la pagination en invoquant la méthode {@link innerPaginate} + * @param page numéro de la page + * @param first indice du 1er élément à récupérer + * @param rows nombre d'éléments par page + */ paginate({page, first, rows} = this.pageable): void { this.isLoading = true; - this.pageable.page = page; + if (page) { + this.pageable.page = page; + } else if (rows > 0) { + this.pageable.page = first / rows; + } else { + this.pageable.page = 0; + } this.pageable.first = first; this.pageable.rows = rows; this.innerPaginate(); } + /** + * méthode à implémenter qui lance les appels au service voulu + * @protected + */ protected innerPaginate(): void { } } diff --git a/frontend-implicaction/src/app/shared/components/job-filter/job-filter.component.ts b/frontend-implicaction/src/app/shared/components/job-filter/job-filter.component.ts index 4849d866..0b385318 100644 --- a/frontend-implicaction/src/app/shared/components/job-filter/job-filter.component.ts +++ b/frontend-implicaction/src/app/shared/components/job-filter/job-filter.component.ts @@ -1,23 +1,25 @@ -import {Component, OnInit} from '@angular/core'; +import {Component, OnDestroy, OnInit} from '@angular/core'; import {ContractTypeCode, ContractTypeEnum} from '../../../job/models/contract-type-enum'; import {JobCriteriaFilter} from '../../../job/models/job-criteria-filter'; import {JobFilterContextService} from '../../../job/services/job-filter-context.service'; +import {Subscription} from 'rxjs'; @Component({ selector: 'app-job-filter', templateUrl: './job-filter.component.html', styleUrls: ['./job-filter.component.scss'] }) -export class JobFilterComponent implements OnInit { +export class JobFilterComponent implements OnInit, OnDestroy { contractTypes = ContractTypeEnum.all(); criteria: JobCriteriaFilter = {}; + subscription: Subscription; constructor(private filterContextService: JobFilterContextService) { } ngOnInit(): void { - this.filterContextService + this.subscription = this.filterContextService .observeFilter() .subscribe(criteria => this.criteria = criteria); } @@ -26,4 +28,8 @@ export class JobFilterComponent implements OnInit { this.criteria.contractType = code; this.filterContextService.setFilter(this.criteria); } + + ngOnDestroy(): void { + this.subscription?.unsubscribe(); + } } diff --git a/frontend-implicaction/src/app/shared/services/base-context-service.service.spec.ts b/frontend-implicaction/src/app/shared/services/base-context-service.service.spec.ts new file mode 100644 index 00000000..5aa500e0 --- /dev/null +++ b/frontend-implicaction/src/app/shared/services/base-context-service.service.spec.ts @@ -0,0 +1,16 @@ +import {TestBed} from '@angular/core/testing'; +import {BaseContextServiceService} from './base-context-service.service'; + + +describe('BaseEntityContextServiceService', () => { + let service: BaseContextServiceService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(BaseContextServiceService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/frontend-implicaction/src/app/shared/services/base-context-service.service.ts b/frontend-implicaction/src/app/shared/services/base-context-service.service.ts new file mode 100644 index 00000000..165c3c46 --- /dev/null +++ b/frontend-implicaction/src/app/shared/services/base-context-service.service.ts @@ -0,0 +1,18 @@ +import {Injectable} from '@angular/core'; +import {BehaviorSubject, Observable} from 'rxjs'; + +@Injectable({ + providedIn: 'root' +}) +export class BaseContextServiceService { + + protected behaviorSubject = new BehaviorSubject({} as T); + + public get observe$(): Observable { + return this.behaviorSubject.asObservable(); + } + + public notify(obj: T): void { + this.behaviorSubject.next(obj); + } +} diff --git a/frontend-implicaction/src/app/shared/services/company-context-service.service.spec.ts b/frontend-implicaction/src/app/shared/services/company-context-service.service.spec.ts new file mode 100644 index 00000000..6e9f9081 --- /dev/null +++ b/frontend-implicaction/src/app/shared/services/company-context-service.service.spec.ts @@ -0,0 +1,16 @@ +import {TestBed} from '@angular/core/testing'; + +import {CompanyContextServiceService} from './company-context-service.service'; + +describe('CompanyContextServiceService', () => { + let service: CompanyContextServiceService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(CompanyContextServiceService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/frontend-implicaction/src/app/shared/services/company-context-service.service.ts b/frontend-implicaction/src/app/shared/services/company-context-service.service.ts new file mode 100644 index 00000000..d022b74b --- /dev/null +++ b/frontend-implicaction/src/app/shared/services/company-context-service.service.ts @@ -0,0 +1,13 @@ +import {Injectable} from '@angular/core'; +import {BaseContextServiceService} from './base-context-service.service'; +import {Company} from '../models/company'; + +@Injectable({ + providedIn: 'root' +}) +export class CompanyContextServiceService extends BaseContextServiceService { + + constructor() { + super(); + } +} diff --git a/frontend-implicaction/src/app/shared/shared.module.ts b/frontend-implicaction/src/app/shared/shared.module.ts index 539da972..735662fb 100644 --- a/frontend-implicaction/src/app/shared/shared.module.ts +++ b/frontend-implicaction/src/app/shared/shared.module.ts @@ -11,7 +11,7 @@ import {BrPipe} from './pipes/br.pipe'; import {ContractTypeComponent} from './components/contract-type/contract-type.component'; import {DateTimelapseComponent} from './components/date-timelapse/date-timelapse.component'; import {JobFilterComponent} from './components/job-filter/job-filter.component'; -import {BaseWithPaginationComponent} from './components/base-with-pagination-component/base-with-pagination.component'; +import {BaseWithPaginationComponent} from './components/base-with-pagination/base-with-pagination.component'; import {AvatarModule} from 'primeng/avatar';