From 694ba9718df2d4e3e64aba0ee4bed13221a6bdf0 Mon Sep 17 00:00:00 2001 From: Bill Thornton Date: Mon, 26 Aug 2024 17:10:35 -0400 Subject: [PATCH] Migrate to material react table --- package-lock.json | 388 ++++++++++++++++++++----- package.json | 2 + src/apps/dashboard/routes/activity.tsx | 279 ++++++++++-------- webpack.common.js | 9 + 4 files changed, 480 insertions(+), 198 deletions(-) diff --git a/package-lock.json b/package-lock.json index f3d690680e..822daaa935 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,6 +22,7 @@ "@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 +49,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 +2008,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 +5419,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 +5445,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 +5476,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 +5515,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 +5528,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,9 +5557,9 @@ } }, "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", @@ -5584,6 +5587,70 @@ "react-dom": "^17.0.0 || ^18.0.0" } }, + "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.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", + "react-transition-group": "^4.4.5" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "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": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -6254,6 +6321,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 +6389,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 +6723,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", @@ -6630,9 +6768,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": "*" } @@ -13202,6 +13340,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", @@ -15471,6 +15618,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", @@ -19948,6 +20122,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", @@ -28243,9 +28422,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" } @@ -29785,19 +29964,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", @@ -29806,41 +29985,43 @@ } }, "@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==" } } }, @@ -29857,6 +30038,20 @@ "reselect": "^4.1.8" } }, + "@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.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", + "react-transition-group": "^4.4.5" + } + }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -30266,6 +30461,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", @@ -30292,6 +30495,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", @@ -30555,9 +30784,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", @@ -30599,9 +30828,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": "*" } @@ -35411,6 +35640,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", @@ -37050,6 +37284,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", @@ -39886,6 +40131,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", diff --git a/package.json b/package.json index 74f63f3338..467db13292 100644 --- a/package.json +++ b/package.json @@ -86,6 +86,7 @@ "@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 +113,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", diff --git a/src/apps/dashboard/routes/activity.tsx b/src/apps/dashboard/routes/activity.tsx index e5f102c131..21a7dfd446 100644 --- a/src/apps/dashboard/routes/activity.tsx +++ b/src/apps/dashboard/routes/activity.tsx @@ -1,5 +1,8 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react'; +import { getActivityLogApi } from '@jellyfin/sdk/lib/utils/api/activity-log-api'; +import { getUserApi } from '@jellyfin/sdk/lib/utils/api/user-api'; import type { ActivityLogEntry } from '@jellyfin/sdk/lib/generated-client/models/activity-log-entry'; +import { LogLevel } from '@jellyfin/sdk/lib/generated-client/models/log-level'; 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'; @@ -7,20 +10,19 @@ 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 { type MRT_Cell, type MRT_ColumnDef, type MRT_Row, MaterialReactTable, useMaterialReactTable } from 'material-react-table'; import { Link, useSearchParams } from 'react-router-dom'; 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'; const DEFAULT_PAGE_SIZE = 25; const VIEW_PARAM = 'useractivity'; @@ -37,16 +39,14 @@ const getActivityView = (param: string | null) => { return ActivityView.System; }; -const getRowId = (row: ActivityLogEntry) => row.Id ?? -1; - const Activity = () => { const [ searchParams, setSearchParams ] = useSearchParams(); 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 }); @@ -68,106 +68,104 @@ const Activity = () => { }, [usersData]); 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 ? [ + const columns = useMemo[]>(() => [ { - field: 'User', - headerName: globalize.translate('LabelUser'), - width: 60, - valueGetter: ( value, row ) => users[row.UserId]?.Name, - renderCell: ({ row }) => ( - - - - ) - } - ] : []; - - const columns: GridColDef[] = [ - { - field: 'Date', - headerName: globalize.translate('LabelDate'), - width: 90, - type: 'date', - valueGetter: ( value ) => parseISO8601Date(value), - valueFormatter: ( value ) => toLocaleDateString(value) + id: 'Date', + accessorFn: row => parseISO8601Date(row.Date), + header: globalize.translate('LabelTime'), + size: 160, + Cell: ({ cell }) => toLocaleString(cell.getValue()) }, { - 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 ? ( - + accessorKey: 'Severity', + header: globalize.translate('LabelLevel'), + size: 90, + Cell: ({ cell }: { cell: MRT_Cell }) => ( + cell.getValue() ? ( + ()} /> ) : 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 }) => ( - - ) - }, - { - field: 'Type', - headerName: globalize.translate('LabelType'), - width: 180 - }, - { - field: 'actions', - type: 'actions', - width: 50, - getActions: ({ row }) => { - const actions = []; - - if (row.ItemId) { - actions.push( - } - label={globalize.translate('LabelMediaDetails')} - title={globalize.translate('LabelMediaDetails')} - to={`/details?id=${row.ItemId}`} - /> - ); - } - - return actions; + ), + enableResizing: false, + muiTableBodyCellProps: { + align: 'center' } + }, + { + id: 'User', + accessorFn: row => row.UserId && users[row.UserId]?.Name, + header: globalize.translate('LabelUser'), + size: 75, + Cell: ({ row }: { row: MRT_Row }) => ( + row.original.UserId ? ( + + + + ) : undefined + ), + enableResizing: false, + visibleInShowHideMenu: activityView !== ActivityView.System, + muiTableBodyCellProps: { + align: 'center' + } + }, + { + accessorKey: 'Name', + header: globalize.translate('LabelName'), + size: 270 + }, + { + id: 'Overview', + accessorFn: row => row.ShortOverview || row.Overview, + header: globalize.translate('LabelOverview'), + size: 170, + Cell: ({ row }: { row: MRT_Row }) => ( + + ) + }, + { + accessorKey: 'Type', + header: globalize.translate('LabelType'), + size: 150 + }, + { + id: 'Actions', + accessorFn: row => row.ItemId, + header: '', + size: 60, + Cell: ({ row }: { row: MRT_Row }) => ( + row.original.ItemId ? ( + + + + ) : undefined + ), + enableColumnActions: false, + enableColumnFilter: false, + enableResizing: false, + enableSorting: false } - ]; + ], [ activityView, users ]); const onViewChange = useCallback((_e: React.MouseEvent, newView: ActivityView | null) => { if (newView !== null) { @@ -187,6 +185,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 + state: { + isLoading, + pagination, + columnVisibility: { + User: activityView !== ActivityView.System + } + }, + + // Server pagination + manualPagination: true, + onPaginationChange: setPagination, + rowCount: logEntries?.TotalRecordCount || 0, + + // Custom toolbar contents + renderTopToolbarCustomActions: () => ( + + + {globalize.translate('All')} + + + {globalize.translate('LabelUser')} + + + {globalize.translate('LabelSystem')} + + + ) + }); + return ( { > - - - {globalize.translate('HeaderActivity')} - - - - - {globalize.translate('All')} - - - {globalize.translate('LabelUser')} - - - {globalize.translate('LabelSystem')} - - + + {globalize.translate('HeaderActivity')} + - + ); diff --git a/webpack.common.js b/webpack.common.js index 46e372da34..cceb788807 100644 --- a/webpack.common.js +++ b/webpack.common.js @@ -186,12 +186,18 @@ const config = { 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 +206,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'),