This commit is contained in:
2024-02-13 10:52:48 +01:00
parent a37cf12ef1
commit a09e8acbab
12 changed files with 402 additions and 0 deletions

BIN
TP3/BDD/MCD.mcd Normal file

Binary file not shown.

BIN
TP3/BDD/MCD.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

BIN
TP3/BDD/MPD.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

31
TP3/BDD/sql/data.sql Normal file
View File

@@ -0,0 +1,31 @@
DELETE FROM users;
DELETE FROM channels;
DELETE FROM messages;
-- -------------------------------------------------------------------------------
-- --- Populate users database ----------------------------------------------------------------------------------------------------------------------------------
INSERT INTO users(login, nickname, password) VALUES('etudiant0', 'E0','mp0');
INSERT INTO users(login, nickname, password) VALUES('etudiant1', 'E1','mp1');
INSERT INTO users(login, nickname, password) VALUES('etudiant2', 'E2','mp2');
INSERT INTO users(login, nickname, password) VALUES('etudiant3', 'E3','mp3');
-- -------------------------------------------------------------------------------
-- --- Populate channels database ---------------------------------------------------
-- -------------------------------------------------------------------------------
ALTER SEQUENCE channels_id_seq RESTART;
INSERT INTO channels(name) VALUES('General');
INSERT INTO channels(name) VALUES('Musique');
INSERT INTO channels(name) VALUES('Voyage');
INSERT INTO channels(name) VALUES('Cinema');
INSERT INTO channels(name) VALUES('Bricolage');
-------------------------------------------------------------------------------
--- Populate messages database ------------------------------------------------
-------------------------------------------------------------------------------
ALTER SEQUENCE messages_id_seq RESTART;
INSERT INTO messages(userLogin, channelid, message) VALUES('etudiant0', 1, 'a');
INSERT INTO messages(userLogin, channelid, message) VALUES('etudiant1', 1, 'b');
INSERT INTO messages(userLogin, channelid, message) VALUES('etudiant0', 1, 'c');
INSERT INTO messages(userLogin, channelid, message) VALUES('etudiant2', 3, 'd');
INSERT INTO messages(userLogin, channelid, message) VALUES('etudiant3', 4, 'e');

35
TP3/BDD/sql/model.sql Normal file
View File

@@ -0,0 +1,35 @@
DROP TABLE IF EXISTS messages;
DROP TABLE IF EXISTS channels;
DROP TABLE IF EXISTS users;
CREATE TABLE users
(
login VARCHAR(20) PRIMARY KEY,
nickname VARCHAR(20) NOT NULL,
password VARCHAR(40) NOT NULL
);
CREATE TABLE channels
(
id SERIAL PRIMARY KEY,
name VARCHAR(20) NOT NULL
);
CREATE TABLE messages
(
id SERIAL PRIMARY KEY,
userLogin VARCHAR(20) NOT NULL,
channelid INT NOT NULL,
message VARCHAR(256) NOT NULL,
timestamp TIMESTAMP NOT NULL default CURRENT_TIMESTAMP,
FOREIGN KEY(userLogin) REFERENCES users(login)
ON UPDATE CASCADE ON DELETE CASCADE,
FOREIGN KEY(channelid) REFERENCES channels(id)
ON UPDATE CASCADE ON DELETE CASCADE
);

7
TP3/BDD/sql/test.sql Normal file
View File

@@ -0,0 +1,7 @@
SELECT name FROM channels;
SELECT nickname, message, timestamp FROM users JOIN messages ON users.login = messages.userlogin WHERE messages.channelid = 1;
INSERT INTO messages (userlogin, channelid, message) VALUES ('etudiant0', 1, 'Vive Star Citizen !');
SELECT * FROM messages;

104
TP3/index1.html Normal file
View File

