Porównaj commity

...

4 Commity

Autor SHA1 Wiadomość Data
Štěpán Škorpil 75c9fd63e7 Stats page now stores the search query in url 2022-05-15 12:57:18 +02:00
Štěpán Škorpil 861e2a1476 Node page now stores the search query in url 2022-05-15 12:40:42 +02:00
Štěpán Škorpil abc52b915a Feed page now stores the search query in url 2022-05-15 11:45:37 +02:00
Štěpán Škorpil 91faebaa50 Updated vulnerable libraries 2022-05-15 11:44:40 +02:00
12 zmienionych plików z 317 dodań i 249 usunięć

Wyświetl plik

@ -2340,9 +2340,9 @@
}
},
"node_modules/@next/env": {
"version": "12.0.10",
"resolved": "https://registry.npmjs.org/@next/env/-/env-12.0.10.tgz",
"integrity": "sha512-mQVj0K6wQ5WEk/sL9SZ+mJXJUaG7el8CpZ6io1uFe9GgNTSC7EgUyNGqM6IQovIFc5ukF4O/hqsdh3S/DCgT2g=="
"version": "12.1.6",
"resolved": "https://registry.npmjs.org/@next/env/-/env-12.1.6.tgz",
"integrity": "sha512-Te/OBDXFSodPU6jlXYPAXpmZr/AkG6DCATAxttQxqOWaq6eDFX25Db3dK0120GZrSZmv4QCe9KsZmJKDbWs4OA=="
},
"node_modules/@next/eslint-plugin-next": {
"version": "12.0.8",
@ -2353,10 +2353,25 @@
"glob": "7.1.7"
}
},
"node_modules/@next/swc-android-arm-eabi": {
"version": "12.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-12.1.6.tgz",
"integrity": "sha512-BxBr3QAAAXWgk/K7EedvzxJr2dE014mghBSA9iOEAv0bMgF+MRq4PoASjuHi15M2zfowpcRG8XQhMFtxftCleQ==",
"cpu": [
"arm"
],
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@next/swc-android-arm64": {
"version": "12.0.10",
"resolved": "https://registry.npmjs.org/@next/swc-android-arm64/-/swc-android-arm64-12.0.10.tgz",
"integrity": "sha512-xYwXGkNhzZZsM5MD7KRwF5ZNiC8OLPtVMUiagpPnwENg8Hb0GSQo/NbYWXM8YrawEwp9LaZ7OXiuRKPh2JyBdA==",
"version": "12.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-android-arm64/-/swc-android-arm64-12.1.6.tgz",
"integrity": "sha512-EboEk3ROYY7U6WA2RrMt/cXXMokUTXXfnxe2+CU+DOahvbrO8QSWhlBl9I9ZbFzJx28AGB9Yo3oQHCvph/4Lew==",
"cpu": [
"arm64"
],
@ -2369,9 +2384,9 @@
}
},
"node_modules/@next/swc-darwin-arm64": {
"version": "12.0.10",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.0.10.tgz",
"integrity": "sha512-f2zngulkpIJKWHckhRi7X8GZ+J/tNgFF7lYIh7Qx15JH0OTBsjkqxORlkzy+VZyHJ5sWTCaI6HYYd3ow6qkEEg==",
"version": "12.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.1.6.tgz",
"integrity": "sha512-P0EXU12BMSdNj1F7vdkP/VrYDuCNwBExtRPDYawgSUakzi6qP0iKJpya2BuLvNzXx+XPU49GFuDC5X+SvY0mOw==",
"cpu": [
"arm64"
],
@ -2384,9 +2399,9 @@
}
},
"node_modules/@next/swc-darwin-x64": {
"version": "12.0.10",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-12.0.10.tgz",
"integrity": "sha512-Qykcu/gVC5oTvOQoRBhyuS5GYm5SbcgrFTsaLFkGBmEkg9eMQRiaCswk4IafpDXVzITkVFurzSM28q3tLW2qUw==",
"version": "12.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-12.1.6.tgz",
"integrity": "sha512-9FptMnbgHJK3dRDzfTpexs9S2hGpzOQxSQbe8omz6Pcl7rnEp9x4uSEKY51ho85JCjL4d0tDLBcXEJZKKLzxNg==",
"cpu": [
"x64"
],
@ -2399,9 +2414,9 @@
}
},
"node_modules/@next/swc-linux-arm-gnueabihf": {
"version": "12.0.10",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.0.10.tgz",
"integrity": "sha512-EhqrTFsIXAXN9B/fiiW/QKUK/lSLCXRsLalkUp58KDfMqVLLlj1ORbESAcswiNQOChLuHQSldGEEtOBPQZcd9A==",
"version": "12.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.1.6.tgz",
"integrity": "sha512-PvfEa1RR55dsik/IDkCKSFkk6ODNGJqPY3ysVUZqmnWMDSuqFtf7BPWHFa/53znpvVB5XaJ5Z1/6aR5CTIqxPw==",
"cpu": [
"arm"
],
@ -2414,9 +2429,9 @@
}
},
"node_modules/@next/swc-linux-arm64-gnu": {
"version": "12.0.10",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.0.10.tgz",
"integrity": "sha512-kqGtC72g3+JYXZbY2ca6digXR5U6AQ6Dzv4eAxYluMePLHjI/Xye1mf9dwVsgmeXfrD/IRDp5K/3A6UNvBm4oQ==",
"version": "12.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.1.6.tgz",
"integrity": "sha512-53QOvX1jBbC2ctnmWHyRhMajGq7QZfl974WYlwclXarVV418X7ed7o/EzGY+YVAEKzIVaAB9JFFWGXn8WWo0gQ==",
"cpu": [
"arm64"
],
@ -2429,9 +2444,9 @@
}
},
"node_modules/@next/swc-linux-arm64-musl": {
"version": "12.0.10",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.0.10.tgz",
"integrity": "sha512-bG9zTSNwnSgc1Un/7oz1ZVN4UeXsTWrsQhAGWU78lLLCn4Zj9HQoUCRCGLt0OVs2DBZ+WC8CzzFliQ1SKipVbg==",
"version": "12.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.1.6.tgz",
"integrity": "sha512-CMWAkYqfGdQCS+uuMA1A2UhOfcUYeoqnTW7msLr2RyYAys15pD960hlDfq7QAi8BCAKk0sQ2rjsl0iqMyziohQ==",
"cpu": [
"arm64"
],
@ -2444,9 +2459,9 @@
}
},
"node_modules/@next/swc-linux-x64-gnu": {
"version": "12.0.10",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.0.10.tgz",
"integrity": "sha512-c79PcfWtyThiYRa1+3KVfDq0zXaI8o1d6dQWNVqDrtLz5HKM/rbjLdvoNuxDwUeZhxI/d9CtyH6GbuKPw5l/5A==",
"version": "12.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.1.6.tgz",
"integrity": "sha512-AC7jE4Fxpn0s3ujngClIDTiEM/CQiB2N2vkcyWWn6734AmGT03Duq6RYtPMymFobDdAtZGFZd5nR95WjPzbZAQ==",
"cpu": [
"x64"
],
@ -2459,9 +2474,9 @@
}
},
"node_modules/@next/swc-linux-x64-musl": {
"version": "12.0.10",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.0.10.tgz",
"integrity": "sha512-g/scgn+21/MLfizOCZOZt+MxNj2/8Tdlwjvy+QZcSUPZRUI2Y5o3HwBvI1f/bSci+NGRU+bUAO0NFtRJ9MzH5w==",
"version": "12.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.1.6.tgz",
"integrity": "sha512-c9Vjmi0EVk0Kou2qbrynskVarnFwfYIi+wKufR9Ad7/IKKuP6aEhOdZiIIdKsYWRtK2IWRF3h3YmdnEa2WLUag==",
"cpu": [
"x64"
],
@ -2474,9 +2489,9 @@
}
},
"node_modules/@next/swc-win32-arm64-msvc": {
"version": "12.0.10",
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.0.10.tgz",
"integrity": "sha512-gl6B/ravwMeY5Nv4Il2/ARYJQ6u+KPRwGMjS1ZrNudIKlNn4YBeXh5A4cIVm+dHaff6/O/lGOa5/SUYDMZpkww==",
"version": "12.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.1.6.tgz",
"integrity": "sha512-3UTOL/5XZSKFelM7qN0it35o3Cegm6LsyuERR3/OoqEExyj3aCk7F025b54/707HTMAnjlvQK3DzLhPu/xxO4g==",
"cpu": [
"arm64"
],
@ -2489,9 +2504,9 @@
}
},
"node_modules/@next/swc-win32-ia32-msvc": {
"version": "12.0.10",
"resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.0.10.tgz",
"integrity": "sha512-7RVpZ3tSThC6j+iZB0CUYmFiA3kXmN+pE7QcfyAxFaflKlaZoWNMKHIEZDuxSJc6YmQ6kyxsjqxVay2F5+/YCg==",
"version": "12.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.1.6.tgz",
"integrity": "sha512-8ZWoj6nCq6fI1yCzKq6oK0jE6Mxlz4MrEsRyu0TwDztWQWe7rh4XXGLAa2YVPatYcHhMcUL+fQQbqd1MsgaSDA==",
"cpu": [
"ia32"
],
@ -2504,9 +2519,9 @@
}
},
"node_modules/@next/swc-win32-x64-msvc": {
"version": "12.0.10",
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.0.10.tgz",
"integrity": "sha512-oUIWRKd24jFLRWUYO1CZmML5+32BcpVfqhimGaaZIXcOkfQW+iqiAzdqsv688zaGtyKGeB9ZtiK3NDf+Q0v+Vw==",
"version": "12.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.1.6.tgz",
"integrity": "sha512-4ZEwiRuZEicXhXqmhw3+de8Z4EpOLQj/gp+D9fFWo6ii6W1kBkNNvvEx4A90ugppu+74pT1lIJnOuz3A9oQeJA==",
"cpu": [
"x64"
],
@ -3800,13 +3815,19 @@
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001299",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001299.tgz",
"integrity": "sha512-iujN4+x7QzqA2NCSrS5VUy+4gLmRd4xv6vbBBsmfVqTx8bLAD8097euLqQgKxSVLvxjSDcvF1T/i9ocgnUFexw==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/browserslist"
}
"version": "1.0.30001341",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001341.tgz",
"integrity": "sha512-2SodVrFFtvGENGCv0ChVJIDQ0KPaS1cg7/qtfMaICgeMolDdo/Z2OD32F0Aq9yl6F4YFwGPBS5AaPqNYiW4PoA==",
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/browserslist"
},
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/caniuse-lite"
}
]
},
"node_modules/chalk": {
"version": "4.1.2",
@ -5270,9 +5291,9 @@
"dev": true
},
"node_modules/follow-redirects": {
"version": "1.14.7",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.7.tgz",
"integrity": "sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ==",
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.0.tgz",
"integrity": "sha512-aExlJShTV4qOUOL7yF1U5tvLCB0xQuudbf6toyYA0E/acBNw71mvjFTnLaRp50aQaYocMR0a/RMMBIHeZnGyjQ==",
"funding": [
{
"type": "individual",
@ -7071,9 +7092,9 @@
}
},
"node_modules/minimist": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
"integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q=="
},
"node_modules/ms": {
"version": "2.1.2",
@ -7098,15 +7119,14 @@
"dev": true
},
"node_modules/next": {
"version": "12.0.10",
"resolved": "https://registry.npmjs.org/next/-/next-12.0.10.tgz",
"integrity": "sha512-1y3PpGzpb/EZzz1jgne+JfZXKAVJUjYXwxzrADf/LWN+8yi9o79vMLXpW3mevvCHkEF2sBnIdjzNn16TJrINUw==",
"version": "12.1.6",
"resolved": "https://registry.npmjs.org/next/-/next-12.1.6.tgz",
"integrity": "sha512-cebwKxL3/DhNKfg9tPZDQmbRKjueqykHHbgaoG4VBRH3AHQJ2HO0dbKFiS1hPhe1/qgc2d/hFeadsbPicmLD+A==",
"dependencies": {
"@next/env": "12.0.10",
"caniuse-lite": "^1.0.30001283",
"@next/env": "12.1.6",
"caniuse-lite": "^1.0.30001332",
"postcss": "8.4.5",
"styled-jsx": "5.0.0",
"use-subscription": "1.5.1"
"styled-jsx": "5.0.2"
},
"bin": {
"next": "dist/bin/next"
@ -7115,21 +7135,22 @@
"node": ">=12.22.0"
},
"optionalDependencies": {
"@next/swc-android-arm64": "12.0.10",
"@next/swc-darwin-arm64": "12.0.10",
"@next/swc-darwin-x64": "12.0.10",
"@next/swc-linux-arm-gnueabihf": "12.0.10",
"@next/swc-linux-arm64-gnu": "12.0.10",
"@next/swc-linux-arm64-musl": "12.0.10",
"@next/swc-linux-x64-gnu": "12.0.10",
"@next/swc-linux-x64-musl": "12.0.10",
"@next/swc-win32-arm64-msvc": "12.0.10",
"@next/swc-win32-ia32-msvc": "12.0.10",
"@next/swc-win32-x64-msvc": "12.0.10"
"@next/swc-android-arm-eabi": "12.1.6",
"@next/swc-android-arm64": "12.1.6",
"@next/swc-darwin-arm64": "12.1.6",
"@next/swc-darwin-x64": "12.1.6",
"@next/swc-linux-arm-gnueabihf": "12.1.6",
"@next/swc-linux-arm64-gnu": "12.1.6",
"@next/swc-linux-arm64-musl": "12.1.6",
"@next/swc-linux-x64-gnu": "12.1.6",
"@next/swc-linux-x64-musl": "12.1.6",
"@next/swc-win32-arm64-msvc": "12.1.6",
"@next/swc-win32-ia32-msvc": "12.1.6",
"@next/swc-win32-x64-msvc": "12.1.6"
},
"peerDependencies": {
"fibers": ">= 3.1.0",
"node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0",
"node-sass": "^6.0.0 || ^7.0.0",
"react": "^17.0.2 || ^18.0.0-0",
"react-dom": "^17.0.2 || ^18.0.0-0",
"sass": "^1.3.0"
@ -8896,14 +8917,14 @@
"integrity": "sha512-g45ZOGzHDMe2bdYMdIvdAfCQkCTDMGBazSw1ypMowwGIee7ZQ5dU0rBJ8Jqgl+jAKIv4dbeE1jscZq9wid1Tkw=="
},
"node_modules/styled-jsx": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.0.0.tgz",
"integrity": "sha512-qUqsWoBquEdERe10EW8vLp3jT25s/ssG1/qX5gZ4wu15OZpmSMFI2v+fWlRhLfykA5rFtlJ1ME8A8pm/peV4WA==",
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.0.2.tgz",
"integrity": "sha512-LqPQrbBh3egD57NBcHET4qcgshPks+yblyhPlH2GY8oaDgKs8SK4C3dBh3oSJjgzJ3G5t1SYEZGHkP+QEpX9EQ==",
"engines": {
"node": ">= 12.0.0"
},
"peerDependencies": {
"react": ">= 16.8.0 || 17.x.x || 18.x.x"
"react": ">= 16.8.0 || 17.x.x || ^18.0.0-0"
},
"peerDependenciesMeta": {
"@babel/core": {
@ -9339,17 +9360,6 @@
"punycode": "^2.1.0"
}
},
"node_modules/use-subscription": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/use-subscription/-/use-subscription-1.5.1.tgz",
"integrity": "sha512-Xv2a1P/yReAjAbhylMfFplFKj9GssgTwN7RlcTxBujFQcloStWNDQdc4g4NRWH9xS4i/FDk04vQBptAXoF3VcA==",
"dependencies": {
"object-assign": "^4.1.1"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0"
}
},
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
@ -11253,9 +11263,9 @@
}
},
"@next/env": {
"version": "12.0.10",
"resolved": "https://registry.npmjs.org/@next/env/-/env-12.0.10.tgz",
"integrity": "sha512-mQVj0K6wQ5WEk/sL9SZ+mJXJUaG7el8CpZ6io1uFe9GgNTSC7EgUyNGqM6IQovIFc5ukF4O/hqsdh3S/DCgT2g=="
"version": "12.1.6",
"resolved": "https://registry.npmjs.org/@next/env/-/env-12.1.6.tgz",
"integrity": "sha512-Te/OBDXFSodPU6jlXYPAXpmZr/AkG6DCATAxttQxqOWaq6eDFX25Db3dK0120GZrSZmv4QCe9KsZmJKDbWs4OA=="
},
"@next/eslint-plugin-next": {
"version": "12.0.8",
@ -11266,70 +11276,76 @@
"glob": "7.1.7"
}
},
"@next/swc-android-arm-eabi": {
"version": "12.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-12.1.6.tgz",
"integrity": "sha512-BxBr3QAAAXWgk/K7EedvzxJr2dE014mghBSA9iOEAv0bMgF+MRq4PoASjuHi15M2zfowpcRG8XQhMFtxftCleQ==",
"optional": true
},
"@next/swc-android-arm64": {
"version": "12.0.10",
"resolved": "https://registry.npmjs.org/@next/swc-android-arm64/-/swc-android-arm64-12.0.10.tgz",
"integrity": "sha512-xYwXGkNhzZZsM5MD7KRwF5ZNiC8OLPtVMUiagpPnwENg8Hb0GSQo/NbYWXM8YrawEwp9LaZ7OXiuRKPh2JyBdA==",
"version": "12.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-android-arm64/-/swc-android-arm64-12.1.6.tgz",
"integrity": "sha512-EboEk3ROYY7U6WA2RrMt/cXXMokUTXXfnxe2+CU+DOahvbrO8QSWhlBl9I9ZbFzJx28AGB9Yo3oQHCvph/4Lew==",
"optional": true
},
"@next/swc-darwin-arm64": {
"version": "12.0.10",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.0.10.tgz",
"integrity": "sha512-f2zngulkpIJKWHckhRi7X8GZ+J/tNgFF7lYIh7Qx15JH0OTBsjkqxORlkzy+VZyHJ5sWTCaI6HYYd3ow6qkEEg==",
"version": "12.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.1.6.tgz",
"integrity": "sha512-P0EXU12BMSdNj1F7vdkP/VrYDuCNwBExtRPDYawgSUakzi6qP0iKJpya2BuLvNzXx+XPU49GFuDC5X+SvY0mOw==",
"optional": true
},
"@next/swc-darwin-x64": {
"version": "12.0.10",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-12.0.10.tgz",
"integrity": "sha512-Qykcu/gVC5oTvOQoRBhyuS5GYm5SbcgrFTsaLFkGBmEkg9eMQRiaCswk4IafpDXVzITkVFurzSM28q3tLW2qUw==",
"version": "12.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-12.1.6.tgz",
"integrity": "sha512-9FptMnbgHJK3dRDzfTpexs9S2hGpzOQxSQbe8omz6Pcl7rnEp9x4uSEKY51ho85JCjL4d0tDLBcXEJZKKLzxNg==",
"optional": true
},
"@next/swc-linux-arm-gnueabihf": {
"version": "12.0.10",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.0.10.tgz",
"integrity": "sha512-EhqrTFsIXAXN9B/fiiW/QKUK/lSLCXRsLalkUp58KDfMqVLLlj1ORbESAcswiNQOChLuHQSldGEEtOBPQZcd9A==",
"version": "12.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.1.6.tgz",
"integrity": "sha512-PvfEa1RR55dsik/IDkCKSFkk6ODNGJqPY3ysVUZqmnWMDSuqFtf7BPWHFa/53znpvVB5XaJ5Z1/6aR5CTIqxPw==",
"optional": true
},
"@next/swc-linux-arm64-gnu": {
"version": "12.0.10",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.0.10.tgz",
"integrity": "sha512-kqGtC72g3+JYXZbY2ca6digXR5U6AQ6Dzv4eAxYluMePLHjI/Xye1mf9dwVsgmeXfrD/IRDp5K/3A6UNvBm4oQ==",
"version": "12.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.1.6.tgz",
"integrity": "sha512-53QOvX1jBbC2ctnmWHyRhMajGq7QZfl974WYlwclXarVV418X7ed7o/EzGY+YVAEKzIVaAB9JFFWGXn8WWo0gQ==",
"optional": true
},
"@next/swc-linux-arm64-musl": {
"version": "12.0.10",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.0.10.tgz",
"integrity": "sha512-bG9zTSNwnSgc1Un/7oz1ZVN4UeXsTWrsQhAGWU78lLLCn4Zj9HQoUCRCGLt0OVs2DBZ+WC8CzzFliQ1SKipVbg==",
"version": "12.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.1.6.tgz",
"integrity": "sha512-CMWAkYqfGdQCS+uuMA1A2UhOfcUYeoqnTW7msLr2RyYAys15pD960hlDfq7QAi8BCAKk0sQ2rjsl0iqMyziohQ==",
"optional": true
},
"@next/swc-linux-x64-gnu": {
"version": "12.0.10",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.0.10.tgz",
"integrity": "sha512-c79PcfWtyThiYRa1+3KVfDq0zXaI8o1d6dQWNVqDrtLz5HKM/rbjLdvoNuxDwUeZhxI/d9CtyH6GbuKPw5l/5A==",
"version": "12.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.1.6.tgz",
"integrity": "sha512-AC7jE4Fxpn0s3ujngClIDTiEM/CQiB2N2vkcyWWn6734AmGT03Duq6RYtPMymFobDdAtZGFZd5nR95WjPzbZAQ==",
"optional": true
},
"@next/swc-linux-x64-musl": {
"version": "12.0.10",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.0.10.tgz",
"integrity": "sha512-g/scgn+21/MLfizOCZOZt+MxNj2/8Tdlwjvy+QZcSUPZRUI2Y5o3HwBvI1f/bSci+NGRU+bUAO0NFtRJ9MzH5w==",
"version": "12.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.1.6.tgz",
"integrity": "sha512-c9Vjmi0EVk0Kou2qbrynskVarnFwfYIi+wKufR9Ad7/IKKuP6aEhOdZiIIdKsYWRtK2IWRF3h3YmdnEa2WLUag==",
"optional": true
},
"@next/swc-win32-arm64-msvc": {
"version": "12.0.10",
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.0.10.tgz",
"integrity": "sha512-gl6B/ravwMeY5Nv4Il2/ARYJQ6u+KPRwGMjS1ZrNudIKlNn4YBeXh5A4cIVm+dHaff6/O/lGOa5/SUYDMZpkww==",
"version": "12.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.1.6.tgz",
"integrity": "sha512-3UTOL/5XZSKFelM7qN0it35o3Cegm6LsyuERR3/OoqEExyj3aCk7F025b54/707HTMAnjlvQK3DzLhPu/xxO4g==",
"optional": true
},
"@next/swc-win32-ia32-msvc": {
"version": "12.0.10",
"resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.0.10.tgz",
"integrity": "sha512-7RVpZ3tSThC6j+iZB0CUYmFiA3kXmN+pE7QcfyAxFaflKlaZoWNMKHIEZDuxSJc6YmQ6kyxsjqxVay2F5+/YCg==",
"version": "12.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.1.6.tgz",
"integrity": "sha512-8ZWoj6nCq6fI1yCzKq6oK0jE6Mxlz4MrEsRyu0TwDztWQWe7rh4XXGLAa2YVPatYcHhMcUL+fQQbqd1MsgaSDA==",
"optional": true
},
"@next/swc-win32-x64-msvc": {
"version": "12.0.10",
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.0.10.tgz",
"integrity": "sha512-oUIWRKd24jFLRWUYO1CZmML5+32BcpVfqhimGaaZIXcOkfQW+iqiAzdqsv688zaGtyKGeB9ZtiK3NDf+Q0v+Vw==",
"version": "12.1.6",
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.1.6.tgz",
"integrity": "sha512-4ZEwiRuZEicXhXqmhw3+de8Z4EpOLQj/gp+D9fFWo6ii6W1kBkNNvvEx4A90ugppu+74pT1lIJnOuz3A9oQeJA==",
"optional": true
},
"@nodelib/fs.scandir": {
@ -12225,9 +12241,9 @@
"dev": true
},
"caniuse-lite": {
"version": "1.0.30001299",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001299.tgz",
"integrity": "sha512-iujN4+x7QzqA2NCSrS5VUy+4gLmRd4xv6vbBBsmfVqTx8bLAD8097euLqQgKxSVLvxjSDcvF1T/i9ocgnUFexw=="
"version": "1.0.30001341",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001341.tgz",
"integrity": "sha512-2SodVrFFtvGENGCv0ChVJIDQ0KPaS1cg7/qtfMaICgeMolDdo/Z2OD32F0Aq9yl6F4YFwGPBS5AaPqNYiW4PoA=="
},
"chalk": {
"version": "4.1.2",
@ -13322,9 +13338,9 @@
"dev": true
},
"follow-redirects": {
"version": "1.14.7",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.7.tgz",
"integrity": "sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ=="
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.0.tgz",
"integrity": "sha512-aExlJShTV4qOUOL7yF1U5tvLCB0xQuudbf6toyYA0E/acBNw71mvjFTnLaRp50aQaYocMR0a/RMMBIHeZnGyjQ=="
},
"form-data": {
"version": "3.0.1",
@ -14667,9 +14683,9 @@
}
},
"minimist": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
"integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q=="
},
"ms": {
"version": "2.1.2",
@ -14688,26 +14704,26 @@
"dev": true
},
"next": {
"version": "12.0.10",
"resolved": "https://registry.npmjs.org/next/-/next-12.0.10.tgz",
"integrity": "sha512-1y3PpGzpb/EZzz1jgne+JfZXKAVJUjYXwxzrADf/LWN+8yi9o79vMLXpW3mevvCHkEF2sBnIdjzNn16TJrINUw==",
"version": "12.1.6",
"resolved": "https://registry.npmjs.org/next/-/next-12.1.6.tgz",
"integrity": "sha512-cebwKxL3/DhNKfg9tPZDQmbRKjueqykHHbgaoG4VBRH3AHQJ2HO0dbKFiS1hPhe1/qgc2d/hFeadsbPicmLD+A==",
"requires": {
"@next/env": "12.0.10",
"@next/swc-android-arm64": "12.0.10",
"@next/swc-darwin-arm64": "12.0.10",
"@next/swc-darwin-x64": "12.0.10",
"@next/swc-linux-arm-gnueabihf": "12.0.10",
"@next/swc-linux-arm64-gnu": "12.0.10",
"@next/swc-linux-arm64-musl": "12.0.10",
"@next/swc-linux-x64-gnu": "12.0.10",
"@next/swc-linux-x64-musl": "12.0.10",
"@next/swc-win32-arm64-msvc": "12.0.10",
"@next/swc-win32-ia32-msvc": "12.0.10",
"@next/swc-win32-x64-msvc": "12.0.10",
"caniuse-lite": "^1.0.30001283",
"@next/env": "12.1.6",
"@next/swc-android-arm-eabi": "12.1.6",
"@next/swc-android-arm64": "12.1.6",
"@next/swc-darwin-arm64": "12.1.6",
"@next/swc-darwin-x64": "12.1.6",
"@next/swc-linux-arm-gnueabihf": "12.1.6",
"@next/swc-linux-arm64-gnu": "12.1.6",
"@next/swc-linux-arm64-musl": "12.1.6",
"@next/swc-linux-x64-gnu": "12.1.6",
"@next/swc-linux-x64-musl": "12.1.6",
"@next/swc-win32-arm64-msvc": "12.1.6",
"@next/swc-win32-ia32-msvc": "12.1.6",
"@next/swc-win32-x64-msvc": "12.1.6",
"caniuse-lite": "^1.0.30001332",
"postcss": "8.4.5",
"styled-jsx": "5.0.0",
"use-subscription": "1.5.1"
"styled-jsx": "5.0.2"
}
},
"node-cache": {
@ -15994,9 +16010,9 @@
"integrity": "sha512-g45ZOGzHDMe2bdYMdIvdAfCQkCTDMGBazSw1ypMowwGIee7ZQ5dU0rBJ8Jqgl+jAKIv4dbeE1jscZq9wid1Tkw=="
},
"styled-jsx": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.0.0.tgz",
"integrity": "sha512-qUqsWoBquEdERe10EW8vLp3jT25s/ssG1/qX5gZ4wu15OZpmSMFI2v+fWlRhLfykA5rFtlJ1ME8A8pm/peV4WA==",
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.0.2.tgz",
"integrity": "sha512-LqPQrbBh3egD57NBcHET4qcgshPks+yblyhPlH2GY8oaDgKs8SK4C3dBh3oSJjgzJ3G5t1SYEZGHkP+QEpX9EQ==",
"requires": {}
},
"supports-color": {
@ -16305,14 +16321,6 @@
"punycode": "^2.1.0"
}
},
"use-subscription": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/use-subscription/-/use-subscription-1.5.1.tgz",
"integrity": "sha512-Xv2a1P/yReAjAbhylMfFplFKj9GssgTwN7RlcTxBujFQcloStWNDQdc4g4NRWH9xS4i/FDk04vQBptAXoF3VcA==",
"requires": {
"object-assign": "^4.1.1"
}
},
"util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",

Wyświetl plik

@ -18,6 +18,14 @@ export function preserveNull<Source, Target> (cast: (value:Source)=>Target) {
}
}
export function undefinedToDefault<Type> (defaultValue:Type): (value:Type|undefined)=>Type {
return (value) => typeof value === 'undefined' ? defaultValue : value
}
export function stringTrimmed (value: string|undefined): string {
return (value ?? '').trim().replace(/^\++|\++$/g, '')
}
export function stringToInt (value: string): number {
return parseInt(value)
}

Wyświetl plik

@ -8,7 +8,7 @@ const handleFeedSearch = async (req: NextApiRequest, res: NextApiResponse<FeedRe
console.info('Searching feeds', { query: req.query })
const feedRequest = feedRequestSchema.parse(req.query)
const phrases = feedRequest.search.trim().split(/[\s+]+/)
const phrases = feedRequest.search.split(/[\s+]+/)
const feeds = await prisma.feed.findMany({
where: {
AND: phrases.map(phrase => {

Wyświetl plik

@ -8,9 +8,7 @@ const handleFeedSearch = async (req: NextApiRequest, res: NextApiResponse<NodeRe
console.info('Searching nodes', { query: req.query })
const nodeRequest = nodeRequestSchema.parse(req.query)
const phrases = (nodeRequest.search ?? '').trim().split(/[\s+]+/)
nodeRequest.sortBy = nodeRequest.sortBy ?? 'refreshedAt'
nodeRequest.sortWay = nodeRequest.sortWay ?? 'desc'
const phrases = nodeRequest.search.split(/[\s+]+/)
const order = {}
order[nodeRequest.sortBy] = nodeRequest.sortWay
const nodes = await prisma.node.findMany({

Wyświetl plik

@ -16,8 +16,6 @@ const CACHE_KEY = 'stats'
const handleGetStats = async (req: NextApiRequest, res: NextApiResponse<StatsResponse>): Promise<void> => {
const query = await statsRequestSchema.parseAsync(req.query)
query.sortBy = query.sortBy ?? 'nodeCount'
query.sortWay = query.sortWay ?? 'desc'
const cacheKey = `${CACHE_KEY}_${query.sortWay}_${query.sortBy}`
if (!cache.has(cacheKey)) {
console.info('Retrieving new stats', { cacheKey, query })

Wyświetl plik

@ -1,7 +1,7 @@
import Head from 'next/head'
import React, { useEffect, useState } from 'react'
import axios from 'axios'
import { feedResponseSchema } from '../types/FeedResponse'
import { FeedResponseItem, feedResponseSchema } from '../types/FeedResponse'
import Loader from '../components/Loader'
import FeedResults from '../components/FeedResults'
import Layout, { siteTitle } from '../components/Layout'
@ -10,17 +10,22 @@ import getMatomo from '../lib/getMatomo'
import { GetServerSideProps, InferGetServerSidePropsType } from 'next'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faSearch, faAngleDoubleDown } from '@fortawesome/free-solid-svg-icons'
import { useRouter } from 'next/router'
import { FeedRequestQuery, feedRequestQuerySchema } from '../types/FeedRequest'
let source = axios.CancelToken.source()
const Feeds: React.FC<InferGetServerSidePropsType<typeof getServerSideProps>> = ({ matomoConfig }) => {
const [query, setQuery] = useState('')
const [submitted, setSubmitted] = useState(null)
const [loading, setLoading] = useState(false)
const [results, setResults] = useState([])
const [page, setPage] = useState(0)
const [hasMore, setHasMore] = useState(false)
const [loaded, setLoaded] = useState(false)
const router = useRouter()
const routerQuery = feedRequestQuerySchema.parse(router.query)
console.log('Router query', routerQuery)
const [query, setQuery] = useState<FeedRequestQuery>(routerQuery)
const [submitted, setSubmitted] = useState<Date | null>(null)
const [loading, setLoading] = useState<boolean>(false)
const [results, setResults] = useState<FeedResponseItem[]>([])
const [page, setPage] = useState<number>(0)
const [hasMore, setHasMore] = useState<boolean>(false)
const [loaded, setLoaded] = useState<boolean>(false)
const search = async () => {
setLoading(true)
@ -28,7 +33,7 @@ const Feeds: React.FC<InferGetServerSidePropsType<typeof getServerSideProps>> =
console.info('Retrieving results', { query, page })
source = axios.CancelToken.source()
const response = await axios.get('/api/feed', {
params: { search: query, page },
params: { ...query, page },
cancelToken: source.token
})
const responseData = await feedResponseSchema.parseAsync(response.data)
@ -51,7 +56,10 @@ const Feeds: React.FC<InferGetServerSidePropsType<typeof getServerSideProps>> =
setResults([])
setHasMore(false)
setLoaded(false)
if (query.length < 1) {
router.push({ query })
if ((query.search ?? '').length < 1) {
console.info('Query too short.')
return
}
@ -84,9 +92,15 @@ const Feeds: React.FC<InferGetServerSidePropsType<typeof getServerSideProps>> =
}
const handleQueryChange = (event) => {
const value = event.target.value
console.info('Query changed', { query: value })
setQuery(value)
const inputElement = event.target
const value = inputElement.value
const name = inputElement.name
const newQuery = {
...query
}
newQuery[name] = value
console.info('Query changed', { name, value })
setQuery(newQuery)
setPage(0)
}
@ -114,12 +128,12 @@ const Feeds: React.FC<InferGetServerSidePropsType<typeof getServerSideProps>> =
<form onSubmit={handleSearchSubmit}>
<div className="input-group mb-3">
<input
name={'query'}
id={'query'}
name={'search'}
id={'search'}
type={'search'}
onChange={handleQueryChange}
onBlur={handleQueryChange}
value={query}
value={query.search ?? ''}
placeholder={'Search people on Fediverse'}
className="form-control"
autoFocus={true}
@ -154,7 +168,7 @@ const Feeds: React.FC<InferGetServerSidePropsType<typeof getServerSideProps>> =
)
}
export const getServerSideProps: GetServerSideProps = async (context) => {
export const getServerSideProps: GetServerSideProps = async () => {
console.info('Loading matomo config', matomoConfig)
return {
props: {

Wyświetl plik

@ -6,27 +6,27 @@ import Layout, { siteTitle } from '../components/Layout'
import { matomoConfig } from '../lib/matomoConfig'
import getMatomo from '../lib/getMatomo'
import { GetServerSideProps, InferGetServerSidePropsType } from 'next'
import { nodeResponseSchema } from '../types/NodeResponse'
import { NodeResponseItem, nodeResponseSchema } from '../types/NodeResponse'
import SoftwareBadge from '../components/badges/SoftwareBadge'
import SortToggle from '../components/SortToggle'
import { StatsRequestSortBy } from '../types/StatsRequest'
import { Sort } from '../types/Sort'
import { faSearch, faAngleDoubleDown } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { useRouter } from 'next/router'
import { NodeRequestQuery, nodeRequestQuerySchema, NodeRequestSortBy } from '../types/NodeRequest'
let source = axios.CancelToken.source()
const Nodes: React.FC<InferGetServerSidePropsType<typeof getServerSideProps>> = ({ matomoConfig }) => {
const [query, setQuery] = useState('')
const [submitted, setSubmitted] = useState(null)
const [loading, setLoading] = useState(false)
const [results, setResults] = useState([])
const [page, setPage] = useState(0)
const [hasMore, setHasMore] = useState(false)
const [loaded, setLoaded] = useState(false)
const [sort, setSort] = useState<Sort>({
sortBy: 'refreshedAt', sortWay: 'desc'
})
const router = useRouter()
const routerQuery = nodeRequestQuerySchema.parse(router.query)
console.log('Router query', routerQuery)
const [query, setQuery] = useState<NodeRequestQuery>(routerQuery)
const [submitted, setSubmitted] = useState<Date|null>(null)
const [loading, setLoading] = useState<boolean>(false)
const [results, setResults] = useState<NodeResponseItem[]>([])
const [page, setPage] = useState<number>(0)
const [hasMore, setHasMore] = useState<boolean>(false)
const [loaded, setLoaded] = useState<boolean>(false)
const search = async () => {
setLoading(true)
@ -34,7 +34,7 @@ const Nodes: React.FC<InferGetServerSidePropsType<typeof getServerSideProps>> =
console.info('Retrieving results', { query, page })
source = axios.CancelToken.source()
const response = await axios.get('/api/node', {
params: { search: query, page, sortBy: sort.sortBy, sortWay: sort.sortWay },
params: { ...query, page },
cancelToken: source.token
})
const responseData = await nodeResponseSchema.parseAsync(response.data)
@ -54,6 +54,7 @@ const Nodes: React.FC<InferGetServerSidePropsType<typeof getServerSideProps>> =
const loadNewQueryResults = () => {
console.info('Cancelling searches')
source.cancel('New query on the way')
router.push({ query })
setResults([])
setHasMore(false)
setLoaded(false)
@ -86,9 +87,13 @@ const Nodes: React.FC<InferGetServerSidePropsType<typeof getServerSideProps>> =
}
const handleQueryChange = (event) => {
const value = event.target.value
console.info('Query changed', { query: value })
setQuery(value)
const targetInput = event.target
const value = targetInput.value
const name = targetInput.name
const newQuery:NodeRequestQuery = { ...query }
newQuery[name] = value
console.info('Query changed', { name, value })
setQuery(newQuery)
setPage(0)
}
@ -104,8 +109,8 @@ const Nodes: React.FC<InferGetServerSidePropsType<typeof getServerSideProps>> =
setPage(page + 1)
}
const toggleSort = (sortBy: StatsRequestSortBy) => {
const sortWay = sort.sortBy === sortBy && sort.sortWay === 'asc' ? 'desc' : 'asc'
const toggleSort = (sortBy: NodeRequestSortBy) => {
const sortWay = query.sortBy === sortBy && query.sortWay === 'asc' ? 'desc' : 'asc'
getMatomo(matomoConfig).trackEvent({
category: 'nodes',
action: 'sort',
@ -116,13 +121,13 @@ const Nodes: React.FC<InferGetServerSidePropsType<typeof getServerSideProps>> =
}
]
})
setSort({
sortBy: sortBy,
sortWay: sortWay
})
const newQuery:NodeRequestQuery = { ...query }
newQuery.sortBy = sortBy
newQuery.sortWay = sortWay
setQuery(newQuery)
}
useEffect(loadNewQueryResults, [query, submitted, sort])
useEffect(loadNewQueryResults, [query, submitted])
useEffect(loadNextPageResults, [page])
return (
@ -134,13 +139,13 @@ const Nodes: React.FC<InferGetServerSidePropsType<typeof getServerSideProps>> =
<form onSubmit={handleSearchSubmit}>
<div className={'input-group mb-3'}>
<input
name={'query'}
id={'query'}
name={'search'}
id={'search'}
type={'search'}
className={'form-control'}
onChange={handleQueryChange}
onBlur={handleQueryChange}
value={query}
value={query.search}
placeholder={'Search servers on fediverse'}
autoFocus={true}
aria-label="Search servers on fediverse"
@ -161,45 +166,45 @@ const Nodes: React.FC<InferGetServerSidePropsType<typeof getServerSideProps>> =
<thead>
<tr>
<th rowSpan={2}>
<SortToggle onToggle={toggleSort} field={'domain'} sort={sort}>
<SortToggle onToggle={toggleSort} field={'domain'} sort={query}>
Domain
</SortToggle>
</th>
<th rowSpan={2}>
<SortToggle onToggle={toggleSort} field={'softwareName'} sort={sort}>
<SortToggle onToggle={toggleSort} field={'softwareName'} sort={query}>
Software
</SortToggle>
</th>
<th colSpan={3}>User count</th>
<th rowSpan={2} className={'number-cell'}>
<SortToggle onToggle={toggleSort} field={'statusesCount'} sort={sort}>
<SortToggle onToggle={toggleSort} field={'statusesCount'} sort={query}>
Statuses
</SortToggle>
</th>
<th rowSpan={2}>
<SortToggle onToggle={toggleSort} field={'openRegistrations'} sort={sort}>
<SortToggle onToggle={toggleSort} field={'openRegistrations'} sort={query}>
Registrations
</SortToggle>
</th>
<th rowSpan={2}>
<SortToggle onToggle={toggleSort} field={'refreshedAt'} sort={sort}>
<SortToggle onToggle={toggleSort} field={'refreshedAt'} sort={query}>
Last refreshed
</SortToggle>
</th>
</tr>
<tr>
<th className={'text-end'}>
<SortToggle onToggle={toggleSort} field={'totalUserCount'} sort={sort}>
<SortToggle onToggle={toggleSort} field={'totalUserCount'} sort={query}>
Total
</SortToggle>
</th>
<th className={'text-end'}>
<SortToggle onToggle={toggleSort} field={'monthActiveUserCount'} sort={sort}>
<SortToggle onToggle={toggleSort} field={'monthActiveUserCount'} sort={query}>
Month active
</SortToggle>
</th>
<th className={'text-end'}>
<SortToggle onToggle={toggleSort} field={'halfYearActiveUserCount'} sort={sort}>
<SortToggle onToggle={toggleSort} field={'halfYearActiveUserCount'} sort={query}>
Half year active
</SortToggle>
</th>

Wyświetl plik

@ -8,23 +8,24 @@ import axios from 'axios'
import { StatsResponse, statsResponseSchema } from '../types/StatsResponse'
import SoftwareBadge from '../components/badges/SoftwareBadge'
import ProgressBar from '../components/ProgressBar'
import { StatsRequestSortBy } from '../types/StatsRequest'
import { StatsRequest, statsRequestSchema, StatsRequestSortBy } from '../types/StatsRequest'
import SortToggle from '../components/SortToggle'
import getMatomo from '../lib/getMatomo'
import { Sort } from '../types/Sort'
import { useRouter } from 'next/router'
let source = axios.CancelToken.source()
const Stats: React.FC<InferGetServerSidePropsType<typeof getServerSideProps>> = ({ matomoConfig }) => {
const router = useRouter()
const routerQuery = statsRequestSchema.parse(router.query)
console.log('Router query', routerQuery)
const [query, setQuery] = useState<StatsRequest>(routerQuery)
const [loading, setLoading] = useState<boolean>(true)
const [loaded, setLoaded] = useState<boolean>(false)
const [stats, setStats] = useState<StatsResponse | null>(null)
const [sort, setSort] = useState<Sort>({
sortBy: 'nodeCount', sortWay: 'desc'
})
const toggleSort = (sortBy: StatsRequestSortBy) => {
const sortWay = sort.sortBy === sortBy && sort.sortWay === 'asc' ? 'desc' : 'asc'
const sortWay = query.sortBy === sortBy && query.sortWay === 'asc' ? 'desc' : 'asc'
getMatomo(matomoConfig).trackEvent({
category: 'stats',
action: 'sort',
@ -35,19 +36,20 @@ const Stats: React.FC<InferGetServerSidePropsType<typeof getServerSideProps>> =
}
]
})
setSort({
sortBy: sortBy,
sortWay: sortWay
})
const newQuery:StatsRequest = { ...query }
newQuery.sortBy = sortBy
newQuery.sortWay = sortWay
setQuery(newQuery)
}
const retrieveStats = async () => {
console.info('Retrieving stats', { sort })
console.info('Retrieving stats', { query })
source = axios.CancelToken.source()
setLoading(true)
await router.push({ query })
try {
const response = await axios.get('/api/stats', {
params: sort,
params: query,
cancelToken: source.token
})
const stats = await statsResponseSchema.parseAsync(response.data)
@ -67,7 +69,7 @@ const Stats: React.FC<InferGetServerSidePropsType<typeof getServerSideProps>> =
}
useEffect(() => {
loadStats()
}, [sort])
}, [query])
const sum = {
nodeCount: 0,
accountCount: 0,
@ -101,22 +103,22 @@ const Stats: React.FC<InferGetServerSidePropsType<typeof getServerSideProps>> =
<thead>
<tr>
<th>
<SortToggle onToggle={toggleSort} field={'softwareName'} sort={sort}>
<SortToggle onToggle={toggleSort} field={'softwareName'} sort={query}>
Software name
</SortToggle>
</th>
<th className={'text-end'}>
<SortToggle onToggle={toggleSort} field={'nodeCount'} sort={sort}>
<SortToggle onToggle={toggleSort} field={'nodeCount'} sort={query}>
Instance count
</SortToggle>
</th>
<th className={'text-end'}>
<SortToggle onToggle={toggleSort} field={'accountCount'} sort={sort}>
<SortToggle onToggle={toggleSort} field={'accountCount'} sort={query}>
Account count
</SortToggle>
</th>
<th className={'text-end'}>
<SortToggle onToggle={toggleSort} field={'channelCount'} sort={sort}>
<SortToggle onToggle={toggleSort} field={'channelCount'} sort={query}>
Channel count
</SortToggle>
</th>

Wyświetl plik

@ -1,12 +1,11 @@
import { z } from 'zod'
import { preserveUndefined, stringToInt, transform } from '../lib/transform'
import { preserveUndefined, stringToInt, stringTrimmed, transform } from '../lib/transform'
export const feedRequestSchema = z.object({
search: z.string(),
page: transform(
export const feedRequestQuerySchema = z.object({
search: transform(
z.string().optional(),
preserveUndefined(stringToInt),
z.number().gte(0).optional()
stringTrimmed,
z.string()
)
/*
softwareName: z.string().optional(),
@ -40,4 +39,13 @@ export const feedRequestSchema = z.object({
*/
})
export const feedRequestSchema = feedRequestQuerySchema.extend({
page: transform(
z.string().optional(),
preserveUndefined(stringToInt),
z.number().gte(0).optional()
)
})
export type FeedRequest = z.infer<typeof feedRequestSchema>
export type FeedRequestQuery = z.infer<typeof feedRequestQuerySchema>

Wyświetl plik

@ -1,7 +1,7 @@
import { z } from 'zod'
import { preserveUndefined, stringToInt, transform } from '../lib/transform'
import { preserveUndefined, stringToInt, stringTrimmed, transform, undefinedToDefault } from '../lib/transform'
export const statsRequestSortBySchema = z.enum([
export const nodeRequestSortBySchema = z.enum([
'softwareName',
'softwareVersion',
'totalUserCount',
@ -13,15 +13,30 @@ export const statsRequestSortBySchema = z.enum([
'domain'
])
export const statsRequestSortWaySchema = z.enum([
export const nodeRequestSortWaySchema = z.enum([
'asc',
'desc'
])
export const nodeRequestSchema = z.object({
sortBy: z.optional(statsRequestSortBySchema),
sortWay: z.optional(statsRequestSortWaySchema),
search: z.string().optional(),
export const nodeRequestQuerySchema = z.object({
sortBy: transform(
z.optional(nodeRequestSortBySchema),
undefinedToDefault<NodeRequestSortBy>('refreshedAt'),
nodeRequestSortBySchema
),
sortWay: transform(
z.optional(nodeRequestSortWaySchema),
undefinedToDefault<NodeRequestSortWay>('desc'),
nodeRequestSortWaySchema
),
search: transform(
z.string().optional(),
stringTrimmed,
z.string()
)
})
export const nodeRequestSchema = nodeRequestQuerySchema.extend({
page: transform(
z.string().optional(),
preserveUndefined(stringToInt),
@ -29,4 +44,7 @@ export const nodeRequestSchema = z.object({
)
})
export type NodeRequestQuery = z.infer<typeof nodeRequestQuerySchema>
export type NodeRequest = z.infer<typeof nodeRequestSchema>
export type NodeRequestSortWay = z.infer<typeof nodeRequestSortWaySchema>
export type NodeRequestSortBy = z.infer<typeof nodeRequestSortBySchema>

Wyświetl plik

@ -1,4 +1,4 @@
export type Sort = {
sortBy: string,
sortWay: 'asc' | 'desc'
sortBy?: string,
sortWay?: 'asc' | 'desc'
}

Wyświetl plik

@ -1,9 +1,18 @@
import { z } from 'zod'
import { transform, undefinedToDefault } from '../lib/transform'
export const statsRequestSortBySchema = z.enum(['nodeCount', 'accountCount', 'channelCount', 'softwareName'])
export const statsRequestSortWaySchema = z.enum(['asc', 'desc'])
export const statsRequestSchema = z.object({
sortBy: z.optional(statsRequestSortBySchema),
sortWay: z.optional(statsRequestSortWaySchema)
sortBy: transform(
z.optional(statsRequestSortBySchema),
undefinedToDefault<StatsRequestSortBy>('accountCount'),
z.optional(statsRequestSortBySchema)
),
sortWay: transform(
z.optional(statsRequestSortWaySchema),
undefinedToDefault<StatsRequestSortWay>('desc'),
statsRequestSortWaySchema
)
})
export type StatsRequest = z.infer<typeof statsRequestSchema>