Compare commits

...
This repository has been archived on 2026-05-01. You can view files and clone it, but you cannot make any changes to it's state, such as pushing and creating new issues, pull requests or comments.

21 commits

Author SHA1 Message Date
MiharyR
89e35a1fbb correction des pages 'adsPopularity' et 'subjectsPopularity' 2022-01-01 12:41:04 +01:00
Yûki VACHOT
a9eaa3d93e Merge remote-tracking branch 'origin/front-user-advertiser' into front-user-advertiser 2021-12-26 18:49:45 +01:00
Yûki VACHOT
efa2a0129a Update: Add npm start in production mode 2021-12-26 18:49:13 +01:00
MiharyR
2d95837985 ajout de la guard 2021-12-24 15:58:45 +01:00
Yûki VACHOT
c18fd4c24d Update: Environment for Heroku Production 2021-12-22 23:49:47 +01:00
Yûki VACHOT
f47c9df512 Merge remote-tracking branch 'origin/front-user-advertiser' into front-user-advertiser 2021-12-22 23:09:06 +01:00
Yûki VACHOT
2d837bdf2e Update: Environment for Heroku Production 2021-12-22 23:08:55 +01:00
2320a58eff
Update package.json 2021-12-22 21:14:25 +01:00
bbb468878e
Update package.json 2021-12-22 21:14:12 +01:00
Yûki VACHOT
bc7a3c1bc0 Update: Environment for Heroku Production 2021-12-22 13:58:08 +01:00
Yûki VACHOT
71a6f877ca Update: Environment for Heroku Production 2021-12-22 13:55:49 +01:00
Yûki VACHOT
13daf10ca8 Update: Environment for Heroku Production 2021-12-22 13:39:06 +01:00
MiharyR
5fbdb7098e
Delete admin directory 2021-12-21 13:35:41 +01:00
MiharyR
f80fee841f
Delete angular.json 2021-12-21 13:00:33 +01:00
MiharyR
00df25e8ff
Delete karma.conf.js 2021-12-21 12:58:25 +01:00
MiharyR
e51fabfe64
Delete tsconfig.app.json 2021-12-21 12:57:48 +01:00
MiharyR
eea9f714d6
Delete tsconfig.json 2021-12-21 12:57:30 +01:00
MiharyR
007391f124
Delete tsconfig.spec.json 2021-12-21 12:57:17 +01:00
MiharyR
006e58a922
Delete tslint.json 2021-12-21 12:57:01 +01:00
MiharyR
427d837b35
Suppression de l'ancien frontend 2021-12-21 12:56:16 +01:00
MiharyR
d62915bfe5 separation des fronts 2021-12-21 12:47:33 +01:00
148 changed files with 539 additions and 6486 deletions

7
.gitignore vendored
View file

@ -12,7 +12,6 @@
# profiling files
chrome-profiler-events*.json
speed-measure-plugin*.json
# IDEs and editors
/.idea
@ -40,13 +39,7 @@ npm-debug.log
yarn-error.log
testem.log
/typings
*.env
# System Files
.DS_Store
Thumbs.db
/backend/database/
/backend/node_modules/
package-lock.json

View file

@ -1,18 +1,19 @@
# Frontend
# UserAndAdvertiser
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 11.2.7.
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 12.2.14.
## Development server
Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
## Code scaffolding
à
Run `ng generate component component-title` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.
Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.
## Build
Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build.
Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory.
Then run `npm start`
## Running unit tests
@ -20,7 +21,7 @@ Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.
## Running end-to-end tests
Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).
Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities.
## Further help

View file

@ -3,11 +3,14 @@
"version": 1,
"newProjectRoot": "projects",
"projects": {
"frontend": {
"userAndAdvertiser": {
"projectType": "application",
"schematics": {
"@schematics/angular:component": {
"style": "scss"
},
"@schematics/angular:application": {
"strict": true
}
},
"root": "",
@ -17,12 +20,12 @@
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/frontend",
"outputPath": "dist/frontend-userAndAdvertiser",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.app.json",
"aot": true,
"inlineStyleLanguage": "scss",
"assets": [
"src/favicon.ico",
"src/assets"
@ -32,56 +35,57 @@
"src/styles.scss",
"node_modules/bootstrap/scss/bootstrap.scss"
],
"scripts": [
"node_modules/jquery/dist/jquery.js",
"node_modules/bootstrap/dist/js/bootstrap.js"
]
"scripts": []
},
"configurations": {
"production": {
"budgets": [
{
"type": "initial",
"maximumWarning": "1mb",
"maximumError": "2mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "2kb",
"maximumError": "4kb"
}
],
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"namedChunks": false,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"budgets": [
{
"type": "initial",
"maximumWarning": "2mb",
"maximumError": "5mb"
"outputHashing": "all"
},
{
"type": "anyComponentStyle",
"maximumWarning": "6kb",
"maximumError": "10kb"
}
]
}
"development": {
"buildOptimizer": false,
"optimization": false,
"vendorChunk": true,
"extractLicenses": false,
"sourceMap": true,
"namedChunks": true
}
},
"defaultConfiguration": "production"
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "frontend:build"
},
"configurations": {
"production": {
"browserTarget": "frontend:build:production"
}
"browserTarget": "userAndAdvertiser:build:production"
},
"development": {
"browserTarget": "userAndAdvertiser:build:development"
}
},
"defaultConfiguration": "development"
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "frontend:build"
"browserTarget": "userAndAdvertiser:build"
}
},
"test": {
@ -91,44 +95,19 @@
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.spec.json",
"karmaConfig": "karma.conf.js",
"inlineStyleLanguage": "scss",
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"./node_modules/@angular/material/prebuilt-themes/indigo-pink.css",
"src/styles.scss"
],
"scripts": []
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"tsconfig.app.json",
"tsconfig.spec.json",
"e2e/tsconfig.json"
],
"exclude": [
"**/node_modules/**"
]
}
},
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
"options": {
"protractorConfig": "e2e/protractor.conf.js",
"devServerTarget": "frontend:serve"
},
"configurations": {
"production": {
"devServerTarget": "frontend:serve:production"
}
}
}
}
}
},
"defaultProject": "frontend"
"defaultProject": "userAndAdvertiser"
}

View file

@ -1,26 +0,0 @@
const request = require("request");
const VideoCategories = require("../models/objects/video.categories.model");
function asyncRequest(uri, option){
return new Promise(function(resolve){
request(uri, option,function (error, response, body){
resolve({response: response, body: JSON.parse(body)});
});
});
}
module.exports.asyncRequest = asyncRequest;
function asyncInterest(interest, source){
return new Promise(function(resolve){
for(const i in VideoCategories){
for(const j in VideoCategories[i].categories){
if((VideoCategories[i].categories[j].name === interest || VideoCategories[i].categories[j].id === interest)
&& VideoCategories[i].categories[j].source === source){
resolve(VideoCategories[i].interest);
}
}
}
resolve(null);
});
}
module.exports.asyncInterest = asyncInterest;

View file

@ -1,26 +0,0 @@
if(process.env.YOUTUBE_API_KEY === undefined ||
process.env.YOUTUBE_API_KEY === '' ||
process.env.DAILYMOTION_API_KEY === undefined ||
process.env.DAILYMOTION_API_KEY === ''){
console.log('Error Env YOUTUBE_API_KEY & DAILYMOTION_API_KEY Variables');
process.exit();
}
console.log('Env variables YOUTUBE_API_KEY & DAILYMOTION_API_KEY received');
module.exports = {
youtube: {
name: "Youtube",
shortname: "yt",
baseAPIUrl: 'https://youtube.googleapis.com/youtube/v3',
baseChannelUrl: 'https://www.youtube.com/channel/',
YOUTUBE_API_KEY: process.env.YOUTUBE_API_KEY
},
dailymotion: {
name: "Dailymotion",
shortname: "dm",
baseAPIUrl: 'https://api.dailymotion.com',
baseChannelUrl: 'https://www.dailymotion.com/',
DAILYMOTION_API_KEY: process.env.DAILYMOTION_API_KEY
}
};

View file

@ -1,4 +0,0 @@
module.exports = {
prodUrl: process.env.DATABASE,
devUrl: "mongodb://127.0.0.1:27017/polynotfound"
};

View file

@ -1,9 +0,0 @@
function sendMessage (res, successCode, data, token=null) {
res.status(200).json({ status: 'success', successCode: successCode, token: token, data: data });
}
function sendError (res, statusCode, errorCode, reason, token=null) {
res.status(statusCode).json({ status: 'error', errorCode: errorCode, token: token, reason: reason});
}
module.exports = { sendMessage, sendError };

View file

@ -1,109 +0,0 @@
const sessionJWTConfig = require ('jsonwebtoken');
require('dotenv').config({ path: './app-backend/.env' });
const {sendError} = require ("./response.config");
if(process.env.JWTRS256_PRIVATE_KEY === undefined || process.env.JWTRS256_PUBLIC_KEY === undefined){
console.log('Error Env JWTRS256_PRIVATE_KEY & JWTRS256_PUBLIC_KEY Variables');
process.exit();
}
console.log('Env variables JWTRS256_PRIVATE_KEY & JWTRS256_PUBLIC_KEY received');
const JWTRS256_PRIVATE_KEY = Buffer.from(process.env.JWTRS256_PRIVATE_KEY, 'base64').toString('utf-8');
const JWTRS256_PUBLIC_KEY = Buffer.from(process.env.JWTRS256_PUBLIC_KEY, 'base64').toString('utf-8');
function createSessionJWT (id, email, profileImageUrl, role) {
return sessionJWTConfig.sign(
{
id: id,
email: email,
profileImageUrl: profileImageUrl,
role: role,
midExp: Math.floor(Date.now() / 1000) + 1800
},
JWTRS256_PRIVATE_KEY,
{
algorithm: 'RS256',
expiresIn: '1h'
}
);
}
function createSessionCookie(req, res, payload) {
let jwtToken;
if (typeof payload.id !== 'undefined' &&
typeof payload.email !== 'undefined' &&
typeof payload.profileImageUrl !== 'undefined' &&
typeof payload.role !== 'undefined' &&
typeof payload.midExp !== 'undefined' &&
(Math.floor(Date.now() / 1000) <= payload.midExp)) {
jwtToken = req.headers.cookie;
}
else {
jwtToken = createSessionJWT(payload.id, payload.email, payload.profileImageUrl, payload.role);
}
res.cookie('SESSIONID', jwtToken, {httpOnly:true, secure:false});
}
function decodeSessionCookie(sessionid) {
if (typeof sessionid === 'undefined') {
return {id: -1, email: -1, profileImageUrl: -1, role: -1};
}
try {
const token = sessionJWTConfig.verify(
sessionid,
JWTRS256_PUBLIC_KEY,
{algorithms: ['RS256']});
return {token: token};
}
catch (err) {
return {id: -1, email: -1, profileImageUrl: -1, role: -1};
}
}
function getSession(sessionid) {
return decodeSessionCookie(sessionid);
}
module.exports.getSession = getSession
function setSessionCookie (req, res, session) {
createSessionCookie(req, res, session);
}
module.exports.setSessionCookie = setSessionCookie;
function getToken(session) {
if (typeof session === 'undefined' || typeof session.token === 'undefined') return -1;
return session.token;
}
module.exports.getToken = getToken;
function checkLogin(req, res, role=null){
if(typeof req.cookies !== 'undefined'){
const session = getSession(req.cookies.SESSIONID);
const token = getToken(session);
if(typeof token.email === 'undefined' ||
token.email === -1 ||
typeof token.id === 'undefined' ||
token.id === -1){
return sendError(res, 500, 102, "User not authenticated.");
} else {
token.midExp = new Date(token.midExp*1000);
token.iat = new Date(token.iat*1000);
token.exp = new Date(token.exp*1000);
if(role === null){
return token;
} else {
if(typeof token.role !== 'undefined' &&
((Array.isArray(role) && role.includes(token.role)) ||
( typeof role === 'object' && typeof token.role.permission !== 'undefined' && token.role.permission >= role.permission && token.role.isAccepted === true))){
return token;
} else {
return sendError(res, 500, 106, "User doesn't have permission.", token);
}
}
}
} else {
return sendError(res, 500, -1, "Cookies don't exist.");
}
}
module.exports.checkLogin = checkLogin;

View file

@ -1,290 +0,0 @@
const db = require("../models/mongodb.model");
const {sendError, sendMessage} = require ("../config/response.config");
const {checkLogin} = require("../config/sessionJWT.config");
const ObjectId = require('mongoose').Types.ObjectId;
const roles = require("../models/objects/role.model");
const Ad = db.ads;
// Create a new Ad
exports.create = (req, res) => {
const token = checkLogin(req, res, roles.Advertiser);
if(token && req.body.title){
Ad.exists({title: req.body.title, userId: token.id, isActive: true}, function (err, docs){
if(err){
sendError(res, 500,100,err.message || "Some error occurred while checking if the Ad already exists.", token);
} else{
if(docs === null) {
let ad;
ad = new Ad({
userId: token.id,
title: req.body.title,
images: req.body.images ? req.body.images : undefined,
url: req.body.url ? req.body.url : undefined,
interests: req.body.interests ? req.body.interests : undefined,
comment: req.body.comment ? req.body.comment : undefined,
isVisible: req.body.isVisible ? req.body.isVisible : undefined,
isActive: req.body.isActive ? req.body.isActive : undefined
});
// Save User in the database
ad
.save(ad)
.then(data => {
return sendMessage(res, 41, data, token)
})
.catch(err => {
return sendError(res, 500,100,err.message || "Some error occurred while creating the Ad.", token);
});
} else{
return sendError(res, 500, 104, err || `Ad ${req.body.title} already exists.`, token);
}
}
});
} else {
return sendError(res, 500, -1, `No title given`, token);
}
};
// Retrieve all Ad from id if admin or session id
exports.findAll = (req, res) => {
const token = checkLogin(req, res, roles.Advertiser);
if(token){
let query = {};
let condition;
const adId = req.query.adId;
condition = adId ? adId : undefined;
query._id = condition;
let userId;
if(typeof token.role !== 'undefined' &&
typeof token.role.permission !== 'undefined' &&
typeof token.role.isAccepted !== 'undefined' &&
token.role.isAccepted === true &&
token.role.permission >= roles.Admin.permission) {
userId = req.query.userId;
} else {
userId = token.id;
}
condition = userId ? userId : undefined;
query.userId = condition;
const title = req.query.title;
condition = title ? { $regex: new RegExp(title), $options: "i" } : undefined;
query.title = condition;
const url = req.query.url;
condition = url ? { $regex: new RegExp(url), $options: "i" } : undefined;
query.url = condition;
const interests = req.query.interests;
condition = interests ? {$in: interests.split(',')} : undefined;
query["interests.interest"] = condition
const comment = req.query.comment;
condition = comment ? { $regex: new RegExp(comment), $options: "i" } : undefined;
query.comment = condition;
const isVisible = req.query.isVisible;
condition = isVisible ? isVisible : undefined;
query.isVisible = condition;
const isActive = req.query.isActive;
condition = isActive ? isActive : undefined;
query.isActive = condition;
const sort = req.query.sort;
if(sort !== 'undefined'){
switch (sort){
case 'asc':
condition = {title: 1};
break;
case 'desc':
condition = {title: -1};
break;
case 'createdAtAsc':
condition = {createdAt: 1};
break;
case 'createdAtDesc':
condition = {createdAt: -1};
break;
case 'updatedAtAsc':
condition = {updatedAt: 1};
break;
case 'updatedAtDesc':
condition = {updatedAt: -1};
break;
default:
condition = {title: 1};
}
}
const query_sort = {sort: condition};
// Remove undefined key
Object.keys(query).forEach(key => query[key] === undefined ? delete query[key] : {});
console.log(query);
Ad.find(query, {}, query_sort)
.then(data => {
if(data){
return sendMessage(res, 42, data, token);
}
})
.catch(err => {
return sendError(res,500,100,err.message || "Some error occurred while finding the Ads.", token);
});
}
};
// Find single Ad from id if admin or session id
exports.findOne = (req, res) => {
const token = checkLogin(req, res, roles.Advertiser);
if(token && typeof req.params.id !== 'undefined') {
const id = req.params.id;
if(id && ObjectId.isValid(id)){
Ad.findById(id, {})
.then(data => {
if(data){
return sendMessage(res, 43, data, token);
} else {
return sendError(res,404,105,`Ad not found with id=${id}`, token);
}
})
.catch(err => {
return sendError(res,500,100,err.message || `Some error occurred while finding the Ad with id=${id}`, token);
});
} else {
return sendError(res, 500, -1, `Error id is not valid`, token);
}
} else {
return sendError(res, 500, -1, `No id given`, token);
}
};
// Update a Ad with ad id
exports.update = (req, res) => {
const token = checkLogin(req, res, roles.Advertiser);
if(token && typeof req.params.id !== 'undefined') {
const id = req.params.id;
if(typeof req.body._id !== 'undefined' || typeof req.body.id !== 'undefined'){
return sendError(res, 500, -1, `User do not have the permission to modify id or _id`, token);
} else{
let update = {};
let condition;
const title = req.body.title;
condition = title ? title : undefined;
update.title = condition;
const images = req.body.images;
condition = images ? images : undefined;
update.images = condition;
const url = req.body.url;
condition = url ? url : undefined;
update.url = condition;
let interests = req.body.interests;
condition = interests ? {interests: [...new Map(interests.map(v => [v.id, v])).values()]} : undefined;
update.$addToSet = condition;
const comment = req.body.comment;
condition = comment ? comment : undefined;
update.comment = condition;
const isVisible = req.body.isVisible;
if(typeof isVisible !== 'undefined'){
condition = isVisible;
} else{
condition = undefined;
}
update.isVisible = condition;
const isActive = req.body.isActive;
if(typeof isActive !== 'undefined'){
condition = isActive;
} else{
condition = undefined;
}
update.isActive = condition;
// Remove undefined key
Object.keys(update).forEach(key => update[key] === undefined ? delete update[key] : {});
if(id && ObjectId.isValid(id)){
Ad.updateOne({_id: id, userId: token.id}, update)
.then(data => {
if(data) {
//Object.keys(update).forEach(key => data[key] = update[key]);
return sendMessage(res, 44, update, token);
} else {
return sendError(res, 404, -1, `Ad not found with id=${id}`, token);
}
})
.catch(err => {
return sendError(res, 500, -1, err.message || `Some error occurred while updating the Ad with id=${id}`, token);
});
} else {
return sendError(res, 500, -1, `Error id is not valid`, token);
}
}
} else {
return sendError(res, 500, -1, `No id given`, token);
}
};
// Delete an Ad with ad id
exports.delete = (req, res) => {
const token = checkLogin(req, res, roles.Advertiser);
if(token && typeof req.params.id !== 'undefined') {
let match = null;
const id = req.params.id;
if(id && ObjectId.isValid(id)){
if(typeof token.role !== 'undefined' &&
typeof token.role.permission !== 'undefined' &&
typeof token.role.isAccepted !== 'undefined' &&
token.role.isAccepted === true &&
token.role.permission >= roles.Admin.permission) {
match = {_id: id, isActive: true};
} else {
match = {_id: id, userId: token.id, isActive: true};
}
Ad.findOneAndUpdate(match, {isActive: false}, {useFindAndModify: false, new: true})
.then(data => {
if(data) {
if(data.isActive !== true){
return sendMessage(res, 45, {message: `Ad ${id} was successfully deleted.`}, token);
} else {
return sendError(res, 404, 105, `Ad ${id} was not deleted.`, token);
}
} else {
return sendError(res, 404, 105, `Ad not found with id=${id}`, token);
}
})
.catch(err => {
return sendError(res, 500, 100, err.message || `Some error occurred while deleting the Ad with id=${id}`, token);
});
} else {
return sendError(res, 500, -1, `Error id is not valid`, token);
}
} else {
return sendError(res, 500, -1, `No id given`, token);
}
};
// Delete all Ad from session id
exports.deleteAll = (req, res) => {
const token = checkLogin(req, res, roles.Advertiser);
if(token) {
Ad.updateMany({userId: {$eq: token.id}, isActive: true}, {isActive: false})
.then(data => {
return sendMessage(res, 46, {
message: `${data.modifiedCount} Ads were deleted successfully.`
});
})
.catch(err => {
return sendError(res, 500, -1, err.message || "Some error occurred while removing all Ads.");
});
}
};

View file

@ -1,7 +0,0 @@
const {sendMessage} = require ("../config/response.config");
const interests = require("../models/objects/video.categories.model");
// Get all interests available
exports.getInterests = (req, res) => {
return sendMessage(res, 51, interests, null)
};

View file

