Browse Source

Merge branch 'main' into developpement

fix/clean
Sacha GUERIN 5 months ago
committed by GitHub
parent
commit
d53f80a9d3
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 26
      backend/app/controllers/comment.controller.js
  2. 47
      backend/logs/access.log
  3. 26
      frontend/src/components/Comment.jsx
  4. 102
      frontend/src/pages/Video.jsx

26
backend/app/controllers/comment.controller.js

@ -17,10 +17,30 @@ export async function upload(req, res) {
logger.action("try to post comment"); logger.action("try to post comment");
const client = await getClient(); const client = await getClient();
const query = `INSERT INTO comments (content, author, video, created_at) VALUES ($1, $2, $3, $4)`; const query = `INSERT INTO comments (content, author, video, created_at) VALUES ($1, $2, $3, $4) RETURNING id, created_at`;
await client.query(query, [comment.content, comment.author, comment.video, comment.createdAt]); const result = await client.query(query, [comment.content, comment.author, comment.video, comment.createdAt]);
logger.write("successfully post comment", 200); logger.write("successfully post comment", 200);
res.status(200).send("successfully post comment");
const createdAt = result.rows[0].created_at;
comment.id = result.rows[0].id;
// Send back the comment
// Get the author's name and profile picture
const authorQuery = `SELECT username, picture FROM users WHERE id = $1`;
const authorResult = await client.query(authorQuery, [comment.author]);
const author = authorResult.rows[0];
const responseComment = {
id: comment.id,
content: comment.content,
video: comment.video,
username: author.username,
picture: author.picture,
createdAt: createdAt
}
res.status(200).json(responseComment);
} }

47
backend/logs/access.log

@ -831,49 +831,4 @@
[2025-07-19 23:05:34.319] [undefined] GET(/:id/similar): successfully retrieved similar videos for video 3 with status 200 [2025-07-19 23:05:34.319] [undefined] GET(/:id/similar): successfully retrieved similar videos for video 3 with status 200
[2025-07-19 23:05:34.328] [undefined] GET(/:id/views): try to add views for video 3 [2025-07-19 23:05:34.328] [undefined] GET(/:id/views): try to add views for video 3
[2025-07-19 23:05:34.333] [undefined] GET(/:id/views): successfully added views for video 3 with status 200 [2025-07-19 23:05:34.333] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-07-20 08:47:03.500] [undefined] GET(/:id): try to get video 3
[2025-07-20 08:47:03.511] [undefined] GET(/:id): successfully get video 3 with status 200
[2025-07-20 08:47:03.524] [undefined] GET(/:id/similar): try to get similar videos for video 3
[2025-07-20 08:47:03.535] [undefined] GET(/:id/similar): successfully retrieved similar videos for video 3 with status 200
[2025-07-20 08:47:03.553] [undefined] GET(/:id/views): try to add views for video 3
[2025-07-20 08:47:03.561] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-07-20 08:47:07.593] [undefined] GET(/:id): try to get video 3
[2025-07-20 08:47:07.601] [undefined] GET(/:id): successfully get video 3 with status 200
[2025-07-20 08:47:07.616] [undefined] GET(/:id/similar): try to get similar videos for video 3
[2025-07-20 08:47:07.626] [undefined] GET(/:id/similar): successfully retrieved similar videos for video 3 with status 200
[2025-07-20 08:47:07.670] [undefined] GET(/:id/views): try to add views for video 3
[2025-07-20 08:47:07.679] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-07-20 08:47:09.941] [undefined] POST(/:id/subscribe): try to toggle subscription for channel with id 2
[2025-07-20 08:47:09.947] [undefined] POST(/:id/subscribe): Successfully unsubscribed from channel with status 200
[2025-07-20 08:51:41.655] [undefined] GET(/:id): try to get video 3
[2025-07-20 08:51:41.668] [undefined] GET(/:id): successfully get video 3 with status 200
[2025-07-20 08:51:41.681] [undefined] GET(/:id/similar): try to get similar videos for video 3
[2025-07-20 08:51:41.695] [undefined] GET(/:id/similar): successfully retrieved similar videos for video 3 with status 200
[2025-07-20 08:51:41.737] [undefined] GET(/:id/views): try to add views for video 3
[2025-07-20 08:51:41.747] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-07-20 08:51:45.125] [undefined] POST(/:id/subscribe): try to toggle subscription for channel with id 2
[2025-07-20 08:51:45.132] [undefined] POST(/:id/subscribe): Successfully subscribed to channel with status 200
[2025-07-20 08:51:46.253] [undefined] POST(/:id/subscribe): try to toggle subscription for channel with id 2
[2025-07-20 08:51:46.260] [undefined] POST(/:id/subscribe): Successfully unsubscribed from channel with status 200
[2025-07-20 08:51:47.141] [undefined] POST(/:id/subscribe): try to toggle subscription for channel with id 2
[2025-07-20 08:51:47.147] [undefined] POST(/:id/subscribe): Successfully subscribed to channel with status 200
[2025-07-20 08:54:06.806] [undefined] GET(/:id): try to get video 3
[2025-07-20 08:54:06.817] [undefined] GET(/:id): successfully get video 3 with status 200
[2025-07-20 08:54:06.833] [undefined] GET(/:id/similar): try to get similar videos for video 3
[2025-07-20 08:54:06.845] [undefined] GET(/:id/similar): successfully retrieved similar videos for video 3 with status 200
[2025-07-20 08:54:06.897] [undefined] GET(/:id/views): try to add views for video 3
[2025-07-20 08:54:06.906] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-07-20 08:54:09.393] [undefined] GET(/:id/like): try to toggle like on video 3
[2025-07-20 08:54:09.399] [undefined] GET(/:id/like): likes found, removing like for video 3 with status 200
[2025-07-20 08:54:59.934] [undefined] GET(/:id): try to get video 3
[2025-07-20 08:54:59.942] [undefined] GET(/:id): successfully get video 3 with status 200
[2025-07-20 08:54:59.953] [undefined] GET(/:id/similar): try to get similar videos for video 3
[2025-07-20 08:54:59.964] [undefined] GET(/:id/similar): successfully retrieved similar videos for video 3 with status 200
[2025-07-20 08:54:59.995] [undefined] GET(/:id/views): try to add views for video 3
[2025-07-20 08:55:00.002] [undefined] GET(/:id/views): successfully added views for video 3 with status 200
[2025-07-20 08:55:01.907] [undefined] GET(/:id/like): try to toggle like on video 3
[2025-07-20 08:55:01.915] [undefined] GET(/:id/like): no likes found adding likes for video 3 with status 200
[2025-07-20 08:55:02.619] [undefined] GET(/:id/like): try to toggle like on video 3
[2025-07-20 08:55:02.625] [undefined] GET(/:id/like): likes found, removing like for video 3 with status 200
[2025-07-20 08:55:03.148] [undefined] GET(/:id/like): try to toggle like on video 3
[2025-07-20 08:55:03.155] [undefined] GET(/:id/like): no likes found adding likes for video 3 with status 200

26
frontend/src/components/Comment.jsx

