continuation de la partie admin

This commit is contained in:
MiharyR 2021-11-13 20:44:12 +01:00
parent de939b47f1
commit 91171a3765
35 changed files with 840 additions and 162 deletions

View file

@ -75,26 +75,22 @@
</td>
</ng-container>
<!-- Delete Column -->
<ng-container matColumnDef="delete">
<th mat-header-cell *matHeaderCellDef> Supprimer </th>
<!-- Actions Column -->
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef> Actions </th>
<td mat-cell *matCellDef="let advert">
<button mat-icon-button (click)="onVisualizeImages(advert)">
<mat-icon> insert_photo</mat-icon>
</button>
<button mat-icon-button (click)="onVisualizeInfo(advert)">
<mat-icon>aspect_ratio</mat-icon>
</button>
<button mat-icon-button (click)="onDelete(advert)">
<mat-icon>delete</mat-icon>
</button>
</td>
</ng-container>
<!-- Visualisation Column -->
<ng-container matColumnDef="visualisation">
<th mat-header-cell *matHeaderCellDef> Visualisation </th>
<td mat-cell *matCellDef="let advert">
<button mat-icon-button (click)="onVisualize(advert)">
<mat-icon>aspect_ratio</mat-icon>
</button>
</td>
</ng-container>
<!-- Directives -->
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>

View file

@ -9,6 +9,7 @@ import {MatTableDataSource} from "@angular/material/table";
import {Advert} from "../../../utils/interfaces/advert";
import {PopupVisualizeAdAdminComponent} from "../popup-visualize-ad-admin/popup-visualize-ad-admin.component";
import {PopupDeleteAdAdminComponent} from "../popup-delete-ad-admin/popup-delete-ad-admin.component";
import {PopupVisualizeImagesAdminComponent} from "../popup-visualize-images-admin/popup-visualize-images-admin.component";
@ -19,7 +20,7 @@ import {PopupDeleteAdAdminComponent} from "../popup-delete-ad-admin/popup-delete
})
export class PageAdListAdminComponent implements AfterViewInit
{
displayedColumns: string[] = [ 'title', 'advertiser', 'tags', 'createdAt', 'updatedAt', 'views', 'isVisible', 'delete', 'visualisation' ];
displayedColumns: string[] = [ 'title', 'advertiser', 'tags', 'createdAt', 'updatedAt', 'views', 'isVisible', 'actions' ];
dataSource ;
@ViewChild(MatSort) sort: MatSort;
@ViewChild(MatPaginator) paginator: MatPaginator;
@ -49,7 +50,25 @@ export class PageAdListAdminComponent implements AfterViewInit
}
onVisualize(advert: Advert): void
onVisualizeImages(advert: Advert)
{
const config = {
width: '30%',
height: '90%',
data: {
images: advert.images,
width: 300,
height: 800,
}
};
this.dialog
.open(PopupVisualizeImagesAdminComponent, config)
.afterClosed()
.subscribe(retour => {});
}
onVisualizeInfo(advert: Advert): void
{
const config = {
width: '50%',
@ -82,7 +101,7 @@ export class PageAdListAdminComponent implements AfterViewInit
this.dataSource.data.splice(index, 1);
this.dataSource.data = this.dataSource.data;
this.dataSource = this.dataSource;
message = "L'annonce a bien été supprimée ✔" ;
message = advert.title + " a bien été supprimée ✔" ;
}
this.snackBar.open( message, "", config);
});

View file

@ -15,11 +15,9 @@
<!-- Images -->
<div class="row myRow">
<div class="col-6 myLabel" style="padding-top: 10px"> Images: </div>
<div class="col-6">
<button mat-icon-button (click)="onVisualizeImages(advert.images)">
<mat-icon>aspect_ratio</mat-icon>
</button>
<div class="col-6 myLabel"> Images: </div>
<div class="col-6 myValue" style="border-left: solid 1px #e6e6e6">
<div *ngFor="let image of advert.images"> {{image.url}} </div>
</div>
</div>
@ -27,7 +25,7 @@
<div class="row myRow">
<div class="col-6 myLabel"> Tags: </div>
<div class="col-6 myValue" style="border-left: solid 1px #e6e6e6">
<div *ngFor="let tag of advert.tags"> {{tag}} </div>
<div *ngFor="let tag of advert.tags"> {{tag}} </div>
</div>
</div>

View file

@ -1,8 +1,7 @@
import {Component, Inject, OnInit} from '@angular/core';
import {Advert} from "../../../utils/interfaces/advert";
import {MAT_DIALOG_DATA, MatDialog, MatDialogRef} from "@angular/material/dialog";
import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";
import {ThemeService} from "../../../utils/services/theme/theme.service";
import {PopupVisualizeImagesAdminComponent} from "../popup-visualize-images-admin/popup-visualize-images-admin.component";
@ -15,34 +14,13 @@ export class PopupVisualizeAdAdminComponent implements OnInit
{
advert: Advert;
constructor( public dialogRef: MatDialogRef<PopupVisualizeAdAdminComponent>,
@Inject(MAT_DIALOG_DATA) public data,
public themeService: ThemeService,
public dialog: MatDialog ) { }
public themeService: ThemeService ) { }
ngOnInit(): void
{
this.advert = this.data.advert;
}
onVisualizeImages(images: any[])
{
const config = {
width: '400px',
height: '950px',
data: {
images: images,
width: 300,
height: 800,
}
};
this.dialog
.open(PopupVisualizeImagesAdminComponent, config)
.afterClosed()
.subscribe(retour => {});
}
}

