diff --git a/backend/routes/api.js b/backend/routes/api.js index 55c68615..ae3d82f6 100644 --- a/backend/routes/api.js +++ b/backend/routes/api.js @@ -707,10 +707,20 @@ router.post("/getItemDetails", async (req, res) => { //DB Queries - History router.get("/getHistory", async (req, res) => { try { + // Extract page and limit from query parameters + const page = parseInt(req.query.page) || 0; // default to page 1 if not provided + const limit = parseInt(req.query.limit) || 10; // default to 10 items per page if not provided + const offset = (page) * limit; + + // Fetch rows with pagination const { rows } = await db.query( - `SELECT * FROM jf_playback_activity order by "ActivityDateInserted" desc`, + `SELECT * FROM jf_playback_activity + ORDER BY "ActivityDateInserted" DESC + LIMIT $1 OFFSET $2`, + [limit, offset] ); + // Group results as per the existing logic const groupedResults = {}; rows.forEach((row) => { if (groupedResults[row.NowPlayingItemId + row.EpisodeId]) { @@ -734,12 +744,21 @@ router.get("/getHistory", async (req, res) => { } }); - res.send(Object.values(groupedResults)); + // Return paginated results + res.send({ + page, + limit, + totalItems: rows.length, // Total number of items in the current page + totalGroups: Object.keys(groupedResults).length, // Total number of grouped results in the current page + data: Object.values(groupedResults), + }); } catch (error) { console.log(error); + res.status(500).send("Server error"); } }); + router.post("/getLibraryHistory", async (req, res) => { try { const { libraryid } = req.body; diff --git a/frontend/src/pages/activity.js b/frontend/src/pages/activity.js index d046c6db..f70473d2 100644 --- a/frontend/src/pages/activity.js +++ b/frontend/src/pages/activity.js @@ -1,5 +1,4 @@ import React, { useState, useEffect } from "react"; - import axios from "axios"; import "./css/activity.css"; @@ -9,10 +8,11 @@ import ActivityTable from "./components/activity/activity-table"; import Loading from "./components/general/loading"; function Activity() { - const [data, setData] = useState(); + const [data, setData] = useState([]); const [config, setConfig] = useState(null); - const [itemCount, setItemCount] = useState(10); + const [itemCount, setItemCount] = useState(10); // Nombre d'éléments par page + const [page, setPage] = useState(0); // Page actuelle useEffect(() => { const fetchConfig = async () => { @@ -34,44 +34,32 @@ function Activity() { Authorization: `Bearer ${config.token}`, "Content-Type": "application/json", }, + params: { + page, + limit: itemCount, + }, }) - .then((data) => { - setData(data.data); + .then((response) => { + setData(response.data.data); }) .catch((error) => { console.log(error); }); }; - if (!data && config) { + if (config) { fetchLibraries(); - } - - if (!config) { + } else { fetchConfig(); } - const intervalId = setInterval(fetchLibraries, 60000 * 60); - return () => clearInterval(intervalId); - }, [data, config]); + return () => {}; + }, [config, page, itemCount]); - if (!data) { + if (!data.length) { return ; } - if (data.length === 0) { - return ( -
-
-

Activity

-
-
-

No Activity to display

-
-
- ); - } - return (
@@ -82,6 +70,7 @@ function Activity() { value={itemCount} onChange={(event) => { setItemCount(event.target.value); + setPage(0); // Revenir à la première page lors du changement de nombre d'éléments }} > @@ -92,7 +81,12 @@ function Activity() {
- +
); diff --git a/frontend/src/pages/components/activity/activity-table.js b/frontend/src/pages/components/activity/activity-table.js index 78201cbe..4693e3bc 100644 --- a/frontend/src/pages/components/activity/activity-table.js +++ b/frontend/src/pages/components/activity/activity-table.js @@ -21,7 +21,6 @@ import StreamInfo from "./stream_info"; import "../../css/activity/activity-table.css"; -// localStorage.setItem('hour12',true); function formatTotalWatchTime(seconds) { const hours = Math.floor(seconds / 3600); @@ -134,12 +133,10 @@ function Row(data) { openModal(row)}>{row.Client} - {Intl.DateTimeFormat("en-UK", options).format( - new Date(row.ActivityDateInserted), - )} + {row.ActivityDateInserted} - {formatTotalWatchTime(row.PlaybackDuration) || "0 seconds"} + {formatTotalWatchTime(row.TotalPlaybackDuration) || "0 seconds"} {row.results.length !== 0 ? row.results.length : 1} @@ -302,23 +299,17 @@ function EnhancedTableHead(props) { } export default function ActivityTable(props) { - const [page, setPage] = React.useState(0); - const [rowsPerPage, setRowsPerPage] = React.useState(10); const [order, setOrder] = React.useState("desc"); const [orderBy, setOrderBy] = React.useState("ActivityDateInserted"); - if (rowsPerPage !== props.itemCount) { - setRowsPerPage(props.itemCount); - setPage(0); - } const handleNextPageClick = () => { - setPage((prevPage) => prevPage + 1); + props.setPage(() => props.page + 1); }; const handlePreviousPageClick = () => { - setPage((prevPage) => prevPage - 1); + props.setPage(() => props.page - 1); }; function descendingComparator(a, b, orderBy) { @@ -352,14 +343,6 @@ export default function ActivityTable(props) { return stabilizedThis.map((el) => el[0]); } - const visibleRows = React.useMemo( - () => - stableSort(props.data, getComparator(order, orderBy)).slice( - page * rowsPerPage, - page * rowsPerPage + rowsPerPage, - ), - [order, orderBy, page, rowsPerPage, getComparator, props.data], - ); const handleRequestSort = (event, property) => { const isAsc = orderBy === property && order === "asc"; @@ -375,10 +358,10 @@ export default function ActivityTable(props) { order={order} orderBy={orderBy} onRequestSort={handleRequestSort} - rowCount={rowsPerPage} + rowCount={props.itemPerPage} /> - {visibleRows.map((row) => ( + {props.data.map((row) => ( @@ -418,35 +401,24 @@ export default function ActivityTable(props) {
{`${ - page * rowsPerPage + 1 - }-${Math.min( - page * rowsPerPage + 1 + (rowsPerPage - 1), - props.data.length, - )} of ${props.data.length}`}
+ (props.page) * props.itemPerPage + 1 + }-${ + props.page * props.itemPerPage + 1 + (props.itemPerPage - 1) + }`} -