@ -2,7 +2,7 @@ import {useAuth} from "../contexts/AuthContext.jsx";
import {useRef, useState} from "react"; import {useRef, useState} from "react";
export default function Comment({ comment, index, videoId }) { export default function Comment({ comment, index, videoId, refetchVideo }) {
let {user, isAuthenticated} = useAuth(); let {user, isAuthenticated} = useAuth();
let commentRef = useRef(); let commentRef = useRef();
@ -15,15 +15,25 @@ export default function Comment({ comment, index, videoId }) {
const commentElement = commentRef.current; const commentElement = commentRef.current;
commentElement.contentEditable = true; commentElement.contentEditable = true;
} }
const handleDelete = async (id) => { const handleDelete = async (id) => {
const token = localStorage.getItem('token'); try {
await fetch(`/api/comments/${id}`, { const token = localStorage.getItem('token');
method: 'DELETE', const response = await fetch(`/api/comments/${id}`, {
headers: { method: 'DELETE',
'Content-Type': 'application/json', headers: {
'Authorization': `Bearer ${token}` 'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
}
});
if (response.ok) {
// Refresh the video data to update the comments list
refetchVideo();
} }
}) } catch (error) {
console.error('Error deleting comment:', error);
}
} }
const handleEditSubmit = async (id, content) => { const handleEditSubmit = async (id, content) => {

102
frontend/src/pages/Video.jsx

@ -1,5 +1,5 @@
import {useNavigate, useParams} from "react-router-dom"; import {useNavigate, useParams} from "react-router-dom";
import {useEffect, useState, useRef} from "react"; import {useEffect, useState, useRef, useCallback} from "react";
import Navbar from "../components/Navbar.jsx"; import Navbar from "../components/Navbar.jsx";
import { useAuth } from "../contexts/AuthContext.jsx"; import { useAuth } from "../contexts/AuthContext.jsx";
import Comment from "../components/Comment.jsx"; import Comment from "../components/Comment.jsx";
@ -22,51 +22,69 @@ export default function Video() {
const [showControls, setShowControls] = useState(false); const [showControls, setShowControls] = useState(false);
const [comment, setComment] = useState(""); const [comment, setComment] = useState("");
useEffect(() => { const fetchVideo = useCallback(async () => {
const fetchVideo = async () => { // Fetch video data and similar videos based on the video ID from the URL
// Fetch video data and similar videos based on the video ID from the URL try {
try { const response = await fetch(`/api/videos/${id}`);
const response = await fetch(`/api/videos/${id}`); if (!response.ok) {
if (!response.ok) { throw new Error('Network response was not ok');
throw new Error('Network response was not ok');
}
const videoData = await response.json();
setVideo(videoData);
} catch (error) {
console.error('Error fetching video:', error);
} }
try { const videoData = await response.json();
const response = await fetch(`/api/videos/${id}/similar`); setVideo(videoData);
if (!response.ok) { } catch (error) {
throw new Error('Network response was not ok'); console.error('Error fetching video:', error);
} }
const similarVideosData = await response.json(); try {
setSimilarVideos(similarVideosData); const response = await fetch(`/api/videos/${id}/similar`);
} catch (error) { if (!response.ok) {
console.error('Error fetching similar videos:', error); throw new Error('Network response was not ok');
} }
const similarVideosData = await response.json();
setSimilarVideos(similarVideosData);
} catch (error) {
console.error('Error fetching similar videos:', error);
}
// Add views to the video // Add views to the video
try { try {
const token = localStorage.getItem('token'); const token = localStorage.getItem('token');
if (!token) { if (!token) {
navigation('/login'); navigation('/login');
return; return;
}
await fetch(`/api/videos/${id}/views`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
} }
await fetch(`/api/videos/${id}/views`, { });
method: 'GET', } catch (error) {
headers: { console.error('Error adding views:', error);
'Content-Type': 'application/json', }
'Authorization': `Bearer ${token}` }, [id, navigation]);
}
}); const fetchComments = useCallback(async () => {
} catch (error) { // Fetch comments for the video
console.error('Error adding views:', error); try {
const response = await fetch(`/api/comments/video/${id}`);
if (!response.ok) {
throw new Error('Network response was not ok');
} }
const commentsData = await response.json();
setVideo((prevVideo) => ({
...prevVideo,
comments: commentsData
}));
} catch (error) {
console.error('Error fetching comments:', error);
} }
fetchVideo();
}, [id]); }, [id]);
useEffect(() => {
fetchVideo();
}, [fetchVideo]);
const handlePlayPause = () => { const handlePlayPause = () => {
if (videoRef.current) { if (videoRef.current) {
if (videoRef.current.paused) { if (videoRef.current.paused) {
@ -278,6 +296,12 @@ export default function Video() {
console.log('Comment posted successfully:', data); console.log('Comment posted successfully:', data);
setComment(""); // Clear the comment input setComment(""); // Clear the comment input
setVideo((prevVideo) => ({
...prevVideo,
comments: [...(prevVideo.comments || []), data] // Add the new comment to the existing comments
}));
} catch (error) { } catch (error) {
console.error('Error posting comment:', error); console.error('Error posting comment:', error);
} }
@ -405,7 +429,7 @@ export default function Video() {
<div className="mt-4"> <div className="mt-4">
{video.comments && video.comments.length > 0 ? ( {video.comments && video.comments.length > 0 ? (
video.comments.map((comment, index) => ( video.comments.map((comment, index) => (
<Comment comment={comment} index={index} videoId={id} /> <Comment comment={comment} index={index} videoId={id} key={index} refetchVideo={fetchVideo} />
)) ))
) : ( ) : (
<p className="text-gray-400">Aucun commentaire pour le moment. Soyez le premier à en publier !</p> <p className="text-gray-400">Aucun commentaire pour le moment. Soyez le premier à en publier !</p>

Loading…
Cancel
Save