diff --git a/src/app/admin/admin.module.ts b/src/app/admin/admin.module.ts index 80f80da23b10c3328a06667601a51d8ac69f2b90..05b87149d0291f9799d6b13cd69d2a8277c301ad 100644 --- a/src/app/admin/admin.module.ts +++ b/src/app/admin/admin.module.ts @@ -2,10 +2,11 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { PanelComponent } from './components/panel/panel.component'; import { ClaimStructureComponent } from './components/claim-structure/claim-structure.component'; +import { DeleteUserComponent } from './components/delete-user/delete-user.component'; import { SharedModule } from '../shared/shared.module'; @NgModule({ - declarations: [PanelComponent, ClaimStructureComponent], + declarations: [PanelComponent, ClaimStructureComponent, DeleteUserComponent], imports: [CommonModule, SharedModule], }) export class AdminModule {} diff --git a/src/app/admin/components/delete-user/delete-user.component.html b/src/app/admin/components/delete-user/delete-user.component.html new file mode 100644 index 0000000000000000000000000000000000000000..5649bff291a72590b0f0f6d65fbce1f30fb3458b --- /dev/null +++ b/src/app/admin/components/delete-user/delete-user.component.html @@ -0,0 +1,22 @@ +<div fxLayout="column" fxLayoutGap="5px" fxLayoutAlign="center center" class="userBlock"> + <h4>Suppression d'utilisateurs</h4> + <div fxLayout="row"> + <input #searchstring (keyup)="(0)" /> + <button (click)="searchUsers(searchstring.value)">Rechercher</button> + </div> + <div class="userList"> + <tr *ngFor="let user of users"> + <td>{{ user.email }}</td> + <td> + <button (click)="toggleDeleteModal(user)">Supprimer</button> + </td> + </tr> + <app-modal-confirmation + *ngIf="userToDelete" + [openned]="deleteModalOpenned" + [content]="'Voulez-vous vraiment supprimer cet utilisateur ? (' + userToDelete.email + ')'" + (closed)="deleteUser(userToDelete, $event)" + ></app-modal-confirmation> + <div *ngIf="users && users.length == 0">Aucun résultat</div> + </div> +</div> diff --git a/src/app/admin/components/delete-user/delete-user.component.scss b/src/app/admin/components/delete-user/delete-user.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..39b7a07412c002ae97dc36db12c0bbee2304561b --- /dev/null +++ b/src/app/admin/components/delete-user/delete-user.component.scss @@ -0,0 +1,8 @@ +.userList { + max-width: 50%; +} + +.userBlock { + max-width: 50%; + margin: 0 auto; +} \ No newline at end of file diff --git a/src/app/admin/components/delete-user/delete-user.component.spec.ts b/src/app/admin/components/delete-user/delete-user.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..4f1ef118955e67f22af84be2d66afc6ab65e42ed --- /dev/null +++ b/src/app/admin/components/delete-user/delete-user.component.spec.ts @@ -0,0 +1,61 @@ +import { HttpClientModule } from '@angular/common/http'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { of } from 'rxjs'; +import { AdminService } from '../../services/admin.service'; + +import { DeleteUserComponent } from './delete-user.component'; + +describe('DeleteUserComponent', () => { + let component: DeleteUserComponent; + let fixture: ComponentFixture<DeleteUserComponent>; + let USERS; + let service; + + beforeEach(async () => { + USERS = [ + {email: "paula@test.com", name: "paula"}, + {email: "jeanpaul@test.com", name: "jeanpaul"}, + {email: "admin@test.com", name: "admin"}, + ]; + await TestBed.configureTestingModule({ + imports: [HttpClientModule], + declarations: [DeleteUserComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(DeleteUserComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + + service = jasmine.createSpyObj(['searchUsers', 'deleteUser']) + component = new DeleteUserComponent(service); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should searchUsers', () => { + let searchString = "paula" + service.searchUsers.and.returnValue(of(USERS.filter(item => item.email.indexOf(searchString) !== -1))); + component.users = USERS; + component.searchUsers(searchString); + expect(component.users.length).toBe(1); + }); + + it('should searchUsers all users', () => { + let searchString = "" + service.searchUsers.and.returnValue(of(USERS.filter(item => item.email.indexOf(searchString) !== -1))); + component.users = USERS; + component.searchUsers(searchString); + expect(component.users.length).toBe(USERS.length); + }); + + it('should delete user', () => { + component.users = USERS; + service.deleteUser.and.returnValue(of(USERS.splice(USERS.findIndex(e => e.email === USERS[0].email),1))); + component.deleteUser(component.users[0]); + expect(component.users.length).toBe(2); + }); +}); diff --git a/src/app/admin/components/delete-user/delete-user.component.ts b/src/app/admin/components/delete-user/delete-user.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..00e5c943bc5b000a1ee540b2efa020a7dfa1e174 --- /dev/null +++ b/src/app/admin/components/delete-user/delete-user.component.ts @@ -0,0 +1,39 @@ +import { Component } from '@angular/core'; +import { User } from '../../../models/user.model'; +import { ProfileService } from '../../../profile/services/profile.service'; +import { AdminService } from '../../services/admin.service'; + +@Component({ + selector: 'app-admin-delete-user', + templateUrl: './delete-user.component.html', + styleUrls: ['./delete-user.component.scss'], +}) +export class DeleteUserComponent { + public users: User[]; + public deleteModalOpenned = false; + public userToDelete: User = null; + + constructor(private adminService: AdminService, private profileService: ProfileService) {} + + public deleteUser(user: User, shouldDelete: boolean): void { + this.toggleDeleteModal(user); + if (shouldDelete) { + this.adminService.deleteUser(user._id).subscribe((data) => { + this.users = this.users.filter((obj) => obj.email !== data.email); + }); + } + } + + public toggleDeleteModal(userToDelete: User): void { + this.userToDelete = userToDelete; + this.deleteModalOpenned = !this.deleteModalOpenned; + } + + public searchUsers(searchString: string): void { + this.adminService.searchUsers(searchString).subscribe((users) => { + this.profileService.getProfile().then((profile) => { + this.users = users.filter((obj) => obj.email != profile.email); + }); + }); + } +} diff --git a/src/app/admin/components/panel/panel.component.html b/src/app/admin/components/panel/panel.component.html index 2d250110650d55fe3ae55e07c6e031cc24cfaecb..783642e9976aa5314289f449e131647f1ace2a45 100644 --- a/src/app/admin/components/panel/panel.component.html +++ b/src/app/admin/components/panel/panel.component.html @@ -1,4 +1,14 @@ -<div fxLayout="column" class="content-container full-screen"> +<div fxLayout="column" fxLayoutGap="20px" class="content-container full-screen"> <div fxLayout="row" fxLayoutAlign="center center"><h1>Administration</h1></div> - <app-admin-claim-structure></app-admin-claim-structure> + <div fxLayout="row" fxLayoutGap="20px" fxLayoutAlign="center center"> + <button (click)="changeActiveFeature(features.pendingStructures)">Gestion structure</button> + <button (click)="changeActiveFeature(features.deleteUsers)">Suppression d'utilisateurs</button> + <button routerLink="/blog/ghost/">Ghost</button> + </div> + <div *ngIf="selectedFeature === features.deleteUsers"> + <app-admin-delete-user></app-admin-delete-user> + </div> + <div *ngIf="selectedFeature === features.pendingStructures"> + <app-admin-claim-structure></app-admin-claim-structure> + </div> </div> diff --git a/src/app/admin/components/panel/panel.component.ts b/src/app/admin/components/panel/panel.component.ts index c4a2164095eadf3a3269fc10d437249c9ad131d1..2fa9821737c1ba5eb9668c35ad32a93d91219a1d 100644 --- a/src/app/admin/components/panel/panel.component.ts +++ b/src/app/admin/components/panel/panel.component.ts @@ -1,11 +1,23 @@ import { Component, OnInit } from '@angular/core'; +import { TestBed } from '@angular/core/testing'; +import { AdminPannelEnum } from '../../../shared/enum/adminPanel.enum'; @Component({ selector: 'app-admin-panel', templateUrl: './panel.component.html', }) export class PanelComponent implements OnInit { + + public features = AdminPannelEnum; + public selectedFeature; + constructor() {} - ngOnInit(): void {} + ngOnInit(): void { + this.selectedFeature = this.features.pendingStructures; + } + + public changeActiveFeature(newFeature: AdminPannelEnum) { + this.selectedFeature = newFeature; + } } diff --git a/src/app/admin/services/admin.service.ts b/src/app/admin/services/admin.service.ts index cdea9a41bafe956e74a11c854f61b50bf173bec9..689fdc66831e08fc0049f84c18842a1d8723054a 100644 --- a/src/app/admin/services/admin.service.ts +++ b/src/app/admin/services/admin.service.ts @@ -1,6 +1,8 @@ import { HttpClient } from '@angular/common/http'; +import { stringify } from '@angular/compiler/src/util'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; +import { User } from '../../models/user.model'; import { DemandAttachment } from '../models/demandAttachment.model'; @Injectable({ @@ -15,6 +17,19 @@ export class AdminService { return this.http.get<DemandAttachment[]>(`${this.baseUrl}/pendingStructures`); } + public getUsers(): Observable<User[]> { + return this.http.get<User[]>(`api/admin/searchUsers`); + } + + public searchUsers(searchString: string): Observable<User[]> { + return this.http.post<User[]>(`api/admin/searchUsers`, { searchString }); + } + + + public deleteUser(id: string): Observable<User> { + return this.http.delete<User>(`api/admin/user/` + id); + } + public acceptStructureClaim( userEmail: string, structureId: number, diff --git a/src/app/map/services/map.service.spec.ts b/src/app/map/services/map.service.spec.ts index e4d405c3fb227f95433c198c2d822075acffa53b..cd06fb3f41abb24d4fd933ea73c71ff3cbd27970 100644 --- a/src/app/map/services/map.service.spec.ts +++ b/src/app/map/services/map.service.spec.ts @@ -33,14 +33,14 @@ describe('MapService', () => { }); it('should get marker', () => { - const marker = service.createMarker(45.764043, 4.835659, 1, 53, '<p>Hello <br/>World !</p>'); - expect(marker).toEqual(service.getMarker(53)); + const marker = service.createMarker(45.764043, 4.835659, 1, "53", '<p>Hello <br/>World !</p>'); + expect(marker).toEqual(service.getMarker("53")); }); it('should not get marker, with missing id', () => { service.createMarker(45.764043, 4.835659, 1, null, '<p>Hello <br/>World !</p>'); - expect(service.getMarker(2)).toEqual(null); + expect(service.getMarker("2")).toEqual(null); }); it('should not get marker, empty', () => { - expect(service.getMarker(2)).toEqual(null); + expect(service.getMarker("2")).toEqual(null); }); }); diff --git a/src/app/shared/components/modal-confirmation/modal-confirmation.component.ts b/src/app/shared/components/modal-confirmation/modal-confirmation.component.ts index a143aa820f4aa0785d96f603b7010f7a6c54bd0f..2232792d2922ad98c9d20f39c8eac152cff867e3 100644 --- a/src/app/shared/components/modal-confirmation/modal-confirmation.component.ts +++ b/src/app/shared/components/modal-confirmation/modal-confirmation.component.ts @@ -1,16 +1,16 @@ -import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { Component, EventEmitter, Input, Output } from '@angular/core'; @Component({ selector: 'app-modal-confirmation', templateUrl: './modal-confirmation.component.html', styleUrls: ['./modal-confirmation.component.scss'], }) -export class ModalConfirmationComponent implements OnInit { - constructor() {} +export class ModalConfirmationComponent { @Input() public openned: boolean; @Input() public content: string; @Output() closed = new EventEmitter<boolean>(); - ngOnInit(): void {} + + constructor() {} public closeModal(value: boolean): void { this.closed.emit(value); diff --git a/src/app/shared/enum/adminPanel.enum.ts b/src/app/shared/enum/adminPanel.enum.ts new file mode 100644 index 0000000000000000000000000000000000000000..39dbc605f5c246238e3378dd4d14de15c4d2ae24 --- /dev/null +++ b/src/app/shared/enum/adminPanel.enum.ts @@ -0,0 +1,4 @@ +export enum AdminPannelEnum { + deleteUsers, + pendingStructures, +} diff --git a/src/app/structure-list/structure-list.component.spec.ts b/src/app/structure-list/structure-list.component.spec.ts index 793f39969e1010251686b75b678a9078b9f60352..f7e967fcd9c65b7f5ce25d22bcf0fb783092abb1 100644 --- a/src/app/structure-list/structure-list.component.spec.ts +++ b/src/app/structure-list/structure-list.component.spec.ts @@ -180,7 +180,7 @@ describe('StructureListComponent', () => { spyOn(component.selectedMarkerId, 'emit'); component.showDetails(structure); expect(component.selectedMarkerId.emit).toHaveBeenCalled(); - expect(component.selectedMarkerId.emit).toHaveBeenCalledWith(structure.id); + expect(component.selectedMarkerId.emit).toHaveBeenCalledWith(structure._id); expect(component.showStructureDetails).toBe(true); expect(component.structure).toBe(structure); }); @@ -197,7 +197,7 @@ describe('StructureListComponent', () => { spyOn(component.displayMapMarkerId, 'emit'); component.handleCardHover(structure); expect(component.displayMapMarkerId.emit).toHaveBeenCalled(); - expect(component.displayMapMarkerId.emit).toHaveBeenCalledWith([structure.id]); + expect(component.displayMapMarkerId.emit).toHaveBeenCalledWith([structure._id]); }); it('should emit undefined id structure to remove map marker', () => {