changed the whole structure
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 Dario Weinberger & Raphael Payet
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
105
README.md
Normal file
@ -0,0 +1,105 @@
|
||||
<div align="center">
|
||||
|
||||
<p>
|
||||
<img src="img/logo.svg"
|
||||
height="130">
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://blog-raph.dariow.fr" alt="Portfolio">
|
||||
<img alt="Website" src="https://img.shields.io/website?up_message=Raphael%20PAYET&url=https%3A%2F%2Fblog-raph.dariow.fr&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAAsQAAALEBxi1JjQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAJjSURBVEiJtdbLb01RFAbwX28inWhSb0nrVUpHUiYkImZE0AlT8RirMJcwk0iMatT6AzojHp0WiYiJeA1QrXhdUgyUeKSqBnud3H2PtirhS072veusvR7fWWvt3WBmLEcXdqENLSF/hWe4ikt48Qc7v6EV5/EDk/G8xvN4XmfycfTFnlmhC2MYxUlUcR+LcDmexXgY706F7hj2lI1VSv+7cQHX0Y4JzMc+vMv0RrEXCyLLdtzAxbAxbeQT6A/HjWGoJ9MpMijQEzqNsac/bPyWSWuk+E3i9ZbE6090zOCgI3T6Ys9k2BhTKwikD/pG4vYgBiOSSXzFEK5JnFfj91C8mwzdQRwIG2/DqQapFEdwDOcyp89xB7exBguxJd7dxPtwshkbsSLbexRnpdLWjS+YmynMi8j2q0eZIqHzE82ZrCmyO1LBTqlqPmcKq2N97M94LDHRlsk+SVW1syKV2N3SpoWxjs7CQVG+i0rye1jTEN7eSJwXWIz1Umbjmbwz1jygOdgmNWMe0AosrUhc/1c8wemSbEc4XlWST/WR20J3e0l+Bo8qeKqWeoEPsZZ5nQqFzvuSvBPDFQxIHOZlOhzrulk4WCtlMJLJmrAVA0WjDeO46RutXRpseaN9kBptEzZgZba3rtFIbV2MisPSKPjbUXENh9RGRW+e5r8edh+Vhh1pxP6rcb27bLxAdyhckWbLiYio+Ni5gw58D51m6XyeMMOBk2cyJo2AUxLnDyRuCwdL1B+Z7yRapo28jBaJ13G1w72qduhX1R/6vabgnDQFZ8Iy9deW4ubwSqr74trycjoDvwCYk8zNCgNVYwAAAABJRU5ErkJggg==&label=&labelColor=white&color=blue"></a>
|
||||
<a href="https://blog.dariow.fr" alt="Portfolio">
|
||||
<img alt="Website" src="https://img.shields.io/website?up_message=Dario%20WEINBERGER&url=https%3A%2F%2Fblog.dariow.fr&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAAsQAAALEBxi1JjQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAJjSURBVEiJtdbLb01RFAbwX28inWhSb0nrVUpHUiYkImZE0AlT8RirMJcwk0iMatT6AzojHp0WiYiJeA1QrXhdUgyUeKSqBnud3H2PtirhS072veusvR7fWWvt3WBmLEcXdqENLSF/hWe4ikt48Qc7v6EV5/EDk/G8xvN4XmfycfTFnlmhC2MYxUlUcR+LcDmexXgY706F7hj2lI1VSv+7cQHX0Y4JzMc+vMv0RrEXCyLLdtzAxbAxbeQT6A/HjWGoJ9MpMijQEzqNsac/bPyWSWuk+E3i9ZbE6090zOCgI3T6Ys9k2BhTKwikD/pG4vYgBiOSSXzFEK5JnFfj91C8mwzdQRwIG2/DqQapFEdwDOcyp89xB7exBguxJd7dxPtwshkbsSLbexRnpdLWjS+YmynMi8j2q0eZIqHzE82ZrCmyO1LBTqlqPmcKq2N97M94LDHRlsk+SVW1syKV2N3SpoWxjs7CQVG+i0rye1jTEN7eSJwXWIz1Umbjmbwz1jygOdgmNWMe0AosrUhc/1c8wemSbEc4XlWST/WR20J3e0l+Bo8qeKqWeoEPsZZ5nQqFzvuSvBPDFQxIHOZlOhzrulk4WCtlMJLJmrAVA0WjDeO46RutXRpseaN9kBptEzZgZba3rtFIbV2MisPSKPjbUXENh9RGRW+e5r8edh+Vhh1pxP6rcb27bLxAdyhckWbLiYio+Ni5gw58D51m6XyeMMOBk2cyJo2AUxLnDyRuCwdL1B+Z7yRapo28jBaJ13G1w72qduhX1R/6vabgnDQFZ8Iy9deW4ubwSqr74trycjoDvwCYk8zNCgNVYwAAAABJRU5ErkJggg==&label=&labelColor=white&color=blue"></a>
|
||||
|
||||
|
||||
|
||||
|
||||
</p>
|
||||
|
||||
</div>
|
||||
|
||||
<br>
|
||||
|
||||
Wikipedia article comparison tool. This tool allows you to compare the data contained in the infoboxes as well as statistics of 2 different wikipedia articles.
|
||||
|
||||
|
||||
## Demo
|
||||
|
||||
|
||||
|
||||
|
||||
<div align="center">
|
||||
<img src="img/demo.gif">
|
||||
|
||||
<p>Access online demo : [radar.dariow.fr](https://radar.dariow.fr)</p>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
## Dependencies
|
||||
|
||||
|
||||
We use docker containers, so it will be necessary to have Docker and Docker compose.
|
||||
|
||||
Installation Guides:
|
||||
- [docker](https://docs.docker.com/)
|
||||
- [docker-compose](https://docs.docker.com/compose/install/)
|
||||
|
||||
## Install
|
||||
Configure logins and passwords in the ".env" located in the root of the project (PLEASE USE STRONG PASSWORDS):
|
||||
|
||||
```yml
|
||||
# Root password
|
||||
DATABASE_ROOT_PASSWORD=changeme # NEED TO CHANGE !
|
||||
|
||||
# User to use
|
||||
DATABASE_USER=radar
|
||||
|
||||
# User password
|
||||
DATABASE_PASSWORD=changeme # NEED TO CHANGE !
|
||||
|
||||
# Database name
|
||||
DATABASE=rappaurio
|
||||
|
||||
```
|
||||
|
||||
And do the same for the ".env" inside the "app-rappaurio" folder :
|
||||
|
||||
```yml
|
||||
# Root password
|
||||
DATABASE_ROOT_PASSWORD=changeme # NEED TO CHANGE !
|
||||
|
||||
# MariaDB hostname
|
||||
DATABASE_HOST=db
|
||||
|
||||
# User to use
|
||||
DATABASE_USER=radar
|
||||
|
||||
# User password
|
||||
DATABASE_PASSWORD=changeme # NEED TO CHANGE !
|
||||
|
||||
# Database name
|
||||
DATABASE=rappaurio
|
||||
|
||||
# Token private Key
|
||||
JWT_SECRET=hsdgbniojksdgoijosidgjoisdg # NEED TO CHANGE !
|
||||
|
||||
JWT_EXPIRES_IN=86400000
|
||||
JWT_COOKIE_EXPIRES_IN=86400000
|
||||
```
|
||||
|
||||
Building images using docker-compose.yml:
|
||||
|
||||
```shell
|
||||
docker-compose build
|
||||
```
|
||||
Launching containers using the docker-compose.yml file:
|
||||
|
||||
```shell
|
||||
docker-compose up -d
|
||||
|
||||
```
|
||||
|
||||
The site is now available locally on https://localhost:8888
|
||||
|
||||
Or at the ip address of your machine [https://\<your-ip-adresse>:8888]()
|
20
app-rappaurio/.env
Normal file
@ -0,0 +1,20 @@
|
||||
# Root password
|
||||
DATABASE_ROOT_PASSWORD=changeme # NEED TO CHANGE !
|
||||
|
||||
# MariaDB hostname
|
||||
DATABASE_HOST=db
|
||||
|
||||
# User to use
|
||||
DATABASE_USER=radar
|
||||
|
||||
# User password
|
||||
DATABASE_PASSWORD=changeme # NEED TO CHANGE !
|
||||
|
||||
# Database name
|
||||
DATABASE=rappaurio
|
||||
|
||||
# Token private Key
|
||||
JWT_SECRET=hsdgbniojksdgoijosidgjoisdg # NEED TO CHANGE !
|
||||
|
||||
JWT_EXPIRES_IN=86400000
|
||||
JWT_COOKIE_EXPIRES_IN=86400000
|
20
app-rappaurio/Dockerfile
Normal file
@ -0,0 +1,20 @@
|
||||
# pull the Node.js Docker image
|
||||
FROM node:alpine
|
||||
|
||||
# create the directory inside the container
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
# copy the package.json files from local machine to the workdir in container
|
||||
COPY package*.json ./
|
||||
|
||||
# run npm install in our local machine
|
||||
RUN npm install
|
||||
|
||||
# copy the generated modules and all other files to the container
|
||||
COPY . .
|
||||
|
||||
# our app is running on port 5000 within the container, so need to expose it
|
||||
EXPOSE 5000
|
||||
|
||||
# the command that starts our app
|
||||
CMD ["npm", "start"]
|
63
app-rappaurio/app.js
Normal file
@ -0,0 +1,63 @@
|
||||
var createError = require('http-errors');
|
||||
var express = require('express');
|
||||
var path = require('path');
|
||||
var cookieParser = require('cookie-parser');
|
||||
var logger = require('morgan');
|
||||
const mysql = require('mysql');
|
||||
const dotenv = require('dotenv');
|
||||
|
||||
var app = express();
|
||||
|
||||
dotenv.config({ path : './.env'})
|
||||
|
||||
// Create database connection
|
||||
const db = mysql.createConnection({
|
||||
host: process.env.DATABASE_HOST,
|
||||
user: process.env.DATABASE_USER,
|
||||
password: process.env.DATABASE_PASSWORD,
|
||||
database: process.env.DATABASE
|
||||
});
|
||||
|
||||
|
||||
// Connecting our databse and checking everything works fine
|
||||
db.connect( (error)=>{
|
||||
if(error){
|
||||
console.log(error)
|
||||
}
|
||||
else{
|
||||
console.log("MySQL database connected...")
|
||||
}
|
||||
})
|
||||
|
||||
// view engine setup
|
||||
app.set('views', path.join(__dirname, 'views'));
|
||||
app.set('view engine', 'hbs');
|
||||
|
||||
app.use(logger('dev'));
|
||||
app.use(express.json());
|
||||
app.use(express.urlencoded({ extended: false }));
|
||||
app.use(cookieParser());
|
||||
app.use(express.static(path.join(__dirname, 'public')));
|
||||
|
||||
// Define Routes
|
||||
app.use('/', require('./server/routes/index'));
|
||||
app.use('/auth', require('./server/routes/auth'));
|
||||
|
||||
|
||||
// catch 404 and forward to error handler
|
||||
app.use(function(req, res, next) {
|
||||
next(createError(404));
|
||||
});
|
||||
|
||||
// error handler
|
||||
app.use(function(err, req, res, next) {
|
||||
// set locals, only providing error in development
|
||||
res.locals.message = err.message;
|
||||
res.locals.error = req.app.get('env') === 'development' ? err : {};
|
||||
|
||||
// render the error page
|
||||
res.status(err.status || 500);
|
||||
res.render('contains/404');
|
||||
});
|
||||
|
||||
module.exports = app;
|
91
app-rappaurio/bin/www
Normal file
@ -0,0 +1,91 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var app = require('../app');
|
||||
var debug = require('debug')('app-rappaurio:server');
|
||||
var http = require('http');
|
||||
|
||||
/**
|
||||
* Get port from environment and store in Express.
|
||||
*/
|
||||
|
||||
var port = normalizePort(process.env.PORT || '5000');
|
||||
app.set('port', port);
|
||||
console.log("Server started on port : " + port);
|
||||
|
||||
/**
|
||||
* Create HTTP server.
|
||||
*/
|
||||
|
||||
var server = http.createServer(app);
|
||||
|
||||
/**
|
||||
* Listen on provided port, on all network interfaces.
|
||||
*/
|
||||
|
||||
server.listen(port);
|
||||
server.on('error', onError);
|
||||
server.on('listening', onListening);
|
||||
|
||||
/**
|
||||
* Normalize a port into a number, string, or false.
|
||||
*/
|
||||
|
||||
function normalizePort(val) {
|
||||
var port = parseInt(val, 10);
|
||||
|
||||
if (isNaN(port)) {
|
||||
// named pipe
|
||||
return val;
|
||||
}
|
||||
|
||||
if (port >= 0) {
|
||||
// port number
|
||||
return port;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Event listener for HTTP server "error" event.
|
||||
*/
|
||||
|
||||
function onError(error) {
|
||||
if (error.syscall !== 'listen') {
|
||||
throw error;
|
||||
}
|
||||
|
||||
var bind = typeof port === 'string'
|
||||
? 'Pipe ' + port
|
||||
: 'Port ' + port;
|
||||
|
||||
// handle specific listen errors with friendly messages
|
||||
switch (error.code) {
|
||||
case 'EACCES':
|
||||
console.error(bind + ' requires elevated privileges');
|
||||
process.exit(1);
|
||||
break;
|
||||
case 'EADDRINUSE':
|
||||
console.error(bind + ' is already in use');
|
||||
process.exit(1);
|
||||
break;
|
||||
default:
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Event listener for HTTP server "listening" event.
|
||||
*/
|
||||
|
||||
function onListening() {
|
||||
var addr = server.address();
|
||||
var bind = typeof addr === 'string'
|
||||
? 'pipe ' + addr
|
||||
: 'port ' + addr.port;
|
||||
debug('Listening on ' + bind);
|
||||
}
|
1292
app-rappaurio/package-lock.json
generated
Normal file
26
app-rappaurio/package.json
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "app-rappaurio",
|
||||
"version": "1.2.0",
|
||||
"description": "Require nodejs 14 or higher",
|
||||
"main": "app.js",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "node ./bin/www"
|
||||
},
|
||||
"author": "Dario WEINBERGER & Raphael PAYET",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"axios": "^1.5.1",
|
||||
"bcryptjs": "^2.4.3",
|
||||
"cookie-parser": "~1.4.4",
|
||||
"debug": "~2.6.9",
|
||||
"dotenv": "^16.3.1",
|
||||
"express": "^4.18.2",
|
||||
"hbs": "^4.2.0",
|
||||
"http-errors": "~1.6.3",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"morgan": "~1.9.1",
|
||||
"mysql": "^2.18.1",
|
||||
"wikiapi": "^1.19.4"
|
||||
}
|
||||
}
|
BIN
app-rappaurio/public/images/blog-details-02.jpg
Normal file
After Width: | Height: | Size: 133 KiB |
BIN
app-rappaurio/public/images/icon.png
Normal file
After Width: | Height: | Size: 3.9 KiB |
BIN
app-rappaurio/public/images/log-wiki-cust.png
Normal file
After Width: | Height: | Size: 21 KiB |
94
app-rappaurio/public/images/log-wiki.svg
Normal file
@ -0,0 +1,94 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||
width="933.000000pt" height="178.000000pt" viewBox="0 0 933.000000 178.000000"
|
||||
preserveAspectRatio="xMidYMid meet">
|
||||
|
||||
<g transform="translate(0.000000,178.000000) scale(0.100000,-0.100000)"
|
||||
fill="#000000" stroke="none">
|
||||
<path d="M7523 1475 c-40 -17 -53 -42 -53 -103 0 -71 21 -93 96 -102 141 -17
|
||||
214 18 214 101 0 59 -23 96 -68 108 -52 15 -151 13 -189 -4z"/>
|
||||
<path d="M380 1420 c0 -5 1 -11 2 -12 1 -2 -4 -13 -10 -25 -9 -16 -9 -24 -1
|
||||
-29 8 -5 6 -10 -5 -16 -23 -13 -21 -48 3 -48 10 0 21 -7 25 -15 6 -18 36 -9
|
||||
36 11 0 9 11 14 29 14 25 0 28 3 23 25 -2 15 0 25 7 25 6 0 11 7 11 15 0 19
|
||||
-14 19 -30 0 -7 -9 -21 -13 -31 -10 -11 4 -22 -1 -28 -12 -9 -16 -12 -16 -21
|
||||
-3 -10 14 -8 38 6 74 3 9 1 16 -5 16 -6 0 -11 -4 -11 -10z"/>
|
||||
<path d="M1095 1420 c-3 -5 -7 -26 -9 -45 -2 -20 -8 -41 -15 -48 -17 -17 -14
|
||||
-48 4 -40 9 3 22 -2 31 -13 14 -18 15 -18 30 4 10 12 27 22 41 22 20 0 23 4
|
||||
18 21 -5 14 -1 25 11 33 13 10 14 15 4 21 -8 5 -18 1 -26 -9 -8 -12 -20 -16
|
||||
-32 -12 -13 4 -22 1 -26 -9 -3 -8 -9 -15 -15 -15 -16 0 -19 36 -5 69 12 28 4
|
||||
45 -11 21z"/>
|
||||
<path d="M2010 981 l0 -441 140 0 140 0 0 131 0 130 32 -3 c31 -3 34 -8 88
|
||||
-128 l56 -125 152 -3 c84 -1 152 0 152 4 0 4 -33 69 -72 145 l-73 138 38 34
|
||||
c64 59 82 113 82 247 0 96 -3 122 -21 160 -27 57 -67 97 -124 124 -42 19 -65
|
||||
21 -317 24 l-273 3 0 -440z m428 197 c14 -14 16 -116 2 -138 -6 -10 -32 -16
|
||||
-79 -18 l-71 -4 0 86 0 86 68 0 c40 0 73 -5 80 -12z"/>
|
||||
<path d="M620 1400 c0 -5 5 -10 11 -10 5 0 7 5 4 10 -3 6 -8 10 -11 10 -2 0
|
||||
-4 -4 -4 -10z"/>
|
||||
<path d="M1340 1400 c0 -5 5 -10 11 -10 5 0 7 5 4 10 -3 6 -8 10 -11 10 -2 0
|
||||
-4 -4 -4 -10z"/>
|
||||
<path d="M3085 1260 c-87 -8 -193 -29 -200 -40 -3 -6 24 -190 29 -197 0 -1 26
|
||||
5 56 13 30 8 108 17 173 21 l117 6 0 -25 c0 -25 -2 -25 -93 -32 -217 -16 -308
|
||||
-71 -338 -204 -9 -38 -9 -64 -1 -108 24 -117 97 -168 242 -168 72 -1 94 4 145
|
||||
27 33 16 70 38 83 49 l22 22 43 -42 c42 -41 45 -42 110 -42 l67 0 0 273 c0
|
||||
307 -4 326 -75 384 -66 55 -214 79 -380 63z m175 -459 c0 -56 -19 -71 -91 -71
|
||||
l-59 0 0 45 c0 54 14 64 93 65 l57 0 0 -39z"/>
|
||||
<path d="M4012 1259 c-59 -10 -103 -30 -134 -61 l-21 -21 -24 32 c-23 29 -28
|
||||
31 -94 31 l-69 0 0 -466 0 -466 43 5 c23 4 86 9 140 13 l97 6 0 104 0 104 90
|
||||
0 c168 0 248 36 303 137 79 146 51 407 -54 512 -62 63 -166 89 -277 70z m78
|
||||
-342 c0 -176 -5 -187 -86 -187 l-54 0 0 149 c0 176 2 181 86 181 l54 0 0 -143z"/>
|
||||
<path d="M4849 1260 c-56 -10 -111 -34 -135 -61 -23 -25 -27 -24 -47 11 -18
|
||||
29 -20 30 -93 30 l-74 0 0 -466 0 -466 43 5 c23 4 86 9 140 13 l97 6 0 103 0
|
||||
102 123 5 c97 4 130 9 162 25 99 51 145 137 153 281 11 209 -49 343 -179 395
|
||||
-46 19 -133 27 -190 17z m71 -355 c0 -177 1 -175 -89 -175 l-51 0 0 149 c0
|
||||
144 1 151 22 165 13 9 43 16 70 16 l48 0 0 -155z"/>
|
||||
<path d="M5550 1260 c-71 -7 -188 -28 -201 -36 -5 -3 16 -159 26 -191 3 -9 17
|
||||
-8 57 3 29 8 106 17 171 21 l117 6 0 -24 c0 -24 -3 -25 -113 -36 -230 -23
|
||||
-317 -93 -317 -255 1 -145 60 -209 208 -224 75 -8 171 16 238 61 l51 33 39
|
||||
-39 c37 -38 40 -39 106 -39 l68 0 0 277 c0 262 -1 279 -21 321 -48 99 -210
|
||||
145 -429 122z m170 -465 c0 -54 -16 -65 -94 -65 l-56 0 0 45 c0 54 14 64 93
|
||||
65 l57 0 0 -45z"/>
|
||||
<path d="M8160 1260 c-130 -21 -195 -62 -240 -154 -77 -156 -50 -415 53 -502
|
||||
77 -66 221 -96 356 -76 187 27 272 124 287 325 11 153 -34 287 -119 348 -71
|
||||
51 -218 77 -337 59z m160 -343 c0 -176 -5 -187 -86 -187 l-54 0 0 155 c0 177
|
||||
-1 174 88 175 l52 0 0 -143z"/>
|
||||
<path d="M7296 1240 c-27 -10 -66 -31 -87 -45 l-38 -27 -31 36 c-31 35 -34 36
|
||||
-106 36 l-74 0 0 -350 0 -351 138 3 137 3 3 199 c1 120 7 204 13 212 6 7 41
|
||||
21 79 30 l69 18 -5 86 c-8 144 -13 170 -32 170 -9 -1 -39 -10 -66 -20z"/>
|
||||
<path d="M6120 952 c0 -281 1 -290 23 -333 34 -66 96 -94 207 -94 98 0 143 13
|
||||
204 60 l44 33 38 -39 c39 -40 39 -40 109 -37 l70 3 3 348 2 347 -140 0 -140 0
|
||||
0 -233 c0 -277 0 -277 -86 -277 l-54 0 0 255 0 255 -140 0 -140 0 0 -288z"/>
|
||||
<path d="M7605 1225 c-49 -7 -98 -14 -107 -14 -17 -1 -18 -24 -18 -336 l0
|
||||
-335 140 0 140 0 0 350 0 350 -32 -1 c-18 -1 -73 -7 -123 -14z"/>
|
||||
<path d="M611 1194 c0 -11 3 -14 6 -6 3 7 2 16 -1 19 -3 4 -6 -2 -5 -13z"/>
|
||||
<path d="M581 1184 c0 -11 3 -14 6 -6 3 7 2 16 -1 19 -3 4 -6 -2 -5 -13z"/>
|
||||
<path d="M1155 1131 c-3 -5 -1 -12 5 -16 5 -3 10 1 10 9 0 18 -6 21 -15 7z"/>
|
||||
<path d="M792 1118 c-18 -18 -15 -113 3 -128 12 -10 15 -37 15 -121 l0 -109
|
||||
-110 0 -110 0 0 35 0 35 50 0 c41 0 56 5 75 25 32 31 35 89 6 105 -21 11 -348
|
||||
14 -375 4 -11 -4 -16 -19 -16 -48 0 -63 16 -79 89 -84 l61 -4 0 -34 0 -34 -58
|
||||
0 c-66 0 -92 -18 -92 -62 0 -54 16 -58 258 -58 l222 0 0 -45 c0 -43 -1 -45
|
||||
-30 -45 -38 0 -70 -32 -70 -70 l0 -30 -75 0 c-41 0 -85 -5 -99 -11 -31 -15
|
||||
-48 -55 -44 -105 l3 -39 173 -3 c149 -2 172 0 172 13 0 13 -23 15 -160 15
|
||||
l-160 0 0 34 c0 65 6 66 352 66 341 0 338 1 338 -66 l0 -34 -160 0 c-137 0
|
||||
-160 -2 -160 -15 0 -13 23 -15 173 -13 l172 3 3 52 c3 45 -1 56 -22 78 -23 23
|
||||
-33 25 -106 25 -77 0 -80 1 -80 24 0 39 -36 76 -76 76 -34 0 -34 0 -34 45 l0
|
||||
45 125 0 c104 0 125 2 125 15 0 13 -21 15 -125 15 l-125 0 0 30 0 30 218 0
|
||||
c229 0 251 -4 231 -42 -8 -15 -22 -18 -79 -18 -56 0 -70 -3 -70 -15 0 -12 15
|
||||
-15 74 -15 84 0 106 13 106 60 0 44 -23 60 -86 60 l-54 0 0 35 0 35 48 0 c69
|
||||
0 92 19 92 79 0 35 -4 51 -16 55 -20 8 -348 8 -368 0 -11 -4 -16 -19 -16 -48
|
||||
0 -62 17 -78 84 -84 l56 -4 0 -34 0 -34 -110 0 -110 0 0 106 c0 85 3 109 16
|
||||
118 24 18 30 90 10 121 -15 22 -23 25 -79 25 -36 0 -68 -5 -75 -12z m133 -63
|
||||
l0 -40 -57 -3 -58 -3 0 46 0 46 58 -3 57 -3 0 -40z m-35 -295 l0 -210 -25 0
|
||||
-25 0 0 210 0 210 25 0 25 0 0 -210z m-180 153 c-1 -42 -10 -44 -181 -41
|
||||
l-164 3 -3 28 -3 27 175 0 c161 0 176 -1 176 -17z m670 0 c-1 -42 -10 -44
|
||||
-181 -41 l-164 3 -3 28 -3 27 175 0 c161 0 176 -1 176 -17z m-820 -118 c0 -31
|
||||
-3 -35 -25 -35 -22 0 -25 4 -25 35 0 31 3 35 25 35 22 0 25 -4 25 -35z m670
|
||||
-1 c0 -33 -2 -35 -27 -32 -23 2 -29 8 -31 36 -3 30 -1 32 27 32 29 0 31 -3 31
|
||||
-36z m-420 -94 l0 -30 -220 0 c-187 0 -222 2 -226 15 -4 8 -4 22 0 30 4 13 39
|
||||
15 226 15 l220 0 0 -30z m180 -199 c25 -48 19 -51 -120 -51 l-130 0 0 29 c0
|
||||
16 6 32 13 34 6 3 60 6 119 6 96 1 108 -1 118 -18z"/>
|
||||
<path d="M605 1100 c3 -5 8 -10 11 -10 2 0 4 5 4 10 0 6 -5 10 -11 10 -5 0 -7
|
||||
-4 -4 -10z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 6.0 KiB |
1
app-rappaurio/public/images/logo-2.svg
Normal file
After Width: | Height: | Size: 265 KiB |
1
app-rappaurio/public/images/logo.svg
Normal file
After Width: | Height: | Size: 265 KiB |
BIN
app-rappaurio/public/images/wikipedia-dark.png
Normal file
After Width: | Height: | Size: 1.0 MiB |
BIN
app-rappaurio/public/images/wikipedia.png
Normal file
After Width: | Height: | Size: 67 KiB |
16
app-rappaurio/public/js/bundle.js
Normal file
368
app-rappaurio/public/js/custom.js
Normal file
@ -0,0 +1,368 @@
|
||||
|
||||
// === SCROLL MENU ===
|
||||
const pageLink = document.querySelectorAll('.menu-scroll');
|
||||
|
||||
pageLink.forEach((elem) => {
|
||||
elem.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
document.querySelector(elem.getAttribute('href')).scrollIntoView({
|
||||
behavior: 'smooth',
|
||||
offsetTop: 1 - 60,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// section menu active
|
||||
function onScroll(event) {
|
||||
const sections = document.querySelectorAll('.menu-scroll');
|
||||
const scrollPos = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
|
||||
|
||||
for (let i = 0; i < sections.length; i++) {
|
||||
const currLink = sections[i];
|
||||
const val = currLink.getAttribute('href');
|
||||
const refElement = document.querySelector(val);
|
||||
const scrollTopMinus = scrollPos + 73;
|
||||
if (refElement.offsetTop <= scrollTopMinus && refElement.offsetTop + refElement.offsetHeight > scrollTopMinus) {
|
||||
document.querySelector('.menu-scroll').classList.remove('active');
|
||||
currLink.classList.add('active');
|
||||
} else {
|
||||
currLink.classList.remove('active');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
window.document.addEventListener('scroll', onScroll);
|
||||
|
||||
// === FOOTER DYNAMIC ===
|
||||
|
||||
// Sélectionnez le footer par son ID
|
||||
const footer = document.getElementById('leFooter');
|
||||
|
||||
// Fonction pour positionner le footer en bas de la page
|
||||
function positionFooter() {
|
||||
const windowHeight = window.innerHeight;
|
||||
const bodyHeight = document.body.clientHeight;
|
||||
const footerHeight = footer.clientHeight;
|
||||
|
||||
if (bodyHeight < windowHeight) {
|
||||
footer.style.position = 'absolute';
|
||||
footer.style.bottom = '0';
|
||||
} else {
|
||||
footer.style.position = 'static';
|
||||
}
|
||||
}
|
||||
|
||||
// Appelez la fonction lors du chargement de la page et lorsque la fenêtre est redimensionnée
|
||||
window.addEventListener('load', positionFooter);
|
||||
window.addEventListener('resize', positionFooter);
|
||||
|
||||
|
||||
// === MODE SOMBRE +> LOCAL STORAGE ===
|
||||
|
||||
// Fonction pour lire la valeur du thème depuis localStorage
|
||||
function getThemeLocalStorage() {
|
||||
return localStorage.getItem('theme');
|
||||
}
|
||||
|
||||
// Fonction pour définir le thème dans localStorage
|
||||
function setThemeLocalStorage(theme) {
|
||||
localStorage.setItem('theme', theme);
|
||||
}
|
||||
|
||||
// Fonction pour mettre à jour la classe sur le <html> en fonction du thème
|
||||
function updateThemeClass() {
|
||||
const darkTogglerCheckbox = document.querySelector('#darkToggler');
|
||||
const html = document.querySelector('html');
|
||||
const theme = getThemeLocalStorage();
|
||||
|
||||
// Appliquer la classe en fonction de la valeur de localStorage
|
||||
if (theme === 'dark') {
|
||||
darkTogglerCheckbox.checked = true;
|
||||
html.classList.add('dark');
|
||||
} else {
|
||||
darkTogglerCheckbox.checked = false;
|
||||
html.classList.remove('dark');
|
||||
}
|
||||
}
|
||||
|
||||
// Appeler la fonction d'initialisation de la gestion du thème
|
||||
updateThemeClass();
|
||||
|
||||
// Gérer le changement de thème lorsque l'utilisateur clique sur la case à cocher
|
||||
const darkTogglerCheckbox = document.querySelector('#darkToggler');
|
||||
darkTogglerCheckbox.addEventListener('click', function () {
|
||||
if (darkTogglerCheckbox.checked) {
|
||||
setThemeLocalStorage('dark');
|
||||
} else {
|
||||
setThemeLocalStorage('light');
|
||||
}
|
||||
});
|
||||
|
||||
// === ENVOIE FORMULAIRE AVEC AJAX ===
|
||||
|
||||
// Attendre que le document soit prêt
|
||||
$(document).ready(function () {
|
||||
|
||||
// Sélectionnez le formulaire de COMPARAISON par son ID
|
||||
$('#formulaire-comp').submit(function (e) {
|
||||
|
||||
// Fait scroll une fois le formulaire envoyé
|
||||
$(document).ready(function () {
|
||||
// Sélectionnez le lien par son ID
|
||||
|
||||
$('html, body').animate({
|
||||
scrollTop: $('#resultat').offset().top
|
||||
}, 1000); // 1000 millisecondes (1 seconde) pour l'animation
|
||||
});
|
||||
|
||||
// Empêchez la soumission normale du formulaire
|
||||
e.preventDefault();
|
||||
|
||||
// Affiche le chargement
|
||||
$('#loading').removeClass('hidden');
|
||||
|
||||
$('#articleIntrouvable').addClass('hidden');
|
||||
$('#articleContainer1').addClass('hidden');
|
||||
$('#articleContainer2').addClass('hidden');
|
||||
|
||||
// Reste du code pour gérer la soumission du formulaire
|
||||
//console.log('Formulaire soumis !');
|
||||
|
||||
// Récupérez les valeurs des champs du formulaire
|
||||
const articleTitle1 = $('#articleTitle1').val();
|
||||
const articleTitle2 = $('#articleTitle2').val();
|
||||
|
||||
// Créez un objet JavaScript avec les données à envoyer au serveur
|
||||
const formData = {
|
||||
articleTitle1: articleTitle1,
|
||||
articleTitle2: articleTitle2
|
||||
};
|
||||
|
||||
// Utilisez AJAX pour envoyer les données au serveur
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: '/search',
|
||||
data: formData,
|
||||
dataType: 'json',
|
||||
success: function (response) {
|
||||
console.log(response);
|
||||
|
||||
$('#loading').addClass('hidden');
|
||||
$('#articleIntrouvable').removeClass('hidden');
|
||||
|
||||
// Mettez à jour la section HTML avec les données reçues ici
|
||||
|
||||
// Vérifiez si response.articleInfo1 existe et contient les informations nécessaires
|
||||
if (response.articleInfo1) {
|
||||
$('#articleInfo1Title').html(response.articleInfo1.title);
|
||||
|
||||
// Article 1
|
||||
$('#articleInfo1Title').html(response.articleInfo1.title);
|
||||
$('#articleInfo1url').attr('href', response.articleInfo1.url);
|
||||
$('#articleInfo1extract').html(response.articleInfo1.extract);
|
||||
$('#articleInfo1lastEdit').html(response.articleInfo1.lastEdit);
|
||||
$('#articleInfo1numRevisions').html(response.articleInfo1.numRevisions);
|
||||
$('#articleInfo1pageSize').html(response.articleInfo1.pageSize);
|
||||
$('#articleInfo1firstRevisionUser').html(response.articleInfo1.firstRevisionUser);
|
||||
$('#articleInfo1latestRevisionId').html(response.articleInfo1.latestRevisionId);
|
||||
$('#articleInfo1pageId').html(response.articleInfo1.pageId);
|
||||
$('#articleInfo1latestVersion').html(response.articleInfo1.latestVersion);
|
||||
$('#articleInfo1wordCount').html(response.articleInfo1.wordCount);
|
||||
$('#articleInfo1charCount').html(response.articleInfo1.charCount);
|
||||
$('#articleInfo1lastContributor').html(response.articleInfo1.lastContributor);
|
||||
$('#articleInfo1image').attr('href', response.articleInfo1.image);
|
||||
$('#articleInfo1image img').attr('src', response.articleInfo1.image);
|
||||
|
||||
// Récupérez la valeur de l'image
|
||||
const articleInfo1ImageValue = response.articleInfo1.image;
|
||||
|
||||
// Récupérez l'élément image par son ID
|
||||
const articleInfo1Image = document.getElementById("articleInfo1image");
|
||||
|
||||
if (articleInfo1ImageValue === "Non disponible") {
|
||||
// Si la valeur est "Non disponible", masquez l'élément
|
||||
articleInfo1Image.style.display = "none";
|
||||
} else {
|
||||
// Sinon, affichez l'élément
|
||||
articleInfo1Image.style.display = "block"; // Vous pouvez utiliser "inline" si nécessaire
|
||||
// Assurez-vous de définir la source de l'image ici en fonction de votre logique
|
||||
articleInfo1Image.src = articleInfo1ImageValue;
|
||||
}
|
||||
|
||||
|
||||
const infoboxContainer1 = document.getElementById("infoboxcontainer1");
|
||||
// Supprimer le contenu précédent de l'infobox
|
||||
while (infoboxContainer1.firstChild) {
|
||||
infoboxContainer1.removeChild(infoboxContainer1.firstChild);
|
||||
}
|
||||
// Ajouter les nouvelles informations pour articleInfo1
|
||||
const infoboxData1 = response.articleInfo1.infobox;
|
||||
Object.entries(infoboxData1).forEach(([key, value]) => {
|
||||
const ligne = document.createElement("tr");
|
||||
ligne.innerHTML = `<th>${key}</th> <td>${value}</td>`;
|
||||
infoboxContainer1.appendChild(ligne);
|
||||
});
|
||||
} else {
|
||||
// Traitez le cas où response.articleInfo1 n'existe pas
|
||||
}
|
||||
|
||||
|
||||
// Vérifiez si response.articleInfo2 existe et contient les informations nécessaires
|
||||
if (response.articleInfo2) {
|
||||
$('#articleInfo2Title').html(response.articleInfo2.title);
|
||||
|
||||
// Article 2
|
||||
$('#articleInfo2Title').html(response.articleInfo2.title);
|
||||
$('#articleInfo2url').attr('href', response.articleInfo2.url);
|
||||
$('#articleInfo2extract').html(response.articleInfo2.extract);
|
||||
$('#articleInfo2lastEdit').html(response.articleInfo2.lastEdit);
|
||||
$('#articleInfo2numRevisions').html(response.articleInfo2.numRevisions);
|
||||
$('#articleInfo2pageSize').html(response.articleInfo2.pageSize);
|
||||
$('#articleInfo2firstRevisionUser').html(response.articleInfo2.firstRevisionUser);
|
||||
$('#articleInfo2latestRevisionId').html(response.articleInfo2.latestRevisionId);
|
||||
$('#articleInfo2pageId').html(response.articleInfo2.pageId);
|
||||
$('#articleInfo2latestVersion').html(response.articleInfo2.latestVersion);
|
||||
$('#articleInfo2wordCount').html(response.articleInfo2.wordCount);
|
||||
$('#articleInfo2charCount').html(response.articleInfo2.charCount);
|
||||
$('#articleInfo2lastContributor').html(response.articleInfo2.lastContributor);
|
||||
$('#articleInfo2image').attr('href', response.articleInfo2.image);
|
||||
$('#articleInfo2image img').attr('src', response.articleInfo2.image);
|
||||
|
||||
|
||||
// Récupérez la valeur de l'image
|
||||
const articleInfo2ImageValue = response.articleInfo2.image;
|
||||
|
||||
// Récupérez l'élément image par son ID
|
||||
const articleInfo2Image = document.getElementById("articleInfo2image");
|
||||
|
||||
if (articleInfo2ImageValue === "Non disponible") {
|
||||
// Si la valeur est "Non disponible", masquez l'élément
|
||||
articleInfo2Image.style.display = "none";
|
||||
} else {
|
||||
// Sinon, affichez l'élément
|
||||
articleInfo2Image.style.display = "block"; // Vous pouvez utiliser "inline" si nécessaire
|
||||
// Assurez-vous de définir la source de l'image ici en fonction de votre logique
|
||||
articleInfo2Image.src = articleInfo2ImageValue;
|
||||
}
|
||||
|
||||
const infoboxContainer2 = document.getElementById("infoboxcontainer2");
|
||||
// Supprimer le contenu précédent de l'infobox
|
||||
while (infoboxContainer2.firstChild) {
|
||||
infoboxContainer2.removeChild(infoboxContainer2.firstChild);
|
||||
}
|
||||
// Ajouter les nouvelles informations pour articleInfo2
|
||||
const infoboxData2 = response.articleInfo2.infobox;
|
||||
Object.entries(infoboxData2).forEach(([key, value]) => {
|
||||
const ligne = document.createElement("tr");
|
||||
ligne.innerHTML = `<th>${key}</th> <td>${value}</td>`;
|
||||
infoboxContainer2.appendChild(ligne);
|
||||
});
|
||||
} else {
|
||||
// Traitez le cas où response.articleInfo2 n'existe pas
|
||||
}
|
||||
|
||||
// Vérifiez si toutes les informations nécessaires sont disponibles
|
||||
const allInfoAvailable = checkIfAllInfoAvailable(response);
|
||||
|
||||
if (allInfoAvailable) {
|
||||
$('#articleContainer1').removeClass('hidden');
|
||||
$('#articleContainer2').removeClass('hidden');
|
||||
$('#articleIntrouvable').addClass('hidden');
|
||||
|
||||
$(document).ready(function () {
|
||||
// Sélectionnez le lien par son ID
|
||||
$('html, body').animate({
|
||||
scrollTop: $('#resultat').offset().top
|
||||
}, 1000); // 1000 millisecondes (1 seconde) pour l'animation
|
||||
});
|
||||
|
||||
} else {
|
||||
// Traitez le cas où certaines informations ne sont pas disponibles
|
||||
const articleIntrouvable = document.getElementById("articleIntrouvable");
|
||||
let errorMessage = "";
|
||||
|
||||
if (!response.articleInfo1 && !response.articleInfo2) {
|
||||
errorMessage += "Les articles " +
|
||||
'<span class="underline">' + articleTitle1 + "</span> et " +
|
||||
'<span class="underline">' + articleTitle2 + "</span> sont introuvables.";
|
||||
}
|
||||
else {
|
||||
|
||||
if (!response.articleInfo1) {
|
||||
errorMessage += "L'article " + '<span class="underline">' + articleTitle1 + "</span> est introuvable.";
|
||||
}
|
||||
|
||||
if (!response.articleInfo2) {
|
||||
errorMessage += "L'article " + '<span class="underline">' + articleTitle2 + "</span> est introuvable.";
|
||||
}
|
||||
}
|
||||
|
||||
articleIntrouvable.innerHTML = errorMessage;
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
error: function (error) {
|
||||
console.error('Erreur lors de la recherche d\'informations sur les articles :', error);
|
||||
|
||||
// Ajoutez une console.log pour vérifier si cette partie du code est exécutée
|
||||
console.log('Erreur AJAX');
|
||||
|
||||
// Sélectionnez le div d'erreur par son ID
|
||||
const articleIntrouvable = document.getElementById("articleIntrouvable");
|
||||
|
||||
// Mettez à jour le contenu du div avec un message d'erreur
|
||||
articleIntrouvable.textContent = "Aucun article n'a été trouvé.";
|
||||
|
||||
// Assurez-vous de masquer les conteneurs d'articles
|
||||
$('#articleContainer1').addClass('hidden');
|
||||
$('#articleContainer2').addClass('hidden');
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
function checkIfAllInfoAvailable(response) {
|
||||
// Vérifiez si response.articleInfo1 contient toutes les informations nécessaires
|
||||
const articleInfo1 = response.articleInfo1;
|
||||
if (!articleInfo1) {
|
||||
return false; // Si articleInfo1 est absent, retournez false
|
||||
}
|
||||
// Ajoutez ici des vérifications spécifiques pour les propriétés nécessaires dans articleInfo1
|
||||
if (!articleInfo1.title || !articleInfo1.url || !articleInfo1.extract || !articleInfo1.lastEdit) {
|
||||
return false; // Si l'une des propriétés nécessaires est absente, retournez false
|
||||
}
|
||||
|
||||
// Vérifiez si response.articleInfo2 contient toutes les informations nécessaires
|
||||
const articleInfo2 = response.articleInfo2;
|
||||
if (!articleInfo2) {
|
||||
return false; // Si articleInfo2 est absent, retournez false
|
||||
}
|
||||
// Ajoutez ici des vérifications spécifiques pour les propriétés nécessaires dans articleInfo2
|
||||
if (!articleInfo2.title || !articleInfo2.url || !articleInfo2.extract || !articleInfo2.lastEdit) {
|
||||
return false; // Si l'une des propriétés nécessaires est absente, retournez false
|
||||
}
|
||||
|
||||
// Si toutes les vérifications sont passées, cela signifie que toutes les informations nécessaires sont disponibles
|
||||
return true;
|
||||
}
|
||||
|
||||
// === SMOOTH SCROLL ~(^^)~
|
||||
|
||||
// Fait scroll jusqu'au formulaire de comparaison
|
||||
$(document).ready(function () {
|
||||
// Sélectionnez le lien par son ID
|
||||
$('#letzgooo').click(function (e) {
|
||||
e.preventDefault(); // Empêchez le comportement de clic par défaut
|
||||
|
||||
$('html, body').animate({
|
||||
scrollTop: $('#comparaison').offset().top
|
||||
}, 1000); // 1000 millisecondes (1 seconde) pour l'animation
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
3867
app-rappaurio/public/stylesheets/style.css
Normal file
162
app-rappaurio/server/controllers/auth.js
Normal file
@ -0,0 +1,162 @@
|
||||
const mysql = require('mysql');
|
||||
const jwt = require('jsonwebtoken');
|
||||
const bcrypt = require('bcryptjs');
|
||||
const { promisify } = require('util');
|
||||
|
||||
const db = mysql.createConnection({
|
||||
host: process.env.DATABASE_HOST,
|
||||
user: process.env.DATABASE_USER,
|
||||
password: process.env.DATABASE_PASSWORD,
|
||||
database: process.env.DATABASE
|
||||
});
|
||||
|
||||
exports.login = async (req, res) => {
|
||||
try {
|
||||
const { email, password } = req.body;
|
||||
if (!email || !password) {
|
||||
return res.status(400).render('contains/connexion', {
|
||||
message: 'Veuillez entrer un email et un mot de passe'
|
||||
})
|
||||
}
|
||||
|
||||
db.query('SELECT * FROM users WHERE email = ?', [email], async (error, result) => {
|
||||
console.log(result)
|
||||
if (!result || result.length == 0 || !(await bcrypt.compare(password, result[0].password))) {
|
||||
res.status(401).render('contains/connexion', {
|
||||
message: 'Email ou Mot de passe incorrect'
|
||||
})
|
||||
}
|
||||
else {
|
||||
const id = result[0].id;
|
||||
// creating a token
|
||||
const token = jwt.sign({ id: id }, process.env.JWT_SECRET, {
|
||||
expiresIn: process.env.JWT_EXPIRES_IN
|
||||
});
|
||||
|
||||
console.log("The token is : " + token);
|
||||
|
||||
// when does our token expires
|
||||
const cookieOptions = {
|
||||
expires: new Date(
|
||||
Date.now() + process.env.JWT_COOKIE_EXPIRES_IN * 24 * 60 * 60 * 1000
|
||||
),
|
||||
// just to prevent if someone is not messing with our cookies
|
||||
httpOnly: true
|
||||
}
|
||||
// we can use any name here in res.cookie(name , token , cookieoptions ) ;
|
||||
// after a user is loged in we put cookie in browser
|
||||
res.cookie('jwt', token, cookieOptions);
|
||||
res.status(200).redirect('/');
|
||||
}
|
||||
})
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
exports.register = (req, res) => {
|
||||
console.log(req.body);
|
||||
|
||||
// de-structuring in javaScript....
|
||||
const { name, email, password } = req.body;
|
||||
|
||||
db.query('SELECT email FROM users WHERE email = ?', [email], async (error, result) => {
|
||||
if (error) {
|
||||
console.log(error);
|
||||
}
|
||||
if (result.length > 0) {
|
||||
return res.render('contains/inscription', {
|
||||
message: 'Cet email est déjà utilisé'
|
||||
})
|
||||
}
|
||||
|
||||
let hashedPassword = await bcrypt.hash(password, 8);
|
||||
|
||||
console.log(hashedPassword);
|
||||
|
||||
db.query('INSERT INTO users SET ?', { name: name, email: email, password: hashedPassword }, (error, result) => {
|
||||
if (error) {
|
||||
console.log(error);
|
||||
}
|
||||
else {
|
||||
console.log(result);
|
||||
|
||||
db.query('SELECT * FROM users WHERE email = ?', [email], async (error, result) => {
|
||||
console.log(result)
|
||||
|
||||
const id = result[0].id;
|
||||
// creating a token
|
||||
const token = jwt.sign({ id: id }, process.env.JWT_SECRET, {
|
||||
expiresIn: process.env.JWT_EXPIRES_IN
|
||||
});
|
||||
|
||||
console.log("The token is : " + token);
|
||||
|
||||
// when does our token expires
|
||||
const cookieOptions = {
|
||||
expires: new Date(
|
||||
Date.now() + process.env.JWT_COOKIE_EXPIRES_IN * 24 * 60 * 60 * 1000
|
||||
),
|
||||
// just to prevent if someone is not messing with our cookies
|
||||
httpOnly: true
|
||||
}
|
||||
// we can use any name here in res.cookie(name , token , cookieoptions ) ;
|
||||
// after a user is loged in we put cookie in browser
|
||||
res.cookie('jwt', token, cookieOptions);
|
||||
res.status(200).redirect('/');
|
||||
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
exports.isLoggedIn = async (req, res, next) => {
|
||||
|
||||
console.log(req.cookies);
|
||||
if (req.cookies.jwt) {
|
||||
try {
|
||||
// step 1 : Verify the token
|
||||
const decoded = await promisify(jwt.verify)(
|
||||
req.cookies.jwt,
|
||||
process.env.JWT_SECRET
|
||||
)
|
||||
|
||||
//console.log(decoded);
|
||||
|
||||
const userId = decoded.id;
|
||||
req.userId = userId;
|
||||
|
||||
// step 2: check if the user still exists
|
||||
db.query('SELECT * FROM users WHERE id = ?', [decoded.id], (error, result) => {
|
||||
console.log(result);
|
||||
|
||||
if (!result) {
|
||||
return next();
|
||||
}
|
||||
req.user = result[0];
|
||||
return next();
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
return next();
|
||||
}
|
||||
}
|
||||
else {
|
||||
next();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
exports.logout = async (req, res) => {
|
||||
res.cookie('jwt', 'déconnecté', {
|
||||
expires: new Date(Date.now() + 2 * 1000),
|
||||
httpOnly: true
|
||||
});
|
||||
res.status(200).redirect('/');
|
||||
}
|
21
app-rappaurio/server/controllers/historiqueController.js
Normal file
@ -0,0 +1,21 @@
|
||||
const mysql = require('mysql');
|
||||
|
||||
// Créez une connexion à la base de données
|
||||
const db = mysql.createConnection({
|
||||
host: process.env.DATABASE_HOST,
|
||||
user: process.env.DATABASE_USER,
|
||||
password: process.env.DATABASE_PASSWORD,
|
||||
database: process.env.DATABASE
|
||||
});
|
||||
|
||||
// Fonction pour récupérer les données depuis la base de données
|
||||
exports.getHistoriqueData = (userId, callback) => {
|
||||
db.query('SELECT * FROM search WHERE id = ? LIMIT 50', [userId], (error, results) => {
|
||||
if (error) {
|
||||
console.error('Erreur lors de la récupération des données depuis la base de données :', error);
|
||||
callback(error, null);
|
||||
} else {
|
||||
callback(null, results);
|
||||
}
|
||||
});
|
||||
};
|
27
app-rappaurio/server/controllers/searchController.js
Normal file
@ -0,0 +1,27 @@
|
||||
// searchController.js
|
||||
|
||||
const mysql = require('mysql');
|
||||
|
||||
// Créez une connexion à la base de données
|
||||
const db = mysql.createConnection({
|
||||
host: process.env.DATABASE_HOST,
|
||||
user: process.env.DATABASE_USER,
|
||||
password: process.env.DATABASE_PASSWORD,
|
||||
database: process.env.DATABASE
|
||||
});
|
||||
|
||||
// Fonction pour insérer les données de recherche dans la base de données
|
||||
exports.insertSearchData = (userId, articleTitle1, articleTitle2, callback) => {
|
||||
db.query('INSERT INTO search (id, article1, article2) VALUES (?, ?, ?)', [userId, articleTitle1, articleTitle2], (error, result) => {
|
||||
if (error) {
|
||||
console.error('Erreur lors de l\'insertion des données dans la base de données :', error);
|
||||
// Vous pouvez gérer l'erreur en appelant le callback avec l'erreur
|
||||
callback(error, null);
|
||||
} else {
|
||||
// Les données ont été insérées avec succès
|
||||
console.log('Données insérées avec succès dans la base de données.');
|
||||
// Appelez le callback avec succès
|
||||
callback(null, result);
|
||||
}
|
||||
});
|
||||
};
|
165
app-rappaurio/server/functions/compare.js
Normal file
@ -0,0 +1,165 @@
|
||||
const Wikiapi = require('wikiapi');
|
||||
const wiki = new Wikiapi('fr');
|
||||
const axios = require('axios');
|
||||
|
||||
|
||||
// == Functions
|
||||
|
||||
// Fonction de nettoyage personnalisée (pour infobox)
|
||||
function cleanInfoboxText(text) {
|
||||
// Supprimer les balises HTML
|
||||
const cleanedText = text.replace(/<\/?[^>]+(>|$)/g, "");
|
||||
|
||||
// Supprimer les caractères '{' et '}'
|
||||
const cleanedTextWithoutBraces = cleanedText.replace(/[{}]/g, "");
|
||||
|
||||
// Supprimer le caractère '|'
|
||||
const cleanedTextWithoutPipe = cleanedTextWithoutBraces.replace(/\|/g, "");
|
||||
|
||||
// Supprimer les caractères '[' et ']'
|
||||
const finalText = cleanedTextWithoutPipe.replace(/[\[\]]/g, "");
|
||||
|
||||
return finalText.trim();
|
||||
}
|
||||
|
||||
// Fonction pour récupérer les informations d'un article depuis l'API MediaWiki
|
||||
async function fetchArticleInfoFromAPI(articleTitle) {
|
||||
try {
|
||||
// Définir les paramètres de la requête pour obtenir les suggestions de titre
|
||||
const suggestionParams = new URLSearchParams({
|
||||
action: 'opensearch',
|
||||
search: articleTitle,
|
||||
format: 'json',
|
||||
});
|
||||
|
||||
// Effectuer la requête GET pour obtenir les suggestions de titre
|
||||
const suggestionResponse = await axios.get(`https://fr.wikipedia.org/w/api.php?${suggestionParams.toString()}`);
|
||||
const suggestionData = suggestionResponse.data;
|
||||
|
||||
// Vérifier s'il y a des suggestions de titre
|
||||
if (Array.isArray(suggestionData[1]) && suggestionData[1].length > 0) {
|
||||
// Utiliser le premier titre suggéré comme titre de l'article
|
||||
articleTitle = suggestionData[1][0];
|
||||
}
|
||||
|
||||
// Répéter la requête pour obtenir les informations de l'article avec le titre corrigé ou suggéré
|
||||
const params = new URLSearchParams({
|
||||
action: 'query',
|
||||
titles: articleTitle,
|
||||
format: 'json',
|
||||
prop: 'extracts|info|revisions|pageimages', // Ajoutez 'pageimages' pour obtenir les informations sur l'image
|
||||
inprop: 'url',
|
||||
explaintext: true,
|
||||
rvprop: 'timestamp|user|size|ids',
|
||||
rvlimit: 1,
|
||||
piprop: 'original', // Spécifiez 'original' pour obtenir l'URL de l'image originale
|
||||
});
|
||||
|
||||
// Effectuer la requête GET à l'API MediaWiki
|
||||
const response = await axios.get(`https://fr.wikipedia.org/w/api.php?${params.toString()}`);
|
||||
const data = response.data;
|
||||
|
||||
// ==== RECHERCHE INFOBOX ====
|
||||
|
||||
let infobox = {};
|
||||
|
||||
// Vérifiez si articleTitle est défini et non vide
|
||||
if (articleTitle) {
|
||||
const page_data = await wiki.page(articleTitle);
|
||||
const parsed = page_data.parse();
|
||||
|
||||
// Filtre des données compliquée à représentée
|
||||
const variablesExclues = ['image', 'blason', 'drapeau', 'logo', 'légende', 'carte', 'légende-carte', '_', 'statut', 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||
|
||||
// Lire les modèles Infobox, les convertir en JSON.
|
||||
parsed.each('template', (template_token) => {
|
||||
if (template_token.name.startsWith('Infobox')) {
|
||||
const parameters = template_token.parameters;
|
||||
for (const key of Object.keys(parameters)) {
|
||||
const value = parameters[key];
|
||||
if (value !== '' && !variablesExclues.some(excluded => key.includes(excluded))) {
|
||||
infobox[key] = cleanInfoboxText(value.toString()); // Appliquer la fonction de nettoyage ici
|
||||
}
|
||||
}
|
||||
return parsed.each.exit;
|
||||
}
|
||||
});
|
||||
|
||||
// Vérifiez si l'infobox est vide
|
||||
if (Object.keys(infobox).length === 0) {
|
||||
console.log("Warning : Pas d'infobox");
|
||||
infobox = {
|
||||
Erreur: "Pas d'infobox sur wikipédia"
|
||||
};
|
||||
}
|
||||
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
|
||||
// Vérifier si 'query' existe dans les données
|
||||
if (data.query) {
|
||||
// Obtenir la première page (il peut y avoir plusieurs résultats, nous prenons le premier)
|
||||
const page = Object.values(data.query.pages)[0];
|
||||
|
||||
if (page.missing !== undefined) {
|
||||
console.log(`Warning : l'article "${articleTitle}" n'a pas été trouvé.`);
|
||||
return null;
|
||||
} else {
|
||||
|
||||
// Fonction pour limiter le texte à 300 caractères et s'arrêter au dernier point
|
||||
function limitTextTo300Chars(text) {
|
||||
if (text.length <= 300) {
|
||||
// Si le texte est déjà inférieur ou égal à 300 caractères, retournez-le tel quel
|
||||
return text;
|
||||
} else {
|
||||
// Trouvez le dernier point dans les 300 premiers caractères
|
||||
const truncatedText = text.substring(0, 300);
|
||||
const lastPeriodIndex = truncatedText.lastIndexOf('.');
|
||||
|
||||
if (lastPeriodIndex !== -1) {
|
||||
// S'il y a un point dans les 300 premiers caractères, coupez le texte jusqu'à ce point
|
||||
return truncatedText.substring(0, lastPeriodIndex + 1);
|
||||
} else {
|
||||
// S'il n'y a pas de point, retournez simplement les 200 premiers caractères
|
||||
return truncatedText;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Extraire les informations
|
||||
const articleInfo = {
|
||||
url: page.fullurl,
|
||||
title: page.title,
|
||||
extract: page.extract ? limitTextTo300Chars(page.extract) : 'Non disponible',
|
||||
lastEdit: page.revisions ? new Date(page.revisions[0].timestamp).toLocaleString() : 'Non disponible',
|
||||
numRevisions: page.revisions ? page.revisions[0].revid : 'Non disponible',
|
||||
pageSize: page.revisions ? page.revisions[0].size : 'Non disponible',
|
||||
firstRevisionUser: page.revisions ? page.revisions[0].user : 'Non disponible',
|
||||
latestRevisionId: page.revisions ? page.revisions[0].revid : 'Non disponible',
|
||||
pageId: page.pageid ? page.pageid : 'Non disponible',
|
||||
latestVersion: page.revisions ? page.revisions[0].parentid : 'Non disponible',
|
||||
wordCount: page.extract ? page.extract.split(/\s+/).length : 'Non disponible',
|
||||
charCount: page.extract ? page.extract.length : 'Non disponible',
|
||||
lastContributor: page.revisions ? page.revisions[0].user : 'Non disponible',
|
||||
image: page.original ? page.original.source : 'Non disponible',
|
||||
infobox,
|
||||
};
|
||||
|
||||
return articleInfo;
|
||||
}
|
||||
} else {
|
||||
console.log(`Warning : l'article "${articleTitle}" n'a pas été trouvé.`);
|
||||
return null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Erreur : lors de la récupération des informations depuis l\'API :', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
fetchArticleInfoFromAPI
|
||||
};
|
14
app-rappaurio/server/routes/auth.js
Normal file
@ -0,0 +1,14 @@
|
||||
const express = require('express');
|
||||
const authController = require('../controllers/auth');
|
||||
const router = express.Router();
|
||||
|
||||
|
||||
|
||||
router.post('/inscription' , authController.register);
|
||||
|
||||
router.post('/connexion' , authController.login);
|
||||
|
||||
router.get('/deconnexion' , authController.logout)
|
||||
|
||||
|
||||
module.exports = router ;
|
83
app-rappaurio/server/routes/index.js
Normal file
@ -0,0 +1,83 @@
|
||||
var express = require('express');
|
||||
const authController = require('../controllers/auth')
|
||||
const searchController = require('../controllers/searchController');
|
||||
const historiqueController = require('../controllers/historiqueController');
|
||||
const { fetchArticleInfoFromAPI } = require('../functions/compare');
|
||||
|
||||
var router = express.Router();
|
||||
|
||||
/* GET home page. */
|
||||
router.get('/', authController.isLoggedIn, (req, res, next) => {
|
||||
res.render('contains/index', { user_details: req.user });
|
||||
});
|
||||
|
||||
|
||||
// inscription page
|
||||
router.get('/inscription', (req, res) => {
|
||||
res.render('contains/inscription')
|
||||
});
|
||||
|
||||
router.get('/connexion', (req, res) => {
|
||||
res.render('contains/connexion')
|
||||
});
|
||||
|
||||
|
||||
router.get('/historique', authController.isLoggedIn, (req, res) => {
|
||||
console.log(req.user);
|
||||
|
||||
if (req.user) {
|
||||
const userId = req.user.id;
|
||||
historiqueController.getHistoriqueData(userId, (error, historiqueData) => {
|
||||
if (error) {
|
||||
console.error('Erreur lors de la récupération des données depuis la base de données :', error);
|
||||
res.status(500).json({ error: 'Une erreur s\'est produite lors de la récupération des données.' });
|
||||
} else {
|
||||
|
||||
res.render('contains/historique', {
|
||||
user_details: req.user,
|
||||
historiqueData: historiqueData
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
res.redirect('/connexion');
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Send search for articles
|
||||
router.post('/search', authController.isLoggedIn, async (req, res) => {
|
||||
try {
|
||||
// Récupérez les données du formulaire depuis req.body
|
||||
const articleTitle1 = req.body.articleTitle1;
|
||||
const articleTitle2 = req.body.articleTitle2;
|
||||
|
||||
// Utilisez la fonction pour récupérer les informations des articles
|
||||
const articleInfo1 = await fetchArticleInfoFromAPI(articleTitle1);
|
||||
const articleInfo2 = await fetchArticleInfoFromAPI(articleTitle2);
|
||||
|
||||
// Récupérez l'ID de l'utilisateur
|
||||
const userId = req.userId;
|
||||
|
||||
// Utilisez la fonction du contrôleur pour insérer les données
|
||||
|
||||
if (userId) {
|
||||
searchController.insertSearchData(userId, articleTitle1, articleTitle2, (error, result) => {
|
||||
if (error) {
|
||||
console.error('Erreur lors de l\'insertion des données dans la base de données :', error);
|
||||
res.status(500).json({ error: 'Une erreur s\'est produite lors de l\'enregistrement des données.' });
|
||||
} else {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Renvoyez la réponse au format JSON
|
||||
res.json({ articleInfo1, articleInfo2 });
|
||||
} catch (error) {
|
||||
console.error('Erreur lors de la recherche d\'informations sur les articles :', error);
|
||||
res.status(500).json({ error: 'Une erreur s\'est produite lors de la recherche d\'informations sur les articles.' });
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
module.exports = router;
|
71
app-rappaurio/views/contains/404.hbs
Normal file
@ -0,0 +1,71 @@
|
||||
|
||||
<section class="relative z-10 pt-[180px] pb-[120px]">
|
||||
<div class="container">
|
||||
<div class="flex flex-wrap mx-[-16px]">
|
||||
<div class="w-full px-4">
|
||||
<div class="max-w-[530px] mx-auto text-center">
|
||||
<div class="mx-auto mb-9 text-center">
|
||||
<svg class="w-full mx-auto text-center" height="210" viewBox="0 0 474 210" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.5"
|
||||
d="M25 163.051H101.211V191H133.308V163.051H153V136.111H133.308V32H91.2871L25 136.577V163.051ZM101.831 136.111H58.8025V134.869L100.591 68.6445H101.831V136.111Z"
|
||||
stroke="url(#paint0_linear_116:1137)" stroke-width="3" />
|
||||
<path opacity="0.5"
|
||||
d="M307 133.051H383.211V161H415.308V133.051H435V106.111H415.308V2H373.287L307 106.577V133.051ZM383.831 106.111H340.803V104.869L382.591 38.6445H383.831V106.111Z"
|
||||
stroke="url(#paint1_linear_116:1137)" stroke-width="3" />
|
||||
<circle opacity="0.8" cx="227.5" cy="81.5" r="68.5" fill="#4A6CF7" />
|
||||
<mask id="mask0_116:1137" style="mask-type: alpha" maskUnits="userSpaceOnUse" x="159"
|
||||
y="13" width="137" height="137">
|
||||
<circle opacity="0.8" cx="227.5" cy="81.5" r="68.5" fill="#4A6CF7" />
|
||||
</mask>
|
||||
<g mask="url(#mask0_116:1137)">
|
||||
<circle opacity="0.8" cx="227.5" cy="81.5" r="68.5"
|
||||
fill="url(#paint2_radial_116:1137)" />
|
||||
<g opacity="0.8" filter="url(#filter0_f_116:1137)">
|
||||
<circle cx="233.543" cy="49.2645" r="28.2059" fill="white" />
|
||||
</g>
|
||||
</g>
|
||||
<defs>
|
||||
<filter id="filter0_f_116:1137" x="175.337" y="-8.94141" width="116.412"
|
||||
height="116.412" filterUnits="userSpaceOnUse"
|
||||
color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix" />
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix"
|
||||
result="shape" />
|
||||
<feGaussianBlur stdDeviation="15" result="effect1_foregroundBlur_116:1137" />
|
||||
</filter>
|
||||
<linearGradient id="paint0_linear_116:1137" x1="25" y1="183" x2="126.155"
|
||||
y2="27.0837" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#4A6CF7" stop-opacity="0" />
|
||||
<stop offset="1" stop-color="#4A6CF7" />
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_116:1137" x1="307" y1="153" x2="408.155"
|
||||
y2="-2.91631" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#4A6CF7" stop-opacity="0" />
|
||||
<stop offset="1" stop-color="#4A6CF7" />
|
||||
</linearGradient>
|
||||
<radialGradient id="paint2_radial_116:1137" cx="0" cy="0" r="1"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(227.5 81.5) rotate(90) scale(73.5368)">
|
||||
<stop stop-opacity="0.47" />
|
||||
<stop offset="1" stop-opacity="0" />
|
||||
</radialGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="font-bold text-black dark:text-white text-3xl sm:text-4xl mb-4">
|
||||
Oups ! La page n'a pas été trouvée.
|
||||
</h3>
|
||||
<p
|
||||
class="font-medium text-body-color text-base sm:text-lg leading-relaxed sm:leading-relaxed mb-10">
|
||||
La page que vous avez demandée peut avoir été déplacée, supprimée ou n'a jamais existé. Vous avez peut-être suivi un lien incorrect ou une URL mal orthographiée.
|
||||
</p>
|
||||
<a href="/" class="text-base font-semibold text-white bg-primary py-4 px-8 hover:bg-opacity-80 mx-2 rounded-md transition duration-300 ease-in-out">
|
||||
page d'accueil
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
90
app-rappaurio/views/contains/connexion.hbs
Normal file
@ -0,0 +1,90 @@
|
||||
<section class="relative overflow-hidden z-10 pt-[180px] pb-[120px]">
|
||||
<div class="container">
|
||||
<div class="flex flex-wrap mx-[-16px]">
|
||||
<div class="w-full px-4">
|
||||
<div class="max-w-[500px] mx-auto bg-dark bg-opacity-15 dark:bg-dark rounded-md p-12 sm:p-[60px]">
|
||||
<h3 class="font-bold text-white dark:text-white text-2xl sm:text-3xl mb-6 text-center">
|
||||
Connexion à votre compte
|
||||
</h3>
|
||||
|
||||
<!--FORMULAIRE-->
|
||||
<form method="POST" action="/auth/connexion">
|
||||
<div class="mb-8">
|
||||
<label for="email" class="block text-sm font-medium text-white dark:text-white mb-3">
|
||||
Email <sup class="text-body-color">*</sup>
|
||||
</label>
|
||||
<input type="email" name="email" id="email" placeholder="Entrer votre email..."
|
||||
required="required"
|
||||
class="w-full border border-transparent bg-primary bg-opacity-10 dark:bg-[#242B51] rounded-md shadow-one dark:shadow-signUp py-3 px-6 text-body-color text-base placeholder-body-color outline-none focus-visible:shadow-none focus:border-primary" />
|
||||
</div>
|
||||
<div class="mb-8">
|
||||
<label for="password" class="block text-sm font-medium text-white dark:text-white mb-3">
|
||||
Mot de passe <sup class="text-body-color">*</sup>
|
||||
</label>
|
||||
<input type="password" name="password" id="password"
|
||||
placeholder="Entrer votre mot de passe..." required="required"
|
||||
class="w-full border border-transparent bg-primary bg-opacity-10 dark:bg-[#242B51] rounded-md shadow-one dark:shadow-signUp py-3 px-6 text-body-color text-base placeholder-body-color outline-none focus-visible:shadow-none focus:border-primary" />
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<sup class="text-body-color">* champs obligatoires</sup>
|
||||
</div>
|
||||
|
||||
<!--CASE COCHER POUR SOUVENIR MDP-->
|
||||
<div class="flex items-center justify-between mb-8">
|
||||
<!--
|
||||
<div>
|
||||
<label for="checkboxLabel"
|
||||
class="flex items-center cursor-pointer text-body-color text-sm font-medium select-none">
|
||||
<div class="relative">
|
||||
<input type="checkbox" id="checkboxLabel" class="sr-only" />
|
||||
<div
|
||||
class="box flex items-center justify-center w-5 h-5 rounded border border-body-color border-opacity-20 dark:border-white dark:border-opacity-10 mr-4">
|
||||
<span class="opacity-0">
|
||||
<svg width="11" height="8" viewBox="0 0 11 8" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M10.0915 0.951972L10.0867 0.946075L10.0813 0.940568C9.90076 0.753564 9.61034 0.753146 9.42927 0.939309L4.16201 6.22962L1.58507 3.63469C1.40401 3.44841 1.11351 3.44879 0.932892 3.63584C0.755703 3.81933 0.755703 4.10875 0.932892 4.29224L0.932878 4.29225L0.934851 4.29424L3.58046 6.95832C3.73676 7.11955 3.94983 7.2 4.1473 7.2C4.36196 7.2 4.55963 7.11773 4.71406 6.9584L10.0468 1.60234C10.2436 1.4199 10.2421 1.1339 10.0915 0.951972ZM4.2327 6.30081L4.2317 6.2998C4.23206 6.30015 4.23237 6.30049 4.23269 6.30082L4.2327 6.30081Z"
|
||||
fill="#3056D3" stroke="#3056D3" stroke-width="0.4" />
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
Rester connecté
|
||||
</label>
|
||||
</div>
|
||||
|
||||
|
||||
<div>
|
||||
<a href="javascript:void(0)" class="text-primary text-sm font-medium hover:underline">
|
||||
Mot de passe oublié? </a>
|
||||
</div>
|
||||
-->
|
||||
|
||||
</div>
|
||||
|
||||
<!--MDP OUBLIER-->
|
||||
<div class="mb-6">
|
||||
<button type="submit"
|
||||
class="w-full flex items-center justify-center text-base font-medium text-white bg-primary py-4 px-9 hover:shadow-signUp hover:bg-opacity-80 transition duration-300 ease-in-out rounded-md">
|
||||
Connexion
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
|
||||
|
||||
<p class="font-medium text-base text-body-color text-center">
|
||||
Vous n'avez pas de compte?
|
||||
<a href="/inscription" class="text-primary hover:underline"> Inscription </a>
|
||||
</p>
|
||||
|
||||
{{#if message }}
|
||||
<h4 class="text-center mt-6 border text-alert px-4 py-3 rounded relative">{{message}}</h4>
|
||||
{{/if}}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
34
app-rappaurio/views/contains/historique.hbs
Normal file
@ -0,0 +1,34 @@
|
||||
<section id="home"
|
||||
class="relative overflow-hidden z-10 pt-[120px] pb-[110px] md:pt-[150px] md:pb-[120px] xl:pt-[180px] xl:pb-[160px] 2xl:pt-[210px] 2xl:pb-[200px]">
|
||||
<div class="container">
|
||||
<div class="flex flex-wrap mx-[-16px]">
|
||||
<div class="w-full px-4">
|
||||
|
||||
|
||||
<table class="text-center">
|
||||
|
||||
<!-- Statistiques -->
|
||||
|
||||
|
||||
<tr>
|
||||
<th>Article 1</th>
|
||||
<th>Article 2</th>
|
||||
|
||||
</tr>
|
||||
|
||||
<tbody>
|
||||
{{#each historiqueData }}
|
||||
<tr>
|
||||
<td>{{this.article1}}</td>
|
||||
<td>{{this.article2}}</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
455
app-rappaurio/views/contains/index.hbs
Normal file
@ -0,0 +1,455 @@
|
||||
<!--BIENVENUE-->
|
||||
|
||||
<section id="home"
|
||||
class="relative overflow-hidden z-10 pt-[120px] pb-[110px] md:pt-[150px] md:pb-[120px] xl:pt-[180px] xl:pb-[160px] 2xl:pt-[210px] 2xl:pb-[200px]">
|
||||
<div class="container">
|
||||
<div class="flex flex-wrap mx-[-16px]">
|
||||
<div class="w-full px-4">
|
||||
<div class="mx-auto max-w-[570px] text-center wow fadeInUp" data-wow-delay=".2s">
|
||||
<h1
|
||||
class="text-black dark:text-white font-bold text-3xl sm:text-4xl md:text-5xl leading-tight sm:leading-tight md:leading-tight mb-8">
|
||||
Comparateur d'articles Wikipédia
|
||||
</h1>
|
||||
<img src="/images/wikipedia.png" alt="logo wikipedia" width="150"
|
||||
class="mx-auto mb-8 dark:hidden" />
|
||||
<img src="/images/wikipedia-dark.png" alt="logo wikipedia" width="150"
|
||||
class="mx-auto mb-8 hidden dark:block" />
|
||||
<p
|
||||
class="font-lg text-lg md:text-xl leading-relaxed md:leading-relaxed text-body-color dark:text-white dark:opacity-90 mb-12">
|
||||
Bienvenue sur notre outil de comparaison d'articles Wikipédia ! Cet outil permet de comparer les
|
||||
données contenues dans les infoboîtes ainsi que les statistiques liées aux utilisateurs tels que
|
||||
les
|
||||
vues et le nombre de contributions.
|
||||
</p>
|
||||
<div class="flex items-center justify-center">
|
||||
<a href="/#comparaison" id="letzgooo"
|
||||
class="text-base font-semibold text-white bg-primary py-4 px-8 hover:bg-opacity-80 mx-2 rounded-md transition duration-300 ease-in-out">
|
||||
C'est parti !
|
||||
</a>
|
||||
<!--
|
||||
<a href="/#savoir-plus"
|
||||
class="text-base font-semibold text-black bg-black bg-opacity-10 dark:text-white dark:bg-white dark:bg-opacity-10 py-4 px-8 hover:bg-opacity-20 dark:hover:bg-opacity-20 mx-2 rounded-md transition duration-300 ease-in-out">
|
||||
En savoir plus
|
||||
</a>
|
||||
-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
<!--COMPARAISON DES SITES-->
|
||||
|
||||
<section id="comparaison" class="pt-[120px] overflow-hidden">
|
||||
|
||||
<!--ENVOYER LA COMPARAISON-->
|
||||
<div class="container">
|
||||
<div class="flex flex-wrap mx-[-16px]">
|
||||
<div class="w-full px-4">
|
||||
<div class="bg-dark bg-opacity-15 dark:text-white dark:bg-dark rounded-md p-11 mb-4 lg:mb-5 sm:p-[55px] lg:p-11 xl:p-[55px] wow fadeInUp"
|
||||
data-wow-delay=".15s">
|
||||
|
||||
<h2
|
||||
class="font-bold text-white dark:text-white text-2xl sm:text-3xl lg:text-2xl xl:text-3xl mb-6 flex items-center justify-center">
|
||||
Articles à Comparer
|
||||
</h2>
|
||||
<p class="text-body-color text-base font-medium mb-16 flex items-center justify-center">
|
||||
Completer les champs suivant :
|
||||
</p>
|
||||
|
||||
<!--FORMULAIRE-->
|
||||
<form id="formulaire-comp" method="POST" autocomplete="off">
|
||||
<div class="flex flex-wrap mx-[-16px] p-10">
|
||||
<div class="w-full md:w-1/2 px-4">
|
||||
<div class="mb-8">
|
||||
<label for="name" class="block text-sm font-medium text-white dark:text-white mb-3">
|
||||
Premier article <sup class="text-body-color">*</sup>
|
||||
</label>
|
||||
|
||||
<input type="text" name="articleTitle1" id="articleTitle1" required="required"
|
||||
autocomplete="new-password" placeholder="Rechercher un article..."
|
||||
class="w-full border border-transparent bg-primary bg-opacity-10 dark:bg-[#242B51] rounded-md shadow-one dark:shadow-signUp py-3 px-6 text-body-color text-base placeholder-body-color outline-none focus-visible:shadow-none focus:border-primary" />
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-full mb-8 md:w-1/2 px-4">
|
||||
<div class="mb-8 ">
|
||||
<label for="text" class="block text-sm font-medium text-white dark:text-white mb-3">
|
||||
Deuxième article <sup class="text-body-color">*</sup>
|
||||
</label>
|
||||
<input type="text" name="articleTitle2" id="articleTitle2" required="required"
|
||||
autocomplete="new-password" placeholder="Rechercher un article..."
|
||||
class="w-full border border-transparent bg-primary bg-opacity-10 dark:bg-[#242B51] rounded-md shadow-one dark:shadow-signUp py-3 px-6 text-body-color text-base placeholder-body-color outline-none focus-visible:shadow-none focus:border-primary " />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="w-full px-4 flex items-center justify-center">
|
||||
<button id="lance-comparaison" type="submit"
|
||||
class="text-base mb-16 font-medium text-white bg-primary py-4 px-9 hover:bg-opacity-80 hover:shadow-signUp rounded-md transition duration-300 ease-in-out">
|
||||
Comparer
|
||||
</button>
|
||||
</div>
|
||||
<sup class="text-body-color">* champs obligatoires</sup>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!--RESULTAT RECHERCHE-->
|
||||
<section id="resultat" class="pt-[120px] pb-[120px]">
|
||||
<div class="container">
|
||||
<div class="flex flex-wrap mx-[-16px] justify-center">
|
||||
|
||||
<!--ANNIMATION CHAREMENT-->
|
||||
<div id="loading" class="hidden">
|
||||
<div class="loadingio-spinner-dual-ring-4e7xs5jqq4d">
|
||||
<div class="ldio-jzq166pp4c">
|
||||
<div></div>
|
||||
<div>
|
||||
<div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--RESULTAT INTROUVABLE-->
|
||||
<div id="articleIntrouvable"
|
||||
class="hidden font-lg text-lg md:text-xl leading-relaxed md:leading-relaxed text-body-color dark:text-white dark:opacity-90 mb-12 text-center">
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!--Article 1-->
|
||||
|
||||
<div id="articleContainer1" class="w-full md:w-2/3 lg:w-1/2 xl:w-2/4 px-4 hidden">
|
||||
<div class="relative bg-dark bg-opacity-15 text-white dark:text-white dark:bg-dark shadow-one rounded-md overflow-hidden mb-10 wow fadeInUp"
|
||||
data-wow-delay=".1s">
|
||||
|
||||
<div class="p-6 sm:p-8 md:py-8 md:px-6 lg:p-8 xl:py-8 xl:px-5 2xl:p-8 mb-12 pb-4">
|
||||
<div
|
||||
class="mb-12 pb-8 border-b border-body-color border-opacity-5 dark:border-white dark:border-opacity-10">
|
||||
<h3 class="font-bold text-white dark:text-white text-xl sm:text-2xl block mb-6">
|
||||
<span id="articleInfo1Title"></span>
|
||||
</h3>
|
||||
<p id="articleInfo1extract" class="pb-8"></p>
|
||||
|
||||
<div class="flex items-center justify-center">
|
||||
<a id="articleInfo1url" href="#" target="_blank"
|
||||
class="text-base font-semibold bg-opacity-10 text-white bg-white py-4 px-8 hover:bg-opacity-20 mx-2 rounded-md transition duration-300 ease-in-out">
|
||||
Voir l'article (wiki)
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<table>
|
||||
<!-- Infobox -->
|
||||
<tr>
|
||||
<th style="background-color: #151b20; text-align:center; padding: 12px;"
|
||||
colspan="2">INFOBOX</th>
|
||||
</tr>
|
||||
|
||||
<tbody id="infoboxcontainer1"></tbody>
|
||||
|
||||
<!-- Statistiques -->
|
||||
<tr>
|
||||
<th style="background-color: #151b20 ; text-align:center; padding: 12px;"
|
||||
colspan="2">STATISTIQUES</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Dernière modification</th>
|
||||
<td><span id="articleInfo1lastEdit"></span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Nombre de révisions</th>
|
||||
<td><span id="articleInfo1numRevisions"></span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Taille de la page</th>
|
||||
<td><span id="articleInfo1pageSize"></span> octets</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Auteur de la première révision</th>
|
||||
<td><span id="articleInfo1firstRevisionUser"></span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>ID de la dernière révision</th>
|
||||
<td><span id="articleInfo1latestRevisionId"></span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>ID de la page</th>
|
||||
<td><span id="articleInfo1pageId"></span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Dernière version</th>
|
||||
<td><span id="articleInfo1latestVersion"></span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Nombre de mots</th>
|
||||
<td><span id="articleInfo1wordCount"></span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Nombre de caractères</th>
|
||||
<td><span id="articleInfo1charCount"></span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Dernier contributeur</th>
|
||||
<td><span id="articleInfo1lastContributor"></span></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
<a id="articleInfo1image" href="#" class="w-full block relative" target="_blank">
|
||||
<img id="articleInfo1image" src="#" alt="image" class="w-full" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--Article 2-->
|
||||
|
||||
<div id="articleContainer2" class="w-full md:w-2/3 lg:w-1/2 xl:w-2/4 px-4 hidden">
|
||||
<div class="relative bg-dark bg-opacity-15 text-white dark:text-white dark:bg-dark shadow-one rounded-md overflow-hidden mb-10 wow fadeInUp"
|
||||
data-wow-delay=".1s">
|
||||
|
||||
<div class="p-6 sm:p-8 md:py-8 md:px-6 lg:p-8 xl:py-8 xl:px-5 2xl:p-8 mb-12 pb-4">
|
||||
<div
|
||||
class="mb-12 pb-8 border-b border-body-color border-opacity-5 dark:border-white dark:border-opacity-10">
|
||||
<h3>
|
||||
<h3 class="font-bold text-white dark:text-white text-xl sm:text-2xl block mb-6">
|
||||
<span id="articleInfo2Title"></span>
|
||||
</h3>
|
||||
</h3>
|
||||
<p id="articleInfo2extract" class="pb-8"></p>
|
||||
<div class="flex items-center justify-center">
|
||||
<a id="articleInfo2url" href="#" target="_blank"
|
||||
class="text-base font-semibold bg-opacity-10 text-white bg-white py-4 px-8 hover:bg-opacity-20 mx-2 rounded-md transition duration-300 ease-in-out">
|
||||
Voir l'article (wiki)
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<table>
|
||||
<!-- Infobox -->
|
||||
<tr>
|
||||
<th style="background-color: #151b20; text-align:center; padding: 12px;"
|
||||
colspan="2">INFOBOX</th>
|
||||
</tr>
|
||||
|
||||
<tbody id="infoboxcontainer2"></tbody>
|
||||
|
||||
<!-- Statistiques -->
|
||||
<tr>
|
||||
<th style="background-color: #151b20 ; text-align:center; padding: 12px;"
|
||||
colspan="2">STATISTIQUES</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Dernière modification</th>
|
||||
<td><span id="articleInfo2lastEdit"></span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Nombre de révisions</th>
|
||||
<td><span id="articleInfo2numRevisions"></span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Taille de la page</th>
|
||||
<td><span id="articleInfo2pageSize"></span> octets</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Auteur de la première révision</th>
|
||||
<td><span id="articleInfo2firstRevisionUser"></span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>ID de la dernière révision</th>
|
||||
<td><span id="articleInfo2latestRevisionId"></span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>ID de la page</th>
|
||||
<td><span id="articleInfo2pageId"></span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Dernière version</th>
|
||||
<td><span id="articleInfo2latestVersion"></span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Nombre de mots</th>
|
||||
<td><span id="articleInfo2wordCount"></span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Nombre de caractères</th>
|
||||
<td><span id="articleInfo2charCount"></span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Dernier contributeur</th>
|
||||
<td><span id="articleInfo2lastContributor"></span></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
<a id="articleInfo2image" href="#" class="w-full block relative" target="_blank">
|
||||
<img id="articleInfo2image" src="#" alt="image" class="w-full" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</section>
|
||||
|
||||
<!--EN SAVOIR PLUS-->
|
||||
|
||||
<!--
|
||||
<section id="savoir-plus" class="pt-[150px] pb-[120px]">
|
||||
<div class="container">
|
||||
<div class="flex flex-wrap justify-center mx-[-16px]">
|
||||
<div class="w-full lg:w-8/12 px-4">
|
||||
<div>
|
||||
<h2
|
||||
class="font-bold text-black dark:text-white text-3xl sm:text-4xl leading-tight sm:leading-tight mb-12 pb-4 border-b border-body-color border-opacity-5 dark:border-white dark:border-opacity-10">
|
||||
En savoir plus
|
||||
</h2>
|
||||
|
||||
<div>
|
||||
<p
|
||||
class="font-medium text-body-color text-base sm:text-lg lg:text-base xl:text-lg sm:leading-relaxed lg:leading-relaxed xl:leading-relaxed leading-relaxed mb-10">
|
||||
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat
|
||||
nulla pariatur.
|
||||
Excepteur sint occaecat cupidatat.
|
||||
</p>
|
||||
<div class="w-full rounded overflow-hidden mb-10">
|
||||
<img src="/images/blog-details-02.jpg" alt="image"
|
||||
class="w-full h-full object-cover object-center" />
|
||||
</div>
|
||||
<p
|
||||
class="font-medium text-body-color text-base sm:text-lg lg:text-base xl:text-lg sm:leading-relaxed lg:leading-relaxed xl:leading-relaxed leading-relaxed mb-8">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
|
||||
incididunt ut labore et
|
||||
dolore magna aliqua. Quis enim lobortis scelerisque fermentum. Neque sodales ut
|
||||
etiam sit amet. Ligula ullamcorper
|
||||
<strong class="text-primary dark:text-white"> malesuada </strong>
|
||||
proin libero nunc consequat interdum varius. Quam pellentesque nec nam aliquam sem et
|
||||
tortor consequat.
|
||||
Pellentesque adipiscing commodo elit at imperdiet.
|
||||
</p>
|
||||
<p
|
||||
class="font-medium text-body-color text-base sm:text-lg lg:text-base xl:text-lg sm:leading-relaxed lg:leading-relaxed xl:leading-relaxed leading-relaxed mb-10">
|
||||
Semper auctor neque vitae tempus quam pellentesque nec.
|
||||
<span class="text-primary dark:text-white underline"> Amet dictum sit amet justo </span>
|
||||
donec enim diam. Varius sit amet mattis vulputate enim nulla aliquet porttitor. Odio
|
||||
pellentesque diam
|
||||
volutpat commodo sed.
|
||||
</p>
|
||||
<h3
|
||||
class="font-bold text-black dark:text-white font-xl sm:text-2xl lg:text-xl xl:text-2xl leading-tight sm:leading-tight lg:leading-tight xl:leading-tight mb-10">
|
||||
Digital marketplace for Ui/Ux designers.
|
||||
</h3>
|
||||
<p
|
||||
class="font-medium text-body-color text-base sm:text-lg lg:text-base xl:text-lg sm:leading-relaxed lg:leading-relaxed xl:leading-relaxed leading-relaxed mb-10">
|
||||
consectetur adipiscing elit in voluptate velit esse cillum dolore eu fugiat nulla
|
||||
pariatur. Excepteur
|
||||
sint occaecat mattis vulputate cupidatat.
|
||||
</p>
|
||||
<ul class="list-disc list-inside text-body-color mb-10">
|
||||
<li class="font-medium text-body-color text-base sm:text-lg lg:text-base xl:text-lg mb-2">
|
||||
Consectetur
|
||||
adipiscing elit in voluptate velit.</li>
|
||||
<li class="font-medium text-body-color text-base sm:text-lg lg:text-base xl:text-lg mb-2">
|
||||
Mattis
|
||||
vulputate cupidatat.</li>
|
||||
<li class="font-medium text-body-color text-base sm:text-lg lg:text-base xl:text-lg mb-2">
|
||||
Vulputate enim
|
||||
nulla aliquet porttitor odio pellentesque</li>
|
||||
<li class="font-medium text-body-color text-base sm:text-lg lg:text-base xl:text-lg mb-2">
|
||||
Ligula
|
||||
ullamcorper malesuada proin</li>
|
||||
</ul>
|
||||
<div
|
||||
class="rounded-md overflow-hidden p-8 md:p-9 lg:p-8 xl:p-9 bg-black bg-opacity-10 dark:text-white dark:bg-dark relative z-10 mb-10">
|
||||
<p class="text-center text-base text-body-color italic font-medium">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod incididunt
|
||||
utionals labore et
|
||||
dolore magna aliqua. Quis lobortis scelerisque fermentum, The Neque ut etiam
|
||||
sit amet.
|
||||
</p>
|
||||
</div>
|
||||
<p
|
||||
class="font-medium text-body-color text-base sm:text-lg lg:text-base xl:text-lg sm:leading-relaxed lg:leading-relaxed xl:leading-relaxed leading-relaxed mb-10">
|
||||
consectetur adipiscing elit in voluptate velit esse cillum dolore eu fugiat nulla
|
||||
pariatur. Excepteur
|
||||
sint occaecat mattis vulputate cupidatat.
|
||||
</p>
|
||||
|
||||
|
||||
<div
|
||||
class="sm:flex items-center justify-between py-6 border-t border-body-color border-opacity-5 dark:border-white dark:border-opacity-10">
|
||||
<div class="mb-5">
|
||||
<h5 class="font-medium text-body-color text-sm mb-3">
|
||||
Nous contacter :
|
||||
</h5>
|
||||
<div class="flex items-center">
|
||||
<a href="mailto:contact@dariow.fr" target="_blank"
|
||||
class="inline-flex items-center justify-center py-2 px-4 mr-4 rounded-md text-black bg-black bg-opacity-10 dark:text-white dark:bg-white dark:bg-opacity-10 hover:bg-opacity-20 dark:hover:bg-opacity-20 transition duration-300 ease-in-out">
|
||||
Dario WEINBERGER
|
||||
</a>
|
||||
|
||||
<a href="mailto:raphael.alexis.payet@gmail.com"
|
||||
class="inline-flex items-center justify-center py-2 px-4 mr-4 rounded-md text-black bg-black bg-opacity-10 dark:text-white dark:bg-white dark:bg-opacity-10 hover:bg-opacity-20 dark:hover:bg-opacity-20 transition duration-300 ease-in-out">
|
||||
Raphael PAYET
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-5">
|
||||
<h5 class="font-medium text-body-color text-sm sm:text-right mb-3">
|
||||
Code source du projet :
|
||||
</h5>
|
||||
<div class="flex items-center sm:justify-end">
|
||||
<a href="#gitea" target="_blank"
|
||||
class="inline-flex items-center justify-center w-9 h-9 sm:ml-3 rounded-md text-black bg-black bg-opacity-10 dark:text-white dark:bg-white dark:bg-opacity-10 hover:bg-opacity-20 dark:hover:bg-opacity-20 transition duration-300 ease-in-out">
|
||||
<svg version="1.1" id="main_outline" xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 640 640"
|
||||
style="enable-background:new 0 0 640 640; width: 28px;"
|
||||
xml:space="preserve">
|
||||
<g>
|
||||
<path id="teabag" style="fill:#FFFFFF"
|
||||
d="M395.9,484.2l-126.9-61c-12.5-6-17.9-21.2-11.8-33.8l61-126.9c6-12.5,21.2-17.9,33.8-11.8 c17.2,8.3,27.1,13,27.1,13l-0.1-109.2l16.7-0.1l0.1,117.1c0,0,57.4,24.2,83.1,40.1c3.7,2.3,10.2,6.8,12.9,14.4 c2.1,6.1,2,13.1-1,19.3l-61,126.9C423.6,484.9,408.4,490.3,395.9,484.2z" />
|
||||
<g>
|
||||
<g>
|
||||
<path style="fill:#609926"
|
||||
d="M622.7,149.8c-4.1-4.1-9.6-4-9.6-4s-117.2,6.6-177.9,8c-13.3,0.3-26.5,0.6-39.6,0.7c0,39.1,0,78.2,0,117.2 c-5.5-2.6-11.1-5.3-16.6-7.9c0-36.4-0.1-109.2-0.1-109.2c-29,0.4-89.2-2.2-89.2-2.2s-141.4-7.1-156.8-8.5 c-9.8-0.6-22.5-2.1-39,1.5c-8.7,1.8-33.5,7.4-53.8,26.9C-4.9,212.4,6.6,276.2,8,285.8c1.7,11.7,6.9,44.2,31.7,72.5 c45.8,56.1,144.4,54.8,144.4,54.8s12.1,28.9,30.6,55.5c25,33.1,50.7,58.9,75.7,62c63,0,188.9-0.1,188.9-0.1s12,0.1,28.3-10.3 c14-8.5,26.5-23.4,26.5-23.4s12.9-13.8,30.9-45.3c5.5-9.7,10.1-19.1,14.1-28c0,0,55.2-117.1,55.2-231.1 C633.2,157.9,624.7,151.8,622.7,149.8z M125.6,353.9c-25.9-8.5-36.9-18.7-36.9-18.7S69.6,321.8,60,295.4 c-16.5-44.2-1.4-71.2-1.4-71.2s8.4-22.5,38.5-30c13.8-3.7,31-3.1,31-3.1s7.1,59.4,15.7,94.2c7.2,29.2,24.8,77.7,24.8,77.7 S142.5,359.9,125.6,353.9z M425.9,461.5c0,0-6.1,14.5-19.6,15.4c-5.8,0.4-10.3-1.2-10.3-1.2s-0.3-0.1-5.3-2.1l-112.9-55 c0,0-10.9-5.7-12.8-15.6c-2.2-8.1,2.7-18.1,2.7-18.1L322,273c0,0,4.8-9.7,12.2-13c0.6-0.3,2.3-1,4.5-1.5c8.1-2.1,18,2.8,18,2.8 l110.7,53.7c0,0,12.6,5.7,15.3,16.2c1.9,7.4-0.5,14-1.8,17.2C474.6,363.8,425.9,461.5,425.9,461.5z" />
|
||||
<path style="fill:#609926"
|
||||
d="M326.8,380.1c-8.2,0.1-15.4,5.8-17.3,13.8c-1.9,8,2.0,16.3,9.1,20c7.7,4,17.5,1.8,22.7-5.4 c5.1-7.1,4.3-16.9-1.8-23.1l24-49.1c1.5,0.1,3.7,0.2,6.2-0.5c4.1-0.9,7.1-3.6,7.1-3.6c4.2,1.8,8.6,3.8,13.2,6.1 c4.8,2.4,9.3,4.9,13.4,7.3c0.9,0.5,1.8,1.1,2.8,1.9c1.6,1.3,3.4,3.1,4.7,5.5c1.9,5.5-1.9,14.9-1.9,14.9 c-2.3,7.6-18.4,40.6-18.4,40.6c-8.1-0.2-15.3,5-17.7,12.5c-2.6,8.1,1.1,17.3,8.9,21.3c7.8,4,17.4,1.7,22.5-5.3 c5.0-6.8,4.6-16.3-1.1-22.6c1.9-3.7,3.7-7.4,5.6-11.3c5-10.4,13.5-30.4,13.5-30.4c0.9-1.7,5.7-10.3,2.7-21.3 c-2.5-11.4-12.6-16.7-12.6-16.7c-12.2-7.9-29.2-15.2-29.2-15.2s0-4.1-1.1-7.1c-1.1-3.1-2.8-5.1-3.9-6.3c4.7-9.7,9.4-19.3,14.1-29 c-4.1-2-8.1-4-12.2-6.1c-4.8,9.8-9.7,19.7-14.5,29.5c-6.7-0.1-12.9,3.5-16.1,9.4c-3.4,6.3-2.7,14.1,1.9,19.8 C343.2,346.5,335,363.3,326.8,380.1z" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
-->
|
94
app-rappaurio/views/contains/inscription.hbs
Normal file
@ -0,0 +1,94 @@
|
||||
<section class="relative overflow-hidden z-10 pt-[180px] pb-[120px]">
|
||||
<div class="container">
|
||||
<div class="flex flex-wrap mx-[-16px]">
|
||||
<div class="w-full px-4">
|
||||
<div class="max-w-[500px] mx-auto bg-dark bg-opacity-15 dark:bg-dark rounded-md p-12 sm:p-[60px]">
|
||||
<h3 class="font-bold text-white dark:text-white text-2xl mb-6 sm:text-3xl text-center">
|
||||
Créez votre compte
|
||||
</h3>
|
||||
<form method="POST" action="/auth/inscription">
|
||||
<div class="mb-8">
|
||||
<label for="name" class="block text-sm font-medium text-white dark:text-white mb-3">
|
||||
Nom <sup class="text-body-color">*</sup>
|
||||
</label>
|
||||
<input type="text" name="name" id="name" placeholder="Entrer votre nom..."
|
||||
required="required"
|
||||
class="w-full border border-transparent bg-primary bg-opacity-10 dark:bg-[#242B51] rounded-md shadow-one dark:shadow-signUp py-3 px-6 text-body-color text-base placeholder-body-color outline-none focus-visible:shadow-none focus:border-primary" />
|
||||
</div>
|
||||
<div class="mb-8">
|
||||
<label for="email" class="block text-sm font-medium text-white dark:text-white mb-3">
|
||||
Email <sup class="text-body-color">*</sup>
|
||||
</label>
|
||||
<input type="email" name="email" id="email" placeholder="Entrer votre Email..."
|
||||
required="required"
|
||||
class="w-full border border-transparent bg-primary bg-opacity-10 dark:bg-[#242B51] rounded-md shadow-one dark:shadow-signUp py-3 px-6 text-body-color text-base placeholder-body-color outline-none focus-visible:shadow-none focus:border-primary" />
|
||||
</div>
|
||||
<div class="mb-12">
|
||||
<label for="password" class="block text-sm font-medium text-white dark:text-white mb-3">
|
||||
Mot de passe <sup class="text-body-color">*</sup>
|
||||
</label>
|
||||
<input type="password" name="password" id="password"
|
||||
placeholder="Entrer votre mot de passe..." required="required"
|
||||
class="w-full border border-transparent bg-primary bg-opacity-10 dark:bg-[#242B51] rounded-md shadow-one dark:shadow-signUp py-3 px-6 text-body-color text-base placeholder-body-color outline-none focus-visible:shadow-none focus:border-primary" />
|
||||
</div>
|
||||
|
||||
<div class="mb-8">
|
||||
<sup class="text-body-color">* champs obligatoires</sup>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<!-- CONDITIONS D'UTILISATION
|
||||
|
||||
<div class="flex mb-8">
|
||||
<label for="checkboxLabel"
|
||||
class="flex cursor-pointer text-body-color text-sm font-medium select-none">
|
||||
<div class="relative">
|
||||
<input type="checkbox" id="checkboxLabel" class="sr-only" />
|
||||
<div
|
||||
class="box flex items-center justify-center w-5 h-5 rounded border border-body-color border-opacity-20 dark:border-white dark:border-opacity-10 mr-4 mt-1">
|
||||
<span class="opacity-0">
|
||||
<svg width="11" height="8" viewBox="0 0 11 8" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M10.0915 0.951972L10.0867 0.946075L10.0813 0.940568C9.90076 0.753564 9.61034 0.753146 9.42927 0.939309L4.16201 6.22962L1.58507 3.63469C1.40401 3.44841 1.11351 3.44879 0.932892 3.63584C0.755703 3.81933 0.755703 4.10875 0.932892 4.29224L0.932878 4.29225L0.934851 4.29424L3.58046 6.95832C3.73676 7.11955 3.94983 7.2 4.1473 7.2C4.36196 7.2 4.55963 7.11773 4.71406 6.9584L10.0468 1.60234C10.2436 1.4199 10.2421 1.1339 10.0915 0.951972ZM4.2327 6.30081L4.2317 6.2998C4.23206 6.30015 4.23237 6.30049 4.23269 6.30082L4.2327 6.30081Z"
|
||||
fill="#3056D3" stroke="#3056D3" stroke-width="0.4" />
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<span>
|
||||
By creating account means you agree to the
|
||||
<a href="javascript:void(0)" class="text-primary hover:underline"> Terms and
|
||||
Conditions </a>
|
||||
, and our
|
||||
<a href="javascript:void(0)" class="text-primary hover:underline"> Privacy
|
||||
Policy </a>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
-->
|
||||
|
||||
<div class="mb-6">
|
||||
<button type="submit"
|
||||
class="w-full flex items-center justify-center text-base font-medium text-white bg-primary py-4 px-9 hover:shadow-signUp hover:bg-opacity-80 transition duration-300 ease-in-out rounded-md">
|
||||
Inscription
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
<p class="font-medium text-base text-body-color text-center">
|
||||
Déjà un compte?
|
||||
<a href="/connexion" class="text-primary hover:underline"> Connexion </a>
|
||||
</p>
|
||||
|
||||
{{#if message }}
|
||||
<h4 class="text-center mt-6 border text-alert px-4 py-3 rounded relative">{{message}}</h4>
|
||||
{{/if}}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
202
app-rappaurio/views/layout.hbs
Normal file
@ -0,0 +1,202 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr" class="{{ theme }}">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="title" content="Rappaurio | Projet Universitaire" />
|
||||
<meta name="darkreader-lock">
|
||||
<title>Rappaurio - Wiki</title>
|
||||
<link rel="icon" href="/images/icon.png">
|
||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
||||
<link href="/stylesheets/style.css" rel="stylesheet">
|
||||
|
||||
</head>
|
||||
|
||||
<body class="dark:bg-black">
|
||||
|
||||
|
||||
<!--BAR DE NAVIGATION-->
|
||||
|
||||
<header class="header bg-primary bg-opacity-5 bg-transparent absolute top-0 left-0 z-40 w-full flex items-center">
|
||||
<div class="container">
|
||||
<div class="flex mx-[-16px] items-center justify-between relative">
|
||||
<div class="px-4 w-60 max-w-full">
|
||||
<a href="/" class="w-full block py-8 header-logo">
|
||||
<img src="/images/logo-2.svg" alt="logo" class="w-full dark:hidden" />
|
||||
<img src="/images/logo.svg" alt="logo" class="w-full hidden dark:block" />
|
||||
</a>
|
||||
</div>
|
||||
<div class="flex px-4 justify-between items-center w-full">
|
||||
<div>
|
||||
<button id="navbarToggler" aria-label="Mobile Menu"
|
||||
class="block absolute right-4 top-1/2 translate-y-[-50%] lg:hidden focus:ring-2 ring-primary px-3 py-[6px] rounded-lg">
|
||||
<span class="relative w-[30px] h-[2px] my-[6px] block bg-dark dark:bg-white"></span>
|
||||
<span class="relative w-[30px] h-[2px] my-[6px] block bg-dark dark:bg-white"></span>
|
||||
<span class="relative w-[30px] h-[2px] my-[6px] block bg-dark dark:bg-white"></span>
|
||||
</button>
|
||||
<nav id="navbarCollapse"
|
||||
class="absolute py-5 lg:py-0 lg:px-4 xl:px-6 bg-white dark:bg-dark lg:dark:bg-transparent lg:bg-transparent shadow-lg rounded-lg max-w-[250px] w-full lg:max-w-full lg:w-full right-4 top-full hidden lg:block lg:static lg:shadow-none">
|
||||
|
||||
<ul class="block lg:flex">
|
||||
|
||||
{{#if user_details }}
|
||||
|
||||
<li class="relative group">
|
||||
<a href="/historique"
|
||||
class="text-base text-dark dark:text-white group-hover:opacity-70 py-2 lg:py-6 lg:inline-flex lg:px-0 flex mx-8 lg:mr-0">
|
||||
Historique
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="relative group submenu-item">
|
||||
<a href="javascript:void(0)"
|
||||
class="text-base text-dark dark:text-white group-hover:opacity-70 py-2 lg:py-6 lg:inline-flex lg:pl-0 lg:pr-4 flex mx-8 lg:mr-0 lg:ml-8 xl:ml-12 relative after:absolute after:w-2 after:h-2 after:border-b-2 after:border-r-2 after:border-current after:rotate-45 lg:after:right-0 after:right-1 after:top-1/2 after:translate-y-[-50%] after:mt-[-2px]">
|
||||
Contact
|
||||
</a>
|
||||
<div
|
||||
class="submenu hidden relative lg:absolute w-[250px] top-full lg:top-[110%] left-0 rounded-md lg:shadow-lg p-4 lg:block lg:opacity-0 lg:invisible group-hover:opacity-100 lg:group-hover:visible lg:group-hover:top-full bg-white dark:bg-dark transition-[top] duration-300">
|
||||
<a href="https://blog-raph.dariow.fr/" target="_blank"
|
||||
class="block text-base rounded py-[10px] px-4 text-dark dark:text-white hover:opacity-70">
|
||||
Raphael Payet
|
||||
</a>
|
||||
<a href="https://blog.dariow.fr/" target="_blank"
|
||||
class="block text-base rounded py-[10px] px-4 text-dark dark:text-white hover:opacity-70">
|
||||
Dario Weinberger
|
||||
</a>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="relative group visible sm:visible md:invisible lg:invisible">
|
||||
<a href="/auth/deconnexion"
|
||||
class="text-base text-dark dark:text-white group-hover:opacity-70 py-2 lg:py-6 lg:inline-flex lg:px-0 flex mx-8 lg:mr-0 lg:ml-8 xl:ml-12">
|
||||
Deconnexion
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
{{else}}
|
||||
|
||||
<li class="relative group submenu-item">
|
||||
<a href="javascript:void(0)"
|
||||
class="text-base text-dark dark:text-white group-hover:opacity-70 py-2 lg:py-6 lg:inline-flex lg:pl-0 lg:pr-4 flex mx-8 lg:mr-0 lg:ml-8 xl:ml-12 relative after:absolute after:w-2 after:h-2 after:border-b-2 after:border-r-2 after:border-current after:rotate-45 lg:after:right-0 after:right-1 after:top-1/2 after:translate-y-[-50%] after:mt-[-2px]">
|
||||
Contact
|
||||
</a>
|
||||
<div
|
||||
class="submenu hidden relative lg:absolute w-[250px] top-full lg:top-[110%] left-0 rounded-md lg:shadow-lg p-4 lg:block lg:opacity-0 lg:invisible group-hover:opacity-100 lg:group-hover:visible lg:group-hover:top-full bg-white dark:bg-dark transition-[top] duration-300">
|
||||
<a href="https://blog-raph.dariow.fr/" target="_blank"
|
||||
class="block text-base rounded py-[10px] px-4 text-dark dark:text-white hover:opacity-70">
|
||||
Raphael Payet
|
||||
</a>
|
||||
<a href="https://blog.dariow.fr/" target="_blank"
|
||||
class="block text-base rounded py-[10px] px-4 text-dark dark:text-white hover:opacity-70">
|
||||
Dario Weinberger
|
||||
</a>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="visible md:invisible lg:invisible relative group submenu-item">
|
||||
<a href="javascript:void(0)"
|
||||
class="text-base text-dark dark:text-white group-hover:opacity-70 py-2 lg:py-6 lg:inline-flex lg:pl-0 lg:pr-4 flex mx-8 lg:mr-0 lg:ml-8 xl:ml-12 relative after:absolute after:w-2 after:h-2 after:border-b-2 after:border-r-2 after:border-current after:rotate-45 lg:after:right-0 after:right-1 after:top-1/2 after:translate-y-[-50%] after:mt-[-2px]">
|
||||
Plus
|
||||
</a>
|
||||
<div
|
||||
class="submenu hidden relative lg:absolute w-[150px] top-full lg:top-[110%] left-0 rounded-md lg:shadow-lg p-4 lg:block lg:opacity-0 lg:invisible group-hover:opacity-100 lg:group-hover:visible lg:group-hover:top-full bg-white dark:bg-dark transition-[top] duration-300">
|
||||
<a href="/connexion"
|
||||
class="block text-base rounded py-[10px] px-4 text-dark dark:text-white hover:opacity-70">
|
||||
Connexion
|
||||
</a>
|
||||
<a href="/inscription"
|
||||
class="block text-base font-bold rounded py-[10px] px-4 text-dark dark:text-white hover:opacity-70">
|
||||
Inscription
|
||||
</a>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
{{/if}}
|
||||
</ul>
|
||||
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="flex justify-end items-center pr-16 lg:pr-0">
|
||||
{{#if user_details }}
|
||||
<a href="/auth/deconnexion"
|
||||
class="hidden visible sm:invisible md:block text-base font-bold text-dark dark:text-white hover:opacity-70 py-3 px-7">
|
||||
Deconnexion
|
||||
</a>
|
||||
{{else}}
|
||||
<a href="/connexion"
|
||||
class="hidden visible sm:invisible md:block text-base font-bold text-dark dark:text-white hover:opacity-70 py-3 px-7">
|
||||
Connexion
|
||||
</a>
|
||||
<a href="/inscription"
|
||||
class="hidden visible sm:invisible md:block text-base font-bold text-white bg-primary py-3 px-8 md:px-9 lg:px-6 xl:px-9 hover:shadow-signUp hover:bg-opacity-90 rounded-md transition ease-in-up duration-300">
|
||||
Inscription
|
||||
</a>
|
||||
{{/if}}
|
||||
<div>
|
||||
<label for="darkToggler"
|
||||
class="cursor-pointer w-9 h-9 md:w-14 md:h-14 rounded-full flex items-center justify-center bg-gray-2 dark:bg-dark-bg text-black dark:text-white">
|
||||
<input type="checkbox" name="darkToggler" id="darkToggler" class="sr-only" aria-label="darkToggler" />
|
||||
<svg viewBox="0 0 23 23" class="stroke-current dark:hidden w-5 h-5 md:w-6 md:h-6" fill="none">
|
||||
<path
|
||||
d="M9.55078 1.5C5.80078 1.5 1.30078 5.25 1.30078 11.25C1.30078 17.25 5.80078 21.75 11.8008 21.75C17.8008 21.75 21.5508 17.25 21.5508 13.5C13.3008 18.75 4.30078 9.75 9.55078 1.5Z"
|
||||
stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
|
||||
</svg>
|
||||
<svg viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg"
|
||||
class="hidden dark:block w-5 h-5 md:w-6 md:h-6">
|
||||
<mask id="path-1-inside-1_977:1934" fill="white">
|
||||
<path
|
||||
d="M12.0508 16.5C10.8573 16.5 9.71271 16.0259 8.8688 15.182C8.02489 14.3381 7.55078 13.1935 7.55078 12C7.55078 10.8065 8.02489 9.66193 8.8688 8.81802C9.71271 7.97411 10.8573 7.5 12.0508 7.5C13.2443 7.5 14.3888 7.97411 15.2328 8.81802C16.0767 9.66193 16.5508 10.8065 16.5508 12C16.5508 13.1935 16.0767 14.3381 15.2328 15.182C14.3888 16.0259 13.2443 16.5 12.0508 16.5ZM12.0508 18C13.6421 18 15.1682 17.3679 16.2934 16.2426C17.4186 15.1174 18.0508 13.5913 18.0508 12C18.0508 10.4087 17.4186 8.88258 16.2934 7.75736C15.1682 6.63214 13.6421 6 12.0508 6C10.4595 6 8.93336 6.63214 7.80814 7.75736C6.68292 8.88258 6.05078 10.4087 6.05078 12C6.05078 13.5913 6.68292 15.1174 7.80814 16.2426C8.93336 17.3679 10.4595 18 12.0508 18ZM12.0508 0C12.2497 0 12.4405 0.0790176 12.5811 0.21967C12.7218 0.360322 12.8008 0.551088 12.8008 0.75V3.75C12.8008 3.94891 12.7218 4.13968 12.5811 4.28033C12.4405 4.42098 12.2497 4.5 12.0508 4.5C11.8519 4.5 11.6611 4.42098 11.5205 4.28033C11.3798 4.13968 11.3008 3.94891 11.3008 3.75V0.75C11.3008 0.551088 11.3798 0.360322 11.5205 0.21967C11.6611 0.0790176 11.8519 0 12.0508 0V0ZM12.0508 19.5C12.2497 19.5 12.4405 19.579 12.5811 19.7197C12.7218 19.8603 12.8008 20.0511 12.8008 20.25V23.25C12.8008 23.4489 12.7218 23.6397 12.5811 23.7803C12.4405 23.921 12.2497 24 12.0508 24C11.8519 24 11.6611 23.921 11.5205 23.7803C11.3798 23.6397 11.3008 23.4489 11.3008 23.25V20.25C11.3008 20.0511 11.3798 19.8603 11.5205 19.7197C11.6611 19.579 11.8519 19.5 12.0508 19.5ZM24.0508 12C24.0508 12.1989 23.9718 12.3897 23.8311 12.5303C23.6905 12.671 23.4997 12.75 23.3008 12.75H20.3008C20.1019 12.75 19.9111 12.671 19.7705 12.5303C19.6298 12.3897 19.5508 12.1989 19.5508 12C19.5508 11.8011 19.6298 11.6103 19.7705 11.4697C19.9111 11.329 20.1019 11.25 20.3008 11.25H23.3008C23.4997 11.25 23.6905 11.329 23.8311 11.4697C23.9718 11.6103 24.0508 11.8011 24.0508 12ZM4.55078 12C4.55078 12.1989 4.47176 12.3897 4.33111 12.5303C4.19046 12.671 3.99969 12.75 3.80078 12.75H0.800781C0.601869 12.75 0.411103 12.671 0.270451 12.5303C0.129799 12.3897 0.0507813 12.1989 0.0507812 12C0.0507813 11.8011 0.129799 11.6103 0.270451 11.4697C0.411103 11.329 0.601869 11.25 0.800781 11.25H3.80078C3.99969 11.25 4.19046 11.329 4.33111 11.4697C4.47176 11.6103 4.55078 11.8011 4.55078 12ZM20.5363 3.5145C20.6769 3.65515 20.7559 3.84588 20.7559 4.04475C20.7559 4.24362 20.6769 4.43435 20.5363 4.575L18.4153 6.6975C18.3455 6.76713 18.2628 6.82235 18.1717 6.86C18.0806 6.89765 17.983 6.91699 17.8845 6.91692C17.6855 6.91678 17.4947 6.83758 17.354 6.69675C17.2844 6.62702 17.2292 6.54425 17.1915 6.45318C17.1539 6.36211 17.1345 6.26452 17.1346 6.16597C17.1348 5.96695 17.214 5.77613 17.3548 5.6355L19.4758 3.5145C19.6164 3.3739 19.8072 3.29491 20.006 3.29491C20.2049 3.29491 20.3956 3.3739 20.5363 3.5145ZM6.74678 17.304C6.88738 17.4446 6.96637 17.6354 6.96637 17.8342C6.96637 18.0331 6.88738 18.2239 6.74678 18.3645L4.62578 20.4855C4.48433 20.6221 4.29488 20.6977 4.09823 20.696C3.90158 20.6943 3.71347 20.6154 3.57442 20.4764C3.43536 20.3373 3.35648 20.1492 3.35478 19.9526C3.35307 19.7559 3.42866 19.5665 3.56528 19.425L5.68628 17.304C5.82693 17.1634 6.01766 17.0844 6.21653 17.0844C6.4154 17.0844 6.60614 17.1634 6.74678 17.304ZM20.5363 20.4855C20.3956 20.6261 20.2049 20.7051 20.006 20.7051C19.8072 20.7051 19.6164 20.6261 19.4758 20.4855L17.3548 18.3645C17.2182 18.223 17.1426 18.0336 17.1443 17.8369C17.146 17.6403 17.2249 17.4522 17.3639 17.3131C17.503 17.1741 17.6911 17.0952 17.8877 17.0935C18.0844 17.0918 18.2738 17.1674 18.4153 17.304L20.5363 19.425C20.6769 19.5656 20.7559 19.7564 20.7559 19.9552C20.7559 20.1541 20.6769 20.3449 20.5363 20.4855ZM6.74678 6.6975C6.60614 6.8381 6.4154 6.91709 6.21653 6.91709C6.01766 6.91709 5.82693 6.8381 5.68628 6.6975L3.56528 4.575C3.49365 4.50582 3.43651 4.42306 3.39721 4.33155C3.3579 4.24005 3.33721 4.14164 3.33634 4.04205C3.33548 3.94247 3.35445 3.84371 3.39216 3.75153C3.42988 3.65936 3.48557 3.57562 3.55598 3.5052C3.6264 3.43478 3.71014 3.37909 3.80232 3.34138C3.89449 3.30367 3.99325 3.2847 4.09283 3.28556C4.19242 3.28643 4.29083 3.30712 4.38233 3.34642C4.47384 3.38573 4.5566 3.44287 4.62578 3.5145L6.74678 5.6355C6.81663 5.70517 6.87204 5.78793 6.90985 5.87905C6.94766 5.97017 6.96712 6.06785 6.96712 6.1665C6.96712 6.26515 6.94766 6.36283 6.90985 6.45395C6.87204 6.54507 6.81663 6.62783 6.74678 6.6975Z" />
|
||||
</mask>
|
||||
<path
|
||||
d="M12.0508 16.5C10.8573 16.5 9.71271 16.0259 8.8688 15.182C8.02489 14.3381 7.55078 13.1935 7.55078 12C7.55078 10.8065 8.02489 9.66193 8.8688 8.81802C9.71271 7.97411 10.8573 7.5 12.0508 7.5C13.2443 7.5 14.3888 7.97411 15.2328 8.81802C16.0767 9.66193 16.5508 10.8065 16.5508 12C16.5508 13.1935 16.0767 14.3381 15.2328 15.182C14.3888 16.0259 13.2443 16.5 12.0508 16.5ZM12.0508 18C13.6421 18 15.1682 17.3679 16.2934 16.2426C17.4186 15.1174 18.0508 13.5913 18.0508 12C18.0508 10.4087 17.4186 8.88258 16.2934 7.75736C15.1682 6.63214 13.6421 6 12.0508 6C10.4595 6 8.93336 6.63214 7.80814 7.75736C6.68292 8.88258 6.05078 10.4087 6.05078 12C6.05078 13.5913 6.68292 15.1174 7.80814 16.2426C8.93336 17.3679 10.4595 18 12.0508 18ZM12.0508 0C12.2497 0 12.4405 0.0790176 12.5811 0.21967C12.7218 0.360322 12.8008 0.551088 12.8008 0.75V3.75C12.8008 3.94891 12.7218 4.13968 12.5811 4.28033C12.4405 4.42098 12.2497 4.5 12.0508 4.5C11.8519 4.5 11.6611 4.42098 11.5205 4.28033C11.3798 4.13968 11.3008 3.94891 11.3008 3.75V0.75C11.3008 0.551088 11.3798 0.360322 11.5205 0.21967C11.6611 0.0790176 11.8519 0 12.0508 0V0ZM12.0508 19.5C12.2497 19.5 12.4405 19.579 12.5811 19.7197C12.7218 19.8603 12.8008 20.0511 12.8008 20.25V23.25C12.8008 23.4489 12.7218 23.6397 12.5811 23.7803C12.4405 23.921 12.2497 24 12.0508 24C11.8519 24 11.6611 23.921 11.5205 23.7803C11.3798 23.6397 11.3008 23.4489 11.3008 23.25V20.25C11.3008 20.0511 11.3798 19.8603 11.5205 19.7197C11.6611 19.579 11.8519 19.5 12.0508 19.5ZM24.0508 12C24.0508 12.1989 23.9718 12.3897 23.8311 12.5303C23.6905 12.671 23.4997 12.75 23.3008 12.75H20.3008C20.1019 12.75 19.9111 12.671 19.7705 12.5303C19.6298 12.3897 19.5508 12.1989 19.5508 12C19.5508 11.8011 19.6298 11.6103 19.7705 11.4697C19.9111 11.329 20.1019 11.25 20.3008 11.25H23.3008C23.4997 11.25 23.6905 11.329 23.8311 11.4697C23.9718 11.6103 24.0508 11.8011 24.0508 12ZM4.55078 12C4.55078 12.1989 4.47176 12.3897 4.33111 12.5303C4.19046 12.671 3.99969 12.75 3.80078 12.75H0.800781C0.601869 12.75 0.411103 12.671 0.270451 12.5303C0.129799 12.3897 0.0507813 12.1989 0.0507812 12C0.0507813 11.8011 0.129799 11.6103 0.270451 11.4697C0.411103 11.329 0.601869 11.25 0.800781 11.25H3.80078C3.99969 11.25 4.19046 11.329 4.33111 11.4697C4.47176 11.6103 4.55078 11.8011 4.55078 12ZM20.5363 3.5145C20.6769 3.65515 20.7559 3.84588 20.7559 4.04475C20.7559 4.24362 20.6769 4.43435 20.5363 4.575L18.4153 6.6975C18.3455 6.76713 18.2628 6.82235 18.1717 6.86C18.0806 6.89765 17.983 6.91699 17.8845 6.91692C17.6855 6.91678 17.4947 6.83758 17.354 6.69675C17.2844 6.62702 17.2292 6.54425 17.1915 6.45318C17.1539 6.36211 17.1345 6.26452 17.1346 6.16597C17.1348 5.96695 17.214 5.77613 17.3548 5.6355L19.4758 3.5145C19.6164 3.3739 19.8072 3.29491 20.006 3.29491C20.2049 3.29491 20.3956 3.3739 20.5363 3.5145ZM6.74678 17.304C6.88738 17.4446 6.96637 17.6354 6.96637 17.8342C6.96637 18.0331 6.88738 18.2239 6.74678 18.3645L4.62578 20.4855C4.48433 20.6221 4.29488 20.6977 4.09823 20.696C3.90158 20.6943 3.71347 20.6154 3.57442 20.4764C3.43536 20.3373 3.35648 20.1492 3.35478 19.9526C3.35307 19.7559 3.42866 19.5665 3.56528 19.425L5.68628 17.304C5.82693 17.1634 6.01766 17.0844 6.21653 17.0844C6.4154 17.0844 6.60614 17.1634 6.74678 17.304ZM20.5363 20.4855C20.3956 20.6261 20.2049 20.7051 20.006 20.7051C19.8072 20.7051 19.6164 20.6261 19.4758 20.4855L17.3548 18.3645C17.2182 18.223 17.1426 18.0336 17.1443 17.8369C17.146 17.6403 17.2249 17.4522 17.3639 17.3131C17.503 17.1741 17.6911 17.0952 17.8877 17.0935C18.0844 17.0918 18.2738 17.1674 18.4153 17.304L20.5363 19.425C20.6769 19.5656 20.7559 19.7564 20.7559 19.9552C20.7559 20.1541 20.6769 20.3449 20.5363 20.4855ZM6.74678 6.6975C6.60614 6.8381 6.4154 6.91709 6.21653 6.91709C6.01766 6.91709 5.82693 6.8381 5.68628 6.6975L3.56528 4.575C3.49365 4.50582 3.43651 4.42306 3.39721 4.33155C3.3579 4.24005 3.33721 4.14164 3.33634 4.04205C3.33548 3.94247 3.35445 3.84371 3.39216 3.75153C3.42988 3.65936 3.48557 3.57562 3.55598 3.5052C3.6264 3.43478 3.71014 3.37909 3.80232 3.34138C3.89449 3.30367 3.99325 3.2847 4.09283 3.28556C4.19242 3.28643 4.29083 3.30712 4.38233 3.34642C4.47384 3.38573 4.5566 3.44287 4.62578 3.5145L6.74678 5.6355C6.81663 5.70517 6.87204 5.78793 6.90985 5.87905C6.94766 5.97017 6.96712 6.06785 6.96712 6.1665C6.96712 6.26515 6.94766 6.36283 6.90985 6.45395C6.87204 6.54507 6.81663 6.62783 6.74678 6.6975Z"
|
||||
fill="black" stroke="white" stroke-width="2" mask="url(#path-1-inside-1_977:1934)" />
|
||||
</svg>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
|
||||
{{{body}}}
|
||||
|
||||
|
||||
|
||||
<!--FOOTER-->
|
||||
|
||||
<footer id="leFooter" class="relative z-10 bg-primary bg-opacity-5 wow fadeInUp w-full" data-wow-delay=".1s">
|
||||
<div class="py-8 bg-primary bg-opacity-10 relative bottom-0">
|
||||
<div class="container">
|
||||
<p class="text-body-color dark:text-slate-50 text-base text-center">
|
||||
© 2023 | <a href="mailto:contact@dariow.fr" class="dark:hover:text-white hover:text-primary">Dario W.</a>
|
||||
/ <a href="mailto:raphael.alexis.payet@gmail.com" class="dark:hover:text-white hover:text-primary">Raphael
|
||||
P.</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</footer>
|
||||
|
||||
|
||||
<a href="javascript:void(0)"
|
||||
class="hidden items-center justify-center bg-primary text-white w-10 h-10 rounded-md fixed bottom-8 right-8 left-auto z-[999] hover:shadow-signUp hover:bg-opacity-80 transition duration-300 ease-in-out back-to-top shadow-md">
|
||||
<span class="w-3 h-3 border-t border-l border-white rotate-45 mt-[6px]"></span>
|
||||
</a>
|
||||
|
||||
<!--SCRIPTS JS-->
|
||||
<script defer src="/js/custom.js"></script>
|
||||
<script defer src="/js/bundle.js"></script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
44
docker-compose.yml
Normal file
@ -0,0 +1,44 @@
|
||||
version: "3.8"
|
||||
services:
|
||||
nodejs: # Service pour nodejs
|
||||
networks:
|
||||
- rappaurio-net
|
||||
build:
|
||||
context: ./app-rappaurio
|
||||
volumes:
|
||||
- ./app-rappaurio:/user/src/app
|
||||
ports:
|
||||
- "5000:5000"
|
||||
restart: unless-stopped
|
||||
|
||||
nginx: # Service serveur web
|
||||
networks:
|
||||
- rappaurio-net
|
||||
build:
|
||||
context: ./nginx
|
||||
volumes:
|
||||
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf
|
||||
ports:
|
||||
- "8888:80"
|
||||
restart: unless-stopped
|
||||
|
||||
|
||||
db:
|
||||
image: mariadb:latest
|
||||
networks:
|
||||
- rappaurio-net
|
||||
env_file:
|
||||
- .env # fichier contenant les mot de passes
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: ${DATABASE_ROOT_PASSWORD}
|
||||
MYSQL_DATABASE: ${DATABASE}
|
||||
MYSQL_USER: ${DATABASE_USER}
|
||||
MYSQL_PASSWORD: ${DATABASE_PASSWORD}
|
||||
volumes:
|
||||
- ./mariadb/mysql:/var/lib/mysql
|
||||
- ./mariadb:/docker-entrypoint-initdb.d
|
||||
command: --init-file /docker-entrypoint-initdb.d/rappaurio.sql
|
||||
restart: unless-stopped
|
||||
|
||||
networks:
|
||||
rappaurio-net:
|
0
img/.gitkeep
Normal file
BIN
img/Diagramme_architecture.png
Normal file
After Width: | Height: | Size: 354 KiB |
BIN
img/Diagramme_exigence.vpd_v1.png
Normal file
After Width: | Height: | Size: 130 KiB |
BIN
img/demo.gif
Normal file
After Width: | Height: | Size: 4.7 MiB |
1
img/logo.svg
Normal file
After Width: | Height: | Size: 49 KiB |
29
mariadb/rappaurio.sql
Normal file
@ -0,0 +1,29 @@
|
||||
|
||||
/*
|
||||
By Dario Weinberger & Raphael Payet
|
||||
©2023
|
||||
*/
|
||||
|
||||
-- Utiliser la base de données
|
||||
USE rappaurio;
|
||||
|
||||
-- Créer la table "User"
|
||||
CREATE TABLE `users` (
|
||||
`id` int(255) NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`email` varchar(255) NOT NULL,
|
||||
`password` varchar(255) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
|
||||
-- Créer la table "Search"
|
||||
CREATE TABLE `search` (
|
||||
`id_search` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`id` int(11) DEFAULT NULL,
|
||||
`article1` varchar(255) NOT NULL,
|
||||
`article2` varchar(255) NOT NULL,
|
||||
`date` timestamp NULL DEFAULT current_timestamp(),
|
||||
PRIMARY KEY (`id_search`),
|
||||
KEY `id` (`id`),
|
||||
CONSTRAINT `search_ibfk_1` FOREIGN KEY (`id`) REFERENCES `users` (`id`)
|
||||
);
|
2
nginx/Dockerfile
Normal file
@ -0,0 +1,2 @@
|
||||
FROM nginx
|
||||
COPY default.conf /etc/nginx/conf.d/default.conf
|
10
nginx/default.conf
Normal file
@ -0,0 +1,10 @@
|
||||
server {
|
||||
location / {
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
|
||||
proxy_pass http://nodejs:5000;
|
||||
}
|
||||
}
|