@ -1,407 +0,0 @@
const db = require("../models/mongodb.model");
const {sendError, sendMessage} = require ("../config/response.config");
const {checkLogin} = require("../config/sessionJWT.config");
const {youtube, dailymotion} = require("../config/host.config");
const {asyncRequest, asyncInterest} = require("../config/functions.config");
const ObjectId = require('mongoose').Types.ObjectId;
const Playlist = db.playlists;
const Video = db.videos;
// Create a new Playlist
exports.create = (req, res) => {
const token = checkLogin(req, res);
if(token && req.body.name){
const video = req.body.video;
if(typeof video !== 'undefined' &&
video !== null &&
typeof video.videoId !== 'undefined' &&
video.videoId !== null &&
typeof video.source !== 'undefined' &&
video.source !== null &&
typeof video.interest !== 'undefined' &&
video.interest !== null
){
Video.exists({userId: token.id, videoId: video.videoId, source: video.source, isActive: true}, function (err, docs){
if(err){
sendError(res, 500,100,err.message || "Some error occurred while checking if the Video already exists.", token);
} else{
if(docs === null) {
let video;
video = new Video({
userId: token.id,
videoId: id,
source: req.body.source,
interest: req.body.interest,
watchedDates: [new Date()]
});
// Save Video in the database
video
.save(video)
.then(data => {
if(data) {
Playlist.exists({name: req.body.name, isActive: true}, function (err, docs){
if(err){
sendError(res, 500,100,err.message || "Some error occurred while checking if the Playlist already exists.", token);
} else{
if(docs === null) {
let playlist;
playlist = new Playlist({
userId: token.id,
name: req.body.name,
videoIds: data._id ? [data._id] : undefined,
isActive: true
});
// Save User in the database
playlist
.save(playlist)
.then(data => {
return sendMessage(res, 21, data, token)
})
.catch(err => {
return sendError(res, 500,100,err.message || "Some error occurred while creating the Playlist.", token);
});
} else{
return sendError(res, 500, 104, err || `Playlist ${req.body.name} already exists.`, token);
}
}
});
}
})
.catch(err => {
return sendError(res, 500,100,err.message || "Some error occurred while creating the Video.", token);
});
} else{
const id = docs._id.toString();
Playlist.exists({name: req.body.name, isActive: true}, function (err, docs){
if(err){
sendError(res, 500,100,err.message || "Some error occurred while checking if the Playlist already exists.", token);
} else{
if(docs === null) {
let playlist;
playlist = new Playlist({
userId: token.id,
name: req.body.name,
videoIds: [id],
isActive: true
});
// Save User in the database
playlist
.save(playlist)
.then(data => {
return sendMessage(res, 21, data, token)
})
.catch(err => {
return sendError(res, 500,100,err.message || "Some error occurred while creating the Playlist.", token);
});
} else{
return sendError(res, 500, 104, err || `Playlist ${req.body.name} already exists.`, token);
}
}
});
}
}
});
} else {
Playlist.exists({name: req.body.name, isActive: true}, function (err, docs){
if(err){
sendError(res, 500,100,err.message || "Some error occurred while checking if the Playlist already exists.", token);
} else{
if(docs === null) {
let playlist;
playlist = new Playlist({
userId: token.id,
name: req.body.name,
videoIds: req.body.videoIds ? req.body.videoIds : undefined,
isActive: req.body.isActive ? req.body.isActive : undefined
});
// Save User in the database
playlist
.save(playlist)
.then(data => {
return sendMessage(res, 21, data, token)
})
.catch(err => {
return sendError(res, 500,100,err.message || "Some error occurred while creating the Playlist.", token);
});
} else{
return sendError(res, 500, 104, err || `Playlist ${req.body.name} already exists.`, token);
}
}
});
}
}
};
// Retrieve all Playlist from id if admin or session id
exports.findAll = (req, res) => {
const token = checkLogin(req, res);
if(token){
let query = {};
let condition;
const playlistId = req.query.playlistId;
condition = playlistId ? playlistId : undefined;
query._id = condition;
const userId = token.id;
condition = userId ? userId : undefined;
query.userId = condition;
const videoIds = req.query.videoIds;
condition = videoIds ? {$in: videoIds} : undefined;
query.videoIds = condition;
const name = req.query.name;
condition = name ? { $regex: new RegExp(name), $options: "i" } : undefined;
query.name = condition;
const isActive = req.query.isActive;
condition = isActive ? isActive : undefined;
query.isActive = condition;
const sort = req.query.sort;
if(sort !== 'undefined'){
switch (sort){
case 'asc':
condition = {name: 1};
break;
case 'desc':
condition = {name: -1};
break;
case 'createdAtAsc':
condition = {createdAt: 1};
break;
case 'createdAtDesc':
condition = {createdAt: -1};
break;
case 'updatedAtAsc':
condition = {updatedAt: 1};
break;
case 'updatedAtDesc':
condition = {updatedAt: -1};
break;
default:
condition = {name: 1};
}
}
const query_sort = {sort: condition};
// Remove undefined key
Object.keys(query).forEach(key => query[key] === undefined ? delete query[key] : {});
console.log(query);
Playlist.find(query, {}, query_sort)
.then(data => {
return sendMessage(res, 22, data, token);
})
.catch(err => {
return sendError(res,500,100,err.message || "Some error occurred while finding the Playlists.", token);
});
}
};
// Find single Playlist from session id
exports.findOne = (req, res) => {
const token = checkLogin(req, res);
if(token && typeof req.params.id !== 'undefined') {
const id = req.params.id;
if(id && ObjectId.isValid(id)){
Playlist.aggregate([
{$match: {_id: new ObjectId(id), userId: token.id, isActive: true}},
{$unwind: '$videoIds'},
{$project: {
userId: true,
name: true,
isActive: true,
createdAt: true,
updatedAt: true,
videoIds: {$toObjectId: '$videoIds'}
}},
{$lookup: {
from: 'videos',
localField: 'videoIds',
foreignField: '_id',
as: 'videos'
}},
{$unwind: '$videos'},
{$group: {
_id: '$_id',
userId: {$first: "$userId"},
name: {$first: "$name"},
isActive: {$first: "$isActive"},
createdAt: {$first: "$createdAt"},
updatedAt: {$first: "$updatedAt"},
videos: {$push: "$videos"}
}}
])
.then(async data => {
let yt_results = [];
let dm_results = [];
let yt_videoIds = "";
let dm_videoIds = "";
for (const i in data[0].videos) {
if (data[0].videos[i].source === youtube.name) {
yt_videoIds = yt_videoIds + data[0].videos[i].videoId + ",";
} else if (data[0].videos[i].source === dailymotion.name) {
dm_videoIds = dm_videoIds + data[0].videos[i].videoId + ",";
}
}
if (yt_videoIds !== "") {
const uri = youtube.baseAPIUrl + '/videos' + '?part=snippet&part=statistics&id=' + yt_videoIds.slice(0, -1) + '&key=' + youtube.YOUTUBE_API_KEY;
const dataVideos = await asyncRequest(uri, {});
if (dataVideos.response.statusCode === 200 && dataVideos.body.items.length > 0) {
yt_results = dataVideos.body.items;
}
}
if (dm_videoIds !== "") {
const uri = dailymotion.baseAPIUrl + '/videos?ids=' + dm_videoIds.slice(0, -1) + '&fields=thumbnail_480_url%2Ctitle%2Cid';
const data = await asyncRequest(uri, {});
const response = data.response;
const jsonBody = data.body;
if (response.statusCode === 200) {
dm_results = jsonBody.list;
}
}
for (const i in data[0].videos) {
if (data[0].videos[i].source === youtube.name) {
const obj = yt_results.filter(obj => obj.id === data[0].videos[i].videoId);
data[0].videos[i].imageUrl = obj[0].snippet.thumbnails.medium.url ? obj[0].snippet.thumbnails.medium.url : null;
data[0].videos[i].interest = obj[0].snippet.categoryId ? await asyncInterest(obj[0].snippet.categoryId, youtube.name): null;
data[0].videos[i].title = obj[0].snippet.title ? obj[0].snippet.title : null;
data[0].videos[i].views = obj[0].statistics.viewCount ? parseInt(obj[0].statistics.viewCount) : null;
data[0].videos[i].publishedAt = obj[0].snippet.publishedAt ? obj[0].snippet.publishedAt : null;
} else if (data[0].videos[i].source === dailymotion.name) {
const obj = dm_results.filter(obj => obj.id === data[0].videos[i].videoId);
data[0].videos[i].imageUrl = obj[0].thumbnail_480_url ? obj[0].thumbnail_480_url : null;
data[0].videos[i].interest = obj[0]['channel.name'] ? await asyncInterest( obj[0]['channel.name'], dailymotion.name) : null;
data[0].videos[i].title = obj[0].title ? obj[0].title : null;
data[0].videos[i].views = obj[0].views_total ? parseInt(obj[0].views_total) : null;
data[0].videos[i].publishedAt = obj[0].created_time ? new Date(obj[0].created_time * 1000) : null
}
}
return sendMessage(res, 12, data[0], token)
})
.catch(err => {
return sendError(res,500,100,err.message || `Some error occurred while finding the Playlist with id=${id}`, token);
});
} else {
return sendError(res, 500, -1, `Error id is not valid`, token);
}
} else {
return sendError(res, 500, -1, `No id given`, token);
}
};
// Update a Playlist with playlist id
exports.update = (req, res) => {
const token = checkLogin(req, res);
if(token && typeof req.params.id !== 'undefined') {
const id = req.params.id;
if(typeof req.body._id !== 'undefined' || typeof req.body.id !== 'undefined'){
return sendError(res, 500, -1, `User do not have the permission to modify id or _id`, token);
} else{
const ids = id.split(',');
let update = {};
let condition;
const name = req.body.name;
condition = name ? name : undefined;
update.name = condition;
const videoIds = req.body.videoIds;
condition = videoIds ? videoIds : undefined;
update.videoIds = condition;
const videoId = req.body.videoId;
if(typeof videoId !== 'undefined' && typeof videoId.id !== 'undefined' && typeof videoId.action !== 'undefined'){
if(videoId.action === 'add'){
condition = videoId.id ? {videoIds: videoId.id} : undefined;
update.$addToSet = condition;
} else if(videoId.action === 'delete'){
condition = videoId.id ? {videoIds: videoId.id} : undefined;
update.$pull = condition;
}
}
const isActive = req.body.isActive;
if(typeof isActive !== 'undefined'){
condition = isActive;
} else{
condition = undefined;
}
update.isActive = condition;
// Remove undefined key
Object.keys(update).forEach(key => update[key] === undefined ? delete update[key] : {});
Playlist.updateMany({_id: {$in: ids}, userId: token.id, isActive: true}, update, {new: false})
.then(data => {
if(data) {
if(data.modifiedCount > 0){
return sendMessage(res, 24, update, token);
} else {
return sendError(res, 500, -1, `Video in Playlist ${data} already exists.`, token);
}
} else {
return sendError(res, 404, -1, `Playlist not found with id=${id}`, token);
}
})
.catch(err => {
return sendError(res, 500, -1, err.message || `Some error occurred while updating the Playlist with id=${id}`, token);
});
}
} else {
return sendError(res, 500, -1, `No id given`, token);
}
};
// Delete a Playlist with playlist id
exports.delete = (req, res) => {
const token = checkLogin(req, res);
if(token && typeof req.params.id !== 'undefined') {
const id = req.params.id;
if(id && ObjectId.isValid(id)){
Playlist.findByIdAndUpdate(id, {isActive: false}, {useFindAndModify: false})
.then(data => {
if(data) {
return sendMessage(res, 25, {message: `Playlist ${id} was successfully deleted.`}, token);
} else {
return sendError(res, 404, 105, `Playlist not found with id=${id}`, token);
}
})
.catch(err => {
return sendError(res, 500, 100, err.message || `Some error occurred while deleting the Playlist with id=${id}`, token);
});
} else {
return sendError(res, 500, -1, `Error id is not valid`, token);
}
} else {
return sendError(res, 500, -1, `No id given`, token);
}
};
// Delete all Playlists from session id
exports.deleteAll = (req, res) => {
const token = checkLogin(req, res);
if(token) {
Playlist.updateMany({userId: {$eq: token.id}, isActive: true}, {isActive: false})
.then(data => {
return sendMessage(res, 26, {
message: `${data.modifiedCount} Playlists were deleted successfully.`
});
})
.catch(err => {
return sendError(res, 500, -1, err.message || "Some error occurred while removing all Playlists.");
});
}
};

View file

@ -1,546 +0,0 @@
const db = require("../models/mongodb.model");
const {sendError, sendMessage} = require ("../config/response.config");
const {checkLogin, setSessionCookie} = require("../config/sessionJWT.config");
const ObjectId = require('mongoose').Types.ObjectId;
const roles = require("../models/objects/role.model");
const {youtube, dailymotion} = require("../config/host.config");
const {asyncRequest} = require("../config/functions.config");
const User = db.users;
const Video = db.videos;
const Ad = db.ads;
// Authenticate a User
exports.auth = (req, res) => {
// Validate request
if (!req.body.email || !req.body.hashPass) {
sendError(res, 400,-1,"Content can not be empty . (email and hashPass needed)");
} else{
// Check User in the database
User
.findOne({email: req.body.email, hashPass: req.body.hashPass, isActive: true, "role.isAccepted": true}, {role: true, profileImageUrl: true})
.then(data => {
if (data !== null){
User.findByIdAndUpdate(data._id.toString(), {lastConnexion: new Date()}, {useFindAndModify: false},
function (err) {
if (err){
return sendError(res, 400, 100,err.message || "Some error occurred while updating the User.");
}
else{
const dataRes = {id: data._id.toString(), email: req.body.email, profileImageUrl: data.profileImageUrl, role: data.role};
setSessionCookie(req, res, dataRes);
return sendMessage(res, 1, dataRes);
}
});
} else {
setSessionCookie(req, res, {id: -1, email: -1, profileImageUrl: -1, role: -1});
return sendError(res, 500, 101, "Invalid login or password.");
}
})
.catch(err => {
return sendError(res, 400, 100,err.message || "Some error occurred while authenticating the User.");
});
}
};
// Logout a User
exports.logout = (req, res) => {
const token = checkLogin(req, res);
if(token){
setSessionCookie(req, res, {id: -1, email: -1, profileImageUrl: -1, role: -1});
return sendMessage(res, 2, {message: "User disconnected"});
}
};
// Request password reset with email
exports.resetPass = (req, res) => {
return sendError(res, 501, -1, "User.resetPass not Implemented", null);
};
// Create and Save a new User
exports.create = (req, res) => {
// Validate request
if (!req.body.email || !req.body.hashPass || !req.body.login) {
sendError(res, 400,-1,"Content can not be empty . (email, hashPass and login needed");
}
else{
User.exists({email: req.body.email}, function (err, docs){
if(err){
sendError(res, 500,100,err.message || "Some error occurred while checking if the User already exists.");
} else{
if(docs === null) {
let user;
let var_role;
if(typeof req.body.role !== 'undefined'){
switch(req.body.role){
case 'admin':
var_role = roles.Admin;
break;
case 'advertiser':
var_role = roles.Advertiser;
break;
default:
var_role = roles.User;
}
} else{
var_role = roles.User;
}
user = new User({
email: req.body.email,
hashPass: req.body.hashPass,
login: req.body.login,
role: var_role,
company: req.body.company ? req.body.company : null,
dateOfBirth: req.body.dateOfBirth ? req.body.dateOfBirth : null,
gender: req.body.gender ? req.body.gender : null,
interests: req.body.interests ? req.body.interests : null,
});
// Save User in the database
user
.save(user)
.then(data => {
data.hashPass = undefined; // Hiding hashPass on return
return sendMessage(res, 4, data)
})
.catch(err => {
return sendError(res, 500,100,err.message || "Some error occurred while creating the User.");
});
} else{
return sendError(res, 500, 104, err || `Email ${req.body.email} already exists.`);
}
}
});
}
};
// Retrieve all Users from the database if at least admin.
exports.findAll = (req, res) => {
const token = checkLogin(req, res, roles.Admin);
if(token){
let query = {};
let condition;
const ids = req.query.userId;
condition = ids ? {$in: ids} : undefined;
query._id = condition;
const email = req.query.email;
condition = email ? { $regex: new RegExp(email), $options: "i" } : undefined;
query.email = condition;
const login = req.query.login;
condition = login ? { $regex: new RegExp(login), $options: "i" } : undefined;
query.login = condition;
const role = req.query.role;
condition = role ? role : undefined;
query["role.name"] = condition;
const company = req.query.company;
condition = company ? { $regex: new RegExp(company), $options: "i" } : undefined;
query.company = condition;
const dateOfBirth = req.query.dateOfBirth;
condition = dateOfBirth ? new Date(dateOfBirth) : undefined;
query.dateOfBirth = condition;
const gender = req.query.gender;
condition = gender ? gender : undefined;
query.gender = condition;
const isActive = req.query.isActive;
condition = isActive ? isActive : undefined;
query.isActive = condition;
const isAccepted = req.query.isAccepted;
if(isAccepted !== 'undefined'){
switch (isAccepted){
case 'true':
condition = true;
break;
case 'false':
condition = false;
break;
}
}
query["role.isAccepted"] = condition;
const sort = req.query.sort;
if(sort !== 'undefined'){
switch (sort){
case 'asc':
condition = {email: 1};
break;
case 'desc':
condition = {email: -1};
break;
case 'lastConnexionAsc':
condition = {lastConnexion: 1};
break;
case 'lastConnexionDesc':
condition = {lastConnexion: -1};
break;
case 'createdAtAsc':
condition = {createdAt: 1};
break;
case 'createdAtDesc':
condition = {createdAt: -1};
break;
case 'updatedAtAsc':
condition = {updatedAt: 1};
break;
case 'updatedAtDesc':
condition = {updatedAt: -1};
break;
default:
condition = {email: 1};
}
}
const query_sort = {sort: condition};
// Remove undefined key
Object.keys(query).forEach(key => query[key] === undefined ? delete query[key] : {});
console.log(query);
User.find(query, {hashPass: false}, query_sort)
.then(data => {
return sendMessage(res, 5, data, token);
})
.catch(err => {
return sendError(res,500,100,err.message || "Some error occurred while retrieving users.", token);
});
}
};
// Find a single User by session id
exports.findOne = (req, res) => {
const token = checkLogin(req, res);
if(token && typeof req.params.id !== 'undefined') {
let id = null;
if(typeof token.id !== 'undefined' && token.id === req.params.id){
id = req.params.id;
} else {
if(typeof token.role !== 'undefined' &&
typeof token.role.permission !== 'undefined' &&
typeof token.role.isAccepted !== 'undefined' &&
token.role.isAccepted === true &&
token.role.permission >= roles.Admin.permission) {
id = req.params.id;
} else {
return sendError(res, 500, 106, `User do not have the permission.`, token);
}
}
if(id && ObjectId.isValid(id)){
User.findById(id, {hashPass: false})
.then(data => {
if(data){
return sendMessage(res, 6, data, token);
} else {
return sendError(res,404,105,`User not found with id=${id}`, token);
}
})
.catch(err => {
return sendError(res,500,100,err.message || `Some error occurred while finding the User with id=${id}`, token);
});
} else {
sendError(res, 500, -1, `Error id is not valid`, token);
}
} else {
return sendError(res, 500, -1, `No id given`, token);
}
};
// Update a User by the id in the request
exports.update = (req, res) => {
const token = checkLogin(req, res);
if(token && typeof req.params.id !== 'undefined') {
let id = null;
if(typeof token.id !== 'undefined' && token.id === req.params.id){
id = req.params.id;
} else {
if(typeof token.role !== 'undefined' &&
typeof token.role.permission !== 'undefined' &&
typeof token.role.isAccepted !== 'undefined' &&
token.role.isAccepted === true &&
token.role.permission >= roles.Admin.permission) {
id = req.params.id;
} else {
return sendError(res, 500, 106, `User do not have the permission.`, token);
}
}
if(id && ObjectId.isValid(id)){
let update = null;
if(typeof req.body._id !== 'undefined' || typeof req.body.id !== 'undefined'){
return sendError(res, 500, -1, `User do not have the permission to modify id or _id`, token);
} else{
if(typeof req.body.role !== 'undefined' ||
typeof req.body.isActive !== 'undefined' ||
typeof req.body.lastConnexion !== 'undefined' ||
typeof req.body.createdAt !== 'undefined'||
typeof req.body.updatedAt !== 'undefined'){
if(typeof token.role !== 'undefined' &&
typeof token.role.permission !== 'undefined' &&
typeof token.role.isAccepted !== 'undefined' &&
token.role.isAccepted === true &&
token.role.permission >= roles.Admin.permission) {
update = true;
} else{
return sendError(res, 500, 106, `User do not have the permission to modify these keys.`, token);
}
} else{
update = true;
}
}
if(update === true){
User.findByIdAndUpdate(id, req.body, {useFindAndModify: false})
.then(data => {
if(data) {
data.hashPass = undefined;
Object.keys(req.body).forEach(key => data[key] = req.body[key]);
sendMessage(res, 7, data, token);
} else {
sendError(res, 404, -1, `User not found with id=${id}`, token);
}
})
.catch(err => {
sendError(res, 500, -1, err.message || `Some error occurred while updating the User with id=${id}`, token);
});
}
} else {
sendError(res, 500, -1, `Error id is not valid`, token);
}
} else {
return sendError(res, 500, -1, `No id given`, token);
}
};
// Delete a User with the specified id in the request
exports.delete = (req, res) => {
const token = checkLogin(req, res);
if(token && typeof req.params.id !== 'undefined') {
let id = null;
if(typeof token.id !== 'undefined' && token.id === req.params.id){
id = req.params.id;
} else {
if(typeof token.role !== 'undefined' &&
typeof token.role.permission !== 'undefined' &&
typeof token.role.isAccepted !== 'undefined' &&
token.role.isAccepted === true &&
token.role.permission >= roles.Admin.permission) {
id = req.params.id;
} else {
return sendError(res, 500, 106, `User do not have the permission.`, token);
}
}
if(id && ObjectId.isValid(id)){
User.findByIdAndUpdate(id, {isActive: false}, {useFindAndModify: false})
.then(data => {
if(data) {
return sendMessage(res, 8, {message: `User ${id} was successfully deleted.`}, token);
} else {
return sendError(res, 404, 105, `User not found with id=${id}`, token);
}
})
.catch(err => {
return sendError(res, 500, 100, err.message || `Some error occurred while deleting the User with id=${id}`, token);
});
} else {
return sendError(res, 500, -1, `Error id is not valid`, token);
}
} else {
return sendError(res, 500, -1, `No id given`, token);
}
};
// Delete all Users from the database except superAdmin
exports.deleteAll = (req, res) => {
const token = checkLogin(req, res, roles.SuperAdmin);
if(token) {
User.deleteMany({login: {$ne: "superAdmin"}})
.then(data => {
return sendMessage(res, 9, {
message: `${data.deletedCount} Users were deleted successfully.`
});
})
.catch(err => {
return sendError(res, 500, 100, err.message || "Some error occurred while removing all Users.");
});
}
};
// Get all Roles depending on the role of the User
exports.roles = (req, res) => {
const token = checkLogin(req, res);
if(token){
return sendMessage(res, 10, roles, token);
}
};
// Get 1 or multiple ad adapted to the User session id
exports.ad = (req, res) => {
const token = checkLogin(req, res);
if(token && typeof req.query.quantity !== 'undefined'){
const id = token.id;
const quantity = req.query.quantity;
// Interests from the user and from last 20 videos viewed if no ad matches -> find x ad from these interests + add date view to the ad
let interests = [];
const maxInterests = 20;
let limit = maxInterests;
User.findById(id, {_id: false, interests: true})
.then(data => {
if(typeof data.interests !== 'undefined' && data.interests !== null){
interests = interests.concat(data.interests);
limit = maxInterests-data.interests.length;
}
Video.aggregate([
{$match: {userId: id}},
{$project: {_id: false, interest: true}},
{$sort: {watchedDates: -1}},
{$limit: limit},
{$unwind: '$interest'},
{$group: {_id: null, interests: {$push: '$interest'}}}
])
.then(data => {
if(typeof data[0] !== 'undefined' &&
typeof data[0].interests !== 'undefined' &&
data[0].interests !== [] &&
data[0].interests !== null){
interests = interests.concat(data[0].interests);
}
let match, pick;
if(interests.length > 0){
match = {$match: {isVisible: true, isActive: true, interests: {$elemMatch: {interest: {$in: interests}}}}};
pick = {$limit: parseInt(quantity, 10)}
} else {
match = {$match: {isVisible: true, isActive: true}};
pick = {$sample: {size: parseInt(quantity, 10)}};
}
Ad.aggregate([
match,
pick
])
.then(data => {
if(data.length > 0){
let ids = []
for(const i in data){ids.push(data[i]._id);}
Ad.updateMany({_id: {$in: ids}}, {$push: {views: [new Date()]}})
.then(dataUpdate => {
if(dataUpdate && dataUpdate.modifiedCount > 0){
return sendMessage(res, 11, data, token);
} else {
return sendError(res,500,101,`Some error occurred while updating ${quantity} ad(s) for the User.`, token);
}
})
.catch(err => {
return sendError(res,500,101,err.message || `Some error occurred while updating ${quantity} ad(s) for the User.`, token);
});
} else {
Ad.aggregate([{$match: {isVisible: true, isActive: true}}, {$sample: {size: parseInt(quantity, 10)}}])
.then(data => {
let ids = []
for(const i in data){ids.push(data[i]._id);}
Ad.updateMany({_id: {$in: ids}}, {$push: {views: [new Date()]}})
.then(dataUpdate => {
if(dataUpdate && dataUpdate.modifiedCount > 0){
return sendMessage(res, 11, data, token);
} else {
return sendError(res,500,101,`Some error occurred while updating ${quantity} ad(s) for the User.`, token);
}
})
.catch(err => {
return sendError(res,500,101,err.message || `Some error occurred while updating ${quantity} ad(s) for the User.`, token);
});
})
.catch(err => {
return sendError(res,500,101,err.message || `Some error occurred while getting ${quantity} ad(s) for the User.`, token);
});
}
})
.catch(err => {
return sendError(res,500,101,err.message || `Some error occurred while getting ${quantity} ad(s) for the User.`, token);
});
})
.catch(err => {
return sendError(res,500,102,err.message || `Some error occurred while getting ${quantity} ad(s) for the User.`, token);
});
})
.catch(err => {
return sendError(res,500,100,err.message || `Some error occurred while getting ${quantity} ad(s) for the User.`, token);
});
} else {
sendError(res, 500, -1, `No quantity given`, token);
}
};
// Get History
exports.history = (req, res) => {
const token = checkLogin(req, res);
if(token){
const id = token.id;
Video.aggregate([
{$match: {userId: id, $expr: {$gt: [{$size: "$watchedDates"}, 0]}}},
{$limit: 300},
{$project: {
videoId: true,
source: true,
tags: true,
interest: true,
views: {$size: '$watchedDates'},
watchedDate: {$arrayElemAt: ["$watchedDates", -1]},
createdAt: true,
updatedAt: true
}},
{$sort: {watchedDate: -1}}])
.then(async data => {
let yt_results = [];
let dm_results = [];
let yt_videoIds = "";
let dm_videoIds = "";
for(const i in data) {
if(data[i].source === youtube.name) {
yt_videoIds = yt_videoIds + data[i].videoId + ",";
} else if (data[i].source === dailymotion.name) {
dm_videoIds = dm_videoIds + data[i].videoId + ",";
}
}
if(yt_videoIds !== ""){
const uri = youtube.baseAPIUrl + '/videos' + '?part=snippet&part=statistics&id=' + yt_videoIds.slice(0, -1) + '&key=' + youtube.YOUTUBE_API_KEY;
const dataVideos = await asyncRequest(uri, {});
if (dataVideos.response.statusCode === 200 && dataVideos.body.items.length > 0) {
yt_results = dataVideos.body.items;
}
}
if(dm_videoIds !== ""){
const uri = dailymotion.baseAPIUrl + '/videos?ids='+dm_videoIds.slice(0, -1)+'&fields=thumbnail_480_url%2Ctitle%2Cid';
const data = await asyncRequest(uri, {});
const response = data.response;
const jsonBody = data.body;
if(response.statusCode === 200){
dm_results = jsonBody.list;
}
}
for(const i in data) {
if(data[i].source === youtube.name) {
const obj = yt_results.filter(obj => obj.id === data[i].videoId);
data[i].imageUrl = obj[0].snippet.thumbnails.medium.url ? obj[0].snippet.thumbnails.medium.url : null;
data[i].title = obj[0].snippet.title ? obj[0].snippet.title : null;
} else if (data[i].source === dailymotion.name) {
const obj = dm_results.filter(obj => obj.id === data[i].videoId);
data[i].imageUrl = obj[0].thumbnail_480_url ? obj[0].thumbnail_480_url : null;
data[i].title = obj[0].title ? obj[0].title : null;
}
}
return sendMessage(res, 12, data, token)
})
.catch(err => {
return sendError(res,500,100,err.message || "Some error occurred while getting the User history.", token);
});
}
};

View file

@ -1,473 +0,0 @@
const db = require("../models/mongodb.model");
const request = require('request');
const {sendError, sendMessage} = require ("../config/response.config");
const {checkLogin} = require("../config/sessionJWT.config");
const {youtube, dailymotion} = require("../config/host.config");
const {asyncRequest, asyncInterest} = require("../config/functions.config");
const ObjectId = require('mongoose').Types.ObjectId;
const Video = db.videos;
// Search Videos
exports.search = async (req, res) => {
const token = checkLogin(req, res);
if(token && typeof req.query.q !== 'undefined'){
const query = req.query.q;
const maxResults = req.query.maxResults ? req.query.maxResults : 45;
const pageToken = req.query.pageToken ? req.query.pageToken : undefined;
let sources;
if(typeof req.query.sources !== 'undefined' && req.query.sources !== ''){
sources = req.query.sources.split(',');
} else {
sources = ["yt", "dm"];
}
let yt_results = [];
let dm_results = [];
for(const i in sources){
if(sources[i] === youtube.shortname){
if(youtube.YOUTUBE_API_KEY !== 'undefined' && youtube.YOUTUBE_API_KEY !== ''){
let uri;
if(query !== ''){
if(typeof pageToken !== 'undefined'){
uri = youtube.baseAPIUrl+'/search'+'?part=snippet&maxResults='+maxResults+'&q='+query+'&pageToken='+pageToken+'&key='+youtube.YOUTUBE_API_KEY;
} else{
uri = youtube.baseAPIUrl+'/search'+'?part=snippet&maxResults='+maxResults+'&q='+query+'&key='+youtube.YOUTUBE_API_KEY;
}
const dataIds = await asyncRequest(uri, {});
if(dataIds.response.statusCode === 200 && dataIds.body.items.length > 0){
let yt_videoIds = "";
dataIds.body.items.forEach(item => yt_videoIds = yt_videoIds+item.id.videoId+",");
uri = youtube.baseAPIUrl+'/videos'+'?part=snippet&part=statistics&id='+yt_videoIds.slice(0, -1)+'&key='+youtube.YOUTUBE_API_KEY;
const dataVideos = await asyncRequest(uri, {});
if(dataVideos.response.statusCode === 200 && dataVideos.body.items.length > 0){
yt_results = dataVideos.body.items;
}
}
} else {
uri = youtube.baseAPIUrl+'/videos'+'?part=snippet&part=statistics&chart=mostPopular&maxResults='+maxResults+'&key='+youtube.YOUTUBE_API_KEY;
const dataVideos = await asyncRequest(uri, {});
if(dataVideos.response.statusCode === 200 && dataVideos.body.items.length > 0){
yt_results = dataVideos.body.items;
}
}
} else{
return sendError(res, 500, -1, `Error Env Variable DAILYMOTION_API_KEY missing, please contact the admin.`, token);
}
} else if(sources[i] === dailymotion.shortname){
if(dailymotion.DAILYMOTION_API_KEY !== 'undefined' && dailymotion.DAILYMOTION_API_KEY !== '') {
let uri;
if(query !== ''){
uri = dailymotion.baseAPIUrl + '/videos?limit='+maxResults+'&search='+query+'&fields=created_time%2Cdescription%2Cthumbnail_480_url%2Clikes_total%2Ctitle%2Cid%2Cembed_url%2Cviews_total%2Cowner.username%2Cowner.id%2Cchannel.name';
} else {
uri = dailymotion.baseAPIUrl + '/videos?limit='+maxResults+'&sort=trending&fields=created_time%2Cdescription%2Cthumbnail_480_url%2Clikes_total%2Ctitle%2Cid%2Cembed_url%2Cviews_total%2Cowner.username%2Cowner.id%2Cchannel.name';
}
const data = await asyncRequest(uri, {});
const response = data.response;
const jsonBody = data.body;
if(response.statusCode === 200){
dm_results = jsonBody.list;
}
} else{
return sendError(res, 500, -1, `Error Env Variable DAILYMOTION_API_KEY missing, please contact the admin.`, token);
}
}
}
let results = [];
for(let i = 0; i < Math.max(dm_results.length, yt_results.length); i++){
// Youtube
if(yt_results.length > i){
const yt_data = {
videoId: yt_results[i].id,
source: youtube.name,
imageUrl: yt_results[i].snippet.thumbnails.medium.url ? yt_results[i].snippet.thumbnails.medium.url : null,
title: yt_results[i].snippet.title ? yt_results[i].snippet.title : null,
channelTitle: yt_results[i].snippet.channelTitle ? yt_results[i].snippet.channelTitle : null,
channelUrl: youtube.baseChannelUrl+yt_results[i].snippet.channelId ? yt_results[i].snippet.channelId : null,
description: yt_results[i].snippet.description ? yt_results[i].snippet.description : null,
embedUrl: 'https://www.youtube.com/embed/'+yt_results[i].id,
interest: await asyncInterest(yt_results[i].snippet.categoryId, youtube.name),
views: yt_results[i].statistics.viewCount ? parseInt(yt_results[i].statistics.viewCount) : null,
likes: yt_results[i].statistics.likeCount ? parseInt(yt_results[i].statistics.likeCount) : null,
dislikes: yt_results[i].statistics.dislikeCount ? parseInt(yt_results[i].statistics.dislikeCount) : null,
publishedAt: yt_results[i].snippet.publishedAt ? yt_results[i].snippet.publishedAt : null
};
results.push(yt_data);
}
// Dailymotion
if(dm_results.length > i) {
const channelTitle = dm_results[i]['owner.username'] ? dm_results[i]['owner.username'] : null;
const dm_data = {
videoId: dm_results[i].id ? dm_results[i].id : null,
source: dailymotion.name,
imageUrl: dm_results[i].thumbnail_480_url ? dm_results[i].thumbnail_480_url : null,
title: dm_results[i].title ? dm_results[i].title : null,
channelTitle: channelTitle.charAt(0).toUpperCase() + channelTitle.slice(1),
channelUrl: dailymotion.baseChannelUrl + channelTitle,
description: dm_results[i].description ? dm_results[i].description : null,
embedUrl: dm_results[i].embed_url ? dm_results[i].embed_url : null,
interest: await asyncInterest(dm_results[i]['channel.name'], dailymotion.name),
views: dm_results[i].views_total ? parseInt(dm_results[i].views_total) : null,
likes: dm_results[i].likes_total ? parseInt(dm_results[i].likes_total) : null,
dislikes: null,
publishedAt: dm_results[i].created_time ? new Date(dm_results[i].created_time * 1000) : null
};
results.push(dm_data);
}
}
return sendMessage(res, 31, results, token);
} else{
return sendError(res, 500, -1, `No q given`, token);
}
};
// Get Video with id of source
exports.get = (req, res) => {
if(typeof req.query.source !== 'undefined' && typeof req.params.id !== 'undefined'){
const source = req.query.source;
const id = req.params.id;
if(source === youtube.shortname){
if(youtube.YOUTUBE_API_KEY !== 'undefined' && youtube.YOUTUBE_API_KEY !== ''){
const uri = youtube.baseAPIUrl+'/videos'+'?part=snippet&part=statistics&id='+id+'&key='+youtube.YOUTUBE_API_KEY;
request(uri,{},async function (error, response, body){
if(typeof body !== 'undefined'){
const jsonBody = JSON.parse(body);
if(jsonBody.items.length !== 0 &&
typeof jsonBody.items[0] !== 'undefined' &&
typeof jsonBody.items[0].id !== 'undefined' &&
jsonBody.items[0].id === id){
const imageUrl = jsonBody.items[0].snippet.thumbnails.standard.url ? jsonBody.items[0].snippet.thumbnails.standard.url : null;
const title = jsonBody.items[0].snippet.title ? jsonBody.items[0].snippet.title : null;
const channelId = jsonBody.items[0].snippet.channelId ? jsonBody.items[0].snippet.channelId : null;
const channelTitle = jsonBody.items[0].snippet.channelTitle ? jsonBody.items[0].snippet.channelTitle : null;
const description = jsonBody.items[0].snippet.description ? jsonBody.items[0].snippet.description : null;
//const embedUrl = jsonBody.embed_url ? jsonBody.embed_url : null;
const publishedAt = jsonBody.items[0].snippet.publishedAt ? jsonBody.items[0].snippet.publishedAt : null;
const interest = jsonBody.items[0].snippet.categoryId ? await asyncInterest(jsonBody.items[0].snippet.categoryId, youtube.name): null;
const views = jsonBody.items[0].statistics.viewCount ? parseInt(jsonBody.items[0].statistics.viewCount) : null;
const likes = jsonBody.items[0].statistics.likeCount ? parseInt(jsonBody.items[0].statistics.likeCount) : null;
const dislikes = jsonBody.items[0].statistics.dislikeCount ? parseInt(jsonBody.items[0].statistics.dislikeCount) : null;
const data = {
videoId: id,
source: youtube.name,
imageUrl: imageUrl,
title: title,
channelTitle: channelTitle,
channelUrl: youtube.baseChannelUrl+channelId,
description: description,
embedUrl: 'https://www.youtube.com/embed/'+id,
interest: interest,
views: views,
likes: likes,
dislikes: dislikes,
publishedAt: publishedAt
};
return sendMessage(res, 32, data);
} else{
return sendError(res, 404, -1, `No result`);
}
} else{
return sendError(res, 500, -1, error);
}
});
} else{
return sendError(res, 500, -1, `Error Env Variable YOUTUBE_API_KEY missing, please contact the admin.`);
}
} else if(source === dailymotion.shortname){
if(dailymotion.DAILYMOTION_API_KEY !== 'undefined' && dailymotion.DAILYMOTION_API_KEY !== ''){
const uri = dailymotion.baseAPIUrl+'/video/'+id+'?fields=created_time%2Cdescription%2Cthumbnail_480_url%2Clikes_total%2Ctitle%2Cid%2Cembed_url%2Cviews_total%2Cowner.username%2Cowner.id%2Cchannel.name';
request(uri,{},async function (error, response, body) {
if (typeof body !== 'undefined') {
const jsonBody = JSON.parse(body);
if(response.statusCode === 200 &&
typeof jsonBody.id !== 'undefined' &&
jsonBody.id === id){
const imageUrl = jsonBody.thumbnail_480_url ? jsonBody.thumbnail_480_url : null;
const title = jsonBody.title ? jsonBody.title : null;
//const channelId = jsonBody['owner.id'] ? jsonBody['owner.id'] : null;
const channelTitle = jsonBody['owner.username'] ? jsonBody['owner.username'] : null;
const description = jsonBody.description ? jsonBody.description : null;
const embedUrl = jsonBody.embed_url ? jsonBody.embed_url : null;
const publishedAt = jsonBody.created_time ? new Date(jsonBody.created_time * 1000) : null;
const interest = jsonBody['channel.name'] ? await asyncInterest(jsonBody['channel.name'], dailymotion.name) : null;
const views = jsonBody.views_total ? parseInt(jsonBody.views_total) : null;
const likes = jsonBody.likes_total ? parseInt(jsonBody.likes_total) : null;
const dislikes = null;
const data = {
videoId: id,
source: dailymotion.name,
imageUrl: imageUrl,
title: title,
channelTitle: channelTitle.charAt(0).toUpperCase() + channelTitle.slice(1),
channelUrl: dailymotion.baseChannelUrl+channelTitle,
description: description,
embedUrl: embedUrl,
interest: interest,
views: views,
likes: likes,
dislikes: dislikes,
publishedAt: publishedAt
};
return sendMessage(res, 32, data);
} else{
return sendError(res, 404, -1, jsonBody.error.message);
}
}
});
} else{
return sendError(res, 500, -1, `Error Env Variable DAILYMOTION_API_KEY missing, please contact the admin.`);
}
} else{
return sendError(res, 500, -1, `Wrong source name`);
}
} else{
return sendError(res, 500, -1, `No source or/and id given`);
}
};
// Create a new Video
exports.create = (req, res) => {
const token = checkLogin(req, res);
if(token &&
typeof req.body.source !== 'undefined' &&
typeof req.body.interest !== 'undefined' &&
typeof req.params.id !== 'undefined'){
const id = req.params.id;
Video.exists({userId: token.id, videoId: id, source: req.body.source, isActive: true}, function (err, docs){
if(err){
sendError(res, 500,100,err.message || "Some error occurred while checking if the Video already exists.", token);
} else{
if(docs === null) {
let video;
video = new Video({
userId: token.id,
videoId: id,
source: req.body.source,
interest: req.body.interest,
watchedDates: [new Date()]
});
// Save Video in the database
video
.save(video)
.then(data => {
return sendMessage(res, 33, data, token)
})
.catch(err => {
return sendError(res, 500,100,err.message || "Some error occurred while creating the Video.", token);
});
} else{
const id = docs._id.toString();
Video.findByIdAndUpdate(id, {$push: {watchedDates: [new Date()]}}, {useFindAndModify: false, new: true})
.then(data => {
if(data) {
return sendMessage(res, 33, data, token);
} else {
return sendError(res, 404, 105, `Video not found with id=${id}`, token);
}
})
.catch(err => {
return sendError(res, 500, 100, err.message || `Some error occurred while updating the Video with id=${id}`, token);
});
}
}
});
} else {
return sendError(res, 500, -1, `No source or interest or id given`, token);
}
};
// Retrieve all Videos
exports.findAll = (req, res) => {
const token = checkLogin(req, res);
if(token){
let query = {};
let condition;
const userId = req.query.userId;
condition = userId ? userId : undefined;
query.userId = condition;
const videoId = req.query.videoId;
condition = videoId ? videoId : undefined;
query.videoId = condition;
const source = req.query.source;
condition = source ? source : undefined;
query.source = condition;
const interests = req.query.interests;
condition = interests ? {$in: interests} : undefined;
query["interests.interest"] = condition
const isActive = req.query.isActive;
condition = isActive ? isActive : undefined;
query.isActive = condition;
const sort = req.query.sort;
if(sort !== 'undefined'){
switch (sort){
case 'asc':
condition = {videoId: 1};
break;
case 'desc':
condition = {videoId: -1};
break;
case 'createdAtAsc':
condition = {createdAt: 1};
break;
case 'createdAtDesc':
condition = {createdAt: -1};
break;
case 'updatedAtAsc':
condition = {updatedAt: 1};
break;
case 'updatedAtDesc':
condition = {updatedAt: -1};
break;
default:
condition = {createdAt: -1};
}
}
const query_sort = {sort: condition};
// Remove undefined key
Object.keys(query).forEach(key => query[key] === undefined ? delete query[key] : {});
console.log(query);
Video.find(query, {}, query_sort)
.then(data => {
return sendMessage(res, 34, data, token);
})
.catch(err => {
return sendError(res,500,100,err.message || "Some error occurred while finding the Videos.", token);
});
}
};
// Find single Video with id
exports.findOne = (req, res) => {
const token = checkLogin(req, res);
if(token && typeof req.params.id !== 'undefined') {
const id = req.params.id;
if(id && ObjectId.isValid(id)){
Video.findById(id, {})
.then(data => {
if(data){
return sendMessage(res, 35, data, token);
} else {
return sendError(res,404,105,`Video not found with id=${id}`, token);
}
})
.catch(err => {
return sendError(res,500,100,err.message || `Some error occurred while finding the Video with id=${id}`, token);
});
} else {
return sendError(res, 500, -1, `Error id is not valid`, token);
}
} else {
return sendError(res, 500, -1, `No id given`, token);
}
};
// Update Video with id
exports.update = (req, res) => {
const token = checkLogin(req, res);
if(token && typeof req.params.id !== 'undefined') {
const id = req.params.id;
if(typeof req.body._id !== 'undefined' || typeof req.body.id !== 'undefined'){
return sendError(res, 500, -1, `User do not have the permission to modify id or _id`, token);
} else{
let update = {};
let condition;
const watchedDate = req.body.watchedDate;
if(typeof watchedDate !== 'undefined'){
if(watchedDate){
condition = {watchedDates: [new Date()]}
} else {
condition = undefined;
}
} else{
condition = undefined;
}
update.$push = condition;
const watchedDates = req.body.watchedDates ? req.body.watchedDates : undefined;
update.watchedDates = watchedDates;
const isActive = req.body.isActive;
if(typeof isActive !== 'undefined'){
condition = isActive;
} else{
condition = undefined;
}
update.isActive = condition;
// Remove undefined key
Object.keys(update).forEach(key => update[key] === undefined ? delete update[key] : {});
if(id && ObjectId.isValid(id)){
Video.updateOne({_id: id, userId: token.id, isActive: true}, update)
.then(data => {
if(data) {
return sendMessage(res, 36, update, token);
} else {
return sendError(res, 404, -1, `Video not found with id=${id}`, token);
}
})
.catch(err => {
return sendError(res, 500, -1, err.message || `Some error occurred while updating the Video with id=${id}`, token);
});
} else {
return sendError(res, 500, -1, `Error id is not valid`, token);
}
}
} else {
return sendError(res, 500, -1, `No id given`, token);
}
};
// Delete Video with id
exports.delete = (req, res) => {
const token = checkLogin(req, res);
if(token && typeof req.params.id !== 'undefined') {
const id = req.params.id;
if(id && ObjectId.isValid(id)){
Video.updateOne({_id: id, userId: token.id, isActive: true}, {isActive: false}, {useFindAndModify: false})
.then(data => {
if(data.modifiedCount > 0) {
return sendMessage(res, 37, {message: `Video ${id} was successfully deleted.`}, token);
} else {
return sendError(res, 404, 105, `Video not found with id=${id}`, token);
}
})
.catch(err => {
return sendError(res, 500, 100, err.message || `Some error occurred while deleting the Video with id=${id}`, token);
});
} else {
return sendError(res, 500, -1, `Error id is not valid`, token);
}
} else {
return sendError(res, 500, -1, `No id given`, token);
}
};
// Delete all Videos
exports.deleteAll = (req, res) => {
const token = checkLogin(req, res);
if(token) {
Video.updateMany({userId: {$eq: token.id}, isActive: true}, {isActive: false})
.then(data => {
return sendMessage(res, 38, {
message: `${data.modifiedCount} Videos were deleted successfully.`,
});
})
.catch(err => {
return sendError(res, 500, 100, err.message || "Some error occurred while removing all Videos.");
});
}
};