View file

@ -21,8 +21,8 @@ export class PopupVisualizeImagesAdminComponent implements OnInit
ngOnInit(): void
{
this.width = this.data.width;
this.height = this.data.height;
this.width = this.data.width*0.8;
this.height = this.data.height*0.8;
for(let couple of this.data.images)
{

View file

@ -41,6 +41,7 @@ export class PopupUpdateAdminComponent implements OnInit
isAccepted: admin0.isisAccepted,
createdAt: admin0.createdAt,
updatedAt: admin0.updatedAt,
lastConnexion: admin0.lastConnexion
};
for(let interest of admin0.interests) this.adminCopy.interests.push(interest);
}
@ -51,10 +52,8 @@ export class PopupUpdateAdminComponent implements OnInit
this.checkField();
if(!this.hasError)
{
const data = {
user: this.adminCopy,
newPassword: this.newPassword
};
if(this.changePassword) this.adminCopy.hashPass = this.hashage(this.newPassword);
const data = { user: this.adminCopy };
// VRAI CODE: envoie au back ...
@ -104,4 +103,17 @@ export class PopupUpdateAdminComponent implements OnInit
{
this.adminCopy.interests = myInterets;
}
// Fonction de hashage (faible)
hashage(input: string): string
{
let hash = 0;
for (let i = 0; i < input.length; i++) {
let ch = input.charCodeAt(i);
hash = ((hash << 5) - hash) + ch;
hash = hash & hash;
}
return hash.toString();
}
}

View file

@ -0,0 +1,43 @@
<mat-form-field class="example-chip-list" appearance="fill">
<!-- ------------------------------------------------------------------------------------ -->
<mat-label>Tags</mat-label>
<!-- ------------------------------------------------------------------------------------ -->
<mat-chip-list #chipList aria-label="Fruit selection">
<mat-chip
*ngFor="let interest of myInterests"
[selectable]="selectable"
[removable]="removable"
(removed)="remove(interest)">
{{interest}}
<button matChipRemove *ngIf="removable">
<mat-icon>cancel</mat-icon>
</button>
</mat-chip>
<input
placeholder="Tapez un tag et pressez 'Entré' pour l'inserer"
#tagInput
[formControl]="formControl"
[matAutocomplete]="auto"
[matChipInputFor]="chipList"
[matChipInputSeparatorKeyCodes]="separatorKeysCodes"
(matChipInputTokenEnd)="add($event)">
</mat-chip-list>
<!-- ------------------------------------------------------------------------------------ -->
<mat-autocomplete #auto="matAutocomplete" (optionSelected)="selected($event)">
<mat-option *ngFor="let interest of filteredInterests | async" [value]="interest">
{{interest}}
</mat-option>
</mat-autocomplete>
<!-- ------------------------------------------------------------------------------------ -->
</mat-form-field>

View file

@ -0,0 +1,3 @@
mat-form-field {
width: 100%;
}

View file

