New goals page. Upgraded prisma.
|
|
@ -235,42 +235,3 @@ model Report {
|
|||
@@index([name])
|
||||
@@map("report")
|
||||
}
|
||||
|
||||
model Board {
|
||||
id String @id() @unique() @map("board_id") @db.Uuid
|
||||
userId String @map("user_id") @db.Uuid
|
||||
teamId String? @map("team_id") @db.Uuid
|
||||
name String @map("name") @db.VarChar(200)
|
||||
description String @map("description") @db.VarChar(500)
|
||||
parameters Json @map("parameters") @db.JsonB
|
||||
createdAt DateTime? @default(now()) @map("created_at") @db.Timestamptz(6)
|
||||
updatedAt DateTime? @updatedAt @map("updated_at") @db.Timestamptz(6)
|
||||
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
team Team? @relation(fields: [teamId], references: [id])
|
||||
|
||||
@@index([userId])
|
||||
@@index([teamId])
|
||||
@@index([type])
|
||||
@@index([name])
|
||||
@@map("board")
|
||||
}
|
||||
|
||||
model Block {
|
||||
id String @id() @unique() @map("block_id") @db.Uuid
|
||||
userId String @map("user_id") @db.Uuid
|
||||
name String @map("name") @db.VarChar(200)
|
||||
type String @map("type") @db.VarChar(20)
|
||||
parameters Json @map("parameters") @db.JsonB
|
||||
createdAt DateTime? @default(now()) @map("created_at") @db.Timestamptz(6)
|
||||
updatedAt DateTime? @updatedAt @map("updated_at") @db.Timestamptz(6)
|
||||
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
website Website @relation(fields: [websiteId], references: [id])
|
||||
|
||||
@@index([userId])
|
||||
@@index([websiteId])
|
||||
@@index([type])
|
||||
@@index([name])
|
||||
@@map("block")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,12 +74,12 @@
|
|||
"@dicebear/core": "^9.2.1",
|
||||
"@fontsource/inter": "^4.5.15",
|
||||
"@hello-pangea/dnd": "^17.0.0",
|
||||
"@prisma/client": "6.7.0",
|
||||
"@prisma/client": "^6.8.2",
|
||||
"@prisma/extension-read-replicas": "^0.4.1",
|
||||
"@react-spring/web": "^9.7.3",
|
||||
"@svgr/cli": "^8.1.0",
|
||||
"@tanstack/react-query": "^5.28.6",
|
||||
"@umami/react-zen": "^0.119.0",
|
||||
"@umami/react-zen": "^0.127.0",
|
||||
"@umami/redis-client": "^0.27.0",
|
||||
"bcryptjs": "^2.4.3",
|
||||
"chalk": "^4.1.1",
|
||||
|
|
@ -105,13 +105,13 @@
|
|||
"isbot": "^5.1.16",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"kafkajs": "^2.1.0",
|
||||
"lucide-react": "^0.509.0",
|
||||
"lucide-react": "^0.511.0",
|
||||
"maxmind": "^4.3.24",
|
||||
"md5": "^2.3.0",
|
||||
"next": "15.3.1",
|
||||
"node-fetch": "^3.2.8",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"prisma": "6.7.0",
|
||||
"prisma": "6.8.2",
|
||||
"pure-rand": "^6.1.0",
|
||||
"react": "^19.0.0",
|
||||
"react-basics": "^0.126.0",
|
||||
|
|
|
|||
517
pnpm-lock.yaml
generated
|
|
@ -27,11 +27,11 @@ importers:
|
|||
specifier: ^17.0.0
|
||||
version: 17.0.0(@types/react@19.1.5)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@prisma/client':
|
||||
specifier: 6.7.0
|
||||
version: 6.7.0(prisma@6.7.0(typescript@5.8.3))(typescript@5.8.3)
|
||||
specifier: ^6.8.2
|
||||
version: 6.8.2(prisma@6.8.2(typescript@5.8.3))(typescript@5.8.3)
|
||||
'@prisma/extension-read-replicas':
|
||||
specifier: ^0.4.1
|
||||
version: 0.4.1(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.8.3))(typescript@5.8.3))
|
||||
version: 0.4.1(@prisma/client@6.8.2(prisma@6.8.2(typescript@5.8.3))(typescript@5.8.3))
|
||||
'@react-spring/web':
|
||||
specifier: ^9.7.3
|
||||
version: 9.7.5(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
|
|
@ -42,8 +42,8 @@ importers:
|
|||
specifier: ^5.28.6
|
||||
version: 5.77.2(react@19.1.0)
|
||||
'@umami/react-zen':
|
||||
specifier: ^0.119.0
|
||||
version: 0.119.0(@babel/core@7.27.1)(@types/react@19.1.5)(immer@9.0.21)(use-sync-external-store@1.5.0(react@19.1.0))
|
||||
specifier: ^0.127.0
|
||||
version: 0.127.0(@babel/core@7.27.1)(@types/react@19.1.5)(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
|
||||
|
|
@ -120,8 +120,8 @@ importers:
|
|||
specifier: ^2.1.0
|
||||
version: 2.2.4
|
||||
lucide-react:
|
||||
specifier: ^0.509.0
|
||||
version: 0.509.0(react@19.1.0)
|
||||
specifier: ^0.511.0
|
||||
version: 0.511.0(react@19.1.0)
|
||||
maxmind:
|
||||
specifier: ^4.3.24
|
||||
version: 4.3.25
|
||||
|
|
@ -138,8 +138,8 @@ importers:
|
|||
specifier: ^4.1.5
|
||||
version: 4.1.5
|
||||
prisma:
|
||||
specifier: 6.7.0
|
||||
version: 6.7.0(typescript@5.8.3)
|
||||
specifier: 6.8.2
|
||||
version: 6.8.2(typescript@5.8.3)
|
||||
pure-rand:
|
||||
specifier: ^6.1.0
|
||||
version: 6.1.0
|
||||
|
|
@ -346,45 +346,6 @@ importers:
|
|||
specifier: ^5.5.3
|
||||
version: 5.8.3
|
||||
|
||||
dist:
|
||||
dependencies:
|
||||
'@tanstack/react-query':
|
||||
specifier: ^4.33.0
|
||||
version: 4.36.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
classnames:
|
||||
specifier: ^2.3.1
|
||||
version: 2.5.1
|
||||
colord:
|
||||
specifier: ^2.9.2
|
||||
version: 2.9.3
|
||||
date-fns-tz:
|
||||
specifier: ^1.1.4
|
||||
version: 1.3.8(date-fns@2.30.0)
|
||||
immer:
|
||||
specifier: ^9.0.12
|
||||
version: 9.0.21
|
||||
moment-timezone:
|
||||
specifier: ^0.5.35
|
||||
version: 0.5.48
|
||||
next:
|
||||
specifier: ^13.4.0
|
||||
version: 13.5.11(@babel/core@7.27.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
next-basics:
|
||||
specifier: ^0.36.0
|
||||
version: 0.36.0(next@13.5.11(@babel/core@7.27.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
react:
|
||||
specifier: ^18.2.0
|
||||
version: 18.3.1
|
||||
react-dom:
|
||||
specifier: ^18.2.0
|
||||
version: 18.3.1(react@18.3.1)
|
||||
react-intl:
|
||||
specifier: ^5.24.7
|
||||
version: 5.25.1(react@18.3.1)(typescript@4.9.5)
|
||||
zustand:
|
||||
specifier: ^4.3.8
|
||||
version: 4.5.7(@types/react@19.1.5)(immer@9.0.21)(react@18.3.1)
|
||||
|
||||
packages:
|
||||
|
||||
'@ampproject/remapping@2.3.0':
|
||||
|
|
@ -1086,9 +1047,6 @@ packages:
|
|||
'@formatjs/ecma402-abstract@2.3.4':
|
||||
resolution: {integrity: sha512-qrycXDeaORzIqNhBOx0btnhpD1c+/qFIHAN9znofuMJX6QBwtbrmlpWfD4oiUUD2vJUOIYFA/gYtg2KAMGG7sA==}
|
||||
|
||||
'@formatjs/fast-memoize@1.2.1':
|
||||
resolution: {integrity: sha512-Rg0e76nomkz3vF9IPlKeV+Qynok0r7YZjL6syLz4/urSg0IbjPZCB/iYUMNsYA643gh4mgrX3T7KEIFIxJBQeg==}
|
||||
|
||||
'@formatjs/fast-memoize@2.2.3':
|
||||
resolution: {integrity: sha512-3jeJ+HyOfu8osl3GNSL4vVHUuWFXR03Iz9jjgI7RwjG6ysu/Ymdr0JRCPHfF5yGbTE6JCrd63EpvX1/WybYRbA==}
|
||||
|
||||
|
|
@ -1113,15 +1071,9 @@ packages:
|
|||
'@formatjs/icu-skeleton-parser@1.8.8':
|
||||
resolution: {integrity: sha512-vHwK3piXwamFcx5YQdCdJxUQ1WdTl6ANclt5xba5zLGDv5Bsur7qz8AD7BevaKxITwpgDeU0u8My3AIibW9ywA==}
|
||||
|
||||
'@formatjs/intl-displaynames@5.4.3':
|
||||
resolution: {integrity: sha512-4r12A3mS5dp5hnSaQCWBuBNfi9Amgx2dzhU4lTFfhSxgb5DOAiAbMpg6+7gpWZgl4ahsj3l2r/iHIjdmdXOE2Q==}
|
||||
|
||||
'@formatjs/intl-displaynames@6.8.5':
|
||||
resolution: {integrity: sha512-85b+GdAKCsleS6cqVxf/Aw/uBd+20EM0wDpgaxzHo3RIR3bxF4xCJqH/Grbzx8CXurTgDDZHPdPdwJC+May41w==}
|
||||
|
||||
'@formatjs/intl-listformat@6.5.3':
|
||||
resolution: {integrity: sha512-ozpz515F/+3CU+HnLi5DYPsLa6JoCfBggBSSg/8nOB5LYSFW9+ZgNQJxJ8tdhKYeODT+4qVHX27EeJLoxLGLNg==}
|
||||
|
||||
'@formatjs/intl-listformat@7.7.5':
|
||||
resolution: {integrity: sha512-Wzes10SMNeYgnxYiKsda4rnHP3Q3II4XT2tZyOgnH5fWuHDtIkceuWlRQNsvrI3uiwP4hLqp2XdQTCsfkhXulg==}
|
||||
|
||||
|
|
@ -1145,14 +1097,6 @@ packages:
|
|||
typescript:
|
||||
optional: true
|
||||
|
||||
'@formatjs/intl@2.2.1':
|
||||
resolution: {integrity: sha512-vgvyUOOrzqVaOFYzTf2d3+ToSkH2JpR7x/4U1RyoHQLmvEaTQvXJ7A2qm1Iy3brGNXC/+/7bUlc3lpH+h/LOJA==}
|
||||
peerDependencies:
|
||||
typescript: ^4.5
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
|
||||
'@formatjs/ts-transformer@2.13.0':
|
||||
resolution: {integrity: sha512-mu7sHXZk1NWZrQ3eUqugpSYo8x5/tXkrI4uIbFqCEC0eNgQaIcoKgVeDFgDAcgG+cEme2atAUYSFF+DFWC4org==}
|
||||
peerDependencies:
|
||||
|
|
@ -1428,9 +1372,6 @@ packages:
|
|||
resolution: {integrity: sha512-9Hgd/J5nP2U/Vv0teytq9uUAGppiKV9t5tzpsuMLqeqUGD9STxXwKmyZd2v8Z4THSW9rw4+8w7dH7LVlFoym2A==}
|
||||
engines: {node: '>=18.0.0'}
|
||||
|
||||
'@next/env@13.5.11':
|
||||
resolution: {integrity: sha512-fbb2C7HChgM7CemdCY+y3N1n8pcTKdqtQLbC7/EQtPdLvlMUT9JX/dBYl8MMZAtYG4uVMyPFHXckb68q/NRwqg==}
|
||||
|
||||
'@next/env@15.3.1':
|
||||
resolution: {integrity: sha512-cwK27QdzrMblHSn9DZRV+DQscHXRuJv6MydlJRpFSqJWZrTYMLzKDeyueJNN9MGd8NNiUKzDQADAf+dMLXX7YQ==}
|
||||
|
||||
|
|
@ -1440,12 +1381,6 @@ packages:
|
|||
'@next/eslint-plugin-next@14.2.29':
|
||||
resolution: {integrity: sha512-qpxSYiPNJTr9RzqjGi5yom8AIC8Kgdtw4oNIXAB/gDYMDctmfMEv452FRUhT06cWPgcmSsbZiEPYhbFiQtCWTg==}
|
||||
|
||||
'@next/swc-darwin-arm64@13.5.9':
|
||||
resolution: {integrity: sha512-pVyd8/1y1l5atQRvOaLOvfbmRwefxLhqQOzYo/M7FQ5eaRwA1+wuCn7t39VwEgDd7Aw1+AIWwd+MURXUeXhwDw==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@next/swc-darwin-arm64@15.3.1':
|
||||
resolution: {integrity: sha512-hjDw4f4/nla+6wysBL07z52Gs55Gttp5Bsk5/8AncQLJoisvTBP0pRIBK/B16/KqQyH+uN4Ww8KkcAqJODYH3w==}
|
||||
engines: {node: '>= 10'}
|
||||
|
|
@ -1458,12 +1393,6 @@ packages:
|
|||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@next/swc-darwin-x64@13.5.9':
|
||||
resolution: {integrity: sha512-DwdeJqP7v8wmoyTWPbPVodTwCybBZa02xjSJ6YQFIFZFZ7dFgrieKW4Eo0GoIcOJq5+JxkQyejmI+8zwDp3pwA==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@next/swc-darwin-x64@15.3.1':
|
||||
resolution: {integrity: sha512-q+aw+cJ2ooVYdCEqZVk+T4Ni10jF6Fo5DfpEV51OupMaV5XL6pf3GCzrk6kSSZBsMKZtVC1Zm/xaNBFpA6bJ2g==}
|
||||
engines: {node: '>= 10'}
|
||||
|
|
@ -1476,12 +1405,6 @@ packages:
|
|||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@next/swc-linux-arm64-gnu@13.5.9':
|
||||
resolution: {integrity: sha512-wdQsKsIsGSNdFojvjW3Ozrh8Q00+GqL3wTaMjDkQxVtRbAqfFBtrLPO0IuWChVUP2UeuQcHpVeUvu0YgOP00+g==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@next/swc-linux-arm64-gnu@15.3.1':
|
||||
resolution: {integrity: sha512-wBQ+jGUI3N0QZyWmmvRHjXjTWFy8o+zPFLSOyAyGFI94oJi+kK/LIZFJXeykvgXUk1NLDAEFDZw/NVINhdk9FQ==}
|
||||
engines: {node: '>= 10'}
|
||||
|
|
@ -1494,12 +1417,6 @@ packages:
|
|||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@next/swc-linux-arm64-musl@13.5.9':
|
||||
resolution: {integrity: sha512-6VpS+bodQqzOeCwGxoimlRoosiWlSc0C224I7SQWJZoyJuT1ChNCo+45QQH+/GtbR/s7nhaUqmiHdzZC9TXnXA==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@next/swc-linux-arm64-musl@15.3.1':
|
||||
resolution: {integrity: sha512-IIxXEXRti/AulO9lWRHiCpUUR8AR/ZYLPALgiIg/9ENzMzLn3l0NSxVdva7R/VDcuSEBo0eGVCe3evSIHNz0Hg==}
|
||||
engines: {node: '>= 10'}
|
||||
|
|
@ -1512,12 +1429,6 @@ packages:
|
|||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@next/swc-linux-x64-gnu@13.5.9':
|
||||
resolution: {integrity: sha512-XxG3yj61WDd28NA8gFASIR+2viQaYZEFQagEodhI/R49gXWnYhiflTeeEmCn7Vgnxa/OfK81h1gvhUZ66lozpw==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@next/swc-linux-x64-gnu@15.3.1':
|
||||
resolution: {integrity: sha512-bfI4AMhySJbyXQIKH5rmLJ5/BP7bPwuxauTvVEiJ/ADoddaA9fgyNNCcsbu9SlqfHDoZmfI6g2EjzLwbsVTr5A==}
|
||||
engines: {node: '>= 10'}
|
||||
|
|
@ -1530,12 +1441,6 @@ packages:
|
|||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@next/swc-linux-x64-musl@13.5.9':
|
||||
resolution: {integrity: sha512-/dnscWqfO3+U8asd+Fc6dwL2l9AZDl7eKtPNKW8mKLh4Y4wOpjJiamhe8Dx+D+Oq0GYVjuW0WwjIxYWVozt2bA==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@next/swc-linux-x64-musl@15.3.1':
|
||||
resolution: {integrity: sha512-FeAbR7FYMWR+Z+M5iSGytVryKHiAsc0x3Nc3J+FD5NVbD5Mqz7fTSy8CYliXinn7T26nDMbpExRUI/4ekTvoiA==}
|
||||
engines: {node: '>= 10'}
|
||||
|
|
@ -1548,12 +1453,6 @@ packages:
|
|||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@next/swc-win32-arm64-msvc@13.5.9':
|
||||
resolution: {integrity: sha512-T/iPnyurOK5a4HRUcxAlss8uzoEf5h9tkd+W2dSWAfzxv8WLKlUgbfk+DH43JY3Gc2xK5URLuXrxDZ2mGfk/jw==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@next/swc-win32-arm64-msvc@15.3.1':
|
||||
resolution: {integrity: sha512-yP7FueWjphQEPpJQ2oKmshk/ppOt+0/bB8JC8svPUZNy0Pi3KbPx2Llkzv1p8CoQa+D2wknINlJpHf3vtChVBw==}
|
||||
engines: {node: '>= 10'}
|
||||
|
|
@ -1566,18 +1465,6 @@ packages:
|
|||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@next/swc-win32-ia32-msvc@13.5.9':
|
||||
resolution: {integrity: sha512-BLiPKJomaPrTAb7ykjA0LPcuuNMLDVK177Z1xe0nAem33+9FIayU4k/OWrtSn9SAJW/U60+1hoey5z+KCHdRLQ==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
|
||||
'@next/swc-win32-x64-msvc@13.5.9':
|
||||
resolution: {integrity: sha512-/72/dZfjXXNY/u+n8gqZDjI6rxKMpYsgBBYNZKWOQw0BpBF7WCnPflRy3ZtvQ2+IYI3ZH2bPyj7K+6a6wNk90Q==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@next/swc-win32-x64-msvc@15.3.1':
|
||||
resolution: {integrity: sha512-3PMvF2zRJAifcRNni9uMk/gulWfWS+qVI/pagd+4yLF5bcXPZPPH2xlYRYOsUjmCJOXSTAC2PjRzbhsRzR2fDQ==}
|
||||
engines: {node: '>= 10'}
|
||||
|
|
@ -1610,8 +1497,8 @@ packages:
|
|||
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
|
||||
engines: {node: '>=14'}
|
||||
|
||||
'@prisma/client@6.7.0':
|
||||
resolution: {integrity: sha512-+k61zZn1XHjbZul8q6TdQLpuI/cvyfil87zqK2zpreNIXyXtpUv3+H/oM69hcsFcZXaokHJIzPAt5Z8C8eK2QA==}
|
||||
'@prisma/client@6.8.2':
|
||||
resolution: {integrity: sha512-5II+vbyzv4si6Yunwgkj0qT/iY0zyspttoDrL3R4BYgLdp42/d2C8xdi9vqkrYtKt9H32oFIukvyw3Koz5JoDg==}
|
||||
engines: {node: '>=18.18'}
|
||||
peerDependencies:
|
||||
prisma: '*'
|
||||
|
|
@ -1622,28 +1509,28 @@ packages:
|
|||
typescript:
|
||||
optional: true
|
||||
|
||||
'@prisma/config@6.7.0':
|
||||
resolution: {integrity: sha512-di8QDdvSz7DLUi3OOcCHSwxRNeW7jtGRUD2+Z3SdNE3A+pPiNT8WgUJoUyOwJmUr5t+JA2W15P78C/N+8RXrOA==}
|
||||
'@prisma/config@6.8.2':
|
||||
resolution: {integrity: sha512-ZJY1fF4qRBPdLQ/60wxNtX+eu89c3AkYEcP7L3jkp0IPXCNphCYxikTg55kPJLDOG6P0X+QG5tCv6CmsBRZWFQ==}
|
||||
|
||||
'@prisma/debug@6.7.0':
|
||||
resolution: {integrity: sha512-RabHn9emKoYFsv99RLxvfG2GHzWk2ZI1BuVzqYtmMSIcuGboHY5uFt3Q3boOREM9de6z5s3bQoyKeWnq8Fz22w==}
|
||||
'@prisma/debug@6.8.2':
|
||||
resolution: {integrity: sha512-4muBSSUwJJ9BYth5N8tqts8JtiLT8QI/RSAzEogwEfpbYGFo9mYsInsVo8dqXdPO2+Rm5OG5q0qWDDE3nyUbVg==}
|
||||
|
||||
'@prisma/engines-version@6.7.0-36.3cff47a7f5d65c3ea74883f1d736e41d68ce91ed':
|
||||
resolution: {integrity: sha512-EvpOFEWf1KkJpDsBCrih0kg3HdHuaCnXmMn7XFPObpFTzagK1N0Q0FMnYPsEhvARfANP5Ok11QyoTIRA2hgJTA==}
|
||||
'@prisma/engines-version@6.8.0-43.2060c79ba17c6bb9f5823312b6f6b7f4a845738e':
|
||||
resolution: {integrity: sha512-Rkik9lMyHpFNGaLpPF3H5q5TQTkm/aE7DsGM5m92FZTvWQsvmi6Va8On3pWvqLHOt5aPUvFb/FeZTmphI4CPiQ==}
|
||||
|
||||
'@prisma/engines@6.7.0':
|
||||
resolution: {integrity: sha512-3wDMesnOxPrOsq++e5oKV9LmIiEazFTRFZrlULDQ8fxdub5w4NgRBoxtWbvXmj2nJVCnzuz6eFix3OhIqsZ1jw==}
|
||||
'@prisma/engines@6.8.2':
|
||||
resolution: {integrity: sha512-XqAJ//LXjqYRQ1RRabs79KOY4+v6gZOGzbcwDQl0D6n9WBKjV7qdrbd042CwSK0v0lM9MSHsbcFnU2Yn7z8Zlw==}
|
||||
|
||||
'@prisma/extension-read-replicas@0.4.1':
|
||||
resolution: {integrity: sha512-mCMDloqUKUwx2o5uedTs1FHX3Nxdt1GdRMoeyp1JggjiwOALmIYWhxfIN08M2BZ0w8SKwvJqicJZMjkQYkkijw==}
|
||||
peerDependencies:
|
||||
'@prisma/client': ^6.5.0
|
||||
|
||||
'@prisma/fetch-engine@6.7.0':
|
||||
resolution: {integrity: sha512-zLlAGnrkmioPKJR4Yf7NfW3hftcvqeNNEHleMZK9yX7RZSkhmxacAYyfGsCcqRt47jiZ7RKdgE0Wh2fWnm7WsQ==}
|
||||
'@prisma/fetch-engine@6.8.2':
|
||||
resolution: {integrity: sha512-lCvikWOgaLOfqXGacEKSNeenvj0n3qR5QvZUOmPE2e1Eh8cMYSobxonCg9rqM6FSdTfbpqp9xwhSAOYfNqSW0g==}
|
||||
|
||||
'@prisma/get-platform@6.7.0':
|
||||
resolution: {integrity: sha512-i9IH5lO4fQwnMLvQLYNdgVh9TK3PuWBfQd7QLk/YurnAIg+VeADcZDbmhAi4XBBDD+hDif9hrKyASu0hbjwabw==}
|
||||
'@prisma/get-platform@6.8.2':
|
||||
resolution: {integrity: sha512-vXSxyUgX3vm1Q70QwzwkjeYfRryIvKno1SXbIqwSptKwqKzskINnDUcx85oX+ys6ooN2ATGSD0xN2UTfg6Zcow==}
|
||||
|
||||
'@react-aria/autocomplete@3.0.0-beta.3':
|
||||
resolution: {integrity: sha512-8haBygHNMqVt4Ge90VOk+iVlLW+zhiOGHYz2IKCE6+Sy1dTE6mzhHjxrtwWYnSez/OQLbxjHlwLch4CDd5JkLA==}
|
||||
|
|
@ -2459,27 +2346,9 @@ packages:
|
|||
'@swc/helpers@0.5.17':
|
||||
resolution: {integrity: sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==}
|
||||
|
||||
'@swc/helpers@0.5.2':
|
||||
resolution: {integrity: sha512-E4KcWTpoLHqwPHLxidpOqQbcrZVgi0rsmmZXUle1jXmJfuIf/UWpczUJ7MZZ5tlxytgJXyp0w4PGkkeLiuIdZw==}
|
||||
|
||||
'@tanstack/query-core@4.36.1':
|
||||
resolution: {integrity: sha512-DJSilV5+ytBP1FbFcEJovv4rnnm/CokuVvrBEtW/Va9DvuJ3HksbXUJEpI0aV1KtuL4ZoO9AVE6PyNLzF7tLeA==}
|
||||
|
||||
'@tanstack/query-core@5.77.2':
|
||||
resolution: {integrity: sha512-1lqJwPsR6GX6nZFw06erRt518O19tWU6Q+x0fJUygl4lxHCYF2nhzBPwLKk2NPjYOrpR0K567hxPc5K++xDe9Q==}
|
||||
|
||||
'@tanstack/react-query@4.36.1':
|
||||
resolution: {integrity: sha512-y7ySVHFyyQblPl3J3eQBWpXZkliroki3ARnBKsdJchlgt7yJLRDUcf4B8soufgiYt3pEQIkBWBx1N9/ZPIeUWw==}
|
||||
peerDependencies:
|
||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0
|
||||
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0
|
||||
react-native: '*'
|
||||
peerDependenciesMeta:
|
||||
react-dom:
|
||||
optional: true
|
||||
react-native:
|
||||
optional: true
|
||||
|
||||
'@tanstack/react-query@5.77.2':
|
||||
resolution: {integrity: sha512-BRHxWdy1mHmgAcYA/qy2IPLylT81oebLgkm9K85viN2Qol/Vq48t1dzDFeDIVQjTWDV96AmqsLNPlH5HjyKCxA==}
|
||||
peerDependencies:
|
||||
|
|
@ -2696,8 +2565,8 @@ packages:
|
|||
resolution: {integrity: sha512-ar0tjQfObzhSaW3C3QNmTc5ofj0hDoNQ5XWrCy6zDyabdr0TWhCkClp+rywGNj/odAFBVzzJrK4tEq5M4Hmu4w==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
|
||||
'@umami/react-zen@0.119.0':
|
||||
resolution: {integrity: sha512-OXfRRyaQy3RLAqTQYRs94LKl1i1k8n4QuMxYHZigMgdt25jP/E+kHWwWDONrOK5FK1dZ0PcjiBGilQ9nH+Xp5Q==}
|
||||
'@umami/react-zen@0.127.0':
|
||||
resolution: {integrity: sha512-i7HPpkoyE2DJdTVFVbK+aDF5pVYNanNhZBanqptzw69wkt0I9CuG2aVoeLbGH19/j0Pbk7Mfvmw3uDrkGS2Zyw==}
|
||||
|
||||
'@umami/redis-client@0.27.0':
|
||||
resolution: {integrity: sha512-SbHTpxhgeZyTBUSp2zdZM+XUtpsaSL4Tad8QXIEhEtjWhvvfoornyT5kLuyYCVtzSAT4daALeGmOO1z6EE1KcA==}
|
||||
|
|
@ -3134,6 +3003,9 @@ packages:
|
|||
caniuse-lite@1.0.30001718:
|
||||
resolution: {integrity: sha512-AflseV1ahcSunK53NfEs9gFWgOEmzr0f+kaMFA4xiLZlr9Hzt7HxcSpIFcnNCUkz6R6dWKa54rUz3HUmI3nVcw==}
|
||||
|
||||
caniuse-lite@1.0.30001720:
|
||||
resolution: {integrity: sha512-Ec/2yV2nNPwb4DnTANEV99ZWwm3ZWfdlfkQbWSDDt+PsXEVYwlhPH8tdMaPunYTKKmz7AnHi2oNEi1GcmKCD8g==}
|
||||
|
||||
caseless@0.12.0:
|
||||
resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==}
|
||||
|
||||
|
|
@ -3746,11 +3618,6 @@ packages:
|
|||
resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
esbuild-register@3.6.0:
|
||||
resolution: {integrity: sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg==}
|
||||
peerDependencies:
|
||||
esbuild: '>=0.12 <1'
|
||||
|
||||
esbuild@0.25.5:
|
||||
resolution: {integrity: sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==}
|
||||
engines: {node: '>=18'}
|
||||
|
|
@ -4200,9 +4067,6 @@ packages:
|
|||
resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
|
||||
engines: {node: '>=10.13.0'}
|
||||
|
||||
glob-to-regexp@0.4.1:
|
||||
resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==}
|
||||
|
||||
glob@10.3.10:
|
||||
resolution: {integrity: sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==}
|
||||
engines: {node: '>=16 || 14 >=14.17'}
|
||||
|
|
@ -4439,9 +4303,6 @@ packages:
|
|||
intl-messageformat@10.7.7:
|
||||
resolution: {integrity: sha512-F134jIoeYMro/3I0h08D0Yt4N9o9pjddU/4IIxMMURqbAtI2wu70X8hvG1V48W49zXHXv3RKSF/po+0fDfsGjA==}
|
||||
|
||||
intl-messageformat@9.13.0:
|
||||
resolution: {integrity: sha512-7sGC7QnSQGa5LZP7bXLDhVDtQOeKGeBFGHF2Y8LVBwYZoQZCgWeKoPGTa5GMG8g/TzDgeXuYJQis7Ggiw2xTOw==}
|
||||
|
||||
ipaddr.js@2.2.0:
|
||||
resolution: {integrity: sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==}
|
||||
engines: {node: '>= 10'}
|
||||
|
|
@ -4810,6 +4671,10 @@ packages:
|
|||
node-notifier:
|
||||
optional: true
|
||||
|
||||
jiti@2.4.2:
|
||||
resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==}
|
||||
hasBin: true
|
||||
|
||||
joycon@3.1.1:
|
||||
resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==}
|
||||
engines: {node: '>=10'}
|
||||
|
|
@ -5069,11 +4934,6 @@ packages:
|
|||
resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
lucide-react@0.509.0:
|
||||
resolution: {integrity: sha512-xCJHn6Uh5qF6PGml25vveCTrHJZcqS1G1MVzWZK54ZQsOiCVJk4fwY3oyo5EXS2S+aqvTpWYIfJN+PesJ0quxg==}
|
||||
peerDependencies:
|
||||
react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0
|
||||
|
||||
lucide-react@0.511.0:
|
||||
resolution: {integrity: sha512-VK5a2ydJ7xm8GvBeKLS9mu1pVK6ucef9780JVUjw6bAjJL/QXnd4Y0p7SPeOUMC27YhzNCZvm5d/QX0Tp3rc0w==}
|
||||
peerDependencies:
|
||||
|
|
@ -5229,12 +5089,6 @@ packages:
|
|||
resolution: {integrity: sha512-V6DDh3v8tfZFWbeH6fsL5uBIlWL7SvRgGDaAZWFC5kjQ2xP5dl/mLpWwJQ1Ho6ZbEKVp/351QF1JXYTAmeZ/zA==}
|
||||
engines: {node: '>=10', npm: '>=6'}
|
||||
|
||||
moment-timezone@0.5.48:
|
||||
resolution: {integrity: sha512-f22b8LV1gbTO2ms2j2z13MuPogNoh5UzxL3nzNAYKGraILnbGc9NEE6dyiiiLv46DGRb8A4kg8UKWLjPthxBHw==}
|
||||
|
||||
moment@2.30.1:
|
||||
resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==}
|
||||
|
||||
ms@2.1.2:
|
||||
resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
|
||||
|
||||
|
|
@ -5254,28 +5108,6 @@ packages:
|
|||
natural-compare@1.4.0:
|
||||
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
|
||||
|
||||
next-basics@0.36.0:
|
||||
resolution: {integrity: sha512-Nwou8pCjFuoD/ZxUw9iKC7hhZeWbo/ng0ze74yck3W89MNc/CepwCDziflAHY5XcmIVNmpXOCu9OfmzTdVRPWQ==}
|
||||
peerDependencies:
|
||||
next: ^13.4.0
|
||||
react: ^18.2.0
|
||||
react-dom: ^18.2.0
|
||||
|
||||
next@13.5.11:
|
||||
resolution: {integrity: sha512-WUPJ6WbAX9tdC86kGTu92qkrRdgRqVrY++nwM+shmWQwmyxt4zhZfR59moXSI4N8GDYCBY3lIAqhzjDd4rTC8Q==}
|
||||
engines: {node: '>=16.14.0'}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
'@opentelemetry/api': ^1.1.0
|
||||
react: ^18.2.0
|
||||
react-dom: ^18.2.0
|
||||
sass: ^1.3.0
|
||||
peerDependenciesMeta:
|
||||
'@opentelemetry/api':
|
||||
optional: true
|
||||
sass:
|
||||
optional: true
|
||||
|
||||
next@15.3.1:
|
||||
resolution: {integrity: sha512-8+dDV0xNLOgHlyBxP1GwHGVaNXsmp+2NhZEYrXr24GWLHtt27YrBPbPuHvzlhi7kZNYjeJNR93IF5zfFu5UL0g==}
|
||||
engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0}
|
||||
|
|
@ -6000,8 +5832,8 @@ packages:
|
|||
resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==}
|
||||
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
|
||||
|
||||
prisma@6.7.0:
|
||||
resolution: {integrity: sha512-vArg+4UqnQ13CVhc2WUosemwh6hr6cr6FY2uzDvCIFwH8pu8BXVv38PktoMLVjtX7sbYThxbnZF5YiR8sN2clw==}
|
||||
prisma@6.8.2:
|
||||
resolution: {integrity: sha512-JNricTXQxzDtRS7lCGGOB4g5DJ91eg3nozdubXze3LpcMl1oWwcFddrj++Up3jnRE6X/3gB/xz3V+ecBk/eEGA==}
|
||||
engines: {node: '>=18.18'}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
|
|
@ -6078,11 +5910,6 @@ packages:
|
|||
react: ^18.2.0
|
||||
react-dom: ^18.2.0
|
||||
|
||||
react-dom@18.3.1:
|
||||
resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==}
|
||||
peerDependencies:
|
||||
react: ^18.3.1
|
||||
|
||||
react-dom@19.1.0:
|
||||
resolution: {integrity: sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==}
|
||||
peerDependencies:
|
||||
|
|
@ -6104,15 +5931,6 @@ packages:
|
|||
peerDependencies:
|
||||
react: '*'
|
||||
|
||||
react-intl@5.25.1:
|
||||
resolution: {integrity: sha512-pkjdQDvpJROoXLMltkP/5mZb0/XqrqLoPGKUCfbdkP8m6U9xbK40K51Wu+a4aQqTEvEK5lHBk0fWzUV72SJ3Hg==}
|
||||
peerDependencies:
|
||||
react: ^16.3.0 || 17 || 18
|
||||
typescript: ^4.5
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
|
||||
react-intl@6.8.9:
|
||||
resolution: {integrity: sha512-TUfj5E7lyUDvz/GtovC9OMh441kBr08rtIbgh3p0R8iF3hVY+V2W9Am7rb8BpJ/29BH1utJOqOOhmvEVh3GfZg==}
|
||||
peerDependencies:
|
||||
|
|
@ -6168,10 +5986,6 @@ packages:
|
|||
react: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
|
||||
react-dom: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
|
||||
|
||||
react@18.3.1:
|
||||
resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
react@19.1.0:
|
||||
resolution: {integrity: sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
|
@ -6358,9 +6172,6 @@ packages:
|
|||
safer-buffer@2.1.2:
|
||||
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
|
||||
|
||||
scheduler@0.23.2:
|
||||
resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==}
|
||||
|
||||
scheduler@0.26.0:
|
||||
resolution: {integrity: sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==}
|
||||
|
||||
|
|
@ -6616,19 +6427,6 @@ packages:
|
|||
style-search@0.1.0:
|
||||
resolution: {integrity: sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==}
|
||||
|
||||
styled-jsx@5.1.1:
|
||||
resolution: {integrity: sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
peerDependencies:
|
||||
'@babel/core': '*'
|
||||
babel-plugin-macros: '*'
|
||||
react: '>= 16.8.0 || 17.x.x || ^18.0.0-0'
|
||||
peerDependenciesMeta:
|
||||
'@babel/core':
|
||||
optional: true
|
||||
babel-plugin-macros:
|
||||
optional: true
|
||||
|
||||
styled-jsx@5.1.6:
|
||||
resolution: {integrity: sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
|
|
@ -7002,10 +6800,6 @@ packages:
|
|||
walker@1.0.8:
|
||||
resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==}
|
||||
|
||||
watchpack@2.4.0:
|
||||
resolution: {integrity: sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==}
|
||||
engines: {node: '>=10.13.0'}
|
||||
|
||||
web-streams-polyfill@3.3.3:
|
||||
resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==}
|
||||
engines: {node: '>= 8'}
|
||||
|
|
@ -7805,10 +7599,6 @@ snapshots:
|
|||
decimal.js: 10.5.0
|
||||
tslib: 2.8.1
|
||||
|
||||
'@formatjs/fast-memoize@1.2.1':
|
||||
dependencies:
|
||||
tslib: 2.8.1
|
||||
|
||||
'@formatjs/fast-memoize@2.2.3':
|
||||
dependencies:
|
||||
tslib: 2.8.1
|
||||
|
|
@ -7850,24 +7640,12 @@ snapshots:
|
|||
'@formatjs/ecma402-abstract': 2.2.4
|
||||
tslib: 2.8.1
|
||||
|
||||
'@formatjs/intl-displaynames@5.4.3':
|
||||
dependencies:
|
||||
'@formatjs/ecma402-abstract': 1.11.4
|
||||
'@formatjs/intl-localematcher': 0.2.25
|
||||
tslib: 2.8.1
|
||||
|
||||
'@formatjs/intl-displaynames@6.8.5':
|
||||
dependencies:
|
||||
'@formatjs/ecma402-abstract': 2.2.4
|
||||
'@formatjs/intl-localematcher': 0.5.8
|
||||
tslib: 2.8.1
|
||||
|
||||
'@formatjs/intl-listformat@6.5.3':
|
||||
dependencies:
|
||||
'@formatjs/ecma402-abstract': 1.11.4
|
||||
'@formatjs/intl-localematcher': 0.2.25
|
||||
tslib: 2.8.1
|
||||
|
||||
'@formatjs/intl-listformat@7.7.5':
|
||||
dependencies:
|
||||
'@formatjs/ecma402-abstract': 2.2.4
|
||||
|
|
@ -7903,18 +7681,6 @@ snapshots:
|
|||
optionalDependencies:
|
||||
typescript: 5.8.3
|
||||
|
||||
'@formatjs/intl@2.2.1(typescript@4.9.5)':
|
||||
dependencies:
|
||||
'@formatjs/ecma402-abstract': 1.11.4
|
||||
'@formatjs/fast-memoize': 1.2.1
|
||||
'@formatjs/icu-messageformat-parser': 2.1.0
|
||||
'@formatjs/intl-displaynames': 5.4.3
|
||||
'@formatjs/intl-listformat': 6.5.3
|
||||
intl-messageformat: 9.13.0
|
||||
tslib: 2.8.1
|
||||
optionalDependencies:
|
||||
typescript: 4.9.5
|
||||
|
||||
'@formatjs/ts-transformer@2.13.0(ts-jest@29.3.4(@babel/core@7.27.1)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.27.1))(esbuild@0.25.5)(jest@29.7.0(@types/node@22.15.21)(ts-node@10.9.2(@types/node@22.15.21)(typescript@5.8.3)))(typescript@5.8.3))':
|
||||
dependencies:
|
||||
intl-messageformat-parser: 6.1.2
|
||||
|
|
@ -8276,8 +8042,6 @@ snapshots:
|
|||
|
||||
'@netlify/plugin-nextjs@5.11.2': {}
|
||||
|
||||
'@next/env@13.5.11': {}
|
||||
|
||||
'@next/env@15.3.1': {}
|
||||
|
||||
'@next/env@15.3.2': {}
|
||||
|
|
@ -8286,75 +8050,48 @@ snapshots:
|
|||
dependencies:
|
||||
glob: 10.3.10
|
||||
|
||||
'@next/swc-darwin-arm64@13.5.9':
|
||||
optional: true
|
||||
|
||||
'@next/swc-darwin-arm64@15.3.1':
|
||||
optional: true
|
||||
|
||||
'@next/swc-darwin-arm64@15.3.2':
|
||||
optional: true
|
||||
|
||||
'@next/swc-darwin-x64@13.5.9':
|
||||
optional: true
|
||||
|
||||
'@next/swc-darwin-x64@15.3.1':
|
||||
optional: true
|
||||
|
||||
'@next/swc-darwin-x64@15.3.2':
|
||||
optional: true
|
||||
|
||||
'@next/swc-linux-arm64-gnu@13.5.9':
|
||||
optional: true
|
||||
|
||||
'@next/swc-linux-arm64-gnu@15.3.1':
|
||||
optional: true
|
||||
|
||||
'@next/swc-linux-arm64-gnu@15.3.2':
|
||||
optional: true
|
||||
|
||||
'@next/swc-linux-arm64-musl@13.5.9':
|
||||
optional: true
|
||||
|
||||
'@next/swc-linux-arm64-musl@15.3.1':
|
||||
optional: true
|
||||
|
||||
'@next/swc-linux-arm64-musl@15.3.2':
|
||||
optional: true
|
||||
|
||||
'@next/swc-linux-x64-gnu@13.5.9':
|
||||
optional: true
|
||||
|
||||
'@next/swc-linux-x64-gnu@15.3.1':
|
||||
optional: true
|
||||
|
||||
'@next/swc-linux-x64-gnu@15.3.2':
|
||||
optional: true
|
||||
|
||||
'@next/swc-linux-x64-musl@13.5.9':
|
||||
optional: true
|
||||
|
||||
'@next/swc-linux-x64-musl@15.3.1':
|
||||
optional: true
|
||||
|
||||
'@next/swc-linux-x64-musl@15.3.2':
|
||||
optional: true
|
||||
|
||||
'@next/swc-win32-arm64-msvc@13.5.9':
|
||||
optional: true
|
||||
|
||||
'@next/swc-win32-arm64-msvc@15.3.1':
|
||||
optional: true
|
||||
|
||||
'@next/swc-win32-arm64-msvc@15.3.2':
|
||||
optional: true
|
||||
|
||||
'@next/swc-win32-ia32-msvc@13.5.9':
|
||||
optional: true
|
||||
|
||||
'@next/swc-win32-x64-msvc@13.5.9':
|
||||
optional: true
|
||||
|
||||
'@next/swc-win32-x64-msvc@15.3.1':
|
||||
optional: true
|
||||
|
||||
|
|
@ -8378,42 +8115,39 @@ snapshots:
|
|||
'@pkgjs/parseargs@0.11.0':
|
||||
optional: true
|
||||
|
||||
'@prisma/client@6.7.0(prisma@6.7.0(typescript@5.8.3))(typescript@5.8.3)':
|
||||
'@prisma/client@6.8.2(prisma@6.8.2(typescript@5.8.3))(typescript@5.8.3)':
|
||||
optionalDependencies:
|
||||
prisma: 6.7.0(typescript@5.8.3)
|
||||
prisma: 6.8.2(typescript@5.8.3)
|
||||
typescript: 5.8.3
|
||||
|
||||
'@prisma/config@6.7.0':
|
||||
'@prisma/config@6.8.2':
|
||||
dependencies:
|
||||
esbuild: 0.25.5
|
||||
esbuild-register: 3.6.0(esbuild@0.25.5)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
jiti: 2.4.2
|
||||
|
||||
'@prisma/debug@6.7.0': {}
|
||||
'@prisma/debug@6.8.2': {}
|
||||
|
||||
'@prisma/engines-version@6.7.0-36.3cff47a7f5d65c3ea74883f1d736e41d68ce91ed': {}
|
||||
'@prisma/engines-version@6.8.0-43.2060c79ba17c6bb9f5823312b6f6b7f4a845738e': {}
|
||||
|
||||
'@prisma/engines@6.7.0':
|
||||
'@prisma/engines@6.8.2':
|
||||
dependencies:
|
||||
'@prisma/debug': 6.7.0
|
||||
'@prisma/engines-version': 6.7.0-36.3cff47a7f5d65c3ea74883f1d736e41d68ce91ed
|
||||
'@prisma/fetch-engine': 6.7.0
|
||||
'@prisma/get-platform': 6.7.0
|
||||
'@prisma/debug': 6.8.2
|
||||
'@prisma/engines-version': 6.8.0-43.2060c79ba17c6bb9f5823312b6f6b7f4a845738e
|
||||
'@prisma/fetch-engine': 6.8.2
|
||||
'@prisma/get-platform': 6.8.2
|
||||
|
||||
'@prisma/extension-read-replicas@0.4.1(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.8.3))(typescript@5.8.3))':
|
||||
'@prisma/extension-read-replicas@0.4.1(@prisma/client@6.8.2(prisma@6.8.2(typescript@5.8.3))(typescript@5.8.3))':
|
||||
dependencies:
|
||||
'@prisma/client': 6.7.0(prisma@6.7.0(typescript@5.8.3))(typescript@5.8.3)
|
||||
'@prisma/client': 6.8.2(prisma@6.8.2(typescript@5.8.3))(typescript@5.8.3)
|
||||
|
||||
'@prisma/fetch-engine@6.7.0':
|
||||
'@prisma/fetch-engine@6.8.2':
|
||||
dependencies:
|
||||
'@prisma/debug': 6.7.0
|
||||
'@prisma/engines-version': 6.7.0-36.3cff47a7f5d65c3ea74883f1d736e41d68ce91ed
|
||||
'@prisma/get-platform': 6.7.0
|
||||
'@prisma/debug': 6.8.2
|
||||
'@prisma/engines-version': 6.8.0-43.2060c79ba17c6bb9f5823312b6f6b7f4a845738e
|
||||
'@prisma/get-platform': 6.8.2
|
||||
|
||||
'@prisma/get-platform@6.7.0':
|
||||
'@prisma/get-platform@6.8.2':
|
||||
dependencies:
|
||||
'@prisma/debug': 6.7.0
|
||||
'@prisma/debug': 6.8.2
|
||||
|
||||
'@react-aria/autocomplete@3.0.0-beta.3(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
||||
dependencies:
|
||||
|
|
@ -9694,22 +9428,8 @@ snapshots:
|
|||
dependencies:
|
||||
tslib: 2.8.1
|
||||
|
||||
'@swc/helpers@0.5.2':
|
||||
dependencies:
|
||||
tslib: 2.8.1
|
||||
|
||||
'@tanstack/query-core@4.36.1': {}
|
||||
|
||||
'@tanstack/query-core@5.77.2': {}
|
||||
|
||||
'@tanstack/react-query@4.36.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
'@tanstack/query-core': 4.36.1
|
||||
react: 18.3.1
|
||||
use-sync-external-store: 1.5.0(react@18.3.1)
|
||||
optionalDependencies:
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
|
||||
'@tanstack/react-query@5.77.2(react@19.1.0)':
|
||||
dependencies:
|
||||
'@tanstack/query-core': 5.77.2
|
||||
|
|
@ -9976,7 +9696,7 @@ snapshots:
|
|||
'@typescript-eslint/types': 8.32.1
|
||||
eslint-visitor-keys: 4.2.0
|
||||
|
||||
'@umami/react-zen@0.119.0(@babel/core@7.27.1)(@types/react@19.1.5)(immer@9.0.21)(use-sync-external-store@1.5.0(react@19.1.0))':
|
||||
'@umami/react-zen@0.127.0(@babel/core@7.27.1)(@types/react@19.1.5)(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.1
|
||||
|
|
@ -10487,6 +10207,8 @@ snapshots:
|
|||
|
||||
caniuse-lite@1.0.30001718: {}
|
||||
|
||||
caniuse-lite@1.0.30001720: {}
|
||||
|
||||
caseless@0.12.0: {}
|
||||
|
||||
chalk@2.4.2:
|
||||
|
|
@ -11203,13 +10925,6 @@ snapshots:
|
|||
is-date-object: 1.1.0
|
||||
is-symbol: 1.1.1
|
||||
|
||||
esbuild-register@3.6.0(esbuild@0.25.5):
|
||||
dependencies:
|
||||
debug: 4.4.1(supports-color@8.1.1)
|
||||
esbuild: 0.25.5
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
esbuild@0.25.5:
|
||||
optionalDependencies:
|
||||
'@esbuild/aix-ppc64': 0.25.5
|
||||
|
|
@ -11798,8 +11513,6 @@ snapshots:
|
|||
dependencies:
|
||||
is-glob: 4.0.3
|
||||
|
||||
glob-to-regexp@0.4.1: {}
|
||||
|
||||
glob@10.3.10:
|
||||
dependencies:
|
||||
foreground-child: 3.3.1
|
||||
|
|
@ -12029,13 +11742,6 @@ snapshots:
|
|||
'@formatjs/icu-messageformat-parser': 2.9.4
|
||||
tslib: 2.8.1
|
||||
|
||||
intl-messageformat@9.13.0:
|
||||
dependencies:
|
||||
'@formatjs/ecma402-abstract': 1.11.4
|
||||
'@formatjs/fast-memoize': 1.2.1
|
||||
'@formatjs/icu-messageformat-parser': 2.1.0
|
||||
tslib: 2.8.1
|
||||
|
||||
ipaddr.js@2.2.0: {}
|
||||
|
||||
is-array-buffer@3.0.5:
|
||||
|
|
@ -12585,6 +12291,8 @@ snapshots:
|
|||
- supports-color
|
||||
- ts-node
|
||||
|
||||
jiti@2.4.2: {}
|
||||
|
||||
joycon@3.1.1: {}
|
||||
|
||||
js-tokens@4.0.0: {}
|
||||
|
|
@ -12855,10 +12563,6 @@ snapshots:
|
|||
dependencies:
|
||||
yallist: 4.0.0
|
||||
|
||||
lucide-react@0.509.0(react@19.1.0):
|
||||
dependencies:
|
||||
react: 19.1.0
|
||||
|
||||
lucide-react@0.511.0(react@19.1.0):
|
||||
dependencies:
|
||||
react: 19.1.0
|
||||
|
|
@ -13010,12 +12714,6 @@ snapshots:
|
|||
|
||||
mmdb-lib@2.2.0: {}
|
||||
|
||||
moment-timezone@0.5.48:
|
||||
dependencies:
|
||||
moment: 2.30.1
|
||||
|
||||
moment@2.30.1: {}
|
||||
|
||||
ms@2.1.2: {}
|
||||
|
||||
ms@2.1.3: {}
|
||||
|
|
@ -13026,40 +12724,6 @@ snapshots:
|
|||
|
||||
natural-compare@1.4.0: {}
|
||||
|
||||
next-basics@0.36.0(next@13.5.11(@babel/core@7.27.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
|
||||
dependencies:
|
||||
bcryptjs: 2.4.3
|
||||
jsonwebtoken: 9.0.2
|
||||
next: 13.5.11(@babel/core@7.27.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
pure-rand: 6.1.0
|
||||
react: 18.3.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
|
||||
next@13.5.11(@babel/core@7.27.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
|
||||
dependencies:
|
||||
'@next/env': 13.5.11
|
||||
'@swc/helpers': 0.5.2
|
||||
busboy: 1.6.0
|
||||
caniuse-lite: 1.0.30001718
|
||||
postcss: 8.4.31
|
||||
react: 18.3.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
styled-jsx: 5.1.1(@babel/core@7.27.1)(react@18.3.1)
|
||||
watchpack: 2.4.0
|
||||
optionalDependencies:
|
||||
'@next/swc-darwin-arm64': 13.5.9
|
||||
'@next/swc-darwin-x64': 13.5.9
|
||||
'@next/swc-linux-arm64-gnu': 13.5.9
|
||||
'@next/swc-linux-arm64-musl': 13.5.9
|
||||
'@next/swc-linux-x64-gnu': 13.5.9
|
||||
'@next/swc-linux-x64-musl': 13.5.9
|
||||
'@next/swc-win32-arm64-msvc': 13.5.9
|
||||
'@next/swc-win32-ia32-msvc': 13.5.9
|
||||
'@next/swc-win32-x64-msvc': 13.5.9
|
||||
transitivePeerDependencies:
|
||||
- '@babel/core'
|
||||
- babel-plugin-macros
|
||||
|
||||
next@15.3.1(@babel/core@7.27.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0):
|
||||
dependencies:
|
||||
'@next/env': 15.3.1
|
||||
|
|
@ -13091,7 +12755,7 @@ snapshots:
|
|||
'@swc/counter': 0.1.3
|
||||
'@swc/helpers': 0.5.15
|
||||
busboy: 1.6.0
|
||||
caniuse-lite: 1.0.30001718
|
||||
caniuse-lite: 1.0.30001720
|
||||
postcss: 8.4.31
|
||||
react: 19.1.0
|
||||
react-dom: 19.1.0(react@19.1.0)
|
||||
|
|
@ -13783,15 +13447,12 @@ snapshots:
|
|||
ansi-styles: 5.2.0
|
||||
react-is: 18.3.1
|
||||
|
||||
prisma@6.7.0(typescript@5.8.3):
|
||||
prisma@6.8.2(typescript@5.8.3):
|
||||
dependencies:
|
||||
'@prisma/config': 6.7.0
|
||||
'@prisma/engines': 6.7.0
|
||||
'@prisma/config': 6.8.2
|
||||
'@prisma/engines': 6.8.2
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.3
|
||||
typescript: 5.8.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
process@0.11.10: {}
|
||||
|
||||
|
|
@ -13925,12 +13586,6 @@ snapshots:
|
|||
react-hook-form: 7.56.4(react@19.1.0)
|
||||
react-window: 1.8.11(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
|
||||
react-dom@18.3.1(react@18.3.1):
|
||||
dependencies:
|
||||
loose-envify: 1.4.0
|
||||
react: 18.3.1
|
||||
scheduler: 0.23.2
|
||||
|
||||
react-dom@19.1.0(react@19.1.0):
|
||||
dependencies:
|
||||
react: 19.1.0
|
||||
|
|
@ -13949,22 +13604,6 @@ snapshots:
|
|||
dependencies:
|
||||
react: 19.1.0
|
||||
|
||||
react-intl@5.25.1(react@18.3.1)(typescript@4.9.5):
|
||||
dependencies:
|
||||
'@formatjs/ecma402-abstract': 1.11.4
|
||||
'@formatjs/icu-messageformat-parser': 2.1.0
|
||||
'@formatjs/intl': 2.2.1(typescript@4.9.5)
|
||||
'@formatjs/intl-displaynames': 5.4.3
|
||||
'@formatjs/intl-listformat': 6.5.3
|
||||
'@types/hoist-non-react-statics': 3.3.6
|
||||
'@types/react': 18.3.22
|
||||
hoist-non-react-statics: 3.3.2
|
||||
intl-messageformat: 9.13.0
|
||||
react: 18.3.1
|
||||
tslib: 2.8.1
|
||||
optionalDependencies:
|
||||
typescript: 4.9.5
|
||||
|
||||
react-intl@6.8.9(react@19.1.0)(typescript@5.8.3):
|
||||
dependencies:
|
||||
'@formatjs/ecma402-abstract': 2.2.4
|
||||
|
|
@ -14047,10 +13686,6 @@ snapshots:
|
|||
react: 19.1.0
|
||||
react-dom: 19.1.0(react@19.1.0)
|
||||
|
||||
react@18.3.1:
|
||||
dependencies:
|
||||
loose-envify: 1.4.0
|
||||
|
||||
react@19.1.0: {}
|
||||
|
||||
read-babelrc-up@1.1.0:
|
||||
|
|
@ -14284,10 +13919,6 @@ snapshots:
|
|||
|
||||
safer-buffer@2.1.2: {}
|
||||
|
||||
scheduler@0.23.2:
|
||||
dependencies:
|
||||
loose-envify: 1.4.0
|
||||
|
||||
scheduler@0.26.0: {}
|
||||
|
||||
schema-utils@2.7.1:
|
||||
|
|
@ -14604,13 +14235,6 @@ snapshots:
|
|||
|
||||
style-search@0.1.0: {}
|
||||
|
||||
styled-jsx@5.1.1(@babel/core@7.27.1)(react@18.3.1):
|
||||
dependencies:
|
||||
client-only: 0.0.1
|
||||
react: 18.3.1
|
||||
optionalDependencies:
|
||||
'@babel/core': 7.27.1
|
||||
|
||||
styled-jsx@5.1.6(@babel/core@7.27.1)(react@19.1.0):
|
||||
dependencies:
|
||||
client-only: 0.0.1
|
||||
|
|
@ -14992,10 +14616,6 @@ snapshots:
|
|||
dependencies:
|
||||
react: 19.1.0
|
||||
|
||||
use-sync-external-store@1.5.0(react@18.3.1):
|
||||
dependencies:
|
||||
react: 18.3.1
|
||||
|
||||
use-sync-external-store@1.5.0(react@19.1.0):
|
||||
dependencies:
|
||||
react: 19.1.0
|
||||
|
|
@ -15041,11 +14661,6 @@ snapshots:
|
|||
dependencies:
|
||||
makeerror: 1.0.12
|
||||
|
||||
watchpack@2.4.0:
|
||||
dependencies:
|
||||
glob-to-regexp: 0.4.1
|
||||
graceful-fs: 4.2.11
|
||||
|
||||
web-streams-polyfill@3.3.3: {}
|
||||
|
||||
which-boxed-primitive@1.1.1:
|
||||
|
|
@ -15185,14 +14800,6 @@ snapshots:
|
|||
|
||||
zod@3.25.30: {}
|
||||
|
||||
zustand@4.5.7(@types/react@19.1.5)(immer@9.0.21)(react@18.3.1):
|
||||
dependencies:
|
||||
use-sync-external-store: 1.5.0(react@18.3.1)
|
||||
optionalDependencies:
|
||||
'@types/react': 19.1.5
|
||||
immer: 9.0.21
|
||||
react: 18.3.1
|
||||
|
||||
zustand@4.5.7(@types/react@19.1.5)(immer@9.0.21)(react@19.1.0):
|
||||
dependencies:
|
||||
use-sync-external-store: 1.5.0(react@19.1.0)
|
||||
|
|
|
|||
|
|
@ -9,8 +9,7 @@ import {
|
|||
Grid2X2,
|
||||
Settings,
|
||||
} from '@/components/icons';
|
||||
import { useMessages, useNavigation } from '@/components/hooks';
|
||||
import useGlobalState from '@/components/hooks/useGlobalState';
|
||||
import { useMessages, useNavigation, useGlobalState } from '@/components/hooks';
|
||||
|
||||
export function SideNav(props: any) {
|
||||
const { formatMessage, labels } = useMessages();
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import { Button, Icon, Modal, DialogTrigger, Dialog, Text } from '@umami/react-zen';
|
||||
import { useApi, useMessages, useModified } from '@/components/hooks';
|
||||
import { useMessages } from '@/components/hooks';
|
||||
import { Trash } from '@/components/icons';
|
||||
import { ConfirmationForm } from '@/components/common/ConfirmationForm';
|
||||
import { useDeleteQuery } from '@/components/hooks/queries/useDeleteQuery';
|
||||
|
||||
export function ReportDeleteButton({
|
||||
reportId,
|
||||
|
|
@ -13,11 +14,7 @@ export function ReportDeleteButton({
|
|||
onDelete?: () => void;
|
||||
}) {
|
||||
const { formatMessage, labels, messages } = useMessages();
|
||||
const { del, useMutation } = useApi();
|
||||
const { mutate, isPending, error } = useMutation({
|
||||
mutationFn: reportId => del(`/reports/${reportId}`),
|
||||
});
|
||||
const { touch } = useModified();
|
||||
const { mutate, isPending, error, touch } = useDeleteQuery(`/reports/${reportId}`);
|
||||
|
||||
const handleConfirm = (close: () => void) => {
|
||||
mutate(reportId as any, {
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ export function InsightsParameters() {
|
|||
};
|
||||
|
||||
return (
|
||||
<Form values={parameters} onSubmit={handleSubmit} gap="6">
|
||||
<Form values={parameters} onSubmit={handleSubmit}>
|
||||
<BaseParameters allowWebsiteSelect={!id} />
|
||||
{parametersSelected && <FieldParameters />}
|
||||
{parametersSelected && <FilterParameters />}
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ export function WebsiteNav({ websiteId }: { websiteId: string }) {
|
|||
id: 'journeys',
|
||||
label: formatMessage(labels.journey),
|
||||
icon: <Path />,
|
||||
path: '/goals',
|
||||
path: '/journeys',
|
||||
},
|
||||
{
|
||||
id: 'retention',
|
||||
|
|
@ -106,7 +106,7 @@ export function WebsiteNav({ websiteId }: { websiteId: string }) {
|
|||
<Link key={id} href={renderTeamUrl(`/websites/${websiteId}${path}`)}>
|
||||
<NavMenuItem isSelected={isSelected}>
|
||||
<Row alignItems="center" gap>
|
||||
<Icon style={{ fill: 'currentcolor' }}>{icon}</Icon>
|
||||
<Icon>{icon}</Icon>
|
||||
<Text>{label}</Text>
|
||||
</Row>
|
||||
</NavMenuItem>
|
||||
|
|
|
|||
171
src/app/(main)/websites/[websiteId]/goals/Goal.tsx
Normal file
|
|
@ -0,0 +1,171 @@
|
|||
import { useState } from 'react';
|
||||
import {
|
||||
Grid,
|
||||
Row,
|
||||
Column,
|
||||
Text,
|
||||
Icon,
|
||||
Button,
|
||||
MenuTrigger,
|
||||
Menu,
|
||||
MenuItem,
|
||||
Popover,
|
||||
ProgressBar,
|
||||
Dialog,
|
||||
Modal,
|
||||
AlertDialog,
|
||||
} from '@umami/react-zen';
|
||||
import { useMessages, useResultQuery } from '@/components/hooks';
|
||||
import { Edit, More, Trash, File, Lightning, User, Eye } from '@/components/icons';
|
||||
import { LoadingPanel } from '@/components/common/LoadingPanel';
|
||||
import { formatLongNumber } from '@/lib/format';
|
||||
import { GoalAddForm } from '@/app/(main)/websites/[websiteId]/goals/GoalAddForm';
|
||||
import { useDeleteQuery } from '@/components/hooks/queries/useDeleteQuery';
|
||||
|
||||
export interface GoalProps {
|
||||
id: string;
|
||||
name: string;
|
||||
type: string;
|
||||
parameters: {
|
||||
name: string;
|
||||
type: string;
|
||||
value: string;
|
||||
};
|
||||
websiteId: string;
|
||||
startDate: Date;
|
||||
endDate: Date;
|
||||
}
|
||||
|
||||
export type GoalData = { num: number; total: number };
|
||||
|
||||
export function Goal({ id, name, type, parameters, websiteId, startDate, endDate }: GoalProps) {
|
||||
const { formatMessage, labels } = useMessages();
|
||||
const { data, error, isLoading } = useResultQuery<GoalData>(type, {
|
||||
...parameters,
|
||||
websiteId,
|
||||
dateRange: {
|
||||
startDate,
|
||||
endDate,
|
||||
},
|
||||
});
|
||||
const isPage = parameters?.type === 'page';
|
||||
|
||||
return (
|
||||
<LoadingPanel isEmpty={!data} isLoading={isLoading} error={error}>
|
||||
<Grid gap>
|
||||
<Grid columns="1fr auto" gap>
|
||||
<Column gap>
|
||||
<Row>
|
||||
<Text size="4" weight="bold">
|
||||
{name}
|
||||
</Text>
|
||||
</Row>
|
||||
</Column>
|
||||
<Column>
|
||||
<ActionsButton id={id} websiteId={websiteId} />
|
||||
</Column>
|
||||
</Grid>
|
||||
<Row alignItems="center" justifyContent="space-between" gap>
|
||||
<Text color="muted">
|
||||
{formatMessage(isPage ? labels.viewedPage : labels.triggeredEvent)}
|
||||
</Text>
|
||||
<Text color="muted">{formatMessage(labels.conversionRate)}</Text>
|
||||
</Row>
|
||||
<Row alignItems="center" justifyContent="space-between" gap>
|
||||
<Row alignItems="center" gap>
|
||||
<Icon>{parameters.type === 'page' ? <File /> : <Lightning />}</Icon>
|
||||
<Text>{parameters.value}</Text>
|
||||
</Row>
|
||||
<Row alignItems="center" gap>
|
||||
<Icon>{isPage ? <Eye /> : <User />}</Icon>
|
||||
<Text title={`${data?.num} / ${data?.total}`}>{`${formatLongNumber(
|
||||
data?.num,
|
||||
)} / ${formatLongNumber(data?.total)}`}</Text>
|
||||
</Row>
|
||||
</Row>
|
||||
<Row alignItems="center" gap>
|
||||
<ProgressBar
|
||||
value={data?.num || 0}
|
||||
minValue={0}
|
||||
maxValue={data?.total || 1}
|
||||
style={{ width: '100%' }}
|
||||
/>
|
||||
<Text weight="bold" size="7">
|
||||
{data?.total ? Math.round((+data?.num / +data?.total) * 100) : '0'}%
|
||||
</Text>
|
||||
</Row>
|
||||
</Grid>
|
||||
</LoadingPanel>
|
||||
);
|
||||
}
|
||||
|
||||
const ActionsButton = ({ id, websiteId }: { id: string; websiteId: string }) => {
|
||||
const { formatMessage, labels } = useMessages();
|
||||
const [showEdit, setShowEdit] = useState(false);
|
||||
const [showDelete, setShowDelete] = useState(false);
|
||||
const { mutate, touch } = useDeleteQuery(`/reports/${id}`);
|
||||
|
||||
const handleAction = (id: any) => {
|
||||
if (id === 'edit') {
|
||||
setShowEdit(true);
|
||||
} else if (id === 'delete') {
|
||||
setShowDelete(true);
|
||||
}
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
setShowEdit(false);
|
||||
setShowDelete(false);
|
||||
};
|
||||
|
||||
const handleDelete = async () => {
|
||||
mutate(null, {
|
||||
onSuccess: async () => {
|
||||
touch(`goals`);
|
||||
setShowDelete(false);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<MenuTrigger>
|
||||
<Button variant="quiet">
|
||||
<Icon>
|
||||
<More />
|
||||
</Icon>
|
||||
</Button>
|
||||
<Popover placement="bottom">
|
||||
<Menu onAction={handleAction}>
|
||||
<MenuItem id="edit">
|
||||
<Icon>
|
||||
<Edit />
|
||||
</Icon>
|
||||
<Text>{formatMessage(labels.edit)}</Text>
|
||||
</MenuItem>
|
||||
<MenuItem id="delete">
|
||||
<Icon>
|
||||
<Trash />
|
||||
</Icon>
|
||||
<Text>{formatMessage(labels.delete)}</Text>
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
</Popover>
|
||||
</MenuTrigger>
|
||||
<Modal isOpen={showEdit || showDelete} isDismissable={true}>
|
||||
{showEdit && (
|
||||
<Dialog variant="modal" style={{ minHeight: 375, minWidth: 300 }}>
|
||||
<GoalAddForm id={id} websiteId={websiteId} onClose={handleClose} />
|
||||
</Dialog>
|
||||
)}
|
||||
{showDelete && (
|
||||
<AlertDialog
|
||||
title={formatMessage(labels.delete)}
|
||||
onConfirm={handleDelete}
|
||||
onCancel={handleClose}
|
||||
/>
|
||||
)}
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import { Button, MenuTrigger, Dialog, Icon, Text, Modal } from '@umami/react-zen';
|
||||
import { Button, DialogTrigger, Dialog, Icon, Text, Modal } from '@umami/react-zen';
|
||||
import { useMessages } from '@/components/hooks';
|
||||
import { GoalAddForm } from './GoalAddForm';
|
||||
import { Plus } from '@/components/icons';
|
||||
|
|
@ -7,7 +7,7 @@ export function GoalAddButton({ websiteId }: { websiteId: string }) {
|
|||
const { formatMessage, labels } = useMessages();
|
||||
|
||||
return (
|
||||
<MenuTrigger>
|
||||
<DialogTrigger>
|
||||
<Button variant="primary">
|
||||
<Icon>
|
||||
<Plus />
|
||||
|
|
@ -15,10 +15,10 @@ export function GoalAddButton({ websiteId }: { websiteId: string }) {
|
|||
<Text>{formatMessage(labels.addGoal)}</Text>
|
||||
</Button>
|
||||
<Modal>
|
||||
<Dialog variant="modal" title={formatMessage(labels.addGoal)}>
|
||||
<Dialog variant="modal" title={formatMessage(labels.addGoal)} style={{ width: '400px' }}>
|
||||
{({ close }) => <GoalAddForm websiteId={websiteId} onClose={close} />}
|
||||
</Dialog>
|
||||
</Modal>
|
||||
</MenuTrigger>
|
||||
</DialogTrigger>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,72 +2,116 @@ import {
|
|||
Form,
|
||||
FormField,
|
||||
TextField,
|
||||
Select,
|
||||
Grid,
|
||||
FormButtons,
|
||||
FormSubmitButton,
|
||||
Button,
|
||||
RadioGroup,
|
||||
Radio,
|
||||
Text,
|
||||
Icon,
|
||||
Loading,
|
||||
} from '@umami/react-zen';
|
||||
import { useApi, useMessages } from '@/components/hooks';
|
||||
import { useApi, useMessages, useModified, useReportQuery } from '@/components/hooks';
|
||||
import { File, Lightning } from '@/components/icons';
|
||||
|
||||
const defaultValues = {
|
||||
name: '',
|
||||
type: 'page',
|
||||
value: '',
|
||||
};
|
||||
|
||||
export function GoalAddForm({
|
||||
id,
|
||||
websiteId,
|
||||
onSave,
|
||||
onClose,
|
||||
}: {
|
||||
id?: string;
|
||||
websiteId: string;
|
||||
onSave?: () => void;
|
||||
onClose?: () => void;
|
||||
}) {
|
||||
const { formatMessage, labels } = useMessages();
|
||||
const { touch } = useModified();
|
||||
const { post, useMutation } = useApi();
|
||||
const { data } = useReportQuery(id);
|
||||
const { mutate, error, isPending } = useMutation({
|
||||
mutationFn: (data: any) => post('/websites', { ...data }),
|
||||
mutationFn: (params: any) => post(`/websites/${websiteId}/goals`, params),
|
||||
});
|
||||
|
||||
const handleSubmit = async (data: any) => {
|
||||
mutate(data, {
|
||||
onSuccess: async () => {
|
||||
onSave?.();
|
||||
onClose?.();
|
||||
mutate(
|
||||
{ id, ...data },
|
||||
{
|
||||
onSuccess: async () => {
|
||||
onSave?.();
|
||||
onClose?.();
|
||||
touch('goals');
|
||||
},
|
||||
},
|
||||
});
|
||||
);
|
||||
};
|
||||
|
||||
const items = [
|
||||
{ id: 'page', label: formatMessage(labels.page) },
|
||||
{ id: 'event', label: formatMessage(labels.event) },
|
||||
];
|
||||
if (id && !data) {
|
||||
return <Loading position="page" icon="dots" />;
|
||||
}
|
||||
|
||||
return (
|
||||
<Form onSubmit={handleSubmit} error={error?.message}>
|
||||
{websiteId}
|
||||
<FormField
|
||||
name="name"
|
||||
label={formatMessage(labels.name)}
|
||||
rules={{ required: formatMessage(labels.required) }}
|
||||
>
|
||||
<TextField />
|
||||
</FormField>
|
||||
<FormField
|
||||
name="type"
|
||||
label={formatMessage(labels.type)}
|
||||
rules={{ required: formatMessage(labels.required) }}
|
||||
>
|
||||
<Select items={items} defaultValue="page" />
|
||||
</FormField>
|
||||
<FormField
|
||||
name="value"
|
||||
label={formatMessage(labels.value)}
|
||||
rules={{ required: formatMessage(labels.required) }}
|
||||
>
|
||||
<TextField />
|
||||
</FormField>
|
||||
<FormButtons>
|
||||
<Button onPress={onClose} isDisabled={isPending}>
|
||||
{formatMessage(labels.cancel)}
|
||||
</Button>
|
||||
<FormSubmitButton isDisabled={false}>{formatMessage(labels.add)}</FormSubmitButton>
|
||||
</FormButtons>
|
||||
<Form
|
||||
onSubmit={handleSubmit}
|
||||
error={error?.message}
|
||||
defaultValues={data?.parameters || defaultValues}
|
||||
>
|
||||
{({ watch }) => {
|
||||
const watchType = watch('type');
|
||||
return (
|
||||
<>
|
||||
<FormField
|
||||
name="type"
|
||||
label={formatMessage(labels.type)}
|
||||
rules={{ required: formatMessage(labels.required) }}
|
||||
>
|
||||
<RadioGroup orientation="horizontal" variant="box">
|
||||
<Grid columns="1fr 1fr" flexGrow={1} gap>
|
||||
<Radio value="page">
|
||||
<Icon>
|
||||
<File />
|
||||
</Icon>
|
||||
<Text>{formatMessage(labels.page)}</Text>
|
||||
</Radio>
|
||||
<Radio value="event">
|
||||
<Icon>
|
||||
<Lightning />
|
||||
</Icon>
|
||||
<Text>{formatMessage(labels.event)}</Text>
|
||||
</Radio>
|
||||
</Grid>
|
||||
</RadioGroup>
|
||||
</FormField>
|
||||
<FormField
|
||||
name="name"
|
||||
label={formatMessage(labels.name)}
|
||||
rules={{ required: formatMessage(labels.required) }}
|
||||
>
|
||||
<TextField />
|
||||
</FormField>
|
||||
<FormField
|
||||
name="value"
|
||||
label={formatMessage(watchType === 'event' ? labels.eventName : labels.path)}
|
||||
rules={{ required: formatMessage(labels.required) }}
|
||||
>
|
||||
<TextField />
|
||||
</FormField>
|
||||
<FormButtons>
|
||||
<Button onPress={onClose} isDisabled={isPending}>
|
||||
{formatMessage(labels.cancel)}
|
||||
</Button>
|
||||
<FormSubmitButton>{formatMessage(id ? labels.save : labels.add)}</FormSubmitButton>
|
||||
</FormButtons>
|
||||
</>
|
||||
);
|
||||
}}
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,38 @@
|
|||
'use client';
|
||||
import { Column } from '@umami/react-zen';
|
||||
import { Grid, Loading } from '@umami/react-zen';
|
||||
import { SectionHeader } from '@/components/common/SectionHeader';
|
||||
import { Goal } from './Goal';
|
||||
import { GoalAddButton } from './GoalAddButton';
|
||||
import { WebsiteControls } from '@/app/(main)/websites/[websiteId]/WebsiteControls';
|
||||
import { WebsiteControls } from '../WebsiteControls';
|
||||
import { useDateRange, useGoalsQuery } from '@/components/hooks';
|
||||
import { LoadingPanel } from '@/components/common/LoadingPanel';
|
||||
import { Panel } from '@/components/common/Panel';
|
||||
|
||||
export function GoalsPage({ websiteId }: { websiteId: string }) {
|
||||
const { result } = useGoalsQuery({ websiteId });
|
||||
const {
|
||||
dateRange: { startDate, endDate },
|
||||
} = useDateRange(websiteId);
|
||||
|
||||
if (!result) {
|
||||
return <Loading position="page" />;
|
||||
}
|
||||
|
||||
return (
|
||||
<Column>
|
||||
<>
|
||||
<WebsiteControls websiteId={websiteId} />
|
||||
<SectionHeader>
|
||||
<GoalAddButton websiteId={websiteId} />
|
||||
</SectionHeader>
|
||||
</Column>
|
||||
<LoadingPanel isEmpty={!result?.data} isLoading={!result}>
|
||||
<SectionHeader>
|
||||
<GoalAddButton websiteId={websiteId} />
|
||||
</SectionHeader>
|
||||
<Grid columns="1fr 1fr" gap>
|
||||
{result?.data?.map((goal: any) => (
|
||||
<Panel key={goal.id}>
|
||||
<Goal {...goal} reportId={goal.id} startDate={startDate} endDate={endDate} />
|
||||
</Panel>
|
||||
))}
|
||||
</Grid>
|
||||
</LoadingPanel>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,10 +69,12 @@ export function SessionsWeekly({ websiteId }: { websiteId: string }) {
|
|||
{hour > 0 && (
|
||||
<TooltipTrigger delay={0}>
|
||||
<Focusable>
|
||||
<div
|
||||
className={styles.block}
|
||||
style={{ opacity: pct, transform: `scale(${pct})` }}
|
||||
/>
|
||||
<div>
|
||||
<div
|
||||
className={styles.block}
|
||||
style={{ opacity: pct, transform: `scale(${pct})` }}
|
||||
/>
|
||||
</div>
|
||||
</Focusable>
|
||||
<Tooltip placement="right">{`${formatMessage(
|
||||
labels.visitors,
|
||||
|
|
|
|||
|
|
@ -2,34 +2,28 @@ import { z } from 'zod';
|
|||
import { canViewWebsite } from '@/lib/auth';
|
||||
import { unauthorized, json } from '@/lib/response';
|
||||
import { parseRequest } from '@/lib/request';
|
||||
import { getGoals } from '@/queries/sql/reports/getGoals';
|
||||
import { reportParms } from '@/lib/schema';
|
||||
import { getGoal } from '@/queries/sql/reports/getGoal';
|
||||
import { filterParams, reportParms } from '@/lib/schema';
|
||||
|
||||
export async function POST(request: Request) {
|
||||
const schema = z.object({
|
||||
...reportParms,
|
||||
goals: z
|
||||
.array(
|
||||
z
|
||||
.object({
|
||||
type: z.string().regex(/url|event|event-data/),
|
||||
value: z.string(),
|
||||
goal: z.coerce.number(),
|
||||
operator: z
|
||||
.string()
|
||||
.regex(/count|sum|average/)
|
||||
.optional(),
|
||||
property: z.string().optional(),
|
||||
})
|
||||
.refine(data => {
|
||||
if (data['type'] === 'event-data') {
|
||||
return data['operator'] && data['property'];
|
||||
}
|
||||
return true;
|
||||
}),
|
||||
)
|
||||
.min(1),
|
||||
});
|
||||
const schema = z
|
||||
.object({
|
||||
...reportParms,
|
||||
...filterParams,
|
||||
type: z.enum(['page', 'event']),
|
||||
value: z.string(),
|
||||
operator: z
|
||||
.string()
|
||||
.regex(/count|sum|average/)
|
||||
.optional(),
|
||||
property: z.string().optional(),
|
||||
})
|
||||
.refine(data => {
|
||||
if (data['type'] === 'event' && data['property']) {
|
||||
return data['operator'] && data['property'];
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
const { auth, body, error } = await parseRequest(request, schema);
|
||||
|
||||
|
|
@ -39,18 +33,24 @@ export async function POST(request: Request) {
|
|||
|
||||
const {
|
||||
websiteId,
|
||||
type,
|
||||
value,
|
||||
property,
|
||||
operator,
|
||||
dateRange: { startDate, endDate },
|
||||
goals,
|
||||
} = body;
|
||||
|
||||
if (!(await canViewWebsite(auth, websiteId))) {
|
||||
return unauthorized();
|
||||
}
|
||||
|
||||
const data = await getGoals(websiteId, {
|
||||
const data = await getGoal(websiteId, {
|
||||
type,
|
||||
value,
|
||||
property,
|
||||
operator,
|
||||
startDate: new Date(startDate),
|
||||
endDate: new Date(endDate),
|
||||
goals,
|
||||
});
|
||||
|
||||
return json(data);
|
||||
|
|
|
|||
94
src/app/api/websites/[websiteId]/goals/route.ts
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
import { z } from 'zod';
|
||||
import { canViewWebsite } from '@/lib/auth';
|
||||
import { unauthorized, json, ok } from '@/lib/response';
|
||||
import { parseRequest } from '@/lib/request';
|
||||
import { getReports, createReport, updateReport } from '@/queries';
|
||||
import { uuid } from '@/lib/crypto';
|
||||
|
||||
export async function GET(
|
||||
request: Request,
|
||||
{ params }: { params: Promise<{ websiteId: string }> },
|
||||
) {
|
||||
const { auth, query, error } = await parseRequest(request);
|
||||
|
||||
if (error) {
|
||||
return error();
|
||||
}
|
||||
|
||||
const { websiteId } = await params;
|
||||
const { page, search, pageSize } = query;
|
||||
const filters = {
|
||||
page,
|
||||
pageSize,
|
||||
search,
|
||||
};
|
||||
|
||||
if (!(await canViewWebsite(auth, websiteId))) {
|
||||
return unauthorized();
|
||||
}
|
||||
|
||||
const data = await getReports(
|
||||
{
|
||||
where: {
|
||||
websiteId,
|
||||
type: 'goals',
|
||||
},
|
||||
},
|
||||
filters,
|
||||
).then(result => {
|
||||
result.data = result.data.map(report => {
|
||||
report.parameters = JSON.parse(report.parameters);
|
||||
|
||||
return report;
|
||||
});
|
||||
|
||||
return result;
|
||||
});
|
||||
|
||||
return json(data);
|
||||
}
|
||||
|
||||
export async function POST(
|
||||
request: Request,
|
||||
{ params }: { params: Promise<{ websiteId: string }> },
|
||||
) {
|
||||
const schema = z.object({
|
||||
id: z.string().uuid().optional(),
|
||||
name: z.string(),
|
||||
type: z.enum(['page', 'event']),
|
||||
value: z.string(),
|
||||
});
|
||||
|
||||
const { auth, body, error } = await parseRequest(request, schema);
|
||||
|
||||
if (error) {
|
||||
return error();
|
||||
}
|
||||
|
||||
const { websiteId } = await params;
|
||||
|
||||
if (!(await canViewWebsite(auth, websiteId))) {
|
||||
return unauthorized();
|
||||
}
|
||||
|
||||
const { id, name, type, value } = body;
|
||||
|
||||
if (id) {
|
||||
await updateReport(id, {
|
||||
name,
|
||||
parameters: JSON.stringify({ name, type, value }),
|
||||
});
|
||||
} else {
|
||||
await createReport({
|
||||
id: uuid(),
|
||||
userId: auth.user.id,
|
||||
websiteId,
|
||||
type: 'goals',
|
||||
name,
|
||||
description: '',
|
||||
parameters: JSON.stringify({ name, type, value }),
|
||||
});
|
||||
}
|
||||
|
||||
return ok();
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 24 24"><g clip-rule="evenodd"><path d="M12 4a8 8 0 1 0 0 16 8 8 0 0 0 0-16zM2 12C2 6.477 6.477 2 12 2s10 4.477 10 10-4.477 10-10 10S2 17.523 2 12z"/><path d="M11.168 11.445a1 1 0 0 1 1.387-.277l3 2a1 1 0 0 1-1.11 1.664l-3-2a1 1 0 0 1-.277-1.387z"/><path d="M12 6a1 1 0 0 1 1 1v5a1 1 0 1 1-2 0V7a1 1 0 0 1 1-1z"/></g></svg>
|
||||
|
Before Width: | Height: | Size: 400 B |
|
|
@ -1 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 32 32"><path d="M29 11H3a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h26a1 1 0 0 1 1 1v6a1 1 0 0 1-1 1zM4 9h24V5H4z"/><path d="M25 17H7a1 1 0 0 1-1-1v-6a1 1 0 0 1 1-1h18a1 1 0 0 1 1 1v6a1 1 0 0 1-1 1zM8 15h16v-4H8z"/><path d="M22 23H10a1 1 0 0 1-1-1v-6a1 1 0 0 1 1-1h12a1 1 0 0 1 1 1v6a1 1 0 0 1-1 1zm-11-2h10v-4H11z"/><path d="M19 29h-6a1 1 0 0 1-1-1v-6a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v6a1 1 0 0 1-1 1zm-5-2h4v-4h-4z"/></svg>
|
||||
<svg fill="currentColor" xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 32 32"><path d="M29 11H3a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h26a1 1 0 0 1 1 1v6a1 1 0 0 1-1 1zM4 9h24V5H4z"/><path d="M25 17H7a1 1 0 0 1-1-1v-6a1 1 0 0 1 1-1h18a1 1 0 0 1 1 1v6a1 1 0 0 1-1 1zM8 15h16v-4H8z"/><path d="M22 23H10a1 1 0 0 1-1-1v-6a1 1 0 0 1 1-1h12a1 1 0 0 1 1 1v6a1 1 0 0 1-1 1zm-11-2h10v-4H11z"/><path d="M19 29h-6a1 1 0 0 1-1-1v-6a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v6a1 1 0 0 1-1 1zm-5-2h4v-4h-4z"/></svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 487 B After Width: | Height: | Size: 508 B |
|
|
@ -1 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" style="enable-background:new 0 0 512 512" viewBox="0 0 512 512"><path d="M223.718 124.76c-48.027 11.198-86.688 49.285-98.494 97.031-11.843 47.899 1.711 96.722 36.259 130.601C173.703 364.377 181 383.586 181 403.777V407c0 13.296 5.801 25.26 15 33.505V467c0 24.813 20.187 45 45 45h30c24.813 0 45-20.187 45-45v-26.495c9.199-8.245 15-20.208 15-33.505v-3.282c0-19.884 7.687-39.458 20.563-52.361C376.994 325.87 391 292.005 391 256c0-86.079-79.769-151.638-167.282-131.24zM286 467c0 8.271-6.729 15-15 15h-30c-8.271 0-15-6.729-15-15v-15h60v15zm44.326-136.834C311.689 348.843 301 375.651 301 403.718V407c0 8.271-6.729 15-15 15h-60c-8.271 0-15-6.729-15-15v-3.223c0-28.499-10.393-55.035-28.513-72.804-26.89-26.37-37.409-64.493-28.141-101.981 9.125-36.907 39.029-66.353 76.184-75.015C299.202 137.964 361 189.228 361 256c0 28.004-10.894 54.343-30.674 74.166zM139.327 118.114 96.9 75.688c-5.857-5.858-15.355-5.858-21.213 0-5.858 5.858-5.858 15.355 0 21.213l42.427 42.426c5.857 5.858 15.356 5.858 21.213 0 5.858-5.858 5.858-15.355 0-21.213zM76 241H15c-8.284 0-15 6.716-15 15s6.716 15 15 15h61c8.284 0 15-6.716 15-15s-6.716-15-15-15zm421 0h-61c-8.284 0-15 6.716-15 15s6.716 15 15 15h61c8.284 0 15-6.716 15-15s-6.716-15-15-15zM436.313 75.688c-5.856-5.858-15.354-5.858-21.213 0l-42.427 42.426c-5.858 5.857-5.858 15.355 0 21.213 5.857 5.858 15.355 5.858 21.213 0l42.427-42.426c5.858-5.857 5.858-15.355 0-21.213zM256 0c-8.284 0-15 6.716-15 15v61c0 8.284 6.716 15 15 15s15-6.716 15-15V15c0-8.284-6.716-15-15-15z"/><path d="M256 181c-6.166 0-12.447.739-18.658 2.194-25.865 6.037-47.518 27.328-53.879 52.979-1.994 8.041 2.907 16.175 10.947 18.17 8.042 1.994 16.176-2.909 18.17-10.948 3.661-14.758 16.647-27.5 31.593-30.989 3.982-.933 7.962-1.406 11.827-1.406 8.284 0 15-6.716 15-15s-6.716-15-15-15z"/></svg>
|
||||
<svg fill="currentColor" xmlns="http://www.w3.org/2000/svg" xml:space="preserve" style="enable-background:new 0 0 512 512" viewBox="0 0 512 512"><path d="M223.718 124.76c-48.027 11.198-86.688 49.285-98.494 97.031-11.843 47.899 1.711 96.722 36.259 130.601C173.703 364.377 181 383.586 181 403.777V407c0 13.296 5.801 25.26 15 33.505V467c0 24.813 20.187 45 45 45h30c24.813 0 45-20.187 45-45v-26.495c9.199-8.245 15-20.208 15-33.505v-3.282c0-19.884 7.687-39.458 20.563-52.361C376.994 325.87 391 292.005 391 256c0-86.079-79.769-151.638-167.282-131.24zM286 467c0 8.271-6.729 15-15 15h-30c-8.271 0-15-6.729-15-15v-15h60v15zm44.326-136.834C311.689 348.843 301 375.651 301 403.718V407c0 8.271-6.729 15-15 15h-60c-8.271 0-15-6.729-15-15v-3.223c0-28.499-10.393-55.035-28.513-72.804-26.89-26.37-37.409-64.493-28.141-101.981 9.125-36.907 39.029-66.353 76.184-75.015C299.202 137.964 361 189.228 361 256c0 28.004-10.894 54.343-30.674 74.166zM139.327 118.114 96.9 75.688c-5.857-5.858-15.355-5.858-21.213 0-5.858 5.858-5.858 15.355 0 21.213l42.427 42.426c5.857 5.858 15.356 5.858 21.213 0 5.858-5.858 5.858-15.355 0-21.213zM76 241H15c-8.284 0-15 6.716-15 15s6.716 15 15 15h61c8.284 0 15-6.716 15-15s-6.716-15-15-15zm421 0h-61c-8.284 0-15 6.716-15 15s6.716 15 15 15h61c8.284 0 15-6.716 15-15s-6.716-15-15-15zM436.313 75.688c-5.856-5.858-15.354-5.858-21.213 0l-42.427 42.426c-5.858 5.857-5.858 15.355 0 21.213 5.857 5.858 15.355 5.858 21.213 0l42.427-42.426c5.858-5.857 5.858-15.355 0-21.213zM256 0c-8.284 0-15 6.716-15 15v61c0 8.284 6.716 15 15 15s15-6.716 15-15V15c0-8.284-6.716-15-15-15z"/><path d="M256 181c-6.166 0-12.447.739-18.658 2.194-25.865 6.037-47.518 27.328-53.879 52.979-1.994 8.041 2.907 16.175 10.947 18.17 8.042 1.994 16.176-2.909 18.17-10.948 3.661-14.758 16.647-27.5 31.593-30.989 3.982-.933 7.962-1.406 11.827-1.406 8.284 0 15-6.716 15-15s-6.716-15-15-15z"/></svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
|
|
@ -1 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 428 389.11"><circle cx="214.15" cy="181" r="171" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="20"/><path d="M413 134.11H15.29a15 15 0 0 0-15 15v15.3C.12 168 0 171.52 0 175.11c0 118.19 95.81 214 214 214 116.4 0 211.1-92.94 213.93-208.67 0-.44.07-.88.07-1.33v-30a15 15 0 0 0-15-15Z"/></svg>
|
||||
<svg fill="currentColor" stroke="currentColor" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 428 389.11"><circle cx="214.15" cy="181" r="171" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="20"/><path d="M413 134.11H15.29a15 15 0 0 0-15 15v15.3C.12 168 0 171.52 0 175.11c0 118.19 95.81 214 214 214 116.4 0 211.1-92.94 213.93-208.67 0-.44.07-.88.07-1.33v-30a15 15 0 0 0-15-15Z"/></svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 391 B After Width: | Height: | Size: 433 B |
|
|
@ -1 +1 @@
|
|||
<svg height="512" viewBox="0 0 508.467 508.467" width="512" xmlns="http://www.w3.org/2000/svg"><path d="M426.815 239.006c-11.722-11.724-30.702-11.729-42.427-.001L267.67 355.723c-53.811 53.809-142.478 19.197-140.68-54.511.547-22.415 9.826-43.738 26.129-60.041l116.717-116.717c11.724-11.722 11.728-30.702 0-42.427l-46.668-46.669c-11.725-11.725-30.702-11.726-42.427 0L60.629 155.47C21.579 194.52.047 246.44 0 301.665c-.093 110.827 88.182 206.288 206.244 206.394 56.778 0 109.204-21.924 148.29-61.01l118.948-118.948c11.724-11.722 11.728-30.702 0-42.427zM201.954 56.572l46.669 46.669-58.455 58.456-46.669-46.669zm131.367 369.264c-69.043 69.043-182.868 70.02-251.708.933-68.763-69.009-68.66-181.196.229-250.086l40.443-40.443 46.669 46.669-37.049 37.049c-45.115 45.112-46.916 116.85-3.395 160.371 43.279 43.279 115.221 41.756 160.372-3.394l37.049-37.049 46.669 46.669zm60.494-60.493-46.669-46.669 58.456-58.456 46.669 46.669zM379.357 95.099c15.199 3.839 30.418 19.07 34.336 34.192 2.089 8.058 10.303 12.828 18.283 10.758 8.02-2.078 12.836-10.264 10.758-18.283-6.651-25.662-30.176-49.223-56.03-55.753-8.032-2.027-16.188 2.838-18.217 10.869-2.029 8.032 2.837 16.189 10.87 18.217zm128.627 7.025C495.968 55.749 452.769 12.62 406.239.868c-8.032-2.027-16.188 2.838-18.217 10.869-2.029 8.032 2.838 16.188 10.87 18.217 35.882 9.063 70.769 43.871 80.051 79.695 2.088 8.058 10.304 12.828 18.283 10.758 8.02-2.078 12.836-10.263 10.758-18.283z"/></svg>
|
||||
<svg fill="currentColor" height="512" viewBox="0 0 508.467 508.467" width="512" xmlns="http://www.w3.org/2000/svg"><path d="M426.815 239.006c-11.722-11.724-30.702-11.729-42.427-.001L267.67 355.723c-53.811 53.809-142.478 19.197-140.68-54.511.547-22.415 9.826-43.738 26.129-60.041l116.717-116.717c11.724-11.722 11.728-30.702 0-42.427l-46.668-46.669c-11.725-11.725-30.702-11.726-42.427 0L60.629 155.47C21.579 194.52.047 246.44 0 301.665c-.093 110.827 88.182 206.288 206.244 206.394 56.778 0 109.204-21.924 148.29-61.01l118.948-118.948c11.724-11.722 11.728-30.702 0-42.427zM201.954 56.572l46.669 46.669-58.455 58.456-46.669-46.669zm131.367 369.264c-69.043 69.043-182.868 70.02-251.708.933-68.763-69.009-68.66-181.196.229-250.086l40.443-40.443 46.669 46.669-37.049 37.049c-45.115 45.112-46.916 116.85-3.395 160.371 43.279 43.279 115.221 41.756 160.372-3.394l37.049-37.049 46.669 46.669zm60.494-60.493-46.669-46.669 58.456-58.456 46.669 46.669zM379.357 95.099c15.199 3.839 30.418 19.07 34.336 34.192 2.089 8.058 10.303 12.828 18.283 10.758 8.02-2.078 12.836-10.264 10.758-18.283-6.651-25.662-30.176-49.223-56.03-55.753-8.032-2.027-16.188 2.838-18.217 10.869-2.029 8.032 2.837 16.189 10.87 18.217zm128.627 7.025C495.968 55.749 452.769 12.62 406.239.868c-8.032-2.027-16.188 2.838-18.217 10.869-2.029 8.032 2.838 16.188 10.87 18.217 35.882 9.063 70.769 43.871 80.051 79.695 2.088 8.058 10.304 12.828 18.283 10.758 8.02-2.078 12.836-10.263 10.758-18.283z"/></svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
|
@ -1 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512" xml:space="preserve"><path d="M347 302c8.271 0 15 6.639 15 14.8h30c0-19.468-12.541-36.067-30-42.231V242h-30v32.58c-17.459 6.192-30 22.865-30 42.42 0 24.813 20.187 45 45 45 8.271 0 15 6.729 15 15s-6.729 15-15 15-15-6.729-15-15h-30c0 19.555 12.541 36.228 30 42.42v32.38h30v-32.38c17.459-6.192 30-22.865 30-42.42 0-24.813-20.187-45-45-45-8.271 0-15-6.729-15-15s6.729-15 15-15z"/><path d="M347 182c-5.057 0-10.058.242-15 .689V90c0-26.011-18.548-49.61-52.226-66.449C249.4 8.364 209.35 0 167 0 124.564 0 84.193 8.347 53.323 23.502 18.938 40.385 0 64 0 90v272c0 26 18.938 49.616 53.323 66.498C84.193 443.653 124.564 452 167 452c17.009 0 33.647-1.358 49.615-4.004C246.826 486.909 294.035 512 347 512c90.981 0 165-74.019 165-165s-74.019-165-165-165zM66.545 50.432C92.992 37.447 129.606 30 167 30c79.558 0 135 31.621 135 60s-55.442 60-135 60c-37.394 0-74.008-7.447-100.455-20.432C43.32 118.166 30 103.744 30 90s13.32-28.166 36.545-39.568zM30 142.265c6.724 5.137 14.512 9.907 23.323 14.233C84.193 171.653 124.564 180 167 180c42.35 0 82.4-8.364 112.774-23.551 8.359-4.18 15.783-8.776 22.226-13.722v45.51c-29.896 8.485-56.359 25.209-76.778 47.548C206.946 239.908 187.386 242 167 242c-37.394 0-74.008-7.447-100.455-20.432C43.32 210.166 30 195.744 30 182v-39.735zm0 92c6.724 5.137 14.512 9.907 23.323 14.233C84.193 263.653 124.564 272 167 272c11.581 0 22.942-.621 34.021-1.839a163.743 163.743 0 0 0-18.293 61.395c-5.211.286-10.465.444-15.728.444-37.394 0-74.008-7.447-100.455-20.432C43.32 300.166 30 285.744 30 272v-37.735zM167 422c-37.394 0-74.008-7.447-100.455-20.432C43.32 390.166 30 375.744 30 362v-37.736c6.724 5.137 14.512 9.907 23.323 14.233C84.193 353.653 124.564 362 167 362c5.23 0 10.459-.132 15.654-.388a163.726 163.726 0 0 0 16.486 58.557A280.559 280.559 0 0 1 167 422zm180 60c-74.439 0-135-60.561-135-135s60.561-135 135-135 135 60.561 135 135-60.561 135-135 135z"/></svg>
|
||||
<svg fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512" xml:space="preserve"><path d="M347 302c8.271 0 15 6.639 15 14.8h30c0-19.468-12.541-36.067-30-42.231V242h-30v32.58c-17.459 6.192-30 22.865-30 42.42 0 24.813 20.187 45 45 45 8.271 0 15 6.729 15 15s-6.729 15-15 15-15-6.729-15-15h-30c0 19.555 12.541 36.228 30 42.42v32.38h30v-32.38c17.459-6.192 30-22.865 30-42.42 0-24.813-20.187-45-45-45-8.271 0-15-6.729-15-15s6.729-15 15-15z"/><path d="M347 182c-5.057 0-10.058.242-15 .689V90c0-26.011-18.548-49.61-52.226-66.449C249.4 8.364 209.35 0 167 0 124.564 0 84.193 8.347 53.323 23.502 18.938 40.385 0 64 0 90v272c0 26 18.938 49.616 53.323 66.498C84.193 443.653 124.564 452 167 452c17.009 0 33.647-1.358 49.615-4.004C246.826 486.909 294.035 512 347 512c90.981 0 165-74.019 165-165s-74.019-165-165-165zM66.545 50.432C92.992 37.447 129.606 30 167 30c79.558 0 135 31.621 135 60s-55.442 60-135 60c-37.394 0-74.008-7.447-100.455-20.432C43.32 118.166 30 103.744 30 90s13.32-28.166 36.545-39.568zM30 142.265c6.724 5.137 14.512 9.907 23.323 14.233C84.193 171.653 124.564 180 167 180c42.35 0 82.4-8.364 112.774-23.551 8.359-4.18 15.783-8.776 22.226-13.722v45.51c-29.896 8.485-56.359 25.209-76.778 47.548C206.946 239.908 187.386 242 167 242c-37.394 0-74.008-7.447-100.455-20.432C43.32 210.166 30 195.744 30 182v-39.735zm0 92c6.724 5.137 14.512 9.907 23.323 14.233C84.193 263.653 124.564 272 167 272c11.581 0 22.942-.621 34.021-1.839a163.743 163.743 0 0 0-18.293 61.395c-5.211.286-10.465.444-15.728.444-37.394 0-74.008-7.447-100.455-20.432C43.32 300.166 30 285.744 30 272v-37.735zM167 422c-37.394 0-74.008-7.447-100.455-20.432C43.32 390.166 30 375.744 30 362v-37.736c6.724 5.137 14.512 9.907 23.323 14.233C84.193 353.653 124.564 362 167 362c5.23 0 10.459-.132 15.654-.388a163.726 163.726 0 0 0 16.486 58.557A280.559 280.559 0 0 1 167 422zm180 60c-74.439 0-135-60.561-135-135s60.561-135 135-135 135 60.561 135 135-60.561 135-135 135z"/></svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
|
@ -1 +1 @@
|
|||
<svg height="512" viewBox="0 0 32 32" width="512" xmlns="http://www.w3.org/2000/svg"><g id="_x30_6_network"><path d="m28 19c-.809 0-1.54.325-2.08.847l-6.011-3.01c.058-.271.091-.55.091-.837s-.033-.566-.091-.837l6.011-3.01c.54.522 1.271.847 2.08.847 1.654 0 3-1.346 3-3s-1.346-3-3-3-3 1.346-3 3c0 .123.022.24.036.359l-6.036 3.023c-.521-.597-1.21-1.035-2-1.24v-5.326c1.162-.415 2-1.514 2-2.816 0-1.654-1.346-3-3-3s-3 1.346-3 3c0 1.302.838 2.401 2 2.815v5.327c-.79.205-1.478.643-2 1.24l-6.037-3.022c.015-.12.037-.237.037-.36 0-1.654-1.346-3-3-3s-3 1.346-3 3 1.346 3 3 3c.809 0 1.54-.325 2.08-.847l6.011 3.01c-.058.271-.091.55-.091.837s.033.566.091.837l-6.011 3.01c-.54-.522-1.271-.847-2.08-.847-1.654 0-3 1.346-3 3s1.346 3 3 3 3-1.346 3-3c0-.123-.022-.24-.036-.359l6.036-3.023c.521.597 1.21 1.035 2 1.24v5.326c-1.162.415-2 1.514-2 2.816 0 1.654 1.346 3 3 3s3-1.346 3-3c0-1.302-.838-2.401-2-2.816v-5.326c.79-.205 1.478-.643 2-1.24l6.037 3.022c-.015.12-.037.237-.037.36 0 1.654 1.346 3 3 3s3-1.346 3-3-1.346-3-3-3zm0-10c.551 0 1 .449 1 1s-.449 1-1 1-1-.449-1-1 .449-1 1-1zm-24 2c-.551 0-1-.449-1-1s.449-1 1-1 1 .449 1 1-.449 1-1 1zm0 12c-.551 0-1-.449-1-1s.449-1 1-1 1 .449 1 1-.449 1-1 1zm12-20c.551 0 1 .449 1 1s-.449 1-1 1-1-.449-1-1 .449-1 1-1zm0 26c-.551 0-1-.449-1-1s.449-1 1-1 1 .449 1 1-.449 1-1 1zm0-11c-1.103 0-2-.897-2-2s.897-2 2-2 2 .897 2 2-.897 2-2 2zm12 5c-.551 0-1-.449-1-1s.449-1 1-1 1 .449 1 1-.449 1-1 1z"/></g></svg>
|
||||
<svg fill="currentColor" height="512" viewBox="0 0 32 32" width="512" xmlns="http://www.w3.org/2000/svg"><g id="_x30_6_network"><path d="m28 19c-.809 0-1.54.325-2.08.847l-6.011-3.01c.058-.271.091-.55.091-.837s-.033-.566-.091-.837l6.011-3.01c.54.522 1.271.847 2.08.847 1.654 0 3-1.346 3-3s-1.346-3-3-3-3 1.346-3 3c0 .123.022.24.036.359l-6.036 3.023c-.521-.597-1.21-1.035-2-1.24v-5.326c1.162-.415 2-1.514 2-2.816 0-1.654-1.346-3-3-3s-3 1.346-3 3c0 1.302.838 2.401 2 2.815v5.327c-.79.205-1.478.643-2 1.24l-6.037-3.022c.015-.12.037-.237.037-.36 0-1.654-1.346-3-3-3s-3 1.346-3 3 1.346 3 3 3c.809 0 1.54-.325 2.08-.847l6.011 3.01c-.058.271-.091.55-.091.837s.033.566.091.837l-6.011 3.01c-.54-.522-1.271-.847-2.08-.847-1.654 0-3 1.346-3 3s1.346 3 3 3 3-1.346 3-3c0-.123-.022-.24-.036-.359l6.036-3.023c.521.597 1.21 1.035 2 1.24v5.326c-1.162.415-2 1.514-2 2.816 0 1.654 1.346 3 3 3s3-1.346 3-3c0-1.302-.838-2.401-2-2.816v-5.326c.79-.205 1.478-.643 2-1.24l6.037 3.022c-.015.12-.037.237-.037.36 0 1.654 1.346 3 3 3s3-1.346 3-3-1.346-3-3-3zm0-10c.551 0 1 .449 1 1s-.449 1-1 1-1-.449-1-1 .449-1 1-1zm-24 2c-.551 0-1-.449-1-1s.449-1 1-1 1 .449 1 1-.449 1-1 1zm0 12c-.551 0-1-.449-1-1s.449-1 1-1 1 .449 1 1-.449 1-1 1zm12-20c.551 0 1 .449 1 1s-.449 1-1 1-1-.449-1-1 .449-1 1-1zm0 26c-.551 0-1-.449-1-1s.449-1 1-1 1 .449 1 1-.449 1-1 1zm0-11c-1.103 0-2-.897-2-2s.897-2 2-2 2 .897 2 2-.897 2-2 2zm12 5c-.551 0-1-.449-1-1s.449-1 1-1 1 .449 1 1-.449 1-1 1z"/></g></svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
|
@ -1 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 64 64"><path d="m56.4 47.6-6-6c-.8-.8-2-.8-2.8 0s-.8 2 0 2.8l2.6 2.6H18.5c-3.6 0-6.5-2.9-6.5-6.5s2.9-6.5 6.5-6.5h27C51.3 34 56 29.3 56 23.5S51.3 13 45.5 13H22.7c-.9-3.4-4-6-7.7-6-4.4 0-8 3.6-8 8s3.6 8 8 8c3.7 0 6.8-2.6 7.7-6h22.8c3.6 0 6.5 2.9 6.5 6.5S49.1 30 45.5 30h-27C12.7 30 8 34.7 8 40.5S12.7 51 18.5 51h31.7l-2.6 2.6c-.8.8-.8 2 0 2.8.4.4.9.6 1.4.6s1-.2 1.4-.6l6-6c.8-.8.8-2 0-2.8M15 19c-2.2 0-4-1.8-4-4s1.8-4 4-4 4 1.8 4 4-1.8 4-4 4"/></svg>
|
||||
<svg fill="currentColor" xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 64 64"><path d="m56.4 47.6-6-6c-.8-.8-2-.8-2.8 0s-.8 2 0 2.8l2.6 2.6H18.5c-3.6 0-6.5-2.9-6.5-6.5s2.9-6.5 6.5-6.5h27C51.3 34 56 29.3 56 23.5S51.3 13 45.5 13H22.7c-.9-3.4-4-6-7.7-6-4.4 0-8 3.6-8 8s3.6 8 8 8c3.7 0 6.8-2.6 7.7-6h22.8c3.6 0 6.5 2.9 6.5 6.5S49.1 30 45.5 30h-27C12.7 30 8 34.7 8 40.5S12.7 51 18.5 51h31.7l-2.6 2.6c-.8.8-.8 2 0 2.8.4.4.9.6 1.4.6s1-.2 1.4-.6l6-6c.8-.8.8-2 0-2.8M15 19c-2.2 0-4-1.8-4-4s1.8-4 4-4 4 1.8 4 4-1.8 4-4 4"/></svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 527 B After Width: | Height: | Size: 547 B |
|
|
@ -1 +1 @@
|
|||
<svg height="437pt" viewBox="0 0 437.004 437" width="437pt" xmlns="http://www.w3.org/2000/svg"><path d="M229 14.645A50.173 50.173 0 0 0 192.371.015L52.293 3.586C25.672 4.25 4.246 25.673 3.582 52.298L.016 192.37a50.215 50.215 0 0 0 14.625 36.633l193.367 193.36c19.539 19.495 51.168 19.495 70.707 0l143.644-143.645c19.528-19.524 19.528-51.184 0-70.711zm179.219 249.933-143.645 143.64c-11.722 11.7-30.703 11.7-42.426 0L28.785 214.86a30.131 30.131 0 0 1-8.777-21.98l3.566-140.074c.403-15.973 13.254-28.828 29.227-29.227l140.074-3.57c.254-.004.5-.008.754-.008a30.129 30.129 0 0 1 21.223 8.79l193.367 193.362c11.695 11.723 11.695 30.703 0 42.426zm0 0"/><path d="M130.719 82.574c-26.59 0-48.145 21.555-48.149 48.145 0 26.59 21.559 48.144 48.145 48.144 26.59 0 48.144-21.554 48.144-48.144-.03-26.574-21.566-48.114-48.14-48.145zm0 76.29c-15.547 0-28.145-12.602-28.149-28.145 0-15.543 12.602-28.145 28.145-28.145s28.144 12.602 28.144 28.145c-.015 15.535-12.605 28.125-28.14 28.144zm0 0"/></svg>
|
||||
<svg fill="currentColor" height="437pt" viewBox="0 0 437.004 437" width="437pt" xmlns="http://www.w3.org/2000/svg"><path d="M229 14.645A50.173 50.173 0 0 0 192.371.015L52.293 3.586C25.672 4.25 4.246 25.673 3.582 52.298L.016 192.37a50.215 50.215 0 0 0 14.625 36.633l193.367 193.36c19.539 19.495 51.168 19.495 70.707 0l143.644-143.645c19.528-19.524 19.528-51.184 0-70.711zm179.219 249.933-143.645 143.64c-11.722 11.7-30.703 11.7-42.426 0L28.785 214.86a30.131 30.131 0 0 1-8.777-21.98l3.566-140.074c.403-15.973 13.254-28.828 29.227-29.227l140.074-3.57c.254-.004.5-.008.754-.008a30.129 30.129 0 0 1 21.223 8.79l193.367 193.362c11.695 11.723 11.695 30.703 0 42.426zm0 0"/><path d="M130.719 82.574c-26.59 0-48.145 21.555-48.149 48.145 0 26.59 21.559 48.144 48.145 48.144 26.59 0 48.144-21.554 48.144-48.144-.03-26.574-21.566-48.114-48.14-48.145zm0 76.29c-15.547 0-28.145-12.602-28.149-28.145 0-15.543 12.602-28.145 28.145-28.145s28.144 12.602 28.144 28.145c-.015 15.535-12.605 28.125-28.14 28.144zm0 0"/></svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 984 B After Width: | Height: | Size: 1,005 B |
|
|
@ -1 +1 @@
|
|||
<svg clip-rule="evenodd" fill-rule="evenodd" height="512" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 24 24" width="512" xmlns="http://www.w3.org/2000/svg"><path d="M19.393 10.825a.75.75 0 0 1 1.458-.352c.181.75.277 1.533.277 2.338 0 5.485-4.453 9.939-9.939 9.939-5.485 0-9.939-4.454-9.939-9.939 0-5.486 4.454-9.939 9.939-9.939.805 0 1.588.096 2.338.277a.75.75 0 1 1-.352 1.458A8.442 8.442 0 0 0 2.75 12.811a8.442 8.442 0 0 0 8.439 8.439 8.442 8.442 0 0 0 8.204-10.425z"/><path d="M14.764 12.811a.75.75 0 0 1 1.5 0c0 2.8-2.274 5.074-5.075 5.074a5.077 5.077 0 0 1-5.074-5.074 5.077 5.077 0 0 1 5.074-5.075.75.75 0 0 1 0 1.5 3.575 3.575 0 1 0 3.575 3.575zm7.766-7.223-3.057 3.058a.75.75 0 0 1-.531.22h-3.058a.75.75 0 0 1-.75-.75V5.058a.75.75 0 0 1 .22-.531l3.058-3.057a.75.75 0 0 1 1.242.293L20.3 3.7l1.937.646a.75.75 0 0 1 .293 1.242zm-1.918-.202-1.142-.381a.753.753 0 0 1-.475-.475l-.381-1.142-1.98 1.98v1.998h1.998z"/><path d="M15.354 7.585a.75.75 0 1 1 1.061 1.061l-4.587 4.586a.749.749 0 1 1-1.06-1.06z"/></svg>
|
||||
<svg fill="currentColor" clip-rule="evenodd" fill-rule="evenodd" height="512" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 24 24" width="512" xmlns="http://www.w3.org/2000/svg"><path d="M19.393 10.825a.75.75 0 0 1 1.458-.352c.181.75.277 1.533.277 2.338 0 5.485-4.453 9.939-9.939 9.939-5.485 0-9.939-4.454-9.939-9.939 0-5.486 4.454-9.939 9.939-9.939.805 0 1.588.096 2.338.277a.75.75 0 1 1-.352 1.458A8.442 8.442 0 0 0 2.75 12.811a8.442 8.442 0 0 0 8.439 8.439 8.442 8.442 0 0 0 8.204-10.425z"/><path d="M14.764 12.811a.75.75 0 0 1 1.5 0c0 2.8-2.274 5.074-5.075 5.074a5.077 5.077 0 0 1-5.074-5.074 5.077 5.077 0 0 1 5.074-5.075.75.75 0 0 1 0 1.5 3.575 3.575 0 1 0 3.575 3.575zm7.766-7.223-3.057 3.058a.75.75 0 0 1-.531.22h-3.058a.75.75 0 0 1-.75-.75V5.058a.75.75 0 0 1 .22-.531l3.058-3.057a.75.75 0 0 1 1.242.293L20.3 3.7l1.937.646a.75.75 0 0 1 .293 1.242zm-1.918-.202-1.142-.381a.753.753 0 0 1-.475-.475l-.381-1.142-1.98 1.98v1.998h1.998z"/><path d="M15.354 7.585a.75.75 0 1 1 1.061 1.061l-4.587 4.586a.749.749 0 1 1-1.06-1.06z"/></svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 1 KiB After Width: | Height: | Size: 1 KiB |
|
|
@ -1 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="512pt" height="512pt" viewBox="-56 0 512 512"><path d="M267 236.375c36.254-22.582 60.434-62.797 60.434-108.563C327.434 57.337 270.098 0 199.62 0 129.145 0 71.81 57.336 71.81 127.813c0 45.765 24.18 85.976 60.43 108.558C55.222 264.071 0 337.84 0 424.273v72.243C0 505.066 6.934 512 15.484 512H383.75c8.55 0 15.48-6.934 15.48-15.484v-72.243c0-86.43-55.218-160.195-132.23-187.898zm101.266 244.656H30.969v-56.758c0-92.992 75.652-168.644 168.648-168.644 92.992 0 168.649 75.652 168.649 168.644zm-71.801-353.219c0 53.403-43.442 96.848-96.844 96.848s-96.844-43.445-96.844-96.847c0-53.399 43.442-96.844 96.844-96.844s96.844 43.445 96.844 96.844zm0 0"/></svg>
|
||||
|
Before Width: | Height: | Size: 695 B |
|
|
@ -4,15 +4,14 @@ import { Logo } from '@/components/icons';
|
|||
|
||||
export interface EmptyPlaceholderProps {
|
||||
message?: string;
|
||||
icon?: ReactNode;
|
||||
children?: ReactNode;
|
||||
}
|
||||
|
||||
export function EmptyPlaceholder({ message, children }: EmptyPlaceholderProps) {
|
||||
export function EmptyPlaceholder({ message, icon, children }: EmptyPlaceholderProps) {
|
||||
return (
|
||||
<Column alignItems="center" justifyContent="center" gap="5" height="100%" width="100%">
|
||||
<Icon size="xl" fillColor="3" strokeColor="3">
|
||||
<Logo />
|
||||
</Icon>
|
||||
<Icon size="xl">{icon || <Logo />}</Icon>
|
||||
<Text>{message}</Text>
|
||||
<div>{children}</div>
|
||||
</Column>
|
||||
|
|
|
|||
|
|
@ -1,15 +0,0 @@
|
|||
.error {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
margin: auto;
|
||||
display: flex;
|
||||
background-color: var(--base50);
|
||||
padding: 10px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.icon {
|
||||
margin-inline-end: 10px;
|
||||
}
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
import { Icon, Text } from '@umami/react-zen';
|
||||
import styles from './ErrorMessage.module.css';
|
||||
import { Icon, Text, Row } from '@umami/react-zen';
|
||||
import { useMessages } from '@/components/hooks';
|
||||
import { Alert } from '@/components/icons';
|
||||
|
||||
|
|
@ -7,11 +6,11 @@ export function ErrorMessage() {
|
|||
const { formatMessage, messages } = useMessages();
|
||||
|
||||
return (
|
||||
<div className={styles.error}>
|
||||
<Icon className={styles.icon} size="lg">
|
||||
<Row alignItems="center" justifyContent="center" gap>
|
||||
<Icon>
|
||||
<Alert />
|
||||
</Icon>
|
||||
<Text>{formatMessage(messages.error)}</Text>
|
||||
</div>
|
||||
</Row>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,4 @@
|
|||
import {
|
||||
Grid,
|
||||
Row,
|
||||
Column,
|
||||
TextField,
|
||||
Label,
|
||||
ListItem,
|
||||
Select,
|
||||
Icon,
|
||||
Button,
|
||||
} from '@umami/react-zen';
|
||||
import { Grid, Column, TextField, Label, ListItem, Select, Icon, Button } from '@umami/react-zen';
|
||||
import { useFilters } from '@/components/hooks';
|
||||
import { Close } from '@/components/icons';
|
||||
|
||||
|
|
@ -32,10 +22,10 @@ export function FilterRecord({
|
|||
const { fields, operators } = useFilters();
|
||||
|
||||
return (
|
||||
<Grid columns="1fr auto">
|
||||
<Column>
|
||||
<Label>{fields.find(f => f.name === name)?.label}</Label>
|
||||
<Row gap alignItems="center">
|
||||
<>
|
||||
<Label>{fields.find(f => f.name === name)?.label}</Label>
|
||||
<Grid columns="1fr auto" gap>
|
||||
<Grid columns="200px 1fr" gap>
|
||||
<Select
|
||||
items={operators.filter(({ type }) => type === 'string')}
|
||||
value={operator}
|
||||
|
|
@ -50,15 +40,15 @@ export function FilterRecord({
|
|||
}}
|
||||
</Select>
|
||||
<TextField value={value} onChange={e => onChange?.(name, e.target.value)} />
|
||||
</Row>
|
||||
</Column>
|
||||
<Column justifyContent="flex-end">
|
||||
<Button variant="quiet" onPress={() => onRemove?.(name)}>
|
||||
<Icon>
|
||||
<Close />
|
||||
</Icon>
|
||||
</Button>
|
||||
</Column>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Column justifyContent="flex-end">
|
||||
<Button variant="quiet" onPress={() => onRemove?.(name)}>
|
||||
<Icon>
|
||||
<Close />
|
||||
</Icon>
|
||||
</Button>
|
||||
</Column>
|
||||
</Grid>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,36 +1,36 @@
|
|||
import { ReactNode } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { Loading } from '@umami/react-zen';
|
||||
import { Spinner, Dots } from '@umami/react-zen';
|
||||
import { ErrorMessage } from '@/components/common/ErrorMessage';
|
||||
import { Empty } from '@/components/common/Empty';
|
||||
import styles from './LoadingPanel.module.css';
|
||||
|
||||
export function LoadingPanel({
|
||||
data,
|
||||
error,
|
||||
isEmpty,
|
||||
isFetched,
|
||||
isLoading,
|
||||
loadingIcon = 'dots',
|
||||
renderEmpty = () => <Empty />,
|
||||
className,
|
||||
children,
|
||||
}: {
|
||||
data?: any;
|
||||
error?: Error;
|
||||
isEmpty?: boolean;
|
||||
isFetched?: boolean;
|
||||
isLoading?: boolean;
|
||||
loadingIcon?: 'dots' | 'spinner';
|
||||
isEmpty?: boolean;
|
||||
renderEmpty?: () => ReactNode;
|
||||
className?: string;
|
||||
children: ReactNode;
|
||||
}) {
|
||||
const isEmpty = !isLoading && isFetched && data && Array.isArray(data) && data.length === 0;
|
||||
|
||||
return (
|
||||
<div className={classNames(styles.panel, className)}>
|
||||
{isLoading && !isFetched && <Loading className={styles.loading} icon={loadingIcon} />}
|
||||
{isLoading && !isFetched && (loadingIcon === 'dots' ? <Dots /> : <Spinner />)}
|
||||
{error && <ErrorMessage />}
|
||||
{!error && isEmpty && <Empty />}
|
||||
{!error && !isEmpty && data && children}
|
||||
{!error && !isLoading && isEmpty && renderEmpty()}
|
||||
{!error && !isLoading && !isEmpty && children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
import { ReactNode } from 'react';
|
||||
import { Heading, Icon, Row, Text } from '@umami/react-zen';
|
||||
import { Heading, Icon, Row, Text, RowProps } from '@umami/react-zen';
|
||||
|
||||
export function SectionHeader({
|
||||
title,
|
||||
description,
|
||||
icon,
|
||||
children,
|
||||
...props
|
||||
}: {
|
||||
title?: string;
|
||||
description?: string;
|
||||
|
|
@ -13,9 +14,9 @@ export function SectionHeader({
|
|||
allowEdit?: boolean;
|
||||
className?: string;
|
||||
children?: ReactNode;
|
||||
}) {
|
||||
} & RowProps) {
|
||||
return (
|
||||
<Row justifyContent="space-between" alignItems="center" height="60px">
|
||||
<Row {...props} justifyContent="space-between" alignItems="center" height="60px">
|
||||
<Row gap="3" alignItems="center">
|
||||
{icon && <Icon>{icon}</Icon>}
|
||||
{title && <Heading size="3">{title}</Heading>}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,10 @@ export * from './queries/useActiveUsersQuery';
|
|||
export * from './queries/useEventDataEventsQuery';
|
||||
export * from './queries/useEventDataPropertiesQuery';
|
||||
export * from './queries/useEventDataValuesQuery';
|
||||
export * from './queries/useGoalsQuery';
|
||||
export * from './queries/useLoginQuery';
|
||||
export * from './queries/useRealtimeQuery';
|
||||
export * from './queries/useResultQuery';
|
||||
export * from './queries/useReportQuery';
|
||||
export * from './queries/useReportsQuery';
|
||||
export * from './queries/useRetentionQuery';
|
||||
|
|
|
|||
11
src/components/hooks/queries/useDeleteQuery.ts
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
import { useApi, useModified } from '@/components/hooks';
|
||||
|
||||
export function useDeleteQuery(path: string, params?: { [key: string]: any }) {
|
||||
const { del, useMutation } = useApi();
|
||||
const { mutate, isPending, error } = useMutation({
|
||||
mutationFn: () => del(path, params),
|
||||
});
|
||||
const { touch } = useModified();
|
||||
|
||||
return { mutate, isPending, error, touch };
|
||||
}
|
||||
19
src/components/hooks/queries/useGoalQuery.ts
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
import { useApi } from '../useApi';
|
||||
import { usePagedQuery } from '../usePagedQuery';
|
||||
|
||||
export function useGoalQuery(
|
||||
{ websiteId, reportId }: { websiteId: string; reportId: string },
|
||||
params?: { [key: string]: string | number },
|
||||
) {
|
||||
const { post } = useApi();
|
||||
|
||||
return usePagedQuery({
|
||||
queryKey: ['goal', { websiteId, reportId, ...params }],
|
||||
queryFn: (data: any) => {
|
||||
return post(`/reports/goals`, {
|
||||
...data,
|
||||
...params,
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
21
src/components/hooks/queries/useGoalsQuery.ts
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
import { useApi } from '../useApi';
|
||||
import { usePagedQuery } from '../usePagedQuery';
|
||||
import { useModified } from '../useModified';
|
||||
|
||||
export function useGoalsQuery(
|
||||
{ websiteId }: { websiteId: string },
|
||||
params?: { [key: string]: string | number },
|
||||
) {
|
||||
const { get } = useApi();
|
||||
const { modified } = useModified(`goals`);
|
||||
|
||||
return usePagedQuery({
|
||||
queryKey: ['goals', { websiteId, modified, ...params }],
|
||||
queryFn: (data: any) => {
|
||||
return get(`/websites/${websiteId}/goals`, {
|
||||
...data,
|
||||
...params,
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
@ -1,94 +1,16 @@
|
|||
import { produce } from 'immer';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { useApi } from '../useApi';
|
||||
import { useTimezone } from '../useTimezone';
|
||||
import { useMessages } from '../useMessages';
|
||||
import { parseDateRange } from '@/lib/date';
|
||||
import { useModified } from '../useModified';
|
||||
|
||||
export function useReportQuery(
|
||||
reportId: string,
|
||||
defaultParameters?: { type: string; parameters: { [key: string]: any } },
|
||||
) {
|
||||
const [report, setReport] = useState(null);
|
||||
const [isRunning, setIsRunning] = useState(false);
|
||||
const { get, post } = useApi();
|
||||
const { timezone } = useTimezone();
|
||||
const { formatMessage, labels } = useMessages();
|
||||
export function useReportQuery(reportId: string) {
|
||||
const { get, useQuery } = useApi();
|
||||
const { modified } = useModified(`report:${reportId}`);
|
||||
|
||||
const baseParameters = {
|
||||
name: formatMessage(labels.untitled),
|
||||
description: '',
|
||||
parameters: {},
|
||||
};
|
||||
|
||||
const loadReport = async (id: string) => {
|
||||
const data: any = await get(`/reports/${id}`);
|
||||
|
||||
const { dateRange } = data?.parameters || {};
|
||||
|
||||
data.parameters = {
|
||||
...defaultParameters?.parameters,
|
||||
...data.parameters,
|
||||
dateRange: parseDateRange(dateRange.value),
|
||||
};
|
||||
|
||||
setReport(data);
|
||||
};
|
||||
|
||||
const runReport = useCallback(
|
||||
async (parameters: { [key: string]: any }) => {
|
||||
setIsRunning(true);
|
||||
|
||||
const { type } = report;
|
||||
|
||||
const data = await post(`/reports/${type}`, { ...parameters, timezone });
|
||||
|
||||
setReport(
|
||||
produce((state: any) => {
|
||||
state.parameters = { ...defaultParameters?.parameters, ...parameters };
|
||||
state.data = data;
|
||||
|
||||
return state;
|
||||
}),
|
||||
);
|
||||
|
||||
setIsRunning(false);
|
||||
return useQuery({
|
||||
queryKey: ['report', { reportId, modified }],
|
||||
queryFn: (data: any) => {
|
||||
return get(`/reports/${reportId}`, {
|
||||
...data,
|
||||
});
|
||||
},
|
||||
[report, timezone],
|
||||
);
|
||||
|
||||
const updateReport = useCallback(
|
||||
async (data: { [x: string]: any; parameters: any }) => {
|
||||
setReport(
|
||||
produce((state: any) => {
|
||||
const { parameters, ...rest } = data;
|
||||
|
||||
if (parameters) {
|
||||
state.parameters = {
|
||||
...defaultParameters?.parameters,
|
||||
...state.parameters,
|
||||
...parameters,
|
||||
};
|
||||
}
|
||||
|
||||
for (const key in rest) {
|
||||
state[key] = rest[key];
|
||||
}
|
||||
|
||||
return state;
|
||||
}),
|
||||
);
|
||||
},
|
||||
[report],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (!reportId) {
|
||||
setReport({ ...baseParameters, ...defaultParameters });
|
||||
} else {
|
||||
loadReport(reportId);
|
||||
}
|
||||
}, [reportId]);
|
||||
|
||||
return { report, runReport, updateReport, isRunning };
|
||||
});
|
||||
}
|
||||
|
|
|
|||
17
src/components/hooks/queries/useResultQuery.ts
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
import { useApi } from '@/components/hooks';
|
||||
import { UseQueryOptions, QueryKey } from '@tanstack/react-query';
|
||||
|
||||
export function useResultQuery<T>(
|
||||
type: string,
|
||||
params?: { [key: string]: any },
|
||||
options?: Omit<UseQueryOptions<T, Error, T, QueryKey>, 'queryKey' | 'queryFn'>,
|
||||
) {
|
||||
const { post, useQuery } = useApi();
|
||||
|
||||
return useQuery<T>({
|
||||
queryKey: ['reports', type, params],
|
||||
queryFn: () => post(`/reports/${type}`, params),
|
||||
enabled: !!type,
|
||||
...options,
|
||||
});
|
||||
}
|
||||
|
|
@ -3,12 +3,14 @@ export {
|
|||
ArrowRight as Arrow,
|
||||
Calendar,
|
||||
ChevronRight as Chevron,
|
||||
Clock,
|
||||
X as Close,
|
||||
Copy,
|
||||
Edit,
|
||||
Ellipsis,
|
||||
Eye,
|
||||
ExternalLink,
|
||||
File,
|
||||
Globe,
|
||||
Grid2X2,
|
||||
LayoutDashboard,
|
||||
|
|
@ -28,6 +30,7 @@ export {
|
|||
SquarePen,
|
||||
Sun,
|
||||
Trash,
|
||||
User,
|
||||
Users,
|
||||
} from 'lucide-react';
|
||||
export * from '@/components/svg';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { useState, Key, Fragment } from 'react';
|
||||
import { Modal, Select, ListItem, ListSeparator, Dialog } from '@umami/react-zen';
|
||||
import { Modal, Select, ListItem, ListSeparator, Dialog, Row } from '@umami/react-zen';
|
||||
import { endOfYear } from 'date-fns';
|
||||
import { DatePickerForm } from '@/components/metrics/DatePickerForm';
|
||||
import { useMessages } from '@/components/hooks';
|
||||
|
|
@ -100,7 +100,7 @@ export function DateFilter({
|
|||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Row width="200px">
|
||||
<Select
|
||||
value={value}
|
||||
placeholder={formatMessage(labels.selectDate)}
|
||||
|
|
@ -131,6 +131,6 @@ export function DateFilter({
|
|||
</Dialog>
|
||||
</Modal>
|
||||
)}
|
||||
</>
|
||||
</Row>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
0
src/components/input/DeleteButton.tsx
Normal file
|
|
@ -13,9 +13,8 @@ import {
|
|||
Row,
|
||||
Box,
|
||||
} from '@umami/react-zen';
|
||||
import { User, Users } from 'lucide-react';
|
||||
import { useLoginQuery, useMessages, useTeamsQuery, useNavigation } from '@/components/hooks';
|
||||
import { Chevron } from '@/components/icons';
|
||||
import { Chevron, User, Users } from '@/components/icons';
|
||||
|
||||
export function TeamsButton({
|
||||
className,
|
||||
|
|
|
|||
|
|
@ -63,13 +63,13 @@ export function WebsiteDateFilter({
|
|||
<Row gap="3">
|
||||
{showButtons && !isAllTime && !isCustomRange && (
|
||||
<Row gap="1">
|
||||
<Button onPress={() => handleIncrement(-1)} variant="quiet">
|
||||
<Icon size="xs" rotate={180}>
|
||||
<Button onPress={() => handleIncrement(-1)} variant="outline">
|
||||
<Icon rotate={180}>
|
||||
<Chevron />
|
||||
</Icon>
|
||||
</Button>
|
||||
<Button onPress={() => handleIncrement(1)} variant="quiet" isDisabled={disableForward}>
|
||||
<Icon size="xs">
|
||||
<Button onPress={() => handleIncrement(1)} variant="outline" isDisabled={disableForward}>
|
||||
<Icon>
|
||||
<Chevron />
|
||||
</Icon>
|
||||
</Button>
|
||||
|
|
@ -86,10 +86,16 @@ export function WebsiteDateFilter({
|
|||
{!isAllTime && compare && (
|
||||
<Row alignItems="center" gap>
|
||||
<Text weight="bold">VS</Text>
|
||||
<Select value={compare} onChange={handleSelect} popoverProps={{ style: { width: 200 } }}>
|
||||
<ListItem id="prev">{formatMessage(labels.previousPeriod)}</ListItem>
|
||||
<ListItem id="yoy">{formatMessage(labels.previousYear)}</ListItem>
|
||||
</Select>
|
||||
<Row width="200px">
|
||||
<Select
|
||||
value={compare}
|
||||
onChange={handleSelect}
|
||||
popoverProps={{ style: { width: 200 } }}
|
||||
>
|
||||
<ListItem id="prev">{formatMessage(labels.previousPeriod)}</ListItem>
|
||||
<ListItem id="yoy">{formatMessage(labels.previousYear)}</ListItem>
|
||||
</Select>
|
||||
</Row>
|
||||
</Row>
|
||||
)}
|
||||
{!isAllTime && allowCompare && (
|
||||
|
|
|
|||
|
|
@ -107,6 +107,7 @@ export const labels = defineMessages({
|
|||
sum: { id: 'label.sum', defaultMessage: 'Sum' },
|
||||
event: { id: 'label.event', defaultMessage: 'Event' },
|
||||
events: { id: 'label.events', defaultMessage: 'Events' },
|
||||
eventName: { id: 'label.event-name', defaultMessage: 'Event name' },
|
||||
query: { id: 'label.query', defaultMessage: 'Query' },
|
||||
queryParameters: { id: 'label.query-parameters', defaultMessage: 'Query parameters' },
|
||||
back: { id: 'label.back', defaultMessage: 'Back' },
|
||||
|
|
@ -268,7 +269,8 @@ export const labels = defineMessages({
|
|||
id: 'label.utm-description',
|
||||
defaultMessage: 'Track your campaigns through UTM parameters.',
|
||||
},
|
||||
conversionStep: { id: 'label.conversion-step', defaultMessage: 'Conversion Step' },
|
||||
conversionStep: { id: 'label.conversion-step', defaultMessage: 'Conversion step' },
|
||||
conversionRate: { id: 'label.conversion-ratep', defaultMessage: 'Conversion rate' },
|
||||
steps: { id: 'label.steps', defaultMessage: 'Steps' },
|
||||
startStep: { id: 'label.start-step', defaultMessage: 'Start Step' },
|
||||
endStep: { id: 'label.end-step', defaultMessage: 'End Step' },
|
||||
|
|
|
|||
|
|
@ -1,7 +1,14 @@
|
|||
import * as React from 'react';
|
||||
import type { SVGProps } from 'react';
|
||||
const SvgFunnel = (props: SVGProps<SVGSVGElement>) => (
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width={512} height={512} viewBox="0 0 32 32" {...props}>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width={512}
|
||||
height={512}
|
||||
fill="currentColor"
|
||||
viewBox="0 0 32 32"
|
||||
{...props}
|
||||
>
|
||||
<path d="M29 11H3a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h26a1 1 0 0 1 1 1v6a1 1 0 0 1-1 1M4 9h24V5H4z" />
|
||||
<path d="M25 17H7a1 1 0 0 1-1-1v-6a1 1 0 0 1 1-1h18a1 1 0 0 1 1 1v6a1 1 0 0 1-1 1M8 15h16v-4H8z" />
|
||||
<path d="M22 23H10a1 1 0 0 1-1-1v-6a1 1 0 0 1 1-1h12a1 1 0 0 1 1 1v6a1 1 0 0 1-1 1m-11-2h10v-4H11z" />
|
||||
|
|
|
|||
|
|
@ -1,7 +1,13 @@
|
|||
import * as React from 'react';
|
||||
import type { SVGProps } from 'react';
|
||||
const SvgLightbulb = (props: SVGProps<SVGSVGElement>) => (
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlSpace="preserve" viewBox="0 0 512 512" {...props}>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlSpace="preserve"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 512 512"
|
||||
{...props}
|
||||
>
|
||||
<path d="M223.718 124.76c-48.027 11.198-86.688 49.285-98.494 97.031-11.843 47.899 1.711 96.722 36.259 130.601C173.703 364.377 181 383.586 181 403.777V407c0 13.296 5.801 25.26 15 33.505V467c0 24.813 20.187 45 45 45h30c24.813 0 45-20.187 45-45v-26.495c9.199-8.245 15-20.208 15-33.505v-3.282c0-19.884 7.687-39.458 20.563-52.361C376.994 325.87 391 292.005 391 256c0-86.079-79.769-151.638-167.282-131.24M286 467c0 8.271-6.729 15-15 15h-30c-8.271 0-15-6.729-15-15v-15h60zm44.326-136.834C311.689 348.843 301 375.651 301 403.718V407c0 8.271-6.729 15-15 15h-60c-8.271 0-15-6.729-15-15v-3.223c0-28.499-10.393-55.035-28.513-72.804-26.89-26.37-37.409-64.493-28.141-101.981 9.125-36.907 39.029-66.353 76.184-75.015C299.202 137.964 361 189.228 361 256c0 28.004-10.894 54.343-30.674 74.166M139.327 118.114 96.9 75.688c-5.857-5.858-15.355-5.858-21.213 0s-5.858 15.355 0 21.213l42.427 42.426c5.857 5.858 15.356 5.858 21.213 0s5.858-15.355 0-21.213M76 241H15c-8.284 0-15 6.716-15 15s6.716 15 15 15h61c8.284 0 15-6.716 15-15s-6.716-15-15-15m421 0h-61c-8.284 0-15 6.716-15 15s6.716 15 15 15h61c8.284 0 15-6.716 15-15s-6.716-15-15-15M436.313 75.688c-5.856-5.858-15.354-5.858-21.213 0l-42.427 42.426c-5.858 5.857-5.858 15.355 0 21.213s15.355 5.858 21.213 0l42.427-42.426c5.858-5.857 5.858-15.355 0-21.213M256 0c-8.284 0-15 6.716-15 15v61c0 8.284 6.716 15 15 15s15-6.716 15-15V15c0-8.284-6.716-15-15-15" />
|
||||
<path d="M256 181c-6.166 0-12.447.739-18.658 2.194-25.865 6.037-47.518 27.328-53.879 52.979-1.994 8.041 2.907 16.175 10.947 18.17 8.042 1.994 16.176-2.909 18.17-10.948 3.661-14.758 16.647-27.5 31.593-30.989 3.982-.933 7.962-1.406 11.827-1.406 8.284 0 15-6.716 15-15s-6.716-15-15-15" />
|
||||
</svg>
|
||||
|
|
|
|||
|
|
@ -5,19 +5,13 @@ const SvgLogo = (props: SVGProps<SVGSVGElement>) => (
|
|||
xmlns="http://www.w3.org/2000/svg"
|
||||
width={20}
|
||||
height={20}
|
||||
fill="currentColor"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 428 389.11"
|
||||
{...props}
|
||||
>
|
||||
<circle
|
||||
cx={214.15}
|
||||
cy={181}
|
||||
r={171}
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeMiterlimit={10}
|
||||
strokeWidth={20}
|
||||
/>
|
||||
<path d="M413 134.11H15.29a15 15 0 0 0-15 15v15.3C.12 168 0 171.52 0 175.11c0 118.19 95.81 214 214 214 116.4 0 211.1-92.94 213.93-208.67 0-.44.07-.88.07-1.33v-30a15 15 0 0 0-15-15" />
|
||||
<circle cx={214.15} cy={181} r={171} fill="none" strokeMiterlimit={10} strokeWidth={20} />
|
||||
<path d="M413 134.11H15.29a15 15 0 0 0-15 15v15.3C.12 168 0 171.52 0 175.11c0 118.19 95.81 214 214 214 116.4 0 211.1-92.94 213.93-208.67 0-.44.07-.88.07-1.33v-30a15 15 0 0 0-15-15Z" />
|
||||
</svg>
|
||||
);
|
||||
export default SvgLogo;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ const SvgMagnet = (props: SVGProps<SVGSVGElement>) => (
|
|||
xmlns="http://www.w3.org/2000/svg"
|
||||
width={512}
|
||||
height={512}
|
||||
fill="currentColor"
|
||||
viewBox="0 0 508.467 508.467"
|
||||
{...props}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,13 @@
|
|||
import * as React from 'react';
|
||||
import type { SVGProps } from 'react';
|
||||
const SvgMoney = (props: SVGProps<SVGSVGElement>) => (
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlSpace="preserve" viewBox="0 0 512 512" {...props}>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlSpace="preserve"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 512 512"
|
||||
{...props}
|
||||
>
|
||||
<path d="M347 302c8.271 0 15 6.639 15 14.8h30c0-19.468-12.541-36.067-30-42.231V242h-30v32.58c-17.459 6.192-30 22.865-30 42.42 0 24.813 20.187 45 45 45 8.271 0 15 6.729 15 15s-6.729 15-15 15-15-6.729-15-15h-30c0 19.555 12.541 36.228 30 42.42v32.38h30v-32.38c17.459-6.192 30-22.865 30-42.42 0-24.813-20.187-45-45-45-8.271 0-15-6.729-15-15s6.729-15 15-15" />
|
||||
<path d="M347 182c-5.057 0-10.058.242-15 .689V90c0-26.011-18.548-49.61-52.226-66.449C249.4 8.364 209.35 0 167 0 124.564 0 84.193 8.347 53.323 23.502 18.938 40.385 0 64 0 90v272c0 26 18.938 49.616 53.323 66.498C84.193 443.653 124.564 452 167 452c17.009 0 33.647-1.358 49.615-4.004C246.826 486.909 294.035 512 347 512c90.981 0 165-74.019 165-165s-74.019-165-165-165M66.545 50.432C92.992 37.447 129.606 30 167 30c79.558 0 135 31.621 135 60s-55.442 60-135 60c-37.394 0-74.008-7.447-100.455-20.432C43.32 118.166 30 103.744 30 90s13.32-28.166 36.545-39.568M30 142.265c6.724 5.137 14.512 9.907 23.323 14.233C84.193 171.653 124.564 180 167 180c42.35 0 82.4-8.364 112.774-23.551 8.359-4.18 15.783-8.776 22.226-13.722v45.51c-29.896 8.485-56.359 25.209-76.778 47.548C206.946 239.908 187.386 242 167 242c-37.394 0-74.008-7.447-100.455-20.432C43.32 210.166 30 195.744 30 182zm0 92c6.724 5.137 14.512 9.907 23.323 14.233C84.193 263.653 124.564 272 167 272c11.581 0 22.942-.621 34.021-1.839a163.7 163.7 0 0 0-18.293 61.395c-5.211.286-10.465.444-15.728.444-37.394 0-74.008-7.447-100.455-20.432C43.32 300.166 30 285.744 30 272zM167 422c-37.394 0-74.008-7.447-100.455-20.432C43.32 390.166 30 375.744 30 362v-37.736c6.724 5.137 14.512 9.907 23.323 14.233C84.193 353.653 124.564 362 167 362c5.23 0 10.459-.132 15.654-.388a163.7 163.7 0 0 0 16.486 58.557A281 281 0 0 1 167 422m180 60c-74.439 0-135-60.561-135-135s60.561-135 135-135 135 60.561 135 135-60.561 135-135 135" />
|
||||
</svg>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,14 @@
|
|||
import * as React from 'react';
|
||||
import type { SVGProps } from 'react';
|
||||
const SvgNetwork = (props: SVGProps<SVGSVGElement>) => (
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width={512} height={512} viewBox="0 0 32 32" {...props}>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width={512}
|
||||
height={512}
|
||||
fill="currentColor"
|
||||
viewBox="0 0 32 32"
|
||||
{...props}
|
||||
>
|
||||
<path d="M28 19c-.809 0-1.54.325-2.08.847l-6.011-3.01c.058-.271.091-.55.091-.837s-.033-.566-.091-.837l6.011-3.01c.54.522 1.271.847 2.08.847 1.654 0 3-1.346 3-3s-1.346-3-3-3-3 1.346-3 3c0 .123.022.24.036.359L19 13.382a3.98 3.98 0 0 0-2-1.24V6.816A3 3 0 0 0 19 4c0-1.654-1.346-3-3-3s-3 1.346-3 3c0 1.302.838 2.401 2 2.815v5.327a4 4 0 0 0-2 1.24L6.963 10.36c.015-.12.037-.237.037-.36 0-1.654-1.346-3-3-3s-3 1.346-3 3 1.346 3 3 3c.809 0 1.54-.325 2.08-.847l6.011 3.01q-.089.407-.091.837c-.002.43.033.566.091.837l-6.011 3.01A2.98 2.98 0 0 0 4 19c-1.654 0-3 1.346-3 3s1.346 3 3 3 3-1.346 3-3c0-.123-.022-.24-.036-.359L13 18.618a3.98 3.98 0 0 0 2 1.24v5.326A3 3 0 0 0 13 28c0 1.654 1.346 3 3 3s3-1.346 3-3a3 3 0 0 0-2-2.816v-5.326a4 4 0 0 0 2-1.24l6.037 3.022c-.015.12-.037.237-.037.36 0 1.654 1.346 3 3 3s3-1.346 3-3-1.346-3-3-3m0-10c.551 0 1 .449 1 1s-.449 1-1 1-1-.449-1-1 .449-1 1-1M4 11c-.551 0-1-.449-1-1s.449-1 1-1 1 .449 1 1-.449 1-1 1m0 12c-.551 0-1-.449-1-1s.449-1 1-1 1 .449 1 1-.449 1-1 1M16 3c.551 0 1 .449 1 1s-.449 1-1 1-1-.449-1-1 .449-1 1-1m0 26c-.551 0-1-.449-1-1s.449-1 1-1 1 .449 1 1-.449 1-1 1m0-11c-1.103 0-2-.897-2-2s.897-2 2-2 2 .897 2 2-.897 2-2 2m12 5c-.551 0-1-.449-1-1s.449-1 1-1 1 .449 1 1-.449 1-1 1" />
|
||||
</svg>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,14 @@
|
|||
import * as React from 'react';
|
||||
import type { SVGProps } from 'react';
|
||||
const SvgPath = (props: SVGProps<SVGSVGElement>) => (
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width={512} height={512} viewBox="0 0 64 64" {...props}>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width={512}
|
||||
height={512}
|
||||
fill="currentColor"
|
||||
viewBox="0 0 64 64"
|
||||
{...props}
|
||||
>
|
||||
<path d="m56.4 47.6-6-6c-.8-.8-2-.8-2.8 0s-.8 2 0 2.8l2.6 2.6H18.5c-3.6 0-6.5-2.9-6.5-6.5s2.9-6.5 6.5-6.5h27C51.3 34 56 29.3 56 23.5S51.3 13 45.5 13H22.7c-.9-3.4-4-6-7.7-6-4.4 0-8 3.6-8 8s3.6 8 8 8c3.7 0 6.8-2.6 7.7-6h22.8c3.6 0 6.5 2.9 6.5 6.5S49.1 30 45.5 30h-27C12.7 30 8 34.7 8 40.5S12.7 51 18.5 51h31.7l-2.6 2.6c-.8.8-.8 2 0 2.8.4.4.9.6 1.4.6s1-.2 1.4-.6l6-6c.8-.8.8-2 0-2.8M15 19c-2.2 0-4-1.8-4-4s1.8-4 4-4 4 1.8 4 4-1.8 4-4 4" />
|
||||
</svg>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ const SvgTag = (props: SVGProps<SVGSVGElement>) => (
|
|||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="437pt"
|
||||
height="437pt"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 437.004 437"
|
||||
{...props}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ const SvgTarget = (props: SVGProps<SVGSVGElement>) => (
|
|||
xmlns="http://www.w3.org/2000/svg"
|
||||
width={512}
|
||||
height={512}
|
||||
fill="currentColor"
|
||||
fillRule="evenodd"
|
||||
strokeLinejoin="round"
|
||||
strokeMiterlimit={2}
|
||||
|
|
|
|||
|
|
@ -1,14 +0,0 @@
|
|||
import * as React from 'react';
|
||||
import type { SVGProps } from 'react';
|
||||
const SvgUser = (props: SVGProps<SVGSVGElement>) => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="512pt"
|
||||
height="512pt"
|
||||
viewBox="-56 0 512 512"
|
||||
{...props}
|
||||
>
|
||||
<path d="M267 236.375c36.254-22.582 60.434-62.797 60.434-108.563C327.434 57.337 270.098 0 199.62 0 129.145 0 71.81 57.336 71.81 127.813c0 45.765 24.18 85.976 60.43 108.558C55.222 264.071 0 337.84 0 424.273v72.243C0 505.066 6.934 512 15.484 512H383.75c8.55 0 15.48-6.934 15.48-15.484v-72.243c0-86.43-55.218-160.195-132.23-187.898m101.266 244.656H30.969v-56.758c0-92.992 75.652-168.644 168.648-168.644 92.992 0 168.649 75.652 168.649 168.644zm-71.801-353.219c0 53.403-43.442 96.848-96.844 96.848s-96.844-43.445-96.844-96.847c0-53.399 43.442-96.844 96.844-96.844s96.844 43.445 96.844 96.844zm0 0" />
|
||||
</svg>
|
||||
);
|
||||
export default SvgUser;
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
import * as React from 'react';
|
||||
import type { SVGProps } from 'react';
|
||||
const SvgUsers = (props: SVGProps<SVGSVGElement>) => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlSpace="preserve"
|
||||
viewBox="0 0 477.869 477.869"
|
||||
{...props}
|
||||
>
|
||||
<path d="M387.415 233.496c48.976-44.029 52.987-119.424 8.958-168.4C355.991 20.177 288.4 12.546 239.02 47.332c-53.83-37.99-128.264-25.149-166.254 28.68-34.859 49.393-27.259 117.054 17.689 157.483C34.606 262.935-.251 320.976.002 384.108v51.2c0 9.426 7.641 17.067 17.067 17.067h443.733c9.426 0 17.067-7.641 17.067-17.067v-51.2c.252-63.132-34.605-121.173-90.454-150.612M307.201 59.842c47.062-.052 85.256 38.057 85.309 85.119.037 33.564-19.631 64.023-50.237 77.799-1.314.597-2.628 1.143-3.959 1.707a83.7 83.7 0 0 1-12.988 4.045c-.853.188-1.707.29-2.577.461a85.4 85.4 0 0 1-15.019 1.519c-2.27 0-4.557-.171-6.827-.375-.853 0-1.707 0-2.56-.171a86.2 86.2 0 0 1-27.904-8.226c-.324-.154-.7-.137-1.024-.273-1.707-.819-3.413-1.536-4.932-2.458.137-.171.222-.358.358-.529a119.7 119.7 0 0 0 18.278-33.297l.529-1.434a120.4 120.4 0 0 0 4.523-17.562c.154-.87.273-1.707.41-2.645.987-6.067 1.506-12.2 1.553-18.347a120 120 0 0 0-1.553-18.313c-.137-.887-.256-1.707-.41-2.645a120.4 120.4 0 0 0-4.523-17.562l-.529-1.434a119.8 119.8 0 0 0-18.278-33.297c-.137-.171-.222-.358-.358-.529a84.8 84.8 0 0 1 42.718-11.553M85.335 145.176c-.121-47.006 37.886-85.21 84.892-85.331a85.1 85.1 0 0 1 59.134 23.686c.99.956 1.963 1.911 2.918 2.901a88 88 0 0 1 8.09 9.813c.751 1.058 1.434 2.185 2.133 3.277a84 84 0 0 1 6.263 11.52c.427.973.751 1.963 1.126 2.935a83.4 83.4 0 0 1 4.233 13.653c.12.512.154 1.024.256 1.553a80.3 80.3 0 0 1 0 32.119c-.102.529-.137 1.041-.256 1.553a83 83 0 0 1-4.233 13.653c-.375.973-.7 1.963-1.126 2.935a84 84 0 0 1-6.263 11.503c-.7 1.092-1.382 2.219-2.133 3.277a87.6 87.6 0 0 1-8.09 9.813c-.956.99-1.929 1.946-2.918 2.901a85.2 85.2 0 0 1-23.569 15.906 49 49 0 0 1-4.198 1.707 86 86 0 0 1-12.663 3.925c-1.075.239-2.185.375-3.277.563a84.7 84.7 0 0 1-14.046 1.417h-1.877a84.6 84.6 0 0 1-14.046-1.417c-1.092-.188-2.202-.324-3.277-.563a86 86 0 0 1-12.663-3.925c-1.417-.563-2.816-1.143-4.198-1.707-30.534-13.786-50.173-44.166-50.212-77.667m221.866 273.066H34.135v-34.133c-.25-57.833 36.188-109.468 90.76-128.614a119.1 119.1 0 0 0 91.546 0 137 137 0 0 1 16.623 7.356c3.55 1.826 6.827 3.908 10.24 6.007 2.219 1.382 4.471 2.731 6.605 4.25 3.294 2.338 6.4 4.881 9.455 7.492 1.963 1.707 3.908 3.413 5.751 5.12 2.816 2.662 5.461 5.478 8.004 8.363a135 135 0 0 1 5.291 6.383 133 133 0 0 1 6.349 8.823c1.707 2.56 3.226 5.222 4.727 7.885 1.707 2.935 3.277 5.871 4.71 8.926 1.434 3.055 2.697 6.4 3.925 9.66 1.075 2.833 2.219 5.649 3.106 8.533 1.195 3.959 2.031 8.055 2.867 12.151.512 2.423 1.178 4.796 1.553 7.253a141 141 0 0 1 1.553 20.412v34.133zm136.534 0h-102.4v-34.133c0-5.342-.307-10.633-.785-15.872-.137-1.536-.375-3.055-.546-4.591-.461-3.772-.99-7.509-1.707-11.213a247 247 0 0 0-.973-4.762q-1.228-5.7-2.85-11.298c-.358-1.229-.683-2.475-1.058-3.686a169.1 169.1 0 0 0-20.565-43.127l-.666-.973a169 169 0 0 0-9.404-12.646l-.119-.154a155 155 0 0 0-11.008-12.237h.7a121 121 0 0 0 14.524 1.024h.939c4.496-.039 8.985-.33 13.449-.87 1.399-.171 2.782-.427 4.181-.649a117 117 0 0 0 10.752-2.167c1.007-.256 2.031-.495 3.055-.785a116 116 0 0 0 13.653-4.642c54.612 19.127 91.083 70.785 90.829 128.649v34.132z" />
|
||||
</svg>
|
||||
);
|
||||
export default SvgUsers;
|
||||
|
|
@ -4,7 +4,6 @@ export { default as Bars } from './Bars';
|
|||
export { default as Bolt } from './Bolt';
|
||||
export { default as Bookmark } from './Bookmark';
|
||||
export { default as Change } from './Change';
|
||||
export { default as Clock } from './Clock';
|
||||
export { default as Compare } from './Compare';
|
||||
export { default as Dashboard } from './Dashboard';
|
||||
export { default as Expand } from './Expand';
|
||||
|
|
@ -31,6 +30,5 @@ export { default as Security } from './Security';
|
|||
export { default as Speaker } from './Speaker';
|
||||
export { default as Tag } from './Tag';
|
||||
export { default as Target } from './Target';
|
||||
export { default as User } from './User';
|
||||
export { default as Visitor } from './Visitor';
|
||||
export { default as Website } from './Website';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import bcrypt from 'bcryptjs';
|
||||
import { Report } from '@prisma/client';
|
||||
import { Report } from '@/generated/prisma';
|
||||
import redis from '@/lib/redis';
|
||||
import debug from 'debug';
|
||||
import { PERMISSIONS, ROLE_PERMISSIONS, ROLES, SHARE_TOKEN_HEADER } from '@/lib/constants';
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Website, Session } from '@prisma/client';
|
||||
import { Website, Session } from '@/generated/prisma';
|
||||
import redis from '@/lib/redis';
|
||||
import { getWebsiteSession, getWebsite } from '@/queries';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Prisma, Report } from '@prisma/client';
|
||||
import { Prisma, Report } from '@/generated/prisma';
|
||||
import prisma from '@/lib/prisma';
|
||||
import { PageResult, PageParams } from '@/lib/types';
|
||||
import ReportFindManyArgs = Prisma.ReportFindManyArgs;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Prisma, Team } from '@prisma/client';
|
||||
import { Prisma, Team } from '@/generated/prisma';
|
||||
import { ROLES } from '@/lib/constants';
|
||||
import { uuid } from '@/lib/crypto';
|
||||
import prisma from '@/lib/prisma';
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Prisma, TeamUser } from '@prisma/client';
|
||||
import { Prisma, TeamUser } from '@/generated/prisma';
|
||||
import { uuid } from '@/lib/crypto';
|
||||
import prisma from '@/lib/prisma';
|
||||
import { PageResult, PageParams } from '@/lib/types';
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Prisma } from '@prisma/client';
|
||||
import { Prisma } from '@/generated/prisma';
|
||||
import { ROLES } from '@/lib/constants';
|
||||
import prisma from '@/lib/prisma';
|
||||
import { PageResult, Role, User, PageParams } from '@/lib/types';
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Prisma, Website } from '@prisma/client';
|
||||
import { Prisma, Website } from '@/generated/prisma';
|
||||
import redis from '@/lib/redis';
|
||||
import prisma from '@/lib/prisma';
|
||||
import { PageResult, PageParams } from '@/lib/types';
|
||||
|
|
|
|||
77
src/queries/sql/reports/getGoal.ts
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
import clickhouse from '@/lib/clickhouse';
|
||||
import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db';
|
||||
import prisma from '@/lib/prisma';
|
||||
|
||||
export interface GoalCriteria {
|
||||
startDate: Date;
|
||||
endDate: Date;
|
||||
type: string;
|
||||
value: string;
|
||||
operator?: string;
|
||||
property?: string;
|
||||
}
|
||||
|
||||
export async function getGoal(...args: [websiteId: string, criteria: GoalCriteria]) {
|
||||
return runQuery({
|
||||
[PRISMA]: () => relationalQuery(...args),
|
||||
[CLICKHOUSE]: () => clickhouseQuery(...args),
|
||||
});
|
||||
}
|
||||
|
||||
async function relationalQuery(websiteId: string, criteria: GoalCriteria) {
|
||||
const { type, value } = criteria;
|
||||
const { rawQuery, parseFilters } = prisma;
|
||||
const { filterQuery, dateQuery, params } = await parseFilters(websiteId, criteria);
|
||||
const isPage = type === 'page';
|
||||
const column = isPage ? 'url_path' : 'event_name';
|
||||
const eventType = isPage ? 1 : 2;
|
||||
|
||||
return rawQuery(
|
||||
`
|
||||
select count(*) as num,
|
||||
(
|
||||
select count(${isPage ? '*' : 'distinct session_id'})
|
||||
from website_event
|
||||
where website_id = {websiteId:UUID}
|
||||
and event_type = ${eventType}
|
||||
${dateQuery}
|
||||
) as total
|
||||
from website_event
|
||||
where website_id = {websiteId:UUID}
|
||||
and event_type = ${eventType}
|
||||
and ${column} = {value:String}
|
||||
${dateQuery}
|
||||
${filterQuery}
|
||||
`,
|
||||
{ ...params, value },
|
||||
);
|
||||
}
|
||||
|
||||
async function clickhouseQuery(websiteId: string, criteria: GoalCriteria) {
|
||||
const { type, value } = criteria;
|
||||
const { rawQuery, parseFilters } = clickhouse;
|
||||
const { filterQuery, dateQuery, params } = await parseFilters(websiteId, criteria);
|
||||
const isPage = type === 'page';
|
||||
const column = isPage ? 'url_path' : 'event_name';
|
||||
const eventType = isPage ? 1 : 2;
|
||||
|
||||
return rawQuery(
|
||||
`
|
||||
select count(*) as num,
|
||||
(
|
||||
select count(${isPage ? '*' : 'distinct session_id'})
|
||||
from website_event
|
||||
where website_id = {websiteId:UUID}
|
||||
and event_type = ${eventType}
|
||||
${dateQuery}
|
||||
) as total
|
||||
from website_event
|
||||
where website_id = {websiteId:UUID}
|
||||
and event_type = ${eventType}
|
||||
and ${column} = {value:String}
|
||||
${dateQuery}
|
||||
${filterQuery}
|
||||
`,
|
||||
{ ...params, value },
|
||||
).then(results => results?.[0]);
|
||||
}
|
||||
|
|
@ -1,375 +0,0 @@
|
|||
import clickhouse from '@/lib/clickhouse';
|
||||
import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db';
|
||||
import prisma from '@/lib/prisma';
|
||||
|
||||
export async function getGoals(
|
||||
...args: [
|
||||
websiteId: string,
|
||||
criteria: {
|
||||
startDate: Date;
|
||||
endDate: Date;
|
||||
goals: { type: string; value: string; goal: number; operator?: string }[];
|
||||
},
|
||||
]
|
||||
) {
|
||||
return runQuery({
|
||||
[PRISMA]: () => relationalQuery(...args),
|
||||
[CLICKHOUSE]: () => clickhouseQuery(...args),
|
||||
});
|
||||
}
|
||||
|
||||
async function relationalQuery(
|
||||
websiteId: string,
|
||||
criteria: {
|
||||
startDate: Date;
|
||||
endDate: Date;
|
||||
goals: { type: string; value: string; goal: number; operator?: string }[];
|
||||
},
|
||||
): Promise<any> {
|
||||
const { startDate, endDate, goals } = criteria;
|
||||
const { rawQuery } = prisma;
|
||||
|
||||
const urls = goals.filter(a => a.type === 'url');
|
||||
const events = goals.filter(a => a.type === 'event');
|
||||
const eventData = goals.filter(a => a.type === 'event-data');
|
||||
|
||||
const hasUrl = urls.length > 0;
|
||||
const hasEvent = events.length > 0;
|
||||
const hasEventData = eventData.length > 0;
|
||||
|
||||
function getParameters(
|
||||
urls: { type: string; value: string; goal: number }[],
|
||||
events: { type: string; value: string; goal: number }[],
|
||||
eventData: {
|
||||
type: string;
|
||||
value: string;
|
||||
goal: number;
|
||||
operator?: string;
|
||||
property?: string;
|
||||
}[],
|
||||
) {
|
||||
const urlParam = urls.reduce((acc, cv, i) => {
|
||||
acc[`${cv.type}${i}`] = cv.value;
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
const eventParam = events.reduce((acc, cv, i) => {
|
||||
acc[`${cv.type}${i}`] = cv.value;
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
const eventDataParam = eventData.reduce((acc, cv, i) => {
|
||||
acc[`eventData${i}`] = cv.value;
|
||||
acc[`property${i}`] = cv.property;
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
return {
|
||||
urls: { ...urlParam, startDate, endDate, websiteId },
|
||||
events: { ...eventParam, startDate, endDate, websiteId },
|
||||
eventData: { ...eventDataParam, startDate, endDate, websiteId },
|
||||
};
|
||||
}
|
||||
|
||||
function getColumns(
|
||||
urls: { type: string; value: string; goal: number }[],
|
||||
events: { type: string; value: string; goal: number }[],
|
||||
eventData: {
|
||||
type: string;
|
||||
value: string;
|
||||
goal: number;
|
||||
operator?: string;
|
||||
property?: string;
|
||||
}[],
|
||||
) {
|
||||
const urlColumns = urls
|
||||
.map((a, i) => `COUNT(CASE WHEN url_path = {{url${i}}} THEN 1 END) AS URL${i},`)
|
||||
.join('\n')
|
||||
.slice(0, -1);
|
||||
const eventColumns = events
|
||||
.map((a, i) => `COUNT(CASE WHEN event_name = {{event${i}}} THEN 1 END) AS EVENT${i},`)
|
||||
.join('\n')
|
||||
.slice(0, -1);
|
||||
const eventDataColumns = eventData
|
||||
.map(
|
||||
(a, i) =>
|
||||
`${
|
||||
a.operator === 'average' ? 'avg' : a.operator
|
||||
}(CASE WHEN event_name = {{eventData${i}}} AND data_key = {{property${i}}} THEN ${
|
||||
a.operator === 'count' ? '1' : 'number_value'
|
||||
} END) AS EVENT_DATA${i},`,
|
||||
)
|
||||
.join('\n')
|
||||
.slice(0, -1);
|
||||
|
||||
return { urls: urlColumns, events: eventColumns, eventData: eventDataColumns };
|
||||
}
|
||||
|
||||
function getWhere(
|
||||
urls: { type: string; value: string; goal: number }[],
|
||||
events: { type: string; value: string; goal: number }[],
|
||||
eventData: {
|
||||
type: string;
|
||||
value: string;
|
||||
goal: number;
|
||||
operator?: string;
|
||||
property?: string;
|
||||
}[],
|
||||
) {
|
||||
const urlWhere = urls.map((a, i) => `{{url${i}}}`).join(',');
|
||||
const eventWhere = events.map((a, i) => `{{event${i}}}`).join(',');
|
||||
const eventDataNameWhere = eventData.map((a, i) => `{{eventData${i}}}`).join(',');
|
||||
const eventDataKeyWhere = eventData.map((a, i) => `{{property${i}}}`).join(',');
|
||||
|
||||
return {
|
||||
urls: `and url_path in (${urlWhere})`,
|
||||
events: `and event_name in (${eventWhere})`,
|
||||
eventData: `and event_name in (${eventDataNameWhere}) and data_key in (${eventDataKeyWhere})`,
|
||||
};
|
||||
}
|
||||
|
||||
const parameters = getParameters(urls, events, eventData);
|
||||
const columns = getColumns(urls, events, eventData);
|
||||
const where = getWhere(urls, events, eventData);
|
||||
|
||||
const urlResults = hasUrl
|
||||
? await rawQuery(
|
||||
`
|
||||
select
|
||||
${columns.urls}
|
||||
from website_event
|
||||
where website_id = {{websiteId::uuid}}
|
||||
${where.urls}
|
||||
and created_at between {{startDate}} and {{endDate}}
|
||||
`,
|
||||
parameters.urls,
|
||||
).then(a => {
|
||||
const results = a[0];
|
||||
|
||||
return Object.keys(results).map((key, i) => ({
|
||||
...urls[i],
|
||||
goal: Number(urls[i].goal),
|
||||
result: Number(results[key]),
|
||||
}));
|
||||
})
|
||||
: [];
|
||||
|
||||
const eventResults = hasEvent
|
||||
? await rawQuery(
|
||||
`
|
||||
select
|
||||
${columns.events}
|
||||
from website_event
|
||||
where website_id = {{websiteId::uuid}}
|
||||
${where.events}
|
||||
and created_at between {{startDate}} and {{endDate}}
|
||||
`,
|
||||
parameters.events,
|
||||
).then(a => {
|
||||
const results = a[0];
|
||||
|
||||
return Object.keys(results).map((key, i) => {
|
||||
return { ...events[i], goal: Number(events[i].goal), result: Number(results[key]) };
|
||||
});
|
||||
})
|
||||
: [];
|
||||
|
||||
const eventDataResults = hasEventData
|
||||
? await rawQuery(
|
||||
`
|
||||
select
|
||||
${columns.eventData}
|
||||
from website_event w
|
||||
join event_data d
|
||||
on d.website_event_id = w.event_id
|
||||
where w.website_id = {{websiteId::uuid}}
|
||||
${where.eventData}
|
||||
and w.created_at between {{startDate}} and {{endDate}}
|
||||
`,
|
||||
parameters.eventData,
|
||||
).then(a => {
|
||||
const results = a[0];
|
||||
|
||||
return Object.keys(results).map((key, i) => {
|
||||
return { ...eventData[i], goal: Number(eventData[i].goal), result: Number(results[key]) };
|
||||
});
|
||||
})
|
||||
: [];
|
||||
|
||||
return [...urlResults, ...eventResults, ...eventDataResults];
|
||||
}
|
||||
|
||||
async function clickhouseQuery(
|
||||
websiteId: string,
|
||||
criteria: {
|
||||
startDate: Date;
|
||||
endDate: Date;
|
||||
goals: { type: string; value: string; goal: number; operator?: string; property?: string }[];
|
||||
},
|
||||
): Promise<{ type: string; value: string; goal: number; result: number }[]> {
|
||||
const { startDate, endDate, goals } = criteria;
|
||||
const { rawQuery } = clickhouse;
|
||||
|
||||
const urls = goals.filter(a => a.type === 'url');
|
||||
const events = goals.filter(a => a.type === 'event');
|
||||
const eventData = goals.filter(a => a.type === 'event-data');
|
||||
|
||||
const hasUrl = urls.length > 0;
|
||||
const hasEvent = events.length > 0;
|
||||
const hasEventData = eventData.length > 0;
|
||||
|
||||
function getParameters(
|
||||
urls: { type: string; value: string; goal: number }[],
|
||||
events: { type: string; value: string; goal: number }[],
|
||||
eventData: {
|
||||
type: string;
|
||||
value: string;
|
||||
goal: number;
|
||||
operator?: string;
|
||||
property?: string;
|
||||
}[],
|
||||
) {
|
||||
const urlParam = urls.reduce((acc, cv, i) => {
|
||||
acc[`${cv.type}${i}`] = cv.value;
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
const eventParam = events.reduce((acc, cv, i) => {
|
||||
acc[`${cv.type}${i}`] = cv.value;
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
const eventDataParam = eventData.reduce((acc, cv, i) => {
|
||||
acc[`eventData${i}`] = cv.value;
|
||||
acc[`property${i}`] = cv.property;
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
return {
|
||||
urls: { ...urlParam, startDate, endDate, websiteId },
|
||||
events: { ...eventParam, startDate, endDate, websiteId },
|
||||
eventData: { ...eventDataParam, startDate, endDate, websiteId },
|
||||
};
|
||||
}
|
||||
|
||||
function getColumns(
|
||||
urls: { type: string; value: string; goal: number }[],
|
||||
events: { type: string; value: string; goal: number }[],
|
||||
eventData: {
|
||||
type: string;
|
||||
value: string;
|
||||
goal: number;
|
||||
operator?: string;
|
||||
property?: string;
|
||||
}[],
|
||||
) {
|
||||
const urlColumns = urls
|
||||
.map((a, i) => `countIf(url_path = {url${i}:String}) AS URL${i},`)
|
||||
.join('\n')
|
||||
.slice(0, -1);
|
||||
const eventColumns = events
|
||||
.map((a, i) => `countIf(event_name = {event${i}:String}) AS EVENT${i},`)
|
||||
.join('\n')
|
||||
.slice(0, -1);
|
||||
const eventDataColumns = eventData
|
||||
.map(
|
||||
(a, i) =>
|
||||
`${a.operator === 'average' ? 'avg' : a.operator}If(${
|
||||
a.operator !== 'count' ? 'number_value, ' : ''
|
||||
}event_name = {eventData${i}:String} AND data_key = {property${i}:String}) AS EVENT_DATA${i},`,
|
||||
)
|
||||
.join('\n')
|
||||
.slice(0, -1);
|
||||
|
||||
return { url: urlColumns, events: eventColumns, eventData: eventDataColumns };
|
||||
}
|
||||
|
||||
function getWhere(
|
||||
urls: { type: string; value: string; goal: number }[],
|
||||
events: { type: string; value: string; goal: number }[],
|
||||
eventData: {
|
||||
type: string;
|
||||
value: string;
|
||||
goal: number;
|
||||
operator?: string;
|
||||
property?: string;
|
||||
}[],
|
||||
) {
|
||||
const urlWhere = urls.map((a, i) => `{url${i}:String}`).join(',');
|
||||
const eventWhere = events.map((a, i) => `{event${i}:String}`).join(',');
|
||||
const eventDataNameWhere = eventData.map((a, i) => `{eventData${i}:String}`).join(',');
|
||||
const eventDataKeyWhere = eventData.map((a, i) => `{property${i}:String}`).join(',');
|
||||
|
||||
return {
|
||||
urls: `and url_path in (${urlWhere})`,
|
||||
events: `and event_name in (${eventWhere})`,
|
||||
eventData: `and event_name in (${eventDataNameWhere}) and data_key in (${eventDataKeyWhere})`,
|
||||
};
|
||||
}
|
||||
|
||||
const parameters = getParameters(urls, events, eventData);
|
||||
const columns = getColumns(urls, events, eventData);
|
||||
const where = getWhere(urls, events, eventData);
|
||||
|
||||
const urlResults = hasUrl
|
||||
? await rawQuery(
|
||||
`
|
||||
select
|
||||
${columns.url}
|
||||
from website_event
|
||||
where website_id = {websiteId:UUID}
|
||||
${where.urls}
|
||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
`,
|
||||
parameters.urls,
|
||||
).then(a => {
|
||||
const results = a[0];
|
||||
|
||||
return Object.keys(results).map((key, i) => {
|
||||
return { ...urls[i], goal: Number(urls[i].goal), result: Number(results[key]) };
|
||||
});
|
||||
})
|
||||
: [];
|
||||
|
||||
const eventResults = hasEvent
|
||||
? await rawQuery(
|
||||
`
|
||||
select
|
||||
${columns.events}
|
||||
from website_event
|
||||
where website_id = {websiteId:UUID}
|
||||
${where.events}
|
||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
`,
|
||||
parameters.events,
|
||||
).then(a => {
|
||||
const results = a[0];
|
||||
|
||||
return Object.keys(results).map((key, i) => {
|
||||
return { ...events[i], goal: Number(events[i].goal), result: Number(results[key]) };
|
||||
});
|
||||
})
|
||||
: [];
|
||||
|
||||
const eventDataResults = hasEventData
|
||||
? await rawQuery(
|
||||
`
|
||||
select
|
||||
${columns.eventData}
|
||||
from event_data
|
||||
where website_id = {websiteId:UUID}
|
||||
${where.eventData}
|
||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
`,
|
||||
parameters.eventData,
|
||||
).then(a => {
|
||||
const results = a[0];
|
||||
|
||||
return Object.keys(results).map((key, i) => {
|
||||
return { ...eventData[i], goal: Number(eventData[i].goal), result: Number(results[key]) };
|
||||
});
|
||||
})
|
||||
: [];
|
||||
|
||||
return [...urlResults, ...eventResults, ...eventDataResults];
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import { Prisma } from '@prisma/client';
|
||||
import { Prisma } from '@/generated/prisma';
|
||||
import prisma from '@/lib/prisma';
|
||||
|
||||
export async function createSession(data: Prisma.SessionCreateInput) {
|
||||
|
|
|
|||