View file

@ -1,14 +0,0 @@
-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtW31Xj62sjbJVBxnn0G2
Habc22q7/pFIBdfn8+OsajdNVnmtfRNOsSXZP8sNhXt1QLPSgxZ/wogG0fLXIX2+
ewzPgqrwTnr+quJ1DZ6RqOY3G1PGOibgk25aHkIXJ/gTPk1yTT6pjUmKiaGKM8pt
M2wGwugCdEH5Wndgby8Jej30v/PPzyPxTSXrIWDeaSMX+jQyFZTGgEdgL7JvjkTj
qLtfWKIAcEeO4PzOlRXVvbzBoYphBiZqkbzEeuOjSLPxgy4cQdbqVMlJ/lZt0SBO
MLiIUBTufLcJS3ApesiZWWfUCq+pFFdhEABc9qrtVumzhmzWAv2rKVrHRXbguxc/
eHKlRjAE4qmnNnTP2fsAuQIPkXVHOPWdXM1IBwnhXVB+XhxEHSANx/2oeKS6fO/e
1oNJCiVkHin9gC8vkU9seEN73lNKZ5wPXMqTYUGA65dCY+8li+n/1pveJOJozFk7
amkmOAPTi44lBJmxRm88XBHC3TXz6tFqX3phMqFDcQs2D9s3/2UylK0dSH5MSLnb
9x24/ykO4RlPRVCC90vwlxzbnb0rfQVlT4dKcE6OIyXw3UsqIqFnXWmm+hnGu4QH
Ysr+i1VIhPOs9YdZwlqhzcPTuNcdxmxy9ZfZ8KlLIWbAMbSH+obwm4w+HYTZjspe
2MwrKGgzpl4YW7ct/ViqeQMCAwEAAQ==
-----END PUBLIC KEY-----

View file

@ -1,8 +0,0 @@
#!/usr/bin/env bash
ssh-keygen -t rsa -b 4096 -m PEM -f jwtRS256.key -q -N ""
openssl rsa -in jwtRS256.key -pubout -outform PEM -out jwtRS256.key.pub
#rm .env
echo "JWTRS256_PRIVATE_KEY='`cat ./jwtRS256.key | base64 -w 0`'" >> .env
echo "JWTRS256_PUBLIC_KEY='`cat ./jwtRS256.key.pub | base64 -w 0`'" >> .env
source .env
rm jwtRS256.key

View file

@ -1,44 +0,0 @@
module.exports = mongoose => {
let schema = mongoose.Schema({
userId: String,
title: String,
images: {
type: Array,
default: []
},
url: {
type: String,
default: null
},
interests: {
type: Array,
default: []
},
comment: {
type: String,
default: null
},
views: {
type: Array,
default: []
},
isVisible: {
type: Boolean,
default: true
},
isActive: {
type: Boolean,
default: true
}
},
{ timestamps: true }
);
schema.method("toJSON", function() {
const { __v, _id, ...object } = this.toObject();
object.id = _id;
return object;
});
return mongoose.model("ads", schema);
};

View file

@ -1,24 +0,0 @@
module.exports = mongoose => {
let schema = mongoose.Schema({
userId: String,
videoIds: {
type: Array,
default: []
},
name: String,
isActive: {
type: Boolean,
default: true
}
},
{ timestamps: true }
);
schema.method("toJSON", function() {
const { __v, _id, ...object } = this.toObject();
object.id = _id;
return object;
});
return mongoose.model("playlists", schema);
};

View file

@ -1,48 +0,0 @@
const roles = require("../objects/role.model");
module.exports = mongoose => {
let schema = mongoose.Schema({
email: String,
hashPass: String, // WARNING: We don't want to send back the hashPass
login: String,
role: {
type: Object,
default: roles.User
},
company: String,
profileImageUrl: {
type: String,
default: "https://www.handiclubnimois.fr/wp-content/uploads/2020/10/blank-profile-picture-973460_1280.png"
},
dateOfBirth: {
type: Date,
default: null
},
gender: {
type: String,
default: null
},
interests: {
type: Array,
default: null
},
isActive: {
type: Boolean,
default: true
},
lastConnexion: {
type: Date,
default: null
}
},
{ timestamps: true }
);
schema.method("toJSON", function() {
const { __v, _id, ...object } = this.toObject();
object.id = _id;
return object;
});
return mongoose.model("users", schema);
};

View file

@ -1,29 +0,0 @@
module.exports = mongoose => {
let schema = mongoose.Schema({
userId: String,
videoId: String,
source: String,
interest: {
type: String,
default: null
},
watchedDates: {
type: Array,
default: null
},
isActive: {
type: Boolean,
default: true
}
},
{ timestamps: true }
);
schema.method("toJSON", function() {
const { __v, _id, ...object } = this.toObject();
object.id = _id;
return object;
});
return mongoose.model("videos", schema);
};

View file

@ -1,19 +0,0 @@
const dbConfig = require("../config/mongodb.config");
const mongoose = require("mongoose");
mongoose.Promise = global.Promise;
const db = {};
db.mongoose = mongoose;
if(typeof process.env.NODE_ENV !== 'undefined' && process.env.NODE_ENV === 'production'){
db.url = dbConfig.prodUrl;
} else {
db.url = dbConfig.devUrl;
}
db.users = require("./database/users.model")(mongoose);
db.playlists = require("./database/playlists.model")(mongoose);
db.videos = require("./database/videos.model")(mongoose);
db.ads = require("./database/ads.model")(mongoose);
module.exports = db;

View file

@ -1,10 +0,0 @@
class Image {
constructor(base64, url, description, type){
this.base64 = base64;
this.url = url;
this.description = description;
this.type = type;
}
}
module.exports = Image;

View file

@ -1,22 +0,0 @@
module.exports = {
User: {
name: "user",
permission: 0,
isAccepted: true
},
Advertiser: {
name: "advertiser",
permission: 5,
isAccepted: false
},
Admin: {
name: "admin",
permission: 10,
isAccepted: false
},
SuperAdmin: {
name: "superAdmin",
permission: 1000,
isAccepted: true
}
};

View file

@ -1,157 +0,0 @@
const {youtube, dailymotion} = require('../../config/host.config');
module.exports = [
{
id: 0,
interest: "Actualités",
categories: [
{id: "news", name: "News", source: dailymotion.name},
{id: "25", name: "News & Politics", source: youtube.name},
]
},
{
id: 1,
interest: "Animaux",
categories: [
{id: "animals", name: "animaux", source: dailymotion.name},
{id: "15", name: "Pets & Animals", source: youtube.name},
]
},
{
id: 2,
interest: "Arts",
categories: [
{id: "creation", name: "Art", source: dailymotion.name},
{id: "", name: "", source: youtube.name},
]
},
{
id: 3,
interest: "Autos",
categories: [
{id: "auto", name: "Auto-Moto", source: dailymotion.name},
{id: "2", name: "Autos & Vehicles", source: youtube.name},
]
},
{
id: 4,
interest: "Divertissements",
categories: [
{id: "tv", name: "TV", source: dailymotion.name},
{id: "fun", name: "Humour & Divertissement", source: dailymotion.name},
{id: "webcam", name: "Webcam", source: dailymotion.name},
{id: "23", name: "Comedy", source: youtube.name},
{id: "24", name: "Entertainment", source: youtube.name},
{id: "43", name: "Shows", source: youtube.name}
]
},
{
id: 5,
interest: "Éducation",
categories: [
{id: "school", name: "Éducation", source: dailymotion.name},
{id: "27", name: "Education", source: youtube.name}
]
},
{
id: 6,
interest: "Événements",
categories: [
{id: "", name: "", source: dailymotion.name},
{id: "19", name: "Travel & Events", source: youtube.name},
]
},
{
id: 7,
interest: "Films",
categories: [
{id: "shortfilms", name: "Cinéma", source: dailymotion.name},
{id: "1", name: "Film & Animation", source: youtube.name},
{id: "18", name: "Short Movies", source: youtube.name},
{id: "30", name: "Movies", source: youtube.name},
{id: "31", name: "Anime/Animation", source: youtube.name},
{id: "32", name: "Action/Adventure", source: youtube.name},
{id: "33", name: "Comedy", source: youtube.name},
{id: "35", name: "Documentary", source: youtube.name},
{id: "36", name: "Drama", source: youtube.name},
{id: "39", name: "Horror", source: youtube.name},
{id: "40", name: "Sci-Fi/Fantasy", source: youtube.name},
{id: "41", name: "Thriller", source: youtube.name},
{id: "42", name: "Shorts", source: youtube.name},
{id: "44", name: "Trailers", source: youtube.name}
]
},
{
id: 8,
interest: "Jeux vidéo",
categories: [
{id: "videogames", name: "Jeux vidéo", source: dailymotion.name},
{id: "20", name: "Gaming", source: youtube.name},
]
},
{
id: 9,
interest: "Kids",
categories: [
{id: "kids", name: "Kids", source: dailymotion.name},
{id: "", name: "", source: youtube.name},
]
},
{
id: 10,
interest: "Modes de vie",
categories: [
{id: "lifestyle", name: "Lifestyle & Tutoriels", source: dailymotion.name},
{id: "26", name: "Howto & Style", source: youtube.name},
]
},
{
id: 11,
interest: "Musiques",
categories: [
{id: "music", name: "Musique", source: dailymotion.name},
{id: "10", name: "Music", source: youtube.name},
]
},
{
id: 12,
interest: "People",
categories: [
{id: "people", name: "Amis & Famille", source: dailymotion.name},
{id: "21", name: "Videoblogging", source: youtube.name},
{id: "22", name: "People & Blogs", source: youtube.name},
{id: "37", name: "Family", source: youtube.name},
]
},
{
id: 13,
interest: "Science et Technologie",
categories: [
{id: "tech", name: "Tech", source: dailymotion.name},
{id: "28", name: "Science & Technology", source: youtube.name},
]
},
{
id: 14,
interest: "Sports",
categories: [
{id: "sport", name: "Sport", source: dailymotion.name},
{id: "17", name: "Sports", source: youtube.name},
]
},
{
id: 15,
interest: "Voyages",
categories: [
{id: "travel", name: "Voyages", source: dailymotion.name},
{id: "38", name: "Foreign", source: youtube.name},
]
},
{
id: 16,
interest: "Autres",
categories: [
{id: "29", name: "Nonprofits & Activism", source: youtube.name},
{id: "33", name: "Classics", source: youtube.name}
]
}
];

View file

@ -1,24 +0,0 @@
const ads = require("../controllers/ad.controller");
module.exports = app => {
let router = require("express").Router();
// Create a new Ad
router.post("/ad/create", ads.create);
// Retrieve all Ad from id if admin or session id
router.get("/ad/findAll", ads.findAll);
// Find single Ad from id if admin or session id
router.get("/ad/findOne/:id", ads.findOne);
// Update a Ad with ad id
router.put("/ad/update/:id", ads.update);
// Delete a Ad with ad id
router.delete("/ad/delete/:id", ads.delete);
// Delete all Ad from id if admin or session id
router.delete("/ad/deleteAll", ads.deleteAll);
app.use('/api', router);
};

View file

@ -1,9 +0,0 @@
const misc = require("../controllers/misc.controller");
module.exports = app => {
let router = require("express").Router();
// Get all interests available
router.get("/misc/getInterests", misc.getInterests);
app.use('/api', router);
};

View file

@ -1,24 +0,0 @@
const playlists = require("../controllers/playlist.controller");
module.exports = app => {
let router = require("express").Router();
// Create a new Playlist
router.post("/playlist/create", playlists.create);
// Retrieve all Playlist from id if admin or session id
router.get("/playlist/findAll", playlists.findAll);
// Find single Playlist from id if admin or session id
router.get("/playlist/findOne/:id", playlists.findOne);
// Update a Playlist with playlist id
router.put("/playlist/update/:id", playlists.update);
// Delete a Playlist with playlist id
router.delete("/playlist/delete/:id", playlists.delete);
// Delete all Playlists from id if admin or session id
router.delete("/playlist/deleteAll", playlists.deleteAll);
app.use('/api', router);
};

View file

@ -1,42 +0,0 @@
const users = require("../controllers/user.controller");
module.exports = app => {
let router = require("express").Router();
// Authenticate a User
router.post("/user/auth", users.auth);
// Logout a User
router.delete("/user/logout", users.logout);
// Request password reset with email
router.post("/user/resetPass", users.resetPass);
// Create and Save a new User
router.post("/user/create", users.create);
// Retrieve all Users if admin
router.get("/user/findAll", users.findAll);
// Find single User from id if admin or session id
router.get("/user/findOne/:id", users.findOne);
// Update a User from id if admin or session id
router.put("/user/update/:id", users.update);
// Delete a User from id if admin or session id
router.delete("/user/delete/:id", users.delete);
// Delete all Users if superAdmin
router.delete("/user/deleteAll", users.deleteAll);
// Get all Roles depending on the User session id
router.get("/user/roles", users.roles);
// Get 1 or multiple ad adapted to the User session id
router.get("/user/ad", users.ad);
// Get History
router.get("/user/history", users.history);
app.use('/api', router);
};

View file

@ -1,30 +0,0 @@
const videos = require("../controllers/video.controller");
module.exports = app => {
let router = require("express").Router();
// Search Videos
router.get("/video/search", videos.search);
// Get Video with id of source
router.get("/video/get/:id", videos.get);
// Create a new Video
router.post("/video/create/:id", videos.create);
// Retrieve all Videos
router.get("/video/findAll", videos.findAll);
// Find single Video with id
router.get("/video/findOne/:id", videos.findOne);
// Update Video with id
router.put("/video/update/:id", videos.update);
// Delete Video with id
router.delete("/video/delete/:id", videos.delete);
// Delete all Videos
router.delete("/video/deleteAll", videos.deleteAll);
app.use('/api', router);
};

View file

@ -25,7 +25,7 @@ module.exports = function (config) {
suppressAll: true // removes the duplicated traces
},
coverageReporter: {
dir: require('path').join(__dirname, './coverage/frontend'),
dir: require('path').join(__dirname, './coverage/userAndAdvertiser'),
subdir: '.',
reporters: [
{ type: 'html' },

View file

@ -1,67 +1,47 @@
{
"name": "frontend",
"version": "1.0.0",
"name": "frontend-user-advertiser",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "node server.js",
"dev": "ng serve",
"build": "ng build --configuration production",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
"build": "ng build",
"watch": "ng build --watch --configuration development",
"test": "ng test"
},
"private": true,
"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",
"@angular/platform-browser": "^12.2.11",
"@angular/platform-browser-dynamic": "^12.2.11",
"@angular/router": "^12.2.11",
"@ng-bootstrap/ng-bootstrap": "^10.0.0",
"angular-responsive-carousel": "^2.1.2",
"body-parser": "^1.19.0",
"@angular/animations": "~12.2.0",
"@angular/cdk": "^13.1.1",
"@angular/common": "~12.2.0",
"@angular/compiler": "~12.2.0",
"@angular/core": "~12.2.0",
"@angular/forms": "~12.2.0",
"@angular/material": "^13.1.1",
"@angular/platform-browser": "~12.2.0",
"@angular/platform-browser-dynamic": "~12.2.0",
"@angular/router": "~12.2.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",
"express": "^4.17.2",
"jquery": "^3.6.0",
"jsonwebtoken": "^8.5.1",
"mongoose": "^6.0.12",
"ng2-charts": "^2.2.3",
"popper": "^1.0.1",
"request": "^2.88.2",
"rxjs": "~6.6.0",
"tslib": "^2.0.0",
"typescript": "~4.3.5",
"zone.js": "~0.11.3"
"tslib": "^2.3.0",
"zone.js": "~0.11.4",
"chart.js": "^2.9.3"
},
"devDependencies": {
"@angular-devkit/build-angular": "~12.2.11",
"@angular/cli": "~12.2.11",
"@angular/compiler-cli": "~12.2.11",
"@angular/localize": "^12.2.11",
"@types/jasmine": "~3.6.0",
"@angular-devkit/build-angular": "~12.2.14",
"@angular/cli": "~12.2.14",
"@angular/compiler-cli": "~12.2.0",
"@types/jasmine": "~3.8.0",
"@types/node": "^12.11.1",
"codelyzer": "^6.0.0",
"jasmine-core": "~3.6.0",
"jasmine-spec-reporter": "~5.0.0",
"karma": "~6.3.5",
"jasmine-core": "~3.8.0",
"karma": "~6.3.0",
"karma-chrome-launcher": "~3.1.0",
"karma-coverage": "~2.0.3",
"karma-jasmine": "~4.0.0",
"karma-jasmine-html-reporter": "^1.5.0",
"protractor": "~7.0.0",
"ts-node": "~8.3.0",
"tslint": "~6.1.0",
"karma-jasmine-html-reporter": "~1.7.0",
"typescript": "~4.3.5"
}
}

View file

