mirror of
https://github.com/BreizhHardware/Jellystat.git
synced 2026-03-18 21:30:35 +01:00
added filtering to all activity table fields and api history endpoints
This commit is contained in:
@@ -39,6 +39,25 @@ const unGroupedSortMap = [
|
||||
{ field: "PlaybackDuration", column: "a.PlaybackDuration" },
|
||||
];
|
||||
|
||||
const filterFields = [
|
||||
{ field: "UserName", column: `LOWER(u."Name")` },
|
||||
{ field: "RemoteEndPoint", column: `LOWER(a."RemoteEndPoint")` },
|
||||
{
|
||||
field: "NowPlayingItemName",
|
||||
column: `LOWER(
|
||||
CASE
|
||||
WHEN a."SeriesName" is null THEN a."NowPlayingItemName"
|
||||
ELSE CONCAT(a."SeriesName" , ' : S' , a."SeasonNumber" , 'E' , a."EpisodeNumber" , ' - ' , a."NowPlayingItemName")
|
||||
END
|
||||
)`,
|
||||
},
|
||||
{ field: "Client", column: `LOWER(a."Client")` },
|
||||
{ field: "DeviceName", column: `LOWER(a."DeviceName")` },
|
||||
{ field: "ActivityDateInserted", column: "a.ActivityDateInserted", isColumn: true },
|
||||
{ field: "PlaybackDuration", column: `a.PlaybackDuration`, isColumn: true, applyToCTE: true },
|
||||
{ field: "TotalPlays", column: `COALESCE("TotalPlays",1)` },
|
||||
];
|
||||
|
||||
//Functions
|
||||
function groupRecentlyAdded(rows) {
|
||||
const groupedResults = {};
|
||||
@@ -121,6 +140,82 @@ async function purgeLibraryItems(id, withActivity, purgeAll = false) {
|
||||
}
|
||||
}
|
||||
|
||||
function buildFilterList(query, filtersArray) {
|
||||
if (filtersArray.length > 0) {
|
||||
query.where = query.where || [];
|
||||
filtersArray.forEach((filter) => {
|
||||
const findField = filterFields.find((item) => item.field === filter.field);
|
||||
const column = findField?.column || "a.ActivityDateInserted";
|
||||
const isColumn = findField?.isColumn || false;
|
||||
const applyToCTE = findField?.applyToCTE || false;
|
||||
if (filter.min) {
|
||||
query.where.push({
|
||||
column: column,
|
||||
operator: ">=",
|
||||
value: filter.min,
|
||||
});
|
||||
|
||||
if (applyToCTE) {
|
||||
if (query.cte) {
|
||||
if (!query.cte.where) {
|
||||
query.cte.where = [];
|
||||
}
|
||||
query.cte.where.push({
|
||||
column: column,
|
||||
operator: ">=",
|
||||
value: filter.min,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (filter.max) {
|
||||
query.where.push({
|
||||
column: column,
|
||||
operator: "<=",
|
||||
value: filter.max,
|
||||
});
|
||||
|
||||
if (applyToCTE) {
|
||||
if (query.cte) {
|
||||
if (!query.cte.where) {
|
||||
query.cte.where = [];
|
||||
}
|
||||
query.cte.where.push({
|
||||
column: column,
|
||||
operator: "<=",
|
||||
value: filter.max,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (filter.value) {
|
||||
const whereClause = {
|
||||
operator: "LIKE",
|
||||
value: filter.value.toLowerCase(),
|
||||
};
|
||||
if (isColumn) {
|
||||
whereClause.column = column;
|
||||
} else {
|
||||
whereClause.field = column;
|
||||
}
|
||||
query.where.push(whereClause);
|
||||
|
||||
if (applyToCTE) {
|
||||
if (query.cte) {
|
||||
if (!query.cte.where) {
|
||||
query.cte.where = [];
|
||||
}
|
||||
query.cte.where.push(whereClause);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
router.get("/getconfig", async (req, res) => {
|
||||
try {
|
||||
const config = await new configClass().getConfig();
|
||||
@@ -1080,7 +1175,55 @@ router.post("/setExcludedBackupTable", async (req, res) => {
|
||||
|
||||
//DB Queries - History
|
||||
router.get("/getHistory", async (req, res) => {
|
||||
const { size = 50, page = 1, search, sort = "ActivityDateInserted", desc = true } = req.query;
|
||||
const { size = 50, page = 1, search, sort = "ActivityDateInserted", desc = true, filters } = req.query;
|
||||
|
||||
let filtersArray = [];
|
||||
if (filters) {
|
||||
try {
|
||||
filtersArray = JSON.parse(filters);
|
||||
} catch (error) {
|
||||
return res.status(400).json({
|
||||
error: "Invalid filters parameter",
|
||||
example: [
|
||||
{
|
||||
field: "ActivityDateInserted",
|
||||
min: "2024-12-31T22:00:00.000Z",
|
||||
max: "2024-12-31T22:00:00.000Z",
|
||||
},
|
||||
{
|
||||
field: "PlaybackDuration",
|
||||
min: "1",
|
||||
max: "10",
|
||||
},
|
||||
{
|
||||
field: "TotalPlays",
|
||||
min: "1",
|
||||
max: "10",
|
||||
},
|
||||
{
|
||||
field: "DeviceName",
|
||||
value: "test",
|
||||
},
|
||||
{
|
||||
field: "Client",
|
||||
value: "test",
|
||||
},
|
||||
{
|
||||
field: "NowPlayingItemName",
|
||||
value: "test",
|
||||
},
|
||||
{
|
||||
field: "RemoteEndPoint",
|
||||
value: "127.0.0.1",
|
||||
},
|
||||
{
|
||||
field: "UserName",
|
||||
value: "test",
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const sortField = groupedSortMap.find((item) => item.field === sort)?.column || "a.ActivityDateInserted";
|
||||
|
||||
@@ -1130,6 +1273,12 @@ router.get("/getHistory", async (req, res) => {
|
||||
{ first: "a.UserId", operator: "=", second: "ar.UserId", type: "and" },
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "left",
|
||||
table: "jf_users",
|
||||
alias: "u",
|
||||
conditions: [{ first: "a.UserId", operator: "=", second: "u.Id" }],
|
||||
},
|
||||
],
|
||||
|
||||
order_by: sortField,
|
||||
@@ -1152,6 +1301,8 @@ router.get("/getHistory", async (req, res) => {
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
buildFilterList(query, filtersArray);
|
||||
const result = await dbHelper.query(query);
|
||||
|
||||
result.results = result.results.map((item) => ({
|
||||
@@ -1163,6 +1314,10 @@ router.get("/getHistory", async (req, res) => {
|
||||
response.search = search;
|
||||
}
|
||||
|
||||
if (filtersArray.length > 0) {
|
||||
response.filters = filtersArray;
|
||||
}
|
||||
|
||||
res.send(response);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
@@ -1171,7 +1326,55 @@ router.get("/getHistory", async (req, res) => {
|
||||
|
||||
router.post("/getLibraryHistory", async (req, res) => {
|
||||
try {
|
||||
const { size = 50, page = 1, search, sort = "ActivityDateInserted", desc = true } = req.query;
|
||||
const { size = 50, page = 1, search, sort = "ActivityDateInserted", desc = true, filters } = req.query;
|
||||
|
||||
let filtersArray = [];
|
||||
if (filters) {
|
||||
try {
|
||||
filtersArray = JSON.parse(filters);
|
||||
} catch (error) {
|
||||
return res.status(400).json({
|
||||
error: "Invalid filters parameter",
|
||||
example: [
|
||||
{
|
||||
field: "ActivityDateInserted",
|
||||
min: "2024-12-31T22:00:00.000Z",
|
||||
max: "2024-12-31T22:00:00.000Z",
|
||||
},
|
||||
{
|
||||
field: "PlaybackDuration",
|
||||
min: "1",
|
||||
max: "10",
|
||||
},
|
||||
{
|
||||
field: "TotalPlays",
|
||||
min: "1",
|
||||
max: "10",
|
||||
},
|
||||
{
|
||||
field: "DeviceName",
|
||||
value: "test",
|
||||
},
|
||||
{
|
||||
field: "Client",
|
||||
value: "test",
|
||||
},
|
||||
{
|
||||
field: "NowPlayingItemName",
|
||||
value: "test",
|
||||
},
|
||||
{
|
||||
field: "RemoteEndPoint",
|
||||
value: "127.0.0.1",
|
||||
},
|
||||
{
|
||||
field: "UserName",
|
||||
value: "test",
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
}
|
||||
const { libraryid } = req.body;
|
||||
|
||||
if (libraryid === undefined) {
|
||||
@@ -1236,6 +1439,12 @@ router.post("/getLibraryHistory", async (req, res) => {
|
||||
{ first: "a.UserId", operator: "=", second: "ar.UserId", type: "and" },
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "left",
|
||||
table: "jf_users",
|
||||
alias: "u",
|
||||
conditions: [{ first: "a.UserId", operator: "=", second: "u.Id" }],
|
||||
},
|
||||
],
|
||||
|
||||
order_by: sortField,
|
||||
@@ -1259,6 +1468,8 @@ router.post("/getLibraryHistory", async (req, res) => {
|
||||
];
|
||||
}
|
||||
|
||||
buildFilterList(query, filtersArray);
|
||||
|
||||
const result = await dbHelper.query(query);
|
||||
|
||||
result.results = result.results.map((item) => ({
|
||||
@@ -1270,6 +1481,9 @@ router.post("/getLibraryHistory", async (req, res) => {
|
||||
if (search && search.length > 0) {
|
||||
response.search = search;
|
||||
}
|
||||
if (filtersArray.length > 0) {
|
||||
response.filters = filtersArray;
|
||||
}
|
||||
res.send(response);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
@@ -1280,7 +1494,7 @@ router.post("/getLibraryHistory", async (req, res) => {
|
||||
|
||||
router.post("/getItemHistory", async (req, res) => {
|
||||
try {
|
||||
const { size = 50, page = 1, search, sort = "ActivityDateInserted", desc = true } = req.query;
|
||||
const { size = 50, page = 1, search, sort = "ActivityDateInserted", desc = true, filters } = req.query;
|
||||
const { itemid } = req.body;
|
||||
|
||||
if (itemid === undefined) {
|
||||
@@ -1289,6 +1503,55 @@ router.post("/getItemHistory", async (req, res) => {
|
||||
return;
|
||||
}
|
||||
|
||||
let filtersArray = [];
|
||||
if (filters) {
|
||||
try {
|
||||
filtersArray = JSON.parse(filters);
|
||||
filtersArray = filtersArray.filter((filter) => filter.field !== "TotalPlays");
|
||||
} catch (error) {
|
||||
return res.status(400).json({
|
||||
error: "Invalid filters parameter",
|
||||
example: [
|
||||
{
|
||||
field: "ActivityDateInserted",
|
||||
min: "2024-12-31T22:00:00.000Z",
|
||||
max: "2024-12-31T22:00:00.000Z",
|
||||
},
|
||||
{
|
||||
field: "PlaybackDuration",
|
||||
min: "1",
|
||||
max: "10",
|
||||
},
|
||||
{
|
||||
field: "TotalPlays",
|
||||
min: "1",
|
||||
max: "10",
|
||||
},
|
||||
{
|
||||
field: "DeviceName",
|
||||
value: "test",
|
||||
},
|
||||
{
|
||||
field: "Client",
|
||||
value: "test",
|
||||
},
|
||||
{
|
||||
field: "NowPlayingItemName",
|
||||
value: "test",
|
||||
},
|
||||
{
|
||||
field: "RemoteEndPoint",
|
||||
value: "127.0.0.1",
|
||||
},
|
||||
{
|
||||
field: "UserName",
|
||||
value: "test",
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const sortField = unGroupedSortMap.find((item) => item.field === sort)?.column || "a.ActivityDateInserted";
|
||||
|
||||
const query = {
|
||||
@@ -1306,6 +1569,14 @@ router.post("/getItemHistory", async (req, res) => {
|
||||
],
|
||||
table: "jf_playback_activity_with_metadata",
|
||||
alias: "a",
|
||||
joins: [
|
||||
{
|
||||
type: "left",
|
||||
table: "jf_users",
|
||||
alias: "u",
|
||||
conditions: [{ first: "a.UserId", operator: "=", second: "u.Id" }],
|
||||
},
|
||||
],
|
||||
where: [
|
||||
[
|
||||
{ column: "a.EpisodeId", operator: "=", value: itemid },
|
||||
@@ -1334,12 +1605,18 @@ router.post("/getItemHistory", async (req, res) => {
|
||||
];
|
||||
}
|
||||
|
||||
buildFilterList(query, filtersArray);
|
||||
const result = await dbHelper.query(query);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (filters) {
|
||||
response.filters = JSON.parse(filters);
|
||||
}
|
||||
|
||||
res.send(response);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
@@ -1350,7 +1627,56 @@ router.post("/getItemHistory", async (req, res) => {
|
||||
|
||||
router.post("/getUserHistory", async (req, res) => {
|
||||
try {
|
||||
const { size = 50, page = 1, search, sort = "ActivityDateInserted", desc = true } = req.query;
|
||||
const { size = 50, page = 1, search, sort = "ActivityDateInserted", desc = true, filters } = req.query;
|
||||
|
||||
let filtersArray = [];
|
||||
if (filters) {
|
||||
try {
|
||||
filtersArray = JSON.parse(filters);
|
||||
filtersArray = filtersArray.filter((filter) => filter.field !== "TotalPlays");
|
||||
} catch (error) {
|
||||
return res.status(400).json({
|
||||
error: "Invalid filters parameter",
|
||||
example: [
|
||||
{
|
||||
field: "ActivityDateInserted",
|
||||
min: "2024-12-31T22:00:00.000Z",
|
||||
max: "2024-12-31T22:00:00.000Z",
|
||||
},
|
||||
{
|
||||
field: "PlaybackDuration",
|
||||
min: "1",
|
||||
max: "10",
|
||||
},
|
||||
{
|
||||
field: "TotalPlays",
|
||||
min: "1",
|
||||
max: "10",
|
||||
},
|
||||
{
|
||||
field: "DeviceName",
|
||||
value: "test",
|
||||
},
|
||||
{
|
||||
field: "Client",
|
||||
value: "test",
|
||||
},
|
||||
{
|
||||
field: "NowPlayingItemName",
|
||||
value: "test",
|
||||
},
|
||||
{
|
||||
field: "RemoteEndPoint",
|
||||
value: "127.0.0.1",
|
||||
},
|
||||
{
|
||||
field: "UserName",
|
||||
value: "test",
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
}
|
||||
const { userid } = req.body;
|
||||
|
||||
if (userid === undefined) {
|
||||
@@ -1376,6 +1702,14 @@ router.post("/getUserHistory", async (req, res) => {
|
||||
],
|
||||
table: "jf_playback_activity_with_metadata",
|
||||
alias: "a",
|
||||
joins: [
|
||||
{
|
||||
type: "left",
|
||||
table: "jf_users",
|
||||
alias: "u",
|
||||
conditions: [{ first: "a.UserId", operator: "=", second: "u.Id" }],
|
||||
},
|
||||
],
|
||||
where: [[{ column: "a.UserId", operator: "=", value: userid }]],
|
||||
order_by: sortField,
|
||||
sort_order: desc ? "desc" : "asc",
|
||||
@@ -1397,6 +1731,9 @@ router.post("/getUserHistory", async (req, res) => {
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
buildFilterList(query, filtersArray);
|
||||
|
||||
const result = await dbHelper.query(query);
|
||||
|
||||
const response = { current_page: page, pages: result.pages, size: size, sort: sort, desc: desc, results: result.results };
|
||||
@@ -1405,6 +1742,10 @@ router.post("/getUserHistory", async (req, res) => {
|
||||
response.search = search;
|
||||
}
|
||||
|
||||
if (filters) {
|
||||
response.filters = JSON.parse(filters);
|
||||
}
|
||||
|
||||
res.send(response);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
@@ -1448,7 +1789,7 @@ router.post("/getActivityTimeLine", async (req, res) => {
|
||||
return;
|
||||
}
|
||||
|
||||
const {rows} = await db.query(`SELECT * FROM fs_get_user_activity($1, $2);`, [userId, libraries]);
|
||||
const { rows } = await db.query(`SELECT * FROM fs_get_user_activity($1, $2);`, [userId, libraries]);
|
||||
res.send(rows);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
|
||||
@@ -2042,12 +2042,20 @@
|
||||
"name": "desc",
|
||||
"in": "query",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "filters",
|
||||
"in": "query",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request"
|
||||
},
|
||||
"401": {
|
||||
"description": "Unauthorized"
|
||||
},
|
||||
@@ -2117,6 +2125,11 @@
|
||||
"in": "query",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "filters",
|
||||
"in": "query",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "body",
|
||||
"in": "body",
|
||||
@@ -2208,6 +2221,11 @@
|
||||
"in": "query",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "filters",
|
||||
"in": "query",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "body",
|
||||
"in": "body",
|
||||
@@ -2299,6 +2317,11 @@
|
||||
"in": "query",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "filters",
|
||||
"in": "query",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "body",
|
||||
"in": "body",
|
||||
@@ -2391,6 +2414,66 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/getActivityTimeLine": {
|
||||
"post": {
|
||||
"tags": [
|
||||
"API"
|
||||
],
|
||||
"description": "",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "authorization",
|
||||
"in": "header",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "x-api-token",
|
||||
"in": "header",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "req",
|
||||
"in": "query",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "body",
|
||||
"in": "body",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"userId": {
|
||||
"example": "any"
|
||||
},
|
||||
"libraries": {
|
||||
"example": "any"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request"
|
||||
},
|
||||
"401": {
|
||||
"description": "Unauthorized"
|
||||
},
|
||||
"403": {
|
||||
"description": "Forbidden"
|
||||
},
|
||||
"404": {
|
||||
"description": "Not Found"
|
||||
},
|
||||
"503": {
|
||||
"description": "Service Unavailable"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/stats/getLibraryOverview": {
|
||||
"get": {
|
||||
"tags": [
|
||||
|
||||
120
package-lock.json
generated
120
package-lock.json
generated
@@ -65,7 +65,7 @@
|
||||
"semver": "^7.5.3",
|
||||
"sequelize": "^6.29.0",
|
||||
"socket.io": "^4.7.2",
|
||||
"socket.io-client": "^4.7.2",
|
||||
"socket.io-client": "^4.8.1",
|
||||
"swagger-autogen": "^2.23.5",
|
||||
"swagger-jsdoc": "^6.2.8",
|
||||
"swagger-ui-express": "^5.0.0",
|
||||
@@ -7574,6 +7574,20 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/bufferutil": {
|
||||
"version": "4.0.9",
|
||||
"resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.9.tgz",
|
||||
"integrity": "sha512-WDtdLmJvAuNNPzByAYpRo2rF1Mmradw6gvWsQKf63476DDXmomT9zUiGypLcG4ibIM67vhAj8jJRdbmEws2Aqw==",
|
||||
"hasInstallScript": true,
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"node-gyp-build": "^4.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.14.2"
|
||||
}
|
||||
},
|
||||
"node_modules/builtin-modules": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz",
|
||||
@@ -9279,23 +9293,23 @@
|
||||
}
|
||||
},
|
||||
"node_modules/engine.io-client": {
|
||||
"version": "6.5.2",
|
||||
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.2.tgz",
|
||||
"integrity": "sha512-CQZqbrpEYnrpGqC07a9dJDz4gePZUgTPMU3NKJPSeQOyw27Tst4Pl3FemKoFGAlHzgZmKjoRmiJvbWfhCXUlIg==",
|
||||
"version": "6.6.3",
|
||||
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.3.tgz",
|
||||
"integrity": "sha512-T0iLjnyNWahNyv/lcjS2y4oE358tVS/SYQNxYXGAJ9/GLgH4VCvOQ/mhTjqU88mLZCQgiG8RIegFHYCdVC+j5w==",
|
||||
"dependencies": {
|
||||
"@socket.io/component-emitter": "~3.1.0",
|
||||
"debug": "~4.3.1",
|
||||
"engine.io-parser": "~5.2.1",
|
||||
"ws": "~8.11.0",
|
||||
"xmlhttprequest-ssl": "~2.0.0"
|
||||
"ws": "~8.17.1",
|
||||
"xmlhttprequest-ssl": "~2.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/engine.io-client/node_modules/debug": {
|
||||
"version": "4.3.4",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
||||
"version": "4.3.7",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
|
||||
"integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
|
||||
"dependencies": {
|
||||
"ms": "2.1.2"
|
||||
"ms": "^2.1.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
@@ -9307,29 +9321,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/engine.io-client/node_modules/ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
},
|
||||
"node_modules/engine.io-client/node_modules/ws": {
|
||||
"version": "8.11.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz",
|
||||
"integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"bufferutil": "^4.0.1",
|
||||
"utf-8-validate": "^5.0.2"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"bufferutil": {
|
||||
"optional": true
|
||||
},
|
||||
"utf-8-validate": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
|
||||
},
|
||||
"node_modules/engine.io-parser": {
|
||||
"version": "5.2.1",
|
||||
@@ -15384,6 +15378,18 @@
|
||||
"node": ">= 6.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/node-gyp-build": {
|
||||
"version": "4.8.4",
|
||||
"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz",
|
||||
"integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"node-gyp-build": "bin.js",
|
||||
"node-gyp-build-optional": "optional.js",
|
||||
"node-gyp-build-test": "build-test.js"
|
||||
}
|
||||
},
|
||||
"node_modules/node-int64": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
|
||||
@@ -19660,13 +19666,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/socket.io-client": {
|
||||
"version": "4.7.2",
|
||||
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.2.tgz",
|
||||
"integrity": "sha512-vtA0uD4ibrYD793SOIAwlo8cj6haOeMHrGvwPxJsxH7CeIksqJ+3Zc06RvWTIFgiSqx4A3sOnTXpfAEE2Zyz6w==",
|
||||
"version": "4.8.1",
|
||||
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.8.1.tgz",
|
||||
"integrity": "sha512-hJVXfu3E28NmzGk8o1sHhN3om52tRvwYeidbj7xKy2eIIse5IoKX3USlS6Tqt3BHAtflLIkCQBkzVrEEfWUyYQ==",
|
||||
"dependencies": {
|
||||
"@socket.io/component-emitter": "~3.1.0",
|
||||
"debug": "~4.3.2",
|
||||
"engine.io-client": "~6.5.2",
|
||||
"engine.io-client": "~6.6.1",
|
||||
"socket.io-parser": "~4.2.4"
|
||||
},
|
||||
"engines": {
|
||||
@@ -19674,11 +19680,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/socket.io-client/node_modules/debug": {
|
||||
"version": "4.3.4",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
||||
"version": "4.3.7",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
|
||||
"integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
|
||||
"dependencies": {
|
||||
"ms": "2.1.2"
|
||||
"ms": "^2.1.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
@@ -19690,9 +19696,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/socket.io-client/node_modules/ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
|
||||
},
|
||||
"node_modules/socket.io-parser": {
|
||||
"version": "4.2.4",
|
||||
@@ -21415,6 +21421,20 @@
|
||||
"requires-port": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/utf-8-validate": {
|
||||
"version": "5.0.10",
|
||||
"resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz",
|
||||
"integrity": "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==",
|
||||
"hasInstallScript": true,
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"node-gyp-build": "^4.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.14.2"
|
||||
}
|
||||
},
|
||||
"node_modules/utf8": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.2.tgz",
|
||||
@@ -22605,9 +22625,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/ws": {
|
||||
"version": "8.14.2",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.14.2.tgz",
|
||||
"integrity": "sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==",
|
||||
"version": "8.17.1",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz",
|
||||
"integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
},
|
||||
@@ -22635,9 +22655,9 @@
|
||||
"integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw=="
|
||||
},
|
||||
"node_modules/xmlhttprequest-ssl": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz",
|
||||
"integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==",
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz",
|
||||
"integrity": "sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==",
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@
|
||||
"semver": "^7.5.3",
|
||||
"sequelize": "^6.29.0",
|
||||
"socket.io": "^4.7.2",
|
||||
"socket.io-client": "^4.7.2",
|
||||
"socket.io-client": "^4.8.1",
|
||||
"swagger-autogen": "^2.23.5",
|
||||
"swagger-jsdoc": "^6.2.8",
|
||||
"swagger-ui-express": "^5.0.0",
|
||||
|
||||
@@ -28,6 +28,7 @@ function Activity() {
|
||||
const [showLibraryFilters, setShowLibraryFilters] = useState(false);
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const [sorting, setSorting] = useState({ column: "ActivityDateInserted", desc: true });
|
||||
const [filterParams, setFilterParams] = useState([]);
|
||||
const [isBusy, setIsBusy] = useState(false);
|
||||
|
||||
const handlePageChange = (newPage) => {
|
||||
@@ -38,6 +39,10 @@ function Activity() {
|
||||
setSorting({ column: sort.column, desc: sort.desc });
|
||||
};
|
||||
|
||||
const onFilterChange = (filter) => {
|
||||
setFilterParams(filter);
|
||||
};
|
||||
|
||||
function setItemLimit(limit) {
|
||||
setItemCount(parseInt(limit));
|
||||
localStorage.setItem("PREF_ACTIVITY_ItemCount", limit);
|
||||
@@ -87,9 +92,21 @@ function Activity() {
|
||||
|
||||
const fetchHistory = () => {
|
||||
setIsBusy(true);
|
||||
const url = `/api/getHistory?size=${itemCount}&page=${currentPage}&search=${debouncedSearchQuery}&sort=${sorting.column}&desc=${sorting.desc}`;
|
||||
const url = `/api/getHistory`;
|
||||
if (filterParams) {
|
||||
console.log(JSON.stringify(filterParams));
|
||||
}
|
||||
|
||||
axios
|
||||
.get(url, {
|
||||
params: {
|
||||
size: itemCount,
|
||||
page: currentPage,
|
||||
search: debouncedSearchQuery,
|
||||
sort: sorting.column,
|
||||
desc: sorting.desc,
|
||||
filters: filterParams != undefined ? JSON.stringify(filterParams) : null,
|
||||
},
|
||||
headers: {
|
||||
Authorization: `Bearer ${config.token}`,
|
||||
"Content-Type": "application/json",
|
||||
@@ -143,7 +160,8 @@ function Activity() {
|
||||
(data.size && data.size !== itemCount) ||
|
||||
(data?.search ?? "") !== debouncedSearchQuery.trim() ||
|
||||
(data?.sort ?? "") !== sorting.column ||
|
||||
(data?.desc ?? true) !== sorting.desc
|
||||
(data?.desc ?? true) !== sorting.desc ||
|
||||
JSON.stringify(data?.filters ?? []) !== JSON.stringify(filterParams ?? [])
|
||||
) {
|
||||
fetchHistory();
|
||||
fetchLibraries();
|
||||
@@ -156,7 +174,7 @@ function Activity() {
|
||||
|
||||
const intervalId = setInterval(fetchHistory, 60000 * 60);
|
||||
return () => clearInterval(intervalId);
|
||||
}, [data, config, itemCount, currentPage, debouncedSearchQuery, sorting]);
|
||||
}, [data, config, itemCount, currentPage, debouncedSearchQuery, sorting, filterParams]);
|
||||
|
||||
if (!data) {
|
||||
return <Loading />;
|
||||
@@ -279,6 +297,7 @@ function Activity() {
|
||||
itemCount={itemCount}
|
||||
onPageChange={handlePageChange}
|
||||
onSortChange={onSortChange}
|
||||
onFilterChange={onFilterChange}
|
||||
pageCount={data.pages}
|
||||
isBusy={isBusy}
|
||||
/>
|
||||
|
||||
@@ -60,8 +60,6 @@ const token = localStorage.getItem("token");
|
||||
export default function ActivityTable(props) {
|
||||
const twelve_hr = JSON.parse(localStorage.getItem("12hr"));
|
||||
const [data, setData] = React.useState(props.data ?? []);
|
||||
const uniqueUserNames = [...new Set(data.map((item) => item.UserName))];
|
||||
const uniqueClients = [...new Set(data.map((item) => item.Client))];
|
||||
const pages = props.pageCount || 1;
|
||||
const isBusy = props.isBusy;
|
||||
|
||||
@@ -72,6 +70,8 @@ export default function ActivityTable(props) {
|
||||
});
|
||||
const [sorting, setSorting] = React.useState([{ id: "Date", desc: true }]);
|
||||
|
||||
const [columnFilters, setColumnFilters] = React.useState([]);
|
||||
|
||||
const [modalState, setModalState] = React.useState(false);
|
||||
const [modalData, setModalData] = React.useState();
|
||||
|
||||
@@ -152,8 +152,6 @@ export default function ActivityTable(props) {
|
||||
{
|
||||
accessorKey: "UserName",
|
||||
header: i18next.t("USER"),
|
||||
filterVariant: "select",
|
||||
filterSelectOptions: uniqueUserNames,
|
||||
Cell: ({ row }) => {
|
||||
row = row.original;
|
||||
return (
|
||||
@@ -207,8 +205,6 @@ export default function ActivityTable(props) {
|
||||
{
|
||||
accessorKey: "Client",
|
||||
header: i18next.t("ACTIVITY_TABLE.CLIENT"),
|
||||
filterVariant: "select",
|
||||
filterSelectOptions: uniqueClients,
|
||||
Cell: ({ row }) => {
|
||||
row = row.original;
|
||||
return (
|
||||
@@ -246,8 +242,8 @@ export default function ActivityTable(props) {
|
||||
accessorKey: "PlaybackDuration",
|
||||
header: i18next.t("ACTIVITY_TABLE.TOTAL_PLAYBACK"),
|
||||
minSize: 200,
|
||||
filterFn: (row, id, filterValue) => formatTotalWatchTime(row.getValue(id)).startsWith(filterValue),
|
||||
|
||||
// filterFn: (row, id, filterValue) => formatTotalWatchTime(row.getValue(id)).startsWith(filterValue),
|
||||
filterVariant: "range",
|
||||
Cell: ({ cell }) => <span>{formatTotalWatchTime(cell.getValue())}</span>,
|
||||
},
|
||||
{
|
||||
@@ -276,6 +272,35 @@ export default function ActivityTable(props) {
|
||||
});
|
||||
};
|
||||
|
||||
const handleFilteringChange = (updater) => {
|
||||
setColumnFilters((old) => {
|
||||
const newFilterState = typeof updater === "function" ? updater(old) : updater;
|
||||
|
||||
const modifiedFilterState = newFilterState.map((filter) => ({ ...filter }));
|
||||
|
||||
modifiedFilterState.map((filter) => {
|
||||
filter.field = fieldMap.find((field) => field.header == filter.id)?.accessorKey ?? filter.id;
|
||||
delete filter.id;
|
||||
if (Array.isArray(filter.value)) {
|
||||
filter.min = filter.value[0];
|
||||
filter.max = filter.value[1];
|
||||
delete filter.value;
|
||||
} else {
|
||||
const val = filter.value;
|
||||
delete filter.value;
|
||||
filter.value = val;
|
||||
}
|
||||
|
||||
return filter;
|
||||
});
|
||||
|
||||
if (props.onFilterChange) {
|
||||
props.onFilterChange(modifiedFilterState);
|
||||
}
|
||||
return newFilterState;
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setData(props.data);
|
||||
}, [props.data]);
|
||||
@@ -300,8 +325,10 @@ export default function ActivityTable(props) {
|
||||
enableExpandAll: false,
|
||||
enableExpanding: true,
|
||||
enableDensityToggle: false,
|
||||
enableFilters: false,
|
||||
enableFilters: true,
|
||||
manualFiltering: true,
|
||||
onSortingChange: handleSortingChange,
|
||||
onColumnFiltersChange: handleFilteringChange,
|
||||
enableTopToolbar: Object.keys(rowSelection).length > 0,
|
||||
manualPagination: true,
|
||||
manualSorting: true,
|
||||
@@ -378,7 +405,7 @@ export default function ActivityTable(props) {
|
||||
},
|
||||
},
|
||||
},
|
||||
state: { rowSelection, pagination, sorting },
|
||||
state: { rowSelection, pagination, sorting, columnFilters },
|
||||
filterFromLeafRows: true,
|
||||
getSubRows: (row) => {
|
||||
if (Array.isArray(row.results) && row.results.length == 1) {
|
||||
|
||||
@@ -16,6 +16,7 @@ function ItemActivity(props) {
|
||||
const [config, setConfig] = useState();
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const [sorting, setSorting] = useState({ column: "ActivityDateInserted", desc: true });
|
||||
const [filterParams, setFilterParams] = useState([]);
|
||||
const [isBusy, setIsBusy] = useState(false);
|
||||
|
||||
const handlePageChange = (newPage) => {
|
||||
@@ -26,6 +27,10 @@ function ItemActivity(props) {
|
||||
setSorting({ column: sort.column, desc: sort.desc });
|
||||
};
|
||||
|
||||
const onFilterChange = (filter) => {
|
||||
setFilterParams(filter);
|
||||
};
|
||||
|
||||
function setItemLimit(limit) {
|
||||
setItemCount(parseInt(limit));
|
||||
localStorage.setItem("PREF_ACTIVITY_ItemCount", limit);
|
||||
@@ -59,7 +64,7 @@ function ItemActivity(props) {
|
||||
try {
|
||||
setIsBusy(true);
|
||||
const itemData = await axios.post(
|
||||
`/api/getItemHistory?size=${itemCount}&page=${currentPage}&search=${debouncedSearchQuery}&sort=${sorting.column}&desc=${sorting.desc}`,
|
||||
`/api/getItemHistory`,
|
||||
{
|
||||
itemid: props.itemid,
|
||||
},
|
||||
@@ -68,6 +73,14 @@ function ItemActivity(props) {
|
||||
Authorization: `Bearer ${token}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
params: {
|
||||
size: itemCount,
|
||||
page: currentPage,
|
||||
search: debouncedSearchQuery,
|
||||
sort: sorting.column,
|
||||
desc: sorting.desc,
|
||||
filters: filterParams != undefined ? JSON.stringify(filterParams) : null,
|
||||
},
|
||||
}
|
||||
);
|
||||
setData(itemData.data);
|
||||
@@ -83,14 +96,15 @@ function ItemActivity(props) {
|
||||
(data.size && data.size !== itemCount) ||
|
||||
(data?.search ?? "") !== debouncedSearchQuery.trim() ||
|
||||
(data?.sort ?? "") !== sorting.column ||
|
||||
(data?.desc ?? true) !== sorting.desc
|
||||
(data?.desc ?? true) !== sorting.desc ||
|
||||
JSON.stringify(data?.filters ?? []) !== JSON.stringify(filterParams ?? [])
|
||||
) {
|
||||
fetchData();
|
||||
}
|
||||
|
||||
const intervalId = setInterval(fetchData, 60000 * 5);
|
||||
return () => clearInterval(intervalId);
|
||||
}, [data, props.itemid, token, itemCount, currentPage, debouncedSearchQuery, sorting]);
|
||||
}, [data, props.itemid, token, itemCount, currentPage, debouncedSearchQuery, sorting, filterParams]);
|
||||
|
||||
if (!data || !data.results) {
|
||||
return <></>;
|
||||
@@ -177,6 +191,7 @@ function ItemActivity(props) {
|
||||
itemCount={itemCount}
|
||||
onPageChange={handlePageChange}
|
||||
onSortChange={onSortChange}
|
||||
onFilterChange={onFilterChange}
|
||||
pageCount={data.pages}
|
||||
isBusy={isBusy}
|
||||
/>
|
||||
|
||||
@@ -19,6 +19,7 @@ function LibraryActivity(props) {
|
||||
const [config, setConfig] = useState();
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const [sorting, setSorting] = useState({ column: "ActivityDateInserted", desc: true });
|
||||
const [filterParams, setFilterParams] = useState([]);
|
||||
const [isBusy, setIsBusy] = useState(false);
|
||||
|
||||
const handlePageChange = (newPage) => {
|
||||
@@ -29,6 +30,10 @@ function LibraryActivity(props) {
|
||||
setSorting({ column: sort.column, desc: sort.desc });
|
||||
};
|
||||
|
||||
const onFilterChange = (filter) => {
|
||||
setFilterParams(filter);
|
||||
};
|
||||
|
||||
function setItemLimit(limit) {
|
||||
setItemCount(parseInt(limit));
|
||||
localStorage.setItem("PREF_LIBRARY_ACTIVITY_ItemCount", limit);
|
||||
@@ -66,7 +71,7 @@ function LibraryActivity(props) {
|
||||
try {
|
||||
setIsBusy(true);
|
||||
const libraryData = await axios.post(
|
||||
`/api/getLibraryHistory?size=${itemCount}&page=${currentPage}&search=${debouncedSearchQuery}&sort=${sorting.column}&desc=${sorting.desc}`,
|
||||
`/api/getLibraryHistory`,
|
||||
{
|
||||
libraryid: props.LibraryId,
|
||||
},
|
||||
@@ -75,6 +80,14 @@ function LibraryActivity(props) {
|
||||
Authorization: `Bearer ${token}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
params: {
|
||||
size: itemCount,
|
||||
page: currentPage,
|
||||
search: debouncedSearchQuery,
|
||||
sort: sorting.column,
|
||||
desc: sorting.desc,
|
||||
filters: filterParams != undefined ? JSON.stringify(filterParams) : null,
|
||||
},
|
||||
}
|
||||
);
|
||||
setData(libraryData.data);
|
||||
@@ -90,14 +103,15 @@ function LibraryActivity(props) {
|
||||
(data.size && data.size !== itemCount) ||
|
||||
(data?.search ?? "") !== debouncedSearchQuery.trim() ||
|
||||
(data?.sort ?? "") !== sorting.column ||
|
||||
(data?.desc ?? true) !== sorting.desc
|
||||
(data?.desc ?? true) !== sorting.desc ||
|
||||
JSON.stringify(data?.filters ?? []) !== JSON.stringify(filterParams ?? [])
|
||||
) {
|
||||
fetchData();
|
||||
}
|
||||
|
||||
const intervalId = setInterval(fetchData, 60000 * 5);
|
||||
return () => clearInterval(intervalId);
|
||||
}, [data, props.LibraryId, token, itemCount, currentPage, debouncedSearchQuery, sorting]);
|
||||
}, [data, props.LibraryId, token, itemCount, currentPage, debouncedSearchQuery, sorting, filterParams]);
|
||||
|
||||
if (!data || !data.results) {
|
||||
return <></>;
|
||||
@@ -183,6 +197,7 @@ function LibraryActivity(props) {
|
||||
itemCount={itemCount}
|
||||
onPageChange={handlePageChange}
|
||||
onSortChange={onSortChange}
|
||||
onFilterChange={onFilterChange}
|
||||
pageCount={data.pages}
|
||||
isBusy={isBusy}
|
||||
/>
|
||||
|
||||
@@ -23,6 +23,7 @@ function UserActivity(props) {
|
||||
const [config, setConfig] = useState();
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const [sorting, setSorting] = useState({ column: "ActivityDateInserted", desc: true });
|
||||
const [filterParams, setFilterParams] = useState([]);
|
||||
const [isBusy, setIsBusy] = useState(false);
|
||||
|
||||
function setItemLimit(limit) {
|
||||
@@ -78,12 +79,16 @@ function UserActivity(props) {
|
||||
setSorting({ column: sort.column, desc: sort.desc });
|
||||
};
|
||||
|
||||
const onFilterChange = (filter) => {
|
||||
setFilterParams(filter);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const fetchHistory = async () => {
|
||||
try {
|
||||
setIsBusy(true);
|
||||
const itemData = await axios.post(
|
||||
`/api/getUserHistory?size=${itemCount}&page=${currentPage}&search=${debouncedSearchQuery}&sort=${sorting.column}&desc=${sorting.desc}`,
|
||||
`/api/getUserHistory`,
|
||||
{
|
||||
userid: props.UserId,
|
||||
},
|
||||
@@ -92,6 +97,14 @@ function UserActivity(props) {
|
||||
Authorization: `Bearer ${token}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
params: {
|
||||
size: itemCount,
|
||||
page: currentPage,
|
||||
search: debouncedSearchQuery,
|
||||
sort: sorting.column,
|
||||
desc: sorting.desc,
|
||||
filters: filterParams != undefined ? JSON.stringify(filterParams) : null,
|
||||
},
|
||||
}
|
||||
);
|
||||
setData(itemData.data);
|
||||
@@ -132,7 +145,8 @@ function UserActivity(props) {
|
||||
(data.size && data.size !== itemCount) ||
|
||||
(data?.search ?? "") !== debouncedSearchQuery.trim() ||
|
||||
(data?.sort ?? "") !== sorting.column ||
|
||||
(data?.desc ?? true) !== sorting.desc
|
||||
(data?.desc ?? true) !== sorting.desc ||
|
||||
JSON.stringify(data?.filters ?? []) !== JSON.stringify(filterParams ?? [])
|
||||
) {
|
||||
fetchHistory();
|
||||
}
|
||||
@@ -141,7 +155,7 @@ function UserActivity(props) {
|
||||
|
||||
const intervalId = setInterval(fetchHistory, 60000 * 5);
|
||||
return () => clearInterval(intervalId);
|
||||
}, [props.UserId, token, itemCount, currentPage, debouncedSearchQuery, sorting]);
|
||||
}, [props.UserId, token, itemCount, currentPage, debouncedSearchQuery, sorting, filterParams]);
|
||||
|
||||
if (!data || !data.results) {
|
||||
return <></>;
|
||||
@@ -248,6 +262,7 @@ function UserActivity(props) {
|
||||
itemCount={itemCount}
|
||||
onPageChange={handlePageChange}
|
||||
onSortChange={onSortChange}
|
||||
onFilterChange={onFilterChange}
|
||||
pageCount={data.pages}
|
||||
isBusy={isBusy}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user