From 195cb2d552e3b495e6c9501fb5c0042ff82b5058 Mon Sep 17 00:00:00 2001 From: nekorpeche Date: Wed, 8 Dec 2021 23:24:58 +0100 Subject: [PATCH 01/12] =?UTF-8?q?RI-203:=20permet=20de=20valider=20une=20o?= =?UTF-8?q?ffre=20et=20un=20groupe=20*=20la=20validation=20des=20offres=20?= =?UTF-8?q?fonctionne=20*=20probl=C3=A8me=20quand=20j'utilise=20deux=20pag?= =?UTF-8?q?inate=20dans=20une=20m=C3=AAme=20page,=20le=20paginate.content?= =?UTF-8?q?=20est=20le=20m=C3=AAme=20pour=20les=20deux.=20Ils=20r=C3=A9cup?= =?UTF-8?q?=C3=A8rent=20d'abord=20l'utilisateur=20puis=20les=20offres=20du?= =?UTF-8?q?=20coup=20=C3=A7a=20ne=20s'affiche=20pas=20correctment?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../adapter/JobPostingAdapter.java | 2 ++ .../controller/JobPostingController.java | 17 ++++++++++++++ .../dto/JobPostingDto.java | 1 + .../refonteimplicaction/model/JobPosting.java | 3 +++ .../repository/JobPostingRepository.java | 4 +++- .../service/JobPostingService.java | 13 +++++++++++ .../refonteimplicaction/utils/ApiUrls.java | 2 ++ .../adapter/JobApplicationAdapterTest.java | 4 ++-- .../service/JobApplicationServiceTest.java | 4 ++-- .../admin/dashboard/dashboard.component.html | 7 ++++++ .../app/admin/dashboard/dashboard.module.ts | 4 +++- .../src/app/admin/jobs/admin-jobs.module.ts | 9 ++++++-- .../pending-user-table.component.html | 4 ++-- .../pending-user-table.component.ts | 22 +++++++++++-------- .../core/services/api-endpoints.service.ts | 8 +++++++ .../src/app/job/services/job.service.ts | 8 +++++++ .../src/app/shared/models/job-posting.ts | 1 + .../src/app/shared/models/uris.ts | 2 ++ 18 files changed, 96 insertions(+), 19 deletions(-) diff --git a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/adapter/JobPostingAdapter.java b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/adapter/JobPostingAdapter.java index f6a3e1a1..62a275e5 100644 --- a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/adapter/JobPostingAdapter.java +++ b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/adapter/JobPostingAdapter.java @@ -30,6 +30,7 @@ public JobPostingDto toDto(JobPosting model) { .createdAt(model.getCreatedAt()) .archive(model.isArchive()) .businessSector(model.getBusinessSector()) + .active(model.isActive()) .build(); } @@ -50,6 +51,7 @@ public JobPosting toModel(JobPostingDto dto) { .businessSector(dto.getBusinessSector()) .createdAt(dto.getCreatedAt()) .archive(dto.isArchive()) + .active(dto.isActive()) .build(); } } diff --git a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/controller/JobPostingController.java b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/controller/JobPostingController.java index 9d9c522c..8f63c2a7 100644 --- a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/controller/JobPostingController.java +++ b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/controller/JobPostingController.java @@ -2,6 +2,7 @@ import com.dynonuggets.refonteimplicaction.dto.JobPostingDto; import com.dynonuggets.refonteimplicaction.exception.ImplicactionException; +import com.dynonuggets.refonteimplicaction.model.JobPosting; import com.dynonuggets.refonteimplicaction.service.JobPostingService; import lombok.AllArgsConstructor; import org.apache.commons.lang3.StringUtils; @@ -76,4 +77,20 @@ public ResponseEntity> toggleArchiveJobs(@RequestBody final List updated = jobPostingService.toggleArchiveAll(jobsId); return ResponseEntity.ok(updated); } + + @GetMapping(GET_PENDING_JOB_URI) + public ResponseEntity> getAllPendingJobs( + @RequestParam(value = "page", defaultValue = "0") int page, + @RequestParam(value = "rows", defaultValue = "10") int rows + ) { + Pageable pageable = PageRequest.of(page, rows); + Page pendingJobs = jobPostingService.getAllPendingActivationJobs(pageable); + return ResponseEntity.ok(pendingJobs); + } + + @PatchMapping(ACTIVATE_JOB_URI) + public ResponseEntity activateJob(@RequestBody final JobPosting job) { + jobPostingService.activateJob(job); + return ResponseEntity.ok().build(); + } } diff --git a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/dto/JobPostingDto.java b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/dto/JobPostingDto.java index 3c2270e2..cbb196d7 100644 --- a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/dto/JobPostingDto.java +++ b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/dto/JobPostingDto.java @@ -28,5 +28,6 @@ public class JobPostingDto { private Instant createdAt; private boolean archive; private boolean apply; + private boolean active; } diff --git a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/model/JobPosting.java b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/model/JobPosting.java index 648d6181..6165f201 100644 --- a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/model/JobPosting.java +++ b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/model/JobPosting.java @@ -54,4 +54,7 @@ public class JobPosting { @Column(columnDefinition = "boolean default false") private boolean archive; + + @Column(name = "active") + private boolean active; } diff --git a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/repository/JobPostingRepository.java b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/repository/JobPostingRepository.java index 9c3b5c03..d5225a8f 100644 --- a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/repository/JobPostingRepository.java +++ b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/repository/JobPostingRepository.java @@ -1,10 +1,12 @@ package com.dynonuggets.refonteimplicaction.repository; import com.dynonuggets.refonteimplicaction.model.JobPosting; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @Repository public interface JobPostingRepository extends JpaRepository, JobPostingRepositoryCustom { - + Page findAllByActiveIsFalse(Pageable pageable); } diff --git a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/service/JobPostingService.java b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/service/JobPostingService.java index 9d4e75b0..1a0d975d 100644 --- a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/service/JobPostingService.java +++ b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/service/JobPostingService.java @@ -103,4 +103,17 @@ public List toggleArchiveAll(List jobsId) { .map(jobPostingAdapter::toDto) .collect(Collectors.toList()); } + + @Transactional + public Page getAllPendingActivationJobs(Pageable pageable) { + return jobPostingRepository.findAllByActiveIsFalse(pageable) + .map(jobPostingAdapter::toDto); + } + + @Transactional + public void activateJob(JobPosting job) { + job.setActive(true); + jobPostingRepository.save(job); + } + } diff --git a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/utils/ApiUrls.java b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/utils/ApiUrls.java index 722b7aee..7e6aa0a5 100644 --- a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/utils/ApiUrls.java +++ b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/utils/ApiUrls.java @@ -19,6 +19,8 @@ public class ApiUrls { public static final String DELETE_JOB_URI = "/{jobId}"; public static final String ARCHIVE_JOB_URI = "/{jobId}/archive"; public static final String ARCHIVE_JOBS_URI = "/archive"; + public static final String GET_PENDING_JOB_URI = "/pending"; + public static final String ACTIVATE_JOB_URI = "/activate"; // POSTS public static final String POSTS_BASE_URI = "/api/posts"; diff --git a/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/adapter/JobApplicationAdapterTest.java b/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/adapter/JobApplicationAdapterTest.java index 00d4b7e2..87e2c8db 100644 --- a/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/adapter/JobApplicationAdapterTest.java +++ b/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/adapter/JobApplicationAdapterTest.java @@ -19,7 +19,7 @@ class JobApplicationAdapterTest extends ControllerIntegrationTestBase { void given_company_should_return_dto() { // given Company company = new Company(1234L, "World Company", "http://logo.com", "La World Company est une multinationale imaginaire basée aux États-Unis", "http://word-company.com"); - JobPosting job = new JobPosting(34L, company, "Job de folie", "blablabla", "blablabla", "Paris", "240k", null, CDD, BusinessSectorEnum.ASSURANCE, Instant.now(), false); + JobPosting job = new JobPosting(34L, company, "Job de folie", "blablabla", "blablabla", "Paris", "240k", null, CDD, BusinessSectorEnum.ASSURANCE, Instant.now(), false, true); User user = User.builder().id(87L).build(); JobApplication model = new JobApplication(123L, job, user, PENDING, Instant.now(), false); @@ -40,7 +40,7 @@ void given_company_should_return_dto() { void given_no_company_should_return_dto() { // given Company company = null; - JobPosting job = new JobPosting(34L, company, "Job de folie", "blablabla", "blablabla", "Paris", "240k", null, CDD, BusinessSectorEnum.ASSURANCE, Instant.now(), false); + JobPosting job = new JobPosting(34L, company, "Job de folie", "blablabla", "blablabla", "Paris", "240k", null, CDD, BusinessSectorEnum.ASSURANCE, Instant.now(), false, true); User user = User.builder().id(87L).build(); JobApplication model = new JobApplication(123L, job, user, PENDING, Instant.now(), false); diff --git a/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/service/JobApplicationServiceTest.java b/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/service/JobApplicationServiceTest.java index 11e14cd3..7beeeeaa 100644 --- a/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/service/JobApplicationServiceTest.java +++ b/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/service/JobApplicationServiceTest.java @@ -58,7 +58,7 @@ class JobApplicationServiceTest extends ControllerIntegrationTestBase { void should_create_apply() { // given JobApplicationRequest request = new JobApplicationRequest(123L, PENDING, null); - JobPosting job = new JobPosting(123L, Company.builder().id(23L).build(), "Mon super job", "Il est trop cool", "Blablabla", "Paris", "140k", null, CDI, BusinessSectorEnum.ASSURANCE, Instant.now(), false); + JobPosting job = new JobPosting(123L, Company.builder().id(23L).build(), "Mon super job", "Il est trop cool", "Blablabla", "Paris", "140k", null, CDI, BusinessSectorEnum.ASSURANCE, Instant.now(), false, true); final User currentUser = User.builder().id(45L).build(); JobApplication jobApplication = new JobApplication(67L, job, currentUser, request.getStatus(), Instant.now(), false); JobApplicationDto expectedDto = new JobApplicationDto(jobApplication.getId(), jobApplication.getJob().getId(), jobApplication.getJob().getTitle(), jobApplication.getJob().getCompany().getName(), jobApplication.getJob().getCompany().getLogo(), jobApplication.getStatus().name(), "Paris (75)", CDI, false); @@ -103,7 +103,7 @@ void should_throw_exception_when_creating_with_already_applied_job() { JobApplicationRequest request = new JobApplicationRequest(jobId, PENDING, null); IllegalArgumentException expectedException = new IllegalArgumentException(String.format(APPLY_ALREADY_EXISTS_FOR_JOB, jobId)); final JobApplication apply = JobApplication.builder().id(123L).build(); - JobPosting job = new JobPosting(123L, Company.builder().id(23L).build(), "Mon super job", "Il est trop cool", "Blablabla", "Paris", "140k", null, CDI, BusinessSectorEnum.ASSURANCE, Instant.now(), false); + JobPosting job = new JobPosting(123L, Company.builder().id(23L).build(), "Mon super job", "Il est trop cool", "Blablabla", "Paris", "140k", null, CDI, BusinessSectorEnum.ASSURANCE, Instant.now(), false, true); User currentUser = User.builder().id(123L).build(); given(jobRepository.findById(anyLong())).willReturn(Optional.of(job)); given(authService.getCurrentUser()).willReturn(currentUser); diff --git a/frontend-implicaction/src/app/admin/dashboard/dashboard.component.html b/frontend-implicaction/src/app/admin/dashboard/dashboard.component.html index 6e3e3c41..10316610 100644 --- a/frontend-implicaction/src/app/admin/dashboard/dashboard.component.html +++ b/frontend-implicaction/src/app/admin/dashboard/dashboard.component.html @@ -7,3 +7,10 @@
Nouveaux utilisateurs
+
+
+
Nouvelles offres
+
+ +
+ diff --git a/frontend-implicaction/src/app/admin/dashboard/dashboard.module.ts b/frontend-implicaction/src/app/admin/dashboard/dashboard.module.ts index 57868219..e885791f 100644 --- a/frontend-implicaction/src/app/admin/dashboard/dashboard.module.ts +++ b/frontend-implicaction/src/app/admin/dashboard/dashboard.module.ts @@ -4,6 +4,7 @@ import {DashboardComponent} from './dashboard.component'; import {AdminOverviewComponent} from './components/admin-overview/admin-overview.component'; import {DashboardRoutingModule} from './dashboard-routing.module'; import {UsersModule} from '../users/users.module'; +import {AdminJobsModule} from '../jobs/admin-jobs.module'; @NgModule({ @@ -14,7 +15,8 @@ import {UsersModule} from '../users/users.module'; imports: [ CommonModule, DashboardRoutingModule, - UsersModule + UsersModule, + AdminJobsModule, ] }) export class DashboardModule { diff --git a/frontend-implicaction/src/app/admin/jobs/admin-jobs.module.ts b/frontend-implicaction/src/app/admin/jobs/admin-jobs.module.ts index 2f31963f..3d943005 100644 --- a/frontend-implicaction/src/app/admin/jobs/admin-jobs.module.ts +++ b/frontend-implicaction/src/app/admin/jobs/admin-jobs.module.ts @@ -4,17 +4,22 @@ import {AdminJobsComponent} from './admin-jobs.component'; import {AdminJobsRoutingModule} from './admin-jobs-routing.module'; import {TableModule} from 'primeng/table'; import {EditorModule} from 'primeng/editor'; -import {JobPostingFormComponent} from './components/job-posting-form/job-posting-form.component'; import {ReactiveFormsModule} from '@angular/forms'; import {FeatherModule} from 'angular-feather'; import {DropdownModule} from 'primeng/dropdown'; import {CheckboxModule} from 'primeng/checkbox'; +import {PendingJobTableComponent} from './components/pending-job-table/pending-job-table.component'; +import {JobPostingFormComponent} from './components/job-posting-form/job-posting-form.component'; @NgModule({ declarations: [ AdminJobsComponent, - JobPostingFormComponent + JobPostingFormComponent, + PendingJobTableComponent + ], + exports: [ + PendingJobTableComponent ], imports: [ CommonModule, diff --git a/frontend-implicaction/src/app/admin/users/components/pending-user-table/pending-user-table.component.html b/frontend-implicaction/src/app/admin/users/components/pending-user-table/pending-user-table.component.html index 2671b4eb..1514c6cd 100644 --- a/frontend-implicaction/src/app/admin/users/components/pending-user-table/pending-user-table.component.html +++ b/frontend-implicaction/src/app/admin/users/components/pending-user-table/pending-user-table.component.html @@ -1,5 +1,5 @@ {{roleCodesToString(user.roles)}} + + + + + Aucune offre est en attente de validation. + + diff --git a/frontend-implicaction/src/app/admin/jobs/components/pending-job-table/pending-job-table.component.scss b/frontend-implicaction/src/app/admin/jobs/components/pending-job-table/pending-job-table.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/frontend-implicaction/src/app/admin/jobs/components/pending-job-table/pending-job-table.component.spec.ts b/frontend-implicaction/src/app/admin/jobs/components/pending-job-table/pending-job-table.component.spec.ts new file mode 100644 index 00000000..fec40b42 --- /dev/null +++ b/frontend-implicaction/src/app/admin/jobs/components/pending-job-table/pending-job-table.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { PendingJobTableComponent } from './pending-job-table.component'; + +describe('PendingJobTableComponent', () => { + let component: PendingJobTableComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ PendingJobTableComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(PendingJobTableComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/frontend-implicaction/src/app/admin/jobs/components/pending-job-table/pending-job-table.component.ts b/frontend-implicaction/src/app/admin/jobs/components/pending-job-table/pending-job-table.component.ts new file mode 100644 index 00000000..993c4f02 --- /dev/null +++ b/frontend-implicaction/src/app/admin/jobs/components/pending-job-table/pending-job-table.component.ts @@ -0,0 +1,69 @@ +import {Component, OnInit} from '@angular/core'; +import {BaseWithPaginationComponent} from '../../../../shared/components/base-with-pagination/base-with-pagination.component'; +import {JobPosting} from '../../../../shared/models/job-posting'; +import {Constants} from '../../../../config/constants'; +import {JobSortEnum} from '../../../../job/enums/job-sort.enum'; +import {SortDirectionEnum} from '../../../../shared/enums/sort-direction.enum'; +import {ToasterService} from '../../../../core/services/toaster.service'; +import {JobService} from '../../../../job/services/job.service'; +import {ActivatedRoute} from '@angular/router'; +import {finalize, take} from 'rxjs/operators'; + +@Component({ + selector: 'app-pending-job-table', + templateUrl: './pending-job-table.component.html', + styleUrls: ['./pending-job-table.component.scss'] +}) +export class PendingJobTableComponent extends BaseWithPaginationComponent implements OnInit { + readonly ROWS_PER_PAGE_OPTIONS = Constants.ROWS_PER_PAGE_OPTIONS; + + isLoading = true; + // Pagination et filtres + orderByEnums = JobSortEnum.all(); + selectedOrderCode: string; + sortDirection = SortDirectionEnum; + rowsPerPage = this.pageable.rowsPerPages[0]; + + constructor( + private toastService: ToasterService, + private jobsService: JobService, + protected route: ActivatedRoute + ) { + super(route); + } + + ngOnInit(): void { + this.paginate(); + } + + activateJob(job: JobPosting): void { + this.jobsService + .activateJob(job) + .subscribe( + () => { + this.paginate({first: this.pageable.first, rows: this.pageable.rows}); + }, + () => this.toastService.error('Oops', `Une erreur est survenue lors de la validation de l'offre.`), + () => this.toastService.success('Succès', `L'offre ${job.title} est désormais active.`), + ); + } + + protected innerPaginate(): void { + this.jobsService + .getAllPendingActivationJobs(this.pageable) + .pipe( + take(1), + finalize(() => this.isLoading = 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'), + ); + } + +} From d21cb60b6c676a2a9a0c9a7fa8fb1ea3548fd5ee Mon Sep 17 00:00:00 2001 From: Matthieu Audemard Date: Thu, 9 Dec 2021 22:38:49 +0100 Subject: [PATCH 03/12] RI-203: permet de valider une offre et un groupe * fix du BasePageableWithCriteria --- .../pending-job-table/pending-job-table.component.ts | 9 +++------ .../pending-user-table/pending-user-table.component.ts | 7 ++----- .../base-with-pagination.component.ts | 2 +- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/frontend-implicaction/src/app/admin/jobs/components/pending-job-table/pending-job-table.component.ts b/frontend-implicaction/src/app/admin/jobs/components/pending-job-table/pending-job-table.component.ts index 993c4f02..b9cabd84 100644 --- a/frontend-implicaction/src/app/admin/jobs/components/pending-job-table/pending-job-table.component.ts +++ b/frontend-implicaction/src/app/admin/jobs/components/pending-job-table/pending-job-table.component.ts @@ -1,4 +1,4 @@ -import {Component, OnInit} from '@angular/core'; +import {Component} from '@angular/core'; import {BaseWithPaginationComponent} from '../../../../shared/components/base-with-pagination/base-with-pagination.component'; import {JobPosting} from '../../../../shared/models/job-posting'; import {Constants} from '../../../../config/constants'; @@ -8,13 +8,14 @@ import {ToasterService} from '../../../../core/services/toaster.service'; import {JobService} from '../../../../job/services/job.service'; import {ActivatedRoute} from '@angular/router'; import {finalize, take} from 'rxjs/operators'; +import {Criteria} from '../../../../shared/models/Criteria'; @Component({ selector: 'app-pending-job-table', templateUrl: './pending-job-table.component.html', styleUrls: ['./pending-job-table.component.scss'] }) -export class PendingJobTableComponent extends BaseWithPaginationComponent implements OnInit { +export class PendingJobTableComponent extends BaseWithPaginationComponent { readonly ROWS_PER_PAGE_OPTIONS = Constants.ROWS_PER_PAGE_OPTIONS; isLoading = true; @@ -32,10 +33,6 @@ export class PendingJobTableComponent extends BaseWithPaginationComponent { +export class PendingUserTableComponent extends BaseWithPaginationComponent { loading = true; rowsPerPage = this.pageable.rowsPerPages[0]; @@ -28,10 +29,6 @@ export class PendingUserTableComponent extends BaseWithPaginationComponent { criteria: C; // Pagination - pageable: Pageable = Constants.PAGEABLE_DEFAULT; + pageable: Pageable = {...Constants.PAGEABLE_DEFAULT}; constructor(protected route: ActivatedRoute) { } From 2b880b8787b87aeab598dcef734f073a8bd0c224 Mon Sep 17 00:00:00 2001 From: nekorpeche Date: Sat, 11 Dec 2021 00:07:21 +0100 Subject: [PATCH 04/12] =?UTF-8?q?RI-203:=20permet=20de=20valider=20une=20o?= =?UTF-8?q?ffre=20et=20un=20groupe=20*=20prob=C3=A8le=20quand=20j'essaie?= =?UTF-8?q?=20d'ajouter=20l'utilisateur=20au=20groupe,=20j'ai=20retir?= =?UTF-8?q?=C3=A9=20le=20bout=20de=20code=20qui=20me=20le=20permettait=20e?= =?UTF-8?q?t=20g=C3=A9n=C3=A9rait=20l'erreur?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../adapter/GroupAdapter.java | 6 +- .../controller/GroupController.java | 17 ++++++ .../refonteimplicaction/dto/GroupDto.java | 1 + .../refonteimplicaction/model/Group.java | 4 ++ .../repository/GroupRepository.java | 5 ++ .../service/GroupService.java | 14 ++++- .../refonteimplicaction/utils/ApiUrls.java | 2 + .../adapter/PostAdapterTest.java | 6 +- .../service/CommentServiceTest.java | 2 +- .../service/PostServiceTest.java | 6 +- .../src/app/admin/admin.module.ts | 5 ++ .../admin/dashboard/dashboard.component.html | 6 ++ .../app/admin/dashboard/dashboard.module.ts | 2 + .../pending-group-table.component.html | 39 ++++++++++++ .../pending-group-table.component.scss | 0 .../pending-group-table.component.spec.ts | 25 ++++++++ .../pending-group-table.component.ts | 60 +++++++++++++++++++ .../pending-job-table.component.ts | 2 - .../pending-user-table.component.ts | 3 +- .../core/services/api-endpoints.service.ts | 8 +++ .../src/app/discussion/model/group.ts | 2 + .../app/discussion/services/group.service.ts | 8 +++ .../src/app/shared/models/uris.ts | 2 + 23 files changed, 212 insertions(+), 13 deletions(-) create mode 100644 frontend-implicaction/src/app/admin/groups/pending-group-table/pending-group-table.component.html create mode 100644 frontend-implicaction/src/app/admin/groups/pending-group-table/pending-group-table.component.scss create mode 100644 frontend-implicaction/src/app/admin/groups/pending-group-table/pending-group-table.component.spec.ts create mode 100644 frontend-implicaction/src/app/admin/groups/pending-group-table/pending-group-table.component.ts diff --git a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/adapter/GroupAdapter.java b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/adapter/GroupAdapter.java index 4ff5a389..a5af6831 100644 --- a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/adapter/GroupAdapter.java +++ b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/adapter/GroupAdapter.java @@ -2,6 +2,7 @@ import com.dynonuggets.refonteimplicaction.dto.GroupDto; import com.dynonuggets.refonteimplicaction.model.Group; +import com.dynonuggets.refonteimplicaction.model.User; import com.dynonuggets.refonteimplicaction.service.FileService; import lombok.AllArgsConstructor; import org.springframework.stereotype.Component; @@ -15,13 +16,15 @@ public class GroupAdapter { protected static final String DEFAULT_GROUP_IMAGE_URI = "assets/img/avatar-ia-group.png"; private FileService fileService; + private final UserAdapter userAdapter; - public Group toModel(final GroupDto dto) { + public Group toModel(GroupDto dto) { return Group.builder() .id(dto.getId()) .name(dto.getName()) .description(dto.getDescription()) .createdAt(dto.getCreatedAt()) + .active(dto.isActive()) .build(); } @@ -34,6 +37,7 @@ public GroupDto toDto(Group model) { .description(model.getDescription()) .createdAt(model.getCreatedAt()) .imageUrl(imageUrl) + .active(model.isActive()) .build(); } } diff --git a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/controller/GroupController.java b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/controller/GroupController.java index 6ff5f1c0..463bb121 100644 --- a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/controller/GroupController.java +++ b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/controller/GroupController.java @@ -1,6 +1,7 @@ package com.dynonuggets.refonteimplicaction.controller; import com.dynonuggets.refonteimplicaction.dto.GroupDto; +import com.dynonuggets.refonteimplicaction.model.Group; import com.dynonuggets.refonteimplicaction.service.GroupService; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -63,4 +64,20 @@ public ResponseEntity> subscribeGroup(@PathVariable final String final List groupDtos = groupService.addGroup(groupName); return ResponseEntity.ok(groupDtos); } + + @GetMapping(GET_PENDING_GROUP_URI) + public ResponseEntity> getAllPendingGroups( + @RequestParam(value = "page", defaultValue = "0") int page, + @RequestParam(value = "rows", defaultValue = "10") int rows + ) { + Pageable pageable = PageRequest.of(page, rows); + Page pendingGroups = groupService.getAllPendingActivationGroups(pageable); + return ResponseEntity.ok(pendingGroups); + } + + @PatchMapping(ACTIVATE_GROUP_URI) + public ResponseEntity activateJob(@RequestBody final Group group) { + groupService.activateGroup(group); + return ResponseEntity.ok().build(); + } } diff --git a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/dto/GroupDto.java b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/dto/GroupDto.java index 355de990..e22eaf50 100644 --- a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/dto/GroupDto.java +++ b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/dto/GroupDto.java @@ -18,5 +18,6 @@ public class GroupDto { private Integer numberOfPosts; private String imageUrl; private Instant createdAt; + private boolean active; private List users; } diff --git a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/model/Group.java b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/model/Group.java index 0ce3cd84..41ea86e5 100644 --- a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/model/Group.java +++ b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/model/Group.java @@ -35,6 +35,7 @@ public class Group { private Instant createdAt; @ManyToOne(fetch = LAZY) + @JoinColumn(name = "user_id") private User user; @ManyToOne(fetch = LAZY) @@ -42,4 +43,7 @@ public class Group { @ManyToMany(fetch = FetchType.LAZY, cascade = ALL, mappedBy = "groups") private List users; + + @Column(name = "active") + private boolean active; } diff --git a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/repository/GroupRepository.java b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/repository/GroupRepository.java index 682f5e41..d9683380 100644 --- a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/repository/GroupRepository.java +++ b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/repository/GroupRepository.java @@ -1,6 +1,7 @@ package com.dynonuggets.refonteimplicaction.repository; import com.dynonuggets.refonteimplicaction.model.Group; +import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; @@ -13,4 +14,8 @@ public interface GroupRepository extends JpaRepository { List findAllByTopPosting(Pageable pageable); Optional findByName(String name); + + Page findAllByActiveIsFalse(Pageable pageable); + + Page findAllByActiveIsTrue(Pageable pageable); } diff --git a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/service/GroupService.java b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/service/GroupService.java index 0b510512..c3b639d5 100644 --- a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/service/GroupService.java +++ b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/service/GroupService.java @@ -59,7 +59,7 @@ public GroupDto save(GroupDto groupDto) { @Transactional(readOnly = true) public Page getAll(Pageable pageable) { - final Page subreddits = groupRepository.findAll(pageable); + final Page subreddits = groupRepository.findAllByActiveIsTrue(pageable); return subreddits.map(groupAdapter::toDto); } @@ -82,4 +82,16 @@ public List addGroup(String groupName) { .map(groupAdapter::toDto) .collect(toList()); } + + @Transactional + public Page getAllPendingActivationGroups(Pageable pageable) { + return subredditRepository.findAllByActiveIsFalse(pageable) + .map(subredditAdapter::toDto); + } + + @Transactional + public void activateGroup(Group group) { + group.setActive(true); + subredditRepository.save(group); + } } diff --git a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/utils/ApiUrls.java b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/utils/ApiUrls.java index 7e6aa0a5..e6f44e25 100644 --- a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/utils/ApiUrls.java +++ b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/utils/ApiUrls.java @@ -31,6 +31,8 @@ public class ApiUrls { public static final String GROUPS_BASE_URI = "/api/groups"; public static final String GET_ALL_BY_TOP_POSTING_URI = "/top-posting"; public static final String CREATE_NO_IMAGE = "/no-image"; + public static final String GET_PENDING_GROUP_URI = "/pending"; + public static final String ACTIVATE_GROUP_URI = "/activate"; public static final String SUBSCRIBE_GROUP = "/{groupName}/subscribe"; // COMMENTS diff --git a/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/adapter/PostAdapterTest.java b/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/adapter/PostAdapterTest.java index d37ecadc..510c81de 100644 --- a/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/adapter/PostAdapterTest.java +++ b/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/adapter/PostAdapterTest.java @@ -32,7 +32,7 @@ class PostAdapterTest { void toPost() { // given User currentUser = User.builder().id(123L).username("test user").build(); - Group group = new Group(123L, "Super Subreddit", "Subreddit Description", emptyList(), now(), currentUser, null, emptyList()); + Group group = new Group(123L, "Super Subreddit", "Subreddit Description", emptyList(), now(), currentUser, null, emptyList(), true); Post expected = new Post(123L, "Super Post", "http://url.site", "Test", 0, currentUser, now(), group); PostRequest postRequest = new PostRequest(123L, null, "Super Post", "http://url.site", "Test"); @@ -62,7 +62,7 @@ void should_return_post_with_no_subreddit_and_poster_has_no_image() { @Test void should_return_post_with_subreddit_image_null() { User currentUser = User.builder().id(123L).username("test user").build(); - Group group = new Group(123L, "Super Subreddit", "Subreddit Description", emptyList(), now(), currentUser, null, emptyList()); + Group group = new Group(123L, "Super Subreddit", "Subreddit Description", emptyList(), now(), currentUser, null, emptyList(), true); Post expected = new Post(123L, "Super Post", "http://url.site", "Test", 12, currentUser, now(), group); final int expectedCommentCount = 10; @@ -77,7 +77,7 @@ void should_return_post_with_subreddit_image_null() { void toPostResponse() { // given User currentUser = User.builder().id(123L).username("test user").image(FileModel.builder().url("http://url.com").build()).build(); - Group group = new Group(123L, "Super Subreddit", "Subreddit Description", emptyList(), now(), currentUser, FileModel.builder().url("http://img.com").build(), emptyList()); + Group group = new Group(123L, "Super Subreddit", "Subreddit Description", emptyList(), now(), currentUser, FileModel.builder().url("http://img.com").build(), emptyList(), true); Post expected = new Post(123L, "Super Post", "http://url.site", "Test", 12, currentUser, now(), group); final int expectedCommentCount = 10; diff --git a/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/service/CommentServiceTest.java b/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/service/CommentServiceTest.java index 5c8e7cfa..b9d07870 100644 --- a/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/service/CommentServiceTest.java +++ b/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/service/CommentServiceTest.java @@ -144,7 +144,7 @@ void should_throw_exception_when_not_exists() { void should_get_comments_for_post_when_exists() { // given User currentUser = User.builder().id(123L).username("Sankukai").build(); - Group group = new Group(123L, "Super Subreddit", "Subreddit Description", emptyList(), Instant.now(), currentUser, null, emptyList()); + Group group = new Group(123L, "Super Subreddit", "Subreddit Description", emptyList(), Instant.now(), currentUser, null, emptyList(), true); Post post = new Post(12L, "Super Post", "http://url.site", "Test", 88000, currentUser, Instant.now(), group); List comments = asList( new Comment(3L, "comment1", post, Instant.now(), currentUser), diff --git a/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/service/PostServiceTest.java b/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/service/PostServiceTest.java index c065725a..f810f517 100644 --- a/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/service/PostServiceTest.java +++ b/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/service/PostServiceTest.java @@ -63,7 +63,7 @@ class PostServiceTest { void should_save_post_if_subreddit_exists() { // given User currentUser = User.builder().id(123L).username("test user").build(); - Group group = new Group(123L, "Super Subreddit", "Subreddit Description", emptyList(), Instant.now(), currentUser, null, emptyList()); + Group group = new Group(123L, "Super Subreddit", "Subreddit Description", emptyList(), Instant.now(), currentUser, null, emptyList(), true); Post expected = new Post(123L, "Super Post", "http://url.site", "Test", 0, null, Instant.now(), null); PostRequest postRequest = new PostRequest(123L, 123L, "First Subreddit", "http://url.site", "Test"); @@ -128,7 +128,7 @@ void should_throw_exception_when_save_post_and_subreddit_not_found() { void should_get_post_when_exists() { // given User currentUser = User.builder().id(123L).username("Sankukai").build(); - Group group = new Group(123L, "Super Subreddit", "Subreddit Description", emptyList(), Instant.now(), currentUser, null, emptyList()); + Group group = new Group(123L, "Super Subreddit", "Subreddit Description", emptyList(), Instant.now(), currentUser, null, emptyList(), true); Post post = new Post(12L, "Super Post", "http://url.site", "Test", 88000, currentUser, Instant.now(), group); PostResponse expectedResponse = new PostResponse(123L, "Super post", "http://url.site", "Test", "Sankukai", currentUser.getId(), null, "Super Subreddit", 88000, 12, null, true, false, null); given(postRepository.findById(anyLong())).willReturn(Optional.of(post)); @@ -158,7 +158,7 @@ void should_throw_exception_when_post_not_exists() { void should_list_all_posts() { // given User currentUser = User.builder().id(1345L).username("gustave").build(); - Group group = new Group(123L, "Sub 1", "Description Sub 1", null, Instant.now(), currentUser, null, emptyList()); + Group group = new Group(123L, "Sub 1", "Description Sub 1", null, Instant.now(), currentUser, null, emptyList(), true); Pageable pageable = PageRequest.of(0, 10, Sort.DEFAULT_DIRECTION, "id"); Page expectedPages = new PageImpl<>(asList( new Post(1L, "Post 1", null, "Description 1", 0, currentUser, Instant.now(), group), diff --git a/frontend-implicaction/src/app/admin/admin.module.ts b/frontend-implicaction/src/app/admin/admin.module.ts index 19926ba9..97210239 100644 --- a/frontend-implicaction/src/app/admin/admin.module.ts +++ b/frontend-implicaction/src/app/admin/admin.module.ts @@ -8,12 +8,14 @@ import {CompaniesComponent} from './companies/companies.component'; import {TableModule} from 'primeng/table'; import {CompaniesModule} from './companies/companies.module'; import {FeatherModule} from 'angular-feather'; +import {PendingGroupTableComponent} from './groups/pending-group-table/pending-group-table.component'; @NgModule({ declarations: [ AdminComponent, CompaniesComponent, + PendingGroupTableComponent, ], imports: [ CommonModule, @@ -24,6 +26,9 @@ import {FeatherModule} from 'angular-feather'; FeatherModule ], providers: [{provide: LOCALE_ID, useValue: 'fr'}], + exports: [ + PendingGroupTableComponent + ] }) export class AdminModule { constructor() { diff --git a/frontend-implicaction/src/app/admin/dashboard/dashboard.component.html b/frontend-implicaction/src/app/admin/dashboard/dashboard.component.html index 10316610..7280055b 100644 --- a/frontend-implicaction/src/app/admin/dashboard/dashboard.component.html +++ b/frontend-implicaction/src/app/admin/dashboard/dashboard.component.html @@ -13,4 +13,10 @@
Nouvelles offres
+
+
+
Nouveaux groupes
+
+ +
diff --git a/frontend-implicaction/src/app/admin/dashboard/dashboard.module.ts b/frontend-implicaction/src/app/admin/dashboard/dashboard.module.ts index e885791f..68e0a150 100644 --- a/frontend-implicaction/src/app/admin/dashboard/dashboard.module.ts +++ b/frontend-implicaction/src/app/admin/dashboard/dashboard.module.ts @@ -5,6 +5,7 @@ import {AdminOverviewComponent} from './components/admin-overview/admin-overview import {DashboardRoutingModule} from './dashboard-routing.module'; import {UsersModule} from '../users/users.module'; import {AdminJobsModule} from '../jobs/admin-jobs.module'; +import {AdminModule} from '../admin.module'; @NgModule({ @@ -17,6 +18,7 @@ import {AdminJobsModule} from '../jobs/admin-jobs.module'; DashboardRoutingModule, UsersModule, AdminJobsModule, + AdminModule, ] }) export class DashboardModule { diff --git a/frontend-implicaction/src/app/admin/groups/pending-group-table/pending-group-table.component.html b/frontend-implicaction/src/app/admin/groups/pending-group-table/pending-group-table.component.html new file mode 100644 index 00000000..62ab483d --- /dev/null +++ b/frontend-implicaction/src/app/admin/groups/pending-group-table/pending-group-table.component.html @@ -0,0 +1,39 @@ + + + + Nom + Description + Crée le + + + + + {{group.name}} + {{group.description}} + {{group.createdAt}} + + + + + + + Aucun groupe est en attente de validation. + + diff --git a/frontend-implicaction/src/app/admin/groups/pending-group-table/pending-group-table.component.scss b/frontend-implicaction/src/app/admin/groups/pending-group-table/pending-group-table.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/frontend-implicaction/src/app/admin/groups/pending-group-table/pending-group-table.component.spec.ts b/frontend-implicaction/src/app/admin/groups/pending-group-table/pending-group-table.component.spec.ts new file mode 100644 index 00000000..0add9b8d --- /dev/null +++ b/frontend-implicaction/src/app/admin/groups/pending-group-table/pending-group-table.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { PendingGroupTableComponent } from './pending-group-table.component'; + +describe('PendingGroupTableComponent', () => { + let component: PendingGroupTableComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ PendingGroupTableComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(PendingGroupTableComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/frontend-implicaction/src/app/admin/groups/pending-group-table/pending-group-table.component.ts b/frontend-implicaction/src/app/admin/groups/pending-group-table/pending-group-table.component.ts new file mode 100644 index 00000000..c44f3fd8 --- /dev/null +++ b/frontend-implicaction/src/app/admin/groups/pending-group-table/pending-group-table.component.ts @@ -0,0 +1,60 @@ +import {Component} from '@angular/core'; +import {BaseWithPaginationComponent} from '../../../shared/components/base-with-pagination/base-with-pagination.component'; +import {Group} from '../../../discussion/model/group'; +import {SortDirectionEnum} from '../../../shared/enums/sort-direction.enum'; +import {ActivatedRoute} from '@angular/router'; +import {ToasterService} from '../../../core/services/toaster.service'; +import {GroupService} from '../../../discussion/services/group.service'; +import {finalize, take} from 'rxjs/operators'; +import {Criteria} from '../../../shared/models/Criteria'; + +@Component({ + selector: 'app-pending-group-table', + templateUrl: './pending-group-table.component.html', + styleUrls: ['./pending-group-table.component.scss'] +}) +export class PendingGroupTableComponent extends BaseWithPaginationComponent { + + isLoading = true; + selectedOrderCode: string; + sortDirection = SortDirectionEnum; + rowsPerPage = this.pageable.rowsPerPages[0]; + + constructor( + private toastService: ToasterService, + private groupService: GroupService, + protected route: ActivatedRoute + ) { + super(route); + } + + activateGroup(group: Group): void { + this.groupService + .activateGroup(group) + .subscribe( + (data) => { + this.paginate({first: this.pageable.first, rows: this.pageable.rows}); + }, + () => this.toastService.error('Oops', `Une erreur est survenue lors de la validation du groupe.`), + () => this.toastService.success('Succès', `Le groupe ${group.name} est désormais actif.`), + ); + } + + protected innerPaginate(): void { + this.groupService + .getAllPendingActivationGroup(this.pageable) + .pipe( + take(1), + finalize(() => this.isLoading = 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/pending-job-table/pending-job-table.component.ts b/frontend-implicaction/src/app/admin/jobs/components/pending-job-table/pending-job-table.component.ts index b9cabd84..3ac76223 100644 --- a/frontend-implicaction/src/app/admin/jobs/components/pending-job-table/pending-job-table.component.ts +++ b/frontend-implicaction/src/app/admin/jobs/components/pending-job-table/pending-job-table.component.ts @@ -1,7 +1,6 @@ import {Component} from '@angular/core'; import {BaseWithPaginationComponent} from '../../../../shared/components/base-with-pagination/base-with-pagination.component'; import {JobPosting} from '../../../../shared/models/job-posting'; -import {Constants} from '../../../../config/constants'; import {JobSortEnum} from '../../../../job/enums/job-sort.enum'; import {SortDirectionEnum} from '../../../../shared/enums/sort-direction.enum'; import {ToasterService} from '../../../../core/services/toaster.service'; @@ -16,7 +15,6 @@ import {Criteria} from '../../../../shared/models/Criteria'; styleUrls: ['./pending-job-table.component.scss'] }) export class PendingJobTableComponent extends BaseWithPaginationComponent { - readonly ROWS_PER_PAGE_OPTIONS = Constants.ROWS_PER_PAGE_OPTIONS; isLoading = true; // Pagination et filtres diff --git a/frontend-implicaction/src/app/admin/users/components/pending-user-table/pending-user-table.component.ts b/frontend-implicaction/src/app/admin/users/components/pending-user-table/pending-user-table.component.ts index e42dbb77..9508bd34 100644 --- a/frontend-implicaction/src/app/admin/users/components/pending-user-table/pending-user-table.component.ts +++ b/frontend-implicaction/src/app/admin/users/components/pending-user-table/pending-user-table.component.ts @@ -6,7 +6,6 @@ import {RoleEnum, RoleEnumCode} from '../../../../shared/enums/role.enum'; import {User} from '../../../../shared/models/user'; import {AuthService} from '../../../../shared/services/auth.service'; import {BaseWithPaginationComponent} from '../../../../shared/components/base-with-pagination/base-with-pagination.component'; -import {JobPosting} from '../../../../shared/models/job-posting'; import {ActivatedRoute} from '@angular/router'; import {Criteria} from '../../../../shared/models/Criteria'; @@ -15,7 +14,7 @@ import {Criteria} from '../../../../shared/models/Criteria'; templateUrl: './pending-user-table.component.html', styleUrls: ['./pending-user-table.component.scss'] }) -export class PendingUserTableComponent extends BaseWithPaginationComponent { +export class PendingUserTableComponent extends BaseWithPaginationComponent { loading = true; rowsPerPage = this.pageable.rowsPerPages[0]; diff --git a/frontend-implicaction/src/app/core/services/api-endpoints.service.ts b/frontend-implicaction/src/app/core/services/api-endpoints.service.ts index 6bf68f3f..7015ffc0 100644 --- a/frontend-implicaction/src/app/core/services/api-endpoints.service.ts +++ b/frontend-implicaction/src/app/core/services/api-endpoints.service.ts @@ -350,6 +350,14 @@ export class ApiEndpointsService { return ApiEndpointsService.createUrlWithPageable(Uris.GROUP.BASE_URI, pageable); } + getActivateGroupEndpoint(): string { + return ApiEndpointsService.createUrl(Uris.GROUP.ACTIVATE_GROUP); + } + + getAllPendingActivationGroupEndpoint(pageable: Pageable): string { + return ApiEndpointsService.createUrlWithPageable(Uris.GROUP.GET_ALL_PENDING_GROUPS, pageable); + } + createGroupSubscription(groupName: string): string { return ApiEndpointsService.createUrlWithPathVariables(Uris.GROUP.BASE_URI, [groupName, 'subscribe']); } diff --git a/frontend-implicaction/src/app/discussion/model/group.ts b/frontend-implicaction/src/app/discussion/model/group.ts index 93398691..66c3d335 100644 --- a/frontend-implicaction/src/app/discussion/model/group.ts +++ b/frontend-implicaction/src/app/discussion/model/group.ts @@ -4,4 +4,6 @@ export interface Group { description?: string; numberOfPosts?: number; imageUrl?: string; + createdAt?: Date; + active?: boolean; } diff --git a/frontend-implicaction/src/app/discussion/services/group.service.ts b/frontend-implicaction/src/app/discussion/services/group.service.ts index 52418e51..71e9e9a9 100644 --- a/frontend-implicaction/src/app/discussion/services/group.service.ts +++ b/frontend-implicaction/src/app/discussion/services/group.service.ts @@ -35,4 +35,12 @@ export class GroupService { subscribeGroup(groupName: string): Observable { return this.http.post(this.apiEndpointService.createGroupSubscription(groupName), null); } + + getAllPendingActivationGroup(pageable: Pageable): Observable { + return this.http.get(this.apiEndpointService.getAllPendingActivationGroupEndpoint(pageable)); + } + + activateGroup(group: Group): Observable { + return this.http.patch(this.apiEndpointService.getActivateGroupEndpoint(), group); + } } diff --git a/frontend-implicaction/src/app/shared/models/uris.ts b/frontend-implicaction/src/app/shared/models/uris.ts index 9c1ae8ce..d4d47a51 100644 --- a/frontend-implicaction/src/app/shared/models/uris.ts +++ b/frontend-implicaction/src/app/shared/models/uris.ts @@ -93,6 +93,8 @@ export class Uris { static readonly BASE_URI = 'groups'; static readonly TOP_POSTING = 'groups/top-posting'; static readonly CREATE_NO_IMAGE = 'groups/no-image'; + static readonly ACTIVATE_GROUP = 'groups/activate'; + static readonly GET_ALL_PENDING_GROUPS = 'groups/pending'; }; /** From 1e5d120dcda372a1f47fe9ed63ddea01008a16f7 Mon Sep 17 00:00:00 2001 From: nekorpeche Date: Sat, 11 Dec 2021 13:44:49 +0100 Subject: [PATCH 05/12] RI-203: permet de valider une offre et un groupe * tests --- .../adapter/GroupAdapter.java | 1 - .../GroupControllerIntegrationTest.java | 42 +++++++++++++++++ .../controller/JobsPostingControllerTest.java | 47 +++++++++++++++++++ 3 files changed, 89 insertions(+), 1 deletion(-) diff --git a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/adapter/GroupAdapter.java b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/adapter/GroupAdapter.java index a5af6831..efac628c 100644 --- a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/adapter/GroupAdapter.java +++ b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/adapter/GroupAdapter.java @@ -2,7 +2,6 @@ import com.dynonuggets.refonteimplicaction.dto.GroupDto; import com.dynonuggets.refonteimplicaction.model.Group; -import com.dynonuggets.refonteimplicaction.model.User; import com.dynonuggets.refonteimplicaction.service.FileService; import lombok.AllArgsConstructor; import org.springframework.stereotype.Component; diff --git a/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/controller/GroupControllerIntegrationTest.java b/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/controller/GroupControllerIntegrationTest.java index 9124eb9a..48447070 100644 --- a/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/controller/GroupControllerIntegrationTest.java +++ b/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/controller/GroupControllerIntegrationTest.java @@ -11,6 +11,7 @@ import org.springframework.security.test.context.support.WithMockUser; import org.springframework.test.web.servlet.ResultActions; +import java.util.Arrays; import java.util.List; import static com.dynonuggets.refonteimplicaction.utils.ApiUrls.*; @@ -157,4 +158,45 @@ void should_response_forbidden_when_top_posting_and_not_authenticated() throws E verify(groupService, never()).getAllByTopPosting(anyInt()); } + + @Test + @WithMockUser + void should_get_all_pending_groups_when_authenticated() throws Exception { + //given + List groupDtos = Arrays.asList( + GroupDto.builder().id(1L).active(false).build(), + GroupDto.builder().id(2L).active(false).build(), + GroupDto.builder().id(3L).active(false).build() + ); + Page groupPageMockResponse = new PageImpl<>(groupDtos); + given(groupService.getAllPendingActivationGroups(any())).willReturn(groupPageMockResponse); + + // when + ResultActions resultActions = mvc.perform( + get(GROUPS_BASE_URI + GET_PENDING_GROUP_URI).contentType(APPLICATION_JSON)); + + // then + resultActions.andDo(print()) + .andExpect(status().isOk()); + + for (int i = 0; i < groupDtos.size(); i++) { + final String contentPath = String.format("$.content[%d]", i); + resultActions.andExpect(jsonPath(contentPath + ".id", is(Math.toIntExact(groupDtos.get(i).getId())))); + resultActions.andExpect(jsonPath(contentPath + ".active", is(groupDtos.get(i).isActive()))); + } + + verify(groupService, times(1)).getAllPendingActivationGroups(any()); + } + + @Test + void should_response_forbidden_when_pending_groups_and_not_authenticated() throws Exception { + + // when + final ResultActions resultActions = mvc.perform(get(GROUPS_BASE_URI + GET_PENDING_GROUP_URI).contentType(APPLICATION_JSON)); + + // then + resultActions.andDo(print()).andExpect(status().isForbidden()); + + verify(groupService, never()).getAllPendingActivationGroups(any()); + } } diff --git a/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/controller/JobsPostingControllerTest.java b/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/controller/JobsPostingControllerTest.java index 99afb790..13a31b46 100644 --- a/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/controller/JobsPostingControllerTest.java +++ b/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/controller/JobsPostingControllerTest.java @@ -1,7 +1,9 @@ package com.dynonuggets.refonteimplicaction.controller; +import com.dynonuggets.refonteimplicaction.adapter.JobPostingAdapter; import com.dynonuggets.refonteimplicaction.dto.JobPostingDto; import com.dynonuggets.refonteimplicaction.exception.NotFoundException; +import com.dynonuggets.refonteimplicaction.model.JobPosting; import com.dynonuggets.refonteimplicaction.service.JobPostingService; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -36,6 +38,9 @@ class JobsPostingControllerTest extends ControllerIntegrationTestBase { @MockBean JobPostingService jobPostingService; + @MockBean + JobPostingAdapter jobPostingAdapter; + List jobPostings; @BeforeEach @@ -246,4 +251,46 @@ void archiveJobListWithoutJwtShouldBeForbidden() throws Exception { .andExpect(status().isForbidden()); verify(jobPostingService, never()).toggleArchiveAll(Collections.singletonList(anyLong())); } + + @Test + @WithMockUser + void should_get_all_pending_jobs_when_authenticated() throws Exception { + //given + List jobPostingDtos = Arrays.asList( + JobPostingDto.builder().id(1L).active(false).build(), + JobPostingDto.builder().id(2L).active(false).build(), + JobPostingDto.builder().id(3L).active(false).build() + ); + Page jobPageMockResponse = new PageImpl<>(jobPostingDtos); + given(jobPostingService.getAllPendingActivationJobs(any())).willReturn(jobPageMockResponse); + + // when + ResultActions resultActions = mvc.perform( + get(JOBS_BASE_URI + GET_PENDING_JOB_URI).contentType(APPLICATION_JSON)); + + // then + resultActions.andDo(print()) + .andExpect(status().isOk()); + + for (int i = 0; i < jobPostingDtos.size(); i++) { + final String contentPath = String.format("$.content[%d]", i); + resultActions.andExpect(jsonPath(contentPath + ".id", is(Math.toIntExact(jobPostingDtos.get(i).getId())))); + resultActions.andExpect(jsonPath(contentPath + ".active", is(jobPostingDtos.get(i).isActive()))); + } + + verify(jobPostingService, times(1)).getAllPendingActivationJobs(any()); + } + + @Test + void should_response_forbidden_when_pending_jobs_and_not_authenticated() throws Exception { + + // when + final ResultActions resultActions = mvc.perform(get(JOBS_BASE_URI + GET_PENDING_JOB_URI).contentType(APPLICATION_JSON)); + + // then + resultActions.andDo(print()).andExpect(status().isForbidden()); + + verify(jobPostingService, never()).getAllPendingActivationJobs(any()); + } + } From c9d90645dd0a8bb826249dac38836a115e2b9d81 Mon Sep 17 00:00:00 2001 From: nekorpeche Date: Sat, 11 Dec 2021 16:55:01 +0100 Subject: [PATCH 06/12] RI-203: validation des groupes et des offres * code review --- .../adapter/GroupAdapter.java | 6 +++- .../controller/GroupController.java | 12 ++++---- .../refonteimplicaction/dto/GroupDto.java | 2 ++ .../service/GroupService.java | 15 +++++++--- .../refonteimplicaction/utils/ApiUrls.java | 1 + .../adapter/GroupAdapterTest.java | 18 +++++++++-- .../GroupControllerIntegrationTest.java | 23 ++++++++++---- .../service/GroupServiceTest.java | 30 +++++++++++++++---- .../pending-group-table.component.html | 2 ++ .../core/services/api-endpoints.service.ts | 4 +-- .../src/app/discussion/model/group.ts | 2 ++ .../app/discussion/services/group.service.ts | 2 +- .../src/app/shared/models/uris.ts | 1 + 13 files changed, 92 insertions(+), 26 deletions(-) diff --git a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/adapter/GroupAdapter.java b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/adapter/GroupAdapter.java index efac628c..b38b953b 100644 --- a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/adapter/GroupAdapter.java +++ b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/adapter/GroupAdapter.java @@ -2,6 +2,7 @@ import com.dynonuggets.refonteimplicaction.dto.GroupDto; import com.dynonuggets.refonteimplicaction.model.Group; +import com.dynonuggets.refonteimplicaction.model.User; import com.dynonuggets.refonteimplicaction.service.FileService; import lombok.AllArgsConstructor; import org.springframework.stereotype.Component; @@ -17,13 +18,14 @@ public class GroupAdapter { private FileService fileService; private final UserAdapter userAdapter; - public Group toModel(GroupDto dto) { + public Group toModel(GroupDto dto, User user) { return Group.builder() .id(dto.getId()) .name(dto.getName()) .description(dto.getDescription()) .createdAt(dto.getCreatedAt()) .active(dto.isActive()) + .user(user) .build(); } @@ -37,6 +39,8 @@ public GroupDto toDto(Group model) { .createdAt(model.getCreatedAt()) .imageUrl(imageUrl) .active(model.isActive()) + .username(model.getUser().getUsername()) + .userId(model.getUser().getId()) .build(); } } diff --git a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/controller/GroupController.java b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/controller/GroupController.java index 463bb121..f6dcda44 100644 --- a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/controller/GroupController.java +++ b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/controller/GroupController.java @@ -41,15 +41,15 @@ public ResponseEntity createSubreddit(@RequestBody GroupDto group) { return ResponseEntity.status(CREATED).body(saveDto); } - @GetMapping - public ResponseEntity> getAll( + @GetMapping(ACTIVE_GROUPS) + public ResponseEntity> getAllActiveGroups( @RequestParam(value = "page", defaultValue = "0") int page, @RequestParam(value = "rows", defaultValue = "10") int rows, @RequestParam(value = "sortBy", defaultValue = "id") String sortBy, @RequestParam(value = "sortOrder", defaultValue = "ASC") String sortOrder ) { Pageable pageable = PageRequest.of(page, rows, Sort.by(Sort.Direction.valueOf(sortOrder), sortBy)); - Page subredditDtos = groupService.getAll(pageable); + Page subredditDtos = groupService.getAllActiveGroups(pageable); return ResponseEntity.ok(subredditDtos); } @@ -68,9 +68,11 @@ public ResponseEntity> subscribeGroup(@PathVariable final String @GetMapping(GET_PENDING_GROUP_URI) public ResponseEntity> getAllPendingGroups( @RequestParam(value = "page", defaultValue = "0") int page, - @RequestParam(value = "rows", defaultValue = "10") int rows + @RequestParam(value = "rows", defaultValue = "10") int rows, + @RequestParam(value = "sortBy", defaultValue = "id") String sortBy, + @RequestParam(value = "sortOrder", defaultValue = "ASC") String sortOrder ) { - Pageable pageable = PageRequest.of(page, rows); + Pageable pageable = PageRequest.of(page, rows, Sort.by(Sort.Direction.valueOf(sortOrder), sortBy)); Page pendingGroups = groupService.getAllPendingActivationGroups(pageable); return ResponseEntity.ok(pendingGroups); } diff --git a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/dto/GroupDto.java b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/dto/GroupDto.java index e22eaf50..fcfe7e32 100644 --- a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/dto/GroupDto.java +++ b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/dto/GroupDto.java @@ -20,4 +20,6 @@ public class GroupDto { private Instant createdAt; private boolean active; private List users; + private String username; + private Long userId; } diff --git a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/service/GroupService.java b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/service/GroupService.java index c3b639d5..047a621a 100644 --- a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/service/GroupService.java +++ b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/service/GroupService.java @@ -3,12 +3,16 @@ import com.dynonuggets.refonteimplicaction.adapter.GroupAdapter; import com.dynonuggets.refonteimplicaction.dto.GroupDto; import com.dynonuggets.refonteimplicaction.exception.NotFoundException; +import com.dynonuggets.refonteimplicaction.exception.UserNotFoundException; import com.dynonuggets.refonteimplicaction.model.FileModel; import com.dynonuggets.refonteimplicaction.model.Group; import com.dynonuggets.refonteimplicaction.model.User; import com.dynonuggets.refonteimplicaction.repository.FileRepository; import com.dynonuggets.refonteimplicaction.repository.GroupRepository; import com.dynonuggets.refonteimplicaction.repository.UserRepository; +import com.dynonuggets.refonteimplicaction.repository.SubredditRepository; +import com.dynonuggets.refonteimplicaction.repository.UserRepository; +import com.dynonuggets.refonteimplicaction.utils.Message; import lombok.AllArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -37,8 +41,9 @@ public class GroupService { public GroupDto save(MultipartFile image, GroupDto groupDto) { final FileModel fileModel = cloudService.uploadImage(image); final FileModel fileSave = fileRepository.save(fileModel); - - Group group = groupAdapter.toModel(groupDto); + User user = userRepository.findById(groupDto.getUserId()) + .orElseThrow(() -> new UserNotFoundException(String.format(Message.USER_NOT_FOUND_MESSAGE, groupDto.getUserId()))); + Group group = groupAdapter.toModel(groupDto, user); group.setImage(fileSave); group.setCreatedAt(Instant.now()); group.setUser(authService.getCurrentUser()); @@ -50,7 +55,9 @@ public GroupDto save(MultipartFile image, GroupDto groupDto) { @Transactional public GroupDto save(GroupDto groupDto) { - Group group = groupAdapter.toModel(groupDto); + User user = userRepository.findById(groupDto.getUserId()) + .orElseThrow(() -> new UserNotFoundException(String.format(Message.USER_NOT_FOUND_MESSAGE, groupDto.getUserId()))); + Group group = groupAdapter.toModel(groupDto, user); group.setCreatedAt(Instant.now()); group.setUser(authService.getCurrentUser()); final Group save = groupRepository.save(group); @@ -58,7 +65,7 @@ public GroupDto save(GroupDto groupDto) { } @Transactional(readOnly = true) - public Page getAll(Pageable pageable) { + public Page getAllActiveGroups(Pageable pageable) { final Page subreddits = groupRepository.findAllByActiveIsTrue(pageable); return subreddits.map(groupAdapter::toDto); } diff --git a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/utils/ApiUrls.java b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/utils/ApiUrls.java index e6f44e25..cbcc41e6 100644 --- a/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/utils/ApiUrls.java +++ b/backend-implicaction/src/main/java/com/dynonuggets/refonteimplicaction/utils/ApiUrls.java @@ -33,6 +33,7 @@ public class ApiUrls { public static final String CREATE_NO_IMAGE = "/no-image"; public static final String GET_PENDING_GROUP_URI = "/pending"; public static final String ACTIVATE_GROUP_URI = "/activate"; + public static final String ACTIVE_GROUPS = "/active"; public static final String SUBSCRIBE_GROUP = "/{groupName}/subscribe"; // COMMENTS diff --git a/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/adapter/GroupAdapterTest.java b/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/adapter/GroupAdapterTest.java index e816091f..f28169ae 100644 --- a/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/adapter/GroupAdapterTest.java +++ b/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/adapter/GroupAdapterTest.java @@ -4,6 +4,8 @@ import com.dynonuggets.refonteimplicaction.model.FileModel; import com.dynonuggets.refonteimplicaction.model.Group; import com.dynonuggets.refonteimplicaction.model.Post; +import com.dynonuggets.refonteimplicaction.model.User; +import com.dynonuggets.refonteimplicaction.repository.UserRepository; import com.dynonuggets.refonteimplicaction.service.FileService; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -27,6 +29,9 @@ class GroupAdapterTest { @InjectMocks GroupAdapter groupAdapter; + @Mock + UserRepository userRepository; + @Test void should_map_to_model() { // given @@ -34,10 +39,17 @@ void should_map_to_model() { .id(123L) .description("blablabla") .name("blabla") + .userId(1L) + .username("test") + .build(); + + User user = User.builder() + .id(1L) + .username("test") .build(); // when - final Group actual = groupAdapter.toModel(expected); + final Group actual = groupAdapter.toModel(expected, user); // then assertThat(actual.getId()).isEqualTo(expected.getId()); @@ -62,7 +74,7 @@ void should_map_to_dto_with_count_when_model_has_posts() { // then assertThat(actualDto).usingRecursiveComparison() - .ignoringFields("user", "posts", "numberOfPosts", "imageUrl") + .ignoringFields("user", "posts", "numberOfPosts", "imageUrl", "username", "userId") .isEqualTo(expectedModel); assertThat(actualDto.getNumberOfPosts()).isEqualTo(expectedModel.getPosts().size()); @@ -89,7 +101,7 @@ void should_map_to_dto_with_image_url_when_model_has_image() { // then assertThat(actualDto).usingRecursiveComparison() - .ignoringFields("user", "posts", "numberOfPosts", "imageUrl") + .ignoringFields("user", "posts", "numberOfPosts", "imageUrl", "username", "userId") .isEqualTo(expectedModel); assertThat(actualDto.getNumberOfPosts()).isZero(); diff --git a/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/controller/GroupControllerIntegrationTest.java b/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/controller/GroupControllerIntegrationTest.java index 48447070..646c7801 100644 --- a/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/controller/GroupControllerIntegrationTest.java +++ b/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/controller/GroupControllerIntegrationTest.java @@ -1,10 +1,13 @@ package com.dynonuggets.refonteimplicaction.controller; import com.dynonuggets.refonteimplicaction.dto.GroupDto; +import com.dynonuggets.refonteimplicaction.model.User; +import com.dynonuggets.refonteimplicaction.repository.UserRepository; import com.dynonuggets.refonteimplicaction.service.GroupService; import com.google.common.collect.Ordering; import com.google.gson.reflect.TypeToken; import org.junit.jupiter.api.Test; +import org.mockito.Mock; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.data.domain.*; @@ -13,6 +16,7 @@ import java.util.Arrays; import java.util.List; +import java.util.Optional; import static com.dynonuggets.refonteimplicaction.utils.ApiUrls.*; import static java.util.Arrays.asList; @@ -34,6 +38,9 @@ class GroupControllerIntegrationTest extends ControllerIntegrationTestBase { @MockBean GroupService groupService; + @Mock + UserRepository userRepository; + @Test void should_response_forbidden_when_create_subreddit_with_no_authentication() throws Exception { // given @@ -56,7 +63,7 @@ void should_response_forbidden_when_create_subreddit_with_no_authentication() th @Test @WithMockUser - void should_list_all_subreddit_whith_no_authentication() throws Exception { + void should_list_all_subreddit_with_no_authentication() throws Exception { // given final Pageable DEFAULT_PAGEABLE = PageRequest.of(0, 10, Sort.DEFAULT_DIRECTION, "id"); final Page subreddits = new PageImpl<>(asList( @@ -71,10 +78,16 @@ void should_list_all_subreddit_whith_no_authentication() throws Exception { GroupDto.builder().id(14L).build(), GroupDto.builder().id(15L).build() )); - given(groupService.getAll(DEFAULT_PAGEABLE)).willReturn(subreddits); + final User user = User.builder() + .id(1L) + .username("test") + .build(); + + given(groupService.getAllActiveGroups(DEFAULT_PAGEABLE)).willReturn(subreddits); + given(userRepository.findById(any())).willReturn(Optional.of(user)); // when - final ResultActions resultActions = mvc.perform(get(GROUPS_BASE_URI).contentType(APPLICATION_JSON)); + final ResultActions resultActions = mvc.perform(get(GROUPS_BASE_URI + ACTIVE_GROUPS).contentType(APPLICATION_JSON)); // then resultActions.andDo(print()) @@ -92,7 +105,7 @@ void should_list_all_subreddit_whith_no_authentication() throws Exception { } resultActions.andReturn(); - verify(groupService, times(1)).getAll(any()); + verify(groupService, times(1)).getAllActiveGroups(any()); } @Test @@ -103,7 +116,7 @@ void should_response_forbidden_when_listing_all_subreddit_whith_no_authenticatio // then resultActions.andDo(print()).andExpect(status().isForbidden()); - verify(groupService, never()).getAll(any()); + verify(groupService, never()).getAllActiveGroups(any()); } @Test diff --git a/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/service/GroupServiceTest.java b/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/service/GroupServiceTest.java index 56d3c0cb..a5017edb 100644 --- a/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/service/GroupServiceTest.java +++ b/backend-implicaction/src/test/java/com/dynonuggets/refonteimplicaction/service/GroupServiceTest.java @@ -1,12 +1,14 @@ package com.dynonuggets.refonteimplicaction.service; import com.dynonuggets.refonteimplicaction.adapter.GroupAdapter; +import com.dynonuggets.refonteimplicaction.adapter.UserAdapter; import com.dynonuggets.refonteimplicaction.dto.GroupDto; import com.dynonuggets.refonteimplicaction.model.FileModel; import com.dynonuggets.refonteimplicaction.model.Group; import com.dynonuggets.refonteimplicaction.model.User; import com.dynonuggets.refonteimplicaction.repository.FileRepository; import com.dynonuggets.refonteimplicaction.repository.GroupRepository; +import com.dynonuggets.refonteimplicaction.repository.UserRepository; import com.dynonuggets.refonteimplicaction.service.impl.S3CloudServiceImpl; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -23,6 +25,7 @@ import java.util.Arrays; import java.util.List; +import java.util.Optional; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.BDDMockito.given; @@ -46,6 +49,12 @@ class GroupServiceTest { @Mock FileRepository fileRepository; + @Mock + UserRepository userRepository; + + @Mock + UserAdapter userAdapter; + @InjectMocks GroupService groupService; @@ -93,9 +102,15 @@ void should_save_subreddit_with_image() { "test data".getBytes() ); + final User user = User.builder() + .id(1L) + .username("test") + .build(); + given(userRepository.findById(any())).willReturn(Optional.of(user)); + when(cloudService.uploadImage(any())).thenReturn(fileModel); when(fileRepository.save(fileModel)).thenReturn(fileModel); - when(groupAdapter.toModel(any())).thenReturn(sentModel); + when(groupAdapter.toModel(any(), any())).thenReturn(sentModel); when(authService.getCurrentUser()).thenReturn(currentUser); when(groupRepository.save(any())).thenReturn(saveModel); when(groupAdapter.toDto(any())).thenReturn(expectedDto); @@ -136,9 +151,15 @@ void should_save_when_no_image() { .description("Elle est super bien ma description") .build(); - given(groupAdapter.toModel(any())).willReturn(sentModel); + final User user = User.builder() + .id(1L) + .username("test") + .build(); + + given(groupAdapter.toModel(any(), any())).willReturn(sentModel); given(authService.getCurrentUser()).willReturn(currentUser); given(groupRepository.save(any())).willReturn(saveModel); + given(userRepository.findById(any())).willReturn(Optional.of(user)); // when groupService.save(sentDto); @@ -173,10 +194,9 @@ void should_list_all_subreddits() { Pageable pageable = PageRequest.of(first, first * size); Page subredditsPage = new PageImpl<>(groups.subList(0, size - 1)); - given(groupRepository.findAll(any(Pageable.class))).willReturn(subredditsPage); - + given(groupRepository.findAllByActiveIsTrue(any(Pageable.class))).willReturn(subredditsPage); // when - Page actuals = groupService.getAll(pageable); + Page actuals = groupService.getAllActiveGroups(pageable); // then assertThat(actuals.getTotalElements()).isEqualTo(subredditsPage.getTotalElements()); diff --git a/frontend-implicaction/src/app/admin/groups/pending-group-table/pending-group-table.component.html b/frontend-implicaction/src/app/admin/groups/pending-group-table/pending-group-table.component.html index 62ab483d..80e7dcc8 100644 --- a/frontend-implicaction/src/app/admin/groups/pending-group-table/pending-group-table.component.html +++ b/frontend-implicaction/src/app/admin/groups/pending-group-table/pending-group-table.component.html @@ -14,6 +14,7 @@ Nom Description + Administrateur Crée le @@ -21,6 +22,7 @@ {{group.name}} {{group.description}} + {{group.username}} {{group.createdAt}}