@ -3,80 +3,9 @@ const express = require('express');
const app = express();
const port = process.env.PORT || 3000;
const cookieParser = require('cookie-parser');
app.use(cookieParser());
const bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({extended:true}));
app.use(bodyParser.json());
const cors = require('cors');
app.use(cors({origin: 'http://127.0.0.1:4200', credentials: true}));
const db = require("./app-backend/models/mongodb.model");
console.log("Db Url: ",db.url);
db.mongoose
.connect(db.url, {
useNewUrlParser: true,
useUnifiedTopology: true
}, function (err){
const admin = new db.mongoose.mongo.Admin(db.mongoose.connection.db);
admin.buildInfo(function (err, info) {
console.log("MongoDB Version: "+info.version);
});
if(err){
console.log("Cannot connect to the database!", err);
process.exit();
} else{
console.log("Connected to the database!", db.url);
}
});
require("./app-backend/routes/user.routes")(app);
require("./app-backend/routes/playlist.routes")(app);
require("./app-backend/routes/video.routes")(app);
require("./app-backend/routes/ad.routes")(app);
require("./app-backend/routes/misc.routes")(app);
const roles = require("./app-backend/models/objects/role.model");
const User = db.users;
const login = 'superAdmin';
const hashPass = 'hashPassSuperAdmin';
const mail = 'superAdmin@email.admin';
User.exists({role: roles.SuperAdmin}, function (err, docs){
if(err){
console.log("Some error occurred while checking if superAdmin already exists.");
} else{
if(docs === null){
const user = new User({
login: login,
hashPass: hashPass,
email: mail,
role: roles.SuperAdmin
});
user
.save(user)
.then(data => {
data.hashPass = undefined; // Hiding hashPass on return
console.log(data);
})
.catch(err => {
console.log(err.message || "Some error occurred while creating superAdmin.");
});
} else {
console.log("superAdmin already exist !");
}
}
});
app.get('/*all', function(req,res) {
res.sendFile(path.join(__dirname+ '/dist/index.html'));
});
app.use(express.static(__dirname + '/dist/frontend'));
app.use(express.static(__dirname + '/dist/frontend-userAndAdvertiser'));
app.get('/*', function(req,res) {
res.sendFile(path.join(__dirname+ '/dist/frontend/index.html'));
res.sendFile(path.join(__dirname+ '/dist/frontend-userAndAdvertiser/index.html'));
});
app.listen(port, '0.0.0.0',() => {

View file

@ -1,167 +0,0 @@
<div [class]="themeService.getClassTheme()">
<div class="myContainer">
<!-- Navbar -->
<app-navbar-admin></app-navbar-admin><br><br>
<!-- filtre -->
<div class="filtersContainer mat-elevation-z8">
<!-- titre -->
<div style="font-weight: bold; margin-bottom: 10px;">
Filtre
</div>
<mat-divider></mat-divider>
<!-- filtre textuelle-->
<div style="margin: 10px 0px 20px 2%;">
<input class="textFilter" (keyup)="applyFilter($event)" placeholder="Rechercher par mots-clés...">
</div>
<!-- visible + interests + 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>
<!-- subjects -->
<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: &nbsp;
<mat-form-field appearance="fill" style="width: 140px; font-size: small;">
<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>
&nbsp; - &nbsp;
<mat-form-field appearance="fill" style="width: 140px; font-size: small;">
<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>
<!-- table -->
<table mat-table [dataSource]="dataSource" matSort class="mat-elevation-z8">
<!-- Title Column -->
<ng-container matColumnDef="title">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Titre </th>
<td mat-cell *matCellDef="let advert">
{{advert.title}}
</td>
</ng-container>
<!-- Advertiser Column -->
<ng-container matColumnDef="company">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Entreprise </th>
<td mat-cell *matCellDef="let advert">
{{advert.company}}
</td>
</ng-container>
<!-- Tags Column -->
<ng-container matColumnDef="interests">
<th mat-header-cell *matHeaderCellDef> Sujets </th>
<td mat-cell *matCellDef="let advert">
<span *ngFor="let objectInterest of advert.interests; let isLast = last;">
<span *ngIf="!isLast"> {{objectInterest.interest}}, </span>
<span *ngIf="isLast"> {{objectInterest.interest}} </span>
</span>
</td>
</ng-container>
<!-- CreatedAt Column -->
<ng-container matColumnDef="createdAt">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Date de création </th>
<td mat-cell *matCellDef="let advert">
{{ advert.createdAt | date:'dd/LL/YYYY à HH:mm:ss' }}
</td>
</ng-container>
<!-- UpdatedAt Column -->
<ng-container matColumnDef="updatedAt">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Dernière modification </th>
<td mat-cell *matCellDef="let advert">
{{ advert.updatedAt | date:'dd/LL/YYYY à HH:mm:ss' }}
</td>
</ng-container>
<!-- CountViews Column -->
<ng-container matColumnDef="countViews">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Vues </th>
<td mat-cell *matCellDef="let advert">
{{advert.countViews}}
</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>
</td>
</ng-container>
<!-- Actions Column -->
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef> Actions </th>
<td mat-cell *matCellDef="let advert">
<button mat-icon-button (click)="onVisualizeImages(advert)">
<mat-icon> insert_photo</mat-icon>
</button>
<button mat-icon-button (click)="onDelete(advert)">
<mat-icon>delete</mat-icon>
</button>
</td>
</ng-container>
<!-- Directives -->
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
<tr class="mat-row" *matNoDataRow>
<td class="mat-cell" colspan="4"> Aucune vidéo ne correspond au filtre: "{{input.value}}" </td>
</tr>
</table>
<div style="width: 94%; margin: auto auto">
<mat-paginator [pageSizeOptions]="[10, 20, 50, 100]" showFirstLastButtons aria-label="Select page of periodic elements"></mat-paginator>
</div>
<br><br>
</div>
</div>

View file

@ -1,74 +0,0 @@
.myContainer {
max-width: 100vw;
height: 100vh;
overflow-x: hidden;
font-size: small;
}
// ----------------------------------------------------------
.filtersContainer {
width: 80%;
background-color: white;
padding: 10px 10px 10px 10px;
margin: 20px 3% 20px 3%
}
.myRow {
margin-left: 1%;
}
.textFilter {
width: 50%;
font-size: medium;
border-radius: 5px;
}
// ----------------------------------------------------------
table {
margin: 0 auto;
width: 94%;
font-size: small;
}
.darkTheme table { border: solid 2px white; }
th.mat-sort-header-sorted {
color: black;
}
td {
font-size: small;
}
input {
width: 30%;
font-size: large;
border-radius: 5px;
}
// -------------------------------------------------------------------------
// 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;
}
::ng-deep .mat-pseudo-checkbox-checked {
background-color: black !important;
}

View file

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

View file

@ -1,262 +0,0 @@
import {AfterViewInit, Component, ViewChild} from '@angular/core';
import {MatSort} from "@angular/material/sort";
import {MatPaginator} from "@angular/material/paginator";
import {ThemeService} from "../../../utils/services/theme/theme.service";
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 {PopupDeleteAdAdminComponent} from "../popup-delete-ad-admin/popup-delete-ad-admin.component";
import {PopupVisualizeImagesAdminComponent} from "../popup-visualize-images-admin/popup-visualize-images-admin.component";
import {FormControl} from "@angular/forms";
import {MessageService} from "../../../utils/services/message/message.service";
import {HttpParams} from "@angular/common/http";
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,
}
@Component({
selector: 'app-page-ad-list-admin',
templateUrl: './page-ad-list-admin.component.html',
styleUrls: ['./page-ad-list-admin.component.scss']
})
export class PageAdListAdminComponent implements AfterViewInit
{
tabAdvertWithCountViews: AdvertWithCountViewsAndCompany[] = [];
tabAdvertiser: any[];
displayedColumns: string[] = [ 'title', 'company', 'interests', 'createdAt', 'updatedAt', 'countViews', 'isVisible', 'actions' ];
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,
public dialog: MatDialog,
private snackBar: MatSnackBar,
private messageService: MessageService) { }
ngAfterViewInit(): void
{
// Ask for ads and then for advertiser
let params = new HttpParams();
params = params.append("isActive", true);
this.messageService
.get("ad/findAll", params)
.subscribe(ret => this.afterReceivingAds(ret), err => this.afterReceivingAds(err) );
// Ask for interest
this.messageService
.get("misc/getInterests")
.subscribe(ret => this.afterReceivingInterests(ret), err => this.afterReceivingInterests(err) );
}
afterReceivingAds(retour: any): void
{
if(retour.status !== "success") {
console.log(retour);
}
else {
const tabAdvert = retour.data;
this.messageService
.get("user/findAll")
.subscribe(ret => this.afterReceivingAdvertiser(ret, tabAdvert), err => this.afterReceivingAdvertiser(err, tabAdvert) );
}
}
afterReceivingAdvertiser(retour: any, tabAdvert): void
{
if(retour.status !== "success") {
console.log(retour);
}
else {
this.tabAdvertiser = retour.data.filter(x => x.role.name === "advertiser");
for(let advert of tabAdvert) this.tabAdvertWithCountViews.push(this.advertToAdvertWithCountViewsAndCompany(advert));
this.dataSource = new MatTableDataSource<Advert>();
this.onFilter();
}
}
afterReceivingInterests(retour: any): void
{
if(retour.status !== "success") {
console.log(retour);
}
else {
this.allInterests = retour.data.map(x => x.interest);
this.allInterests.sort();
}
}
applyFilter(event: Event): void
{
const filterValue = (event.target as HTMLInputElement).value;
this.dataSource.filter = filterValue.trim().toLowerCase();
}
onVisualizeImages(advert: AdvertWithCountViewsAndCompany)
{
if(advert.images.length !== 0)
{
const config = {
width: '30%',
height: '90%',
data: { images: advert.images }
};
this.dialog
.open(PopupVisualizeImagesAdminComponent, config)
.afterClosed()
.subscribe(retour => {});
}
else {
const config = { duration: 2000, panelClass: "custom-class" };
const message = "Cette annonce ne contient aucune image" ;
this.snackBar.open( message, "", config);
}
}
onDelete(advert: AdvertWithCountViewsAndCompany): void
{
const config = {
data: { advert: advert }
};
this.dialog
.open(PopupDeleteAdAdminComponent, config)
.afterClosed()
.subscribe( retour => {
const config = { duration: 1000, panelClass: "custom-class" };
let message = "" ;
if((retour === undefined) || (retour === null)) {
message = "Opération annulée" ;
}
else {
const index = this.dataSource.data.findIndex( elt => (elt.id === advert.id));
this.dataSource.data.splice(index, 1);
this.dataSource.data = this.dataSource.data;
this.dataSource = this.dataSource;
message = advert.title + " a bien été supprimée ✔" ;
}
this.snackBar.open( message, "", config);
});
}
onFilter(): void
{
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);
}
advertToAdvertWithCountViewsAndCompany(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,
}
}
}

View file

@ -1,8 +0,0 @@
<mat-dialog-content class="mat-typography">
Êtes-vous sûr de vouloir supprimer l'annonce <i>{{advert.title}}</i> ?
</mat-dialog-content>
<mat-dialog-actions align="end">
<button mat-button (click)="dialogRef.close();">Annuler</button>
<button mat-button (click)="onValidate()" cdkFocusInitial>Valider</button>
</mat-dialog-actions>

View file

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

View file

@ -1,49 +0,0 @@
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-ad-admin',
templateUrl: './popup-delete-ad-admin.component.html',
styleUrls: ['./popup-delete-ad-admin.component.scss']
})
export class PopupDeleteAdAdminComponent implements OnInit
{
advert: any;
constructor( public dialogRef: MatDialogRef<PopupDeleteAdAdminComponent>,
@Inject(MAT_DIALOG_DATA) public data,
private messageService: MessageService) { }
ngOnInit(): void
{
this.advert = this.data.advert;
}
onValidate(): void
{
this.messageService
.delete("ad/delete/"+this.advert.id)
.subscribe(ret => this.onValidateCallback(ret), err => this.onValidateCallback(err));
}
onValidateCallback(retour: any): void
{
if(retour.status !== "success") {
console.log(retour);
this.dialogRef.close();
}
else {
console.log("suppr");
console.log(retour);
this.dialogRef.close(true);
}
}
}

View file

@ -1,20 +0,0 @@
<div mat-dialog-title class="dialog-title">
<h2></h2>
<button mat-icon-button aria-label="close dialog" mat-dialog-close>
<mat-icon>close</mat-icon>
</button>
</div>
<mat-grid-list cols="12" rowHeight="500">
<mat-grid-tile colspan="1" rowspan="1" (click)="onPrecedent()">
<button> < </button>
</mat-grid-tile>
<mat-grid-tile colspan="10" rowspan="1">
<img [src]="tabImages[index].base64" [alt]="tabImages[index].description">
</mat-grid-tile>
<mat-grid-tile colspan="1" rowspan="1" (click)="onSuivant()">
<button> > </button>
</mat-grid-tile>
</mat-grid-list>

View file

@ -1,14 +0,0 @@
carousel {
width: 100%;
margin: 0 auto;
text-align: center;
justify-content: center
}
.dialog-title {
display: flex;
justify-content: space-between;
align-items: center;
}

View file

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

View file

@ -1,38 +0,0 @@
import {Component, Inject, OnInit} from '@angular/core';
import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";
@Component({
selector: 'app-popup-visualize-images-admin',
templateUrl: './popup-visualize-images-admin.component.html',
styleUrls: ['./popup-visualize-images-admin.component.scss']
})
export class PopupVisualizeImagesAdminComponent implements OnInit
{
tabImages = [];
index: number = 0;
nbImage: number = 0;
constructor( public dialogRef: MatDialogRef<PopupVisualizeImagesAdminComponent>,
@Inject(MAT_DIALOG_DATA) public data ) { }
ngOnInit(): void
{
this.tabImages = this.data.images;
this.nbImage = this.tabImages.length;
}
onPrecedent(): void
{
if(this.index !== 0) this.index -= 1;
}
onSuivant(): void
{
if(this.index !== (this.nbImage-1)) this.index += 1;
}
}

View file

@ -1,43 +0,0 @@
<div [class]="themeService.getClassTheme()">
<div class="myContainer">
<!-- NavBar -->
<app-navbar-admin></app-navbar-admin>
<!-- Boite -->
<div class="boite">
<!-- Photo de profil -->
<div style="text-align: center">
<img [src]="admin.profileImageUrl"
onerror="this.onerror=null; this.src='assets/profil.png'">
</div>
<!-- login -->
<div class="row myRow">
<div class="col-6 myLabel">Pseudo:</div>
<div class="col-6 myValue"> {{admin.login}} </div>
</div>
<!-- email -->
<div class="row myRow">
<div class="col-6 myLabel">Mail:</div>
<div class="col-6 myValue"> {{admin.email}} </div>
</div>
<!-- createdAt -->
<div class="row myRow">
<div class="col-6 myLabel">Date de création:</div>
<div class="col-6 myValue">{{admin.createdAt | date:'dd/LL/YYYY'}}</div>
</div>
<!-- Modifier profil -->
<div class="btnContainer">
<button mat-button class="myBtn" (click)="onModifier()">Modifier profil</button>
</div>
</div>
</div>
</div>

View file

@ -1,61 +0,0 @@
.myContainer {
max-width: 100vw;
height: 100vh;
overflow-x: hidden;
}
.boite {
margin-left: auto;
margin-right: auto;
width: 25%;
margin-top: 10vh;
border: solid 3px;
border-radius: 10px;
padding: 20px 40px 20px 40px;
background-color: #ffffff;
text-align: center;
box-shadow: 10px 5px 5px black;
}
.lightTheme .boite {
border-color: black;
}
.darkTheme .boite {
border-color: white;
}
img {
margin: 0px 0px 10px 0px;
width: 5vw;
height: 5vw;
border: solid 2px black;
border-radius: 50%;
font-size: xxx-large;
}
.myRow {
margin: 15px 0px 15px 0px;
}
.myLabel {
text-align: right;
padding: 0px 5px 0px 0px;
margin: 0px;
font-weight: bold;
}
.myValue {
text-align: left;
padding: 0px 0px 0px 5px;
margin: 0px;
}
.btnContainer {
text-align: center;
margin-top: 40px;
}
.myBtn {
border: solid 1px black;
background-color: white;
}

View file

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

View file

@ -1,90 +0,0 @@
import { Component, OnInit } from '@angular/core';
import {User} from "../../../utils/interfaces/user";
import {ThemeService} from "../../../utils/services/theme/theme.service";
import {MatDialog} from "@angular/material/dialog";
import {MatSnackBar} from "@angular/material/snack-bar";
import {PopupUpdateAdminComponent} from "../popup-update-admin/popup-update-admin.component";
import {MessageService} from "../../../utils/services/message/message.service";
import {ProfilService} from "../../../utils/services/profil/profil.service";
@Component({
selector: 'app-page-profil-admin',
templateUrl: './page-profil-admin.component.html',
styleUrls: ['./page-profil-admin.component.scss']
})
export class PageProfilAdminComponent implements OnInit
{
admin: User = {
_id: "",
login: "",
hashPass: "",
email: "",
role: {
name: "admin",
permission: 10,
isAccepted: true,
},
profileImageUrl: "",
dateOfBirth: null,
gender: "man",
interests: [],
company: "",
isActive: true,
createdAt: new Date(),
updatedAt: new Date(),
lastConnexion: null
};
constructor( public themeService: ThemeService,
public dialog: MatDialog,
private snackBar: MatSnackBar,
private messageService: MessageService,
private profilService: ProfilService ) { }
ngOnInit(): void
{
this.messageService
.get( "user/findOne/"+this.profilService.getId())
.subscribe( retour => this.ngOnInitCallback(retour), err => this.ngOnInitCallback(err) )
}
ngOnInitCallback(retour: any)
{
if(retour.status !== "success") {
console.log(retour);
}
else {
this.admin = retour.data;
}
}
onModifier()
{
const config = {
width: '25%',
data: { admin: this.admin }
};
this.dialog
.open(PopupUpdateAdminComponent, config)
.afterClosed()
.subscribe(retour => {
if((retour === null) || (retour === undefined))
{
const config = { duration: 1000, panelClass: "custom-class" };
this.snackBar.open( "Opération annulé", "", config);
}
else
{
this.admin = retour;
}
});
}
}

View file

@ -1,59 +0,0 @@
<div class="myContainer">
<div class="boite">
<!-- photo de profil -->
<div style="text-align: center">
<img [src]="adminCopy.profileImageUrl" onerror="this.onerror=null; this.src='assets/profil.png'"><br>
<input title="lien vers image" type="text" [(ngModel)]="adminCopy.profileImageUrl" style="width: 90%">
</div>
<!-- divider -->
<br><mat-divider></mat-divider><br>
<!-- login -->
<mat-form-field appearance="fill">
<mat-label>Pseudo</mat-label>
<input matInput type="text" [(ngModel)]="adminCopy.login">
</mat-form-field><br>
<!-- divider -->
<mat-divider></mat-divider><br>
<!-- Modifier mot de passe -->
<div>
Modifier mot de passe:
<mat-checkbox [(ngModel)]="changePassword"></mat-checkbox>
</div>
<!-- nouveau mot de passe -->
<div *ngIf="changePassword" style="margin-top: 10px">
<!-- Nouveau mot de passe -->
<mat-form-field appearance="fill">
<mat-label>Nouveau mot de passe</mat-label>
<input matInput type="password" [(ngModel)]="newPassword">
</mat-form-field>
<br>
<!-- Confirmation npuveau mot de passe -->
<mat-form-field appearance="fill">
<mat-label>Confirmation nouveau mot de passe</mat-label>
<input matInput type="password" [(ngModel)]="confirmNewPassword">
</mat-form-field>
</div>
<div *ngIf="!changePassword"><br></div>
<!-- divider -->
<mat-divider></mat-divider><br>
<!-- message d'erreur -->
<div *ngIf="hasError" style="text-align: center; margin-bottom: 20px;">
<span class="mat-error">{{errorMessage}}</span>
</div>
<!-- boutons -->
<div style="width: 100%; text-align: right">
<button mat-button (click)="this.dialogRef.close(null)"> Annuler </button>
<button mat-button (click)="onValider()"> Enregistrer </button>
</div>
</div>
</div>

View file

@ -1,33 +0,0 @@
.boite {
font-size: small;
}
button {
font-size: small;
}
img {
margin: 0px 0px 10px 0px;
width: 5vw;
height: 5vw;
border: solid 2px black;
border-radius: 50%;
font-size: xxx-large;
}
// -------------------------------------------------------------------------
// 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 {
background-color: white !important;
}

View file

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

View file

@ -1,124 +0,0 @@
import {Component, Inject, OnInit} from '@angular/core';
import {User} from "../../../utils/interfaces/user";
import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";
import {MessageService} from "../../../utils/services/message/message.service";
import {ProfilService} from "../../../utils/services/profil/profil.service";
@Component({
selector: 'app-popup-update-admin',
templateUrl: './popup-update-admin.component.html',
styleUrls: ['./popup-update-admin.component.scss']
})
export class PopupUpdateAdminComponent implements OnInit
{
adminCopy: User;
newPassword: string = "";
confirmNewPassword: string = "" ;
changePassword: boolean = false ;
hasError: boolean = false;
errorMessage: string = "" ;
constructor( public dialogRef: MatDialogRef<PopupUpdateAdminComponent>,
@Inject(MAT_DIALOG_DATA) public data,
private messageService: MessageService,
private profilService: ProfilService ) { }
ngOnInit(): void
{
const admin0 = this.data.admin;
this.adminCopy = {
_id: admin0._id,
login: admin0.login,
hashPass: admin0.hashPass,
email: admin0.email,
role: {
name: admin0.role.name,
permission: admin0.role.permission,
isAccepted: admin0.role.isAccepted,
},
profileImageUrl: admin0.profileImageUrl,
dateOfBirth: admin0.dateOfBirth,
gender: admin0.gender,
interests: [],
company: "",
isActive: admin0.isActive,
createdAt: admin0.createdAt,
updatedAt: admin0.updatedAt,
lastConnexion: admin0.lastConnexion
};
for(let interest of admin0.interests) this.adminCopy.interests.push(interest);
}
onValider()
{
this.checkField();
if(!this.hasError)
{
if(this.changePassword) this.adminCopy.hashPass = this.newPassword;
const data = {
login: this.adminCopy.login,
hashPass: this.adminCopy.hashPass,
email: this.adminCopy.email,
profileImageUrl: this.adminCopy.profileImageUrl,
};
this.messageService
.put("user/update/"+this.profilService.getId(), data)
.subscribe( ret => this.onValiderCallback(ret), err => this.onValiderCallback(err) );
}
}
onValiderCallback(retour: any)
{
if(retour.status !== "success") {
console.log(retour);
this.dialogRef.close(null);
}
else {
this.profilService.setProfileImageUrl(this.adminCopy.profileImageUrl);
this.dialogRef.close(this.adminCopy);
}
}
checkField()
{
if(this.adminCopy.login.length === 0) {
this.errorMessage = "Veuillez remplir le champ 'pseudo'" ;
this.hasError = true;
}
else if(this.adminCopy.email.length === 0) {
this.errorMessage = "Veuillez remplir le champ 'email'" ;
this.hasError = true;
}
else if(!this.isValidEmail(this.adminCopy.email)) {
this.errorMessage = "Email invalide" ;
this.hasError = true;
}
else if((this.changePassword) && (this.newPassword.length === 0)) {
this.errorMessage = "Veuillez remplir le champ 'mot de passe'" ;
this.hasError = true;
}
else if((this.changePassword) && (this.newPassword !== this.confirmNewPassword)) {
this.errorMessage = "Le mot de passe est différent de sa confirmation" ;
this.hasError = true;
}
else {
this.errorMessage = "" ;
this.hasError = false;
}
}
isValidEmail(email)
{
let re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return re.test(email);
}
}

View file

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

View file

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

View file

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

View file

@ -1,121 +0,0 @@
import {Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild} from '@angular/core';
import {COMMA, ENTER} from "@angular/cdk/keycodes";
import {FormControl} from "@angular/forms";
import {Observable} from "rxjs";
import {MessageService} from "../../../utils/services/message/message.service";
import {map, startWith} from "rxjs/operators";
import {MatChipInputEvent} from "@angular/material/chips";
import {MatAutocompleteSelectedEvent} from "@angular/material/autocomplete";
@Component({
selector: 'app-input-interests-admin',
templateUrl: './input-interests-admin.component.html',
styleUrls: ['./input-interests-admin.component.scss']
})
export class InputInterestsAdminComponent implements OnInit
{
selectable = true;
removable = true;
separatorKeysCodes: number[] = [ENTER, COMMA];
formControl = new FormControl();
filteredInterests: Observable<string[]>;
@Input() myInterests: string[] = [];
allInterests: string[] = [];
@Output() eventEmitter = new EventEmitter<string[]>();
@ViewChild('tagInput') tagInput: ElementRef<HTMLInputElement>;
interestsNotSelected: string[] = [];
constructor( private messageService: MessageService ) {}
ngOnInit(): void
{
this.filteredInterests = this.formControl.valueChanges.pipe(
startWith(null),
map((fruit: string | null) => fruit ? this._filter(fruit) : this.interestsNotSelected.slice()));
this.messageService
.get("misc/getInterests")
.subscribe( retour => {
if(retour.status !== "success") {
console.log(retour);
}
else {
this.allInterests = [];
for(let elt of retour.data)
{
this.allInterests.push(elt.interest);
this.interestsNotSelected.push(elt.interest);
}
}
});
}
add(event: MatChipInputEvent): void
{
const value = (event.value || '').trim();
const index = this.interestsNotSelected.indexOf(value);
if (value && (index !== -1) && (!this.myInterests.includes(value)))
{
this.myInterests.push(value);
event.chipInput!.clear();
this.formControl.setValue(null);
this.eventEmitter.emit(this.myInterests);
this.interestsNotSelected.splice(index, 1);
}
}
remove(interest: string): void
{
// supprimer 'interest' de 'myInterest'
const index = this.myInterests.indexOf(interest);
if (index >= 0) this.myInterests.splice(index, 1);
this.eventEmitter.emit(this.myInterests);
// remmettre 'interest' dans 'interestsNotSelected'
if(!this.interestsNotSelected.includes(interest))
{
const indexOfAutres = this.interestsNotSelected.indexOf("Autres");
if(indexOfAutres !== -1)
{
this.interestsNotSelected.splice(indexOfAutres, 1);
if(interest !== "Autres") this.interestsNotSelected.push(interest);
this.interestsNotSelected.sort();
this.interestsNotSelected.push("Autres");
}
else {
this.interestsNotSelected.push(interest);
if(interest !== "Autres") this.interestsNotSelected.sort();
}
}
}
selected(event: MatAutocompleteSelectedEvent): void
{
const value = event.option.viewValue;
if(!this.myInterests.includes(value))
{
this.myInterests.push(value);
const index = this.interestsNotSelected.indexOf(value);
this.interestsNotSelected.splice(index, 1);
}
this.tagInput.nativeElement.value = '';
this.formControl.setValue(null);
this.eventEmitter.emit(this.myInterests);
}
private _filter(value: string): string[]
{
const filterValue = value.toLowerCase();
return this.interestsNotSelected.filter(fruit => fruit.toLowerCase().includes(filterValue));
}
}