@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { InputInterestsAdminComponent } from './input-interests-admin.component';
describe('InputInterestsAdminComponent', () => {
let component: InputInterestsAdminComponent;
let fixture: ComponentFixture<InputInterestsAdminComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ InputInterestsAdminComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(InputInterestsAdminComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View file

@ -0,0 +1,81 @@
import {Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild} from '@angular/core';
import {COMMA, ENTER} from "@angular/cdk/keycodes";
import {FormControl} from "@angular/forms";
import {Observable} from "rxjs";
import {FictitiousDatasService} from "../../../utils/services/fictitiousDatas/fictitious-datas.service";
import {MessageService} from "../../../utils/services/message/message.service";
import {map, startWith} from "rxjs/operators";
import {MatChipInputEvent} from "@angular/material/chips";
import {MatAutocompleteSelectedEvent} from "@angular/material/autocomplete";
@Component({
selector: 'app-input-interests-admin',
templateUrl: './input-interests-admin.component.html',
styleUrls: ['./input-interests-admin.component.scss']
})
export class InputInterestsAdminComponent implements OnInit
{
selectable = true;
removable = true;
separatorKeysCodes: number[] = [ENTER, COMMA];
formControl = new FormControl();
filteredInterests: Observable<string[]>;
@Input() myInterests: string[] = [];
allInterests: string[] = [];
@Output() eventEmitter = new EventEmitter<string[]>();
@ViewChild('tagInput') tagInput: ElementRef<HTMLInputElement>;
constructor( private fictitiousDatasService: FictitiousDatasService,
private messageService: MessageService ) {}
ngOnInit(): void
{
this.filteredInterests = this.formControl.valueChanges.pipe(
startWith(null),
map((fruit: string | null) => fruit ? this._filter(fruit) : this.allInterests.slice()));
// --- FAUX CODE ---
this.allInterests = this.fictitiousDatasService.getTags();
this.allInterests.sort();
}
add(event: MatChipInputEvent): void
{
const value = (event.value || '').trim();
if (value && (this.allInterests.indexOf(value) !== -1))
{
this.myInterests.push(value);
event.chipInput!.clear();
this.formControl.setValue(null);
this.eventEmitter.emit(this.myInterests);
}
}
remove(tag: string): void
{
const index = this.myInterests.indexOf(tag);
if (index >= 0) this.myInterests.splice(index, 1);
this.eventEmitter.emit(this.myInterests);
}
selected(event: MatAutocompleteSelectedEvent): void
{
this.myInterests.push(event.option.viewValue);
this.tagInput.nativeElement.value = '';
this.formControl.setValue(null);
this.eventEmitter.emit(this.myInterests);
}
private _filter(value: string): string[]
{
const filterValue = value.toLowerCase();
return this.allInterests.filter(fruit => fruit.toLowerCase().includes(filterValue));
}
}

View file

@ -30,8 +30,8 @@
</div>
<div class="btnAjouterContainer">
<button mat-button class="btnAjouter" (click)="onAddAdmin()">
<mat-icon>add_circle</mat-icon> Ajouter un admin
<button mat-button class="btnAjouter" (click)="onCreateUser()">
<mat-icon>add_circle</mat-icon> Ajouter un utilisateur
</button>
</div>
@ -60,13 +60,30 @@
<ng-container matColumnDef="dateOfBirth">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Date de naissance </th>
<td mat-cell *matCellDef="let user">
{{ user.dateOfBirth | date:'dd/LL/YYYY à HH:mm:ss' }}
{{ user.dateOfBirth | date:'dd/LL/YYYY' }}
</td>
</ng-container>
<!-- Age Column -->
<ng-container matColumnDef="age">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Âge </th>
<td mat-cell *matCellDef="let user">
{{user.age}}
</td>
</ng-container>
<!-- Sexe Column -->
<ng-container matColumnDef="sexe">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Sexe </th>
<td mat-cell *matCellDef="let user">
<span *ngIf="user.gender === 'man'">Homme</span>
<span *ngIf="user.gender === 'woman'">Femme</span>
</td>
</ng-container>
<!-- Interests Column -->
<ng-container matColumnDef="interests">
<th mat-header-cell *matHeaderCellDef> Centre d'intérêts </th>
<th mat-header-cell *matHeaderCellDef> Centres d'intérêt </th>
<td mat-cell *matCellDef="let user">
<span *ngFor="let interest of user.interests; let isLast = last;">
<span *ngIf="!isLast"> {{interest}}, </span>
@ -83,11 +100,11 @@
</td>
</ng-container>
<!-- UpdatedAt Column -->
<ng-container matColumnDef="updatedAt">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Dernière modification </th>
<!-- LastConnexion Column -->
<ng-container matColumnDef="lastConnexion">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Dernière connexion </th>
<td mat-cell *matCellDef="let user">
{{ user.updatedAt | date:'dd/LL/YYYY à HH:mm:ss' }}
{{ user.lastConnexion | date:'dd/LL/YYYY à HH:mm:ss' }}
</td>
</ng-container>
@ -101,22 +118,15 @@
</ng-container>
<!-- Delete Column -->
<ng-container matColumnDef="delete">
<th mat-header-cell *matHeaderCellDef> Supprimer </th>
<td mat-cell *matCellDef="let user">
<button mat-icon-button (click)="onDelete(user)">
<mat-icon>delete</mat-icon>
</button>
</td>
</ng-container>
<!-- Visualisation Column -->
<ng-container matColumnDef="visualisation">
<th mat-header-cell *matHeaderCellDef> Visualisation </th>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef> Actions </th>
<td mat-cell *matCellDef="let user">
<button mat-icon-button (click)="onVisualize(user)">
<mat-icon>aspect_ratio</mat-icon>
</button>
<button mat-icon-button (click)="onDelete(user)">
<mat-icon>delete</mat-icon>
</button>
</td>
</ng-container>

View file

@ -18,7 +18,7 @@
.btnAjouterContainer {
float:left;
margin-left: 67%;
margin-left: 65%;
padding-top: 20px;
}

View file

@ -9,6 +9,7 @@ import {MatTableDataSource} from "@angular/material/table";
import {User} from "../../../utils/interfaces/user";
import {PopupVisualizeUserComponent} from "../popup-visualize-user/popup-visualize-user.component";
import {PopupDeleteUserComponent} from "../popup-delete-user/popup-delete-user.component";
import {PopupCreateUserComponent} from "../popup-create-user/popup-create-user.component";
@ -20,11 +21,11 @@ import {PopupDeleteUserComponent} from "../popup-delete-user/popup-delete-user.c
export class PageUserListComponent implements AfterViewInit
{
displayedColumns: string[];
displayedColumnsUser: string[] = [ 'login', 'mail', 'dateOfBirth', 'interests', 'createdAt', 'updatedAt', 'delete', 'visualisation' ];
displayedColumnsAdvertiser: string[] = [ 'login', 'mail', 'createdAt', 'updatedAt', 'isAccepted', 'delete', 'visualisation' ];
displayedColumnsAdmin: string[] = [ 'login', 'mail', 'createdAt', 'updatedAt', 'delete', 'visualisation' ];
displayedColumnsUser: string[] = [ 'login', 'mail', 'dateOfBirth', 'age', 'sexe', 'interests', 'createdAt', 'lastConnexion', 'actions' ];
displayedColumnsAdvertiser: string[] = [ 'login', 'mail', 'createdAt', 'lastConnexion', 'isAccepted', 'actions' ];
displayedColumnsAdmin: string[] = [ 'login', 'mail', 'createdAt', 'lastConnexion', 'actions' ];
tabUser: User[] = [];
tabUser: any[] = [];
tabAdvertiser: User[] = [];
tabAdmin: User[] = [];
@ -47,9 +48,11 @@ export class PageUserListComponent implements AfterViewInit
this.tabAdvertiser = this.fictitiousDatasService.getTabAdvertiser(8);
this.tabAdmin = this.fictitiousDatasService.getTabAdmin(4);
for(const user of this.tabUser) user.age = this.getAge(user.dateOfBirth);
this.displayedColumns = this.displayedColumnsUser;
this.dataSource = new MatTableDataSource<User>(this.tabUser);
this.dataSource = new MatTableDataSource(this.tabUser);
this.dataSource.sort = this.sort;
this.dataSource.paginator = this.paginator;
this.dataSource = this.dataSource;
@ -114,14 +117,36 @@ export class PageUserListComponent implements AfterViewInit
this.dataSource.data.splice(index, 1);
this.dataSource.data = this.dataSource.data;
this.dataSource = this.dataSource;
message = "L'annonce a bien été supprimée ✔" ;
message = user.login + " a bien été supprimée ✔" ;
}
this.snackBar.open( message, "", config);
});
}
onAddAdmin(): void
{
onCreateUser(): void
{
const config = { width: '50%' };
this.dialog
.open(PopupCreateUserComponent, config)
.afterClosed()
.subscribe( retour => {
const config = { duration: 1000, panelClass: "custom-class" };
if((retour === null) || (retour === undefined)) {
this.snackBar.open( "Opération annulée", "", config);
}
else {
this.snackBar.open( "L'utilisateur a bien été créé", "", config);
}
});
}
getAge(date: Date): number
{
const diff = Date.now() - date.getTime();
const age = new Date(diff);
return Math.abs(age.getUTCFullYear() - 1970);
}
}

