mirror of
https://github.com/BreizhHardware/Jellystat.git
synced 2026-01-18 16:27:20 +01:00
added sorting to history endpoints and changed Activity tables to apply sorting to api calls
This commit is contained in:
@@ -12,7 +12,8 @@ function wrapField(field) {
|
||||
field.includes("MIN") ||
|
||||
field.includes("AVG") ||
|
||||
field.includes("DISTINCT") ||
|
||||
field.includes("json_agg")
|
||||
field.includes("json_agg") ||
|
||||
field.includes("CASE")
|
||||
) {
|
||||
return field;
|
||||
}
|
||||
|
||||
@@ -17,6 +17,28 @@ const { tables } = require("../global/backup_tables");
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
//consts
|
||||
const groupedSortMap = [
|
||||
{ field: "UserName", column: "a.UserName" },
|
||||
{ field: "RemoteEndPoint", column: "a.RemoteEndPoint" },
|
||||
{ field: "NowPlayingItemName", column: "FullName" },
|
||||
{ field: "Client", column: "a.Client" },
|
||||
{ field: "DeviceName", column: "a.DeviceName" },
|
||||
{ field: "ActivityDateInserted", column: "a.ActivityDateInserted" },
|
||||
{ field: "PlaybackDuration", column: "ar.TotalDuration" },
|
||||
{ field: "TotalPlays", column: "TotalPlays" },
|
||||
];
|
||||
|
||||
const unGroupedSortMap = [
|
||||
{ field: "UserName", column: "a.UserName" },
|
||||
{ field: "RemoteEndPoint", column: "a.RemoteEndPoint" },
|
||||
{ field: "NowPlayingItemName", column: "FullName" },
|
||||
{ field: "Client", column: "a.Client" },
|
||||
{ field: "DeviceName", column: "a.DeviceName" },
|
||||
{ field: "ActivityDateInserted", column: "a.ActivityDateInserted" },
|
||||
{ field: "PlaybackDuration", column: "a.PlaybackDuration" },
|
||||
];
|
||||
|
||||
//Functions
|
||||
function groupRecentlyAdded(rows) {
|
||||
const groupedResults = {};
|
||||
@@ -1058,7 +1080,9 @@ router.post("/setExcludedBackupTable", async (req, res) => {
|
||||
|
||||
//DB Queries - History
|
||||
router.get("/getHistory", async (req, res) => {
|
||||
const { size = 50, page = 1, search } = req.query;
|
||||
const { size = 50, page = 1, search, sort = "ActivityDateInserted", desc = true } = req.query;
|
||||
|
||||
const sortField = groupedSortMap.find((item) => item.field === sort)?.column || "a.ActivityDateInserted";
|
||||
|
||||
try {
|
||||
const cte = {
|
||||
@@ -1078,7 +1102,21 @@ router.get("/getHistory", async (req, res) => {
|
||||
|
||||
const query = {
|
||||
cte: cte,
|
||||
select: ["a.*", "a.EpisodeNumber", "a.SeasonNumber", "a.ParentId", "ar.results", "ar.TotalPlays", "ar.TotalDuration"],
|
||||
select: [
|
||||
"a.*",
|
||||
"a.EpisodeNumber",
|
||||
"a.SeasonNumber",
|
||||
"a.ParentId",
|
||||
"ar.results",
|
||||
"ar.TotalPlays",
|
||||
"ar.TotalDuration",
|
||||
`
|
||||
CASE
|
||||
WHEN a."SeriesName" is null THEN a."NowPlayingItemName"
|
||||
ELSE CONCAT(a."SeriesName" , ' : S' , a."SeasonNumber" , 'E' , a."EpisodeNumber" , ' - ' , a."NowPlayingItemName")
|
||||
END AS "FullName"
|
||||
`,
|
||||
],
|
||||
table: "js_latest_playback_activity",
|
||||
alias: "a",
|
||||
joins: [
|
||||
@@ -1094,8 +1132,8 @@ router.get("/getHistory", async (req, res) => {
|
||||
},
|
||||
],
|
||||
|
||||
order_by: "a.ActivityDateInserted",
|
||||
sort_order: "desc",
|
||||
order_by: sortField,
|
||||
sort_order: desc ? "desc" : "asc",
|
||||
pageNumber: page,
|
||||
pageSize: size,
|
||||
};
|
||||
@@ -1103,7 +1141,12 @@ router.get("/getHistory", async (req, res) => {
|
||||
if (search && search.length > 0) {
|
||||
query.where = [
|
||||
{
|
||||
field: `LOWER(COALESCE(a."SeriesName" || ' - ' || a."NowPlayingItemName", a."NowPlayingItemName"))`,
|
||||
field: `LOWER(
|
||||
CASE
|
||||
WHEN a."SeriesName" is null THEN a."NowPlayingItemName"
|
||||
ELSE CONCAT(a."SeriesName" , ' : S' , a."SeasonNumber" , 'E' , a."EpisodeNumber" , ' - ' , a."NowPlayingItemName")
|
||||
END
|
||||
)`,
|
||||
operator: "LIKE",
|
||||
value: `${search.toLowerCase()}`,
|
||||
},
|
||||
@@ -1115,10 +1158,11 @@ router.get("/getHistory", async (req, res) => {
|
||||
...item,
|
||||
PlaybackDuration: item.TotalDuration ? item.TotalDuration : item.PlaybackDuration,
|
||||
}));
|
||||
const response = { current_page: page, pages: result.pages, size: size, results: result.results };
|
||||
const response = { current_page: page, pages: result.pages, size: size, sort: sort, desc: desc, results: result.results };
|
||||
if (search && search.length > 0) {
|
||||
response.search = search;
|
||||
}
|
||||
|
||||
res.send(response);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
@@ -1127,7 +1171,7 @@ router.get("/getHistory", async (req, res) => {
|
||||
|
||||
router.post("/getLibraryHistory", async (req, res) => {
|
||||
try {
|
||||
const { size = 50, page = 1, search } = req.query;
|
||||
const { size = 50, page = 1, search, sort = "ActivityDateInserted", desc = true } = req.query;
|
||||
const { libraryid } = req.body;
|
||||
|
||||
if (libraryid === undefined) {
|
||||
@@ -1136,6 +1180,8 @@ router.post("/getLibraryHistory", async (req, res) => {
|
||||
return;
|
||||
}
|
||||
|
||||
const sortField = groupedSortMap.find((item) => item.field === sort)?.column || "a.ActivityDateInserted";
|
||||
|
||||
const cte = {
|
||||
cteAlias: "activity_results",
|
||||
select: [
|
||||
@@ -1153,7 +1199,21 @@ router.post("/getLibraryHistory", async (req, res) => {
|
||||
|
||||
const query = {
|
||||
cte: cte,
|
||||
select: ["a.*", "a.EpisodeNumber", "a.SeasonNumber", "a.ParentId", "ar.results", "ar.TotalPlays", "ar.TotalDuration"],
|
||||
select: [
|
||||
"a.*",
|
||||
"a.EpisodeNumber",
|
||||
"a.SeasonNumber",
|
||||
"a.ParentId",
|
||||
"ar.results",
|
||||
"ar.TotalPlays",
|
||||
"ar.TotalDuration",
|
||||
`
|
||||
CASE
|
||||
WHEN a."SeriesName" is null THEN a."NowPlayingItemName"
|
||||
ELSE CONCAT(a."SeriesName" , ' : S' , a."SeasonNumber" , 'E' , a."EpisodeNumber" , ' - ' , a."NowPlayingItemName")
|
||||
END AS "FullName"
|
||||
`,
|
||||
],
|
||||
table: "js_latest_playback_activity",
|
||||
alias: "a",
|
||||
joins: [
|
||||
@@ -1178,8 +1238,8 @@ router.post("/getLibraryHistory", async (req, res) => {
|
||||
},
|
||||
],
|
||||
|
||||
order_by: "a.ActivityDateInserted",
|
||||
sort_order: "desc",
|
||||
order_by: sortField,
|
||||
sort_order: desc ? "desc" : "asc",
|
||||
pageNumber: page,
|
||||
pageSize: size,
|
||||
};
|
||||
@@ -1187,9 +1247,14 @@ router.post("/getLibraryHistory", async (req, res) => {
|
||||
if (search && search.length > 0) {
|
||||
query.where = [
|
||||
{
|
||||
field: `LOWER(COALESCE(a."SeriesName" || ' - ' || a."NowPlayingItemName", a."NowPlayingItemName"))`,
|
||||
field: `LOWER(
|
||||
CASE
|
||||
WHEN a."SeriesName" is null THEN a."NowPlayingItemName"
|
||||
ELSE CONCAT(a."SeriesName" , ' : S' , a."SeasonNumber" , 'E' , a."EpisodeNumber" , ' - ' , a."NowPlayingItemName")
|
||||
END
|
||||
)`,
|
||||
operator: "LIKE",
|
||||
value: `%${search.toLowerCase()}%`,
|
||||
value: `${search.toLowerCase()}`,
|
||||
},
|
||||
];
|
||||
}
|
||||
@@ -1201,7 +1266,7 @@ router.post("/getLibraryHistory", async (req, res) => {
|
||||
PlaybackDuration: item.TotalDuration ? item.TotalDuration : item.PlaybackDuration,
|
||||
}));
|
||||
|
||||
const response = { current_page: page, pages: result.pages, size: size, results: result.results };
|
||||
const response = { current_page: page, pages: result.pages, size: size, sort: sort, desc: desc, results: result.results };
|
||||
if (search && search.length > 0) {
|
||||
response.search = search;
|
||||
}
|
||||
@@ -1215,7 +1280,7 @@ router.post("/getLibraryHistory", async (req, res) => {
|
||||
|
||||
router.post("/getItemHistory", async (req, res) => {
|
||||
try {
|
||||
const { size = 50, page = 1, search } = req.query;
|
||||
const { size = 50, page = 1, search, sort = "ActivityDateInserted", desc = true } = req.query;
|
||||
const { itemid } = req.body;
|
||||
|
||||
if (itemid === undefined) {
|
||||
@@ -1224,8 +1289,21 @@ router.post("/getItemHistory", async (req, res) => {
|
||||
return;
|
||||
}
|
||||
|
||||
const sortField = unGroupedSortMap.find((item) => item.field === sort)?.column || "a.ActivityDateInserted";
|
||||
|
||||
const query = {
|
||||
select: ["a.*", "a.EpisodeNumber", "a.SeasonNumber", "a.ParentId"],
|
||||
select: [
|
||||
"a.*",
|
||||
"a.EpisodeNumber",
|
||||
"a.SeasonNumber",
|
||||
"a.ParentId",
|
||||
`
|
||||
CASE
|
||||
WHEN a."SeriesName" is null THEN a."NowPlayingItemName"
|
||||
ELSE CONCAT(a."SeriesName" , ' : S' , a."SeasonNumber" , 'E' , a."EpisodeNumber" , ' - ' , a."NowPlayingItemName")
|
||||
END AS "FullName"
|
||||
`,
|
||||
],
|
||||
table: "jf_playback_activity_with_metadata",
|
||||
alias: "a",
|
||||
where: [
|
||||
@@ -1235,25 +1313,30 @@ router.post("/getItemHistory", async (req, res) => {
|
||||
{ column: "a.NowPlayingItemId", operator: "=", value: itemid, type: "or" },
|
||||
],
|
||||
],
|
||||
order_by: "ActivityDateInserted",
|
||||
sort_order: "desc",
|
||||
order_by: sortField,
|
||||
sort_order: desc ? "desc" : "asc",
|
||||
pageNumber: page,
|
||||
pageSize: size,
|
||||
};
|
||||
|
||||
if (search && search.length > 0) {
|
||||
query.where.push([
|
||||
query.where = [
|
||||
{
|
||||
field: `LOWER(COALESCE(a."SeriesName" || ' - ' || a."NowPlayingItemName", a."NowPlayingItemName"))`,
|
||||
field: `LOWER(
|
||||
CASE
|
||||
WHEN a."SeriesName" is null THEN a."NowPlayingItemName"
|
||||
ELSE CONCAT(a."SeriesName" , ' : S' , a."SeasonNumber" , 'E' , a."EpisodeNumber" , ' - ' , a."NowPlayingItemName")
|
||||
END
|
||||
)`,
|
||||
operator: "LIKE",
|
||||
value: `%${search.toLowerCase()}%`,
|
||||
value: `${search.toLowerCase()}`,
|
||||
},
|
||||
]);
|
||||
];
|
||||
}
|
||||
|
||||
const result = await dbHelper.query(query);
|
||||
|
||||
const response = { current_page: page, pages: result.pages, size: size, results: result.results };
|
||||
const response = { current_page: page, pages: result.pages, size: size, sort: sort, desc: desc, results: result.results };
|
||||
if (search && search.length > 0) {
|
||||
response.search = search;
|
||||
}
|
||||
@@ -1267,7 +1350,7 @@ router.post("/getItemHistory", async (req, res) => {
|
||||
|
||||
router.post("/getUserHistory", async (req, res) => {
|
||||
try {
|
||||
const { size = 50, page = 1, search } = req.query;
|
||||
const { size = 50, page = 1, search, sort = "ActivityDateInserted", desc = true } = req.query;
|
||||
const { userid } = req.body;
|
||||
|
||||
if (userid === undefined) {
|
||||
@@ -1276,29 +1359,47 @@ router.post("/getUserHistory", async (req, res) => {
|
||||
return;
|
||||
}
|
||||
|
||||
const sortField = unGroupedSortMap.find((item) => item.field === sort)?.column || "a.ActivityDateInserted";
|
||||
|
||||
const query = {
|
||||
select: ["a.*", "a.EpisodeNumber", "a.SeasonNumber", "a.ParentId"],
|
||||
select: [
|
||||
"a.*",
|
||||
"a.EpisodeNumber",
|
||||
"a.SeasonNumber",
|
||||
"a.ParentId",
|
||||
`
|
||||
CASE
|
||||
WHEN a."SeriesName" is null THEN a."NowPlayingItemName"
|
||||
ELSE CONCAT(a."SeriesName" , ' : S' , a."SeasonNumber" , 'E' , a."EpisodeNumber" , ' - ' , a."NowPlayingItemName")
|
||||
END AS "FullName"
|
||||
`,
|
||||
],
|
||||
table: "jf_playback_activity_with_metadata",
|
||||
alias: "a",
|
||||
where: [[{ column: "a.UserId", operator: "=", value: userid }]],
|
||||
order_by: "ActivityDateInserted",
|
||||
sort_order: "desc",
|
||||
order_by: sortField,
|
||||
sort_order: desc ? "desc" : "asc",
|
||||
pageNumber: page,
|
||||
pageSize: size,
|
||||
};
|
||||
|
||||
if (search && search.length > 0) {
|
||||
query.where.push([
|
||||
query.where = [
|
||||
{
|
||||
field: `LOWER(COALESCE(a."SeriesName" || ' - ' || a."NowPlayingItemName", a."NowPlayingItemName"))`,
|
||||
field: `LOWER(
|
||||
CASE
|
||||
WHEN a."SeriesName" is null THEN a."NowPlayingItemName"
|
||||
ELSE CONCAT(a."SeriesName" , ' : S' , a."SeasonNumber" , 'E' , a."EpisodeNumber" , ' - ' , a."NowPlayingItemName")
|
||||
END
|
||||
)`,
|
||||
operator: "LIKE",
|
||||
value: `%${search.toLowerCase()}%`,
|
||||
value: `${search.toLowerCase()}`,
|
||||
},
|
||||
]);
|
||||
];
|
||||
}
|
||||
const result = await dbHelper.query(query);
|
||||
|
||||
const response = { current_page: page, pages: result.pages, size: size, results: result.results };
|
||||
const response = { current_page: page, pages: result.pages, size: size, sort: sort, desc: desc, results: result.results };
|
||||
|
||||
if (search && search.length > 0) {
|
||||
response.search = search;
|
||||
|
||||
@@ -27,12 +27,17 @@ function Activity() {
|
||||
const [libraries, setLibraries] = useState([]);
|
||||
const [showLibraryFilters, setShowLibraryFilters] = useState(false);
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const [sorting, setSorting] = useState({ column: "ActivityDateInserted", desc: true });
|
||||
const [isBusy, setIsBusy] = useState(false);
|
||||
|
||||
const handlePageChange = (newPage) => {
|
||||
setCurrentPage(newPage);
|
||||
};
|
||||
|
||||
const onSortChange = (sort) => {
|
||||
setSorting({ column: sort.column, desc: sort.desc });
|
||||
};
|
||||
|
||||
function setItemLimit(limit) {
|
||||
setItemCount(parseInt(limit));
|
||||
localStorage.setItem("PREF_ACTIVITY_ItemCount", limit);
|
||||
@@ -82,7 +87,7 @@ function Activity() {
|
||||
|
||||
const fetchHistory = () => {
|
||||
setIsBusy(true);
|
||||
const url = `/api/getHistory?size=${itemCount}&page=${currentPage}&search=${debouncedSearchQuery}`;
|
||||
const url = `/api/getHistory?size=${itemCount}&page=${currentPage}&search=${debouncedSearchQuery}&sort=${sorting.column}&desc=${sorting.desc}`;
|
||||
axios
|
||||
.get(url, {
|
||||
headers: {
|
||||
@@ -136,7 +141,9 @@ function Activity() {
|
||||
!data ||
|
||||
(data.current_page && data.current_page !== currentPage) ||
|
||||
(data.size && data.size !== itemCount) ||
|
||||
(data.search ? data.search : "") !== debouncedSearchQuery.trim()
|
||||
(data?.search ?? "") !== debouncedSearchQuery.trim() ||
|
||||
(data?.sort ?? "") !== sorting.column ||
|
||||
(data?.desc ?? true) !== sorting.desc
|
||||
) {
|
||||
fetchHistory();
|
||||
fetchLibraries();
|
||||
@@ -149,7 +156,7 @@ function Activity() {
|
||||
|
||||
const intervalId = setInterval(fetchHistory, 60000 * 60);
|
||||
return () => clearInterval(intervalId);
|
||||
}, [data, config, itemCount, currentPage, debouncedSearchQuery]);
|
||||
}, [data, config, itemCount, currentPage, debouncedSearchQuery, sorting]);
|
||||
|
||||
if (!data) {
|
||||
return <Loading />;
|
||||
@@ -271,6 +278,7 @@ function Activity() {
|
||||
data={filteredData}
|
||||
itemCount={itemCount}
|
||||
onPageChange={handlePageChange}
|
||||
onSortChange={onSortChange}
|
||||
pageCount={data.pages}
|
||||
isBusy={isBusy}
|
||||
/>
|
||||
|
||||
@@ -70,6 +70,7 @@ export default function ActivityTable(props) {
|
||||
pageSize: 10,
|
||||
pageIndex: 0,
|
||||
});
|
||||
const [sorting, setSorting] = React.useState([{ id: "Date", desc: true }]);
|
||||
|
||||
const [modalState, setModalState] = React.useState(false);
|
||||
const [modalData, setModalData] = React.useState();
|
||||
@@ -84,6 +85,7 @@ export default function ActivityTable(props) {
|
||||
return newPaginationState;
|
||||
});
|
||||
};
|
||||
|
||||
//IP MODAL
|
||||
|
||||
const ipv4Regex = new RegExp(
|
||||
@@ -188,6 +190,7 @@ export default function ActivityTable(props) {
|
||||
? row.NowPlayingItemName
|
||||
: row.SeriesName + " : S" + row.SeasonNumber + "E" + row.EpisodeNumber + " - " + row.NowPlayingItemName
|
||||
}`,
|
||||
field: "NowPlayingItemName",
|
||||
header: i18next.t("TITLE"),
|
||||
minSize: 300,
|
||||
Cell: ({ row }) => {
|
||||
@@ -221,6 +224,7 @@ export default function ActivityTable(props) {
|
||||
},
|
||||
{
|
||||
accessorFn: (row) => new Date(row.ActivityDateInserted),
|
||||
field: "ActivityDateInserted",
|
||||
header: i18next.t("DATE"),
|
||||
size: 110,
|
||||
filterVariant: "date-range",
|
||||
@@ -248,6 +252,7 @@ export default function ActivityTable(props) {
|
||||
},
|
||||
{
|
||||
accessorFn: (row) => Number(row.TotalPlays ?? 1),
|
||||
field: "TotalPlays",
|
||||
header: i18next.t("TOTAL_PLAYS"),
|
||||
filterFn: "betweenInclusive",
|
||||
|
||||
@@ -255,6 +260,22 @@ export default function ActivityTable(props) {
|
||||
},
|
||||
];
|
||||
|
||||
const fieldMap = columns.map((column) => {
|
||||
return { accessorKey: column.accessorKey ?? column.field, header: column.header };
|
||||
});
|
||||
|
||||
const handleSortingChange = (updater) => {
|
||||
setSorting((old) => {
|
||||
const newSortingState = typeof updater === "function" ? updater(old) : updater;
|
||||
const column = newSortingState.length > 0 ? newSortingState[0].id : "Date";
|
||||
const desc = newSortingState.length > 0 ? newSortingState[0].desc : true;
|
||||
if (props.onSortChange) {
|
||||
props.onSortChange({ column: fieldMap.find((field) => field.header == column)?.accessorKey ?? column, desc: desc });
|
||||
}
|
||||
return newSortingState;
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setData(props.data);
|
||||
}, [props.data]);
|
||||
@@ -279,8 +300,10 @@ export default function ActivityTable(props) {
|
||||
enableExpandAll: false,
|
||||
enableExpanding: true,
|
||||
enableDensityToggle: false,
|
||||
onSortingChange: handleSortingChange,
|
||||
enableTopToolbar: Object.keys(rowSelection).length > 0,
|
||||
manualPagination: true,
|
||||
manualSorting: true,
|
||||
autoResetPageIndex: false,
|
||||
initialState: {
|
||||
expanded: false,
|
||||
@@ -354,7 +377,7 @@ export default function ActivityTable(props) {
|
||||
},
|
||||
},
|
||||
},
|
||||
state: { rowSelection, pagination },
|
||||
state: { rowSelection, pagination, sorting },
|
||||
filterFromLeafRows: true,
|
||||
getSubRows: (row) => {
|
||||
if (Array.isArray(row.results) && row.results.length == 1) {
|
||||
|
||||
@@ -15,11 +15,17 @@ function ItemActivity(props) {
|
||||
const [streamTypeFilter, setStreamTypeFilter] = useState("All");
|
||||
const [config, setConfig] = useState();
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const [sorting, setSorting] = useState({ column: "ActivityDateInserted", desc: true });
|
||||
const [isBusy, setIsBusy] = useState(false);
|
||||
|
||||
const handlePageChange = (newPage) => {
|
||||
setCurrentPage(newPage);
|
||||
};
|
||||
|
||||
const onSortChange = (sort) => {
|
||||
setSorting({ column: sort.column, desc: sort.desc });
|
||||
};
|
||||
|
||||
function setItemLimit(limit) {
|
||||
setItemCount(parseInt(limit));
|
||||
localStorage.setItem("PREF_ACTIVITY_ItemCount", limit);
|
||||
@@ -53,7 +59,7 @@ function ItemActivity(props) {
|
||||
try {
|
||||
setIsBusy(true);
|
||||
const itemData = await axios.post(
|
||||
`/api/getItemHistory?size=${itemCount}&page=${currentPage}&search=${debouncedSearchQuery}`,
|
||||
`/api/getItemHistory?size=${itemCount}&page=${currentPage}&search=${debouncedSearchQuery}&sort=${sorting.column}&desc=${sorting.desc}`,
|
||||
{
|
||||
itemid: props.itemid,
|
||||
},
|
||||
@@ -75,14 +81,16 @@ function ItemActivity(props) {
|
||||
!data ||
|
||||
(data.current_page && data.current_page !== currentPage) ||
|
||||
(data.size && data.size !== itemCount) ||
|
||||
(data.search ? data.search : "") !== debouncedSearchQuery.trim()
|
||||
(data?.search ?? "") !== debouncedSearchQuery.trim() ||
|
||||
(data?.sort ?? "") !== sorting.column ||
|
||||
(data?.desc ?? true) !== sorting.desc
|
||||
) {
|
||||
fetchData();
|
||||
}
|
||||
|
||||
const intervalId = setInterval(fetchData, 60000 * 5);
|
||||
return () => clearInterval(intervalId);
|
||||
}, [data, props.itemid, token, itemCount, currentPage, debouncedSearchQuery]);
|
||||
}, [data, props.itemid, token, itemCount, currentPage, debouncedSearchQuery, sorting]);
|
||||
|
||||
if (!data || !data.results) {
|
||||
return <></>;
|
||||
@@ -168,6 +176,7 @@ function ItemActivity(props) {
|
||||
data={filteredData}
|
||||
itemCount={itemCount}
|
||||
onPageChange={handlePageChange}
|
||||
onSortChange={onSortChange}
|
||||
pageCount={data.pages}
|
||||
isBusy={isBusy}
|
||||
/>
|
||||
|
||||
@@ -18,12 +18,17 @@ function LibraryActivity(props) {
|
||||
);
|
||||
const [config, setConfig] = useState();
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const [sorting, setSorting] = useState({ column: "ActivityDateInserted", desc: true });
|
||||
const [isBusy, setIsBusy] = useState(false);
|
||||
|
||||
const handlePageChange = (newPage) => {
|
||||
setCurrentPage(newPage);
|
||||
};
|
||||
|
||||
const onSortChange = (sort) => {
|
||||
setSorting({ column: sort.column, desc: sort.desc });
|
||||
};
|
||||
|
||||
function setItemLimit(limit) {
|
||||
setItemCount(parseInt(limit));
|
||||
localStorage.setItem("PREF_LIBRARY_ACTIVITY_ItemCount", limit);
|
||||
@@ -61,7 +66,7 @@ function LibraryActivity(props) {
|
||||
try {
|
||||
setIsBusy(true);
|
||||
const libraryData = await axios.post(
|
||||
`/api/getLibraryHistory?size=${itemCount}&page=${currentPage}&search=${debouncedSearchQuery}`,
|
||||
`/api/getLibraryHistory?size=${itemCount}&page=${currentPage}&search=${debouncedSearchQuery}&sort=${sorting.column}&desc=${sorting.desc}`,
|
||||
{
|
||||
libraryid: props.LibraryId,
|
||||
},
|
||||
@@ -83,14 +88,16 @@ function LibraryActivity(props) {
|
||||
!data ||
|
||||
(data.current_page && data.current_page !== currentPage) ||
|
||||
(data.size && data.size !== itemCount) ||
|
||||
(data.search ? data.search : "") !== debouncedSearchQuery.trim()
|
||||
(data?.search ?? "") !== debouncedSearchQuery.trim() ||
|
||||
(data?.sort ?? "") !== sorting.column ||
|
||||
(data?.desc ?? true) !== sorting.desc
|
||||
) {
|
||||
fetchData();
|
||||
}
|
||||
|
||||
const intervalId = setInterval(fetchData, 60000 * 5);
|
||||
return () => clearInterval(intervalId);
|
||||
}, [data, props.LibraryId, token, itemCount, currentPage, debouncedSearchQuery]);
|
||||
}, [data, props.LibraryId, token, itemCount, currentPage, debouncedSearchQuery, sorting]);
|
||||
|
||||
if (!data || !data.results) {
|
||||
return <></>;
|
||||
@@ -175,6 +182,7 @@ function LibraryActivity(props) {
|
||||
data={filteredData}
|
||||
itemCount={itemCount}
|
||||
onPageChange={handlePageChange}
|
||||
onSortChange={onSortChange}
|
||||
pageCount={data.pages}
|
||||
isBusy={isBusy}
|
||||
/>
|
||||
|
||||
@@ -22,6 +22,7 @@ function UserActivity(props) {
|
||||
const [showLibraryFilters, setShowLibraryFilters] = useState(false);
|
||||
const [config, setConfig] = useState();
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const [sorting, setSorting] = useState({ column: "ActivityDateInserted", desc: true });
|
||||
const [isBusy, setIsBusy] = useState(false);
|
||||
|
||||
function setItemLimit(limit) {
|
||||
@@ -73,12 +74,16 @@ function UserActivity(props) {
|
||||
setCurrentPage(newPage);
|
||||
};
|
||||
|
||||
const onSortChange = (sort) => {
|
||||
setSorting({ column: sort.column, desc: sort.desc });
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const fetchHistory = async () => {
|
||||
try {
|
||||
setIsBusy(true);
|
||||
const itemData = await axios.post(
|
||||
`/api/getUserHistory?size=${itemCount}&page=${currentPage}&search=${debouncedSearchQuery}`,
|
||||
`/api/getUserHistory?size=${itemCount}&page=${currentPage}&search=${debouncedSearchQuery}&sort=${sorting.column}&desc=${sorting.desc}`,
|
||||
{
|
||||
userid: props.UserId,
|
||||
},
|
||||
@@ -125,7 +130,9 @@ function UserActivity(props) {
|
||||
!data ||
|
||||
(data.current_page && data.current_page !== currentPage) ||
|
||||
(data.size && data.size !== itemCount) ||
|
||||
(data.search ? data.search : "") !== debouncedSearchQuery.trim()
|
||||
(data?.search ?? "") !== debouncedSearchQuery.trim() ||
|
||||
(data?.sort ?? "") !== sorting.column ||
|
||||
(data?.desc ?? true) !== sorting.desc
|
||||
) {
|
||||
fetchHistory();
|
||||
}
|
||||
@@ -134,7 +141,7 @@ function UserActivity(props) {
|
||||
|
||||
const intervalId = setInterval(fetchHistory, 60000 * 5);
|
||||
return () => clearInterval(intervalId);
|
||||
}, [props.UserId, token, itemCount, currentPage, debouncedSearchQuery]);
|
||||
}, [props.UserId, token, itemCount, currentPage, debouncedSearchQuery, sorting]);
|
||||
|
||||
if (!data || !data.results) {
|
||||
return <></>;
|
||||
@@ -240,6 +247,7 @@ function UserActivity(props) {
|
||||
data={filteredData}
|
||||
itemCount={itemCount}
|
||||
onPageChange={handlePageChange}
|
||||
onSortChange={onSortChange}
|
||||
pageCount={data.pages}
|
||||
isBusy={isBusy}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user