View file

@ -1,193 +0,0 @@
<div [class]="themeService.getClassTheme()">
<div class="myContainer">
<!-- Navbar -->
<app-navbar-admin></app-navbar-admin><br><br>
<!-- filtre + btnAddUser -->
<div class="row" style="margin: 20px 3% 20px 3%">
<!-- filtre -->
<div class="col-9" style="padding: 0px 0px 0px 0px;">
<div class="filtersContainer mat-elevation-z8">
<!-- titre -->
<div style="font-weight: bold; margin-bottom: 10px;">
Filtre
</div>
<mat-divider></mat-divider>
<!-- filtre textuelle-->
<div style="margin: 10px 0px 20px 2%;">
<input class="textFilter" (keyup)="applyFilter($event)" placeholder="Rechercher par mots-clés...">
</div>
<!-- role + actif + période -->
<div class="row myRow">
<!-- choix role -->
<div class="col-2">
<mat-radio-group [(ngModel)]="roleName">
<mat-radio-button value="user" (click)="this.roleName = 'user'; onFilter()">
Utilisateur
</mat-radio-button><br>
<mat-radio-button value="advertiser" (click)="this.roleName = 'advertiser'; onFilter()">
Annonceur
</mat-radio-button><br>
<mat-radio-button value="admin" (click)="this.roleName = 'admin'; onFilter()">
Admin
</mat-radio-button>
</mat-radio-group>
</div>
<!-- actif -->
<div class="col-2">
<mat-checkbox [(ngModel)]="active" (change)="onFilter()">actif</mat-checkbox><br>
<mat-checkbox [(ngModel)]="noActive" (change)="onFilter()">non actif</mat-checkbox>
</div>
<!-- période -->
<div class="col-8" style="text-align: right;">
Période de dernière connexion: &nbsp;
<mat-form-field appearance="fill" style="width: 140px;">
<mat-label>Date de début</mat-label>
<input matInput type="date"
[ngModel] ="startDate | date:'yyyy-MM-dd'"
(ngModelChange)="onNewStartDate($event); onFilter();">
</mat-form-field>
&nbsp; - &nbsp;
<mat-form-field appearance="fill" style="width: 140px;">
<mat-label>Date de fin</mat-label>
<input matInput type="date"
[ngModel] ="endDate | date:'yyyy-MM-dd'"
(ngModelChange)="onNewEndDate($event); onFilter();">
</mat-form-field>
</div>
</div>
</div>
</div>
<!-- btnAddUser -->
<div class="col-3" style="text-align: right; position: relative;">
<button mat-button class="btnAjouter" (click)="onCreateUser()" style="position: absolute; bottom: 0; right: 0;">
<mat-icon>add_circle</mat-icon> Ajouter un utilisateur
</button>
</div>
</div>
<!-- Table -->
<table mat-table [dataSource]="dataSource" matSort class="mat-elevation-z8">
<!-- IsActive Column -->
<ng-container matColumnDef="isActive">
<th mat-header-cell *matHeaderCellDef mat-sort-header>
<mat-icon>power_settings_new</mat-icon>
</th>
<td mat-cell *matCellDef="let user">
<mat-slide-toggle *ngIf="user.role.name !== 'superAdmin'" [(ngModel)]="user.isActive" (click)="onSliderIsActive(user)"></mat-slide-toggle>
<mat-slide-toggle *ngIf="user.role.name === 'superAdmin'" [(ngModel)]="user.isActive" disabled></mat-slide-toggle>
</td>
</ng-container>
<!-- Login Column -->
<ng-container matColumnDef="login">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Pseudo </th>
<td mat-cell *matCellDef="let user">
{{user.login}}
</td>
</ng-container>
<!-- Mail Column -->
<ng-container matColumnDef="email">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Email </th>
<td mat-cell *matCellDef="let user">
{{user.email}}
</td>
</ng-container>
<!-- DateOfBirth Column -->
<ng-container matColumnDef="dateOfBirth">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Date de naissance </th>
<td mat-cell *matCellDef="let user">
<span *ngIf="((user.dateOfBirth === null) || (user.dateOfBirth === undefined)); else elseDateOfBirth"></span>
<ng-template #elseDateOfBirth> {{ user.dateOfBirth | date:'dd/LL/YYYY' }} </ng-template>
</td>
</ng-container>
<!-- Age Column -->
<ng-container matColumnDef="age">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Âge </th>
<td mat-cell *matCellDef="let user">
<span *ngIf="(user.age < 0) ; else elseAge"></span>
<ng-template #elseAge> {{user.age}} </ng-template>
</td>
</ng-container>
<!-- Sexe Column -->
<ng-container matColumnDef="sexe">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Sexe </th>
<td mat-cell *matCellDef="let user">
<span *ngIf="(user.gender === 'man') ; else elseSexe"> H </span>
<ng-template #elseSexe> F </ng-template>
</td>
</ng-container>
<!-- Interests Column -->
<ng-container matColumnDef="interests">
<th mat-header-cell *matHeaderCellDef> Centres d'intérêt </th>
<td mat-cell *matCellDef="let user">
<span *ngFor="let interest of user.interests; let isLast = last;">
<span *ngIf="!isLast ; else elseInterests"> {{interest}}, </span>
<ng-template #elseInterests> {{interest}} </ng-template>
</span>
</td>
</ng-container>
<!-- CreatedAt Column -->
<ng-container matColumnDef="createdAt">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Date de création </th>
<td mat-cell *matCellDef="let user">
{{ user.createdAt | date:'dd/LL/YYYY à HH:mm:ss' }}
</td>
</ng-container>
<!-- LastConnexion Column -->
<ng-container matColumnDef="lastConnexion">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Dernière connexion </th>
<td mat-cell *matCellDef="let user">
{{ user.lastConnexion | date:'dd/LL/YYYY à HH:mm:ss' }}
</td>
</ng-container>
<!-- IsAccepted Column -->
<ng-container matColumnDef="isAccepted">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Accepté </th>
<td mat-cell *matCellDef="let user">
<mat-slide-toggle [(ngModel)]="user.role.isAccepted" (click)="onSlideIsAccepted(user)"></mat-slide-toggle>
</td>
</ng-container>
<!-- Directives -->
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
<tr class="mat-row" *matNoDataRow>
<td class="mat-cell" colspan="4"> Aucune vidéo ne correspond au filtre: "{{input.value}}" </td>
</tr>
</table>
<div style="width: 94%; margin: auto auto">
<mat-paginator [pageSizeOptions]="[10, 20, 50, 100]" showFirstLastButtons aria-label="Select page of periodic elements"></mat-paginator>
</div>
<br><br>
</div>
</div>

View file

@ -1,99 +0,0 @@
.myContainer {
min-height: 100vh;
font-size: small;
}
// ----------------------------------------------------------
.filtersContainer {
width: 90%;
background-color: white;
padding: 10px 10px 10px 10px;
}
.myRow {
margin-left: 1%;
}
.textFilter {
width: 50%;
font-size: medium;
border-radius: 5px;
}
.btnAjouter {
background-color: white;
border: solid 1px black;
}
// ----------------------------------------------------------
table {
margin: 0 auto;
width: 94%;
font-size: small;
}
.darkTheme table { border: solid 2px white; }
th.mat-sort-header-sorted {
color: black;
}
td {
font-size: small;
}
// -------------------------------------------------------------------------
::ng-deep .mat-radio-inner-circle {
color: black !important;
background-color: black !important;
}
::ng-deep .mat-radio-outer-circle{
color: black !important;
border: solid 1px gray !important;
}
// -------------------------------------------------------------------------
// 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;
}
// --------------------------------------------------------------------
// 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;
}

View file

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

View file

@ -1,233 +0,0 @@
import {AfterViewInit, Component, ViewChild} from '@angular/core';
import {MatSort} from "@angular/material/sort";
import {MatPaginator} from "@angular/material/paginator";
import {ThemeService} from "../../../utils/services/theme/theme.service";
import {MatDialog} from "@angular/material/dialog";
import {MatSnackBar} from "@angular/material/snack-bar";
import {MatTableDataSource} from "@angular/material/table";
import {PopupDeleteUserComponent} from "../popup-delete-user/popup-delete-user.component";
import {PopupCreateUserComponent} from "../popup-create-user/popup-create-user.component";
import {MessageService} from "../../../utils/services/message/message.service";
@Component({
selector: 'app-page-user-list',
templateUrl: './page-user-list.component.html',
styleUrls: ['./page-user-list.component.scss']
})
export class PageUserListComponent implements AfterViewInit
{
displayedColumns: string[];
displayedColumnsUser: string[] = [ 'isActive', 'login', 'email', 'dateOfBirth', 'age', 'sexe', 'interests', 'createdAt', 'lastConnexion' ];
displayedColumnsAdvertiser: string[] = [ 'isActive', 'login', 'email', 'createdAt', 'lastConnexion', 'isAccepted' ];
displayedColumnsAdmin: string[] = [ 'isActive', 'login', 'email', 'createdAt', 'lastConnexion' ];
tabUser: any[] = [];
tabAdvertiser: any[] = [];
tabAdmin: any[] = [];
roleName: string = "user" ;
dataSource ;
@ViewChild(MatSort) sort: MatSort;
@ViewChild(MatPaginator) paginator: MatPaginator;
active: boolean = true;
noActive: boolean = false;
startDate: Date = null;
endDate: Date = null;
constructor( public themeService: ThemeService,
public dialog: MatDialog,
private snackBar: MatSnackBar,
private messageService: MessageService ) { }
ngAfterViewInit(): void
{
this.messageService
.get("user/findAll")
.subscribe(ret => this.ngAfterViewInitCallback(ret), err => this.ngAfterViewInitCallback(err));
}
ngAfterViewInitCallback(retour: any): void
{
if(retour.status !== "success") {
console.log(retour);
}
else {
for(let person of retour.data)
{
if(person.role.name === "user") {
person["age"] = this.getAge(person.dateOfBirth);
this.tabUser.push(person);
}
else if(person.role.name === "advertiser") this.tabAdvertiser.push(person);
else this.tabAdmin.push(person);
}
this.onFilter();
}
}
applyFilter(event: Event): void
{
const filterValue = (event.target as HTMLInputElement).value;
this.dataSource.filter = filterValue.trim().toLowerCase();
}
onDelete(user: any): void
{
const config = {
data: { user: user }
};
this.dialog
.open(PopupDeleteUserComponent, config)
.afterClosed()
.subscribe( retour => {
const config = { duration: 1000, panelClass: "custom-class" };
let message = "" ;
if((retour === undefined) || (retour === null)) {
message = "Opération annulée" ;
}
else {
const index = this.dataSource.data.findIndex( elt => (elt.id === user.id));
this.dataSource.data.splice(index, 1);
this.dataSource.data = this.dataSource.data;
this.dataSource = this.dataSource;
message = user.login + " a bien été supprimée ✔" ;
}
this.snackBar.open(message, "", config);
});
}
onCreateUser(): void
{
const config = { width: '50%' };
this.dialog
.open(PopupCreateUserComponent, config)
.afterClosed()
.subscribe( retour => {
const config = { duration: 1000, panelClass: "custom-class" };
if((retour === null) || (retour === undefined)) {
this.snackBar.open( "Opération annulée", "", config);
}
else {
this.snackBar.open( "L'utilisateur a bien été créé", "", config);
if(retour.role.name === "user") this.tabUser.push(retour);
else if(retour.role.name === "advertiser") this.tabAdvertiser.push(retour);
else if(retour.role.name === "admin") this.tabAdmin.push(retour);
this.onFilter();
}
});
}
onSliderIsActive(user: any): void
{
// il faut envoyer la négation de user.isActive
this.messageService
.put("user/update/"+user.id, { isActive: !user.isActive })
.subscribe(
ret => {},
err => {
console.log("onSliderIsActive");
console.log(err);
}
);
}
onSlideIsAccepted(user: any): void
{
// il faut envoyer la négation de user.role.isAccepted
const role0 = {
name: user.role.name,
permission: user.role.permission,
isAccepted: !user.role.isAccepted,
};
this.messageService
.put("user/update/"+user.id, {role: role0})
.subscribe(
ret => {},
err => {
console.log("onSlideIsAccepted");
console.log(err);
}
);
}
getAge(date: Date): number
{
if((date === null) || (date === undefined)) return -1;
else {
const diff = Date.now() - (new Date(date)).getTime();
const age = new Date(diff);
return Math.abs(age.getUTCFullYear() - 1970);
}
}
onFilter(): void
{
let tab1 = [];
if(this.roleName === "user") {
this.displayedColumns = this.displayedColumnsUser;
tab1 = this.tabUser;
}
else if(this.roleName === "advertiser") {
this.displayedColumns = this.displayedColumnsAdvertiser;
tab1 = this.tabAdvertiser;
}
else if(this.roleName === "admin") {
this.displayedColumns = this.displayedColumnsAdmin;
tab1 = this.tabAdmin;
}
let tab2 = [];
for(let user of tab1)
{
let valide: boolean = true;
if(user.isActive && this.active) valide = true;
else if((!user.isActive) && this.noActive) valide = true;
else valide = false;
if(valide)
{
if ((user.lastConnexion === null) && (this.startDate !== null)) valide = false;
else if ((user.lastConnexion === null) && (this.endDate !== null)) valide = false;
else if (this.startDate !== null)
{
if(this.startDate.getTime() > user.lastConnexion.getTime()) valide = false;
else if (this.endDate !== null)
{
if(this.endDate.getTime() < user.lastConnexion.getTime()) valide = false;
}
}
}
if(valide) tab2.push(user);
}
this.dataSource = new MatTableDataSource(tab2);
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);
}
}

View file

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

View file

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

View file

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

View file

@ -1,127 +0,0 @@
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-create-user',
templateUrl: './popup-create-user.component.html',
styleUrls: ['./popup-create-user.component.scss']
})
export class PopupCreateUserComponent implements OnInit
{
user: any;
hasError: boolean = false;
errorMessage: string = "";
password: string = "";
confirmPassword: string = "";
constructor( public dialogRef: MatDialogRef<PopupCreateUserComponent>,
@Inject(MAT_DIALOG_DATA) public data,
private messageService: MessageService ) { }
// Initialise l'utilisateur qui va être créé
ngOnInit(): void
{
this.user = {
_id: "",
login: "",
hashPass: "",
email: "",
role: {
name: "",
permission: 0,
isAccepted: false,
},
profileImageUrl: "",
dateOfBirth: null,
gender: "man",
interests: [],
company: "",
isActive: false,
createdAt: new Date(),
updatedAt: new Date(),
lastConnexion: new Date()
};
}
// Crée le nouvel utilisateur
onEnregistrer(): void
{
this.checkField();
if(!this.hasError)
{
this.user.hashPass = this.password;
this.user.role = this.user.role.name;
this.messageService
.post("user/create", this.user)
.subscribe(ret => this.onEnregistrerCallback(ret), err => this.onEnregistrerCallback(err));
}
}
// Callback de 'onEnregistrer'
onEnregistrerCallback(retour: any): void
{
if(retour.status !== "success") {
console.log(retour);
}
else {
this.dialogRef.close(retour.data);
}
}
// Check les champs saisies par l'utilisateur
checkField(): void
{
if(this.user.login.length === 0) {
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;
}
else if(!this.isValidEmail(this.user.email)) {
this.errorMessage = "Email invalide.";
this.hasError = true;
}
else if(this.password.length === 0) {
this.errorMessage = "Veuillez remplir le champ 'mot de passe'.";
this.hasError = true;
}
else if(this.password !== this.confirmPassword) {
this.errorMessage = "Le mot de passe est différent de sa confirmation.";
this.hasError = true;
}
else 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;
}
}
// Indique si email a bien le format d'un email
isValidEmail(email): boolean
{
let re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return re.test(email);
}
// Récupère la liste des centres d'intérets (car celle-ci est remplie à l'aide d'un component intermédiaire)
onEventInputInterests(myInterets: string[]): void
{
this.user.interests = myInterets;
}
}

View file

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

View file

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

View file

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

View file

@ -1,37 +0,0 @@
<nav class="navbar navbar-expand-lg">
<!-- PolyNotFound -->
<a class="navbar-brand" routerLink="/admin/userList"> 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>
<!-- [userList] [adList] -->
<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">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 *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]=profilService.getProfileImageUrl()
onerror="this.onerror=null; this.src='assets/profil.png'"
[routerLink]="routes[3]"
alt="">
<!-- Deconnexion -->
<button mat-button class="btnDeconnexion" (click)="onDeconnexion()" routerLink="/">
Déconnexion
</button>
</nav>

View file

@ -1,80 +0,0 @@
.navbar {
background-color: black;
height: 60px;
font-size: medium;
color: white;
}
.navbar-expand-lg {
border-bottom: solid;
border-color: white;
border-bottom-width: 2px;
}
// PolyNotFound
.navbar-brand {
font-family: cursive;
font-weight: bold;
font-size: x-large;
margin-left: 15px;
color: white;
}
.monLi {
margin: 0px 10px 0px 10px;
}
.nav-link {
color: white;
}
.nav-link:hover {
color: grey;
}
.myActiveLink {
text-decoration: underline;
}
.btnDeconnexion {
font-size: medium;
margin: 0px 10px 0px 10px
}
.btnDeconnexion:hover {
color: grey;
}
img {
border: solid 2px white;
border-radius: 50px;
margin: 0px 10px 0px 15px;
width: 40px;
height: 40px;
}
img:hover {
cursor: pointer;
}
// --------------------------------------------------------------------
::ng-deep .mat-slide-toggle-thumb {
background-color: #c8c8c8;
}
::ng-deep .mat-slide-toggle-bar {
background-color: #ffffff;
}
::ng-deep .mat-slide-toggle.mat-checked:not(.mat-disabled) .mat-slide-toggle-thumb {
background-color: #ffffff;
}
::ng-deep .mat-slide-toggle.mat-checked:not(.mat-disabled) .mat-slide-toggle-bar {
background-color: #646464;
}

View file

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

View file

@ -1,40 +0,0 @@
import {Component} from '@angular/core';
import {Router} from "@angular/router";
import {ProfilService} from "../../../utils/services/profil/profil.service";
import {MessageService} from "../../../utils/services/message/message.service";
@Component({
selector: 'app-navbar-admin',
templateUrl: './navbar-admin.component.html',
styleUrls: ['./navbar-admin.component.scss']
})
export class NavbarAdminComponent
{
routes: string[] = [
"/admin", // 0
"/admin/userList", // 1
"/admin/adList", // 2
"/admin/myProfil", // 3
];
url = this.router.url;
constructor( private router: Router,
public profilService: ProfilService,
private messageService: MessageService ) { }
onDeconnexion(): void
{
this.messageService
.delete('user/logout')
.subscribe(retour => this.onDeconnexionCallback(retour), err => this.onDeconnexionCallback(err));
}
onDeconnexionCallback(retour: any): void
{
if(retour.status !== "success") console.log(retour);
}
}

View file

@ -5,7 +5,7 @@ import {Observable} from "rxjs";
import {map, startWith} from "rxjs/operators";
import {MatChipInputEvent} from "@angular/material/chips";
import {MatAutocompleteSelectedEvent} from "@angular/material/autocomplete";
import {MessageService} from "../../../utils/services/message/message.service";
import {MessageService} from "../../../utils/message/message.service";

View file

@ -25,7 +25,7 @@
<!-- filtre textuelle-->
<div style="margin: 10px 0px 20px 2%;">
<input class="textFilter" (keyup)="applyFilter($event)" placeholder="filtre...">
<input class="textFilter" [(ngModel)]="filteredText" (ngModelChange)="onFilter()" placeholder="Rechercher par mots-clés...">
</div>
<!-- role + actif + période -->
@ -60,23 +60,24 @@
<!-- période -->
<div class="col-6" style="text-align: right;">
Période de création: &nbsp;
<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>
&nbsp; - &nbsp;
<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();">
<div class="col-6" style="text-align: right; font-size: small;">
<mat-form-field appearance="fill">
<mat-label>Période de date de création</mat-label>
<mat-date-range-input
[formGroup]="campaignOne"
[rangePicker]="campaignOnePicker">
<input matStartDate placeholder="Start date" formControlName="start" style="font-size: small;">
<input matEndDate placeholder="End date" formControlName="end" style="font-size: small;">
</mat-date-range-input>
<mat-datepicker-toggle matSuffix [for]="campaignOnePicker"></mat-datepicker-toggle>
<mat-date-range-picker #campaignOnePicker></mat-date-range-picker>
</mat-form-field>
<button mat-icon-button (click)="onFilter()">
<mat-icon>keyboard_tab</mat-icon>
</button>
<button mat-icon-button (click)="onEffacerDate()">
<mat-icon>close</mat-icon>
</button>
</div>
</div>
@ -171,9 +172,6 @@
<!-- Directives -->
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
<tr class="mat-row" *matNoDataRow>
<td class="mat-cell" colspan="4"> Aucune vidéo ne correspond au filtre: "{{input.value}}" </td>
</tr>
</table>
<div style="width: 94%; margin: auto auto">