View file

@ -0,0 +1,145 @@
<div class="myContainer">
<!-- Rôle -->
<div class="matRadioGroupContainer">
<mat-radio-group [(ngModel)]="user.role.name" (change)="hasError=false; errorMessage = '';">
<mat-radio-button value="user"> Utilisateur </mat-radio-button><br>
<mat-radio-button value="advertiser"> Annonceur </mat-radio-button><br>
<mat-radio-button value="admin"> Admin </mat-radio-button>
</mat-radio-group>
</div><br>
<!-- divider -->
<mat-divider></mat-divider><br>
<!-- userBlock or advertiserOrAdminBlock -->
<div *ngIf="user.role.name === 'user'; then userBlock"></div>
<div *ngIf="(user.role.name === 'advertiser' || user.role.name === 'admin'); then advertiserOrAdminBlock"></div>
<!-- divider -->
<mat-divider *ngIf="user.role.name !== ''" style="margin-top: 10px;"></mat-divider><br>
<!-- Error -->
<div *ngIf="hasError" style="text-align: center; margin-bottom: 20px;">
<span class="mat-error">{{errorMessage}}</span>
</div>
<!-- Boutons -->
<div style="width: 100%; text-align: right">
<button mat-button (click)="this.dialogRef.close(null)"> Annuler </button>
<button mat-button (click)="onEnregistrer()" [disabled]="user.role.name === ''" > Enregistrer </button>
</div>
</div>
<!-- ------------------------------------------------------------------------------------------------------------------- -->
<!-- userBlock -->
<ng-template #userBlock>
<!-- photo de profil -->
<div style="text-align: center">
<img [src]="user.profilePictureUrl" onerror="this.onerror=null; this.src='assets/profil.png'"><br>
<input title="lien vers image" type="text" [(ngModel)]="user.profilePictureUrl" style="width: 90%">
</div><br>
<div class="row">
<!-- Colonne gauche -->
<div class="col-4 leftCol">
<!-- Email -->
<mat-form-field appearance="fill">
<mat-label>Email</mat-label>
<input matInput type="email" [(ngModel)]="user.mail" required>
</mat-form-field><br>
<!-- Login -->
<mat-form-field appearance="fill">
<mat-label>Login</mat-label>
<input matInput type="text" [(ngModel)]="user.login" required>
</mat-form-field><br>
<!-- Mot de passe -->
<mat-form-field appearance="fill">
<mat-label>Mot de passe</mat-label>
<input matInput type="password" [(ngModel)]="password" required>
</mat-form-field><br>
<!-- Confirmation mot de passe -->
<mat-form-field appearance="fill">
<mat-label>Confirmation mot de passe</mat-label>
<input matInput type="password" [(ngModel)]="confirmPassword" required>
</mat-form-field>
</div>
<!-- Colonne droite -->
<div class="col-8">
<!-- dateOfBirth -->
<mat-form-field appearance="fill">
<mat-label>Date de naissance</mat-label>
<input matInput type="date"
[ngModel] ="user.dateOfBirth | date:'yyyy-MM-dd'"
(ngModelChange)="user.dateOfBirth = $event">
</mat-form-field><br>
<!-- gender -->
<mat-radio-group [(ngModel)]="user.gender">
<mat-radio-button value="man"> Homme </mat-radio-button>&nbsp; &nbsp;
<mat-radio-button value="woman"> Femme </mat-radio-button>
</mat-radio-group>
<br><br>
<!-- interests -->
<app-input-interests-admin
[myInterests]="user.interests"
(eventEmitter)="onEventInputInterests($event)"></app-input-interests-admin>
</div>
</div>
</ng-template>
<!-- ------------------------------------------------------------------------------------------------------------------- -->
<!-- advertiserOrAdminBlock -->
<ng-template #advertiserOrAdminBlock>
<div style="text-align: center">
<!-- photo de profil -->
<div style="text-align: center">
<img [src]="user.profilePictureUrl" onerror="this.onerror=null; this.src='assets/profil.png'"><br>
<input title="lien vers image" type="text" [(ngModel)]="user.profilePictureUrl" style="width: 90%">
</div><br>
<!-- email -->
<mat-form-field appearance="fill">
<mat-label>Email</mat-label>
<input matInput type="text" [(ngModel)]="user.mail">
</mat-form-field><br>
<!-- login -->
<mat-form-field appearance="fill">
<mat-label>Login</mat-label>
<input matInput type="text" [(ngModel)]="user.login">
</mat-form-field><br>
<!-- mot de passe -->
<mat-form-field appearance="fill">
<mat-label>Mot de passe</mat-label>
<input matInput type="password" [(ngModel)]="password">
</mat-form-field><br>
<!-- confirmation mot de passe -->
<mat-form-field appearance="fill">
<mat-label>Confirmation nouveau mot de passe</mat-label>
<input matInput type="password" [(ngModel)]="confirmPassword">
</mat-form-field>
</div>
</ng-template>

View file

@ -0,0 +1,16 @@
.myContainer {
font-size: small;
}
img {
margin: 0px 0px 10px 0px;
width: 10%;
height: 10%;
border: solid 2px black;
border-radius: 50%;
font-size: xxx-large;
}
.leftCol {
border-right: solid 1px #dcdcdc;
}

View file

@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { PopupCreateUserComponent } from './popup-create-user.component';
describe('PopupCreateUserComponent', () => {
let component: PopupCreateUserComponent;
let fixture: ComponentFixture<PopupCreateUserComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ PopupCreateUserComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(PopupCreateUserComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View file

@ -0,0 +1,121 @@
import {Component, Inject, OnInit} from '@angular/core';
import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";
import {User} from "../../../utils/interfaces/user";
@Component({
selector: 'app-popup-create-user',
templateUrl: './popup-create-user.component.html',
styleUrls: ['./popup-create-user.component.scss']
})
export class PopupCreateUserComponent implements OnInit
{
user: User;
hasError: boolean = false;
errorMessage: string = "";
password: string = "";
confirmPassword: string = "";
constructor( public dialogRef: MatDialogRef<PopupCreateUserComponent>,
@Inject(MAT_DIALOG_DATA) public data ) { }
// Initialise l'utilisateur qui va être créé
ngOnInit(): void
{
this.user = {
_id: "",
login: "",
hashPass: "",
mail: "",
role: {
name: "",
permission: 0,
},
profilePictureUrl: "",
dateOfBirth: null,
gender: "man",
interests: [],
isActive: false,
isAccepted: false,
createdAt: new Date(),
updatedAt: new Date(),
lastConnexion: new Date()
};
}
// Crée le nouvel utilisateur
onEnregistrer(): void
{
this.checkField();
if(!this.hasError)
{
this.user.hashPass = this.hashage(this.password);
this.dialogRef.close(this.user);
// VRAI CODE ...
}
}
// Check les champs saisies par l'utilisateur
checkField(): void
{
if(this.user.login.length === 0) {
this.errorMessage = "Veuillez remplir le champ 'login'.";
this.hasError = true;
}
else if(this.user.mail.length === 0) {
this.errorMessage = "Veuillez remplir le champ 'email'.";
this.hasError = true;
}
else if(!this.isValidEmail(this.user.mail)) {
this.errorMessage = "Email invalide";
this.hasError = true;
}
else if(this.password.length === 0) {
this.errorMessage = "Veuillez remplir le champ 'mot de passe'.";
this.hasError = true;
}
else if(this.password !== this.confirmPassword) {
this.errorMessage = "Le mot de passe est différent de sa confirmation.";
this.hasError = true;
}
else {
this.errorMessage = "" ;
this.hasError = false;
}
}
// Indique si email a bien le format d'un email
isValidEmail(email): boolean
{
let re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return re.test(email);
}
// Récupère la liste des centres d'intérets (car celle-ci est remplie à l'aide d'un component intermédiaire)
onEventInputInterests(myInterets: string[]): void
{
this.user.interests = myInterets;
}
// Fonction de hashage (faible)
hashage(input: string): string
{
let hash = 0;
for (let i = 0; i < input.length; i++) {
let ch = input.charCodeAt(i);
hash = ((hash << 5) - hash) + ch;
hash = hash & hash;
}
return hash.toString();
}
}

View file

@ -1 +1,8 @@
<p>popup-delete-user works!</p>
<mat-dialog-content class="mat-typography">
Êtes-vous sûr de vouloir supprimer <i>{{user.login}}</i> ?
</mat-dialog-content>
<mat-dialog-actions align="end">
<button mat-button (click)="dialogRef.close();">Annuler</button>
<button mat-button (click)="onValidate()" cdkFocusInitial>Valider</button>
</mat-dialog-actions>

View file

@ -1,15 +1,47 @@
import { Component, OnInit } from '@angular/core';
import {Component, Inject, OnInit} from '@angular/core';
import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";
import {MessageService} from "../../../utils/services/message/message.service";
@Component({
selector: 'app-popup-delete-user',
templateUrl: './popup-delete-user.component.html',
styleUrls: ['./popup-delete-user.component.scss']
})
export class PopupDeleteUserComponent implements OnInit {
export class PopupDeleteUserComponent implements OnInit
{
user;
constructor() { }
constructor( public dialogRef: MatDialogRef<PopupDeleteUserComponent>,
@Inject(MAT_DIALOG_DATA) public data,
private messageService: MessageService ) { }
ngOnInit(): void {
ngOnInit(): void
{
this.user = this.data.user;
}
onValidate(): void
{
// --- FAUX CODE ---
this.dialogRef.close(true);
// --- VRAI CODE ---
/*
this.messageService
.sendMessage("user/delete", {"advert": this.advert})
.subscribe( retour => {
if(retour.status === "error") {
console.log(retour);
this.dialogRef.close();
}
else {
this.dialogRef.close(true);
}
});
*/
}
}

View file

@ -1 +1,76 @@
<p>popup-visualize-user works!</p>
<div class="myContainer">
<!-- Photo de profil -->
<div style="text-align: center">
<img [src]="user.profilePictureUrl"
onerror="this.onerror=null; this.src='assets/profil.png'">
</div>
<!-- login -->
<div class="row myRow">
<div class="col-6 myLabel">Login:</div>
<div class="col-6 myValue"> {{user.login}} </div>
</div>
<!-- mail -->
<div class="row myRow">
<div class="col-6 myLabel">Mail:</div>
<div class="col-6 myValue"> {{user.mail}} </div>
</div>
<div *ngIf="user.role.name === 'user'">
<!-- dateOfBirth -->
<div class="row myRow">
<div class="col-6 myLabel">Date de naissance:</div>
<div class="col-6 myValue">{{ user.dateOfBirth | date:'dd/LL/YYYY' }}</div>
</div>
<!-- age -->
<div class="row myRow">
<div class="col-6 myLabel">Âge:</div>
<div class="col-6 myValue">{{user.age}}</div>
</div>
<!-- gender -->
<div class="row myRow">
<div class="col-6 myLabel">Sexe:</div>
<div class="col-6 myValue">
<span *ngIf="user.gender==='man'"> Homme </span>
<span *ngIf="user.gender==='woman'"> Femme </span>
</div>
</div>
<!-- interets -->
<div class="row myRow">
<div class="col-6 myLabel">Centres d'intérêt:</div>
<div class="col-6 myValue" style="border-left: solid 1px #e6e6e6">
<div *ngFor="let interest of user.interests">• {{interest}}</div>
</div>
</div>
<!-- createdAt -->
<div class="row myRow">
<div class="col-6 myLabel">Date de création:</div>
<div class="col-6 myValue">{{ user.createdAt | date:'dd/LL/YYYY' }}</div>
</div>
</div>
<!-- Role -->
<div class="row myRow">
<div class="col-6 myLabel">Rôle:</div>
<div class="col-6 myValue">
<span *ngIf="user.role.name === 'user'">Utilisateur</span>
<span *ngIf="user.role.name === 'advertiser'">Annonceur</span>
<span *ngIf="user.role.name === 'admin'">Admin</span>
</div>
</div>
<br>
<!-- boutons -->
<div style="text-align: center">
<button mat-button (click)="this.dialogRef.close(null)"> Fermer </button>
</div>
</div>

View file

@ -0,0 +1,29 @@
.myContainer {
font-size: small;
}
img {
margin: 0px 0px 10px 0px;
width: 5vw;
height: 5vw;
border: solid 2px black;
border-radius: 50%;
font-size: xxx-large;
}
.myRow {
margin: 15px 0px 15px 0px;
}
.myLabel {
text-align: right;
padding: 0px 5px 0px 0px;
margin: 0px;
font-weight: bold;
}
.myValue {
text-align: left;
padding: 0px 0px 0px 5px;
margin: 0px;
}

View file

@ -1,15 +1,23 @@
import { Component, OnInit } from '@angular/core';
import {Component, Inject, OnInit} from '@angular/core';
import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";
@Component({
selector: 'app-popup-visualize-user',
templateUrl: './popup-visualize-user.component.html',
styleUrls: ['./popup-visualize-user.component.scss']
})
export class PopupVisualizeUserComponent implements OnInit {
export class PopupVisualizeUserComponent implements OnInit
{
user;
constructor() { }
constructor( public dialogRef: MatDialogRef<PopupVisualizeUserComponent>,
@Inject(MAT_DIALOG_DATA) public data ) { }
ngOnInit(): void {
ngOnInit(): void
{
this.user = this.data.user;
}
}

View file

@ -1,4 +1,4 @@
<mat-form-field class="example-chip-list" appearance="fill" style="font-size: small">
<mat-form-field class="example-chip-list" appearance="fill">
<!-- ------------------------------------------------------------------------------------ -->

View file

@ -1,3 +1,16 @@
mat-form-field {
width: 100%;
font-size: small;
}
mat-chip-list {
font-size: small;
}
mat-chip {
font-size: small;
}
input {
font-size: small;
}

View file

@ -74,33 +74,22 @@
</td>
</ng-container>
<!-- Update Column -->
<ng-container matColumnDef="update">
<th mat-header-cell *matHeaderCellDef> Modifier </th>
<!-- Actions Column -->
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef> Actions </th>
<td mat-cell *matCellDef="let advert">
<button mat-icon-button (click)="onVisualizeImages(advert)">
<mat-icon> insert_photo</mat-icon>
</button>
<button mat-icon-button (click)="onUpdate(advert)">
<mat-icon>settings</mat-icon>
</button>
</td>
</ng-container>
<!-- Delete Column -->
<ng-container matColumnDef="delete">
<th mat-header-cell *matHeaderCellDef> Supprimer </th>
<td mat-cell *matCellDef="let advert">
<button mat-icon-button (click)="onDelete(advert)">
<mat-icon>delete</mat-icon>
</button>
</td>
</ng-container>
<!-- Visualisation Column -->
<ng-container matColumnDef="visualisation">
<th mat-header-cell *matHeaderCellDef> Visualisation </th>
<td mat-cell *matCellDef="let advert">
<button mat-icon-button (click)="onVisualize(advert)">
<mat-icon>aspect_ratio</mat-icon>
</button>
<button mat-icon-button (click)="onDelete(advert)">
<mat-icon>delete</mat-icon>
</button>
</td>
</ng-container>

View file

@ -10,6 +10,7 @@ import {MatSnackBar} from "@angular/material/snack-bar";
import {PopupDeleteAdAdvertiserComponent} from "../popup-delete-ad-advertiser/popup-delete-ad-advertiser.component";
import {PopupVisualizeAdAdvertiserComponent} from "../popup-visualize-ad-advertiser/popup-visualize-ad-advertiser.component";
import {MatPaginator} from "@angular/material/paginator";
import {PopupVisualizeImagesAdvertiserComponent} from "../popup-visualize-images-advertiser/popup-visualize-images-advertiser.component";
@ -20,7 +21,7 @@ import {MatPaginator} from "@angular/material/paginator";
})
export class PageAdListAdvertiserComponent implements AfterViewInit
{
displayedColumns: string[] = [ 'title', 'tags', 'createdAt', 'updatedAt', 'views', 'isVisible', 'update', 'delete', 'visualisation' ];
displayedColumns: string[] = [ 'title', 'tags', 'createdAt', 'updatedAt', 'views', 'isVisible', 'actions' ];
dataSource ;
@ViewChild(MatSort) sort: MatSort;
@ViewChild(MatPaginator) paginator: MatPaginator;
@ -50,6 +51,24 @@ export class PageAdListAdvertiserComponent implements AfterViewInit
}
onVisualizeImages(advert: Advert)
{
const config = {
width: '30%',
height: '90%',
data: {
images: advert.images,
width: 300,
height: 800,
}
};
this.dialog
.open(PopupVisualizeImagesAdvertiserComponent, config)
.afterClosed()
.subscribe(retour => {});
}
onVisualize(advert: Advert): void
{
const config = {
@ -140,7 +159,7 @@ export class PageAdListAdvertiserComponent implements AfterViewInit
this.dataSource.data.splice(index, 1);
this.dataSource.data = this.dataSource.data;
this.dataSource = this.dataSource;
message = "L'annonce a bien été supprimée ✔" ;
message = advert.title + " a bien été supprimée ✔" ;
}
this.snackBar.open( message, "", config);
});

View file

@ -9,11 +9,9 @@
<!-- Images -->
<div class="row myRow">
<div class="col-6 myLabel" style="padding-top: 10px"> Images: </div>
<div class="col-6">
<button mat-icon-button (click)="onVisualizeImages(advert.images)">
<mat-icon>aspect_ratio</mat-icon>
</button>
<div class="col-6 myLabel"> Images: </div>
<div class="col-6 myValue" style="border-left: solid 1px #e6e6e6">
<div *ngFor="let image of advert.images"> {{image.url}} </div>
</div>
</div>

View file

@ -2,7 +2,6 @@ import {Component, Inject, OnInit} from '@angular/core';
import {ThemeService} from "../../../utils/services/theme/theme.service";
import {MAT_DIALOG_DATA, MatDialog, MatDialogRef} from "@angular/material/dialog";
import {Advert} from "../../../utils/interfaces/advert";
import {PopupVisualizeImagesAdvertiserComponent} from "../popup-visualize-images-advertiser/popup-visualize-images-advertiser.component";
@ -15,34 +14,14 @@ export class PopupVisualizeAdAdvertiserComponent implements OnInit
{
advert: Advert;
constructor( public dialogRef: MatDialogRef<PopupVisualizeAdAdvertiserComponent>,
@Inject(MAT_DIALOG_DATA) public data,
public themeService: ThemeService,
public dialog: MatDialog ) { }
ngOnInit(): void
{
this.advert = this.data.advert;
}
onVisualizeImages(images: any[])
{
const config = {
width: '400px',
height: '950px',
data: {
images: images,
width: 300,
height: 800,
}
};
this.dialog
.open(PopupVisualizeImagesAdvertiserComponent, config)
.afterClosed()
.subscribe(retour => {});
}
}

View file

@ -39,7 +39,7 @@
<input matInput type="password" [(ngModel)]="newPassword">
</mat-form-field>
<br>
<!-- Confirmation npuveau mot de passe -->
<!-- Confirmation nouveau mot de passe -->
<mat-form-field appearance="fill">
<mat-label>Confirmation nouveau mot de passe</mat-label>
<input matInput type="password" [(ngModel)]="confirmNewPassword">

View file

@ -43,6 +43,7 @@ export class PopupUpdateAdvertiserComponent implements OnInit
isAccepted: advertiser0.isAccepted,
createdAt: advertiser0.createdAt,
updatedAt: advertiser0.updatedAt,
lastConnexion: new Date()
};
for(let interest of advertiser0.interests) this.advertiserCopy.interests.push(interest);
}
@ -53,10 +54,8 @@ export class PopupUpdateAdvertiserComponent implements OnInit
this.checkField();
if(!this.hasError)
{
const data = {
user: this.advertiserCopy,
newPassword: this.newPassword
};
if(this.changePassword) this.advertiserCopy.hashPass = this.hashage(this.newPassword);
const data = { user: this.advertiserCopy };
// VRAI CODE: envoie au back ...
@ -107,4 +106,16 @@ export class PopupUpdateAdvertiserComponent implements OnInit
this.advertiserCopy.interests = myInterets;
}
// Fonction de hashage (faible)
hashage(input: string): string
{
let hash = 0;
for (let i = 0; i < input.length; i++) {
let ch = input.charCodeAt(i);
hash = ((hash << 5) - hash) + ch;
hash = hash & hash;
}
return hash.toString();
}
}

View file

@ -67,6 +67,8 @@ import { PopupVisualizeImagesAdminComponent } from './admin/adList/popup-visuali
import { PageUserListComponent } from './admin/userList/page-user-list/page-user-list.component';
import { PopupVisualizeUserComponent } from './admin/userList/popup-visualize-user/popup-visualize-user.component';
import { PopupDeleteUserComponent } from './admin/userList/popup-delete-user/popup-delete-user.component';
import { PopupCreateUserComponent } from './admin/userList/popup-create-user/popup-create-user.component';
import { InputInterestsAdminComponent } from './admin/userList/input-interests-admin/input-interests-admin.component';
@NgModule({
@ -114,6 +116,8 @@ import { PopupDeleteUserComponent } from './admin/userList/popup-delete-user/pop
PageUserListComponent,
PopupVisualizeUserComponent,
PopupDeleteUserComponent,
PopupCreateUserComponent,
InputInterestsAdminComponent,
],
imports: [
BrowserModule,

View file

@ -37,6 +37,7 @@ export class PageRegisterComponent
isAccepted: false,
createdAt: new Date(),
updatedAt: new Date(),
lastConnexion: new Date()
};
@ -88,14 +89,6 @@ export class PageRegisterComponent
}
// Indique si email a bien le format d'un email
isValidEmail(email): boolean
{
let re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return re.test(email);
}
// Check les champs saisies par l'utilisateur
checkField(): void
{
@ -126,6 +119,14 @@ export class PageRegisterComponent
}
// Indique si email a bien le format d'un email
isValidEmail(email): boolean
{
let re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return re.test(email);
}
// Récupère la liste des centres d'intérets (car celle-ci est remplie à l'aide d'un component intermédiaire)
onEventInputInterests(myInterets: string[]): void
{

View file

@ -43,6 +43,7 @@ export class PopupUpdateUserComponent implements OnInit
isAccepted: user0.isAccepted,
createdAt: user0.createdAt,
updatedAt: user0.updatedAt,
lastConnexion: new Date()
};
for(let interest of user0.interests) this.userCopy.interests.push(interest);
}
@ -53,10 +54,8 @@ export class PopupUpdateUserComponent implements OnInit
this.checkField();
if(!this.hasError)
{
const data = {
user: this.userCopy,
newPassword: this.newPassword
};
if(this.changePassword) this.userCopy.hashPass = this.hashage(this.newPassword);
const data = { user: this.userCopy };
// VRAI CODE: envoie au back ...
@ -107,4 +106,17 @@ export class PopupUpdateUserComponent implements OnInit
this.userCopy.interests = myInterets;
}
// Fonction de hashage (faible)
hashage(input: string): string
{
let hash = 0;
for (let i = 0; i < input.length; i++) {
let ch = input.charCodeAt(i);
hash = ((hash << 5) - hash) + ch;
hash = hash & hash;
}
return hash.toString();
}
}

View file

@ -16,4 +16,5 @@ export interface User
isAccepted: boolean,
createdAt: Date,
updatedAt: Date,
lastConnexion: Date,
}

View file

@ -152,6 +152,7 @@ const USER: User = {
isAccepted: true,
createdAt: new Date(),
updatedAt: new Date(),
lastConnexion: new Date()
};
const ADVERTISER: User = {
@ -171,6 +172,7 @@ const ADVERTISER: User = {
isAccepted: true,
createdAt: new Date(),
updatedAt: new Date(),
lastConnexion: new Date()
};
const ADMIN: User = {
@ -190,6 +192,7 @@ const ADMIN: User = {
isAccepted: true,
createdAt: new Date(),
updatedAt: new Date(),
lastConnexion: new Date()
};
// ------------------------------------------------------------------------------------------------------------------------------