Merge remote-tracking branch 'origin/main' into main
This commit is contained in:
commit
a70574a8e2
92 changed files with 1549 additions and 499 deletions
28
package.json
28
package.json
|
|
@ -14,8 +14,10 @@
|
|||
"dependencies": {
|
||||
"@angular/animations": "^12.2.11",
|
||||
"@angular/cdk": "^12.2.11",
|
||||
"@angular/cli": "~12.2.11",
|
||||
"@angular/common": "^12.2.11",
|
||||
"@angular/compiler": "^12.2.11",
|
||||
"@angular/compiler-cli": "~12.2.11",
|
||||
"@angular/core": "^12.2.11",
|
||||
"@angular/forms": "^12.2.11",
|
||||
"@angular/material": "^12.2.11",
|
||||
|
|
@ -24,28 +26,27 @@
|
|||
"@angular/router": "^12.2.11",
|
||||
"@ng-bootstrap/ng-bootstrap": "^10.0.0",
|
||||
"angular-responsive-carousel": "^2.1.2",
|
||||
"bootstrap": "^5.1.3",
|
||||
"jquery": "^3.6.0",
|
||||
"popper": "^1.0.1",
|
||||
"rxjs": "~6.6.0",
|
||||
"tslib": "^2.0.0",
|
||||
"zone.js": "~0.11.3",
|
||||
"@angular/cli": "~12.2.11",
|
||||
"@angular/compiler-cli": "~12.2.11",
|
||||
"typescript": "~4.3.5",
|
||||
"body-parser": "^1.19.0",
|
||||
"bootstrap": "^5.1.3",
|
||||
"chart.js": "^2.9.3",
|
||||
"cookie-parser": "^1.4.5",
|
||||
"cors": "^2.8.5",
|
||||
"dotenv": "^10.0.0",
|
||||
"express": "^4.17.1",
|
||||
"jquery": "^3.6.0",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"mongoose": "^6.0.12"
|
||||
"mongoose": "^6.0.12",
|
||||
"ng2-charts": "^2.2.3",
|
||||
"popper": "^1.0.1",
|
||||
"rxjs": "~6.6.0",
|
||||
"tslib": "^2.0.0",
|
||||
"typescript": "~4.3.5",
|
||||
"zone.js": "~0.11.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "~12.2.11",
|
||||
"@angular/cli": "~12.2.11",
|
||||
"@angular/compiler-cli": "~12.2.11",
|
||||
"typescript": "~4.3.5",
|
||||
"@angular-devkit/build-angular": "~12.2.11",
|
||||
"@angular/localize": "^12.2.11",
|
||||
"@types/jasmine": "~3.6.0",
|
||||
"@types/node": "^12.11.1",
|
||||
|
|
@ -59,6 +60,7 @@
|
|||
"karma-jasmine-html-reporter": "^1.5.0",
|
||||
"protractor": "~7.0.0",
|
||||
"ts-node": "~8.3.0",
|
||||
"tslint": "~6.1.0"
|
||||
"tslint": "~6.1.0",
|
||||
"typescript": "~4.3.5"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
<input class="textFilter" (keyup)="applyFilter($event)" placeholder="filtre...">
|
||||
</div>
|
||||
|
||||
<!-- visible + tags + période -->
|
||||
<!-- visible + interests + période -->
|
||||
<div class="row myRow">
|
||||
|
||||
<!-- visible -->
|
||||
|
|
@ -30,18 +30,18 @@
|
|||
<mat-checkbox [(ngModel)]="noVisible" (change)="onFilter()">non visible</mat-checkbox>
|
||||
</div>
|
||||
|
||||
<!-- tags -->
|
||||
<!-- subjects -->
|
||||
<div class="col-4">
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-label>Tags</mat-label>
|
||||
<mat-select [formControl]="formControlTags" multiple>
|
||||
<mat-label>Sujets</mat-label>
|
||||
<mat-select [formControl]="formControlInterests" multiple>
|
||||
<mat-select-trigger>
|
||||
{{formControlTags.value ? formControlTags.value[0] : ''}}
|
||||
<span *ngIf="formControlTags.value?.length > 1">
|
||||
(+{{formControlTags.value.length - 1}} {{formControlTags.value?.length === 2 ? 'autre' : 'autres'}})
|
||||
{{formControlInterests.value ? formControlInterests.value[0] : ''}}
|
||||
<span *ngIf="formControlInterests.value?.length > 1">
|
||||
(+{{formControlInterests.value.length - 1}} {{formControlInterests.value?.length === 2 ? 'autre' : 'autres'}})
|
||||
</span>
|
||||
</mat-select-trigger>
|
||||
<mat-option *ngFor="let topping of allTags" [value]="topping">{{topping}}</mat-option>
|
||||
<mat-option *ngFor="let topping of allInterests" [value]="topping">{{topping}}</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<button mat-icon-button (click)="onFilter()">
|
||||
|
|
@ -86,20 +86,20 @@
|
|||
</ng-container>
|
||||
|
||||
<!-- Advertiser Column -->
|
||||
<ng-container matColumnDef="advertiser">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> Annonceur </th>
|
||||
<ng-container matColumnDef="company">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> Entreprise </th>
|
||||
<td mat-cell *matCellDef="let advert">
|
||||
{{advert.advertiser}}
|
||||
{{advert.company}}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Tags Column -->
|
||||
<ng-container matColumnDef="tags">
|
||||
<th mat-header-cell *matHeaderCellDef> Tags </th>
|
||||
<ng-container matColumnDef="interests">
|
||||
<th mat-header-cell *matHeaderCellDef> Sujets </th>
|
||||
<td mat-cell *matCellDef="let advert">
|
||||
<span *ngFor="let tag of advert.tags; let isLast = last;">
|
||||
<span *ngIf="!isLast"> {{tag}}, </span>
|
||||
<span *ngIf="isLast"> {{tag}} </span>
|
||||
<span *ngFor="let interest of advert.interests; let isLast = last;">
|
||||
<span *ngIf="!isLast"> {{interest}}, </span>
|
||||
<span *ngIf="isLast"> {{interest}} </span>
|
||||
</span>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
|
@ -120,11 +120,11 @@
|
|||
</td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Views Column -->
|
||||
<ng-container matColumnDef="views">
|
||||
<!-- CountViews Column -->
|
||||
<ng-container matColumnDef="countViews">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> Vues </th>
|
||||
<td mat-cell *matCellDef="let advert">
|
||||
{{advert.views}}
|
||||
{{advert.countViews}}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
|
||||
.filtersContainer {
|
||||
width: 70%;
|
||||
width: 80%;
|
||||
background-color: white;
|
||||
padding: 10px 10px 10px 10px;
|
||||
margin: 20px 3% 20px 3%
|
||||
|
|
@ -68,3 +68,7 @@ input {
|
|||
border: solid 1px black !important;
|
||||
background-color: white !important;
|
||||
}
|
||||
|
||||
::ng-deep .mat-pseudo-checkbox-checked {
|
||||
background-color: black !important;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,12 +6,35 @@ import {MatDialog} from "@angular/material/dialog";
|
|||
import {MatSnackBar} from "@angular/material/snack-bar";
|
||||
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";
|
||||
import {FictitiousAdvertsService} from "../../../utils/services/fictitiousDatas/fictitiousAdverts/fictitious-adverts.service";
|
||||
import {FormControl} from "@angular/forms";
|
||||
import {FictitiousUtilsService} from "../../../utils/services/fictitiousDatas/fictitiousUtils/fictitious-utils.service";
|
||||
import {User} from "../../../utils/interfaces/user";
|
||||
import {FictitiousUsersService} from "../../../utils/services/fictitiousDatas/fictitiousUsers/fictitious-users.service";
|
||||
|
||||
|
||||
|
||||
export interface AdvertWithCountViewsAndCompany {
|
||||
_id: string,
|
||||
userId: string,
|
||||
company: string,
|
||||
title: string,
|
||||
url: string,
|
||||
images: {
|
||||
url: string,
|
||||
description: string,
|
||||
}[],
|
||||
interests: string[],
|
||||
comment: string,
|
||||
views: Date[],
|
||||
countViews: number,
|
||||
isVisible: boolean,
|
||||
isActive: boolean,
|
||||
createdAt: Date,
|
||||
updatedAt: Date,
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -22,8 +45,9 @@ import {FictitiousUtilsService} from "../../../utils/services/fictitiousDatas/fi
|
|||
})
|
||||
export class PageAdListAdminComponent implements AfterViewInit
|
||||
{
|
||||
tabAdvert: Advert[];
|
||||
displayedColumns: string[] = [ 'title', 'advertiser', 'tags', 'createdAt', 'updatedAt', 'views', 'isVisible', 'actions' ];
|
||||
tabAdvertWithCountViews: AdvertWithCountViewsAndCompany[] = [];
|
||||
tabAdvertiser: User[];
|
||||
displayedColumns: string[] = [ 'title', 'company', 'interests', 'createdAt', 'updatedAt', 'countViews', 'isVisible', 'actions' ];
|
||||
dataSource ;
|
||||
@ViewChild(MatSort) sort: MatSort;
|
||||
@ViewChild(MatPaginator) paginator: MatPaginator;
|
||||
|
|
@ -32,13 +56,14 @@ export class PageAdListAdminComponent implements AfterViewInit
|
|||
noVisible: boolean = true;
|
||||
startDate: Date = null;
|
||||
endDate: Date = null;
|
||||
formControlTags = new FormControl();
|
||||
allTags: string[] = [];
|
||||
formControlInterests = new FormControl();
|
||||
allInterests: string[] = [];
|
||||
|
||||
|
||||
constructor( public themeService: ThemeService,
|
||||
private fictitiousAdvertsService: FictitiousAdvertsService,
|
||||
private fictitiousUtilsService: FictitiousUtilsService,
|
||||
private fictitiousUsersService: FictitiousUsersService,
|
||||
public dialog: MatDialog,
|
||||
private snackBar: MatSnackBar ) { }
|
||||
|
||||
|
|
@ -46,12 +71,13 @@ export class PageAdListAdminComponent implements AfterViewInit
|
|||
ngAfterViewInit(): void
|
||||
{
|
||||
// --- FAUX CODE ---
|
||||
this.tabAdvert = this.fictitiousAdvertsService.getTabAdvert(8);
|
||||
this.dataSource = new MatTableDataSource<Advert>(this.tabAdvert);
|
||||
this.dataSource.sort = this.sort;
|
||||
this.dataSource.paginator = this.paginator;
|
||||
this.dataSource = this.dataSource;
|
||||
this.allTags = this.fictitiousUtilsService.getTags();
|
||||
const tabAdvert = this.fictitiousAdvertsService.getTabAdvert(8);
|
||||
this.allInterests = this.fictitiousUtilsService.getTags();
|
||||
this.tabAdvertiser = this.fictitiousUsersService.getTabAdvertiser(3);
|
||||
|
||||
for(let advert of tabAdvert) this.tabAdvertWithCountViews.push(this.advertToAdvertWithCountViewsAndCompany(advert));
|
||||
this.dataSource = new MatTableDataSource<Advert>();
|
||||
this.onFilter();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -62,7 +88,7 @@ export class PageAdListAdminComponent implements AfterViewInit
|
|||
}
|
||||
|
||||
|
||||
onVisualizeImages(advert: Advert)
|
||||
onVisualizeImages(advert: AdvertWithCountViewsAndCompany)
|
||||
{
|
||||
const config = {
|
||||
width: '30%',
|
||||
|
|
@ -80,20 +106,7 @@ export class PageAdListAdminComponent implements AfterViewInit
|
|||
}
|
||||
|
||||
|
||||
onVisualizeInfo(advert: Advert): void
|
||||
{
|
||||
const config = {
|
||||
width: '50%',
|
||||
data: { advert: advert }
|
||||
};
|
||||
this.dialog
|
||||
.open(PopupVisualizeAdAdminComponent, config)
|
||||
.afterClosed()
|
||||
.subscribe(retour => {});
|
||||
}
|
||||
|
||||
|
||||
onDelete(advert: Advert): void
|
||||
onDelete(advert: AdvertWithCountViewsAndCompany): void
|
||||
{
|
||||
const config = {
|
||||
data: { advert: advert }
|
||||
|
|
@ -122,9 +135,8 @@ export class PageAdListAdminComponent implements AfterViewInit
|
|||
|
||||
onFilter(): void
|
||||
{
|
||||
console.log("b:" + this.formControlTags.value);
|
||||
this.dataSource.data = [];
|
||||
for(let advert of this.tabAdvert)
|
||||
for(let advert of this.tabAdvertWithCountViews)
|
||||
{
|
||||
let valide: boolean = true;
|
||||
|
||||
|
|
@ -147,9 +159,9 @@ export class PageAdListAdminComponent implements AfterViewInit
|
|||
}
|
||||
|
||||
if(valide) {
|
||||
if(this.formControlTags.value !== null) {
|
||||
for (let tag of this.formControlTags.value) {
|
||||
if (advert.tags.indexOf(tag) === -1) {
|
||||
if(this.formControlInterests.value !== null) {
|
||||
for (let interest of this.formControlInterests.value) {
|
||||
if (advert.interests.indexOf(interest) === -1) {
|
||||
valide = false;
|
||||
break;
|
||||
}
|
||||
|
|
@ -174,4 +186,34 @@ export class PageAdListAdminComponent implements AfterViewInit
|
|||
this.endDate = new Date(event);
|
||||
}
|
||||
|
||||
|
||||
advertToAdvertWithCountViewsAndCompany(advert: Advert): AdvertWithCountViewsAndCompany
|
||||
{
|
||||
let company0 = "company" ;
|
||||
for(let advertiser of this.tabAdvertiser)
|
||||
{
|
||||
if(advert.userId === advertiser._id) {
|
||||
company0 = advertiser.company;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
_id: advert._id,
|
||||
userId: advert.userId,
|
||||
title: advert.title,
|
||||
company: company0,
|
||||
url: advert.url,
|
||||
images: advert.images,
|
||||
interests: advert.interests,
|
||||
comment: advert.comment,
|
||||
views: advert.views,
|
||||
countViews: advert.views.length,
|
||||
isVisible: advert.isVisible,
|
||||
isActive: advert.isActive,
|
||||
createdAt: advert.createdAt,
|
||||
updatedAt: advert.updatedAt,
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ export class PopupDeleteAdAdminComponent implements OnInit
|
|||
// --- VRAI CODE ---
|
||||
/*
|
||||
this.messageService
|
||||
.sendMessage("advertiser/delete/ad", {"advert": this.advert})
|
||||
.sendMessage("url/delete/ad", {"advert": this.advert})
|
||||
.subscribe( retour => {
|
||||
|
||||
if(retour.status === "error") {
|
||||
|
|
|
|||
|
|
@ -7,10 +7,10 @@
|
|||
<mat-divider></mat-divider>
|
||||
<mat-dialog-content>
|
||||
|
||||
<!-- Advertiser -->
|
||||
<!-- URL -->
|
||||
<div class="row myRow">
|
||||
<div class="col-6 myLabel"> Annonceur: </div>
|
||||
<div class="col-6 myValue"> {{advert.advertiser}} </div>
|
||||
<div class="col-6 myValue"> {{advert.url}} </div>
|
||||
</div>
|
||||
|
||||
<!-- Images -->
|
||||
|
|
@ -25,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 interest of advert.interests"> {{interest}} </div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
<!-- login -->
|
||||
<div class="row myRow">
|
||||
<div class="col-6 myLabel">Login:</div>
|
||||
<div class="col-6 myLabel">Pseudo:</div>
|
||||
<div class="col-6 myValue"> {{admin.login}} </div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ export class PopupUpdateAdminComponent implements OnInit
|
|||
dateOfBirth: admin0.dateOfBirth,
|
||||
gender: admin0.gender,
|
||||
interests: [],
|
||||
company: "",
|
||||
isActive: admin0.isActive,
|
||||
isAccepted: admin0.isisAccepted,
|
||||
createdAt: admin0.createdAt,
|
||||
|
|
@ -67,7 +68,7 @@ export class PopupUpdateAdminComponent implements OnInit
|
|||
checkField()
|
||||
{
|
||||
if(this.adminCopy.login.length === 0) {
|
||||
this.errorMessage = "Veuillez remplir le champ 'login'" ;
|
||||
this.errorMessage = "Veuillez remplir le champ 'pseudo'" ;
|
||||
this.hasError = true;
|
||||
}
|
||||
else if(this.adminCopy.email.length === 0) {
|
||||
|
|
@ -112,4 +113,5 @@ export class PopupUpdateAdminComponent implements OnInit
|
|||
}
|
||||
return hash.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@
|
|||
|
||||
<!-- Login Column -->
|
||||
<ng-container matColumnDef="login">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> Login </th>
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> Pseudo </th>
|
||||
<td mat-cell *matCellDef="let user">
|
||||
{{user.login}}
|
||||
</td>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
// ----------------------------------------------------------
|
||||
|
||||
.filtersContainer {
|
||||
width: 85%;
|
||||
width: 90%;
|
||||
background-color: white;
|
||||
padding: 10px 10px 10px 10px;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@
|
|||
|
||||
<!-- Login -->
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-label>Login</mat-label>
|
||||
<mat-label>Pseudo</mat-label>
|
||||
<input matInput type="text" [(ngModel)]="user.login" required>
|
||||
</mat-form-field><br>
|
||||
|
||||
|
|
@ -130,9 +130,14 @@
|
|||
</mat-form-field><br>
|
||||
<!-- login -->
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-label>Login</mat-label>
|
||||
<mat-label>Pseudo</mat-label>
|
||||
<input matInput type="text" [(ngModel)]="user.login">
|
||||
</mat-form-field><br>
|
||||
<!-- company -->
|
||||
<mat-form-field appearance="fill" *ngIf="user.role.name === 'advertiser'">
|
||||
<mat-label>Entreprise</mat-label>
|
||||
<input matInput type="text" [(ngModel)]="user.company">
|
||||
</mat-form-field><br *ngIf="user.role.name === 'advertiser'">
|
||||
</div>
|
||||
|
||||
<!-- mdp + confirmation -->
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ export class PopupCreateUserComponent implements OnInit
|
|||
dateOfBirth: null,
|
||||
gender: "man",
|
||||
interests: [],
|
||||
company: "",
|
||||
isActive: false,
|
||||
isAccepted: false,
|
||||
createdAt: new Date(),
|
||||
|
|
@ -65,19 +66,15 @@ export class PopupCreateUserComponent implements OnInit
|
|||
checkField(): void
|
||||
{
|
||||
if(this.user.login.length === 0) {
|
||||
this.errorMessage = "Veuillez remplir le champ 'login'.";
|
||||
this.errorMessage = "Veuillez remplir le champ 'pseudo'.";
|
||||
this.hasError = true;
|
||||
}
|
||||
else if(this.user.email.length === 0) {
|
||||
this.errorMessage = "Veuillez remplir le champ 'email'.";
|
||||
this.hasError = true;
|
||||
}
|
||||
if((this.user.role.name === 'user') && ((this.user.dateOfBirth === undefined) || (this.user.dateOfBirth === null))) {
|
||||
this.errorMessage = "Veuillez remplir le champ 'date de naissance'.";
|
||||
this.hasError = true;
|
||||
}
|
||||
else if(!this.isValidEmail(this.user.email)) {
|
||||
this.errorMessage = "Email invalide";
|
||||
this.errorMessage = "Email invalide.";
|
||||
this.hasError = true;
|
||||
}
|
||||
else if(this.password.length === 0) {
|
||||
|
|
@ -88,6 +85,14 @@ export class PopupCreateUserComponent implements OnInit
|
|||
this.errorMessage = "Le mot de passe est différent de sa confirmation.";
|
||||
this.hasError = true;
|
||||
}
|
||||
else if((this.user.role.name === 'user') && ((this.user.dateOfBirth === undefined) || (this.user.dateOfBirth === null))) {
|
||||
this.errorMessage = "Veuillez remplir le champ 'date de naissance'.";
|
||||
this.hasError = true;
|
||||
}
|
||||
else if((this.user.role.name === 'advertiser') && (this.user.company.length === 0)) {
|
||||
this.errorMessage = "Veuillez remplir le champ 'entreprise'.";
|
||||
this.hasError = true;
|
||||
}
|
||||
else {
|
||||
this.errorMessage = "" ;
|
||||
this.hasError = false;
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@
|
|||
<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 === 'url'">Annonceur</span>
|
||||
<span *ngIf="user.role.name === 'admin'">Admin</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -6,24 +6,29 @@
|
|||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<!-- [UserList] [Mes AdList] [Historique] -->
|
||||
|
||||
<!-- [userList] [adList] -->
|
||||
<div class="collapse navbar-collapse">
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item active monLi">
|
||||
<a class="nav-link" routerLink="/admin/userList"> Liste des utillisateurs </a>
|
||||
<a *ngIf="(url !== routes[0]) && (url !== routes[1])" [routerLink]="routes[1]" class="nav-link">Liste des utillisateurs</a>
|
||||
<a *ngIf="(url === routes[0]) || (url === routes[1])" [routerLink]="routes[1]" class="nav-link myActiveLink">Liste des utillisateurs</a>
|
||||
</li>
|
||||
<li class="nav-item active monLi">
|
||||
<a class="nav-link" routerLink="/admin/adList"> Liste des pubs </a>
|
||||
<a *ngIf="url !== routes[2]" [routerLink]="routes[2]" class="nav-link">Liste des publicités</a>
|
||||
<a *ngIf="url === routes[2]" [routerLink]="routes[2]" class="nav-link myActiveLink">Liste des publicités</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Mon profil -->
|
||||
<img [src]=urlImage
|
||||
onerror="this.onerror=null; this.src='assets/profil.png'"
|
||||
routerLink="/admin/myProfil"
|
||||
[routerLink]="routes[3]"
|
||||
alt="">
|
||||
|
||||
|
||||
<!-- Deconnexion -->
|
||||
<button mat-button class="btnDeconnexion" (click)="onDeconnexion()" routerLink="/">
|
||||
Deconnexion
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
.navbar {
|
||||
background-color: black;
|
||||
height: 50px;
|
||||
height: 60px;
|
||||
font-size: medium;
|
||||
color: white;
|
||||
}
|
||||
|
|
@ -23,16 +23,22 @@
|
|||
}
|
||||
|
||||
|
||||
// Recherche, Mes Playlists, Historique
|
||||
.monLi {
|
||||
margin: 0px 10px 0px 10px;
|
||||
}
|
||||
|
||||
|
||||
.nav-link {
|
||||
color: white;
|
||||
}
|
||||
.nav-link:hover {
|
||||
color: grey;
|
||||
}
|
||||
.myActiveLink {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
|
||||
// Bonton deconnexion
|
||||
.btnDeconnexion {
|
||||
font-size: medium;
|
||||
margin: 0px 10px 0px 10px
|
||||
|
|
@ -42,11 +48,6 @@
|
|||
}
|
||||
|
||||
|
||||
.monLi {
|
||||
margin: 0px 10px 0px 10px;
|
||||
}
|
||||
|
||||
|
||||
img {
|
||||
border: solid 2px white;
|
||||
border-radius: 50px;
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
import {Component} from '@angular/core';
|
||||
import {Router} from "@angular/router";
|
||||
|
||||
|
||||
|
||||
|
|
@ -9,9 +10,18 @@ import { Component } from '@angular/core';
|
|||
})
|
||||
export class NavbarAdminComponent
|
||||
{
|
||||
routes: string[] = [
|
||||
"/admin", // 0
|
||||
"/admin/userList", // 1
|
||||
"/admin/adList", // 2
|
||||
"/admin/myProfil", // 3
|
||||
];
|
||||
|
||||
url = this.router.url;
|
||||
|
||||
urlImage: string = "https://www.reference-gaming.com/assets/media/product/41195/figurine-pop-duck-tales-n-309-loulou.jpg?format=product-cover-large&k=1519639530" ;
|
||||
|
||||
constructor() { }
|
||||
constructor(private router: Router) { }
|
||||
|
||||
onDeconnexion(): void {}
|
||||
}
|
||||
|
|
@ -7,7 +7,9 @@
|
|||
<div style="font-style: italic" for="fileDropRef">Cliquer pour selectionner</div>
|
||||
</div>
|
||||
|
||||
<div style="text-align: center;">
|
||||
<mat-icon [title]=info_image>info</mat-icon>
|
||||
</div>
|
||||
|
||||
<div class="files-list">
|
||||
<div class="single-file" *ngFor="let file of files; let i = index">
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
<!-- ------------------------------------------------------------------------------------ -->
|
||||
|
||||
<mat-label>Tags</mat-label>
|
||||
<mat-label>Sujets</mat-label>
|
||||
|
||||
<!-- ------------------------------------------------------------------------------------ -->
|
||||
|
||||
|
|
@ -20,7 +20,7 @@
|
|||
</mat-chip>
|
||||
|
||||
<input
|
||||
placeholder="Tapez un tag et pressez 'Entré' pour l'inserer"
|
||||
placeholder="Tapez un sujet et pressez 'Entré' pour l'inserer"
|
||||
#tagInput
|
||||
[formControl]="formControl"
|
||||
[matAutocomplete]="auto"
|
||||
|
|
@ -1,20 +1,20 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { InputTagsComponent } from './input-tags.component';
|
||||
import { InputInterestsAdComponent } from './input-interests-ad.component';
|
||||
|
||||
describe('BarTagsComponent', () => {
|
||||
let component: InputTagsComponent;
|
||||
let fixture: ComponentFixture<InputTagsComponent>;
|
||||
let component: InputInterestsAdComponent;
|
||||
let fixture: ComponentFixture<InputInterestsAdComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ InputTagsComponent ]
|
||||
declarations: [ InputInterestsAdComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(InputTagsComponent);
|
||||
fixture = TestBed.createComponent(InputInterestsAdComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
|
@ -11,11 +11,11 @@ import {FictitiousUtilsService} from "../../../utils/services/fictitiousDatas/fi
|
|||
|
||||
|
||||
@Component({
|
||||
selector: 'app-input-tags',
|
||||
templateUrl: './input-tags.component.html',
|
||||
styleUrls: ['./input-tags.component.scss']
|
||||
selector: 'app-input-interests-ad',
|
||||
templateUrl: './input-interests-ad.component.html',
|
||||
styleUrls: ['./input-interests-ad.component.scss']
|
||||
})
|
||||
export class InputTagsComponent implements OnInit
|
||||
export class InputInterestsAdComponent implements OnInit
|
||||
{
|
||||
selectable = true;
|
||||
removable = true;
|
||||
|
|
@ -2,26 +2,113 @@
|
|||
<div class="myContainer">
|
||||
|
||||
|
||||
<!-- Navbar -->
|
||||
<app-navbar-advertiser></app-navbar-advertiser><br><br>
|
||||
|
||||
<!-- ---------------------------------------------------------------------------------- -->
|
||||
|
||||
<div style="text-align: center">
|
||||
<input (keyup)="applyFilter($event)" placeholder="Filtre...">
|
||||
|
||||
|
||||
|
||||
<!-- filtre + btnAddUser -->
|
||||
<div class="row" style="margin: 20px 3% 20px 3%">
|
||||
|
||||
<!-- filtre -->
|
||||
<div class="col-10" style="padding: 0px 0px 0px 0px;">
|
||||
<div class="filtersContainer mat-elevation-z8">
|
||||
|
||||
<!-- titre -->
|
||||
<div style="font-weight: bold; margin-bottom: 10px;">
|
||||
Filtre
|
||||
</div>
|
||||
<br>
|
||||
|
||||
<!-- ---------------------------------------------------------------------------------- -->
|
||||
<mat-divider></mat-divider>
|
||||
|
||||
<button mat-button class="btnAjouter" (click)="onAdd()">
|
||||
<!-- filtre textuelle-->
|
||||
<div style="margin: 10px 0px 20px 2%;">
|
||||
<input class="textFilter" (keyup)="applyFilter($event)" placeholder="filtre...">
|
||||
</div>
|
||||
|
||||
<!-- role + actif + période -->
|
||||
<div class="row myRow">
|
||||
|
||||
|
||||
<!-- visible -->
|
||||
<div class="col-2">
|
||||
<mat-checkbox [(ngModel)]="visible" (change)="onFilter()">visible</mat-checkbox><br>
|
||||
<mat-checkbox [(ngModel)]="noVisible" (change)="onFilter()">non visible</mat-checkbox>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- sujets -->
|
||||
<div class="col-4">
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-label>Sujets</mat-label>
|
||||
<mat-select [formControl]="formControlInterests" multiple>
|
||||
<mat-select-trigger>
|
||||
{{formControlInterests.value ? formControlInterests.value[0] : ''}}
|
||||
<span *ngIf="formControlInterests.value?.length > 1">
|
||||
(+{{formControlInterests.value.length - 1}} {{formControlInterests.value?.length === 2 ? 'autre' : 'autres'}})
|
||||
</span>
|
||||
</mat-select-trigger>
|
||||
<mat-option *ngFor="let topping of allInterests" [value]="topping">{{topping}}</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<button mat-icon-button (click)="onFilter()">
|
||||
<mat-icon>keyboard_tab</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- période -->
|
||||
<div class="col-6" style="text-align: right;">
|
||||
Période de création:
|
||||
<mat-form-field appearance="fill" style="width: 140px;">
|
||||
<mat-label>Date de début</mat-label>
|
||||
<input matInput type="date"
|
||||
style="font-size: small; width: 140px;"
|
||||
[ngModel] ="startDate | date:'yyyy-MM-dd'"
|
||||
(ngModelChange)="onNewStartDate($event); onFilter();">
|
||||
</mat-form-field>
|
||||
-
|
||||
<mat-form-field appearance="fill" style="width: 140px;">
|
||||
<mat-label>Date de fin</mat-label>
|
||||
<input matInput type="date"
|
||||
style="font-size: small; width: 140px;"
|
||||
[ngModel] ="endDate | date:'yyyy-MM-dd'"
|
||||
(ngModelChange)="onNewEndDate($event); onFilter();">
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- btnAdd -->
|
||||
<div class="col-2" style="text-align: right; position: relative;">
|
||||
<button mat-button class="btnAjouter" (click)="onAdd()" style="position: absolute; bottom: 0; right: 0;">
|
||||
<mat-icon>add_circle</mat-icon> Ajouter une annonce
|
||||
</button>
|
||||
<br>
|
||||
</div>
|
||||
|
||||
<!-- ---------------------------------------------------------------------------------- -->
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- Table -->
|
||||
<table mat-table [dataSource]="dataSource" matSort class="mat-elevation-z8">
|
||||
|
||||
<!-- IsActive Column -->
|
||||
<ng-container matColumnDef="isVisible">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header>
|
||||
<mat-icon>power_settings_new</mat-icon>
|
||||
</th>
|
||||
<td mat-cell *matCellDef="let advert">
|
||||
<mat-slide-toggle [(ngModel)]="advert.isVisible" (click)="onSliderIsVisible(advert)"></mat-slide-toggle>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Title Column -->
|
||||
<ng-container matColumnDef="title">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> Titre </th>
|
||||
|
|
@ -30,13 +117,13 @@
|
|||
</td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Tags Column -->
|
||||
<ng-container matColumnDef="tags">
|
||||
<th mat-header-cell *matHeaderCellDef> Tags </th>
|
||||
<!-- Subject Column -->
|
||||
<ng-container matColumnDef="interests">
|
||||
<th mat-header-cell *matHeaderCellDef> Sujets </th>
|
||||
<td mat-cell *matCellDef="let advert">
|
||||
<span *ngFor="let tag of advert.tags; let isLast = last;">
|
||||
<span *ngIf="!isLast"> {{tag}}, </span>
|
||||
<span *ngIf="isLast"> {{tag}} </span>
|
||||
<span *ngFor="let interest of advert.interests; let isLast = last;">
|
||||
<span *ngIf="!isLast"> {{interest}}, </span>
|
||||
<span *ngIf="isLast"> {{interest}} </span>
|
||||
</span>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
|
@ -58,19 +145,10 @@
|
|||
</ng-container>
|
||||
|
||||
<!-- Views Column -->
|
||||
<ng-container matColumnDef="views">
|
||||
<ng-container matColumnDef="countViews">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> Vues </th>
|
||||
<td mat-cell *matCellDef="let advert">
|
||||
{{advert.views}}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<!-- IsVisible Column -->
|
||||
<ng-container matColumnDef="isVisible">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> Visible </th>
|
||||
<td mat-cell *matCellDef="let advert">
|
||||
<span *ngIf="advert.isVisible"> <mat-icon>check</mat-icon> </span>
|
||||
<span *ngIf="!advert.isVisible"></span>
|
||||
{{advert.countViews}}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
|
|
@ -82,10 +160,7 @@
|
|||
<mat-icon> insert_photo</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button (click)="onUpdate(advert)">
|
||||
<mat-icon>settings</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button (click)="onVisualize(advert)">
|
||||
<mat-icon>aspect_ratio</mat-icon>
|
||||
<mat-icon>edit</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button (click)="onDelete(advert)">
|
||||
<mat-icon>delete</mat-icon>
|
||||
|
|
|
|||
|
|
@ -9,28 +9,25 @@
|
|||
// ----------------------------------------------------------
|
||||
|
||||
|
||||
.btnAjouter {
|
||||
margin-left: 3%;
|
||||
padding: 5px 20px 5px 20px;
|
||||
font-size: small;
|
||||
}
|
||||
.lightTheme .btnAjouter {
|
||||
border-top: solid 1px #dcdcdc;
|
||||
border-right: solid 1px #dcdcdc;
|
||||
border-left: solid 1px #dcdcdc;
|
||||
color: black;
|
||||
.filtersContainer {
|
||||
width: 95%;
|
||||
background-color: white;
|
||||
padding: 10px 10px 10px 10px;
|
||||
}
|
||||
.darkTheme .btnAjouter {
|
||||
border-top: solid 1px white;
|
||||
border-right: solid 1px white;
|
||||
border-left: solid 1px white;
|
||||
color: white;
|
||||
background-color: black;
|
||||
|
||||
.myRow {
|
||||
margin-left: 1%;
|
||||
}
|
||||
.darkTheme .btnAjouter:hover {
|
||||
background-color: #646464;
|
||||
color: black;
|
||||
|
||||
.textFilter {
|
||||
width: 50%;
|
||||
font-size: medium;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.btnAjouter {
|
||||
background-color: white;
|
||||
border: solid 1px black;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -57,3 +54,34 @@ input {
|
|||
font-size: large;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
|
||||
// rong gauche
|
||||
::ng-deep .mat-slide-toggle-thumb {
|
||||
background-color: white !important;
|
||||
}
|
||||
|
||||
// trait droite
|
||||
::ng-deep .mat-slide-toggle-bar {
|
||||
background-color: gray !important;
|
||||
}
|
||||
|
||||
// rond droite
|
||||
::ng-deep .mat-slide-toggle.mat-checked:not(.mat-disabled) .mat-slide-toggle-thumb {
|
||||
background-color: white !important;
|
||||
}
|
||||
|
||||
// trait gauche
|
||||
::ng-deep .mat-slide-toggle.mat-checked:not(.mat-disabled) .mat-slide-toggle-bar {
|
||||
background-color: cornflowerblue !important;
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
::ng-deep .mat-pseudo-checkbox-checked {
|
||||
background-color: black !important;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,15 +2,16 @@ import {AfterViewInit, Component, OnInit, ViewChild} from '@angular/core';
|
|||
import {MatSort} from "@angular/material/sort";
|
||||
import {ThemeService} from "../../../utils/services/theme/theme.service";
|
||||
import {MatTableDataSource} from "@angular/material/table";
|
||||
import {Advert} from "../../../utils/interfaces/advert";
|
||||
import {Advert, AdvertWithCountViews} from "../../../utils/interfaces/advert";
|
||||
import {MatDialog} from "@angular/material/dialog";
|
||||
import {PopupAddOrUpdateAdComponent} from "../popup-add-or-update-ad/popup-add-or-update-ad.component";
|
||||
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";
|
||||
import {FictitiousAdvertsService} from "../../../utils/services/fictitiousDatas/fictitiousAdverts/fictitious-adverts.service";
|
||||
import {FormControl} from "@angular/forms";
|
||||
import {FictitiousUtilsService} from "../../../utils/services/fictitiousDatas/fictitiousUtils/fictitious-utils.service";
|
||||
|
||||
|
||||
|
||||
|
|
@ -21,14 +22,23 @@ import {FictitiousAdvertsService} from "../../../utils/services/fictitiousDatas/
|
|||
})
|
||||
export class PageAdListAdvertiserComponent implements AfterViewInit
|
||||
{
|
||||
displayedColumns: string[] = [ 'title', 'tags', 'createdAt', 'updatedAt', 'views', 'isVisible', 'actions' ];
|
||||
displayedColumns: string[] = [ 'isVisible', 'title', 'interests', 'createdAt', 'updatedAt', 'countViews', 'actions' ];
|
||||
tabAdvertWithCountViews: AdvertWithCountViews[] = [];
|
||||
dataSource ;
|
||||
@ViewChild(MatSort) sort: MatSort;
|
||||
@ViewChild(MatPaginator) paginator: MatPaginator;
|
||||
|
||||
visible: boolean = true;
|
||||
noVisible: boolean = true;
|
||||
startDate: Date = null;
|
||||
endDate: Date = null;
|
||||
formControlInterests = new FormControl();
|
||||
allInterests: string[] = [];
|
||||
|
||||
|
||||
constructor( public themeService: ThemeService,
|
||||
private fictitiousAdvertsService: FictitiousAdvertsService,
|
||||
private fictitiousUtilsService: FictitiousUtilsService,
|
||||
public dialog: MatDialog,
|
||||
private snackBar: MatSnackBar ) { }
|
||||
|
||||
|
|
@ -37,10 +47,11 @@ export class PageAdListAdvertiserComponent implements AfterViewInit
|
|||
{
|
||||
// --- FAUX CODE ---
|
||||
const tabAdvert = this.fictitiousAdvertsService.getTabAdvert(8);
|
||||
this.dataSource = new MatTableDataSource<Advert>(tabAdvert);
|
||||
this.dataSource.sort = this.sort;
|
||||
this.dataSource.paginator = this.paginator;
|
||||
this.dataSource = this.dataSource;
|
||||
this.allInterests = this.fictitiousUtilsService.getTags();
|
||||
|
||||
for(let advert of tabAdvert) this.tabAdvertWithCountViews.push(this.advertToAdvertWithCountViews(advert));
|
||||
this.dataSource = new MatTableDataSource<Advert>();
|
||||
this.onFilter();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -51,7 +62,7 @@ export class PageAdListAdvertiserComponent implements AfterViewInit
|
|||
}
|
||||
|
||||
|
||||
onVisualizeImages(advert: Advert)
|
||||
onVisualizeImages(advert: AdvertWithCountViews)
|
||||
{
|
||||
const config = {
|
||||
width: '30%',
|
||||
|
|
@ -69,24 +80,10 @@ export class PageAdListAdvertiserComponent implements AfterViewInit
|
|||
}
|
||||
|
||||
|
||||
onVisualize(advert: Advert): void
|
||||
{
|
||||
const config = {
|
||||
width: '50%',
|
||||
data: { advert: advert }
|
||||
};
|
||||
this.dialog
|
||||
.open(PopupVisualizeAdAdvertiserComponent, config)
|
||||
.afterClosed()
|
||||
.subscribe(retour => {});
|
||||
}
|
||||
|
||||
|
||||
onAdd(): void
|
||||
{
|
||||
const config = {
|
||||
width: '40%',
|
||||
height: '80%',
|
||||
width: '75%',
|
||||
data: { action: "add", advert: null }
|
||||
};
|
||||
this.dialog
|
||||
|
|
@ -110,11 +107,10 @@ export class PageAdListAdvertiserComponent implements AfterViewInit
|
|||
}
|
||||
|
||||
|
||||
onUpdate(advertToUpdate: Advert): void
|
||||
onUpdate(advertToUpdate: AdvertWithCountViews): void
|
||||
{
|
||||
const config = {
|
||||
width: '40%',
|
||||
height: '80%',
|
||||
width: '75%',
|
||||
data: { action: "update", advert: advertToUpdate }
|
||||
};
|
||||
this.dialog
|
||||
|
|
@ -139,7 +135,7 @@ export class PageAdListAdvertiserComponent implements AfterViewInit
|
|||
}
|
||||
|
||||
|
||||
onDelete(advert: Advert): void
|
||||
onDelete(advert: AdvertWithCountViews): void
|
||||
{
|
||||
const config = {
|
||||
data: { advert: advert }
|
||||
|
|
@ -165,4 +161,85 @@ export class PageAdListAdvertiserComponent implements AfterViewInit
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
onFilter(): void
|
||||
{
|
||||
console.log("b:" + this.formControlInterests.value);
|
||||
this.dataSource.data = [];
|
||||
for(let advert of this.tabAdvertWithCountViews)
|
||||
{
|
||||
let valide: boolean = true;
|
||||
|
||||
if(advert.isVisible && this.visible) valide = true;
|
||||
else if((!advert.isVisible) && this.noVisible) valide = true;
|
||||
else valide = false;
|
||||
|
||||
if(valide)
|
||||
{
|
||||
if ((advert.createdAt === null) && (this.startDate !== null)) valide = false;
|
||||
else if ((advert.createdAt === null) && (this.endDate !== null)) valide = false;
|
||||
else if (this.startDate !== null)
|
||||
{
|
||||
if(this.startDate.getTime() > advert.createdAt.getTime()) valide = false;
|
||||
else if (this.endDate !== null)
|
||||
{
|
||||
if(this.endDate.getTime() < advert.createdAt.getTime()) valide = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(valide) {
|
||||
if(this.formControlInterests.value !== null) {
|
||||
for (let interest of this.formControlInterests.value) {
|
||||
if (advert.interests.indexOf(interest) === -1) {
|
||||
valide = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(valide) this.dataSource.data.push(advert);
|
||||
}
|
||||
|
||||
this.dataSource = new MatTableDataSource(this.dataSource.data);
|
||||
this.dataSource.sort = this.sort;
|
||||
this.dataSource.paginator = this.paginator;
|
||||
}
|
||||
|
||||
|
||||
onNewStartDate(event): void {
|
||||
this.startDate = new Date(event);
|
||||
}
|
||||
|
||||
onNewEndDate(event): void {
|
||||
this.endDate = new Date(event);
|
||||
}
|
||||
|
||||
|
||||
onSliderIsVisible(advert: Advert): void
|
||||
{
|
||||
// il faut envoyer la négation de user.isActive
|
||||
}
|
||||
|
||||
|
||||
advertToAdvertWithCountViews(advert: Advert): AdvertWithCountViews
|
||||
{
|
||||
return {
|
||||
_id: advert._id,
|
||||
userId: advert.userId,
|
||||
title: advert.title,
|
||||
url: advert.url,
|
||||
images: advert.images,
|
||||
interests: advert.interests,
|
||||
comment: advert.comment,
|
||||
views: advert.views,
|
||||
countViews: advert.views.length,
|
||||
isVisible: advert.isVisible,
|
||||
isActive: advert.isActive,
|
||||
createdAt: advert.createdAt,
|
||||
updatedAt: advert.updatedAt,
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,17 @@
|
|||
<div [class]="themeService.getClassTheme()">
|
||||
|
||||
<!-- Navbar -->
|
||||
<!-- titre popup -->
|
||||
<h1 mat-dialog-title>{{title}}</h1>
|
||||
|
||||
<!-- --------------------------------------------------------------------------------------------- -->
|
||||
|
||||
<div style="text-align: center; overflow-y: hidden">
|
||||
<mat-divider></mat-divider><br>
|
||||
|
||||
|
||||
<!-- tous les champs -->
|
||||
<div class="row">
|
||||
|
||||
<!-- title + interests + comments + isVisible -->
|
||||
<div class="col-6">
|
||||
|
||||
<!-- Title -->
|
||||
<mat-form-field appearance="fill">
|
||||
|
|
@ -13,12 +19,8 @@
|
|||
<input matInput type="text" [(ngModel)]="advert.title">
|
||||
</mat-form-field>
|
||||
|
||||
<!-- Images -->
|
||||
<br>
|
||||
<app-drag-and-drop></app-drag-and-drop>
|
||||
|
||||
<!-- Tags -->
|
||||
<app-input-tags [myTags]="advert.tags" (eventEmitter)="onEventInputTags($event)"></app-input-tags>
|
||||
<!-- Interests -->
|
||||
<app-input-interests-ad [myTags]="advert.interests" (eventEmitter)="onEventInputTags($event)"></app-input-interests-ad>
|
||||
|
||||
<!-- Comments -->
|
||||
<mat-form-field class="commentContainer" appearance="fill">
|
||||
|
|
@ -26,12 +28,44 @@
|
|||
<textarea matInput [(ngModel)]="advert.comment"></textarea>
|
||||
</mat-form-field><br>
|
||||
|
||||
<!-- url -->
|
||||
<mat-form-field class="commentContainer" appearance="fill">
|
||||
<mat-label> URL </mat-label>
|
||||
<textarea matInput [(ngModel)]="advert.url"></textarea>
|
||||
</mat-form-field><br>
|
||||
|
||||
<!-- IsVisible -->
|
||||
<mat-checkbox [(ngModel)]="advert.isVisible"> Visible </mat-checkbox>
|
||||
<mat-checkbox [(ngModel)]="advert.isVisible"> Visible </mat-checkbox><br><br>
|
||||
|
||||
<!-- Images déjà présentes -->
|
||||
<div *ngIf="advert.images.length !== 0">
|
||||
<div style="font-weight: bold; margin-bottom: 5px;">
|
||||
Images déjà associées:
|
||||
</div>
|
||||
<div style="margin-left: 20px; padding-left: 2px; border-left: solid 1px #a4a4a4">
|
||||
<div *ngFor="let image of advert.images" style="padding: 2px 0px 2px 0px;">
|
||||
<mat-chip [selectable]="true" [removable]="true" style="font-size: small;">
|
||||
{{image.description}}
|
||||
<button matChipRemove (click)="onRemoveImgAlreadyPresent(image)">
|
||||
<mat-icon>cancel</mat-icon>
|
||||
</button>
|
||||
</mat-chip>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- --------------------------------------------------------------------------------------------- -->
|
||||
<!-- nouvelles images -->
|
||||
<div class="col-6" style="overflow-x: hidden; overflow-y: scroll; max-height: 70vh;">
|
||||
<app-drag-and-drop></app-drag-and-drop>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<br><mat-divider></mat-divider>
|
||||
|
||||
|
||||
<!-- Actions -->
|
||||
<mat-dialog-actions align="end">
|
||||
|
|
|
|||
|
|
@ -8,7 +8,10 @@
|
|||
h1 {
|
||||
text-align: center;
|
||||
font-size: large;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.col-6, .col-8 {
|
||||
border-left: solid 1px #a4a4a4;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -9,11 +9,11 @@ const ADVERT_VIDE: Advert = {
|
|||
_id: "",
|
||||
userId: "",
|
||||
title: "",
|
||||
advertiser: "",
|
||||
url: "",
|
||||
images: [],
|
||||
tags: [],
|
||||
interests: [],
|
||||
comment: "",
|
||||
views: 0,
|
||||
views: [],
|
||||
isVisible: true,
|
||||
isActive: true,
|
||||
createdAt: new Date(),
|
||||
|
|
@ -47,15 +47,15 @@ export class PopupAddOrUpdateAdComponent implements OnInit
|
|||
if(this.data.action === "add")
|
||||
{
|
||||
this.advert = Object.assign({}, ADVERT_VIDE);
|
||||
this.advert.tags = [];
|
||||
this.urlBackend = "advertiser/add/ad" ;
|
||||
this.advert.interests = [];
|
||||
this.urlBackend = "url/add/ad" ;
|
||||
this.title = "Ajouter annonce" ;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.advert = Object.assign({}, this.data.advert);
|
||||
this.advert.tags = this.data.advert.tags.slice();
|
||||
this.urlBackend = "advertiser/update/ad" ;
|
||||
this.advert.interests = this.data.advert.interests.slice();
|
||||
this.urlBackend = "url/update/ad" ;
|
||||
this.title = "Modifier annonce" ;
|
||||
}
|
||||
}
|
||||
|
|
@ -86,32 +86,15 @@ export class PopupAddOrUpdateAdComponent implements OnInit
|
|||
|
||||
onEventInputTags(myTags: string[]): void
|
||||
{
|
||||
this.advert.tags = myTags;
|
||||
this.advert.interests = myTags;
|
||||
}
|
||||
|
||||
|
||||
// Lorsque l'annonceur selectionne des fichiers
|
||||
onSelectFile(event)
|
||||
onRemoveImgAlreadyPresent(image)
|
||||
{
|
||||
const nbFileSelected = event.target.files.length ;
|
||||
for(let i=0 ; i<nbFileSelected ; i++) this.tabWaitingFile.push(event.target.files[i]);
|
||||
this._event = event;
|
||||
}
|
||||
|
||||
// Lorsque l'annonceur "valide" sont choix de fichier selectionné
|
||||
onValidateFiles(): void
|
||||
{
|
||||
const nbFile = this.tabWaitingFile.length;
|
||||
for(let i=0 ; i<nbFile ; i++) this.tabSelectedFile.push(this.tabWaitingFile[i]);
|
||||
this.tabWaitingFile = [];
|
||||
this._event.target.value = "";
|
||||
}
|
||||
|
||||
// Lorsque l'annonceur souhaite supprimer un fichier "validé"
|
||||
onDeleteFile(file: File)
|
||||
{
|
||||
const index = this.tabSelectedFile.findIndex(x => file);
|
||||
this.tabSelectedFile.splice(index, 1);
|
||||
const index = this.advert.images.indexOf(image);
|
||||
console.log("idx: " + index);
|
||||
this.advert.images.slice(index, 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ export class PopupDeleteAdAdvertiserComponent implements OnInit
|
|||
// --- VRAI CODE ---
|
||||
/*
|
||||
this.messageService
|
||||
.sendMessage("advertiser/delete/ad", {"advert": this.advert})
|
||||
.sendMessage("url/delete/ad", {"advert": this.advert})
|
||||
.subscribe( retour => {
|
||||
|
||||
if(retour.status === "error") {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,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.interests"> • {{tag}} </div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -13,9 +13,15 @@
|
|||
onerror="this.onerror=null; this.src='assets/profil.png'">
|
||||
</div>
|
||||
|
||||
<!-- entreprise -->
|
||||
<div class="row myRow">
|
||||
<div class="col-6 myLabel">Entreprise:</div>
|
||||
<div class="col-6 myValue"> {{advertiser.company}} </div>
|
||||
</div>
|
||||
|
||||
<!-- login -->
|
||||
<div class="row myRow">
|
||||
<div class="col-6 myLabel">Login:</div>
|
||||
<div class="col-6 myLabel">Pseudo:</div>
|
||||
<div class="col-6 myValue"> {{advertiser.login}} </div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,12 @@
|
|||
<!-- divider -->
|
||||
<br><mat-divider></mat-divider><br>
|
||||
|
||||
<!-- entreprise -->
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-label>Entreprise</mat-label>
|
||||
<input matInput type="text" [(ngModel)]="advertiserCopy.company">
|
||||
</mat-form-field><br>
|
||||
|
||||
<!-- login -->
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-label>Pseudo</mat-label>
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ export class PopupUpdateAdvertiserComponent implements OnInit
|
|||
dateOfBirth: advertiser0.dateOfBirth,
|
||||
gender: advertiser0.gender,
|
||||
interests: [],
|
||||
company: advertiser0.company,
|
||||
isActive: advertiser0.isActive,
|
||||
isAccepted: advertiser0.isAccepted,
|
||||
createdAt: advertiser0.createdAt,
|
||||
|
|
@ -67,7 +68,7 @@ export class PopupUpdateAdvertiserComponent implements OnInit
|
|||
checkField()
|
||||
{
|
||||
if(this.advertiserCopy.login.length === 0) {
|
||||
this.errorMessage = "Veuillez remplir le champ 'login'" ;
|
||||
this.errorMessage = "Veuillez remplir le champ 'pseudo'" ;
|
||||
this.hasError = true;
|
||||
}
|
||||
else if(this.advertiserCopy.email.length === 0) {
|
||||
|
|
|
|||
|
|
@ -1,32 +0,0 @@
|
|||
<nav class="navbar navbar-expand-lg">
|
||||
|
||||
<!-- PolyNotFound -->
|
||||
<a class="navbar-brand" routerLink="/advertiser/adList"> StreamNotFound </a>
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<!-- [adList] [viewsAd]-->
|
||||
<div class="collapse navbar-collapse">
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item active monLi">
|
||||
<a class="nav-link" routerLink="/advertiser/adList"> Gestion des annonces </a>
|
||||
</li>
|
||||
<li class="nav-item active monLi">
|
||||
<a class="nav-link" routerLink="/advertiser/adList"> Popularité des annonces </a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Mon profil -->
|
||||
<img [src]=urlImage
|
||||
onerror="this.onerror=null; this.src='assets/profil.png'"
|
||||
routerLink="/advertiser/myProfil"
|
||||
alt="">
|
||||
|
||||
<!-- Deconnexion -->
|
||||
<button mat-button class="btnDeconnexion" (click)="onDeconnexion()" routerLink="/">
|
||||
Deconnexion
|
||||
</button>
|
||||
|
||||
</nav>
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
<div [class]="themeService.getClassTheme()">
|
||||
<div class="myContainer">
|
||||
|
||||
|
||||
<!-- Navbar -->
|
||||
<app-navbar-advertiser></app-navbar-advertiser>
|
||||
|
||||
|
||||
|
||||
<!-- Filter -->
|
||||
<div class="filtersContainer mat-elevation-z8">
|
||||
|
||||
<div style="font-weight: bold">Filtre</div>
|
||||
|
||||
<mat-divider></mat-divider><br>
|
||||
|
||||
<div *ngIf="true; then colPeriode"></div>
|
||||
|
||||
<br><mat-divider></mat-divider><br>
|
||||
|
||||
<div style="text-align: right; font-size: small;">
|
||||
<button mat-button (click)="onApplyFilter()" style="font-size: small">Appliquer</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<!-- chart -->
|
||||
<div class="chartContainer">
|
||||
<canvas baseChart
|
||||
[datasets]="lineChartData"
|
||||
[labels]="lineChartLabels"
|
||||
[options]="chartOptions"
|
||||
[colors]="[]"
|
||||
[legend]="true"
|
||||
[chartType]="'line'">
|
||||
</canvas>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ------------------------------------------------------------------------------------------------------------------- -->
|
||||
|
||||
|
||||
<ng-template #colPeriode>
|
||||
|
||||
<!-- startDate -->
|
||||
<mat-form-field appearance="fill" style="width: 140px;">
|
||||
<mat-label>début</mat-label>
|
||||
<input matInput type="date" [ngModel] ="startDate | date:'yyyy-MM-dd'" (ngModelChange)="onNewStartDate($event);">
|
||||
</mat-form-field>
|
||||
-
|
||||
|
||||
<!-- endDate -->
|
||||
<mat-form-field appearance="fill" style="width: 140px;">
|
||||
<mat-label>fin</mat-label>
|
||||
<input matInput type="date" [ngModel] ="endDate | date:'yyyy-MM-dd'" (ngModelChange)="onNewEndDate($event);">
|
||||
</mat-form-field>
|
||||
-
|
||||
|
||||
<!-- step -->
|
||||
<mat-form-field appearance="fill" style="width: 140px;">
|
||||
<mat-label>pas d'affichage</mat-label>
|
||||
<input matInput type="number" [(ngModel)] =step>
|
||||
</mat-form-field>
|
||||
-
|
||||
|
||||
<!-- step unity -->
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-label>unité du pas d'affichage</mat-label>
|
||||
<mat-select [(ngModel)]="stepUnity">
|
||||
<mat-option value="jour">jour</mat-option>
|
||||
<mat-option value="semaine">semaine</mat-option>
|
||||
<mat-option value="mois">mois</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
<!-- ads -->
|
||||
<mat-select [formControl]="formControl" multiple style="padding-top: 10px;">
|
||||
<mat-select-trigger>
|
||||
<span *ngIf="formControl.value?.length > 0">
|
||||
<span *ngFor="let coupleNameViews of formControl.value"> {{coupleNameViews.name}}, </span>
|
||||
</span>
|
||||
</mat-select-trigger>
|
||||
<mat-option *ngFor="let coupleNameViews of allCoupleNameViews" [value]="coupleNameViews">{{coupleNameViews.name}}</mat-option>
|
||||
</mat-select>
|
||||
|
||||
</ng-template>
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
.myContainer {
|
||||
font-size: small;
|
||||
max-width: 100vw;
|
||||
height: 100vh;
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
input {
|
||||
font-size: small;
|
||||
width: 140px;
|
||||
}
|
||||
|
||||
.filtersContainer {
|
||||
background-color: white;
|
||||
width: 60%;
|
||||
margin: 50px 50px 50px 50px;
|
||||
padding: 20px 20px 20px 20px;
|
||||
}
|
||||
|
||||
.chartContainer {
|
||||
background-color: white;
|
||||
border: solid 1px black;
|
||||
padding: 10px 10px 10px 10px;
|
||||
margin: 50px 50px 50px 50px;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------
|
||||
// periode
|
||||
|
||||
.periode {
|
||||
padding: 10px 10px 0px 10px;
|
||||
}
|
||||
|
||||
.periode .titleContainer {
|
||||
text-align: right;
|
||||
border-right: solid 1px #dcdcdc;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
::ng-deep .mat-pseudo-checkbox-checked {
|
||||
background-color: black !important;
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { PagesPopularityComponent } from './pages-popularity.component';
|
||||
|
||||
describe('SubjectsPopularityComponent', () => {
|
||||
let component: PagesPopularityComponent;
|
||||
let fixture: ComponentFixture<PagesPopularityComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ PagesPopularityComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(PagesPopularityComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,234 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
import {FormControl} from "@angular/forms";
|
||||
import {ChartDataSets} from "chart.js";
|
||||
import {Label} from "ng2-charts";
|
||||
import { Router} from "@angular/router";
|
||||
import {FictitiousAdvertsService} from "../../utils/services/fictitiousDatas/fictitiousAdverts/fictitious-adverts.service";
|
||||
import {FictitiousVideosService} from "../../utils/services/fictitiousDatas/fictitiousVideos/fictitious-videos.service";
|
||||
import {ThemeService} from "../../utils/services/theme/theme.service";
|
||||
|
||||
|
||||
|
||||
interface CoupleNameViews {
|
||||
name: string,
|
||||
views: Date[],
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'app-subjects-popularity',
|
||||
templateUrl: './pages-popularity.component.html',
|
||||
styleUrls: ['./pages-popularity.component.scss']
|
||||
})
|
||||
export class PagesPopularityComponent implements OnInit
|
||||
{
|
||||
formControl: FormControl;
|
||||
allCoupleNameViews: CoupleNameViews[] = [];
|
||||
|
||||
startDate: Date = null;
|
||||
endDate: Date = null;
|
||||
step: number = 1;
|
||||
stepUnity: string = "jour" ;
|
||||
|
||||
oneDay: number = 24*60*60*1000;
|
||||
oneWeek: number = 7*24*60*60*1000;
|
||||
|
||||
lineChartData: ChartDataSets[] = [];
|
||||
lineChartLabels: Label[] = [];
|
||||
chartOptions: any = {
|
||||
responsive: true,
|
||||
scales: {
|
||||
yAxes: [{ display: true, scaleLabel: { display: true, labelString: "vues" } }],
|
||||
xAxes: [{ scaleLabel: { display: true, labelString: "temps" } }],
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
constructor( private router: Router,
|
||||
public themeService: ThemeService,
|
||||
private fictitiousAdvertsService: FictitiousAdvertsService,
|
||||
private fictitiousVideosService: FictitiousVideosService ) {}
|
||||
|
||||
|
||||
ngOnInit(): void
|
||||
{
|
||||
if(this.router.url.includes("ads")) this.ngOnInitAds();
|
||||
else if(this.router.url.includes("subjects")) this.ngOnInitSubjects();
|
||||
this.formControl = new FormControl(this.allCoupleNameViews);
|
||||
this.onApplyFilter();
|
||||
}
|
||||
|
||||
|
||||
// Sera excuté si on est sur la page 'adsPopularity'
|
||||
// Remplie l'attribut 'allCoupleNameViews'
|
||||
ngOnInitAds(): void
|
||||
{
|
||||
const allAdverts = this.fictitiousAdvertsService.get_TAB_ADVERT();
|
||||
for(let advert of allAdverts)
|
||||
{
|
||||
let couple = {name: advert.title, views: advert.views }
|
||||
this.allCoupleNameViews.push(couple);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Sera excuté si on est sur la page 'subjectsPopularity'
|
||||
// Remplie l'attribut 'allCoupleNameViews'
|
||||
ngOnInitSubjects(): void
|
||||
{
|
||||
const allVideos = this.fictitiousVideosService.get_TAB_VIDEO();
|
||||
let myMap: Map<string,Date[]> = new Map();
|
||||
|
||||
for(let video of allVideos)
|
||||
{
|
||||
const key = video.interest;
|
||||
if(!myMap.has(key)) myMap.set(key, video.watchedDates);
|
||||
else {
|
||||
let tabDate = myMap.get(key);
|
||||
for(let date0 of video.watchedDates) tabDate = this.insertInOrder(tabDate, date0);
|
||||
myMap.set(key, tabDate);
|
||||
}
|
||||
}
|
||||
|
||||
for(const [key, value] of myMap.entries())
|
||||
{
|
||||
let couple = {name: key, views: value }
|
||||
this.allCoupleNameViews.push(couple);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Applique le filtre
|
||||
onApplyFilter(): void
|
||||
{
|
||||
// --- initialisation ---
|
||||
this.lineChartData = [];
|
||||
this.lineChartLabels = [];
|
||||
|
||||
if(this.step <= 0) this.step = 0;
|
||||
if(this.endDate === null) this.endDate = new Date();
|
||||
if(this.startDate === null) this.startDate = new Date(this.endDate.getTime() - this.oneWeek); // date d'il y a une semaine
|
||||
|
||||
const startTime = this.startDate.getTime();
|
||||
const endTime = this.endDate.getTime();
|
||||
|
||||
|
||||
// --- remplissage de 'lineChartLabels' ---
|
||||
let dataWithZeros = [];
|
||||
let time = startTime;
|
||||
const intervals = [];
|
||||
while(time <= endTime)
|
||||
{
|
||||
dataWithZeros.push(0);
|
||||
this.lineChartLabels.push(this.getLabel(new Date(time)));
|
||||
intervals.push(time);
|
||||
time = this.addStep(time);
|
||||
}
|
||||
intervals.push(time);
|
||||
|
||||
|
||||
// --- remplissage de 'lineChartLabels' ---
|
||||
for(let coupleNameViews of this.formControl.value)
|
||||
{
|
||||
let data = dataWithZeros.slice();
|
||||
let label = coupleNameViews.name;
|
||||
let index = 0;
|
||||
|
||||
for(let date0 of coupleNameViews.views)
|
||||
{
|
||||
const time0 = date0.getTime();
|
||||
|
||||
if(time0 > endTime) break;
|
||||
|
||||
if((startTime <= time0) && (time0 <= endTime))
|
||||
{
|
||||
while((index < intervals.length) && (time0 >= intervals[index])) index += 1;
|
||||
index = index - 1;
|
||||
data[index] += 1;
|
||||
}
|
||||
}
|
||||
|
||||
this.lineChartData.push({"data": data.slice(), "label": label});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
onNewStartDate(event): void {
|
||||
this.startDate = new Date(event);
|
||||
}
|
||||
|
||||
|
||||
onNewEndDate(event): void {
|
||||
this.endDate = new Date(event);
|
||||
}
|
||||
|
||||
|
||||
// Renvoie le bon label pour le graph
|
||||
getLabel(date0: Date): string
|
||||
{
|
||||
if((this.stepUnity === 'jour') && (this.step === 1))
|
||||
{
|
||||
return date0.toLocaleDateString();
|
||||
}
|
||||
else {
|
||||
const time2 = this.addStep(date0.getTime()) - this.oneDay;
|
||||
let date2 = new Date(time2);
|
||||
return date0.toLocaleDateString() + " à " + date2.toLocaleDateString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Ajoute le bon pas à la date 'new Date(time)'
|
||||
addStep(time: number): number
|
||||
{
|
||||
let newDate;
|
||||
|
||||
if(this.stepUnity === 'jour') {
|
||||
newDate = new Date(time + this.step*this.oneDay);
|
||||
}
|
||||
else if(this.stepUnity === 'semaine') {
|
||||
newDate = new Date(time + this.step*this.oneWeek);
|
||||
}
|
||||
else
|
||||
{
|
||||
const oldDate = new Date(time);
|
||||
|
||||
let newMonth = oldDate.getMonth() + this.step;
|
||||
const newYear = oldDate.getFullYear() + (newMonth / 12);
|
||||
newMonth = newMonth % 12;
|
||||
const day = this.startDate.getDate();
|
||||
|
||||
if((newMonth === 1) && ([29, 30, 31].includes(day))) { // si fevrier et si jour n'existe pas
|
||||
newDate = new Date(newYear, newMonth, 28);
|
||||
}
|
||||
else if((day === 31) && ([3, 5, 9, 10].includes(newMonth))) { // si 31 et mois à 30 jours
|
||||
newDate = new Date(newYear, newMonth, 30);
|
||||
}
|
||||
else {
|
||||
newDate = new Date(newYear, newMonth, day);
|
||||
}
|
||||
}
|
||||
|
||||
const _1h = 60*60*1000;
|
||||
if(newDate.getHours() === 23) return newDate.getTime() + _1h;
|
||||
else if(newDate.getHours() === 1) return newDate.getTime() - _1h;
|
||||
else return newDate.getTime();
|
||||
}
|
||||
|
||||
|
||||
// Insere la date0 dans le tableau tabDate par ordre croissant
|
||||
insertInOrder(tabDate: Date[], date0: Date): Date[]
|
||||
{
|
||||
let i = 0;
|
||||
let n = tabDate.length;
|
||||
let time0 = date0.getTime();
|
||||
|
||||
while((i <n) && (time0 > tabDate[i].getTime())) i++;
|
||||
if(i === n) tabDate.push(date0);
|
||||
else tabDate.splice(i, 0, date0);
|
||||
|
||||
return tabDate;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
<nav class="navbar navbar-expand-lg">
|
||||
|
||||
<!-- PolyNotFound -->
|
||||
<a class="navbar-brand" routerLink="/url/adList"> StreamNotFound </a>
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
|
||||
<!-- [adList] [adsPopularity] [subjectsPopularity] -->
|
||||
<div class="collapse navbar-collapse">
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item active monLi">
|
||||
<a *ngIf="(url !== routes[0]) && (url !== routes[1])" [routerLink]="routes[1]" class="nav-link">Gestion des annonces</a>
|
||||
<a *ngIf="(url === routes[0]) || (url === routes[1])" [routerLink]="routes[1]" class="nav-link myActiveLink">Gestion des annonces</a>
|
||||
</li>
|
||||
<li class="nav-item active monLi">
|
||||
<a *ngIf="url !== routes[2]" [routerLink]="routes[2]" class="nav-link">Popularité des annonces</a>
|
||||
<a *ngIf="url === routes[2]" [routerLink]="routes[2]" class="nav-link myActiveLink">Popularité des annonces</a>
|
||||
</li>
|
||||
<li class="nav-item active monLi">
|
||||
<a *ngIf="url !== routes[3]" [routerLink]="routes[3]" class="nav-link">Popularité des domaines</a>
|
||||
<a *ngIf="url === routes[3]" [routerLink]="routes[3]" class="nav-link myActiveLink">Popularité des domaines</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Mon profil -->
|
||||
<img [src]=urlImage
|
||||
onerror="this.onerror=null; this.src='assets/profil.png'"
|
||||
[routerLink]="routes[4]"
|
||||
alt="">
|
||||
|
||||
|
||||
<!-- Deconnexion -->
|
||||
<button mat-button class="btnDeconnexion" (click)="onDeconnexion()" routerLink="/">
|
||||
Deconnexion
|
||||
</button>
|
||||
|
||||
</nav>
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
.navbar {
|
||||
background-color: black;
|
||||
height: 50px;
|
||||
height: 60px;
|
||||
font-size: medium;
|
||||
color: white;
|
||||
}
|
||||
|
|
@ -23,16 +23,22 @@
|
|||
}
|
||||
|
||||
|
||||
// Recherche, Mes Playlists, Historique
|
||||
.monLi {
|
||||
margin: 0px 10px 0px 10px;
|
||||
}
|
||||
|
||||
|
||||
.nav-link {
|
||||
color: white;
|
||||
}
|
||||
.nav-link:hover {
|
||||
color: grey;
|
||||
}
|
||||
.myActiveLink {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
|
||||
// Bonton deconnexion
|
||||
.btnDeconnexion {
|
||||
font-size: medium;
|
||||
margin: 0px 10px 0px 10px
|
||||
|
|
@ -42,11 +48,6 @@
|
|||
}
|
||||
|
||||
|
||||
.monLi {
|
||||
margin: 0px 10px 0px 10px;
|
||||
}
|
||||
|
||||
|
||||
img {
|
||||
border: solid 2px white;
|
||||
border-radius: 50px;
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
import { Component } from '@angular/core';
|
||||
import {Router} from "@angular/router";
|
||||
|
||||
|
||||
|
||||
|
|
@ -9,9 +10,19 @@ import { Component } from '@angular/core';
|
|||
})
|
||||
export class NavbarAdvertiserComponent
|
||||
{
|
||||
routes: string[] = [
|
||||
"/advertiser", // 0
|
||||
"/advertiser/adList", // 1
|
||||
"/advertiser/adsPopularity", // 2
|
||||
"/advertiser/subjectsPopularity", // 3
|
||||
"/advertiser/myProfil" // 4
|
||||
];
|
||||
|
||||
url = this.router.url;
|
||||
|
||||
urlImage: string = "https://www.figurines-goodies.com/1188-large_default/dewey-duck-tales-disney-funko-pop.jpg" ;
|
||||
|
||||
constructor() { }
|
||||
constructor(private router: Router) { }
|
||||
|
||||
onDeconnexion(): void {}
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@ import {PageProfilAdminComponent} from "./admin/myProfil/page-profil-admin/page-
|
|||
import {PageAdListAdminComponent} from "./admin/adList/page-ad-list-admin/page-ad-list-admin.component";
|
||||
import {PageUserListComponent} from "./admin/userList/page-user-list/page-user-list.component";
|
||||
import {PageWatchingVideoComponent} from "./user/watching/page-watching-video/page-watching-video.component";
|
||||
import {PagesPopularityComponent} from "./advertiser/pages-popularity/pages-popularity.component";
|
||||
|
||||
|
||||
const routes: Routes = [
|
||||
|
|
@ -27,7 +28,6 @@ const routes: Routes = [
|
|||
{ path: 'user/myPlaylists', component: PageMyPlaylistsComponent },
|
||||
{ path: 'user/history', component: PageHistoryUserComponent },
|
||||
{ path: 'user/myProfil', component: PageProfilUserComponent },
|
||||
|
||||
{ path: 'user/watching/fromSearch/:videoId/:source/:search', component: PageWatchingVideoComponent },
|
||||
{ path: 'user/watching/fromMyPlaylists/:videoId/:_idPlaylist', component: PageWatchingVideoComponent },
|
||||
{ path: 'user/watching/fromHistory/:videoId/:source', component: PageWatchingVideoComponent },
|
||||
|
|
@ -36,6 +36,8 @@ const routes: Routes = [
|
|||
{ path: 'advertiser', component: PageAdListAdvertiserComponent },
|
||||
{ path: 'advertiser/adList', component: PageAdListAdvertiserComponent },
|
||||
{ path: 'advertiser/myProfil', component: PageProfilAdvertiserComponent },
|
||||
{ path: 'advertiser/adsPopularity', component: PagesPopularityComponent },
|
||||
{ path: 'advertiser/subjectsPopularity', component: PagesPopularityComponent },
|
||||
|
||||
// Admin
|
||||
{ path: 'admin', component: PageUserListComponent },
|
||||
|
|
|
|||
|
|
@ -5,3 +5,20 @@
|
|||
//color: green;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
|
||||
// aura
|
||||
::ng-deep .mat-checkbox-ripple .mat-ripple-element {
|
||||
background-color: grey !important;
|
||||
}
|
||||
|
||||
// contenu coche
|
||||
::ng-deep .mat-checkbox-checked.mat-accent .mat-checkbox-background {
|
||||
background-color: black !important;
|
||||
}
|
||||
|
||||
// indeterminate
|
||||
::ng-deep .mat-checkbox .mat-checkbox-frame {
|
||||
border: solid 1px black !important;
|
||||
background-color: white !important;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@ import {MatDividerModule} from "@angular/material/divider";
|
|||
import {MatCheckboxModule} from "@angular/material/checkbox";
|
||||
import {MatFormFieldModule} from "@angular/material/form-field";
|
||||
import {MatSnackBarModule} from "@angular/material/snack-bar";
|
||||
import { IframeTrackerDirective } from './utils/directives/iframe-tracker/iframe-tracker.directive';
|
||||
import {MatGridListModule} from "@angular/material/grid-list";
|
||||
import { PageMyPlaylistsComponent } from './user/myPlaylists/page-my-playlists/page-my-playlists.component';
|
||||
import { PlaylistListComponent } from './user/myPlaylists/playlist-list/playlist-list.component';
|
||||
|
|
@ -36,22 +35,22 @@ import { PageAdListAdvertiserComponent } from './advertiser/adList/page-ad-list-
|
|||
import { PopupDeleteAdAdvertiserComponent } from './advertiser/adList/popup-delete-ad-advertiser/popup-delete-ad-advertiser.component';
|
||||
import { PopupAddOrUpdateAdComponent } from './advertiser/adList/popup-add-or-update-ad/popup-add-or-update-ad.component';
|
||||
import { PopupVisualizeAdAdvertiserComponent } from './advertiser/adList/popup-visualize-ad-advertiser/popup-visualize-ad-advertiser.component';
|
||||
import { InputTagsComponent } from './advertiser/adList/input-tags/input-tags.component';
|
||||
import { InputInterestsAdComponent } from './advertiser/adList/input-interests-ad/input-interests-ad.component';
|
||||
import {MatChipsModule} from "@angular/material/chips";
|
||||
import {MatAutocompleteModule} from "@angular/material/autocomplete";
|
||||
import {MatSelectModule} from "@angular/material/select";
|
||||
import { PopupVisualizeImagesAdvertiserComponent } from './advertiser/adList/popup-visualize-images-advertiser/popup-visualize-images-advertiser.component';
|
||||
import {IvyCarouselModule} from "angular-responsive-carousel";
|
||||
import { DragAndDropComponent } from './advertiser/adList/drag-and-drop/drag-and-drop.component';
|
||||
import { DragAndDropDirective } from './utils/directives/dragAndDrop/drag-and-drop.directive';
|
||||
import { DragAndDropDirective } from './advertiser/utils/dragAndDrop/drag-and-drop.directive';
|
||||
import { PageProfilUserComponent } from './user/myProfil/page-profil-user/page-profil-user.component';
|
||||
import { NavbarUserComponent } from './user/utils/components/navbar-user/navbar-user.component';
|
||||
import { NavbarAdvertiserComponent } from './advertiser/navbar-advertiser/navbar-advertiser.component';
|
||||
import { NavbarAdminComponent } from './admin/navbar-admin/navbar-admin.component';
|
||||
import { NavbarAdvertiserComponent } from './advertiser/utils/navbar-advertiser/navbar-advertiser.component';
|
||||
import { NavbarAdminComponent } from './admin/utils/navbar-admin/navbar-admin.component';
|
||||
import { PageProfilAdvertiserComponent } from './advertiser/myProfil/page-profil-advertiser/page-profil-advertiser.component';
|
||||
import { PopupUpdateAdvertiserComponent } from './advertiser/myProfil/popup-update-advertiser/popup-update-advertiser.component';
|
||||
import { PopupUpdateUserComponent } from './user/myProfil/popup-update-user/popup-update-user.component';
|
||||
import { NavbarBeforeConnexionComponent } from './beforeConnexion/navbar-before-connexion/navbar-before-connexion.component';
|
||||
import { NavbarBeforeConnexionComponent } from './beforeConnexion/utils/navbar-before-connexion/navbar-before-connexion.component';
|
||||
import {MatRadioModule} from "@angular/material/radio";
|
||||
import { InputInterestsProfilComponent } from './user/myProfil/input-interests-profil/input-interests-profil.component';
|
||||
import { PageProfilAdminComponent } from './admin/myProfil/page-profil-admin/page-profil-admin.component';
|
||||
|
|
@ -70,6 +69,9 @@ import { PopupCreateUserComponent } from './admin/userList/popup-create-user/pop
|
|||
import { InputInterestsAdminComponent } from './admin/userList/input-interests-admin/input-interests-admin.component';
|
||||
import { PageWatchingVideoComponent } from './user/watching/page-watching-video/page-watching-video.component';
|
||||
import {MatDatepickerModule} from "@angular/material/datepicker";
|
||||
import { PagesPopularityComponent } from './advertiser/pages-popularity/pages-popularity.component';
|
||||
import { ChartsModule } from 'ng2-charts';
|
||||
import { PopupDeletePlaylistComponent } from './user/myPlaylists/popup-delete-playlist/popup-delete-playlist.component';
|
||||
|
||||
|
||||
@NgModule({
|
||||
|
|
@ -82,7 +84,6 @@ import {MatDatepickerModule} from "@angular/material/datepicker";
|
|||
AdvertComponent,
|
||||
VideoGridComponent,
|
||||
PopupAddVideoToPlaylistsComponent,
|
||||
IframeTrackerDirective,
|
||||
PageMyPlaylistsComponent,
|
||||
VideoListComponent,
|
||||
PlaylistListComponent,
|
||||
|
|
@ -93,7 +94,7 @@ import {MatDatepickerModule} from "@angular/material/datepicker";
|
|||
PopupDeleteAdAdvertiserComponent,
|
||||
PopupAddOrUpdateAdComponent,
|
||||
PopupVisualizeAdAdvertiserComponent,
|
||||
InputTagsComponent,
|
||||
InputInterestsAdComponent,
|
||||
PopupVisualizeImagesAdvertiserComponent,
|
||||
DragAndDropComponent,
|
||||
DragAndDropDirective,
|
||||
|
|
@ -119,6 +120,8 @@ import {MatDatepickerModule} from "@angular/material/datepicker";
|
|||
PopupCreateUserComponent,
|
||||
InputInterestsAdminComponent,
|
||||
PageWatchingVideoComponent,
|
||||
PagesPopularityComponent,
|
||||
PopupDeletePlaylistComponent,
|
||||
],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
|
|
@ -148,6 +151,7 @@ import {MatDatepickerModule} from "@angular/material/datepicker";
|
|||
MatStepperModule,
|
||||
MatPaginatorModule,
|
||||
MatDatepickerModule,
|
||||
ChartsModule
|
||||
],
|
||||
providers: [],
|
||||
bootstrap: [AppComponent]
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
<div [class]="themeService.getClassTheme()">
|
||||
<div class="myContainer">
|
||||
<div class="bg">
|
||||
|
||||
<app-navbar-before-connexion pour="login"></app-navbar-before-connexion>
|
||||
|
|
@ -15,8 +14,8 @@
|
|||
|
||||
<!-- Login Form -->
|
||||
<form>
|
||||
<input [(ngModel)]="pseudo" type="text" id="login" class="fadeIn second" name="login" placeholder="Login">
|
||||
<input [(ngModel)]="password" type="password" id="password" class="fadeIn third" name="login" placeholder="Mot de passe">
|
||||
<input [(ngModel)]="email" type="text" id="email" class="fadeIn second" name="email" placeholder="Email">
|
||||
<input [(ngModel)]="password" type="password" id="password" class="fadeIn third" name="password" placeholder="Mot de passe">
|
||||
<!-- Message d'erreur -->
|
||||
<div *ngIf="hasError" style="text-align: center; margin-bottom: 20px;">
|
||||
<span class="mat-error"> {{errorMessage}} </span>
|
||||
|
|
@ -35,4 +34,3 @@
|
|||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -144,15 +144,10 @@ input[type=text]::placeholder, input[type=password]::placeholder {
|
|||
color: #cccccc;
|
||||
}
|
||||
|
||||
.myContainer {
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
.bg{
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 80vh;
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
overflow-y: hidden;
|
||||
overflow-x: hidden;
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import {ThemeService} from "../../../utils/services/theme/theme.service";
|
|||
})
|
||||
export class PageLoginComponent implements OnInit
|
||||
{
|
||||
pseudo: string = "" ;
|
||||
email: string = "" ;
|
||||
password: string = "" ;
|
||||
hasError: boolean = false;
|
||||
errorMessage: string = "";
|
||||
|
|
@ -33,8 +33,8 @@ export class PageLoginComponent implements OnInit
|
|||
if(!this.hasError)
|
||||
{
|
||||
let data = {
|
||||
login: this.pseudo,
|
||||
hashPass: this.password
|
||||
email: this.email,
|
||||
hashPass: this.hashage(this.password)
|
||||
};
|
||||
this.messageService
|
||||
.sendMessage('user/auth', data)
|
||||
|
|
@ -58,8 +58,8 @@ export class PageLoginComponent implements OnInit
|
|||
|
||||
checkError(): void
|
||||
{
|
||||
if(this.pseudo === "") {
|
||||
this.errorMessage = "Veuillez remplir le champ login" ;
|
||||
if(this.email === "") {
|
||||
this.errorMessage = "Veuillez remplir le champ email" ;
|
||||
this.hasError = true;
|
||||
}
|
||||
else if(this.password === "") {
|
||||
|
|
@ -72,4 +72,16 @@ export class PageLoginComponent implements OnInit
|
|||
}
|
||||
}
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@
|
|||
|
||||
<!-- Login -->
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-label>Login</mat-label>
|
||||
<mat-label>Pseudo</mat-label>
|
||||
<input matInput type="text" [(ngModel)]="user.login" required>
|
||||
</mat-form-field>
|
||||
<br>
|
||||
|
|
@ -124,9 +124,16 @@
|
|||
<!-- Info personnelles advertiser -->
|
||||
<ng-template #advertiserBlock>
|
||||
|
||||
<!-- Entreprise -->
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-label>Entreprise</mat-label>
|
||||
<input matInput type="text" [(ngModel)]="user.company" required>
|
||||
</mat-form-field>
|
||||
<br>
|
||||
|
||||
<!-- Login -->
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-label>Login</mat-label>
|
||||
<mat-label>Pseudo</mat-label>
|
||||
<input matInput type="text" [(ngModel)]="user.login" required>
|
||||
</mat-form-field>
|
||||
<br>
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ export class PageRegisterComponent
|
|||
dateOfBirth: null,
|
||||
gender: "man",
|
||||
interests: [],
|
||||
company: "",
|
||||
isActive: false,
|
||||
isAccepted: false,
|
||||
createdAt: new Date(),
|
||||
|
|
@ -94,8 +95,12 @@ export class PageRegisterComponent
|
|||
// Check les champs saisies par l'utilisateur
|
||||
checkField(): void
|
||||
{
|
||||
if(this.user.login.length === 0) {
|
||||
this.errorMessage = "Veuillez remplir le champ 'login'.";
|
||||
if((this.user.role.name === 'advertiser') && (this.user.company.length === 0)) {
|
||||
this.errorMessage = "Veuillez remplir le champ 'entreprise'.";
|
||||
this.hasError = true;
|
||||
}
|
||||
else if(this.user.login.length === 0) {
|
||||
this.errorMessage = "Veuillez remplir le champ 'pseudo'.";
|
||||
this.hasError = true;
|
||||
}
|
||||
else if(this.user.email.length === 0) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
.navbar {
|
||||
background-color: black;
|
||||
height: 50px;
|
||||
height: 60px;
|
||||
font-size: medium;
|
||||
color: white;
|
||||
}
|
||||
|
|
@ -33,9 +33,9 @@
|
|||
|
||||
<!-- Date Column -->
|
||||
<ng-container matColumnDef="date">
|
||||
<th mat-header-cell *matHeaderCellDef> Date </th>
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> Date </th>
|
||||
<td mat-cell *matCellDef="let video">
|
||||
{{video.watchedDates[video.watchedDates.length-1] | date:'dd/LL/YYYY à HH:mm:ss'}}
|
||||
{{video.date | date:'dd/LL/YYYY à HH:mm:ss'}}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ input {
|
|||
position: relative;
|
||||
width: 20vw;
|
||||
height: 15vh;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.imgPlay {
|
||||
|
|
|
|||
|
|
@ -11,6 +11,15 @@ import {Router} from "@angular/router";
|
|||
|
||||
|
||||
|
||||
interface VideoHistory {
|
||||
imageUrl: string,
|
||||
title: string,
|
||||
date: Date,
|
||||
source: string,
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'app-page-history-user',
|
||||
templateUrl: './page-history-user.component.html',
|
||||
|
|
@ -37,8 +46,10 @@ export class PageHistoryUserComponent implements AfterViewInit
|
|||
this.userHistoryService.clearTabVideoUrlClicked();
|
||||
|
||||
// --- FAUX CODE ---
|
||||
const tabVideo: VideoAll[] = this.fictitiousVideosService.getTabVideoAll(8);
|
||||
this.dataSource = new MatTableDataSource(tabVideo);
|
||||
const tabVideoAll: VideoAll[] = this.fictitiousVideosService.getTabVideoAll(8);
|
||||
let tabVideoHistory: VideoHistory[] = [];
|
||||
for(let videoAll of tabVideoAll) tabVideoHistory.push(this.videoAllToVideoHistory(videoAll));
|
||||
this.dataSource = new MatTableDataSource(tabVideoHistory);
|
||||
this.dataSource.sort = this.sort;
|
||||
this.dataSource.paginator = this.paginator;
|
||||
this.dataSource = this.dataSource;
|
||||
|
|
@ -67,15 +78,6 @@ export class PageHistoryUserComponent implements AfterViewInit
|
|||
}
|
||||
|
||||
|
||||
// Retourne la source de la video en fonction de l'url
|
||||
getSourceByUrl(url: string): string
|
||||
{
|
||||
if(url.includes("youtu")) return "Youtube" ;
|
||||
else if(url.includes("daily")) return "Dailymotion" ;
|
||||
else return "???" ;
|
||||
}
|
||||
|
||||
|
||||
// Supprime la video
|
||||
onDelete(video: VideoAll): void
|
||||
{
|
||||
|
|
@ -109,4 +111,15 @@ export class PageHistoryUserComponent implements AfterViewInit
|
|||
this.router.navigateByUrl(url);
|
||||
}
|
||||
|
||||
|
||||
videoAllToVideoHistory(videoAll: VideoAll): VideoHistory
|
||||
{
|
||||
return {
|
||||
imageUrl: videoAll.imageUrl,
|
||||
title: videoAll.title,
|
||||
date: videoAll.watchedDates[videoAll.watchedDates.length-1],
|
||||
source: videoAll.source,
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,23 +9,35 @@
|
|||
</div>
|
||||
|
||||
|
||||
|
||||
<!-- Liste des playlist -->
|
||||
<div class="row" style="margin: 0px">
|
||||
<div class="playlistListContainer">
|
||||
<div *ngFor="let playlist of tabPlaylist" class="playlistContainer">
|
||||
<button class="btnPlaylist" (click)="eventEmitter.emit(playlist)">
|
||||
|
||||
<div [class]="getClassOfPlaylistContainer(playlist)" (click)="eventEmitter.emit(playlist); playlistFocusedOn = playlist">
|
||||
<div class="col-2"></div>
|
||||
<div class="col-8" style="text-align: center">
|
||||
<span class="playlistName"> {{playlist.name}} </span><br>
|
||||
<span class="playListCount" *ngIf="playlist.videoIds.length <= 1"> {{playlist.videoIds.length}} vidéo </span>
|
||||
<span class="playListCount" *ngIf="playlist.videoIds.length > 1"> {{playlist.videoIds.length}} vidéos </span>
|
||||
</div>
|
||||
<div class="col-2" style="text-align: right">
|
||||
<button mat-icon-button (click)="onDeletePlaylist(playlist)">
|
||||
<mat-icon>delete</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<!-- Bouton creer playlist-->
|
||||
<div class="row btnCreerPlaylistContainer" >
|
||||
<button mat-button class="btnCreerPlaylist" (click)="onCreatePlaylist()"> Creer playlist </button>
|
||||
<button mat-button class="btnCreerPlaylist" (click)="onCreatePlaylist()"> Créer une playlist </button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -15,7 +15,9 @@
|
|||
text-align: center;
|
||||
margin: 0px 0px 0px 0px;
|
||||
padding: 10px 0px 10px 0px;
|
||||
background-color: #dcdcdc;
|
||||
//background-color: #dcdcdc;
|
||||
background: linear-gradient(top, rgba(38,38,38,0.8), #e6e6e6 25%, #fff 38%, #c5c5c5 87%, rgba(38,38,38,0.8));
|
||||
background: -webkit-linear-gradient(top, #c5c5c5, #e6e6e6 25%, #fff 38%, #c5c5c5 87%, #c5c5c5);
|
||||
font-size: large;
|
||||
border-bottom: solid 1px black;
|
||||
border-top-left-radius: 10px;
|
||||
|
|
@ -35,23 +37,36 @@
|
|||
height: 60vh;
|
||||
overflow-y: scroll;
|
||||
padding: 0px;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.playlistContainer {
|
||||
max-width: 100%;
|
||||
padding: 0px;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
|
||||
.btnPlaylist {
|
||||
background-color: white;
|
||||
padding: 20px;
|
||||
border-bottom: solid 1px black;
|
||||
width: 100%;
|
||||
//width: 100%;
|
||||
width: 35vw;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
.btnPlaylist:hover {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.btnPlaylistFocus {
|
||||
background-color: #e6e6e6;
|
||||
}
|
||||
.btnPlaylistFocus:hover {
|
||||
background-color: #e6e6e6;
|
||||
}
|
||||
|
||||
|
||||
.playListCount {
|
||||
color: gray;
|
||||
font-style: italic;
|
||||
|
|
@ -70,4 +85,10 @@
|
|||
|
||||
.btnCreerPlaylist {
|
||||
margin: 0px 0px 0px 0px;
|
||||
border-bottom-left-radius: 10px;
|
||||
border-bottom-right-radius: 10px;
|
||||
background: linear-gradient(top, rgba(38,38,38,0.8), #e6e6e6 25%, #fff 38%, #c5c5c5 87%, rgba(38,38,38,0.8));
|
||||
background: -webkit-linear-gradient(top, #c5c5c5, #e6e6e6 25%, #fff 38%, #c5c5c5 87%, #c5c5c5);
|
||||
//background: linear-gradient(180deg, #e6e6e6 0%, rgba(0,0,0,0.25) 49%, rgba(38,38,38,0.6) 51%, rgba(0,0,0,0.25) 100%);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
|
||||
import {ThemeService} from "../../../utils/services/theme/theme.service";
|
||||
import {PlaylistDB} from "../../../utils/interfaces/playlist";
|
||||
import {MessageService} from "../../../utils/services/message/message.service";
|
||||
import {MatDialog} from "@angular/material/dialog";
|
||||
import {MatSnackBar} from "@angular/material/snack-bar";
|
||||
import {PopupCreatePlaylistComponent} from "../popup-create-playlist/popup-create-playlist.component";
|
||||
import {FictitiousVideosService} from "../../../utils/services/fictitiousDatas/fictitiousVideos/fictitious-videos.service";
|
||||
import {PopupDeletePlaylistComponent} from "../popup-delete-playlist/popup-delete-playlist.component";
|
||||
|
||||
|
||||
|
||||
|
|
@ -20,6 +20,7 @@ export class PlaylistListComponent implements OnInit
|
|||
@Output() eventEmitter = new EventEmitter<PlaylistDB>(); // pour envoyer au parent la playlist selectionner
|
||||
search: string = "" ; // contenu de la barre de recherche
|
||||
tabPlaylist: PlaylistDB[] = []; // playlist affichées
|
||||
playlistFocusedOn: PlaylistDB;
|
||||
|
||||
|
||||
constructor( public themeService: ThemeService,
|
||||
|
|
@ -30,15 +31,14 @@ export class PlaylistListComponent implements OnInit
|
|||
|
||||
ngOnInit(): void
|
||||
{
|
||||
//this.allPlaylists = this.fictitiousVideosService.getRandomTabPlaylistDB(10, 10);
|
||||
this.allPlaylists = this.fictitiousVideosService.getNoRandomTabPlaylistDB(10);
|
||||
this.tabPlaylist = [].concat(this.allPlaylists);
|
||||
}
|
||||
|
||||
|
||||
// s'execute lorsqu'on écrit sur la barre de recherche
|
||||
whileSearch()
|
||||
{
|
||||
console.log("whileSearch");
|
||||
this.tabPlaylist = [];
|
||||
for(let playlist of this.allPlaylists)
|
||||
{
|
||||
|
|
@ -47,6 +47,7 @@ export class PlaylistListComponent implements OnInit
|
|||
}
|
||||
|
||||
|
||||
// click sur créer playlist
|
||||
onCreatePlaylist(): void
|
||||
{
|
||||
const config = { data: this.tabPlaylist };
|
||||
|
|
@ -55,16 +56,52 @@ export class PlaylistListComponent implements OnInit
|
|||
.afterClosed()
|
||||
.subscribe(playlist => {
|
||||
|
||||
const config = { duration: 1000, panelClass: "custom-class" };
|
||||
const config = { duration: 1500, panelClass: "custom-class" };
|
||||
if((playlist === null) || (playlist === undefined)) {
|
||||
this.snackBar.open("Opération annulée", "", config);
|
||||
}
|
||||
else {
|
||||
this.allPlaylists.push(playlist);
|
||||
this.tabPlaylist.push(playlist);
|
||||
this.snackBar.open("La playlist a bien été créée ✔", "", config);
|
||||
this.snackBar.open(`La playlist '${playlist.name}' a bien été créée ✔`, "", config);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// click sur supprimer playlist
|
||||
onDeletePlaylist(playlist: PlaylistDB): void
|
||||
{
|
||||
const config = {data: playlist};
|
||||
this.dialog
|
||||
.open(PopupDeletePlaylistComponent, config)
|
||||
.afterClosed()
|
||||
.subscribe(retour => {
|
||||
|
||||
const config = { duration: 1500, panelClass: "custom-class" };
|
||||
if((retour === null) || (retour === undefined)) {
|
||||
this.snackBar.open("Opération annulée", "", config);
|
||||
}
|
||||
else {
|
||||
let index = this.allPlaylists.indexOf(playlist);
|
||||
if(index >= 0) this.allPlaylists.splice(index, 1);
|
||||
|
||||
index = this.tabPlaylist.indexOf(playlist);
|
||||
if(index >= 0) this.tabPlaylist.splice(index, 1);
|
||||
|
||||
this.eventEmitter.emit(null);
|
||||
this.playlistFocusedOn = null;
|
||||
this.snackBar.open(`La playlist '${playlist.name}' a bien été suprimée ✔`, "", config);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// retourne la class CSS de conteneur de playlist
|
||||
getClassOfPlaylistContainer(playlist: PlaylistDB): string
|
||||
{
|
||||
if(playlist === this.playlistFocusedOn) return "row btnPlaylist btnPlaylistFocus" ;
|
||||
else return "row btnPlaylist" ;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
<mat-dialog-content class="mat-typography">
|
||||
Êtes-vous sûr de vouloir supprimer <i>{{playlist.name}}</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>
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { PopupDeletePlaylistComponent } from './popup-delete-playlist.component';
|
||||
|
||||
describe('PopupDeletePlaylistComponent', () => {
|
||||
let component: PopupDeletePlaylistComponent;
|
||||
let fixture: ComponentFixture<PopupDeletePlaylistComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ PopupDeletePlaylistComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(PopupDeletePlaylistComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
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-playlist',
|
||||
templateUrl: './popup-delete-playlist.component.html',
|
||||
styleUrls: ['./popup-delete-playlist.component.scss']
|
||||
})
|
||||
export class PopupDeletePlaylistComponent implements OnInit
|
||||
{
|
||||
playlist;
|
||||
|
||||
constructor( public dialogRef: MatDialogRef<PopupDeletePlaylistComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public data,
|
||||
private messageService: MessageService ) { }
|
||||
|
||||
ngOnInit(): void
|
||||
{
|
||||
this.playlist = this.data;
|
||||
}
|
||||
|
||||
onValidate(): void
|
||||
{
|
||||
this.dialogRef.close(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -37,26 +37,24 @@
|
|||
<mat-grid-list cols="12" rowHeight="15vh">
|
||||
|
||||
<!-- btnAdd -->
|
||||
<mat-grid-tile [colspan]="1" [rowspan]="1">
|
||||
<mat-grid-tile [colspan]="2" [rowspan]="1">
|
||||
<button mat-icon-button (click)="onAdd(video)">
|
||||
<mat-icon> add_circle </mat-icon>
|
||||
</button>
|
||||
</mat-grid-tile>
|
||||
|
||||
<!-- imgVideo -->
|
||||
<mat-grid-tile [colspan]="10" [rowspan]="1">
|
||||
<div class="col-8">
|
||||
<mat-grid-tile [colspan]="8" [rowspan]="1">
|
||||
<div style="margin: auto; width: 20vw; height: 15vh;">
|
||||
<div class="imgsContainer" (click)="onVideo(video)">
|
||||
<img class="imgPlay" src="/assets/play.png">
|
||||
<img class="imgVideo" [src]="video.imageUrl">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</mat-grid-tile>
|
||||
|
||||
<!-- btnDelete -->
|
||||
<mat-grid-tile [colspan]="1" [rowspan]="1">
|
||||
<mat-grid-tile [colspan]="2" [rowspan]="1">
|
||||
<button mat-icon-button (click)="onDelete(video, i)">
|
||||
<mat-icon>delete</mat-icon>
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
.myContainer {
|
||||
background-color: white ;
|
||||
//background-color: white ;
|
||||
background: linear-gradient(top, rgba(38,38,38,0.8), #e6e6e6 25%, #fff 38%, #c5c5c5 87%, rgba(38,38,38,0.8));
|
||||
background: -webkit-linear-gradient(top, #c5c5c5, #e6e6e6 25%, #fff 38%, #c5c5c5 87%, #c5c5c5);
|
||||
text-align: center;
|
||||
width: 35vw;
|
||||
margin: 1vh 0vh 3vh 0vh;
|
||||
|
|
@ -13,7 +15,9 @@
|
|||
|
||||
.topBorder {
|
||||
margin: 0px 0px 0px 0px;
|
||||
background-color: #dcdcdc;
|
||||
//background-color: #dcdcdc;
|
||||
background: linear-gradient(top, rgba(38,38,38,0.8), #e6e6e6 25%, #fff 38%, #c5c5c5 87%, rgba(38,38,38,0.8));
|
||||
background: -webkit-linear-gradient(top, #c5c5c5, #e6e6e6 25%, #fff 38%, #c5c5c5 87%, #c5c5c5);
|
||||
text-align: left;
|
||||
padding: 5px 0px 5px 5px;
|
||||
border-bottom: solid 1px black;
|
||||
|
|
@ -45,6 +49,7 @@
|
|||
position: relative;
|
||||
width: 20vw;
|
||||
height: 15vh;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.imgPlay {
|
||||
|
|
@ -67,7 +72,9 @@
|
|||
|
||||
.bottomBorder {
|
||||
margin: 0px 0px 0px 0px;
|
||||
background-color: #dcdcdc;
|
||||
//background-color: #dcdcdc;
|
||||
background: linear-gradient(top, rgba(38,38,38,0.8), #e6e6e6 25%, #fff 38%, #c5c5c5 87%, rgba(38,38,38,0.8));
|
||||
background: -webkit-linear-gradient(top, #c5c5c5, #e6e6e6 25%, #fff 38%, #c5c5c5 87%, #c5c5c5);
|
||||
border-top: solid 1px black;
|
||||
border-bottom: solid 1px black;
|
||||
font-size: large;
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ export class VideoListComponent implements OnChanges
|
|||
{
|
||||
@Input() playlist: PlaylistDB;
|
||||
videosInPlaylist: VideoAll[] = [];
|
||||
allUserVideos: VideoAll[] = this.fictitiousVideosService.getAllVideoAll();
|
||||
allUserVideos: VideoAll[] = this.fictitiousVideosService.get_TAB_VIDEO();
|
||||
|
||||
|
||||
constructor( private messageService: MessageService,
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@
|
|||
|
||||
<!-- login -->
|
||||
<div class="row myRow">
|
||||
<div class="col-8 myLabel">Login:</div>
|
||||
<div class="col-8 myLabel">Pseudo:</div>
|
||||
<div class="col-4 myValue"> {{user.login}} </div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@
|
|||
|
||||
<!-- login -->
|
||||
<div class="form-group row myRow">
|
||||
<label for="login" class="col-sm-6 col-form-label myLeftLabel">Login:</label>
|
||||
<label for="login" class="col-sm-6 col-form-label myLeftLabel">Pseudo:</label>
|
||||
<div class="col-sm-6">
|
||||
<input type="text" class="form-control myValue" id="login" [(ngModel)]="userCopy.login">
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ export class PopupUpdateUserComponent implements OnInit
|
|||
dateOfBirth: user0.dateOfBirth,
|
||||
gender: user0.gender,
|
||||
interests: [],
|
||||
company: "",
|
||||
isActive: user0.isActive,
|
||||
isAccepted: user0.isAccepted,
|
||||
createdAt: user0.createdAt,
|
||||
|
|
@ -67,7 +68,7 @@ export class PopupUpdateUserComponent implements OnInit
|
|||
checkField()
|
||||
{
|
||||
if(this.userCopy.login.length === 0) {
|
||||
this.errorMessage = "Veuillez remplir le champ 'login'." ;
|
||||
this.errorMessage = "Veuillez remplir le champ 'pseudo'." ;
|
||||
this.hasError = true;
|
||||
}
|
||||
else if(this.userCopy.email.length === 0) {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
|
||||
<!-- Grille -->
|
||||
<div style="height: 93%">
|
||||
<div style="height: 93%; background-color: white; padding-top: 7px;">
|
||||
<mat-grid-list cols="3" rowHeight="33%">
|
||||
<mat-grid-tile colspan="1" rowspan="1" *ngFor="let k of [0,1,2,3,4,5,6,7,8]">
|
||||
<div class="myCell" *ngIf="indexPage+k < tabVideo.length" [title]="tabVideo[indexPage+k].title">
|
||||
|
|
@ -16,16 +16,16 @@
|
|||
|
||||
|
||||
<!-- Info video -->
|
||||
<mat-grid-list cols="12" style="margin: 0px 0px 0px 0px; font-size: small">
|
||||
<mat-grid-list cols="12" class="mat-grid-list-info-video">
|
||||
|
||||
<!-- logo -->
|
||||
<mat-grid-tile [colspan]="2" [rowspan]="2" class="mat-grid-tile-info-video">
|
||||
<mat-grid-tile [colspan]="2" [rowspan]="2" class="mat-grid-tile-info-video" (click)="onVideo(tabVideo[indexPage+k])">
|
||||
<img *ngIf="tabVideo[indexPage+k].source==='youtube'" src="/assets/logo_plateforms/youtube.png" alt="ytb" width="20px" height="15px">
|
||||
<img *ngIf="tabVideo[indexPage+k].source==='dailymotion'" src="/assets/logo_plateforms/dailymotion.png" alt="dlm" width="20px" height="20px">
|
||||
</mat-grid-tile>
|
||||
|
||||
<!-- title + views + publishedAt -->
|
||||
<mat-grid-tile [colspan]="8" [rowspan]="2" class="mat-grid-tile-info-video">
|
||||
<mat-grid-tile [colspan]="8" [rowspan]="2" class="mat-grid-tile-info-video" (click)="onVideo(tabVideo[indexPage+k])">
|
||||
<div style="position: absolute; left: 1px; text-align: left">
|
||||
{{tronquage(tabVideo[indexPage+k].title)}}
|
||||
<br>
|
||||
|
|
@ -54,7 +54,7 @@
|
|||
|
||||
|
||||
<!-- Paginator -->
|
||||
<div class="btnContainer">
|
||||
<div class="paginatorContainer">
|
||||
|
||||
<!-- btn précédent -->
|
||||
<button mat-button class="btnPaginator" [disabled]="indexPage<=0" (click)="indexPage=indexPage-9"> < Précédent </button>
|
||||
|
|
|
|||
|
|
@ -7,12 +7,19 @@ mat-grid-list {
|
|||
mat-grid-tile {
|
||||
margin: 0px 0px 0px 0px;
|
||||
padding: 0px 0px 0px 0px;
|
||||
border: solid 1px black;
|
||||
}
|
||||
|
||||
.myCell {
|
||||
margin: 0px 0px 0px 0px;
|
||||
padding: 7px 0px 0px 0px;
|
||||
margin: 7px 0px 0px 0px;
|
||||
padding: 0px 0px 0px 0px;
|
||||
background-color: white;
|
||||
border: solid 1px black;
|
||||
border-bottom-left-radius: 2px;
|
||||
border-bottom-right-radius: 2px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.myCell:hover {
|
||||
background-color: #d2d2d2;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -20,22 +27,22 @@ mat-grid-tile {
|
|||
|
||||
|
||||
.imgsContainer {
|
||||
width: 20vw;
|
||||
//width: 20vw;
|
||||
width: 18vw;
|
||||
height: 15vh;
|
||||
}
|
||||
|
||||
.imgPlay {
|
||||
position: absolute;
|
||||
margin-left: 9vw;
|
||||
width: 3vw;
|
||||
margin-left: 8vw;
|
||||
width: 2.5vw;
|
||||
margin-top: 5vh;
|
||||
height: 6vh;
|
||||
height: 5vh;
|
||||
padding: 0px 0px 0px 0px;
|
||||
}
|
||||
|
||||
.imgVideo {
|
||||
border: solid 1px black;
|
||||
width: 20vw;
|
||||
width: 18vw;
|
||||
height: 15vh;
|
||||
padding: 0px 0px 0px 0px;
|
||||
}
|
||||
|
|
@ -44,9 +51,16 @@ mat-grid-tile {
|
|||
// ---------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
.mat-grid-list-info-video {
|
||||
margin: 0px 0px 0px 0px;
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
.mat-grid-tile-info-video {
|
||||
border: none;
|
||||
font-size: x-small;
|
||||
//background: linear-gradient(top, rgba(38,38,38,0.8), #e6e6e6 25%, #fff 38%, #c5c5c5 87%, rgba(38,38,38,0.8));
|
||||
//background: -webkit-linear-gradient(top, #c5c5c5, #e6e6e6 25%, #fff 38%, #c5c5c5 87%, #c5c5c5);
|
||||
}
|
||||
|
||||
mat-icon {
|
||||
|
|
@ -57,10 +71,11 @@ mat-icon {
|
|||
// ---------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
.btnContainer {
|
||||
.paginatorContainer {
|
||||
margin: 0px 0px 0px 0px;
|
||||
padding: 0px 0px 0px 0px;
|
||||
padding: 5px 0px 0px 0px;
|
||||
text-align: center;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.btnPaginator {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
<span class="helper"></span>
|
||||
<img [src]="'assets/pub/'+ad.images[idxImage].url"
|
||||
[alt]="ad.images[idxImage].url"
|
||||
(click)="onClick()"
|
||||
id="imgFromSearchOrMyPlaylists">
|
||||
</div>
|
||||
|
||||
|
|
@ -10,6 +11,7 @@
|
|||
<img *ngIf="from === 'watchingLeft'"
|
||||
[src]="'assets/pub/'+ad.images[idxImage].url"
|
||||
[alt]="ad.images[idxImage].url"
|
||||
(click)="onClick()"
|
||||
id="imgFromWatchingLeft">
|
||||
|
||||
<!-- --------------------------------------------------------------------- -->
|
||||
|
|
@ -17,4 +19,5 @@
|
|||
<img *ngIf="from === 'watchingRight'"
|
||||
[src]="'assets/pub/'+ad.images[idxImage].url"
|
||||
[alt]="ad.images[idxImage].url"
|
||||
(click)="onClick()"
|
||||
id="imgFromWatchingRight">
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import {Component, Input, OnInit} from '@angular/core';
|
||||
import {Advert} from "../../../../utils/interfaces/advert";
|
||||
import {ThemeService} from "../../../../utils/services/theme/theme.service";
|
||||
import {Router} from "@angular/router";
|
||||
|
||||
|
||||
|
||||
|
|
@ -15,16 +15,17 @@ export class AdvertComponent implements OnInit
|
|||
@Input() from: string = "search";
|
||||
idxImage: number = 0;
|
||||
|
||||
|
||||
constructor(public themeService: ThemeService) { }
|
||||
|
||||
constructor(private router: Router) { }
|
||||
|
||||
ngOnInit(): void
|
||||
{
|
||||
const nbImages = this.ad.images.length;
|
||||
this.idxImage = Math.floor(Math.random() * nbImages);
|
||||
}
|
||||
|
||||
|
||||
onClick(): void
|
||||
{
|
||||
document.location.href = this.ad.url;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,27 +6,33 @@
|
|||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
|
||||
<!-- [Recherche] [Mes Playlists] [Historique] -->
|
||||
<div class="collapse navbar-collapse">
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item active monLi">
|
||||
<a class="nav-link" routerLink="/user/search"> Rechercher </a>
|
||||
<a *ngIf="(url !== routes[0]) && (url !== routes[1])" [routerLink]="routes[1]" class="nav-link">Rechercher</a>
|
||||
<a *ngIf="(url === routes[0]) || (url === routes[1])" [routerLink]="routes[1]" class="nav-link myActiveLink">Rechercher</a>
|
||||
</li>
|
||||
<li class="nav-item active monLi">
|
||||
<a class="nav-link" routerLink="/user/myPlaylists"> Mes playlists </a>
|
||||
<a *ngIf="url !== routes[2]" [routerLink]="routes[2]" class="nav-link">Mes playlists</a>
|
||||
<a *ngIf="url === routes[2]" [routerLink]="routes[2]" class="nav-link myActiveLink">Mes playlists</a>
|
||||
</li>
|
||||
<li class="nav-item active monLi">
|
||||
<a class="nav-link" routerLink="/user/history"> Historique </a>
|
||||
<a *ngIf="url !== routes[3]" [routerLink]="routes[3]" class="nav-link">Historique</a>
|
||||
<a *ngIf="url === routes[3]" [routerLink]="routes[3]" class="nav-link myActiveLink">Historique</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Mon profil -->
|
||||
<img [src]=urlImage
|
||||
onerror="this.onerror=null; this.src='assets/profil.png'"
|
||||
routerLink="/user/myProfil"
|
||||
[routerLink]="routes[4]"
|
||||
alt="">
|
||||
|
||||
|
||||
<!-- Deconnexion -->
|
||||
<button mat-button class="btnDeconnexion" (click)="onDeconnexion()" routerLink="/">
|
||||
Deconnexion
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
.navbar {
|
||||
background-color: black;
|
||||
height: 50px;
|
||||
height: 60px;
|
||||
font-size: medium;
|
||||
color: white;
|
||||
}
|
||||
|
|
@ -23,16 +23,22 @@
|
|||
}
|
||||
|
||||
|
||||
// Recherche, Mes Playlists, Historique
|
||||
.monLi {
|
||||
margin: 0px 10px 0px 10px;
|
||||
}
|
||||
|
||||
|
||||
.nav-link {
|
||||
color: white;
|
||||
}
|
||||
.nav-link:hover {
|
||||
color: grey;
|
||||
}
|
||||
.myActiveLink {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
|
||||
// Bonton deconnexion
|
||||
.btnDeconnexion {
|
||||
font-size: medium;
|
||||
margin: 0px 10px 0px 10px
|
||||
|
|
@ -42,11 +48,6 @@
|
|||
}
|
||||
|
||||
|
||||
.monLi {
|
||||
margin: 0px 10px 0px 10px;
|
||||
}
|
||||
|
||||
|
||||
img {
|
||||
border: solid 2px white;
|
||||
border-radius: 50px;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import {Component} from '@angular/core';
|
||||
import {Router} from "@angular/router";
|
||||
|
||||
|
||||
|
||||
|
|
@ -9,9 +10,19 @@ import {Component} from '@angular/core';
|
|||
})
|
||||
export class NavbarUserComponent
|
||||
{
|
||||
routes: string[] = [
|
||||
"/user", // 0
|
||||
"/user/search", // 1
|
||||
"/user/myPlaylists", // 2
|
||||
"/user/history", // 3
|
||||
"/user/myProfil" // 4
|
||||
];
|
||||
|
||||
url = this.router.url;
|
||||
|
||||
urlImage: string = "https://www.figurines-goodies.com/1185-thickbox_default/huey-duck-tales-disney-funko-pop.jpg" ;
|
||||
|
||||
constructor() { }
|
||||
constructor(private router: Router) { }
|
||||
|
||||
onDeconnexion(): void {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -202,13 +202,20 @@
|
|||
<!-- Liste des videos -->
|
||||
<div class="listVideoContainer">
|
||||
<div *ngFor="let video0 of videosInPlaylist; let i = index;">
|
||||
<div class="videoCell">
|
||||
<div class="imgsContainer" (click)="this.video = video0">
|
||||
<div [class]="getClassOfVideoCell(video0)" (click)="this.video = video0">
|
||||
<div class="imgsContainer">
|
||||
<img class="imgPlay" src="/assets/play.png">
|
||||
<img class="imgVideo" [src]="video0.imageUrl">
|
||||
</div>
|
||||
<div class="titleContainer">
|
||||
{{video0.title}}
|
||||
<div class="infoContainer">
|
||||
<div class="titleContainer">{{video0.title}}</div>
|
||||
<div class="viewsContainer">
|
||||
<!-- <span>{{video.views | number: '1.0-0'}}</span> <mat-icon>visibility</mat-icon> -->
|
||||
{{video.views | number: '1.0-0'}} vues
|
||||
</div>
|
||||
<span class="publishedAtContainer">
|
||||
Publiée le {{ video.publishedAt | date:'dd/LL/YYYY à HH:mm:ss' }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -216,9 +223,11 @@
|
|||
|
||||
|
||||
<!-- Bordure basse -->
|
||||
<!--
|
||||
<div class="bottomBorder">
|
||||
<div style="visibility: hidden">a</div>
|
||||
</div>
|
||||
-->
|
||||
|
||||
</div>
|
||||
</ng-template>
|
||||
|
|
|
|||
|
|
@ -29,14 +29,20 @@
|
|||
.playlistContainer {
|
||||
border: solid 1px black;
|
||||
width: 98%;
|
||||
border-top-right-radius: 10px;
|
||||
border-top-left-radius: 10px;
|
||||
}
|
||||
|
||||
.topBorder {
|
||||
margin: 0px 0px 0px 0px;
|
||||
background-color: #dcdcdc;
|
||||
//background-color: #dcdcdc;
|
||||
background: linear-gradient(top, rgba(38,38,38,0.8), #e6e6e6 25%, #fff 38%, #c5c5c5 87%, rgba(38,38,38,0.8));
|
||||
background: -webkit-linear-gradient(top, #c5c5c5, #e6e6e6 25%, #fff 38%, #c5c5c5 87%, #c5c5c5);
|
||||
text-align: left;
|
||||
padding: 5px 0px 5px 5px;
|
||||
border-bottom: solid 1px black;
|
||||
border-top-right-radius: 10px;
|
||||
border-top-left-radius: 10px;
|
||||
}
|
||||
|
||||
.listVideoContainer {
|
||||
|
|
@ -49,7 +55,19 @@
|
|||
margin: 0px 0px 0px 0px;
|
||||
padding: 10px 0px 10px 10px;
|
||||
border-bottom: solid 1px black;
|
||||
cursor: pointer;
|
||||
}
|
||||
.videoCell:hover {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.videoCellFocus {
|
||||
background-color: #e6e6e6;
|
||||
}
|
||||
.videoCellFocus:hover {
|
||||
background-color: #e6e6e6;
|
||||
}
|
||||
|
||||
|
||||
// ----
|
||||
|
||||
|
|
@ -76,14 +94,40 @@
|
|||
padding: 0px 0px 0px 0px;
|
||||
}
|
||||
|
||||
.titleContainer {
|
||||
// ----
|
||||
|
||||
.infoContainer {
|
||||
display: table-cell;
|
||||
margin-left: 13vw;
|
||||
height: 10vh;
|
||||
padding-left: 2px;
|
||||
padding-left: 5px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.titleContainer {
|
||||
font-weight: bold;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.viewsContainer {
|
||||
text-align: left;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: x-small;
|
||||
color: grey;
|
||||
}
|
||||
mat-icon {
|
||||
vertical-align: middle;
|
||||
//font-size: x-small;
|
||||
}
|
||||
|
||||
.publishedAtContainer {
|
||||
text-align: left;
|
||||
font-size: x-small;
|
||||
color: grey;
|
||||
}
|
||||
|
||||
|
||||
// ----
|
||||
|
||||
.bottomBorder {
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ export class PageWatchingVideoComponent implements OnInit
|
|||
this.from = "myPlaylists";
|
||||
const _idPlaylist = this.activatedRoute.snapshot.paramMap.get('_idPlaylist');
|
||||
this.playlist = this.fictitiousVideosService.getPlaylistBy_id(_idPlaylist);
|
||||
const allVideo = this.fictitiousVideosService.getAllVideoAll();
|
||||
const allVideo = this.fictitiousVideosService.get_TAB_VIDEO();
|
||||
this.videosInPlaylist = [];
|
||||
for(let _idVideo of this.playlist.videoIds)
|
||||
{
|
||||
|
|
@ -117,4 +117,13 @@ export class PageWatchingVideoComponent implements OnInit
|
|||
else if(source === 'dailymotion') videoUrl = "https://www.dailymotion.com/embed/video/" + videoId;
|
||||
return this._sanitizer.bypassSecurityTrustResourceUrl(videoUrl);
|
||||
}
|
||||
|
||||
|
||||
// retourne la classe CSS de videoCell
|
||||
getClassOfVideoCell(video0: VideoAll): string
|
||||
{
|
||||
if(video0 === this.video) return "videoCell videoCellFocus" ;
|
||||
else return "videoCell" ;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
import { IframeTrackerDirective } from './iframe-tracker.directive';
|
||||
|
||||
describe('IframeTrackerDirective', () => {
|
||||
it('should create an instance', () => {
|
||||
const directive = new IframeTrackerDirective();
|
||||
expect(directive).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
import {
|
||||
Directive,
|
||||
ElementRef,
|
||||
OnInit,
|
||||
Renderer2,
|
||||
Input,
|
||||
Output,
|
||||
EventEmitter,
|
||||
HostListener
|
||||
} from '@angular/core';
|
||||
|
||||
@Directive({
|
||||
selector: '[appIframeTracker]'
|
||||
})
|
||||
export class IframeTrackerDirective implements OnInit {
|
||||
private iframeMouseOver: boolean;
|
||||
|
||||
@Input() debug: boolean;
|
||||
|
||||
@Output() iframeClick = new EventEmitter<ElementRef>();
|
||||
|
||||
constructor(private el: ElementRef, private renderer: Renderer2) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.renderer.listen(window, 'blur', () => this.onWindowBlur());
|
||||
}
|
||||
|
||||
@HostListener('mouseover')
|
||||
private onIframeMouseOver() {
|
||||
this.log('Iframe mouse over');
|
||||
this.iframeMouseOver = true;
|
||||
this.resetFocusOnWindow();
|
||||
}
|
||||
|
||||
@HostListener('mouseout')
|
||||
private onIframeMouseOut() {
|
||||
this.log('Iframe mouse out');
|
||||
this.iframeMouseOver = false;
|
||||
this.resetFocusOnWindow();
|
||||
}
|
||||
|
||||
private onWindowBlur() {
|
||||
if (this.iframeMouseOver) {
|
||||
this.log('WOW! Iframe click!!!');
|
||||
this.resetFocusOnWindow();
|
||||
this.iframeClick.emit(this.el);
|
||||
}
|
||||
}
|
||||
|
||||
private resetFocusOnWindow() {
|
||||
setTimeout(() => {
|
||||
this.log('reset focus to window');
|
||||
window.focus();
|
||||
}, 100);
|
||||
}
|
||||
|
||||
private log(message: string) {
|
||||
if (this.debug) {
|
||||
console.log(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,14 +3,35 @@ export interface Advert
|
|||
_id: string,
|
||||
userId: string,
|
||||
title: string,
|
||||
advertiser: string,
|
||||
url: string,
|
||||
images: {
|
||||
url: string,
|
||||
description: string,
|
||||
}[],
|
||||
tags: string[],
|
||||
interests: string[],
|
||||
comment: string,
|
||||
views: number,
|
||||
views: Date[],
|
||||
isVisible: boolean,
|
||||
isActive: boolean,
|
||||
createdAt: Date,
|
||||
updatedAt: Date,
|
||||
}
|
||||
|
||||
|
||||
|
||||
export interface AdvertWithCountViews {
|
||||
_id: string,
|
||||
userId: string,
|
||||
title: string,
|
||||
url: string,
|
||||
images: {
|
||||
url: string,
|
||||
description: string,
|
||||
}[],
|
||||
interests: string[],
|
||||
comment: string,
|
||||
views: Date[],
|
||||
countViews: number,
|
||||
isVisible: boolean,
|
||||
isActive: boolean,
|
||||
createdAt: Date,
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ export interface User
|
|||
dateOfBirth: Date,
|
||||
gender: string,
|
||||
interests: string[],
|
||||
company: string,
|
||||
isActive: boolean,
|
||||
isAccepted: boolean,
|
||||
lastConnexion: Date,
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@ export interface VideoDB
|
|||
userId: string,
|
||||
videoId: string,
|
||||
source: string,
|
||||
tags: String[],
|
||||
tags: string[],
|
||||
interest: string,
|
||||
watchedDates: Date[],
|
||||
createdAt: Date,
|
||||
updatedAt: Date
|
||||
|
|
@ -18,6 +19,7 @@ export interface VideoAll
|
|||
videoId: string,
|
||||
source: string,
|
||||
tags: String[],
|
||||
interest: string,
|
||||
watchedDates: Date[],
|
||||
createdAt: Date,
|
||||
updatedAt: Date
|
||||
|
|
|
|||
|
|
@ -9,15 +9,26 @@ const TAB_ADVERT: Advert[] = [
|
|||
_id: "idNutella",
|
||||
userId: "userId",
|
||||
title: "pot de nutella XXL",
|
||||
advertiser: "nutella",
|
||||
url: "https://www.nutella.com/fr/fr/",
|
||||
images: [
|
||||
{ url: "nutella_v_1.jpeg", description: "image nutella 1" },
|
||||
{ url: "nutella_v_2.png", description: "image nutella 2" },
|
||||
{ url: "nutella_v_3.jpg", description: "image nutella 3" }
|
||||
],
|
||||
tags: [ "rock", "basket" ],
|
||||
interests: [ "rock", "basket" ],
|
||||
comment: "pub pour vacances de noêl",
|
||||
views: 5,
|
||||
views: [
|
||||
new Date(2021,10,1),
|
||||
new Date(2021,10,2),
|
||||
new Date(2021,10,3),
|
||||
new Date(2021,10,3),
|
||||
new Date(2021,10,5),
|
||||
new Date(2021,10,5),
|
||||
new Date(2021,10,5),
|
||||
new Date(2021,10,5),
|
||||
new Date(2021,10,5),
|
||||
new Date(2021,10,7)
|
||||
],
|
||||
isVisible: true,
|
||||
isActive: true,
|
||||
createdAt: new Date(),
|
||||
|
|
@ -27,19 +38,58 @@ const TAB_ADVERT: Advert[] = [
|
|||
_id: "idRolex",
|
||||
userId: "userId",
|
||||
title: "Rolex",
|
||||
advertiser: "rolex",
|
||||
url: "https://www.rolex.com",
|
||||
images: [
|
||||
{ url: "rolex_v_1.jpg", description: "rolex 1" },
|
||||
{ url: "rolex_v_2.png", description: "rolex 2" },
|
||||
],
|
||||
tags: [ "rock", "rap" ],
|
||||
interests: [ "rock", "rap" ],
|
||||
comment: "pub pour cette année",
|
||||
views: 2,
|
||||
views: [
|
||||
new Date(2021,10,5),
|
||||
new Date(2021,10,6),
|
||||
new Date(2021,10,7),
|
||||
new Date(2021,10,8),
|
||||
new Date(2021,10,8),
|
||||
new Date(2021,10,8),
|
||||
new Date(2021,10,25),
|
||||
new Date(2021,10,25),
|
||||
new Date(2021,10,25),
|
||||
new Date(2021,10,27)
|
||||
],
|
||||
isVisible: true,
|
||||
isActive: true,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
},
|
||||
{
|
||||
_id: "idAlbion",
|
||||
userId: "userId",
|
||||
title: "Albion new version",
|
||||
url: "https://www.rolex.com",
|
||||
images: [
|
||||
{ url: "rolex_v_1.jpg", description: "albion 1" },
|
||||
{ url: "rolex_v_2.png", description: "albion 2" },
|
||||
],
|
||||
interests: [ "rock", "rap" ],
|
||||
comment: "pub pour cette année",
|
||||
views: [
|
||||
new Date(2021,10,3),
|
||||
new Date(2021,10,4),
|
||||
new Date(2021,10,4),
|
||||
new Date(2021,10,5),
|
||||
new Date(2021,10,5),
|
||||
new Date(2021,10,6),
|
||||
new Date(2021,10,6),
|
||||
new Date(2021,10,8),
|
||||
new Date(2021,10,8),
|
||||
new Date(2021,10,8)
|
||||
],
|
||||
isVisible: true,
|
||||
isActive: true,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
|
|
@ -58,7 +108,7 @@ export class FictitiousAdvertsService
|
|||
const idx = Math.floor(Math.random() * TAB_ADVERT.length);
|
||||
let advert = Object.assign({}, TAB_ADVERT[idx]);
|
||||
advert._id = advert._id + this.fictitiousUtilsService.makeid(5);
|
||||
advert.tags = advert.tags.slice();
|
||||
advert.interests = advert.interests.slice();
|
||||
advert.isVisible = (Math.random() < 0.5);
|
||||
return advert;
|
||||
}
|
||||
|
|
@ -71,4 +121,10 @@ export class FictitiousAdvertsService
|
|||
return tabAdvert;
|
||||
}
|
||||
|
||||
|
||||
get_TAB_ADVERT(): Advert[]
|
||||
{
|
||||
return TAB_ADVERT;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ const USER: User = {
|
|||
dateOfBirth: new Date(),
|
||||
gender: "man",
|
||||
interests: ["foot", "jeux-vidéo"],
|
||||
company: "",
|
||||
isActive: true,
|
||||
isAccepted: true,
|
||||
lastConnexion: new Date(),
|
||||
|
|
@ -37,6 +38,7 @@ const ADVERTISER: User = {
|
|||
dateOfBirth: null,
|
||||
gender: "",
|
||||
interests: [],
|
||||
company: "My company",
|
||||
isActive: true,
|
||||
isAccepted: true,
|
||||
lastConnexion: new Date(),
|
||||
|
|
@ -57,6 +59,7 @@ const ADMIN: User = {
|
|||
dateOfBirth: null,
|
||||
gender: "",
|
||||
interests: [],
|
||||
company: "",
|
||||
isActive: true,
|
||||
isAccepted: true,
|
||||
lastConnexion: new Date(),
|
||||
|
|
|
|||
|
|
@ -13,7 +13,15 @@ const TAB_VIDEO: VideoAll[] = [
|
|||
userId: "userId",
|
||||
source: "youtube",
|
||||
tags: [ "rap", "musique" ],
|
||||
watchedDates: [new Date()],
|
||||
interest: "PNL",
|
||||
watchedDates: [
|
||||
new Date(2021, 10, 15),
|
||||
new Date(2021, 10, 16),
|
||||
new Date(2021, 10, 17),
|
||||
new Date(2021, 10, 18),
|
||||
new Date(2021, 10, 19),
|
||||
new Date(2021, 10, 20),
|
||||
],
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
|
||||
|
|
@ -30,6 +38,7 @@ const TAB_VIDEO: VideoAll[] = [
|
|||
userId: "userId",
|
||||
source: "youtube",
|
||||
tags: [ "rap", "musique" ],
|
||||
interest: "PNL",
|
||||
watchedDates: [new Date()],
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
|
|
@ -47,6 +56,7 @@ const TAB_VIDEO: VideoAll[] = [
|
|||
userId: "userId",
|
||||
source: "youtube",
|
||||
tags: [ "rap", "musique" ],
|
||||
interest: "PNL",
|
||||
watchedDates: [new Date()],
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
|
|
@ -64,6 +74,7 @@ const TAB_VIDEO: VideoAll[] = [
|
|||
userId: "userId",
|
||||
source: "youtube",
|
||||
tags: [ "rap", "musique" ],
|
||||
interest: "PNL",
|
||||
watchedDates: [new Date()],
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
|
|
@ -81,6 +92,7 @@ const TAB_VIDEO: VideoAll[] = [
|
|||
userId: "userId",
|
||||
source: "dailymotion",
|
||||
tags: [ "rap", "musique" ],
|
||||
interest: "PNL",
|
||||
watchedDates: [new Date()],
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
|
|
@ -98,6 +110,7 @@ const TAB_VIDEO: VideoAll[] = [
|
|||
userId: "userId",
|
||||
source: "youtube",
|
||||
tags: [ "rap", "musique" ],
|
||||
interest: "Nekfeu",
|
||||
watchedDates: [new Date()],
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
|
|
@ -115,6 +128,7 @@ const TAB_VIDEO: VideoAll[] = [
|
|||
userId: "userId",
|
||||
source: "youtube",
|
||||
tags: [ "rap", "musique" ],
|
||||
interest: "Nekfeu",
|
||||
watchedDates: [new Date()],
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
|
|
@ -132,6 +146,7 @@ const TAB_VIDEO: VideoAll[] = [
|
|||
userId: "userId",
|
||||
source: "youtube",
|
||||
tags: [ "rap", "musique" ],
|
||||
interest: "Nekfeu",
|
||||
watchedDates: [new Date()],
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
|
|
@ -149,6 +164,7 @@ const TAB_VIDEO: VideoAll[] = [
|
|||
userId: "userId",
|
||||
source: "dailymotion",
|
||||
tags: [ "rap", "musique" ],
|
||||
interest: "Columbine",
|
||||
watchedDates: [new Date()],
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
|
|
@ -166,6 +182,7 @@ const TAB_VIDEO: VideoAll[] = [
|
|||
userId: "userId",
|
||||
source: "dailymotion",
|
||||
tags: [ "rap", "musique" ],
|
||||
interest: "Columbine",
|
||||
watchedDates: [new Date()],
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
|
|
@ -210,7 +227,7 @@ export class FictitiousVideosService
|
|||
}
|
||||
|
||||
|
||||
getAllVideoAll(): VideoAll[]
|
||||
get_TAB_VIDEO(): VideoAll[]
|
||||
{
|
||||
return TAB_VIDEO;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,3 +29,24 @@ body { margin: 0; }
|
|||
-o-background-size: cover;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
|
||||
// aura
|
||||
::ng-deep .mat-checkbox-ripple .mat-ripple-element {
|
||||
background-color: grey !important;
|
||||
}
|
||||
|
||||
// contenu coche
|
||||
::ng-deep .mat-checkbox-checked.mat-accent .mat-checkbox-background {
|
||||
background-color: black !important;
|
||||
}
|
||||
|
||||
// indeterminate
|
||||
::ng-deep .mat-checkbox .mat-checkbox-frame {
|
||||
border: solid 1px black !important;
|
||||
background-color: white !important;
|
||||
}
|
||||
|
|
|
|||
Reference in a new issue