mirror of
https://github.com/umami-software/umami.git
synced 2026-02-04 12:47:13 +01:00
Custom date range select.
This commit is contained in:
parent
e79f4717e7
commit
52e1440089
11 changed files with 247 additions and 314 deletions
|
|
@ -78,7 +78,7 @@
|
|||
"@react-spring/web": "^9.7.5",
|
||||
"@tanstack/react-query": "^5.71.10",
|
||||
"@umami/prisma-client": "^0.16.0",
|
||||
"@umami/react-zen": "^0.83.0",
|
||||
"@umami/react-zen": "^0.87.0",
|
||||
"@umami/redis-client": "^0.27.0",
|
||||
"bcryptjs": "^2.4.3",
|
||||
"chalk": "^4.1.2",
|
||||
|
|
@ -107,7 +107,7 @@
|
|||
"lucide-react": "^0.475.0",
|
||||
"maxmind": "^4.3.24",
|
||||
"md5": "^2.3.0",
|
||||
"next": "15.2.4",
|
||||
"next": "15.3.0",
|
||||
"node-fetch": "^3.3.2",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"prisma": "6.5.0",
|
||||
|
|
|
|||
295
pnpm-lock.yaml
generated
295
pnpm-lock.yaml
generated
|
|
@ -45,8 +45,8 @@ importers:
|
|||
specifier: ^0.16.0
|
||||
version: 0.16.0(@prisma/client@6.5.0(prisma@6.5.0(typescript@5.8.3))(typescript@5.8.3))(@prisma/extension-read-replicas@0.4.1(@prisma/client@6.5.0(prisma@6.5.0(typescript@5.8.3))(typescript@5.8.3)))
|
||||
'@umami/react-zen':
|
||||
specifier: ^0.83.0
|
||||
version: 0.83.0(@babel/core@7.26.9)(@types/react@19.1.0)(immer@9.0.21)(use-sync-external-store@1.5.0(react@19.1.0))
|
||||
specifier: ^0.87.0
|
||||
version: 0.87.0(@babel/core@7.26.9)(@types/react@19.1.0)(immer@9.0.21)(use-sync-external-store@1.5.0(react@19.1.0))
|
||||
'@umami/redis-client':
|
||||
specifier: ^0.27.0
|
||||
version: 0.27.0
|
||||
|
|
@ -132,8 +132,8 @@ importers:
|
|||
specifier: ^2.3.0
|
||||
version: 2.3.0
|
||||
next:
|
||||
specifier: 15.2.4
|
||||
version: 15.2.4(@babel/core@7.26.9)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
specifier: 15.3.0
|
||||
version: 15.3.0(@babel/core@7.26.9)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
node-fetch:
|
||||
specifier: ^3.3.2
|
||||
version: 3.3.2
|
||||
|
|
@ -1314,8 +1314,8 @@ packages:
|
|||
peerDependencies:
|
||||
'@dicebear/core': ^9.0.0
|
||||
|
||||
'@emnapi/runtime@1.4.0':
|
||||
resolution: {integrity: sha512-64WYIf4UYcdLnbKn/umDlNjQDSS8AgZrI/R9+x5ilkUVFxXcA1Ebl+gQLc/6mERA4407Xof0R7wEyEuj091CVw==}
|
||||
'@emnapi/runtime@1.4.3':
|
||||
resolution: {integrity: sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==}
|
||||
|
||||
'@esbuild/aix-ppc64@0.25.2':
|
||||
resolution: {integrity: sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag==}
|
||||
|
|
@ -1580,107 +1580,112 @@ packages:
|
|||
resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==}
|
||||
deprecated: Use @eslint/object-schema instead
|
||||
|
||||
'@img/sharp-darwin-arm64@0.33.5':
|
||||
resolution: {integrity: sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==}
|
||||
'@img/sharp-darwin-arm64@0.34.1':
|
||||
resolution: {integrity: sha512-pn44xgBtgpEbZsu+lWf2KNb6OAf70X68k+yk69Ic2Xz11zHR/w24/U49XT7AeRwJ0Px+mhALhU5LPci1Aymk7A==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@img/sharp-darwin-x64@0.33.5':
|
||||
resolution: {integrity: sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==}
|
||||
'@img/sharp-darwin-x64@0.34.1':
|
||||
resolution: {integrity: sha512-VfuYgG2r8BpYiOUN+BfYeFo69nP/MIwAtSJ7/Zpxc5QF3KS22z8Pvg3FkrSFJBPNQ7mmcUcYQFBmEQp7eu1F8Q==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@img/sharp-libvips-darwin-arm64@1.0.4':
|
||||
resolution: {integrity: sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==}
|
||||
'@img/sharp-libvips-darwin-arm64@1.1.0':
|
||||
resolution: {integrity: sha512-HZ/JUmPwrJSoM4DIQPv/BfNh9yrOA8tlBbqbLz4JZ5uew2+o22Ik+tHQJcih7QJuSa0zo5coHTfD5J8inqj9DA==}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@img/sharp-libvips-darwin-x64@1.0.4':
|
||||
resolution: {integrity: sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==}
|
||||
'@img/sharp-libvips-darwin-x64@1.1.0':
|
||||
resolution: {integrity: sha512-Xzc2ToEmHN+hfvsl9wja0RlnXEgpKNmftriQp6XzY/RaSfwD9th+MSh0WQKzUreLKKINb3afirxW7A0fz2YWuQ==}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@img/sharp-libvips-linux-arm64@1.0.4':
|
||||
resolution: {integrity: sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==}
|
||||
'@img/sharp-libvips-linux-arm64@1.1.0':
|
||||
resolution: {integrity: sha512-IVfGJa7gjChDET1dK9SekxFFdflarnUB8PwW8aGwEoF3oAsSDuNUTYS+SKDOyOJxQyDC1aPFMuRYLoDInyV9Ew==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@img/sharp-libvips-linux-arm@1.0.5':
|
||||
resolution: {integrity: sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==}
|
||||
'@img/sharp-libvips-linux-arm@1.1.0':
|
||||
resolution: {integrity: sha512-s8BAd0lwUIvYCJyRdFqvsj+BJIpDBSxs6ivrOPm/R7piTs5UIwY5OjXrP2bqXC9/moGsyRa37eYWYCOGVXxVrA==}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@img/sharp-libvips-linux-s390x@1.0.4':
|
||||
resolution: {integrity: sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==}
|
||||
'@img/sharp-libvips-linux-ppc64@1.1.0':
|
||||
resolution: {integrity: sha512-tiXxFZFbhnkWE2LA8oQj7KYR+bWBkiV2nilRldT7bqoEZ4HiDOcePr9wVDAZPi/Id5fT1oY9iGnDq20cwUz8lQ==}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
|
||||
'@img/sharp-libvips-linux-s390x@1.1.0':
|
||||
resolution: {integrity: sha512-xukSwvhguw7COyzvmjydRb3x/09+21HykyapcZchiCUkTThEQEOMtBj9UhkaBRLuBrgLFzQ2wbxdeCCJW/jgJA==}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
|
||||
'@img/sharp-libvips-linux-x64@1.0.4':
|
||||
resolution: {integrity: sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==}
|
||||
'@img/sharp-libvips-linux-x64@1.1.0':
|
||||
resolution: {integrity: sha512-yRj2+reB8iMg9W5sULM3S74jVS7zqSzHG3Ol/twnAAkAhnGQnpjj6e4ayUz7V+FpKypwgs82xbRdYtchTTUB+Q==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@img/sharp-libvips-linuxmusl-arm64@1.0.4':
|
||||
resolution: {integrity: sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==}
|
||||
'@img/sharp-libvips-linuxmusl-arm64@1.1.0':
|
||||
resolution: {integrity: sha512-jYZdG+whg0MDK+q2COKbYidaqW/WTz0cc1E+tMAusiDygrM4ypmSCjOJPmFTvHHJ8j/6cAGyeDWZOsK06tP33w==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@img/sharp-libvips-linuxmusl-x64@1.0.4':
|
||||
resolution: {integrity: sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==}
|
||||
'@img/sharp-libvips-linuxmusl-x64@1.1.0':
|
||||
resolution: {integrity: sha512-wK7SBdwrAiycjXdkPnGCPLjYb9lD4l6Ze2gSdAGVZrEL05AOUJESWU2lhlC+Ffn5/G+VKuSm6zzbQSzFX/P65A==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@img/sharp-linux-arm64@0.33.5':
|
||||
resolution: {integrity: sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==}
|
||||
'@img/sharp-linux-arm64@0.34.1':
|
||||
resolution: {integrity: sha512-kX2c+vbvaXC6vly1RDf/IWNXxrlxLNpBVWkdpRq5Ka7OOKj6nr66etKy2IENf6FtOgklkg9ZdGpEu9kwdlcwOQ==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@img/sharp-linux-arm@0.33.5':
|
||||
resolution: {integrity: sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==}
|
||||
'@img/sharp-linux-arm@0.34.1':
|
||||
resolution: {integrity: sha512-anKiszvACti2sGy9CirTlNyk7BjjZPiML1jt2ZkTdcvpLU1YH6CXwRAZCA2UmRXnhiIftXQ7+Oh62Ji25W72jA==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@img/sharp-linux-s390x@0.33.5':
|
||||
resolution: {integrity: sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==}
|
||||
'@img/sharp-linux-s390x@0.34.1':
|
||||
resolution: {integrity: sha512-7s0KX2tI9mZI2buRipKIw2X1ufdTeaRgwmRabt5bi9chYfhur+/C1OXg3TKg/eag1W+6CCWLVmSauV1owmRPxA==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
|
||||
'@img/sharp-linux-x64@0.33.5':
|
||||
resolution: {integrity: sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==}
|
||||
'@img/sharp-linux-x64@0.34.1':
|
||||
resolution: {integrity: sha512-wExv7SH9nmoBW3Wr2gvQopX1k8q2g5V5Iag8Zk6AVENsjwd+3adjwxtp3Dcu2QhOXr8W9NusBU6XcQUohBZ5MA==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@img/sharp-linuxmusl-arm64@0.33.5':
|
||||
resolution: {integrity: sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==}
|
||||
'@img/sharp-linuxmusl-arm64@0.34.1':
|
||||
resolution: {integrity: sha512-DfvyxzHxw4WGdPiTF0SOHnm11Xv4aQexvqhRDAoD00MzHekAj9a/jADXeXYCDFH/DzYruwHbXU7uz+H+nWmSOQ==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@img/sharp-linuxmusl-x64@0.33.5':
|
||||
resolution: {integrity: sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==}
|
||||
'@img/sharp-linuxmusl-x64@0.34.1':
|
||||
resolution: {integrity: sha512-pax/kTR407vNb9qaSIiWVnQplPcGU8LRIJpDT5o8PdAx5aAA7AS3X9PS8Isw1/WfqgQorPotjrZL3Pqh6C5EBg==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@img/sharp-wasm32@0.33.5':
|
||||
resolution: {integrity: sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==}
|
||||
'@img/sharp-wasm32@0.34.1':
|
||||
resolution: {integrity: sha512-YDybQnYrLQfEpzGOQe7OKcyLUCML4YOXl428gOOzBgN6Gw0rv8dpsJ7PqTHxBnXnwXr8S1mYFSLSa727tpz0xg==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [wasm32]
|
||||
|
||||
'@img/sharp-win32-ia32@0.33.5':
|
||||
resolution: {integrity: sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==}
|
||||
'@img/sharp-win32-ia32@0.34.1':
|
||||
resolution: {integrity: sha512-WKf/NAZITnonBf3U1LfdjoMgNO5JYRSlhovhRhMxXVdvWYveM4kM3L8m35onYIdh75cOMCo1BexgVQcCDzyoWw==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
|
||||
'@img/sharp-win32-x64@0.33.5':
|
||||
resolution: {integrity: sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==}
|
||||
'@img/sharp-win32-x64@0.34.1':
|
||||
resolution: {integrity: sha512-hw1iIAHpNE8q3uMIRCgGOeDoz9KtFNarFLQclLxr/LK1VBkj8nby18RjFvr6aP7USRYAjTZW6yisnBWMX571Tw==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
|
@ -1809,56 +1814,56 @@ packages:
|
|||
resolution: {integrity: sha512-0c4Y6Td2YcWjVaIwvJNNWqV8RJJ6uV/8DvKL2Czbp5Pp6KZ9TEIevexfzFSEZG1VgU6bgUUDAIPI2xFKN2Op8A==}
|
||||
engines: {node: '>=18.0.0'}
|
||||
|
||||
'@next/env@15.2.4':
|
||||
resolution: {integrity: sha512-+SFtMgoiYP3WoSswuNmxJOCwi06TdWE733D+WPjpXIe4LXGULwEaofiiAy6kbS0+XjM5xF5n3lKuBwN2SnqD9g==}
|
||||
'@next/env@15.3.0':
|
||||
resolution: {integrity: sha512-6mDmHX24nWlHOlbwUiAOmMyY7KELimmi+ed8qWcJYjqXeC+G6JzPZ3QosOAfjNwgMIzwhXBiRiCgdh8axTTdTA==}
|
||||
|
||||
'@next/eslint-plugin-next@14.2.26':
|
||||
resolution: {integrity: sha512-SPEj1O5DAVTPaWD9XPupelfT2APNIgcDYD2OzEm328BEmHaglhmYNUvxhzfJYDr12AgAfW4V3UHSV93qaeELJA==}
|
||||
|
||||
'@next/swc-darwin-arm64@15.2.4':
|
||||
resolution: {integrity: sha512-1AnMfs655ipJEDC/FHkSr0r3lXBgpqKo4K1kiwfUf3iE68rDFXZ1TtHdMvf7D0hMItgDZ7Vuq3JgNMbt/+3bYw==}
|
||||
'@next/swc-darwin-arm64@15.3.0':
|
||||
resolution: {integrity: sha512-PDQcByT0ZfF2q7QR9d+PNj3wlNN4K6Q8JoHMwFyk252gWo4gKt7BF8Y2+KBgDjTFBETXZ/TkBEUY7NIIY7A/Kw==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@next/swc-darwin-x64@15.2.4':
|
||||
resolution: {integrity: sha512-3qK2zb5EwCwxnO2HeO+TRqCubeI/NgCe+kL5dTJlPldV/uwCnUgC7VbEzgmxbfrkbjehL4H9BPztWOEtsoMwew==}
|
||||
'@next/swc-darwin-x64@15.3.0':
|
||||
resolution: {integrity: sha512-m+eO21yg80En8HJ5c49AOQpFDq+nP51nu88ZOMCorvw3g//8g1JSUsEiPSiFpJo1KCTQ+jm9H0hwXK49H/RmXg==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@next/swc-linux-arm64-gnu@15.2.4':
|
||||
resolution: {integrity: sha512-HFN6GKUcrTWvem8AZN7tT95zPb0GUGv9v0d0iyuTb303vbXkkbHDp/DxufB04jNVD+IN9yHy7y/6Mqq0h0YVaQ==}
|
||||
'@next/swc-linux-arm64-gnu@15.3.0':
|
||||
resolution: {integrity: sha512-H0Kk04ZNzb6Aq/G6e0un4B3HekPnyy6D+eUBYPJv9Abx8KDYgNMWzKt4Qhj57HXV3sTTjsfc1Trc1SxuhQB+Tg==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@next/swc-linux-arm64-musl@15.2.4':
|
||||
resolution: {integrity: sha512-Oioa0SORWLwi35/kVB8aCk5Uq+5/ZIumMK1kJV+jSdazFm2NzPDztsefzdmzzpx5oGCJ6FkUC7vkaUseNTStNA==}
|
||||
'@next/swc-linux-arm64-musl@15.3.0':
|
||||
resolution: {integrity: sha512-k8GVkdMrh/+J9uIv/GpnHakzgDQhrprJ/FbGQvwWmstaeFG06nnAoZCJV+wO/bb603iKV1BXt4gHG+s2buJqZA==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@next/swc-linux-x64-gnu@15.2.4':
|
||||
resolution: {integrity: sha512-yb5WTRaHdkgOqFOZiu6rHV1fAEK0flVpaIN2HB6kxHVSy/dIajWbThS7qON3W9/SNOH2JWkVCyulgGYekMePuw==}
|
||||
'@next/swc-linux-x64-gnu@15.3.0':
|
||||
resolution: {integrity: sha512-ZMQ9yzDEts/vkpFLRAqfYO1wSpIJGlQNK9gZ09PgyjBJUmg8F/bb8fw2EXKgEaHbCc4gmqMpDfh+T07qUphp9A==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@next/swc-linux-x64-musl@15.2.4':
|
||||
resolution: {integrity: sha512-Dcdv/ix6srhkM25fgXiyOieFUkz+fOYkHlydWCtB0xMST6X9XYI3yPDKBZt1xuhOytONsIFJFB08xXYsxUwJLw==}
|
||||
'@next/swc-linux-x64-musl@15.3.0':
|
||||
resolution: {integrity: sha512-RFwq5VKYTw9TMr4T3e5HRP6T4RiAzfDJ6XsxH8j/ZeYq2aLsBqCkFzwMI0FmnSsLaUbOb46Uov0VvN3UciHX5A==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@next/swc-win32-arm64-msvc@15.2.4':
|
||||
resolution: {integrity: sha512-dW0i7eukvDxtIhCYkMrZNQfNicPDExt2jPb9AZPpL7cfyUo7QSNl1DjsHjmmKp6qNAqUESyT8YFl/Aw91cNJJg==}
|
||||
'@next/swc-win32-arm64-msvc@15.3.0':
|
||||
resolution: {integrity: sha512-a7kUbqa/k09xPjfCl0RSVAvEjAkYBYxUzSVAzk2ptXiNEL+4bDBo9wNC43G/osLA/EOGzG4CuNRFnQyIHfkRgQ==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@next/swc-win32-x64-msvc@15.2.4':
|
||||
resolution: {integrity: sha512-SbnWkJmkS7Xl3kre8SdMF6F/XDh1DTFEhp0jRTj/uB8iPKoU2bb2NDfcu+iifv1+mxQEd1g2vvSxcZbXSKyWiQ==}
|
||||
'@next/swc-win32-x64-msvc@15.3.0':
|
||||
resolution: {integrity: sha512-vHUQS4YVGJPmpjn7r5lEZuMhK5UQBNBRSB+iGDvJjaNk649pTIcRluDWNb9siunyLLiu/LDPHfvxBtNamyuLTw==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
|
@ -2952,8 +2957,8 @@ packages:
|
|||
'@prisma/client': ^4.8.0
|
||||
'@prisma/extension-read-replicas': ^0.3.0
|
||||
|
||||
'@umami/react-zen@0.83.0':
|
||||
resolution: {integrity: sha512-XfS46KJoPd7vKWrC2tRc7OLBfgOvDu/nmWOejqJLRSpJtg3tmwPmOYfT1vFo3T9s9Lj4qWYBX3I/fBt7u4Yv3A==}
|
||||
'@umami/react-zen@0.87.0':
|
||||
resolution: {integrity: sha512-zgsvY54ykQ1jW5YTmvZkNa9JNPspjcJneyhQn6YGrWHBlpr9ddPttBWAr2muQM2WrKFEYHx31WKLnBlzGg2lgg==}
|
||||
|
||||
'@umami/redis-client@0.27.0':
|
||||
resolution: {integrity: sha512-SbHTpxhgeZyTBUSp2zdZM+XUtpsaSL4Tad8QXIEhEtjWhvvfoornyT5kLuyYCVtzSAT4daALeGmOO1z6EE1KcA==}
|
||||
|
|
@ -3323,6 +3328,9 @@ packages:
|
|||
caniuse-lite@1.0.30001712:
|
||||
resolution: {integrity: sha512-MBqPpGYYdQ7/hfKiet9SCI+nmN5/hp4ZzveOJubl5DTAMa5oggjAuoi0Z4onBpKPFI2ePGnQuQIzF3VxDjDJig==}
|
||||
|
||||
caniuse-lite@1.0.30001714:
|
||||
resolution: {integrity: sha512-mtgapdwDLSSBnCI3JokHM7oEQBLxiJKVRtg10AxM1AyeiKcM96f0Mkbqeq+1AbiCtvMcHRulAAEMu693JrSWqg==}
|
||||
|
||||
caseless@0.12.0:
|
||||
resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==}
|
||||
|
||||
|
|
@ -5436,8 +5444,8 @@ packages:
|
|||
natural-compare@1.4.0:
|
||||
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
|
||||
|
||||
next@15.2.4:
|
||||
resolution: {integrity: sha512-VwL+LAaPSxEkd3lU2xWbgEOtrM8oedmyhBqaVNmgKB+GvZlCy9rgaEc+y2on0wv+l0oSFqLtYD6dcC1eAedUaQ==}
|
||||
next@15.3.0:
|
||||
resolution: {integrity: sha512-k0MgP6BsK8cZ73wRjMazl2y2UcXj49ZXLDEgx6BikWuby/CN+nh81qFFI16edgd7xYpe/jj2OZEIwCoqnzz0bQ==}
|
||||
engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
|
|
@ -6558,8 +6566,8 @@ packages:
|
|||
resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
sharp@0.33.5:
|
||||
resolution: {integrity: sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==}
|
||||
sharp@0.34.1:
|
||||
resolution: {integrity: sha512-1j0w61+eVxu7DawFJtnfYcvSv6qPFvfTaqzTQ2BLknVhHTwGS8sc63ZBF4rzkWMBVKybo4S5OBtDdZahh2A1xg==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
|
||||
shebang-command@1.2.0:
|
||||
|
|
@ -8390,7 +8398,7 @@ snapshots:
|
|||
dependencies:
|
||||
'@dicebear/core': 9.2.2
|
||||
|
||||
'@emnapi/runtime@1.4.0':
|
||||
'@emnapi/runtime@1.4.3':
|
||||
dependencies:
|
||||
tslib: 2.8.1
|
||||
optional: true
|
||||
|
|
@ -8634,79 +8642,82 @@ snapshots:
|
|||
|
||||
'@humanwhocodes/object-schema@2.0.3': {}
|
||||
|
||||
'@img/sharp-darwin-arm64@0.33.5':
|
||||
'@img/sharp-darwin-arm64@0.34.1':
|
||||
optionalDependencies:
|
||||
'@img/sharp-libvips-darwin-arm64': 1.0.4
|
||||
'@img/sharp-libvips-darwin-arm64': 1.1.0
|
||||
optional: true
|
||||
|
||||
'@img/sharp-darwin-x64@0.33.5':
|
||||
'@img/sharp-darwin-x64@0.34.1':
|
||||
optionalDependencies:
|
||||
'@img/sharp-libvips-darwin-x64': 1.0.4
|
||||
'@img/sharp-libvips-darwin-x64': 1.1.0
|
||||
optional: true
|
||||
|
||||
'@img/sharp-libvips-darwin-arm64@1.0.4':
|
||||
'@img/sharp-libvips-darwin-arm64@1.1.0':
|
||||
optional: true
|
||||
|
||||
'@img/sharp-libvips-darwin-x64@1.0.4':
|
||||
'@img/sharp-libvips-darwin-x64@1.1.0':
|
||||
optional: true
|
||||
|
||||
'@img/sharp-libvips-linux-arm64@1.0.4':
|
||||
'@img/sharp-libvips-linux-arm64@1.1.0':
|
||||
optional: true
|
||||
|
||||
'@img/sharp-libvips-linux-arm@1.0.5':
|
||||
'@img/sharp-libvips-linux-arm@1.1.0':
|
||||
optional: true
|
||||
|
||||
'@img/sharp-libvips-linux-s390x@1.0.4':
|
||||
'@img/sharp-libvips-linux-ppc64@1.1.0':
|
||||
optional: true
|
||||
|
||||
'@img/sharp-libvips-linux-x64@1.0.4':
|
||||
'@img/sharp-libvips-linux-s390x@1.1.0':
|
||||
optional: true
|
||||
|
||||
'@img/sharp-libvips-linuxmusl-arm64@1.0.4':
|
||||
'@img/sharp-libvips-linux-x64@1.1.0':
|
||||
optional: true
|
||||
|
||||
'@img/sharp-libvips-linuxmusl-x64@1.0.4':
|
||||
'@img/sharp-libvips-linuxmusl-arm64@1.1.0':
|
||||
optional: true
|
||||
|
||||
'@img/sharp-linux-arm64@0.33.5':
|
||||
'@img/sharp-libvips-linuxmusl-x64@1.1.0':
|
||||
optional: true
|
||||
|
||||
'@img/sharp-linux-arm64@0.34.1':
|
||||
optionalDependencies:
|
||||
'@img/sharp-libvips-linux-arm64': 1.0.4
|
||||
'@img/sharp-libvips-linux-arm64': 1.1.0
|
||||
optional: true
|
||||
|
||||
'@img/sharp-linux-arm@0.33.5':
|
||||
'@img/sharp-linux-arm@0.34.1':
|
||||
optionalDependencies:
|
||||
'@img/sharp-libvips-linux-arm': 1.0.5
|
||||
'@img/sharp-libvips-linux-arm': 1.1.0
|
||||
optional: true
|
||||
|
||||
'@img/sharp-linux-s390x@0.33.5':
|
||||
'@img/sharp-linux-s390x@0.34.1':
|
||||
optionalDependencies:
|
||||
'@img/sharp-libvips-linux-s390x': 1.0.4
|
||||
'@img/sharp-libvips-linux-s390x': 1.1.0
|
||||
optional: true
|
||||
|
||||
'@img/sharp-linux-x64@0.33.5':
|
||||
'@img/sharp-linux-x64@0.34.1':
|
||||
optionalDependencies:
|
||||
'@img/sharp-libvips-linux-x64': 1.0.4
|
||||
'@img/sharp-libvips-linux-x64': 1.1.0
|
||||
optional: true
|
||||
|
||||
'@img/sharp-linuxmusl-arm64@0.33.5':
|
||||
'@img/sharp-linuxmusl-arm64@0.34.1':
|
||||
optionalDependencies:
|
||||
'@img/sharp-libvips-linuxmusl-arm64': 1.0.4
|
||||
'@img/sharp-libvips-linuxmusl-arm64': 1.1.0
|
||||
optional: true
|
||||
|
||||
'@img/sharp-linuxmusl-x64@0.33.5':
|
||||
'@img/sharp-linuxmusl-x64@0.34.1':
|
||||
optionalDependencies:
|
||||
'@img/sharp-libvips-linuxmusl-x64': 1.0.4
|
||||
'@img/sharp-libvips-linuxmusl-x64': 1.1.0
|
||||
optional: true
|
||||
|
||||
'@img/sharp-wasm32@0.33.5':
|
||||
'@img/sharp-wasm32@0.34.1':
|
||||
dependencies:
|
||||
'@emnapi/runtime': 1.4.0
|
||||
'@emnapi/runtime': 1.4.3
|
||||
optional: true
|
||||
|
||||
'@img/sharp-win32-ia32@0.33.5':
|
||||
'@img/sharp-win32-ia32@0.34.1':
|
||||
optional: true
|
||||
|
||||
'@img/sharp-win32-x64@0.33.5':
|
||||
'@img/sharp-win32-x64@0.34.1':
|
||||
optional: true
|
||||
|
||||
'@internationalized/date@3.7.0':
|
||||
|
|
@ -8942,34 +8953,34 @@ snapshots:
|
|||
|
||||
'@netlify/plugin-nextjs@5.10.3': {}
|
||||
|
||||
'@next/env@15.2.4': {}
|
||||
'@next/env@15.3.0': {}
|
||||
|
||||
'@next/eslint-plugin-next@14.2.26':
|
||||
dependencies:
|
||||
glob: 10.3.10
|
||||
|
||||
'@next/swc-darwin-arm64@15.2.4':
|
||||
'@next/swc-darwin-arm64@15.3.0':
|
||||
optional: true
|
||||
|
||||
'@next/swc-darwin-x64@15.2.4':
|
||||
'@next/swc-darwin-x64@15.3.0':
|
||||
optional: true
|
||||
|
||||
'@next/swc-linux-arm64-gnu@15.2.4':
|
||||
'@next/swc-linux-arm64-gnu@15.3.0':
|
||||
optional: true
|
||||
|
||||
'@next/swc-linux-arm64-musl@15.2.4':
|
||||
'@next/swc-linux-arm64-musl@15.3.0':
|
||||
optional: true
|
||||
|
||||
'@next/swc-linux-x64-gnu@15.2.4':
|
||||
'@next/swc-linux-x64-gnu@15.3.0':
|
||||
optional: true
|
||||
|
||||
'@next/swc-linux-x64-musl@15.2.4':
|
||||
'@next/swc-linux-x64-musl@15.3.0':
|
||||
optional: true
|
||||
|
||||
'@next/swc-win32-arm64-msvc@15.2.4':
|
||||
'@next/swc-win32-arm64-msvc@15.3.0':
|
||||
optional: true
|
||||
|
||||
'@next/swc-win32-x64-msvc@15.2.4':
|
||||
'@next/swc-win32-x64-msvc@15.3.0':
|
||||
optional: true
|
||||
|
||||
'@nodelib/fs.scandir@2.1.5':
|
||||
|
|
@ -10586,16 +10597,17 @@ snapshots:
|
|||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@umami/react-zen@0.83.0(@babel/core@7.26.9)(@types/react@19.1.0)(immer@9.0.21)(use-sync-external-store@1.5.0(react@19.1.0))':
|
||||
'@umami/react-zen@0.87.0(@babel/core@7.26.9)(@types/react@19.1.0)(immer@9.0.21)(use-sync-external-store@1.5.0(react@19.1.0))':
|
||||
dependencies:
|
||||
'@fontsource/jetbrains-mono': 5.2.5
|
||||
'@internationalized/date': 3.8.0
|
||||
'@react-aria/focus': 3.20.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@react-spring/web': 9.7.5(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
classnames: 2.5.1
|
||||
glob: 10.4.5
|
||||
highlight.js: 11.11.1
|
||||
lucide-react: 0.479.0(react@19.1.0)
|
||||
next: 15.2.4(@babel/core@7.26.9)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
next: 15.3.0(@babel/core@7.26.9)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
react: 19.1.0
|
||||
react-aria-components: 1.8.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
react-dom: 19.1.0(react@19.1.0)
|
||||
|
|
@ -11068,6 +11080,8 @@ snapshots:
|
|||
|
||||
caniuse-lite@1.0.30001712: {}
|
||||
|
||||
caniuse-lite@1.0.30001714: {}
|
||||
|
||||
caseless@0.12.0: {}
|
||||
|
||||
chalk@2.4.2:
|
||||
|
|
@ -13594,27 +13608,27 @@ snapshots:
|
|||
|
||||
natural-compare@1.4.0: {}
|
||||
|
||||
next@15.2.4(@babel/core@7.26.9)(react-dom@19.1.0(react@19.1.0))(react@19.1.0):
|
||||
next@15.3.0(@babel/core@7.26.9)(react-dom@19.1.0(react@19.1.0))(react@19.1.0):
|
||||
dependencies:
|
||||
'@next/env': 15.2.4
|
||||
'@next/env': 15.3.0
|
||||
'@swc/counter': 0.1.3
|
||||
'@swc/helpers': 0.5.15
|
||||
busboy: 1.6.0
|
||||
caniuse-lite: 1.0.30001712
|
||||
caniuse-lite: 1.0.30001714
|
||||
postcss: 8.4.31
|
||||
react: 19.1.0
|
||||
react-dom: 19.1.0(react@19.1.0)
|
||||
styled-jsx: 5.1.6(@babel/core@7.26.9)(react@19.1.0)
|
||||
optionalDependencies:
|
||||
'@next/swc-darwin-arm64': 15.2.4
|
||||
'@next/swc-darwin-x64': 15.2.4
|
||||
'@next/swc-linux-arm64-gnu': 15.2.4
|
||||
'@next/swc-linux-arm64-musl': 15.2.4
|
||||
'@next/swc-linux-x64-gnu': 15.2.4
|
||||
'@next/swc-linux-x64-musl': 15.2.4
|
||||
'@next/swc-win32-arm64-msvc': 15.2.4
|
||||
'@next/swc-win32-x64-msvc': 15.2.4
|
||||
sharp: 0.33.5
|
||||
'@next/swc-darwin-arm64': 15.3.0
|
||||
'@next/swc-darwin-x64': 15.3.0
|
||||
'@next/swc-linux-arm64-gnu': 15.3.0
|
||||
'@next/swc-linux-arm64-musl': 15.3.0
|
||||
'@next/swc-linux-x64-gnu': 15.3.0
|
||||
'@next/swc-linux-x64-musl': 15.3.0
|
||||
'@next/swc-win32-arm64-msvc': 15.3.0
|
||||
'@next/swc-win32-x64-msvc': 15.3.0
|
||||
sharp: 0.34.1
|
||||
transitivePeerDependencies:
|
||||
- '@babel/core'
|
||||
- babel-plugin-macros
|
||||
|
|
@ -14851,31 +14865,32 @@ snapshots:
|
|||
es-errors: 1.3.0
|
||||
es-object-atoms: 1.1.1
|
||||
|
||||
sharp@0.33.5:
|
||||
sharp@0.34.1:
|
||||
dependencies:
|
||||
color: 4.2.3
|
||||
detect-libc: 2.0.3
|
||||
semver: 7.7.1
|
||||
optionalDependencies:
|
||||
'@img/sharp-darwin-arm64': 0.33.5
|
||||
'@img/sharp-darwin-x64': 0.33.5
|
||||
'@img/sharp-libvips-darwin-arm64': 1.0.4
|
||||
'@img/sharp-libvips-darwin-x64': 1.0.4
|
||||
'@img/sharp-libvips-linux-arm': 1.0.5
|
||||
'@img/sharp-libvips-linux-arm64': 1.0.4
|
||||
'@img/sharp-libvips-linux-s390x': 1.0.4
|
||||
'@img/sharp-libvips-linux-x64': 1.0.4
|
||||
'@img/sharp-libvips-linuxmusl-arm64': 1.0.4
|
||||
'@img/sharp-libvips-linuxmusl-x64': 1.0.4
|
||||
'@img/sharp-linux-arm': 0.33.5
|
||||
'@img/sharp-linux-arm64': 0.33.5
|
||||
'@img/sharp-linux-s390x': 0.33.5
|
||||
'@img/sharp-linux-x64': 0.33.5
|
||||
'@img/sharp-linuxmusl-arm64': 0.33.5
|
||||
'@img/sharp-linuxmusl-x64': 0.33.5
|
||||
'@img/sharp-wasm32': 0.33.5
|
||||
'@img/sharp-win32-ia32': 0.33.5
|
||||
'@img/sharp-win32-x64': 0.33.5
|
||||
'@img/sharp-darwin-arm64': 0.34.1
|
||||
'@img/sharp-darwin-x64': 0.34.1
|
||||
'@img/sharp-libvips-darwin-arm64': 1.1.0
|
||||
'@img/sharp-libvips-darwin-x64': 1.1.0
|
||||
'@img/sharp-libvips-linux-arm': 1.1.0
|
||||
'@img/sharp-libvips-linux-arm64': 1.1.0
|
||||
'@img/sharp-libvips-linux-ppc64': 1.1.0
|
||||
'@img/sharp-libvips-linux-s390x': 1.1.0
|
||||
'@img/sharp-libvips-linux-x64': 1.1.0
|
||||
'@img/sharp-libvips-linuxmusl-arm64': 1.1.0
|
||||
'@img/sharp-libvips-linuxmusl-x64': 1.1.0
|
||||
'@img/sharp-linux-arm': 0.34.1
|
||||
'@img/sharp-linux-arm64': 0.34.1
|
||||
'@img/sharp-linux-s390x': 0.34.1
|
||||
'@img/sharp-linux-x64': 0.34.1
|
||||
'@img/sharp-linuxmusl-arm64': 0.34.1
|
||||
'@img/sharp-linuxmusl-x64': 0.34.1
|
||||
'@img/sharp-wasm32': 0.34.1
|
||||
'@img/sharp-win32-ia32': 0.34.1
|
||||
'@img/sharp-win32-x64': 0.34.1
|
||||
optional: true
|
||||
|
||||
shebang-command@1.2.0:
|
||||
|
|
|
|||
|
|
@ -6,5 +6,6 @@ export async function getConfig() {
|
|||
trackerScriptName: process.env.TRACKER_SCRIPT_NAME,
|
||||
uiDisabled: !!process.env.DISABLE_UI,
|
||||
updatesDisabled: !!process.env.DISABLE_UPDATES,
|
||||
loginDisabled: !!process.env.DISABLE_LOGIN,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,22 +1,27 @@
|
|||
import { Key } from 'react';
|
||||
import { Text, Row, Button, Flexbox } from '@umami/react-zen';
|
||||
import { useState } from 'react';
|
||||
import { ToggleGroup, ToggleGroupItem } from '@umami/react-zen';
|
||||
|
||||
export interface FilterButtonsProps {
|
||||
items: any[];
|
||||
selectedKey?: Key;
|
||||
onSelect: (key: any) => void;
|
||||
items: { id: string; label: string }[];
|
||||
value: string;
|
||||
onChange?: (value: string) => void;
|
||||
}
|
||||
|
||||
export function FilterButtons({ items, selectedKey, onSelect }: FilterButtonsProps) {
|
||||
export function FilterButtons({ items, value, onChange }: FilterButtonsProps) {
|
||||
const [selected, setSelected] = useState(value);
|
||||
|
||||
const handleChange = (value: string) => {
|
||||
setSelected(value);
|
||||
onChange?.(value);
|
||||
};
|
||||
|
||||
return (
|
||||
<Flexbox justifyContent="center">
|
||||
<Row>
|
||||
{items.map(({ key, label }) => (
|
||||
<Button key={key} onPress={() => onSelect(key)}>
|
||||
<Text weight={key === selectedKey ? 'bold' : undefined}>{label}</Text>
|
||||
</Button>
|
||||
))}
|
||||
</Row>
|
||||
</Flexbox>
|
||||
<ToggleGroup value={[selected]} onChange={e => handleChange(e[0])}>
|
||||
{items.map(({ id, label }) => (
|
||||
<ToggleGroupItem key={id} id={id}>
|
||||
{label}
|
||||
</ToggleGroupItem>
|
||||
))}
|
||||
</ToggleGroup>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,11 +41,13 @@ export function WebsiteDateFilter({
|
|||
const disableForward =
|
||||
value === 'all' || isAfter(getOffsetDateRange(dateRange, 1).startDate, new Date());
|
||||
|
||||
const handleChange = (value: string | DateRange) => {
|
||||
saveDateRange(value);
|
||||
const handleChange = (date: string | DateRange) => {
|
||||
router.push(renderUrl({ date }));
|
||||
saveDateRange(date);
|
||||
};
|
||||
|
||||
const handleIncrement = (increment: number) => {
|
||||
router.push(renderUrl({ increment }));
|
||||
saveDateRange(getOffsetDateRange(dateRange, increment));
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,44 +0,0 @@
|
|||
.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-width: 100vw;
|
||||
}
|
||||
|
||||
.calendars {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.calendars > div + div {
|
||||
margin-inline-start: 20px;
|
||||
padding-inline-start: 20px;
|
||||
border-inline-start: 1px solid var(--base300);
|
||||
}
|
||||
|
||||
.filter {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.buttons {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 10px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 768px) {
|
||||
.calendars {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.calendars > div + div {
|
||||
padding: 0;
|
||||
margin-inline-start: 0;
|
||||
margin-top: 20px;
|
||||
border: 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +1,8 @@
|
|||
import { useState } from 'react';
|
||||
import { Button, Row, Calendar } from '@umami/react-zen';
|
||||
import { Button, Row, Column, Calendar, ToggleGroup, ToggleGroupItem } from '@umami/react-zen';
|
||||
import { isAfter, isBefore, isSameDay, startOfDay, endOfDay } from 'date-fns';
|
||||
import { FILTER_DAY, FILTER_RANGE } from '@/lib/constants';
|
||||
import { useMessages } from '@/components/hooks';
|
||||
import { parseDate } from '@internationalized/date';
|
||||
import styles from './DatePickerForm.module.css';
|
||||
|
||||
export function DatePickerForm({
|
||||
startDate: defaultStartDate,
|
||||
|
|
@ -14,61 +12,61 @@ export function DatePickerForm({
|
|||
onChange,
|
||||
onClose,
|
||||
}) {
|
||||
const [selected, setSelected] = useState(
|
||||
const [selected, setSelected] = useState<any>([
|
||||
isSameDay(defaultStartDate, defaultEndDate) ? FILTER_DAY : FILTER_RANGE,
|
||||
);
|
||||
const [singleDate, setSingleDate] = useState(defaultStartDate || new Date());
|
||||
]);
|
||||
const [date, setDate] = useState(defaultStartDate || new Date());
|
||||
const [startDate, setStartDate] = useState(defaultStartDate || new Date());
|
||||
const [endDate] = useState(defaultEndDate || new Date());
|
||||
const [endDate, setEndDate] = useState(defaultEndDate || new Date());
|
||||
const { formatMessage, labels } = useMessages();
|
||||
|
||||
const disabled =
|
||||
selected === FILTER_DAY
|
||||
? isAfter(minDate, singleDate) && isBefore(maxDate, singleDate)
|
||||
: isAfter(startDate, endDate);
|
||||
const disabled = selected.includes(FILTER_DAY)
|
||||
? isAfter(minDate, date) && isBefore(maxDate, date)
|
||||
: isAfter(startDate, endDate);
|
||||
|
||||
const handleSave = () => {
|
||||
if (selected === FILTER_DAY) {
|
||||
onChange(`range:${startOfDay(singleDate).getTime()}:${endOfDay(singleDate).getTime()}`);
|
||||
if (selected.includes(FILTER_DAY)) {
|
||||
onChange(`range:${startOfDay(date).getTime()}:${endOfDay(date).getTime()}`);
|
||||
} else {
|
||||
onChange(`range:${startOfDay(startDate).getTime()}:${endOfDay(endDate).getTime()}`);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<div className={styles.filter}>
|
||||
<Row>
|
||||
<Button key={FILTER_DAY} onPress={key => setSelected(key as any)}>
|
||||
{formatMessage(labels.singleDay)}
|
||||
</Button>
|
||||
<Button key={FILTER_RANGE} onPress={key => setSelected(key as any)}>
|
||||
{formatMessage(labels.dateRange)}
|
||||
</Button>
|
||||
</Row>
|
||||
</div>
|
||||
<div className={styles.calendars}>
|
||||
{selected === FILTER_DAY && (
|
||||
<Calendar
|
||||
value={parseDate(singleDate.toISOString().split('T')[0])}
|
||||
onChange={d => setSingleDate(d.toDate('America/Los_Angeles'))}
|
||||
/>
|
||||
<Column gap>
|
||||
<Row justifyContent="center">
|
||||
<ToggleGroup disallowEmptySelection value={selected} onChange={setSelected}>
|
||||
<ToggleGroupItem id={FILTER_DAY}>{formatMessage(labels.singleDay)}</ToggleGroupItem>
|
||||
<ToggleGroupItem id={FILTER_RANGE}>{formatMessage(labels.dateRange)}</ToggleGroupItem>
|
||||
</ToggleGroup>
|
||||
</Row>
|
||||
<Column>
|
||||
{selected.includes(FILTER_DAY) && (
|
||||
<Calendar value={date} minValue={minDate} maxValue={maxDate} onChange={setDate} />
|
||||
)}
|
||||
{selected === FILTER_RANGE && (
|
||||
<>
|
||||
{selected.includes(FILTER_RANGE) && (
|
||||
<Row gap>
|
||||
<Calendar
|
||||
value={parseDate(startDate.toISOString().split('T')[0])}
|
||||
onChange={d => setStartDate(d.toDate('America/Los_Angeles'))}
|
||||
value={startDate}
|
||||
minValue={minDate}
|
||||
maxValue={endDate}
|
||||
onChange={setStartDate}
|
||||
/>
|
||||
</>
|
||||
<Calendar
|
||||
value={endDate}
|
||||
minValue={startDate}
|
||||
maxValue={maxDate}
|
||||
onChange={setEndDate}
|
||||
/>
|
||||
</Row>
|
||||
)}
|
||||
</div>
|
||||
<div className={styles.buttons}>
|
||||
</Column>
|
||||
<Row justifyContent="end" gap>
|
||||
<Button onPress={onClose}>{formatMessage(labels.cancel)}</Button>
|
||||
<Button variant="primary" onPress={handleSave} isDisabled={disabled}>
|
||||
{formatMessage(labels.save)}
|
||||
</Button>
|
||||
<Button onPress={onClose}>{formatMessage(labels.cancel)}</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Row>
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,26 +19,26 @@ export function PagesTable({ allowFilter, ...props }: PagesTableProps) {
|
|||
const { formatMessage, labels } = useMessages();
|
||||
const { domain } = useContext(WebsiteContext);
|
||||
|
||||
const handleSelect = (key: any) => {
|
||||
router.push(renderUrl({ view: key }));
|
||||
const handleChange = (id: any) => {
|
||||
router.push(renderUrl({ view: id }));
|
||||
};
|
||||
|
||||
const buttons = [
|
||||
{
|
||||
id: 'url',
|
||||
label: formatMessage(labels.path),
|
||||
key: 'url',
|
||||
},
|
||||
{
|
||||
id: 'entry',
|
||||
label: formatMessage(labels.entry),
|
||||
key: 'entry',
|
||||
},
|
||||
{
|
||||
id: 'exit',
|
||||
label: formatMessage(labels.exit),
|
||||
key: 'exit',
|
||||
},
|
||||
{
|
||||
id: 'title',
|
||||
label: formatMessage(labels.title),
|
||||
key: 'title',
|
||||
},
|
||||
];
|
||||
|
||||
|
|
@ -66,7 +66,7 @@ export function PagesTable({ allowFilter, ...props }: PagesTableProps) {
|
|||
dataFilter={emptyFilter}
|
||||
renderLabel={renderLink}
|
||||
>
|
||||
{allowFilter && <FilterButtons items={buttons} selectedKey={view} onSelect={handleSelect} />}
|
||||
{allowFilter && <FilterButtons items={buttons} value={view} onChange={handleChange} />}
|
||||
</MetricsTable>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,10 +20,10 @@ export function QueryParametersTable({
|
|||
|
||||
const buttons = [
|
||||
{
|
||||
id: FILTER_COMBINED,
|
||||
label: formatMessage(labels.filterCombined),
|
||||
key: FILTER_COMBINED,
|
||||
},
|
||||
{ label: formatMessage(labels.filterRaw), key: FILTER_RAW },
|
||||
{ id: FILTER_RAW, label: formatMessage(labels.filterRaw) },
|
||||
];
|
||||
|
||||
return (
|
||||
|
|
@ -45,7 +45,7 @@ export function QueryParametersTable({
|
|||
}
|
||||
delay={0}
|
||||
>
|
||||
{allowFilter && <FilterButtons items={buttons} selectedKey={filter} onSelect={setFilter} />}
|
||||
{allowFilter && <FilterButtons items={buttons} value={filter} onChange={setFilter} />}
|
||||
</MetricsTable>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import { Row } from '@umami/react-zen';
|
||||
import { FilterLink } from '@/components/common/FilterLink';
|
||||
import { Favicon } from '@/components/common/Favicon';
|
||||
import { FilterButtons } from '@/components/common/FilterButtons';
|
||||
import { useMessages, useNavigation } from '@/components/hooks';
|
||||
import { MetricsTable, MetricsTableProps } from './MetricsTable';
|
||||
import { FilterButtons } from '@/components/common/FilterButtons';
|
||||
import thenby from 'thenby';
|
||||
import { GROUPED_DOMAINS } from '@/lib/constants';
|
||||
import { Flexbox } from '@umami/react-zen';
|
||||
|
||||
export interface ReferrersTableProps extends MetricsTableProps {
|
||||
allowFilter?: boolean;
|
||||
|
|
@ -25,12 +25,12 @@ export function ReferrersTable({ allowFilter, ...props }: ReferrersTableProps) {
|
|||
|
||||
const buttons = [
|
||||
{
|
||||
id: 'referrer',
|
||||
label: formatMessage(labels.domain),
|
||||
key: 'referrer',
|
||||
},
|
||||
{
|
||||
id: 'grouped',
|
||||
label: formatMessage(labels.grouped),
|
||||
key: 'grouped',
|
||||
},
|
||||
];
|
||||
|
||||
|
|
@ -40,10 +40,10 @@ export function ReferrersTable({ allowFilter, ...props }: ReferrersTableProps) {
|
|||
return `(${formatMessage(labels.other)})`;
|
||||
} else {
|
||||
return (
|
||||
<Flexbox alignItems="center" gap="3">
|
||||
<Row alignItems="center" gap="3">
|
||||
<Favicon domain={referrer} />
|
||||
{GROUPED_DOMAINS.find(({ domain }) => domain === referrer)?.name}
|
||||
</Flexbox>
|
||||
</Row>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -86,19 +86,15 @@ export function ReferrersTable({ allowFilter, ...props }: ReferrersTableProps) {
|
|||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<MetricsTable
|
||||
{...props}
|
||||
title={formatMessage(labels.referrers)}
|
||||
type="referrer"
|
||||
metric={formatMessage(labels.visitors)}
|
||||
dataFilter={view === 'grouped' ? groupedFilter : undefined}
|
||||
renderLabel={renderLink}
|
||||
>
|
||||
{allowFilter && (
|
||||
<FilterButtons items={buttons} selectedKey={view} onSelect={handleSelect} />
|
||||
)}
|
||||
</MetricsTable>
|
||||
</>
|
||||
<MetricsTable
|
||||
{...props}
|
||||
title={formatMessage(labels.referrers)}
|
||||
type="referrer"
|
||||
metric={formatMessage(labels.visitors)}
|
||||
dataFilter={view === 'grouped' ? groupedFilter : undefined}
|
||||
renderLabel={renderLink}
|
||||
>
|
||||
{allowFilter && <FilterButtons items={buttons} value={view} onChange={handleSelect} />}
|
||||
</MetricsTable>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { renderNumberLabels, renderDateLabels } from '../charts';
|
||||
import { formatDate } from '../date';
|
||||
import { renderNumberLabels } from '../charts';
|
||||
|
||||
// test for renderNumberLabels
|
||||
|
||||
|
|
@ -40,42 +39,3 @@ describe('renderNumberLabels', () => {
|
|||
expect(renderNumberLabels(input)).toBe(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('renderDateLabels', () => {
|
||||
const mockValues = [{ value: '2024-03-23T10:00:00Z' }, { value: '2024-03-24T15:30:00Z' }];
|
||||
|
||||
beforeEach(() => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||
jest.spyOn(require('@/lib/date'), 'formatDate');
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks(); // Reset spy to prevent interference
|
||||
});
|
||||
|
||||
test.each([
|
||||
['minute', 'h:mm', 'en-US'],
|
||||
['hour', 'p', 'en-US'],
|
||||
['day', 'MMM d', 'en-US'],
|
||||
['month', 'MMM', 'en-US'],
|
||||
['year', 'yyyy', 'en-US'],
|
||||
])('formats date correctly for unit: %s', (unit, expectedFormat, locale) => {
|
||||
const formatLabel = renderDateLabels(unit, locale);
|
||||
const formatted = formatLabel('label', 0, mockValues);
|
||||
|
||||
expect(formatDate).toHaveBeenCalledWith(new Date(mockValues[0].value), expectedFormat, locale);
|
||||
expect(formatted).toBe(formatDate(new Date(mockValues[0].value), expectedFormat, locale));
|
||||
});
|
||||
|
||||
test('returns label for unknown unit', () => {
|
||||
const formatLabel = renderDateLabels('unknown', 'en-US');
|
||||
expect(formatLabel('original-label', 0, mockValues)).toBe('original-label');
|
||||
});
|
||||
|
||||
test('throws error for invalid date input', () => {
|
||||
const invalidValues = [{ value: 'invalid-date' }];
|
||||
const formatLabel = renderDateLabels('day', 'en-US');
|
||||
|
||||
expect(() => formatLabel('label', 0, invalidValues)).toThrow();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue