Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RI-192: [admin/front] permet d'archiver plusieurs offres depuis le listing d'offres #203

Merged
merged 9 commits into from
Dec 11, 2021
Merged
102 changes: 101 additions & 1 deletion frontend-implicaction/src/app/admin/jobs/admin-jobs.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,107 @@ <h5 class="panel-title">Toutes les offres d'emplois</h5>
title="Ajouter une offre"
>
</i-feather>
<button
(click)="toggleArchiveSelectedJobs()"
class="btn"
data-bs-placement="top"
data-bs-toggle="tooltip"
title="Archiver"
[disabled]="!isArchiveEnabled"
type="button"
>
<i
[ngClass]="isArchive ? 'fa-box border-info text-info':'fa-box-open border-warning text-warning' "
mathusha-sdv marked this conversation as resolved.
Show resolved Hide resolved
class="fas border rounded-3 px-2 py-1"
>
</i>
</button>
</div>
</div>
<app-jobs-table></app-jobs-table>
<p-table
(onLazyLoad)="paginate($event)"
[(selection)]="selectedJobs"
[lazy]="true"
[loading]="loading"
[paginator]="true"
[rowsPerPageOptions]="[10, 25, 50]"
[rows]="pageable.rows"
[showCurrentPageReport]="true"
[totalRecords]="pageable.totalElements"
[value]="pageable.content"
(onRowSelect)="onRowSelected()"
(onRowUnselect)="onRowSelected()"
currentPageReportTemplate="{first} à {last} sur {totalRecords} entrées"
>
<ng-template pTemplate="header">
<tr>
<th class="text-center col-1">
<p-tableHeaderCheckbox></p-tableHeaderCheckbox>
</th>
<th class="text-wrap text-uppercase col-3 col-sm-2 col-lg-3" scope="col">Nom</th>
<th class="text-wrap text-uppercase col-1 col-sm-1 col-lg-1 px-2" scope="col">Type</th>
<th class="text-wrap text-uppercase col-3 col-sm-2 col-lg-3 px-2" scope="col">Localisation</th>
<th class="text-wrap text-uppercase col-6 col-sm-4 col-lg-6 px-2" scope="col">Description</th>
<th class="text-wrap text-uppercase text-center col-4 col-sm-2 col-lg-4 col-xl-3 px-2" scope="col">Actions</th>
</tr>
</ng-template>
<ng-template let-job pTemplate="body">
<tr>
<td class="text-center col-1">
<p-tableCheckbox
[value]="job"
>
</p-tableCheckbox>
</td>
<td class="overflow-ellipsis text-wrap col-4 col-sm-3 col-lg-2">{{job.title}}</td>
<td class="text-wrap col-1 col-sm-1 col-lg-1 px-2">{{job.contractType?.label}}</td>
<td class="overflow-ellipsis text-lg-wrap col-4 col-sm-3 col-lg-2 px-2">{{job.location}}</td>
<td class="overflow-ellipsis col-4 col-sm-3 col-md-2 col-lg-3 px-2">{{job.description}}</td>
<td class="col-4 col-sm-2 col-lg-4 col-xl-3 px-2 text-center">
<ul class="fa-ul d-flex flex-column flex-lg-row justify-content-center list-unstyled list-inline mb-0">
<li class="fa-li list-inline-item m-0 me-lg-2">
<button
(click)="editJob(job)"
class="btn"
data-bs-placement="top"
data-bs-toggle="tooltip"
title="Editer"
type="button"
>
<i class="fas fa-pen border border-primary text-primary rounded-3 px-2 py-1"></i>
</button>
</li>
<li class="fa-li list-inline-item m-0 me-lg-2">
<button
class="btn"
data-bs-placement="top"
data-bs-toggle="tooltip"
title="Supprimer"
type="button"
>
<i class="fas fa-trash border border-danger text-danger rounded-3 px-2 py-1"></i>
</button>
</li>
<li class="fa-li list-inline-item m-0 me-lg-2">
<button
class="btn"
(click)="toggleArchiveJob(job)"
data-bs-placement="top"
data-bs-toggle="tooltip"
title="Archiver"
type="button"
>
<i
[ngClass]="job.archive ? 'fa-box-open border-warning text-warning' : 'fa-box border-info text-info'"
class="fas border rounded-3 px-2 py-1"
>
</i>
</button>
</li>
</ul>
</td>
</tr>
</ng-template>
</p-table>

</div>
13 changes: 13 additions & 0 deletions frontend-implicaction/src/app/admin/jobs/admin-jobs.component.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
::ng-deep {
.p-datatable .p-datatable-tbody > tr > td {
border-width: 0 !important;
}

.p-datatable-thead {

th {
background-color: transparent !important;
border: 0 !important;
}
}
}
121 changes: 119 additions & 2 deletions frontend-implicaction/src/app/admin/jobs/admin-jobs.component.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,126 @@
import {Component} from '@angular/core';
import {Component, OnInit} from '@angular/core';
import {SidebarService} from '../../shared/services/sidebar.service';
import {JobPostingFormComponent} from './components/job-posting-form/job-posting-form.component';
import {BaseWithPaginationComponent} from '../../shared/components/base-with-pagination/base-with-pagination.component';
import {JobPosting} from '../../shared/models/job-posting';
import {JobCriteriaFilter} from '../../job/models/job-criteria-filter';
import {Constants} from '../../config/constants';
import {Pageable} from '../../shared/models/pageable';
import {JobSortEnum} from '../../job/enums/job-sort.enum';
import {SortDirectionEnum} from '../../shared/enums/sort-direction.enum';
import {JobService} from '../../job/services/job.service';
import {ToasterService} from '../../core/services/toaster.service';
import {JobFilterContextService} from '../../job/services/job-filter-context.service';
import {ActivatedRoute} from '@angular/router';
import {finalize, take} from 'rxjs/operators';

@Component({
selector: 'app-job',
templateUrl: './admin-jobs.component.html',
styleUrls: ['./admin-jobs.component.scss']
})
export class AdminJobsComponent {
export class AdminJobsComponent extends BaseWithPaginationComponent<JobPosting, JobCriteriaFilter> implements OnInit {
readonly ROWS_PER_PAGE_OPTIONS = Constants.ROWS_PER_PAGE_OPTIONS;
loading = true; // indique si les données sont en chargement
isArchiveEnabled: boolean;
isArchive: boolean;
selectedJobs: JobPosting[] = [];

// Pagination
pageable: Pageable = Constants.PAGEABLE_DEFAULT;
orderByEnums = JobSortEnum.all();
selectedOrder = JobSortEnum.DATE_DESC;
criteria: JobCriteriaFilter;
selectedOrderCode: string;
sortDirection = SortDirectionEnum;

constructor(
private jobService: JobService,
private toastService: ToasterService,
private sidebarService: SidebarService,
private filterService: JobFilterContextService,
protected route: ActivatedRoute
) {
super(route);
}

ngOnInit(): void {
this.pageable.sortOrder = JobSortEnum.DATE_DESC.sortDirection;
this.pageable.sortBy = JobSortEnum.DATE_DESC.sortBy;
this.selectedOrderCode = JobSortEnum.DATE_DESC.code;

this.filterService
.observe()
.subscribe(criteria => {
this.criteria = criteria;
const objectParam = this.buildQueryParams();
this.filterService.updateRouteQueryParams(objectParam);
this.paginate();
});

this.getFilterFromQueryParams(['search', 'contractType']).then(() => this.filterService.criteria = this.criteria);
}

onSortChange({value}): void {
const selectedOrderField = JobSortEnum.from(value);
this.pageable.sortBy = selectedOrderField.sortBy;
this.pageable.sortOrder = selectedOrderField.sortDirection;
this.filterService.criteria = this.criteria; // on relance la recherche en updatant le filtre
}

onSearchChange(): void {
this.filterService.criteria = this.criteria;
}

protected innerPaginate(): void {
this.jobService
.getAllByCriteria(this.pageable, 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
});
}

toggleArchiveJob(job: JobPosting): void {
this.jobService
.archiveJob(job.id)
.subscribe(
() => this.paginate(),
() => this.toastService.error('Oops', 'Une erreur est survenue'),
() => this.toastService.success('Succès', job.archive ? 'Offre désarchivée' : `Offre archivée`)
);
}

toggleArchiveSelectedJobs(): void {
const jobsId = this.selectedJobs.map(job => job.id);
this.jobService
.toggleArchiveJobs(jobsId)
.subscribe(
() => this.paginate(),
() => this.toastService.error('Oops', 'Une erreur est survenue'),
() => this.toastService.success('Succès', 'Opération effectuée'),
);
this.selectedJobs = [];
this.isArchiveEnabled = false;
}

onAddJob(): void {
Expand All @@ -23,4 +132,12 @@ export class AdminJobsComponent {
});
}

onRowSelected(): void {
// on vérifie que tous les éléments sélectionné sont tous archivés ou désarchivés
this.isArchiveEnabled = this.selectedJobs.every(job => job.archive === this.selectedJobs[0].archive);
// on recherche si le bouton toggleArchive doit archiver ou désarchiver
this.isArchive = this.selectedJobs.length > 0 ? this.selectedJobs[0].archive : false;

}

}
2 changes: 0 additions & 2 deletions frontend-implicaction/src/app/admin/jobs/admin-jobs.module.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import {JobsTableComponent} from './components/jobs-table/jobs-table.component';
import {AdminJobsComponent} from './admin-jobs.component';
import {AdminJobsRoutingModule} from './admin-jobs-routing.module';
import {TableModule} from 'primeng/table';
Expand All @@ -15,7 +14,6 @@ import {CheckboxModule} from 'primeng/checkbox';
@NgModule({
declarations: [
AdminJobsComponent,
JobsTableComponent,
JobPostingFormComponent
],
imports: [
Expand Down

This file was deleted.

This file was deleted.

Loading