View file

@ -50,7 +50,6 @@ td {
}
input {
width: 30%;
font-size: large;
border-radius: 5px;
}

View file

@ -1,19 +1,17 @@
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 {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 {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";
import {MessageService} from "../../../utils/services/message/message.service";
import {FormControl, FormGroup} from "@angular/forms";
import {HttpParams} from "@angular/common/http";
import {ThemeService} from "../../../utils/theme/theme.service";
import {MessageService} from "../../../utils/message/message.service";
import {DatePipe} from "@angular/common";
@ -25,15 +23,18 @@ import {HttpParams} from "@angular/common/http";
export class PageAdListAdvertiserComponent implements AfterViewInit
{
displayedColumns: string[] = [ 'isVisible', 'title', 'interests', 'createdAt', 'updatedAt', 'countViews', 'actions' ];
tabAdvertWithCountViews: AdvertWithCountViews[] = [];
tabAdvertWithCountViews: any[] = [];
dataSource;
@ViewChild(MatSort) sort: MatSort;
@ViewChild(MatPaginator) paginator: MatPaginator;
visible: boolean = true;
noVisible: boolean = true;
startDate: Date = null;
endDate: Date = null;
filteredText: string = "" ;
campaignOne = new FormGroup({
start: new FormControl(null),
end: new FormControl(null),
});
formControlInterests = new FormControl();
allVideoCategorie = [];
@ -41,8 +42,6 @@ export class PageAdListAdvertiserComponent implements AfterViewInit
constructor( public themeService: ThemeService,
private fictitiousAdvertsService: FictitiousAdvertsService,
private fictitiousUtilsService: FictitiousUtilsService,
public dialog: MatDialog,
private snackBar: MatSnackBar,
private messageService: MessageService ) { }
@ -87,21 +86,14 @@ export class PageAdListAdvertiserComponent implements AfterViewInit
if(retour.data.length !== 0)
{
for(let advert of retour.data) this.tabAdvertWithCountViews.push(this.advertToAdvertWithCountViews(advert));
this.dataSource = new MatTableDataSource<AdvertWithCountViews>();
this.dataSource = new MatTableDataSource<any>();
this.onFilter();
}
}
}
applyFilter(event: Event): void
{
const filterValue = (event.target as HTMLInputElement).value;
this.dataSource.filter = filterValue.trim().toLowerCase();
}
onVisualizeImages(advert: AdvertWithCountViews)
onVisualizeImages(advert: any)
{
if(advert.images.length !== 0)
{
@ -156,7 +148,7 @@ export class PageAdListAdvertiserComponent implements AfterViewInit
}
onUpdate(advertToUpdate: AdvertWithCountViews): void
onUpdate(advertToUpdate: any): void
{
const config = {
width: '75%',
@ -190,7 +182,7 @@ export class PageAdListAdvertiserComponent implements AfterViewInit
}
onDelete(advert: AdvertWithCountViews): void
onDelete(advert: any): void
{
const config = {
data: { advert: advert }
@ -219,30 +211,43 @@ export class PageAdListAdvertiserComponent implements AfterViewInit
onFilter(): void
{
const startDate = this.campaignOne.get("start").value;
const endDate = this.campaignOne.get("end").value;
if(this.dataSource === null || this.dataSource === undefined) this.dataSource = new MatTableDataSource();
this.dataSource.data = [];
for(let advert of this.tabAdvertWithCountViews)
{
let valide: boolean = true;
// filtre textuelle
let valide: boolean = this.isTextFiltrationValid(advert);
// filtre visible
if(valide)
{
if(advert.isVisible && this.visible) valide = true;
else if((!advert.isVisible) && this.noVisible) valide = true;
else valide = false;
}
// filtre date
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 ((advert.createdAt === null) && (startDate !== null)) valide = false;
else if ((advert.createdAt === null) && (endDate !== null)) valide = false;
else if (startDate !== null)
{
if(this.startDate.getTime() > advert.createdAt.getTime()) valide = false;
else if (this.endDate !== null)
let timeCreatedAt = 0;
if(advert.createdAt !== null) timeCreatedAt = (new Date(advert.createdAt)).getTime();
if(startDate.getTime() > timeCreatedAt) valide = false;
else if (endDate !== null)
{
if(this.endDate.getTime() < advert.createdAt.getTime()) valide = false;
if(endDate.getTime() < timeCreatedAt) valide = false;
}
}
}
// filtre interests
if(valide) {
if(this.formControlInterests.value !== null) {
for (let interest of this.formControlInterests.value) {
@ -263,12 +268,16 @@ export class PageAdListAdvertiserComponent implements AfterViewInit
}
onNewStartDate(event): void {
this.startDate = new Date(event);
}
onNewEndDate(event): void {
this.endDate = new Date(event);
isTextFiltrationValid(advert): boolean
{
let datePipe = new DatePipe('en-GB');
if(advert.title.includes(this.filteredText)) return true;
const createdAt = datePipe.transform(new Date(advert.createdAt), 'dd/MM/yyyy à HH:mm:ss');
if(createdAt.includes(this.filteredText)) return true;
const updatedAt = datePipe.transform(new Date(advert.updatedAt), 'dd/MM/yyyy à HH:mm:ss');
if(updatedAt.includes(this.filteredText)) return true;
if(advert.countViews.toString().includes(this.filteredText)) return true;
return false;
}
@ -287,7 +296,7 @@ export class PageAdListAdvertiserComponent implements AfterViewInit
}
advertToAdvertWithCountViews(advert): AdvertWithCountViews
advertToAdvertWithCountViews(advert)
{
return {
id: advert.id,
@ -306,4 +315,10 @@ export class PageAdListAdvertiserComponent implements AfterViewInit
}
}
onEffacerDate(): void {
this.campaignOne.setValue({start: null, end: null });
this.onFilter();
}
}

View file

@ -1,13 +1,12 @@
import {Component, Inject, OnInit} from '@angular/core';
import {Advert} from "../../../utils/interfaces/advert";
import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";
import {MessageService} from "../../../utils/services/message/message.service";
import {ThemeService} from "../../../utils/services/theme/theme.service";
import {MessageService} from "../../../utils/message/message.service";
import {ThemeService} from "../../../utils/theme/theme.service";
const ADVERT_VIDE: Advert = {
const ADVERT_VIDE = {
_id: "",
userId: "",
title: "",

View file

@ -1,6 +1,6 @@
import {Component, Inject, OnInit} from '@angular/core';
import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";
import {MessageService} from "../../../utils/services/message/message.service";
import {MessageService} from "../../../utils/message/message.service";

View file

@ -1,7 +1,6 @@
import {Component, Inject, OnInit} from '@angular/core';
import {ThemeService} from "../../../utils/services/theme/theme.service";
import {MAT_DIALOG_DATA, MatDialog, MatDialogRef} from "@angular/material/dialog";
import {Advert} from "../../../utils/interfaces/advert";
import {ThemeService} from "../../../utils/theme/theme.service";
@ -12,7 +11,7 @@ import {Advert} from "../../../utils/interfaces/advert";
})
export class PopupVisualizeAdAdvertiserComponent implements OnInit
{
advert: Advert;
advert: any;
constructor( public dialogRef: MatDialogRef<PopupVisualizeAdAdvertiserComponent>,
@Inject(MAT_DIALOG_DATA) public data,

View file

@ -1,11 +1,10 @@
import { Component, OnInit } from '@angular/core';
import {User} from "../../../utils/interfaces/user";
import {ThemeService} from "../../../utils/services/theme/theme.service";
import {MatDialog} from "@angular/material/dialog";
import {MatSnackBar} from "@angular/material/snack-bar";
import {PopupUpdateAdvertiserComponent} from "../popup-update-advertiser/popup-update-advertiser.component";
import {MessageService} from "../../../utils/services/message/message.service";
import {ProfilService} from "../../../utils/services/profil/profil.service";
import {ThemeService} from "../../../utils/theme/theme.service";
import {MessageService} from "../../../utils/message/message.service";
import {ProfilService} from "../../../utils/profil/profil.service";
@ -16,7 +15,7 @@ import {ProfilService} from "../../../utils/services/profil/profil.service";
})
export class PageProfilAdvertiserComponent implements OnInit
{
advertiser: User = {
advertiser = {
_id: "",
login: "",
hashPass: "",

View file

@ -1,8 +1,7 @@
import {Component, Inject, OnInit} from '@angular/core';
import {User} from "../../../utils/interfaces/user";
import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";
import {MessageService} from "../../../utils/services/message/message.service";
import {ProfilService} from "../../../utils/services/profil/profil.service";
import {MessageService} from "../../../utils/message/message.service";
import {ProfilService} from "../../../utils/profil/profil.service";
@ -13,7 +12,7 @@ import {ProfilService} from "../../../utils/services/profil/profil.service";
})
export class PopupUpdateAdvertiserComponent implements OnInit
{
advertiserCopy: User;
advertiserCopy;
newPassword: string = "";
confirmNewPassword: string = "" ;
changePassword: boolean = false ;

View file

@ -48,23 +48,23 @@
<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>
&nbsp; - &nbsp;
<!-- 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 appearance="fill">
<mat-label>Période de date de création</mat-label>
<mat-date-range-input
[formGroup]="campaignOne"
[rangePicker]="campaignOnePicker">
<input matStartDate placeholder="Start date" formControlName="start" style="font-size: small;">
<input matEndDate placeholder="End date" formControlName="end" style="font-size: small;">
</mat-date-range-input>
<mat-datepicker-toggle matSuffix [for]="campaignOnePicker"></mat-datepicker-toggle>
<mat-date-range-picker #campaignOnePicker></mat-date-range-picker>
</mat-form-field>
&nbsp; - &nbsp;
<!-- step -->
<mat-form-field appearance="fill" style="width: 140px;">
<mat-label>pas d'affichage</mat-label>
<input matInput type="number" [(ngModel)] =step>
<input matInput type="number" [(ngModel)]=step min="1">
</mat-form-field>
&nbsp; - &nbsp;

View file

@ -1,13 +1,11 @@
import { Component, OnInit } from '@angular/core';
import {FormControl} from "@angular/forms";
import {FormControl, FormGroup} 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";
import {MessageService} from "../../utils/services/message/message.service";
import {HttpParams} from "@angular/common/http";
import {ThemeService} from "../../utils/theme/theme.service";
import {MessageService} from "../../utils/message/message.service";
@ -30,13 +28,16 @@ export class PagesPopularityComponent implements OnInit
allInterests: string[] = [];
startDate: Date = null;
endDate: Date = null;
oneDay: number = 24*60*60*1000;
oneWeek: number = 7*24*60*60*1000;
campaignOne = new FormGroup({
start: new FormControl(new Date(((new Date()).getTime() - this.oneWeek))),
end: new FormControl(new Date()),
});
step: number = 1;
stepUnity: string = "jour" ;
oneDay: number = 24*60*60*1000;
oneWeek: number = 7*24*60*60*1000;
lineChartData: ChartDataSets[] = [];
lineChartLabels: Label[] = [];
@ -53,8 +54,6 @@ export class PagesPopularityComponent implements OnInit
constructor( private router: Router,
public themeService: ThemeService,
private fictitiousAdvertsService: FictitiousAdvertsService,
private fictitiousVideosService: FictitiousVideosService,
private messageService: MessageService ) {}
@ -63,6 +62,18 @@ export class PagesPopularityComponent implements OnInit
ngOnInit(): void
{
// Initialisation de campaignOne
let today00h00Date = new Date();
today00h00Date.setHours(0);
today00h00Date.setMinutes(0);
today00h00Date.setSeconds(0);
today00h00Date.setMilliseconds(0);
this.campaignOne = new FormGroup({
start: new FormControl(new Date(today00h00Date.getTime() - this.oneWeek)),
end: new FormControl(today00h00Date),
});
// Sera excuté si on est sur la page 'adsPopularity'
// Remplie l'attribut 'allCoupleNameViews'
if(this.router.url.includes("ads"))
@ -74,6 +85,7 @@ export class PagesPopularityComponent implements OnInit
.subscribe(ret => this.afterReceivingAds(ret), err => this.afterReceivingAds(err));
}
// Sera excuté si on est sur la page 'subjectsPopularity'
// Remplie l'attribut 'allCoupleNameViews'
else if(this.router.url.includes("subjects"))
@ -87,7 +99,6 @@ export class PagesPopularityComponent implements OnInit
}
else {
this.allInterests = retour.data.map(x => x.interest);
this.allInterests.sort();
this.messageService
.get("video/findAll")
.subscribe(ret => this.afterReceivingVideos(ret), err => this.afterReceivingVideos(err));
@ -168,18 +179,20 @@ export class PagesPopularityComponent implements OnInit
this.lineChartData = [];
this.lineChartLabels = [];
if(this.step <= 0) this.step = 0;
if((this.endDate === null) || (this.endDate === undefined)) this.endDate = new Date();
if((this.startDate === null) || (this.startDate === undefined)) this.startDate = new Date(this.endDate.getTime() - this.oneWeek); // date d'il y a une semaine
let startDate = this.campaignOne.get("start").value;
let endDate = this.campaignOne.get("end").value;
if(this.step <= 0) this.step = 1;
if((endDate === null) || (endDate === undefined)) endDate = new Date();
if((startDate === null) || (startDate === undefined)) startDate = new Date(endDate.getTime() - this.oneWeek); // date d'il y a une semaine
const startTime = this.startDate.getTime();
const endTime = this.endDate.getTime();
const startTime = startDate.getTime();
const endTime = endDate.getTime();
// --- remplissage de 'lineChartLabels' ---
let dataWithZeros = [];
let time = startTime;
const intervals = [];
let intervals = [];
while(time <= endTime)
{
dataWithZeros.push(0);
@ -190,7 +203,7 @@ export class PagesPopularityComponent implements OnInit
intervals.push(time);
// --- remplissage de 'lineChartLabels' ---
// --- remplissage de 'lineChartData' ---
for(let coupleNameViews of this.formControl.value)
{
let data = dataWithZeros.slice();
@ -201,11 +214,14 @@ export class PagesPopularityComponent implements OnInit
{
const time0 = (new Date(date0)).getTime();
if(time0 > endTime) break;
if(time0 > (endTime+this.oneDay)) break;
if((startTime <= time0) && (time0 <= endTime))
if((startTime <= time0) && (time0 <= (endTime+this.oneDay)))
{
while((index < intervals.length) && (time0 >= intervals[index])) index += 1;
console.log("index:" + index);
//console.log("index < intervals.length : " + (index < intervals.length));
//console.log("time0 >= intervals[index] : " + (time0 >= intervals[index]));
index = index - 1;
data[index] += 1;
}
@ -214,16 +230,7 @@ export class PagesPopularityComponent implements OnInit
this.lineChartData.push({"data": data.slice(), "label": label});
}
this.isDisplayable = true;
}
onNewStartDate(event): void {
this.startDate = new Date(event);
}
onNewEndDate(event): void {
this.endDate = new Date(event);
console.log(this.lineChartLabels);
}
@ -260,12 +267,13 @@ export class PagesPopularityComponent implements OnInit
let newMonth = oldDate.getMonth() + this.step;
const newYear = oldDate.getFullYear() + (newMonth / 12);
newMonth = newMonth % 12;
const day = this.startDate.getDate();
const startDate = this.campaignOne.get("start").value;
const day = 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
else if((day === 31) && ([3, 5, 8, 10].includes(newMonth))) { // si 31 et mois à 30 jours
newDate = new Date(newYear, newMonth, 30);
}
else {

View file

@ -1,7 +1,7 @@
import { Component } from '@angular/core';
import {Router} from "@angular/router";
import {ProfilService} from "../../../utils/services/profil/profil.service";
import {MessageService} from "../../../utils/services/message/message.service";
import {ProfilService} from "../../../utils/profil/profil.service";
import {MessageService} from "../../../utils/message/message.service";
@ -36,6 +36,7 @@ export class NavbarAdvertiserComponent
onDeconnexionCallback(retour: any): void
{
if(retour.status !== "success") console.log(retour);
this.profilService.setRole("");
}
}

View file

@ -1,51 +1,41 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import {PageLoginComponent} from './beforeConnexion/login/page-login/page-login.component';
import {PageLoginComponent} from "./beforeConnexion/login/page-login/page-login.component";
import {PageRegisterComponent} from "./beforeConnexion/register/page-register/page-register.component";
import {PageSearchComponent} from "./user/search/page-search/page-search.component";
import {PageMyPlaylistsComponent} from "./user/myPlaylists/page-my-playlists/page-my-playlists.component";
import {PageProfilUserComponent} from "./user/myProfil/page-profil-user/page-profil-user.component";
import {PageWatchingVideoComponent} from "./user/watching/page-watching-video/page-watching-video.component";
import {PageHistoryUserComponent} from "./user/history/page-history-user/page-history-user.component";
import {PageAdListAdvertiserComponent} from "./advertiser/adList/page-ad-list-advertiser/page-ad-list-advertiser.component";
import {PageProfilUserComponent} from "./user/myProfil/page-profil-user/page-profil-user.component";
import {PageProfilAdvertiserComponent} from "./advertiser/myProfil/page-profil-advertiser/page-profil-advertiser.component";
import {PageProfilAdminComponent} from "./admin/myProfil/page-profil-admin/page-profil-admin.component";
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";
import {PageProfilAdvertiserComponent} from "./advertiser/myProfil/page-profil-advertiser/page-profil-advertiser.component";
import {UserGuard} from "./utils/guards/user/user.guard";
import {AdvertiserGuard} from "./utils/guards/advertiser/advertiser.guard";
const routes: Routes = [
// Before connexion
{ path: '', component: PageLoginComponent },
{ path: 'login', component: PageLoginComponent },
{ path: 'register', component: PageRegisterComponent },
// User
{ path: 'user', component: PageSearchComponent },
{ path: 'user/search', component: PageSearchComponent },
{ path: 'user/myPlaylists', component: PageMyPlaylistsComponent },
{ path: 'user/history', component: PageHistoryUserComponent },
{ path: 'user/myProfil', component: PageProfilUserComponent },
{ path: 'user/watching', component: PageWatchingVideoComponent },
{ path: 'user', component: PageSearchComponent, canActivate: [UserGuard] },
{ path: 'user/search', component: PageSearchComponent, canActivate: [UserGuard] },
{ path: 'user/myPlaylists', component: PageMyPlaylistsComponent, canActivate: [UserGuard] },
{ path: 'user/history', component: PageHistoryUserComponent, canActivate: [UserGuard] },
{ path: 'user/myProfil', component: PageProfilUserComponent, canActivate: [UserGuard] },
{ path: 'user/watching', component: PageWatchingVideoComponent, canActivate: [UserGuard] },
// Advertiser
{ 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 },
{ path: 'admin/userList', component: PageUserListComponent },
{ path: 'admin/adList', component: PageAdListAdminComponent },
{ path: 'admin/myProfil', component: PageProfilAdminComponent },
{ path: 'advertiser', component: PageAdListAdvertiserComponent, canActivate: [AdvertiserGuard] },
{ path: 'advertiser/adList', component: PageAdListAdvertiserComponent, canActivate: [AdvertiserGuard] },
{ path: 'advertiser/myProfil', component: PageProfilAdvertiserComponent, canActivate: [AdvertiserGuard] },
{ path: 'advertiser/adsPopularity', component: PagesPopularityComponent, canActivate: [AdvertiserGuard] },
{ path: 'advertiser/subjectsPopularity', component: PagesPopularityComponent, canActivate: [AdvertiserGuard] },
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]

View file

@ -1 +1,2 @@
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<router-outlet></router-outlet>

View file

@ -20,16 +20,16 @@ describe('AppComponent', () => {
expect(app).toBeTruthy();
});
it(`should have as title 'frontend'`, () => {
it(`should have as title 'userAndAdvertiser'`, () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.componentInstance;
expect(app.title).toEqual('frontend');
expect(app.title).toEqual('userAndAdvertiser');
});
it('should render title', () => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.nativeElement;
expect(compiled.querySelector('.content span').textContent).toContain('frontend app is running!');
const compiled = fixture.nativeElement as HTMLElement;
expect(compiled.querySelector('.content span')?.textContent).toContain('userAndAdvertiser app is running!');
});
});

View file

@ -6,7 +6,5 @@ import { Component } from '@angular/core';
styleUrls: ['./app.component.scss']
})
export class AppComponent {
title = 'frontend';
themeIsLight = true;
title = 'userAndAdvertiser';
}

View file

@ -3,123 +3,100 @@ import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { PageLoginComponent } from './beforeConnexion/login/page-login/page-login.component';
import { PageRegisterComponent } from './beforeConnexion/register/page-register/page-register.component';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
import {MatSlideToggleModule} from '@angular/material/slide-toggle';
import {BrowserAnimationsModule} from "@angular/platform-browser/animations";
import {MatSlideToggleModule} from "@angular/material/slide-toggle";
import {FormsModule, ReactiveFormsModule} from "@angular/forms";
import { PageSearchComponent } from './user/search/page-search/page-search.component';
import {HttpClientModule} from "@angular/common/http";
import { PopupConfirmationComponent } from './beforeConnexion/register/popup-confirmation/popup-confirmation.component';
import {MatDialogModule} from '@angular/material/dialog';
import {MatButtonModule} from "@angular/material/button";
import { AdvertComponent } from './user/utils/components/advert/advert.component';
import { VideoGridComponent } from './user/search/video-grid/video-grid.component';
import {MatIconModule} from "@angular/material/icon";
import { PopupAddVideoToPlaylistsComponent } from './user/utils/components/popup-add-video-to-playlists/popup-add-video-to-playlists.component';
import {MatDialogModule} from "@angular/material/dialog";
import {MatButtonModule} from "@angular/material/button";
import {MatInputModule} from "@angular/material/input";
import {MatDividerModule} from "@angular/material/divider";
import {MatCheckboxModule} from "@angular/material/checkbox";
import {MatFormFieldModule} from "@angular/material/form-field";
import {MatDividerModule} from "@angular/material/divider";
import {MatSnackBarModule} from "@angular/material/snack-bar";
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';
import {VideoListComponent} from "./user/myPlaylists/video-list/video-list.component";
import { PopupCreateOrUpdatePlaylistComponent } from './user/myPlaylists/popup-create-or-update-playlist/popup-create-or-update-playlist.component';
import { PageHistoryUserComponent } from './user/history/page-history-user/page-history-user.component';
import {MatTableModule} from '@angular/material/table';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import {MatTableModule} from "@angular/material/table";
import {MatSortModule} from "@angular/material/sort";
import { PageAdListAdvertiserComponent } from './advertiser/adList/page-ad-list-advertiser/page-ad-list-advertiser.component';
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 { 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 './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/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/utils/navbar-before-connexion/navbar-before-connexion.component';
import {MatAutocompleteModule} from "@angular/material/autocomplete";
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';
import { PopupUpdateAdminComponent } from './admin/myProfil/popup-update-admin/popup-update-admin.component';
import {MatStepperModule} from "@angular/material/stepper";
import { InputInterestsRegisterComponent } from './beforeConnexion/register/input-interests-register/input-interests-register.component';
import {MatPaginatorModule} from "@angular/material/paginator";
import { PageAdListAdminComponent } from './admin/adList/page-ad-list-admin/page-ad-list-admin.component';
import { PopupDeleteAdAdminComponent } from './admin/adList/popup-delete-ad-admin/popup-delete-ad-admin.component';
import { PopupVisualizeImagesAdminComponent } from './admin/adList/popup-visualize-images-admin/popup-visualize-images-admin.component';
import { PageUserListComponent } from './admin/userList/page-user-list/page-user-list.component';
import { PopupDeleteUserComponent } from './admin/userList/popup-delete-user/popup-delete-user.component';
import { PopupCreateUserComponent } from './admin/userList/popup-create-user/popup-create-user.component';
import { InputInterestsAdminComponent } from './admin/userList/input-interests-admin/input-interests-admin.component';
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';
import { PopupForgottenPasswordComponent } from './beforeConnexion/login/popup-forgotten-password/popup-forgotten-password.component';
import {DragAndDropComponent} from "./advertiser/adList/drag-and-drop/drag-and-drop.component";
import {InputInterestsAdComponent} from "./advertiser/adList/input-interests-ad/input-interests-ad.component";
import {PageAdListAdvertiserComponent} from "./advertiser/adList/page-ad-list-advertiser/page-ad-list-advertiser.component";
import {PopupAddOrUpdateAdComponent} from "./advertiser/adList/popup-add-or-update-ad/popup-add-or-update-ad.component";
import {PopupDeleteAdAdvertiserComponent} from "./advertiser/adList/popup-delete-ad-advertiser/popup-delete-ad-advertiser.component";
import {PopupVisualizeAdAdvertiserComponent} from "./advertiser/adList/popup-visualize-ad-advertiser/popup-visualize-ad-advertiser.component";
import {PopupVisualizeImagesAdvertiserComponent} from "./advertiser/adList/popup-visualize-images-advertiser/popup-visualize-images-advertiser.component";
import {NavbarAdvertiserComponent} from "./advertiser/utils/navbar-advertiser/navbar-advertiser.component";
import {DragAndDropDirective} from "./advertiser/utils/dragAndDrop/drag-and-drop.directive";
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 {PagesPopularityComponent} from "./advertiser/pages-popularity/pages-popularity.component";
import {NavbarUserComponent} from "./user/utils/components/navbar-user/navbar-user.component";
import {PageHistoryUserComponent} from "./user/history/page-history-user/page-history-user.component";
import {PageMyPlaylistsComponent} from "./user/myPlaylists/page-my-playlists/page-my-playlists.component";
import {PlaylistListComponent} from "./user/myPlaylists/playlist-list/playlist-list.component";
import {PopupCreateOrUpdatePlaylistComponent} from "./user/myPlaylists/popup-create-or-update-playlist/popup-create-or-update-playlist.component";
import {PopupDeletePlaylistComponent} from "./user/myPlaylists/popup-delete-playlist/popup-delete-playlist.component";
import {VideoListComponent} from "./user/myPlaylists/video-list/video-list.component";
import {InputInterestsProfilComponent} from "./user/myProfil/input-interests-profil/input-interests-profil.component";
import {PageProfilUserComponent} from "./user/myProfil/page-profil-user/page-profil-user.component";
import {PopupUpdateUserComponent} from "./user/myProfil/popup-update-user/popup-update-user.component";
import {PageSearchComponent} from "./user/search/page-search/page-search.component";
import {VideoGridComponent} from "./user/search/video-grid/video-grid.component";
import {PageWatchingVideoComponent} from "./user/watching/page-watching-video/page-watching-video.component";
import {AdvertComponent} from "./user/utils/components/advert/advert.component";
import {PopupAddVideoToPlaylistsComponent} from "./user/utils/components/popup-add-video-to-playlists/popup-add-video-to-playlists.component";
import {PageLoginComponent} from "./beforeConnexion/login/page-login/page-login.component";
import {PopupForgottenPasswordComponent} from "./beforeConnexion/login/popup-forgotten-password/popup-forgotten-password.component";
import {InputInterestsRegisterComponent} from "./beforeConnexion/register/input-interests-register/input-interests-register.component";
import {PageRegisterComponent} from "./beforeConnexion/register/page-register/page-register.component";
import {PopupConfirmationComponent} from "./beforeConnexion/register/popup-confirmation/popup-confirmation.component";
import {NavbarBeforeConnexionComponent} from "./beforeConnexion/utils/navbar-before-connexion/navbar-before-connexion.component";
import {MatStepperModule} from "@angular/material/stepper";
import {MAT_DATE_LOCALE, MatNativeDateModule} from "@angular/material/core";
@NgModule({
declarations: [
AppComponent,
PageLoginComponent,
PageRegisterComponent,
PageSearchComponent,
PopupConfirmationComponent,
AdvertComponent,
VideoGridComponent,
PopupAddVideoToPlaylistsComponent,
PageMyPlaylistsComponent,
VideoListComponent,
PlaylistListComponent,
VideoListComponent,
PopupCreateOrUpdatePlaylistComponent,
PageHistoryUserComponent,
PageAdListAdvertiserComponent,
PopupDeleteAdAdvertiserComponent,
PopupAddOrUpdateAdComponent,
PopupVisualizeAdAdvertiserComponent,
InputInterestsAdComponent,
PopupVisualizeImagesAdvertiserComponent,
DragAndDropComponent,
DragAndDropDirective,
PageProfilUserComponent,
NavbarUserComponent,
NavbarBeforeConnexionComponent,
PageLoginComponent,
PopupForgottenPasswordComponent,
InputInterestsRegisterComponent,
PageRegisterComponent,
PopupConfirmationComponent,
NavbarAdvertiserComponent,
NavbarAdminComponent,
DragAndDropComponent,
InputInterestsAdComponent,
PageAdListAdvertiserComponent,
PopupAddOrUpdateAdComponent,
PopupDeleteAdAdvertiserComponent,
PopupVisualizeAdAdvertiserComponent,
PopupVisualizeImagesAdvertiserComponent,
PageProfilAdvertiserComponent,
PopupUpdateAdvertiserComponent,
PopupUpdateUserComponent,
NavbarBeforeConnexionComponent,
InputInterestsProfilComponent,
PageProfilAdminComponent,
PopupUpdateAdminComponent,
InputInterestsRegisterComponent,
PageAdListAdminComponent,
PopupDeleteAdAdminComponent,
PopupVisualizeImagesAdminComponent,
PageUserListComponent,
PopupDeleteUserComponent,
PopupCreateUserComponent,
InputInterestsAdminComponent,
PageWatchingVideoComponent,
PagesPopularityComponent,
NavbarUserComponent,
PageHistoryUserComponent,
PageMyPlaylistsComponent,
PlaylistListComponent,
PopupCreateOrUpdatePlaylistComponent,
PopupDeletePlaylistComponent,
PopupForgottenPasswordComponent,
VideoListComponent,
InputInterestsProfilComponent,
PageProfilUserComponent,
PopupUpdateUserComponent,
PageSearchComponent,
VideoGridComponent,
PageWatchingVideoComponent,
AdvertComponent,
PopupAddVideoToPlaylistsComponent
],
imports: [
BrowserModule,
@ -138,20 +115,19 @@ import { PopupForgottenPasswordComponent } from './beforeConnexion/login/popup-f
MatSnackBarModule,
MatGridListModule,
MatTableModule,
NgbModule,
MatSortModule,
MatChipsModule,
ReactiveFormsModule,
MatAutocompleteModule,
MatSelectModule,
IvyCarouselModule,
MatRadioModule,
MatStepperModule,
MatPaginatorModule,
MatDatepickerModule,
ChartsModule
ChartsModule,
MatStepperModule,
MatNativeDateModule
],
providers: [],
providers: [{ provide: MAT_DATE_LOCALE, useValue: 'en-GB' }],
bootstrap: [AppComponent]
})
export class AppModule { }

View file

@ -2,7 +2,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
import { PageLoginComponent } from './page-login.component';
describe('PageConnexionComponent', () => {
describe('PageLoginComponent', () => {
let component: PageLoginComponent;
let fixture: ComponentFixture<PageLoginComponent>;

View file

@ -1,11 +1,11 @@
import {Component, OnInit} from '@angular/core';
import {MessageService} from "../../../utils/services/message/message.service";
import {Router} from "@angular/router";
import {ThemeService} from "../../../utils/services/theme/theme.service";
import {MatDialog} from "@angular/material/dialog";
import {PopupForgottenPasswordComponent} from "../popup-forgotten-password/popup-forgotten-password.component";
import {MatSnackBar} from "@angular/material/snack-bar";
import {ProfilService} from "../../../utils/services/profil/profil.service";
import {ProfilService} from "../../../utils/profil/profil.service";
import {MessageService} from "../../../utils/message/message.service";
import {ThemeService} from "../../../utils/theme/theme.service";
@ -50,7 +50,7 @@ export class PageLoginComponent implements OnInit
}
onSeConnecterCallback(retour): void
onSeConnecterCallback(retour: any): void
{
if(retour.status !== "success") {
console.log(retour);
@ -60,9 +60,15 @@ export class PageLoginComponent implements OnInit
else {
this.profilService.setId(retour.data.id);
this.profilService.setProfileImageUrl(retour.data.profileImageUrl);
if(retour.data.role.name === "user") this.router.navigateByUrl( '/user/search');
else if(retour.data.role.name === "advertiser") this.router.navigateByUrl( '/advertiser/adList');
else if(retour.data.role.name === "admin" || retour.data.role.name === "superAdmin") this.router.navigateByUrl( '/admin/userList');
if(retour.data.role.name === "user") {
this.profilService.setRole("user");
this.router.navigateByUrl( '/user/search');
}
else if(retour.data.role.name === "advertiser") {
this.profilService.setRole("advertiser");
this.router.navigateByUrl( '/advertiser/adList');
}
//else if(retour.data.role.name === "admin" || retour.data.role.name === "superAdmin") this.router.navigateByUrl( '/admin/userList');
}
}

View file

@ -2,10 +2,10 @@ import {Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild} f
import {COMMA, ENTER} from "@angular/cdk/keycodes";
import {FormControl} from "@angular/forms";
import {Observable} from "rxjs";
import {MessageService} from "../../../utils/services/message/message.service";
import {map, startWith} from "rxjs/operators";
import {MatChipInputEvent} from "@angular/material/chips";
import {MatAutocompleteSelectedEvent} from "@angular/material/autocomplete";
import {MessageService} from "../../../utils/message/message.service";

View file

@ -11,7 +11,7 @@
<mat-step label="Type de compte">
<form style="margin-top: 10px">
<!-- Choix du rôle -->
<mat-radio-group [(ngModel)]="user.role.name" (click)="hasError = false; errorMessage = '';">
<mat-radio-group [(ngModel)]="user.role.name" [ngModelOptions]="{standalone: true}" (click)="hasError = false; errorMessage = '';">
<mat-radio-button value="user">Utilisateur standard</mat-radio-button>&nbsp; &nbsp;
<mat-radio-button value="advertiser">Annonceur</mat-radio-button>
</mat-radio-group>
@ -64,21 +64,21 @@
<!-- Login -->
<mat-form-field appearance="fill">
<mat-label>Pseudo</mat-label>
<input matInput type="text" [(ngModel)]="user.login" required>
<input matInput type="text" [(ngModel)]="user.login" [ngModelOptions]="{standalone: true}" required>
</mat-form-field>
<br>
<!-- Mot de passe -->
<mat-form-field appearance="fill">
<mat-label>Mot de passe</mat-label>
<input matInput type="password" [(ngModel)]="password" required>
<input matInput type="password" [(ngModel)]="password" [ngModelOptions]="{standalone: true}" required>
</mat-form-field>
<br>
<!-- Confirmation mot de passe -->
<mat-form-field appearance="fill">
<mat-label>Confirmation mot de passe</mat-label>
<input matInput type="password" [(ngModel)]="confirmPassword" required>
<input matInput type="password" [(ngModel)]="confirmPassword" [ngModelOptions]="{standalone: true}" required>
</mat-form-field>
</div>
@ -89,12 +89,12 @@
<!-- Email -->
<mat-form-field appearance="fill">
<mat-label>Email</mat-label>
<input matInput type="email" [(ngModel)]="user.email" required>
<input matInput type="email" [(ngModel)]="user.email" [ngModelOptions]="{standalone: true}" required>
</mat-form-field>
<br>
<!-- gender -->
<mat-radio-group [(ngModel)]="user.gender">
<mat-radio-group [(ngModel)]="user.gender" [ngModelOptions]="{standalone: true}">
<mat-radio-button value="man"> Homme </mat-radio-button>&nbsp; &nbsp;
<mat-radio-button value="woman"> Femme </mat-radio-button>
</mat-radio-group>
@ -105,7 +105,8 @@
<mat-label>Date de naissance</mat-label>
<input matInput type="date"
[ngModel] ="user.dateOfBirth | date:'yyyy-MM-dd'"
(ngModelChange)="user.dateOfBirth = $event">
(ngModelChange)="user.dateOfBirth = $event"
[ngModelOptions]="{standalone: true}">
</mat-form-field>
<!-- interests -->
@ -127,35 +128,35 @@
<!-- Entreprise -->
<mat-form-field appearance="fill">
<mat-label>Entreprise</mat-label>
<input matInput type="text" [(ngModel)]="user.company" required>
<input matInput type="text" [(ngModel)]="user.company" [ngModelOptions]="{standalone: true}" required>
</mat-form-field>
<br>
<!-- Login -->
<mat-form-field appearance="fill">
<mat-label>Pseudo</mat-label>
<input matInput type="text" [(ngModel)]="user.login" required>
<input matInput type="text" [(ngModel)]="user.login" [ngModelOptions]="{standalone: true}" required>
</mat-form-field>
<br>
<!-- Email -->
<mat-form-field appearance="fill">
<mat-label>Email</mat-label>
<input matInput type="email" [(ngModel)]="user.email" required>
<input matInput type="email" [(ngModel)]="user.email" [ngModelOptions]="{standalone: true}" required>
</mat-form-field>
<br>
<!-- Mot de passe -->
<mat-form-field appearance="fill">
<mat-label>Mot de passe</mat-label>
<input matInput type="password" [(ngModel)]="password" required>
<input matInput type="password" [(ngModel)]="password" [ngModelOptions]="{standalone: true}" required>
</mat-form-field>
<br>
<!-- Confirmation mot de passe -->
<mat-form-field appearance="fill">
<mat-label>Confirmation mot de passe</mat-label>
<input matInput type="password" [(ngModel)]="confirmPassword" required>
<input matInput type="password" [(ngModel)]="confirmPassword" [ngModelOptions]="{standalone: true}" required>
</mat-form-field>
</ng-template>

View file

@ -1,10 +1,9 @@
import { Component } from '@angular/core';
import {MessageService} from "../../../utils/services/message/message.service";
import {PopupConfirmationComponent} from "../popup-confirmation/popup-confirmation.component";
import {MessageService} from "../../../utils/message/message.service";
import {Router} from "@angular/router";
import {MatDialog} from "@angular/material/dialog";
import {PopupConfirmationComponent} from "../popup-confirmation/popup-confirmation.component";
import {ThemeService} from "../../../utils/services/theme/theme.service";
import {User} from "../../../utils/interfaces/user";
import {ThemeService} from "../../../utils/theme/theme.service";
@ -19,7 +18,7 @@ export class PageRegisterComponent
confirmPassword: string = "";
hasError: boolean = false;
errorMessage: string = "";
user: User = {
user = {
_id: "",
login: "",
hashPass: "",

View file

@ -1,8 +1,6 @@
import {Component, Inject} from '@angular/core';
import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";
@Component({
selector: 'app-popup-confirmation',
templateUrl: './popup-confirmation.component.html',

View file

@ -1,6 +1,5 @@
import {Component, Input} from '@angular/core';
@Component({
selector: 'app-navbar-before-connexion',
templateUrl: './navbar-before-connexion.component.html',

View file

@ -1,12 +1,10 @@
import {AfterViewInit, Component, ViewChild} from '@angular/core';
import {ThemeService} from "../../../utils/services/theme/theme.service";
import {MessageService} from "../../../utils/services/message/message.service";
import {MatTableDataSource} from "@angular/material/table";
import {MatSort} from "@angular/material/sort";
import {MatPaginator} from "@angular/material/paginator";
import {FictitiousVideosService} from "../../../utils/services/fictitiousDatas/fictitiousVideos/fictitious-videos.service";
import {VideoAll} from "../../../utils/interfaces/video";
import {Router} from "@angular/router";
import {MessageService} from "../../../utils/message/message.service";
import {ThemeService} from "../../../utils/theme/theme.service";
@ -25,7 +23,6 @@ export class PageHistoryUserComponent implements AfterViewInit
constructor( public themeService: ThemeService,
private messageService: MessageService,
private fictitiousVideosService: FictitiousVideosService,
private router: Router ) { }
@ -93,7 +90,7 @@ export class PageHistoryUserComponent implements AfterViewInit
}
onVideo(video: VideoAll): void
onVideo(video): void
{
this.messageService
.put("video/update/"+video._id, {watchedDate: true})

View file

@ -1,8 +1,7 @@
import { Component, OnInit } from '@angular/core';
import {ThemeService} from "../../../utils/services/theme/theme.service";
import {Advert} from "../../../utils/interfaces/advert";
import {MessageService} from "../../../utils/services/message/message.service";
import {HttpParams} from "@angular/common/http";
import {ThemeService} from "../../../utils/theme/theme.service";
import {MessageService} from "../../../utils/message/message.service";
@ -13,7 +12,7 @@ import {HttpParams} from "@angular/common/http";
})
export class PageMyPlaylistsComponent implements OnInit
{
ad: Advert; // pub
ad; // pub
playlist: any; // la playlist sélectionnée

View file

@ -1,12 +1,10 @@
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
import {ThemeService} from "../../../utils/services/theme/theme.service";
import {PlaylistDB} from "../../../utils/interfaces/playlist";
import {MatDialog} from "@angular/material/dialog";
import {MatSnackBar} from "@angular/material/snack-bar";
import {PopupCreateOrUpdatePlaylistComponent} from "../popup-create-or-update-playlist/popup-create-or-update-playlist.component";
import {FictitiousVideosService} from "../../../utils/services/fictitiousDatas/fictitiousVideos/fictitious-videos.service";
import {PopupDeletePlaylistComponent} from "../popup-delete-playlist/popup-delete-playlist.component";
import {MessageService} from "../../../utils/services/message/message.service";
import {ThemeService} from "../../../utils/theme/theme.service";
import {MessageService} from "../../../utils/message/message.service";
@ -17,17 +15,16 @@ import {MessageService} from "../../../utils/services/message/message.service";
})
export class PlaylistListComponent implements OnInit
{
allPlaylists: PlaylistDB[] = []; // toutes les playlists
@Output() eventEmitter = new EventEmitter<PlaylistDB>(); // pour envoyer au parent la playlist selectionner
allPlaylists: any[] = []; // toutes les playlists
@Output() eventEmitter = new EventEmitter<any>(); // pour envoyer au parent la playlist selectionner
search: string = "" ; // contenu de la barre de recherche
tabPlaylist: PlaylistDB[] = []; // playlist affichées
playlistFocusedOn: PlaylistDB;
tabPlaylist: any[] = []; // playlist affichées
playlistFocusedOn: any;
constructor( public themeService: ThemeService,
public dialog: MatDialog,
public snackBar: MatSnackBar,
private fictitiousVideosService: FictitiousVideosService,
private messageService: MessageService ) { }
@ -94,7 +91,7 @@ export class PlaylistListComponent implements OnInit
// click sur update playlist
onUpdatePlaylist(playlistToUpdate: PlaylistDB): void
onUpdatePlaylist(playlistToUpdate): void
{
const config = {
data: {
@ -127,7 +124,7 @@ export class PlaylistListComponent implements OnInit
// click sur supprimer playlist
onDeletePlaylist(playlist: PlaylistDB): void
onDeletePlaylist(playlist): void
{
const config = {data: playlist};
this.dialog
@ -155,7 +152,7 @@ export class PlaylistListComponent implements OnInit
// retourne la class CSS de conteneur de playlist
getClassOfPlaylistContainer(playlist: PlaylistDB): string
getClassOfPlaylistContainer(playlist): string
{
if(playlist === this.playlistFocusedOn) return "row btnPlaylist btnPlaylistFocus" ;
else return "row btnPlaylist" ;

View file

@ -1,7 +1,6 @@
import {Component, Inject, OnInit} from '@angular/core';
import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";
import {MessageService} from "../../../utils/services/message/message.service";
import {PlaylistDB} from "../../../utils/interfaces/playlist";
import {MessageService} from "../../../utils/message/message.service";
@ -19,7 +18,6 @@ export class PopupCreateOrUpdatePlaylistComponent implements OnInit
action: string = "";
constructor( public dialogRef: MatDialogRef<PopupCreateOrUpdatePlaylistComponent>,
@Inject(MAT_DIALOG_DATA) public data,
private messageService: MessageService) { }

Some files were not shown because too many files have changed in this diff Show more