@@ -0,0 +1,104 @@
<!doctype html>
<html lang="fr">
<head>
<style>
.message{
height: auto;
width: 100%;
}
</style>
<!-- Meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Title -->
<title>Chat</title>
<!-- CSS Styles -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
<!-- JS Scripts -->
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js" integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV" crossorigin="anonymous"></script>
</head>
<body>
<!-- Header -->
<header class="container">
<h1> Chat </h1>
<hr>
</header>
<!-- Errors -->
<section id="errors" class="container alert alert-danger d-none">
</section>
<!-- Authentication -->
<section id="authentication" class="container d-none">
<h2>Authentification</h2>
<form id="authentication-send">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text">Login :</span>
</div>
<input type="text" class="form-control" placeholder="Entrez votre login" required autofocus>
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">Mot de passe :</span>
</div>
<input type="password" class="form-control" placeholder="Entrez votre mot de passe" required>
</div>
<div class="form-check float-right mt-2">
<input class="form-check-input" type="checkbox" value="">
<label class="form-check-label" for="stayconnect">
Rester connecté
</label>
</div>
<button type="submit" class="btn btn-success float-right mr-3 secon">
Se connecter
</button>
<button type="reset" class="btn btn-danger float-right mr-3">
Effacer
</button>
</form>
</section>
<!-- Chat -->
<section id="chat" class="container">
<form>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" id="basic-addon1">Canaux : </span>
</div>
<select class="form-control" id="channels-list">
</select>
<div class="input-group-prepend">
<span class="input-group-text" id="basic-addon1">Rafraîchissement : </span>
</div>
<input type="text" class="form-control" placeholder="Entrez le délai de rafraîchissement" aria-label="Username" aria-describedby="basic-addon1">
<div class="input-group-prepend">
<span class="input-group-text" id="basic-addon1">secondes : </span>
</div>
</div>
<div class="form-control" rows="10" id="chat-room" readonly style="height: 25rem">
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" id="basic-addon1">Message > </span>
</div>
<input id="message" type="text" class="form-control" placeholder="Entrez votre message" required autofocus>
</div>
<button type="button" class="btn btn-secondary sedec">
Se déconnecter
</button>
<button type="submit" id="send-message" class="btn btn-success float-right">
Envoyer
</button>
</form>
</section>
<script src="js/utils.js"></script>
<script src="js/chat.js"></script>
</body>
</html>

85
TP3/js/chat.js Normal file
View File

@@ -0,0 +1,85 @@
console.log("chat.js loaded");
// Define callbacks
/*
let envoyerB = document.querySelector(".secon");
envoyerB.addEventListener("submit", login);
let sedecB = document.querySelector(".sedec");
sedecB.addEventListener("click", logout);
*/
function getChannels(){
ajaxRequest("GET", "http://serveur-ajax-s3.felix/TP3/php/chat.php?request=channels", displayChannels);
}
function displayChannels(channels){
let channelsList = document.getElementById("channels-list");
channels.forEach(channel => {
if(channel.id === 1){
let option = document.createElement("option");
option.value = channel.id;
option.textContent = channel.name;
channelsList.appendChild(option);
option.selected = true;
}else{
let option = document.createElement("option");
option.value = channel.id;
option.textContent = channel.name;
channelsList.appendChild(option);
}
});
getMessages();
}
function getMessages(){
let channelsList = document.getElementById("channels-list");
if(channelsList.selectedIndex !== -1) {
let channelId = channelsList.options[channelsList.selectedIndex].value;
ajaxRequest("GET", "http://serveur-ajax-s3.felix/TP3/php/chat.php?request=messages&channel_id=" + channelId, displayMessages);
}else{
console.log("No channel selected");
}
}
function displayMessages(messages){
let chatRoom = document.getElementById("chat-room");
chatRoom.innerHTML = "";
if (messages.length === 0){
let messageDiv = document.createElement("div");
messageDiv.classList.add("message");
chatRoom.appendChild(messageDiv);
}else{
messages.forEach(message => {
let messageDiv = document.createElement("div");
messageDiv.classList.add("message");
messageDiv.textContent = message.nickname + " : " + message.message;
chatRoom.appendChild(messageDiv);
});
}
chatRoom.scrollTop = chatRoom.scrollHeight;
}
function sendMessage(){
event.preventDefault();
let channelsList = document.getElementById("channels-list");
let channelId = channelsList.options[channelsList.selectedIndex].value;
const message = document.getElementById("message").value;
document.getElementById("message").value = "";
ajaxRequest("POST", "http://serveur-ajax-s3.felix/TP3/php/chat.php?request=messages&channel_id=" + channelId + "&userlogin=etudiant0&message=" + message, getMessages, message);
}
getChannels();
document.getElementById("channels-list").addEventListener("change", getMessages);
document.getElementById("send-message").addEventListener("click", sendMessage);
document.getElementById("message").addEventListener("keypress", function(event){
if(event.key === "Enter"){
sendMessage();
}
});
setInterval(getMessages, 1000);

35
TP3/js/utils.js Normal file
View File

@@ -0,0 +1,35 @@
console.log("utils.js loaded");
function ajaxRequest(type, url, callback=null, data=null){
console.log("ajaxRequest called");
console.log("type: " + type);
console.log("url: " + url);
let xhr = new XMLHttpRequest();
xhr.open(type, url, true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.onload = () => {
switch (xhr.status){
case 200:
case 201:
let parsedResponse = JSON.parse(xhr.responseText);
if (callback){
callback(parsedResponse);
}
break;
default:
errorAlert("Erreur " + xhr.status + ": " + xhr.statusText);
break;
}
};
xhr.send(data);
}
function errorAlert(message){
let error = document.getElementById("errors");
error.textContent = message;
error.classList.toggle("d-none");
setTimeout(() => {
error.classList.toggle("d-none");
}, 5000);
}

47
TP3/php/chat.php Normal file
View File

@@ -0,0 +1,47 @@
<?php
ini_set('display_errors', 1);
error_reporting(E_ALL);
include('./database.php');
$pdo = dbConnect();
if(isset($_GET['request']) && $_GET['request'] == 'channels'){
$channels = dbGetChannels($pdo);
if($channels){
$formattedChannels = [];
$id = 1;
foreach($channels as $channel){
$formattedChannels[] = ['id' => $id, 'name' => $channel['name']];
$id++;
}
echo json_encode($formattedChannels);
}
else{
echo json_encode('No channels found');
}
}
if(isset($_GET['request']) && $_GET['request'] == 'messages' && $_GET['channel_id']){
$channel_id = intval($_GET['channel_id']);
$messages = dbGetMessages($pdo, $channel_id);
if($messages){
echo json_encode($messages);
}
else{
echo json_encode([]);
}
}
if(isset($_POST['request']) && $_POST['request'] == 'messages' && $_POST['channel_id'] && $_POST['userlogin'] && $_POST['message']){
$channel_id = intval($_POST['channel_id']);
$userlogin = $_POST['userlogin'];
$message = $_POST['message'];
$result = dbAddMessage($pdo, $userlogin, $channel_id, $message);
if($result){
echo json_encode('Message added');
}
else{
echo json_encode('Message not added');
}
}

7
TP3/php/constants.php Normal file
View File

@@ -0,0 +1,7 @@
<?php
define ("DB_USER", 'postgres');
define ("DB_PASSWORD", '');
define ("DB_NAME", 'chat');
define ("DB_SERVER", 'localhost');
define ("DB_PORT", '5432');
?>

51
TP3/php/database.php Normal file
View File

@@ -0,0 +1,51 @@
<?php
include('./constants.php');
function dbConnect() {
$dsn = 'pgsql:dbname=' . DB_NAME . ';host=' . DB_SERVER . ';port=' . DB_PORT;
try {
$conn = new PDO($dsn, DB_USER, DB_PASSWORD);
return $conn;
} catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
}
}
function dbGetChannels($pdo){
$statement = $pdo->prepare('SELECT name FROM channels');
$statement->execute();
$result = $statement->fetchAll(PDO::FETCH_ASSOC);
if(!empty($result)){
return $result;
}
else{
return false;
}
}
function dbGetMessages($pdo, $channel_id){
$statement = $pdo->prepare('SELECT nickname, message, timestamp FROM users JOIN messages ON users.login = messages.userlogin WHERE messages.channelid = :channel_id;');
$statement->bindParam(':channel_id', $channel_id);
$statement->execute();
$result = $statement->fetchAll(PDO::FETCH_ASSOC);
if(empty($result)){
return false;
}
else{
return $result;
}
}
function dbAddMessage($pdo, $userlogin, $channelid, $message){
$statement = $pdo->prepare('INSERT INTO messages (userlogin, channelid, message) VALUES (:userlogin, :channelid, :message)');
$statement->bindParam(':userlogin', $userlogin);
$statement->bindParam(':channelid', $channelid);
$statement->bindParam(':message', $message);
$statement->execute();
$result = $statement->rowCount();
if($result == 1){
return true;
}
else{
return false;
}
}