mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
Merge pull request #5970 from thornbill/material-react-table
This commit is contained in:
commit
7c3270725e
13 changed files with 547 additions and 279 deletions
394
package-lock.json
generated
394
package-lock.json
generated
|
@ -21,7 +21,7 @@
|
|||
"@jellyfin/sdk": "0.0.0-unstable.202408290501",
|
||||
"@mui/icons-material": "5.15.19",
|
||||
"@mui/material": "5.15.19",
|
||||
"@mui/x-data-grid": "7.6.1",
|
||||
"@mui/x-date-pickers": "7.14.0",
|
||||
"@react-hook/resize-observer": "2.0.2",
|
||||
"@tanstack/react-query": "5.51.24",
|
||||
"@tanstack/react-query-devtools": "5.51.24",
|
||||
|
@ -48,6 +48,7 @@
|
|||
"lodash-es": "4.17.21",
|
||||
"markdown-it": "14.1.0",
|
||||
"material-design-icons-iconfont": "6.7.0",
|
||||
"material-react-table": "2.13.1",
|
||||
"native-promise-only": "0.8.1",
|
||||
"pdfjs-dist": "3.11.174",
|
||||
"react": "18.3.1",
|
||||
|
@ -2006,10 +2007,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/@babel/runtime": {
|
||||
"version": "7.24.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.7.tgz",
|
||||
"integrity": "sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw==",
|
||||
"license": "MIT",
|
||||
"version": "7.25.4",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.4.tgz",
|
||||
"integrity": "sha512-DSgLeL/FNcpXuzav5wfYvHCGvynXkJbn3Zvc3823AEe9nPwW9IK4UoCSS5yGymmQzN0pCPvivtgS6/8U2kkm1w==",
|
||||
"dependencies": {
|
||||
"regenerator-runtime": "^0.14.0"
|
||||
},
|
||||
|
@ -5418,12 +5418,12 @@
|
|||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@mui/private-theming": {
|
||||
"version": "5.15.14",
|
||||
"resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.15.14.tgz",
|
||||
"integrity": "sha512-UH0EiZckOWcxiXLX3Jbb0K7rC8mxTr9L9l6QhOZxYc4r8FHUkefltV9VDGLrzCaWh30SQiJvAEd7djX3XXY6Xw==",
|
||||
"version": "5.16.6",
|
||||
"resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.16.6.tgz",
|
||||
"integrity": "sha512-rAk+Rh8Clg7Cd7shZhyt2HGTTE5wYKNSJ5sspf28Fqm/PZ69Er9o6KX25g03/FG2dfpg5GCwZh/xOojiTfm3hw==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.23.9",
|
||||
"@mui/utils": "^5.15.14",
|
||||
"@mui/utils": "^5.16.6",
|
||||
"prop-types": "^15.8.1"
|
||||
},
|
||||
"engines": {
|
||||
|
@ -5444,9 +5444,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@mui/styled-engine": {
|
||||
"version": "5.15.14",
|
||||
"resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.15.14.tgz",
|
||||
"integrity": "sha512-RILkuVD8gY6PvjZjqnWhz8fu68dVkqhM5+jYWfB5yhlSQKg+2rHkmEwm75XIeAqI3qwOndK6zELK5H6Zxn4NHw==",
|
||||
"version": "5.16.6",
|
||||
"resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.16.6.tgz",
|
||||
"integrity": "sha512-zaThmS67ZmtHSWToTiHslbI8jwrmITcN93LQaR2lKArbvS7Z3iLkwRoiikNWutx9MBs8Q6okKvbZq1RQYB3v7g==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.23.9",
|
||||
"@emotion/cache": "^11.11.0",
|
||||
|
@ -5475,15 +5475,15 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@mui/system": {
|
||||
"version": "5.15.15",
|
||||
"resolved": "https://registry.npmjs.org/@mui/system/-/system-5.15.15.tgz",
|
||||
"integrity": "sha512-aulox6N1dnu5PABsfxVGOZffDVmlxPOVgj56HrUnJE8MCSh8lOvvkd47cebIVQQYAjpwieXQXiDPj5pwM40jTQ==",
|
||||
"version": "5.16.7",
|
||||
"resolved": "https://registry.npmjs.org/@mui/system/-/system-5.16.7.tgz",
|
||||
"integrity": "sha512-Jncvs/r/d/itkxh7O7opOunTqbbSSzMTHzZkNLM+FjAOg+cYAZHrPDlYe1ZGKUYORwwb2XexlWnpZp0kZ4AHuA==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.23.9",
|
||||
"@mui/private-theming": "^5.15.14",
|
||||
"@mui/styled-engine": "^5.15.14",
|
||||
"@mui/types": "^7.2.14",
|
||||
"@mui/utils": "^5.15.14",
|
||||
"@mui/private-theming": "^5.16.6",
|
||||
"@mui/styled-engine": "^5.16.6",
|
||||
"@mui/types": "^7.2.15",
|
||||
"@mui/utils": "^5.16.6",
|
||||
"clsx": "^2.1.0",
|
||||
"csstype": "^3.1.3",
|
||||
"prop-types": "^15.8.1"
|
||||
|
@ -5514,9 +5514,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@mui/types": {
|
||||
"version": "7.2.14",
|
||||
"resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.14.tgz",
|
||||
"integrity": "sha512-MZsBZ4q4HfzBsywtXgM1Ksj6HDThtiwmOKUXH1pKYISI9gAVXCNHNpo7TlGoGrBaYWZTdNoirIN7JsQcQUjmQQ==",
|
||||
"version": "7.2.15",
|
||||
"resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.15.tgz",
|
||||
"integrity": "sha512-nbo7yPhtKJkdf9kcVOF8JZHPZTmqXjJ/tI0bdWgHg5tp9AnIN4Y7f7wm9T+0SyGYJk76+GYZ8Q5XaTYAsUHN0Q==",
|
||||
"peerDependencies": {
|
||||
"@types/react": "^17.0.0 || ^18.0.0"
|
||||
},
|
||||
|
@ -5527,14 +5527,16 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@mui/utils": {
|
||||
"version": "5.15.14",
|
||||
"resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.15.14.tgz",
|
||||
"integrity": "sha512-0lF/7Hh/ezDv5X7Pry6enMsbYyGKjADzvHyo3Qrc/SSlTsQ1VkbDMbH0m2t3OR5iIVLwMoxwM7yGd+6FCMtTFA==",
|
||||
"version": "5.16.6",
|
||||
"resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.16.6.tgz",
|
||||
"integrity": "sha512-tWiQqlhxAt3KENNiSRL+DIn9H5xNVK6Jjf70x3PnfQPz1MPBdh7yyIcAyVBT9xiw7hP3SomRhPR7hzBMBCjqEA==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.23.9",
|
||||
"@types/prop-types": "^15.7.11",
|
||||
"@mui/types": "^7.2.15",
|
||||
"@types/prop-types": "^15.7.12",
|
||||
"clsx": "^2.1.1",
|
||||
"prop-types": "^15.8.1",
|
||||
"react-is": "^18.2.0"
|
||||
"react-is": "^18.3.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
|
@ -5554,22 +5556,22 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@mui/utils/node_modules/react-is": {
|
||||
"version": "18.2.0",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
|
||||
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
|
||||
"version": "18.3.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
|
||||
"integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="
|
||||
},
|
||||
"node_modules/@mui/x-data-grid": {
|
||||
"version": "7.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@mui/x-data-grid/-/x-data-grid-7.6.1.tgz",
|
||||
"integrity": "sha512-ZUQqSvmJgNQAgwLqVp/XUgNgKFb3zdsBQTbYCagjAK7Saq3iPDJkTb7FNSyT8UN0G6Kqogxgd9fKJW4L4ku1zQ==",
|
||||
"license": "MIT",
|
||||
"node_modules/@mui/x-date-pickers": {
|
||||
"version": "7.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@mui/x-date-pickers/-/x-date-pickers-7.14.0.tgz",
|
||||
"integrity": "sha512-3xI3xYVxqPU4//KfE4FcR+Zs7UT4kkDPvA+IDOcQdRUyVwmcXCjBuJZgKgJMqSCNK/KIJZQQrpmy5XGHOKTbdA==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.24.6",
|
||||
"@mui/system": "^5.15.15",
|
||||
"@mui/utils": "^5.15.14",
|
||||
"@babel/runtime": "^7.25.0",
|
||||
"@mui/system": "^5.16.7",
|
||||
"@mui/utils": "^5.16.6",
|
||||
"@types/react-transition-group": "^4.4.11",
|
||||
"clsx": "^2.1.1",
|
||||
"prop-types": "^15.8.1",
|
||||
"reselect": "^4.1.8"
|
||||
"react-transition-group": "^4.4.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
|
@ -5579,9 +5581,47 @@
|
|||
"url": "https://opencollective.com/mui-org"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@emotion/react": "^11.9.0",
|
||||
"@emotion/styled": "^11.8.1",
|
||||
"@mui/material": "^5.15.14",
|
||||
"date-fns": "^2.25.0 || ^3.2.0",
|
||||
"date-fns-jalali": "^2.13.0-0 || ^3.2.0-0",
|
||||
"dayjs": "^1.10.7",
|
||||
"luxon": "^3.0.2",
|
||||
"moment": "^2.29.4",
|
||||
"moment-hijri": "^2.1.2",
|
||||
"moment-jalaali": "^0.7.4 || ^0.8.0 || ^0.9.0 || ^0.10.0",
|
||||
"react": "^17.0.0 || ^18.0.0",
|
||||
"react-dom": "^17.0.0 || ^18.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@emotion/react": {
|
||||
"optional": true
|
||||
},
|
||||
"@emotion/styled": {
|
||||
"optional": true
|
||||
},
|
||||
"date-fns": {
|
||||
"optional": true
|
||||
},
|
||||
"date-fns-jalali": {
|
||||
"optional": true
|
||||
},
|
||||
"dayjs": {
|
||||
"optional": true
|
||||
},
|
||||
"luxon": {
|
||||
"optional": true
|
||||
},
|
||||
"moment": {
|
||||
"optional": true
|
||||
},
|
||||
"moment-hijri": {
|
||||
"optional": true
|
||||
},
|
||||
"moment-jalaali": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@nodelib/fs.scandir": {
|
||||
|
@ -6254,6 +6294,21 @@
|
|||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tanstack/match-sorter-utils": {
|
||||
"version": "8.15.1",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/match-sorter-utils/-/match-sorter-utils-8.15.1.tgz",
|
||||
"integrity": "sha512-PnVV3d2poenUM31ZbZi/yXkBu3J7kd5k2u51CGwwNojag451AjTH9N6n41yjXz2fpLeewleyLBmNS6+HcGDlXw==",
|
||||
"dependencies": {
|
||||
"remove-accents": "0.5.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/tannerlinsley"
|
||||
}
|
||||
},
|
||||
"node_modules/@tanstack/query-core": {
|
||||
"version": "5.51.24",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.51.24.tgz",
|
||||
|
@ -6307,6 +6362,62 @@
|
|||
"react": "^18 || ^19"
|
||||
}
|
||||
},
|
||||
"node_modules/@tanstack/react-table": {
|
||||
"version": "8.19.3",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.19.3.tgz",
|
||||
"integrity": "sha512-MtgPZc4y+cCRtU16y1vh1myuyZ2OdkWgMEBzyjYsoMWMicKZGZvcDnub3Zwb6XF2pj9iRMvm1SO1n57lS0vXLw==",
|
||||
"dependencies": {
|
||||
"@tanstack/table-core": "8.19.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/tannerlinsley"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.8",
|
||||
"react-dom": ">=16.8"
|
||||
}
|
||||
},
|
||||
"node_modules/@tanstack/react-virtual": {
|
||||
"version": "3.8.3",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.8.3.tgz",
|
||||
"integrity": "sha512-9ICwbDUUzN99CJIGc373i8NLoj6zFTKI2Hlcmo0+lCSAhPQ5mxq4dGOMKmLYoEFyHcGQ64Bd6ZVbnPpM6lNK5w==",
|
||||
"dependencies": {
|
||||
"@tanstack/virtual-core": "3.8.3"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/tannerlinsley"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
|
||||
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@tanstack/table-core": {
|
||||
"version": "8.19.3",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/table-core/-/table-core-8.19.3.tgz",
|
||||
"integrity": "sha512-IqREj9ADoml9zCAouIG/5kCGoyIxPFdqdyoxis9FisXFi5vT+iYfEfLosq4xkU/iDbMcEuAj+X8dWRLvKYDNoQ==",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/tannerlinsley"
|
||||
}
|
||||
},
|
||||
"node_modules/@tanstack/virtual-core": {
|
||||
"version": "3.8.3",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.8.3.tgz",
|
||||
"integrity": "sha512-vd2A2TnM5lbnWZnHi9B+L2gPtkSeOtJOAw358JqokIH1+v2J7vUAzFVPwB/wrye12RFOurffXu33plm4uQ+JBQ==",
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/tannerlinsley"
|
||||
}
|
||||
},
|
||||
"node_modules/@trysound/sax": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz",
|
||||
|
@ -6585,9 +6696,9 @@
|
|||
"integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA=="
|
||||
},
|
||||
"node_modules/@types/prop-types": {
|
||||
"version": "15.7.11",
|
||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz",
|
||||
"integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng=="
|
||||
"version": "15.7.12",
|
||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz",
|
||||
"integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q=="
|
||||
},
|
||||
"node_modules/@types/qs": {
|
||||
"version": "6.9.7",
|
||||
|
@ -6631,9 +6742,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@types/react-transition-group": {
|
||||
"version": "4.4.10",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.10.tgz",
|
||||
"integrity": "sha512-hT/+s0VQs2ojCX823m60m5f0sL5idt9SO6Tj6Dg+rdphGPIeJbJ6CxvBYkgkGKrYeDjvIpKTR38UzmtHJOGW3Q==",
|
||||
"version": "4.4.11",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.11.tgz",
|
||||
"integrity": "sha512-RM05tAniPZ5DZPzzNFP+DmrcOdD0efDUxMy3145oljWSl3x9ZV5vhme98gTxFrj2lhXvmGNnUiuDyJgY9IKkNA==",
|
||||
"dependencies": {
|
||||
"@types/react": "*"
|
||||
}
|
||||
|
@ -13203,6 +13314,15 @@
|
|||
"resolved": "https://registry.npmjs.org/headroom.js/-/headroom.js-0.12.0.tgz",
|
||||
"integrity": "sha512-iXnAafUm3FdzfJ91uixLws2hkKI1jC8bAKK/pt7XYr8Ie1jO7xbK48Ycpl9tUPyBgkzuj1p/PhJS0fy4E/5anA=="
|
||||
},
|
||||
"node_modules/highlight-words": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/highlight-words/-/highlight-words-1.2.2.tgz",
|
||||
"integrity": "sha512-Mf4xfPXYm8Ay1wTibCrHpNWeR2nUMynMVFkXCi4mbl+TEgmNOe+I4hV7W3OCZcSvzGL6kupaqpfHOemliMTGxQ==",
|
||||
"engines": {
|
||||
"node": ">= 16",
|
||||
"npm": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/history": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/history/-/history-5.3.0.tgz",
|
||||
|
@ -15472,6 +15592,33 @@
|
|||
"resolved": "https://registry.npmjs.org/material-design-icons-iconfont/-/material-design-icons-iconfont-6.7.0.tgz",
|
||||
"integrity": "sha512-lSj71DgVv20kO0kGbs42icDzbRot61gEDBLQACzkUuznRQBUYmbxzEkGU6dNBb5fRWHMaScYlAXX96HQ4/cJWA=="
|
||||
},
|
||||
"node_modules/material-react-table": {
|
||||
"version": "2.13.1",
|
||||
"resolved": "https://registry.npmjs.org/material-react-table/-/material-react-table-2.13.1.tgz",
|
||||
"integrity": "sha512-3iWwCa24ogxwllP4+W11euR/GV6f5wQE5FEilJ72/H3hDYHgsN+XehANytaG0G7/qy/OWYE7oXkcsRUU35I/iA==",
|
||||
"dependencies": {
|
||||
"@tanstack/match-sorter-utils": "8.15.1",
|
||||
"@tanstack/react-table": "8.19.3",
|
||||
"@tanstack/react-virtual": "3.8.3",
|
||||
"highlight-words": "1.2.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/kevinvandy"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@emotion/react": ">=11.11",
|
||||
"@emotion/styled": ">=11.11",
|
||||
"@mui/icons-material": ">=5.11",
|
||||
"@mui/material": ">=5.13",
|
||||
"@mui/x-date-pickers": ">=6.15.0",
|
||||
"react": ">=17.0",
|
||||
"react-dom": ">=17.0"
|
||||
}
|
||||
},
|
||||
"node_modules/mathml-tag-names": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz",
|
||||
|
@ -19949,6 +20096,11 @@
|
|||
"url": "https://opencollective.com/unified"
|
||||
}
|
||||
},
|
||||
"node_modules/remove-accents": {
|
||||
"version": "0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.5.0.tgz",
|
||||
"integrity": "sha512-8g3/Otx1eJaVD12e31UbJj1YzdtVvzH85HV7t+9MJYk/u3XmkOUJ5Ys9wQrf9PCPK8+xn4ymzqYCiZl6QWKn+A=="
|
||||
},
|
||||
"node_modules/renderkid": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz",
|
||||
|
@ -20004,11 +20156,6 @@
|
|||
"integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/reselect": {
|
||||
"version": "4.1.8",
|
||||
"resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz",
|
||||
"integrity": "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ=="
|
||||
},
|
||||
"node_modules/resize-observer-polyfill": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz",
|
||||
|
@ -28244,9 +28391,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"@babel/runtime": {
|
||||
"version": "7.24.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.7.tgz",
|
||||
"integrity": "sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw==",
|
||||
"version": "7.25.4",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.4.tgz",
|
||||
"integrity": "sha512-DSgLeL/FNcpXuzav5wfYvHCGvynXkJbn3Zvc3823AEe9nPwW9IK4UoCSS5yGymmQzN0pCPvivtgS6/8U2kkm1w==",
|
||||
"requires": {
|
||||
"regenerator-runtime": "^0.14.0"
|
||||
}
|
||||
|
@ -29786,19 +29933,19 @@
|
|||
}
|
||||
},
|
||||
"@mui/private-theming": {
|
||||
"version": "5.15.14",
|
||||
"resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.15.14.tgz",
|
||||
"integrity": "sha512-UH0EiZckOWcxiXLX3Jbb0K7rC8mxTr9L9l6QhOZxYc4r8FHUkefltV9VDGLrzCaWh30SQiJvAEd7djX3XXY6Xw==",
|
||||
"version": "5.16.6",
|
||||
"resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.16.6.tgz",
|
||||
"integrity": "sha512-rAk+Rh8Clg7Cd7shZhyt2HGTTE5wYKNSJ5sspf28Fqm/PZ69Er9o6KX25g03/FG2dfpg5GCwZh/xOojiTfm3hw==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.23.9",
|
||||
"@mui/utils": "^5.15.14",
|
||||
"@mui/utils": "^5.16.6",
|
||||
"prop-types": "^15.8.1"
|
||||
}
|
||||
},
|
||||
"@mui/styled-engine": {
|
||||
"version": "5.15.14",
|
||||
"resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.15.14.tgz",
|
||||
"integrity": "sha512-RILkuVD8gY6PvjZjqnWhz8fu68dVkqhM5+jYWfB5yhlSQKg+2rHkmEwm75XIeAqI3qwOndK6zELK5H6Zxn4NHw==",
|
||||
"version": "5.16.6",
|
||||
"resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.16.6.tgz",
|
||||
"integrity": "sha512-zaThmS67ZmtHSWToTiHslbI8jwrmITcN93LQaR2lKArbvS7Z3iLkwRoiikNWutx9MBs8Q6okKvbZq1RQYB3v7g==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.23.9",
|
||||
"@emotion/cache": "^11.11.0",
|
||||
|
@ -29807,55 +29954,58 @@
|
|||
}
|
||||
},
|
||||
"@mui/system": {
|
||||
"version": "5.15.15",
|
||||
"resolved": "https://registry.npmjs.org/@mui/system/-/system-5.15.15.tgz",
|
||||
"integrity": "sha512-aulox6N1dnu5PABsfxVGOZffDVmlxPOVgj56HrUnJE8MCSh8lOvvkd47cebIVQQYAjpwieXQXiDPj5pwM40jTQ==",
|
||||
"version": "5.16.7",
|
||||
"resolved": "https://registry.npmjs.org/@mui/system/-/system-5.16.7.tgz",
|
||||
"integrity": "sha512-Jncvs/r/d/itkxh7O7opOunTqbbSSzMTHzZkNLM+FjAOg+cYAZHrPDlYe1ZGKUYORwwb2XexlWnpZp0kZ4AHuA==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.23.9",
|
||||
"@mui/private-theming": "^5.15.14",
|
||||
"@mui/styled-engine": "^5.15.14",
|
||||
"@mui/types": "^7.2.14",
|
||||
"@mui/utils": "^5.15.14",
|
||||
"@mui/private-theming": "^5.16.6",
|
||||
"@mui/styled-engine": "^5.16.6",
|
||||
"@mui/types": "^7.2.15",
|
||||
"@mui/utils": "^5.16.6",
|
||||
"clsx": "^2.1.0",
|
||||
"csstype": "^3.1.3",
|
||||
"prop-types": "^15.8.1"
|
||||
}
|
||||
},
|
||||
"@mui/types": {
|
||||
"version": "7.2.14",
|
||||
"resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.14.tgz",
|
||||
"integrity": "sha512-MZsBZ4q4HfzBsywtXgM1Ksj6HDThtiwmOKUXH1pKYISI9gAVXCNHNpo7TlGoGrBaYWZTdNoirIN7JsQcQUjmQQ==",
|
||||
"version": "7.2.15",
|
||||
"resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.15.tgz",
|
||||
"integrity": "sha512-nbo7yPhtKJkdf9kcVOF8JZHPZTmqXjJ/tI0bdWgHg5tp9AnIN4Y7f7wm9T+0SyGYJk76+GYZ8Q5XaTYAsUHN0Q==",
|
||||
"requires": {}
|
||||
},
|
||||
"@mui/utils": {
|
||||
"version": "5.15.14",
|
||||
"resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.15.14.tgz",
|
||||
"integrity": "sha512-0lF/7Hh/ezDv5X7Pry6enMsbYyGKjADzvHyo3Qrc/SSlTsQ1VkbDMbH0m2t3OR5iIVLwMoxwM7yGd+6FCMtTFA==",
|
||||
"version": "5.16.6",
|
||||
"resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.16.6.tgz",
|
||||
"integrity": "sha512-tWiQqlhxAt3KENNiSRL+DIn9H5xNVK6Jjf70x3PnfQPz1MPBdh7yyIcAyVBT9xiw7hP3SomRhPR7hzBMBCjqEA==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.23.9",
|
||||
"@types/prop-types": "^15.7.11",
|
||||
"@mui/types": "^7.2.15",
|
||||
"@types/prop-types": "^15.7.12",
|
||||
"clsx": "^2.1.1",
|
||||
"prop-types": "^15.8.1",
|
||||
"react-is": "^18.2.0"
|
||||
"react-is": "^18.3.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"react-is": {
|
||||
"version": "18.2.0",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
|
||||
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
|
||||
"version": "18.3.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
|
||||
"integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"@mui/x-data-grid": {
|
||||
"version": "7.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@mui/x-data-grid/-/x-data-grid-7.6.1.tgz",
|
||||
"integrity": "sha512-ZUQqSvmJgNQAgwLqVp/XUgNgKFb3zdsBQTbYCagjAK7Saq3iPDJkTb7FNSyT8UN0G6Kqogxgd9fKJW4L4ku1zQ==",
|
||||
"@mui/x-date-pickers": {
|
||||
"version": "7.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@mui/x-date-pickers/-/x-date-pickers-7.14.0.tgz",
|
||||
"integrity": "sha512-3xI3xYVxqPU4//KfE4FcR+Zs7UT4kkDPvA+IDOcQdRUyVwmcXCjBuJZgKgJMqSCNK/KIJZQQrpmy5XGHOKTbdA==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.24.6",
|
||||
"@mui/system": "^5.15.15",
|
||||
"@mui/utils": "^5.15.14",
|
||||
"@babel/runtime": "^7.25.0",
|
||||
"@mui/system": "^5.16.7",
|
||||
"@mui/utils": "^5.16.6",
|
||||
"@types/react-transition-group": "^4.4.11",
|
||||
"clsx": "^2.1.1",
|
||||
"prop-types": "^15.8.1",
|
||||
"reselect": "^4.1.8"
|
||||
"react-transition-group": "^4.4.5"
|
||||
}
|
||||
},
|
||||
"@nodelib/fs.scandir": {
|
||||
|
@ -30267,6 +30417,14 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"@tanstack/match-sorter-utils": {
|
||||
"version": "8.15.1",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/match-sorter-utils/-/match-sorter-utils-8.15.1.tgz",
|
||||
"integrity": "sha512-PnVV3d2poenUM31ZbZi/yXkBu3J7kd5k2u51CGwwNojag451AjTH9N6n41yjXz2fpLeewleyLBmNS6+HcGDlXw==",
|
||||
"requires": {
|
||||
"remove-accents": "0.5.0"
|
||||
}
|
||||
},
|
||||
"@tanstack/query-core": {
|
||||
"version": "5.51.24",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.51.24.tgz",
|
||||
|
@ -30293,6 +30451,32 @@
|
|||
"@tanstack/query-devtools": "5.51.16"
|
||||
}
|
||||
},
|
||||
"@tanstack/react-table": {
|
||||
"version": "8.19.3",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.19.3.tgz",
|
||||
"integrity": "sha512-MtgPZc4y+cCRtU16y1vh1myuyZ2OdkWgMEBzyjYsoMWMicKZGZvcDnub3Zwb6XF2pj9iRMvm1SO1n57lS0vXLw==",
|
||||
"requires": {
|
||||
"@tanstack/table-core": "8.19.3"
|
||||
}
|
||||
},
|
||||
"@tanstack/react-virtual": {
|
||||
"version": "3.8.3",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.8.3.tgz",
|
||||
"integrity": "sha512-9ICwbDUUzN99CJIGc373i8NLoj6zFTKI2Hlcmo0+lCSAhPQ5mxq4dGOMKmLYoEFyHcGQ64Bd6ZVbnPpM6lNK5w==",
|
||||
"requires": {
|
||||
"@tanstack/virtual-core": "3.8.3"
|
||||
}
|
||||
},
|
||||
"@tanstack/table-core": {
|
||||
"version": "8.19.3",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/table-core/-/table-core-8.19.3.tgz",
|
||||
"integrity": "sha512-IqREj9ADoml9zCAouIG/5kCGoyIxPFdqdyoxis9FisXFi5vT+iYfEfLosq4xkU/iDbMcEuAj+X8dWRLvKYDNoQ=="
|
||||
},
|
||||
"@tanstack/virtual-core": {
|
||||
"version": "3.8.3",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.8.3.tgz",
|
||||
"integrity": "sha512-vd2A2TnM5lbnWZnHi9B+L2gPtkSeOtJOAw358JqokIH1+v2J7vUAzFVPwB/wrye12RFOurffXu33plm4uQ+JBQ=="
|
||||
},
|
||||
"@trysound/sax": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz",
|
||||
|
@ -30556,9 +30740,9 @@
|
|||
"integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA=="
|
||||
},
|
||||
"@types/prop-types": {
|
||||
"version": "15.7.11",
|
||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz",
|
||||
"integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng=="
|
||||
"version": "15.7.12",
|
||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz",
|
||||
"integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q=="
|
||||
},
|
||||
"@types/qs": {
|
||||
"version": "6.9.7",
|
||||
|
@ -30600,9 +30784,9 @@
|
|||
}
|
||||
},
|
||||
"@types/react-transition-group": {
|
||||
"version": "4.4.10",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.10.tgz",
|
||||
"integrity": "sha512-hT/+s0VQs2ojCX823m60m5f0sL5idt9SO6Tj6Dg+rdphGPIeJbJ6CxvBYkgkGKrYeDjvIpKTR38UzmtHJOGW3Q==",
|
||||
"version": "4.4.11",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.11.tgz",
|
||||
"integrity": "sha512-RM05tAniPZ5DZPzzNFP+DmrcOdD0efDUxMy3145oljWSl3x9ZV5vhme98gTxFrj2lhXvmGNnUiuDyJgY9IKkNA==",
|
||||
"requires": {
|
||||
"@types/react": "*"
|
||||
}
|
||||
|
@ -35412,6 +35596,11 @@
|
|||
"resolved": "https://registry.npmjs.org/headroom.js/-/headroom.js-0.12.0.tgz",
|
||||
"integrity": "sha512-iXnAafUm3FdzfJ91uixLws2hkKI1jC8bAKK/pt7XYr8Ie1jO7xbK48Ycpl9tUPyBgkzuj1p/PhJS0fy4E/5anA=="
|
||||
},
|
||||
"highlight-words": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/highlight-words/-/highlight-words-1.2.2.tgz",
|
||||
"integrity": "sha512-Mf4xfPXYm8Ay1wTibCrHpNWeR2nUMynMVFkXCi4mbl+TEgmNOe+I4hV7W3OCZcSvzGL6kupaqpfHOemliMTGxQ=="
|
||||
},
|
||||
"history": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/history/-/history-5.3.0.tgz",
|
||||
|
@ -37051,6 +37240,17 @@
|
|||
"resolved": "https://registry.npmjs.org/material-design-icons-iconfont/-/material-design-icons-iconfont-6.7.0.tgz",
|
||||
"integrity": "sha512-lSj71DgVv20kO0kGbs42icDzbRot61gEDBLQACzkUuznRQBUYmbxzEkGU6dNBb5fRWHMaScYlAXX96HQ4/cJWA=="
|
||||
},
|
||||
"material-react-table": {
|
||||
"version": "2.13.1",
|
||||
"resolved": "https://registry.npmjs.org/material-react-table/-/material-react-table-2.13.1.tgz",
|
||||
"integrity": "sha512-3iWwCa24ogxwllP4+W11euR/GV6f5wQE5FEilJ72/H3hDYHgsN+XehANytaG0G7/qy/OWYE7oXkcsRUU35I/iA==",
|
||||
"requires": {
|
||||
"@tanstack/match-sorter-utils": "8.15.1",
|
||||
"@tanstack/react-table": "8.19.3",
|
||||
"@tanstack/react-virtual": "3.8.3",
|
||||
"highlight-words": "1.2.2"
|
||||
}
|
||||
},
|
||||
"mathml-tag-names": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz",
|
||||
|
@ -39887,6 +40087,11 @@
|
|||
"mdast-util-to-markdown": "^0.6.0"
|
||||
}
|
||||
},
|
||||
"remove-accents": {
|
||||
"version": "0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.5.0.tgz",
|
||||
"integrity": "sha512-8g3/Otx1eJaVD12e31UbJj1YzdtVvzH85HV7t+9MJYk/u3XmkOUJ5Ys9wQrf9PCPK8+xn4ymzqYCiZl6QWKn+A=="
|
||||
},
|
||||
"renderkid": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz",
|
||||
|
@ -39930,11 +40135,6 @@
|
|||
"integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
|
||||
"dev": true
|
||||
},
|
||||
"reselect": {
|
||||
"version": "4.1.8",
|
||||
"resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz",
|
||||
"integrity": "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ=="
|
||||
},
|
||||
"resize-observer-polyfill": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz",
|
||||
|
|
|
@ -85,7 +85,7 @@
|
|||
"@jellyfin/sdk": "0.0.0-unstable.202408290501",
|
||||
"@mui/icons-material": "5.15.19",
|
||||
"@mui/material": "5.15.19",
|
||||
"@mui/x-data-grid": "7.6.1",
|
||||
"@mui/x-date-pickers": "7.14.0",
|
||||
"@react-hook/resize-observer": "2.0.2",
|
||||
"@tanstack/react-query": "5.51.24",
|
||||
"@tanstack/react-query-devtools": "5.51.24",
|
||||
|
@ -112,6 +112,7 @@
|
|||
"lodash-es": "4.17.21",
|
||||
"markdown-it": "14.1.0",
|
||||
"material-design-icons-iconfont": "6.7.0",
|
||||
"material-react-table": "2.13.1",
|
||||
"native-promise-only": "0.8.1",
|
||||
"pdfjs-dist": "3.11.174",
|
||||
"react": "18.3.1",
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
import React, { type RefAttributes } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { GridActionsCellItem, type GridActionsCellItemProps } from '@mui/x-data-grid';
|
||||
|
||||
type GridActionsCellLinkProps = { to: string } & GridActionsCellItemProps & RefAttributes<HTMLButtonElement>;
|
||||
|
||||
/**
|
||||
* Link component to use in mui's data-grid action column due to a current bug with passing props to custom link components.
|
||||
* @see https://github.com/mui/mui-x/issues/4654
|
||||
*/
|
||||
const GridActionsCellLink = ({ to, ...props }: GridActionsCellLinkProps) => (
|
||||
<Link to={to}>
|
||||
<GridActionsCellItem {...props} />
|
||||
</Link>
|
||||
);
|
||||
|
||||
export default GridActionsCellLink;
|
|
@ -1,18 +1,20 @@
|
|||
import type { ActivityLogApiGetLogEntriesRequest } from '@jellyfin/sdk/lib/generated-client';
|
||||
import type { AxiosRequestConfig } from 'axios';
|
||||
import type { Api } from '@jellyfin/sdk';
|
||||
import { getActivityLogApi } from '@jellyfin/sdk/lib/utils/api/activity-log-api';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
|
||||
import { JellyfinApiContext, useApi } from './useApi';
|
||||
import { useApi } from 'hooks/useApi';
|
||||
|
||||
const fetchGetLogEntries = async (
|
||||
currentApi: JellyfinApiContext,
|
||||
requestParams: ActivityLogApiGetLogEntriesRequest,
|
||||
const fetchLogEntries = async (
|
||||
api?: Api,
|
||||
requestParams?: ActivityLogApiGetLogEntriesRequest,
|
||||
options?: AxiosRequestConfig
|
||||
) => {
|
||||
const { api } = currentApi;
|
||||
|
||||
if (!api) return;
|
||||
if (!api) {
|
||||
console.warn('[fetchLogEntries] No API instance available');
|
||||
return;
|
||||
}
|
||||
|
||||
const response = await getActivityLogApi(api).getLogEntries(requestParams, {
|
||||
signal: options?.signal
|
||||
|
@ -24,10 +26,11 @@ const fetchGetLogEntries = async (
|
|||
export const useLogEntires = (
|
||||
requestParams: ActivityLogApiGetLogEntriesRequest
|
||||
) => {
|
||||
const currentApi = useApi();
|
||||
const { api } = useApi();
|
||||
return useQuery({
|
||||
queryKey: ['LogEntries', requestParams],
|
||||
queryFn: ({ signal }) =>
|
||||
fetchGetLogEntries(currentApi, requestParams, { signal })
|
||||
fetchLogEntries(api, requestParams, { signal }),
|
||||
enabled: !!api
|
||||
});
|
||||
};
|
|
@ -0,0 +1,22 @@
|
|||
import IconButton from '@mui/material/IconButton/IconButton';
|
||||
import PermMedia from '@mui/icons-material/PermMedia';
|
||||
import React, { type FC } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import type { ActivityLogEntryCell } from 'apps/dashboard/features/activity/types/ActivityLogEntryCell';
|
||||
import globalize from 'lib/globalize';
|
||||
|
||||
const ActionsCell: FC<ActivityLogEntryCell> = ({ row }) => (
|
||||
row.original.ItemId ? (
|
||||
<IconButton
|
||||
size='large'
|
||||
title={globalize.translate('LabelMediaDetails')}
|
||||
component={Link}
|
||||
to={`/details?id=${row.original.ItemId}`}
|
||||
>
|
||||
<PermMedia fontSize='inherit' />
|
||||
</IconButton>
|
||||
) : undefined
|
||||
);
|
||||
|
||||
export default ActionsCell;
|
|
@ -0,0 +1,14 @@
|
|||
import type { LogLevel } from '@jellyfin/sdk/lib/generated-client/models/log-level';
|
||||
import React, { type FC } from 'react';
|
||||
|
||||
import { ActivityLogEntryCell } from '../types/ActivityLogEntryCell';
|
||||
import LogLevelChip from './LogLevelChip';
|
||||
|
||||
const LogLevelCell: FC<ActivityLogEntryCell> = ({ cell }) => {
|
||||
const level = cell.getValue<LogLevel | undefined>();
|
||||
return level ? (
|
||||
<LogLevelChip level={level} />
|
||||
) : undefined;
|
||||
};
|
||||
|
||||
export default LogLevelCell;
|
|
@ -1,12 +1,14 @@
|
|||
import type { ActivityLogEntry } from '@jellyfin/sdk/lib/generated-client/models/activity-log-entry';
|
||||
import Info from '@mui/icons-material/Info';
|
||||
import Box from '@mui/material/Box';
|
||||
import ClickAwayListener from '@mui/material/ClickAwayListener';
|
||||
import IconButton from '@mui/material/IconButton';
|
||||
import Tooltip from '@mui/material/Tooltip';
|
||||
import React, { FC, useCallback, useState } from 'react';
|
||||
import React, { type FC, useCallback, useState } from 'react';
|
||||
|
||||
const OverviewCell: FC<ActivityLogEntry> = ({ Overview, ShortOverview }) => {
|
||||
import type { ActivityLogEntryCell } from '../types/ActivityLogEntryCell';
|
||||
|
||||
const OverviewCell: FC<ActivityLogEntryCell> = ({ row }) => {
|
||||
const { ShortOverview, Overview } = row.original;
|
||||
const displayValue = ShortOverview ?? Overview;
|
||||
const [ open, setOpen ] = useState(false);
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
import type { UserDto } from '@jellyfin/sdk/lib/generated-client/models/user-dto';
|
||||
import IconButton from '@mui/material/IconButton/IconButton';
|
||||
import React, { type FC } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import UserAvatar from 'components/UserAvatar';
|
||||
|
||||
interface UserAvatarButtonProps {
|
||||
user?: UserDto
|
||||
}
|
||||
|
||||
const UserAvatarButton: FC<UserAvatarButtonProps> = ({ user }) => (
|
||||
user?.Id ? (
|
||||
<IconButton
|
||||
size='large'
|
||||
color='inherit'
|
||||
sx={{ padding: 0 }}
|
||||
title={user.Name || undefined}
|
||||
component={Link}
|
||||
to={`/dashboard/users/profile?userId=${user.Id}`}
|
||||
>
|
||||
<UserAvatar user={user} />
|
||||
</IconButton>
|
||||
) : undefined
|
||||
);
|
||||
|
||||
export default UserAvatarButton;
|
|
@ -0,0 +1,7 @@
|
|||
import type { ActivityLogEntry } from '@jellyfin/sdk/lib/generated-client/models/activity-log-entry';
|
||||
import type { MRT_Cell, MRT_Row } from 'material-react-table';
|
||||
|
||||
export interface ActivityLogEntryCell {
|
||||
cell: MRT_Cell<ActivityLogEntry>
|
||||
row: MRT_Row<ActivityLogEntry>
|
||||
}
|
|
@ -1,34 +1,34 @@
|
|||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import type { ActivityLogEntry } from '@jellyfin/sdk/lib/generated-client/models/activity-log-entry';
|
||||
import type { UserDto } from '@jellyfin/sdk/lib/generated-client/models/user-dto';
|
||||
import PermMedia from '@mui/icons-material/PermMedia';
|
||||
import Box from '@mui/material/Box';
|
||||
import IconButton from '@mui/material/IconButton';
|
||||
import ToggleButton from '@mui/material/ToggleButton';
|
||||
import ToggleButtonGroup from '@mui/material/ToggleButtonGroup';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import { DataGrid, type GridColDef } from '@mui/x-data-grid';
|
||||
import { Link, useSearchParams } from 'react-router-dom';
|
||||
import { type MRT_ColumnDef, MaterialReactTable, useMaterialReactTable } from 'material-react-table';
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
|
||||
import { useLogEntires } from 'apps/dashboard/features/activity/api/useLogEntries';
|
||||
import ActionsCell from 'apps/dashboard/features/activity/components/ActionsCell';
|
||||
import LogLevelCell from 'apps/dashboard/features/activity/components/LogLevelCell';
|
||||
import OverviewCell from 'apps/dashboard/features/activity/components/OverviewCell';
|
||||
import UserAvatarButton from 'apps/dashboard/features/activity/components/UserAvatarButton';
|
||||
import type { ActivityLogEntryCell } from 'apps/dashboard/features/activity/types/ActivityLogEntryCell';
|
||||
import Page from 'components/Page';
|
||||
import UserAvatar from 'components/UserAvatar';
|
||||
import { useLogEntires } from 'hooks/useLogEntries';
|
||||
import { useUsers } from 'hooks/useUsers';
|
||||
import { parseISO8601Date, toLocaleDateString, toLocaleTimeString } from 'scripts/datetime';
|
||||
import { parseISO8601Date, toLocaleString } from 'scripts/datetime';
|
||||
import globalize from 'lib/globalize';
|
||||
import { toBoolean } from 'utils/string';
|
||||
|
||||
import LogLevelChip from '../components/activityTable/LogLevelChip';
|
||||
import OverviewCell from '../components/activityTable/OverviewCell';
|
||||
import GridActionsCellLink from '../components/dataGrid/GridActionsCellLink';
|
||||
type UsersRecords = Record<string, UserDto>;
|
||||
|
||||
const DEFAULT_PAGE_SIZE = 25;
|
||||
const VIEW_PARAM = 'useractivity';
|
||||
|
||||
const enum ActivityView {
|
||||
All,
|
||||
User,
|
||||
System
|
||||
All = 'All',
|
||||
User = 'User',
|
||||
System = 'System'
|
||||
}
|
||||
|
||||
const getActivityView = (param: string | null) => {
|
||||
|
@ -37,7 +37,11 @@ const getActivityView = (param: string | null) => {
|
|||
return ActivityView.System;
|
||||
};
|
||||
|
||||
const getRowId = (row: ActivityLogEntry) => row.Id ?? -1;
|
||||
const getUserCell = (users: UsersRecords) => function UserCell({ row }: ActivityLogEntryCell) {
|
||||
return (
|
||||
<UserAvatarButton user={row.original.UserId && users[row.original.UserId] || undefined} />
|
||||
);
|
||||
};
|
||||
|
||||
const Activity = () => {
|
||||
const [ searchParams, setSearchParams ] = useSearchParams();
|
||||
|
@ -45,14 +49,13 @@ const Activity = () => {
|
|||
const [ activityView, setActivityView ] = useState(
|
||||
getActivityView(searchParams.get(VIEW_PARAM)));
|
||||
|
||||
const [ paginationModel, setPaginationModel ] = useState({
|
||||
page: 0,
|
||||
const [ pagination, setPagination ] = useState({
|
||||
pageIndex: 0,
|
||||
pageSize: DEFAULT_PAGE_SIZE
|
||||
});
|
||||
|
||||
const { data: usersData, isLoading: isUsersLoading } = useUsers();
|
||||
|
||||
type UsersRecords = Record<string, UserDto>;
|
||||
const users: UsersRecords = useMemo(() => {
|
||||
if (!usersData) return {};
|
||||
|
||||
|
@ -67,107 +70,79 @@ const Activity = () => {
|
|||
}, {});
|
||||
}, [usersData]);
|
||||
|
||||
const UserCell = getUserCell(users);
|
||||
|
||||
const activityParams = useMemo(() => ({
|
||||
startIndex: paginationModel.page * paginationModel.pageSize,
|
||||
limit: paginationModel.pageSize,
|
||||
startIndex: pagination.pageIndex * pagination.pageSize,
|
||||
limit: pagination.pageSize,
|
||||
hasUserId: activityView !== ActivityView.All ? activityView === ActivityView.User : undefined
|
||||
}), [activityView, paginationModel.page, paginationModel.pageSize]);
|
||||
}), [activityView, pagination.pageIndex, pagination.pageSize]);
|
||||
|
||||
const { data: logEntries, isLoading: isLogEntriesLoading } = useLogEntires(activityParams);
|
||||
|
||||
const isLoading = isUsersLoading || isLogEntriesLoading;
|
||||
|
||||
const userColDef: GridColDef[] = activityView !== ActivityView.System ? [
|
||||
{
|
||||
field: 'User',
|
||||
headerName: globalize.translate('LabelUser'),
|
||||
width: 60,
|
||||
valueGetter: ( value, row ) => users[row.UserId]?.Name,
|
||||
renderCell: ({ row }) => (
|
||||
<IconButton
|
||||
size='large'
|
||||
color='inherit'
|
||||
sx={{ padding: 0 }}
|
||||
title={users[row.UserId]?.Name ?? undefined}
|
||||
component={Link}
|
||||
to={`/dashboard/users/profile?userId=${row.UserId}`}
|
||||
>
|
||||
<UserAvatar user={users[row.UserId]} />
|
||||
</IconButton>
|
||||
)
|
||||
}
|
||||
] : [];
|
||||
|
||||
const columns: GridColDef[] = [
|
||||
{
|
||||
field: 'Date',
|
||||
headerName: globalize.translate('LabelDate'),
|
||||
width: 90,
|
||||
type: 'date',
|
||||
valueGetter: ( value ) => parseISO8601Date(value),
|
||||
valueFormatter: ( value ) => toLocaleDateString(value)
|
||||
},
|
||||
{
|
||||
field: 'Time',
|
||||
headerName: globalize.translate('LabelTime'),
|
||||
width: 100,
|
||||
type: 'dateTime',
|
||||
valueGetter: ( value, row ) => parseISO8601Date(row.Date),
|
||||
valueFormatter: ( value ) => toLocaleTimeString(value)
|
||||
},
|
||||
{
|
||||
field: 'Severity',
|
||||
headerName: globalize.translate('LabelLevel'),
|
||||
width: 110,
|
||||
renderCell: ({ value }) => (
|
||||
value ? (
|
||||
<LogLevelChip level={value} />
|
||||
) : undefined
|
||||
)
|
||||
},
|
||||
...userColDef,
|
||||
{
|
||||
field: 'Name',
|
||||
headerName: globalize.translate('LabelName'),
|
||||
width: 300
|
||||
},
|
||||
{
|
||||
field: 'Overview',
|
||||
headerName: globalize.translate('LabelOverview'),
|
||||
width: 200,
|
||||
valueGetter: ( value, row ) => row.ShortOverview ?? row.Overview,
|
||||
renderCell: ({ row }) => (
|
||||
<OverviewCell {...row} />
|
||||
)
|
||||
},
|
||||
{
|
||||
field: 'Type',
|
||||
headerName: globalize.translate('LabelType'),
|
||||
width: 180
|
||||
},
|
||||
{
|
||||
field: 'actions',
|
||||
type: 'actions',
|
||||
width: 50,
|
||||
getActions: ({ row }) => {
|
||||
const actions = [];
|
||||
|
||||
if (row.ItemId) {
|
||||
actions.push(
|
||||
<GridActionsCellLink
|
||||
size='large'
|
||||
icon={<PermMedia />}
|
||||
label={globalize.translate('LabelMediaDetails')}
|
||||
title={globalize.translate('LabelMediaDetails')}
|
||||
to={`/details?id=${row.ItemId}`}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return actions;
|
||||
const userColumn: MRT_ColumnDef<ActivityLogEntry>[] = useMemo(() =>
|
||||
(activityView === ActivityView.System) ? [] : [{
|
||||
id: 'User',
|
||||
accessorFn: row => row.UserId && users[row.UserId]?.Name,
|
||||
header: globalize.translate('LabelUser'),
|
||||
size: 75,
|
||||
Cell: UserCell,
|
||||
enableResizing: false,
|
||||
muiTableBodyCellProps: {
|
||||
align: 'center'
|
||||
}
|
||||
}], [ activityView, users, UserCell ]);
|
||||
|
||||
const columns = useMemo<MRT_ColumnDef<ActivityLogEntry>[]>(() => [
|
||||
{
|
||||
id: 'Date',
|
||||
accessorFn: row => parseISO8601Date(row.Date),
|
||||
header: globalize.translate('LabelTime'),
|
||||
size: 160,
|
||||
Cell: ({ cell }) => toLocaleString(cell.getValue<Date>())
|
||||
},
|
||||
{
|
||||
accessorKey: 'Severity',
|
||||
header: globalize.translate('LabelLevel'),
|
||||
size: 90,
|
||||
Cell: LogLevelCell,
|
||||
enableResizing: false,
|
||||
muiTableBodyCellProps: {
|
||||
align: 'center'
|
||||
}
|
||||
},
|
||||
...userColumn,
|
||||
{
|
||||
accessorKey: 'Name',
|
||||
header: globalize.translate('LabelName'),
|
||||
size: 270
|
||||
},
|
||||
{
|
||||
id: 'Overview',
|
||||
accessorFn: row => row.ShortOverview || row.Overview,
|
||||
header: globalize.translate('LabelOverview'),
|
||||
size: 170,
|
||||
Cell: OverviewCell
|
||||
},
|
||||
{
|
||||
accessorKey: 'Type',
|
||||
header: globalize.translate('LabelType'),
|
||||
size: 150
|
||||
},
|
||||
{
|
||||
id: 'Actions',
|
||||
accessorFn: row => row.ItemId,
|
||||
header: '',
|
||||
size: 60,
|
||||
Cell: ActionsCell,
|
||||
enableColumnActions: false,
|
||||
enableColumnFilter: false,
|
||||
enableResizing: false,
|
||||
enableSorting: false
|
||||
}
|
||||
];
|
||||
], [ userColumn ]);
|
||||
|
||||
const onViewChange = useCallback((_e: React.MouseEvent<HTMLElement, MouseEvent>, newView: ActivityView | null) => {
|
||||
if (newView !== null) {
|
||||
|
@ -187,6 +162,58 @@ const Activity = () => {
|
|||
}
|
||||
}, [ activityView, searchParams, setSearchParams ]);
|
||||
|
||||
const table = useMaterialReactTable({
|
||||
columns,
|
||||
data: logEntries?.Items || [],
|
||||
|
||||
// Enable custom features
|
||||
enableColumnPinning: true,
|
||||
enableColumnResizing: true,
|
||||
|
||||
// Sticky header/footer
|
||||
enableStickyFooter: true,
|
||||
enableStickyHeader: true,
|
||||
muiTableContainerProps: {
|
||||
sx: {
|
||||
maxHeight: 'calc(100% - 7rem)' // 2 x 3.5rem for header and footer
|
||||
}
|
||||
},
|
||||
|
||||
// State
|
||||
initialState: {
|
||||
density: 'compact'
|
||||
},
|
||||
state: {
|
||||
isLoading,
|
||||
pagination
|
||||
},
|
||||
|
||||
// Server pagination
|
||||
manualPagination: true,
|
||||
onPaginationChange: setPagination,
|
||||
rowCount: logEntries?.TotalRecordCount || 0,
|
||||
|
||||
// Custom toolbar contents
|
||||
renderTopToolbarCustomActions: () => (
|
||||
<ToggleButtonGroup
|
||||
size='small'
|
||||
value={activityView}
|
||||
onChange={onViewChange}
|
||||
exclusive
|
||||
>
|
||||
<ToggleButton value={ActivityView.All}>
|
||||
{globalize.translate('All')}
|
||||
</ToggleButton>
|
||||
<ToggleButton value={ActivityView.User}>
|
||||
{globalize.translate('LabelUser')}
|
||||
</ToggleButton>
|
||||
<ToggleButton value={ActivityView.System}>
|
||||
{globalize.translate('LabelSystem')}
|
||||
</ToggleButton>
|
||||
</ToggleButtonGroup>
|
||||
)
|
||||
});
|
||||
|
||||
return (
|
||||
<Page
|
||||
id='serverActivityPage'
|
||||
|
@ -203,43 +230,14 @@ const Activity = () => {
|
|||
>
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
alignItems: 'baseline',
|
||||
marginY: 2
|
||||
marginBottom: 1
|
||||
}}
|
||||
>
|
||||
<Box sx={{ flexGrow: 1 }}>
|
||||
<Typography variant='h2'>
|
||||
{globalize.translate('HeaderActivity')}
|
||||
</Typography>
|
||||
</Box>
|
||||
<ToggleButtonGroup
|
||||
value={activityView}
|
||||
onChange={onViewChange}
|
||||
exclusive
|
||||
>
|
||||
<ToggleButton value={ActivityView.All}>
|
||||
{globalize.translate('All')}
|
||||
</ToggleButton>
|
||||
<ToggleButton value={ActivityView.User}>
|
||||
{globalize.translate('LabelUser')}
|
||||
</ToggleButton>
|
||||
<ToggleButton value={ActivityView.System}>
|
||||
{globalize.translate('LabelSystem')}
|
||||
</ToggleButton>
|
||||
</ToggleButtonGroup>
|
||||
<Typography variant='h2'>
|
||||
{globalize.translate('HeaderActivity')}
|
||||
</Typography>
|
||||
</Box>
|
||||
<DataGrid
|
||||
columns={columns}
|
||||
rows={logEntries?.Items || []}
|
||||
pageSizeOptions={[ 10, 25, 50, 100 ]}
|
||||
paginationMode='server'
|
||||
paginationModel={paginationModel}
|
||||
onPaginationModelChange={setPaginationModel}
|
||||
rowCount={logEntries?.TotalRecordCount || 0}
|
||||
getRowId={getRowId}
|
||||
loading={isLoading}
|
||||
/>
|
||||
<MaterialReactTable table={table} />
|
||||
</Box>
|
||||
</Page>
|
||||
);
|
||||
|
|
|
@ -1,18 +1,20 @@
|
|||
import type { AxiosRequestConfig } from 'axios';
|
||||
import type { Api } from '@jellyfin/sdk';
|
||||
import type { UserApiGetUsersRequest } from '@jellyfin/sdk/lib/generated-client';
|
||||
import { getUserApi } from '@jellyfin/sdk/lib/utils/api/user-api';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
|
||||
import { type JellyfinApiContext, useApi } from './useApi';
|
||||
import { useApi } from './useApi';
|
||||
|
||||
export const fetchGetUsers = async (
|
||||
currentApi: JellyfinApiContext,
|
||||
const fetchUsers = async (
|
||||
api?: Api,
|
||||
requestParams?: UserApiGetUsersRequest,
|
||||
options?: AxiosRequestConfig
|
||||
) => {
|
||||
const { api } = currentApi;
|
||||
|
||||
if (!api) return;
|
||||
if (!api) {
|
||||
console.warn('[fetchUsers] No API instance available');
|
||||
return;
|
||||
}
|
||||
|
||||
const response = await getUserApi(api).getUsers(requestParams, {
|
||||
signal: options?.signal
|
||||
|
@ -22,10 +24,11 @@ export const fetchGetUsers = async (
|
|||
};
|
||||
|
||||
export const useUsers = (requestParams?: UserApiGetUsersRequest) => {
|
||||
const currentApi = useApi();
|
||||
const { api } = useApi();
|
||||
return useQuery({
|
||||
queryKey: ['Users'],
|
||||
queryFn: ({ signal }) =>
|
||||
fetchGetUsers(currentApi, requestParams, { signal })
|
||||
fetchUsers(api, requestParams, { signal }),
|
||||
enabled: !!api
|
||||
});
|
||||
};
|
|
@ -185,13 +185,18 @@ const config = {
|
|||
include: [
|
||||
path.resolve(__dirname, 'node_modules/@jellyfin/libass-wasm'),
|
||||
path.resolve(__dirname, 'node_modules/@jellyfin/sdk'),
|
||||
path.resolve(__dirname, 'node_modules/@mui/x-data-grid'),
|
||||
path.resolve(__dirname, 'node_modules/@mui/x-date-pickers'),
|
||||
path.resolve(__dirname, 'node_modules/@react-hook/latest'),
|
||||
path.resolve(__dirname, 'node_modules/@react-hook/passive-layout-effect'),
|
||||
path.resolve(__dirname, 'node_modules/@react-hook/resize-observer'),
|
||||
path.resolve(__dirname, 'node_modules/@remix-run/router'),
|
||||
path.resolve(__dirname, 'node_modules/@tanstack/match-sorter-utils'),
|
||||
path.resolve(__dirname, 'node_modules/@tanstack/query-core'),
|
||||
path.resolve(__dirname, 'node_modules/@tanstack/react-query'),
|
||||
path.resolve(__dirname, 'node_modules/@tanstack/react-table'),
|
||||
path.resolve(__dirname, 'node_modules/@tanstack/react-virtual'),
|
||||
path.resolve(__dirname, 'node_modules/@tanstack/table-core'),
|
||||
path.resolve(__dirname, 'node_modules/@tanstack/virtual-core'),
|
||||
path.resolve(__dirname, 'node_modules/@uupaa/dynamic-import-polyfill'),
|
||||
path.resolve(__dirname, 'node_modules/axios'),
|
||||
path.resolve(__dirname, 'node_modules/blurhash'),
|
||||
|
@ -200,14 +205,17 @@ const config = {
|
|||
path.resolve(__dirname, 'node_modules/dom7'),
|
||||
path.resolve(__dirname, 'node_modules/epubjs'),
|
||||
path.resolve(__dirname, 'node_modules/flv.js'),
|
||||
path.resolve(__dirname, 'node_modules/highlight-words'),
|
||||
path.resolve(__dirname, 'node_modules/libarchive.js'),
|
||||
path.resolve(__dirname, 'node_modules/linkify-it'),
|
||||
path.resolve(__dirname, 'node_modules/markdown-it'),
|
||||
path.resolve(__dirname, 'node_modules/material-react-table'),
|
||||
path.resolve(__dirname, 'node_modules/mdurl'),
|
||||
path.resolve(__dirname, 'node_modules/punycode'),
|
||||
path.resolve(__dirname, 'node_modules/react-blurhash'),
|
||||
path.resolve(__dirname, 'node_modules/react-lazy-load-image-component'),
|
||||
path.resolve(__dirname, 'node_modules/react-router'),
|
||||
path.resolve(__dirname, 'node_modules/remove-accents'),
|
||||
path.resolve(__dirname, 'node_modules/screenfull'),
|
||||
path.resolve(__dirname, 'node_modules/ssr-window'),
|
||||
path.resolve(__dirname, 'node_modules/swiper'),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue