Merge branch 'dev' into analytics

This commit is contained in:
Mike Cao 2024-05-16 22:12:50 -07:00
commit da7a4f3d9f
61 changed files with 1736 additions and 905 deletions

View File

@ -72,13 +72,13 @@ docker compose up -d
Alternatively, to pull just the Umami Docker image with PostgreSQL support:
```bash
docker pull ghcr.io/umami-software/umami:postgresql-latest
docker pull docker.umami.is/umami-software/umami:postgresql-latest
```
Or with MySQL support:
```bash
docker pull ghcr.io/umami-software/umami:mysql-latest
docker pull docker.umami.is/umami-software/umami:mysql-latest
```
## Getting updates
@ -101,3 +101,4 @@ docker compose up --force-recreate
## License
MIT

View File

@ -3,18 +3,17 @@ require('dotenv').config();
const path = require('path');
const pkg = require('./package.json');
const basePath = process.env.BASE_PATH || '';
const forceSSL = process.env.FORCE_SSL || '';
const collectApiEndpoint = process.env.COLLECT_API_ENDPOINT || '';
const defaultLocale = process.env.DEFAULT_LOCALE || '';
const trackerScriptName = process.env.TRACKER_SCRIPT_NAME || '';
const cloudMode = process.env.CLOUD_MODE || '';
const cloudUrl = process.env.CLOUD_URL || '';
const frameAncestors = process.env.ALLOWED_FRAME_URLS || '';
const disableLogin = process.env.DISABLE_LOGIN || '';
const disableUI = process.env.DISABLE_UI || '';
const hostURL = process.env.HOST_URL || '';
const privateMode = process.env.PRIVATE_MODE || '';
const basePath = process.env.BASE_PATH;
const collectApiEndpoint = process.env.COLLECT_API_ENDPOINT;
const cloudMode = process.env.CLOUD_MODE;
const cloudUrl = process.env.CLOUD_URL;
const defaultLocale = process.env.DEFAULT_LOCALE;
const disableLogin = process.env.DISABLE_LOGIN;
const disableUI = process.env.DISABLE_UI;
const forceSSL = process.env.FORCE_SSL;
const frameAncestors = process.env.ALLOWED_FRAME_URLS;
const privateMode = process.env.PRIVATE_MODE;
const trackerScriptName = process.env.TRACKER_SCRIPT_NAME;
const contentSecurityPolicy = [
`default-src 'self'`,
@ -120,7 +119,6 @@ const config = {
defaultLocale,
disableLogin,
disableUI,
hostURL,
privateMode,
},
basePath,

View File

@ -11,6 +11,7 @@
"@tanstack/react-query": "^4.33.0",
"classnames": "^2.3.1",
"colord": "^2.9.2",
"date-fns-tz": "^1.1.4",
"immer": "^9.0.12",
"moment-timezone": "^0.5.35",
"next": "^13.4.0",

View File

@ -64,14 +64,14 @@
".next/cache"
],
"dependencies": {
"@clickhouse/client": "^0.2.2",
"@clickhouse/client": "^1.0.1",
"@fontsource/inter": "^4.5.15",
"@prisma/client": "5.12.1",
"@prisma/client": "5.13.0",
"@prisma/extension-read-replicas": "^0.3.0",
"@react-spring/web": "^9.7.3",
"@tanstack/react-query": "^5.28.6",
"@umami/prisma-client": "^0.14.0",
"@umami/redis-client": "^0.20.0",
"@umami/redis-client": "^0.21.0",
"chalk": "^4.1.1",
"chart.js": "^4.4.2",
"chartjs-adapter-date-fns": "^3.0.0",
@ -98,11 +98,11 @@
"maxmind": "^4.3.6",
"md5": "^2.3.0",
"moment-timezone": "^0.5.35",
"next": "14.1.4",
"next": "14.2.3",
"next-basics": "^0.39.0",
"node-fetch": "^3.2.8",
"npm-run-all": "^4.1.5",
"prisma": "5.12.1",
"prisma": "5.13.0",
"react": "^18.2.0",
"react-basics": "^0.123.0",
"react-beautiful-dnd": "^13.1.0",

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
"label.access-code": [
{
"type": 0,
"value": "Access code"
"value": "Код доступу"
}
],
"label.actions": [
@ -14,31 +14,31 @@
"label.activity-log": [
{
"type": 0,
"value": "Activity log"
"value": "Журнал активності"
}
],
"label.add": [
{
"type": 0,
"value": "Add"
"value": "Додати"
}
],
"label.add-description": [
{
"type": 0,
"value": "Add description"
"value": "Додати опис"
}
],
"label.add-member": [
{
"type": 0,
"value": "Add member"
"value": "Додати учасника"
}
],
"label.add-step": [
{
"type": 0,
"value": "Add step"
"value": "Додати крок"
}
],
"label.add-website": [
@ -56,7 +56,7 @@
"label.after": [
{
"type": 0,
"value": "After"
"value": "Після"
}
],
"label.all": [
@ -74,13 +74,13 @@
"label.analytics": [
{
"type": 0,
"value": "Analytics"
"value": "Аналітика"
}
],
"label.average": [
{
"type": 0,
"value": "Average"
"value": "Середнє"
}
],
"label.average-visit-time": [
@ -98,7 +98,7 @@
"label.before": [
{
"type": 0,
"value": "Before"
"value": "Раніше"
}
],
"label.bounce-rate": [
@ -110,13 +110,13 @@
"label.breakdown": [
{
"type": 0,
"value": "Breakdown"
"value": "Розподіл"
}
],
"label.browser": [
{
"type": 0,
"value": "Browser"
"value": "Браузер"
}
],
"label.browsers": [
@ -140,25 +140,25 @@
"label.cities": [
{
"type": 0,
"value": "Cities"
"value": "Міста"
}
],
"label.city": [
{
"type": 0,
"value": "City"
"value": "Місто"
}
],
"label.clear-all": [
{
"type": 0,
"value": "Clear all"
"value": "Очистити все"
}
],
"label.confirm": [
{
"type": 0,
"value": "Confirm"
"value": "Підтвердити"
}
],
"label.confirm-password": [
@ -170,13 +170,13 @@
"label.contains": [
{
"type": 0,
"value": "Contains"
"value": "Містить"
}
],
"label.continue": [
{
"type": 0,
"value": "Continue"
"value": "Продовжити"
}
],
"label.countries": [
@ -188,43 +188,43 @@
"label.country": [
{
"type": 0,
"value": "Country"
"value": "Країна"
}
],
"label.create": [
{
"type": 0,
"value": "Create"
"value": "Створити"
}
],
"label.create-report": [
{
"type": 0,
"value": "Create report"
"value": "Створити звіт"
}
],
"label.create-team": [
{
"type": 0,
"value": "Create team"
"value": "Створити команду"
}
],
"label.create-user": [
{
"type": 0,
"value": "Create user"
"value": "Створити користувача"
}
],
"label.created": [
{
"type": 0,
"value": "Created"
"value": "Створено"
}
],
"label.created-by": [
{
"type": 0,
"value": "Created By"
"value": "Автор"
}
],
"label.current-password": [
@ -248,13 +248,13 @@
"label.data": [
{
"type": 0,
"value": "Data"
"value": "Дані"
}
],
"label.date": [
{
"type": 0,
"value": "Date"
"value": "Дата"
}
],
"label.date-range": [
@ -266,7 +266,7 @@
"label.day": [
{
"type": 0,
"value": "Day"
"value": "День"
}
],
"label.default-date-range": [
@ -284,19 +284,19 @@
"label.delete-report": [
{
"type": 0,
"value": "Delete report"
"value": "Видалити звіт"
}
],
"label.delete-team": [
{
"type": 0,
"value": "Delete team"
"value": "Видалити команду"
}
],
"label.delete-user": [
{
"type": 0,
"value": "Delete user"
"value": "Видалити користувача"
}
],
"label.delete-website": [
@ -308,7 +308,7 @@
"label.description": [
{
"type": 0,
"value": "Description"
"value": "Опис"
}
],
"label.desktop": [
@ -320,13 +320,13 @@
"label.details": [
{
"type": 0,
"value": "Details"
"value": "Деталі"
}
],
"label.device": [
{
"type": 0,
"value": "Device"
"value": "Пристрій"
}
],
"label.devices": [
@ -344,7 +344,7 @@
"label.does-not-contain": [
{
"type": 0,
"value": "Does not contain"
"value": "Не містить"
}
],
"label.domain": [
@ -368,13 +368,13 @@
"label.edit-dashboard": [
{
"type": 0,
"value": "Edit dashboard"
"value": "Редагувати панель"
}
],
"label.edit-member": [
{
"type": 0,
"value": "Edit member"
"value": "Редагувати учасника"
}
],
"label.enable-share-url": [
@ -386,13 +386,13 @@
"label.event": [
{
"type": 0,
"value": "Event"
"value": "Подія"
}
],
"label.event-data": [
{
"type": 0,
"value": "Event data"
"value": "Дані події"
}
],
"label.events": [
@ -410,19 +410,19 @@
"label.field": [
{
"type": 0,
"value": "Field"
"value": "Поле"
}
],
"label.fields": [
{
"type": 0,
"value": "Fields"
"value": "Поля"
}
],
"label.filter": [
{
"type": 0,
"value": "Filter"
"value": "Фільтр"
}
],
"label.filter-combined": [
@ -440,7 +440,7 @@
"label.filters": [
{
"type": 0,
"value": "Filters"
"value": "Фільтри"
}
],
"label.funnel": [
@ -458,13 +458,13 @@
"label.greater-than": [
{
"type": 0,
"value": "Greater than"
"value": "Більше ніж"
}
],
"label.greater-than-equals": [
{
"type": 0,
"value": "Greater than or equals"
"value": "Більше або рівно"
}
],
"label.insights": [
@ -482,43 +482,43 @@
"label.is": [
{
"type": 0,
"value": "Is"
"value": "Є"
}
],
"label.is-not": [
{
"type": 0,
"value": "Is not"
"value": "Не є"
}
],
"label.is-not-set": [
{
"type": 0,
"value": "Is not set"
"value": "Не встановлено"
}
],
"label.is-set": [
{
"type": 0,
"value": "Is set"
"value": "Встановлено"
}
],
"label.join": [
{
"type": 0,
"value": "Join"
"value": "Приєднатись"
}
],
"label.join-team": [
{
"type": 0,
"value": "Join team"
"value": "Приєднатись до команди"
}
],
"label.language": [
{
"type": 0,
"value": "Language"
"value": "Мова"
}
],
"label.languages": [
@ -564,7 +564,7 @@
"label.last-months": [
{
"type": 0,
"value": "Last "
"value": "Останні "
},
{
"type": 1,
@ -572,31 +572,31 @@
},
{
"type": 0,
"value": " months"
"value": " місяців"
}
],
"label.leave": [
{
"type": 0,
"value": "Leave"
"value": "Покинути"
}
],
"label.leave-team": [
{
"type": 0,
"value": "Leave team"
"value": "Покинути"
}
],
"label.less-than": [
{
"type": 0,
"value": "Less than"
"value": "Менше ніж"
}
],
"label.less-than-equals": [
{
"type": 0,
"value": "Less than or equals"
"value": "Менше або рівно"
}
],
"label.login": [
@ -614,7 +614,7 @@
"label.manage": [
{
"type": 0,
"value": "Manage"
"value": "Керувати"
}
],
"label.max": [
@ -626,13 +626,13 @@
"label.member": [
{
"type": 0,
"value": "Member"
"value": "Учасник"
}
],
"label.members": [
{
"type": 0,
"value": "Members"
"value": "Учасники"
}
],
"label.min": [
@ -656,13 +656,13 @@
"label.my-account": [
{
"type": 0,
"value": "My account"
"value": "Мої аккаунти"
}
],
"label.my-websites": [
{
"type": 0,
"value": "My websites"
"value": "Мої вебсайти"
}
],
"label.name": [
@ -732,7 +732,7 @@
"label.overview": [
{
"type": 0,
"value": "Overview"
"value": "Огляд"
}
],
"label.owner": [
@ -744,7 +744,7 @@
"label.page-of": [
{
"type": 0,
"value": "Page "
"value": "Сторінка "
},
{
"type": 1,
@ -752,7 +752,7 @@
},
{
"type": 0,
"value": " of "
"value": " з "
},
{
"type": 1,
@ -768,7 +768,7 @@
"label.pageTitle": [
{
"type": 0,
"value": "Page title"
"value": "Загловок сторінки"
}
],
"label.pages": [
@ -850,31 +850,31 @@
"label.region": [
{
"type": 0,
"value": "Region"
"value": "Регіон"
}
],
"label.regions": [
{
"type": 0,
"value": "Regions"
"value": "Регіони"
}
],
"label.remove": [
{
"type": 0,
"value": "Remove"
"value": "Видалити"
}
],
"label.remove-member": [
{
"type": 0,
"value": "Remove member"
"value": "Видалити учасника"
}
],
"label.reports": [
{
"type": 0,
"value": "Reports"
"value": "Звіти"
}
],
"label.required": [
@ -910,7 +910,7 @@
"label.role": [
{
"type": 0,
"value": "Role"
"value": "Роль"
}
],
"label.run-query": [
@ -928,19 +928,19 @@
"label.screens": [
{
"type": 0,
"value": "Screens"
"value": "Екрани"
}
],
"label.search": [
{
"type": 0,
"value": "Search"
"value": "Пошук"
}
],
"label.select": [
{
"type": 0,
"value": "Select"
"value": "Вибір"
}
],
"label.select-date": [
@ -964,7 +964,7 @@
"label.sessions": [
{
"type": 0,
"value": "Sessions"
"value": "Сесії"
}
],
"label.settings": [
@ -988,13 +988,13 @@
"label.steps": [
{
"type": 0,
"value": "Steps"
"value": "Кроки"
}
],
"label.sum": [
{
"type": 0,
"value": "Sum"
"value": "Сума"
}
],
"label.tablet": [
@ -1006,55 +1006,55 @@
"label.team": [
{
"type": 0,
"value": "Team"
"value": "Команда"
}
],
"label.team-id": [
{
"type": 0,
"value": "Team ID"
"value": "ID команди"
}
],
"label.team-member": [
{
"type": 0,
"value": "Team member"
"value": "Учасник команди"
}
],
"label.team-name": [
{
"type": 0,
"value": "Team name"
"value": "Назва команди"
}
],
"label.team-owner": [
{
"type": 0,
"value": "Team owner"
"value": "Власник команди"
}
],
"label.team-view-only": [
{
"type": 0,
"value": "Team view only"
"value": "Лише для перегляду командою"
}
],
"label.team-websites": [
{
"type": 0,
"value": "Team websites"
"value": "Вебсайти команди"
}
],
"label.teams": [
{
"type": 0,
"value": "Teams"
"value": "Команди"
}
],
"label.theme": [
{
"type": 0,
"value": "Theme"
"value": "Теми"
}
],
"label.this-month": [
@ -1084,7 +1084,7 @@
"label.title": [
{
"type": 0,
"value": "Title"
"value": "Загловок"
}
],
"label.today": [
@ -1138,13 +1138,13 @@
"label.type": [
{
"type": 0,
"value": "Type"
"value": "Типу"
}
],
"label.unique": [
{
"type": 0,
"value": "Unique"
"value": "Унікальний"
}
],
"label.unique-visitors": [
@ -1162,13 +1162,13 @@
"label.untitled": [
{
"type": 0,
"value": "Untitled"
"value": "Без заголовку"
}
],
"label.update": [
{
"type": 0,
"value": "Update"
"value": "Оновити"
}
],
"label.url": [
@ -1186,7 +1186,7 @@
"label.user": [
{
"type": 0,
"value": "User"
"value": "Користувач"
}
],
"label.username": [
@ -1198,7 +1198,7 @@
"label.users": [
{
"type": 0,
"value": "Users"
"value": "Користувачі"
}
],
"label.utm": [
@ -1216,13 +1216,13 @@
"label.value": [
{
"type": 0,
"value": "Value"
"value": "Значення"
}
],
"label.view": [
{
"type": 0,
"value": "View"
"value": "Перегляд"
}
],
"label.view-details": [
@ -1234,7 +1234,7 @@
"label.view-only": [
{
"type": 0,
"value": "View only"
"value": "Лише для перегляду"
}
],
"label.views": [
@ -1246,7 +1246,7 @@
"label.views-per-visit": [
{
"type": 0,
"value": "Views per visit"
"value": "Перегляди за візит"
}
],
"label.visitors": [
@ -1258,19 +1258,19 @@
"label.visits": [
{
"type": 0,
"value": "Visits"
"value": "Відвідування"
}
],
"label.website": [
{
"type": 0,
"value": "Website"
"value": "Вебсайт"
}
],
"label.website-id": [
{
"type": 0,
"value": "Website ID"
"value": "Вебсайт ID"
}
],
"label.websites": [
@ -1282,19 +1282,19 @@
"label.window": [
{
"type": 0,
"value": "Window"
"value": "Вікно"
}
],
"label.yesterday": [
{
"type": 0,
"value": "Yesterday"
"value": "Вчора"
}
],
"message.action-confirmation": [
{
"type": 0,
"value": "Type "
"value": "Введі "
},
{
"type": 1,
@ -1302,7 +1302,7 @@
},
{
"type": 0,
"value": " in the box below to confirm."
"value": " у поле нижче для підтвердження."
}
],
"message.active-users": [
@ -1332,7 +1332,7 @@
"message.confirm-leave": [
{
"type": 0,
"value": "Are you sure you want to leave "
"value": "Ви впевнені, що хочете покинути "
},
{
"type": 1,
@ -1346,7 +1346,7 @@
"message.confirm-remove": [
{
"type": 0,
"value": "Are you sure you want to remove "
"value": "Ви впевнеі, що хочете видалити "
},
{
"type": 1,
@ -1374,7 +1374,7 @@
"message.delete-team-warning": [
{
"type": 0,
"value": "Deleting a team will also delete all team websites."
"value": "Видалення команди також видалить усі вебсайти команди."
}
],
"message.delete-website-warning": [
@ -1470,25 +1470,25 @@
"message.no-results-found": [
{
"type": 0,
"value": "No results were found."
"value": "Результатів не знайдено."
}
],
"message.no-team-websites": [
{
"type": 0,
"value": "This team does not have any websites."
"value": "Ця команди не має жодних вебсайтів."
}
],
"message.no-teams": [
{
"type": 0,
"value": "You have not created any teams."
"value": "Ви не створили жодної команди."
}
],
"message.no-users": [
{
"type": 0,
"value": "There are no users."
"value": "Користувачів не має."
}
],
"message.no-websites-configured": [
@ -1546,19 +1546,19 @@
"message.team-already-member": [
{
"type": 0,
"value": "You are already a member of the team."
"value": "Ви уже є учасником цієї команди."
}
],
"message.team-not-found": [
{
"type": 0,
"value": "Team not found."
"value": "Команду не знайдено."
}
],
"message.team-websites-info": [
{
"type": 0,
"value": "Websites can be viewed by anyone on the team."
"value": "Вебсайти може переглядати кожен учаник команди."
}
],
"message.tracking-code": [
@ -1594,13 +1594,13 @@
"message.user-deleted": [
{
"type": 0,
"value": "User deleted."
"value": "Користувача видалено."
}
],
"message.viewed-page": [
{
"type": 0,
"value": "Viewed page"
"value": "Переглянута сторінка"
}
],
"message.visitor-log": [

View File

@ -27,7 +27,7 @@ export function App({ children }) {
{children}
<UpdateNotice user={user} config={config} />
{process.env.NODE_ENV === 'production' && !pathname.includes('/share/') && (
<Script src={`${process.env.basePath}/telemetry.js`} />
<Script src={`${process.env.basePath || ''}/telemetry.js`} />
)}
</>
);

View File

@ -80,7 +80,7 @@ export function TestConsole({ websiteId }: { websiteId: string }) {
<Script
async
data-website-id={websiteId}
src={`${process.env.basePath}/script.js`}
src={`${process.env.basePath || ''}/script.js`}
data-cache="true"
/>
<div className={styles.actions}>

View File

@ -19,15 +19,3 @@
height: calc(100vh - 60px);
overflow-y: auto;
}
.content {
flex: 1;
display: flex;
flex-direction: column;
position: relative;
width: 100%;
max-width: 1320px;
margin: 0 auto;
padding: 0 20px;
min-height: calc(100vh - 60px);
}

View File

@ -5,6 +5,10 @@ import Page from 'components/layout/Page';
import styles from './layout.module.css';
export default function ({ children }) {
if (process.env.DISABLE_UI) {
return null;
}
return (
<App>
<main className={styles.layout}>

View File

@ -1,16 +1,23 @@
import { useReports } from 'components/hooks';
import ReportsTable from './ReportsTable';
import DataTable from 'components/common/DataTable';
import { ReactNode } from 'react';
export default function ReportsDataTable({
websiteId,
teamId,
children,
}: {
websiteId?: string;
teamId?: string;
children?: ReactNode;
}) {
const queryResult = useReports({ websiteId, teamId });
if (queryResult?.result?.data?.length === 0) {
return children;
}
return (
<DataTable queryResult={queryResult}>
{({ data }) => <ReportsTable data={data} showDomain={!websiteId} />}

View File

@ -6,11 +6,24 @@
.item {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
gap: 12px;
width: 100%;
flex-wrap: nowrap;
padding: 12px;
border: 1px solid var(--base400);
border-radius: var(--border-radius);
box-shadow: 1px 1px 1px var(--base400);
}
.value {
display: flex;
flex-direction: row;
align-items: center;
flex-wrap: wrap;
flex: 1;
}
.icon,
.close {
height: 1.5rem;
}

View File

@ -24,18 +24,21 @@ export function ParameterList({ children }: ParameterListProps) {
const Item = ({
children,
className,
icon,
onClick,
onRemove,
}: {
children?: ReactNode;
className?: string;
icon?: ReactNode;
onClick?: () => void;
onRemove?: () => void;
}) => {
return (
<div className={classNames(styles.item, className)} onClick={onClick}>
{children}
<Icon onClick={onRemove}>
{icon && <Icon className={styles.icon}>{icon}</Icon>}
<div className={styles.value}>{children}</div>
<Icon className={styles.close} onClick={onRemove}>
<Icons.Close />
</Icon>
</div>

View File

@ -4,6 +4,7 @@ import EventDataReport from '../event-data/EventDataReport';
import InsightsReport from '../insights/InsightsReport';
import RetentionReport from '../retention/RetentionReport';
import UTMReport from '../utm/UTMReport';
import GoalReport from '../goals/GoalsReport';
import { useReport } from 'components/hooks';
const reports = {
@ -12,6 +13,7 @@ const reports = {
insights: InsightsReport,
retention: RetentionReport,
utm: UTMReport,
goals: GoalReport,
};
export default function ReportPage({ reportId }: { reportId: string }) {

View File

@ -5,6 +5,7 @@ import Funnel from 'assets/funnel.svg';
import Lightbulb from 'assets/lightbulb.svg';
import Magnet from 'assets/magnet.svg';
import Tag from 'assets/tag.svg';
import Target from 'assets/target.svg';
import styles from './ReportTemplates.module.css';
import { useMessages, useTeamUrl } from 'components/hooks';
@ -37,6 +38,12 @@ export function ReportTemplates({ showHeader = true }: { showHeader?: boolean })
url: renderTeamUrl('/reports/utm'),
icon: <Tag />,
},
{
title: formatMessage(labels.goals),
description: formatMessage(labels.goalsDescription),
url: renderTeamUrl('/reports/goals'),
icon: <Target />,
},
];
return (

View File

@ -5,10 +5,6 @@
width: 100%;
}
.type {
color: var(--base700);
}
.value {
display: flex;
align-self: center;

View File

@ -93,12 +93,10 @@ export function FunnelParameters() {
<PopupTrigger key={index}>
<ParameterList.Item
className={styles.item}
icon={step.type === 'url' ? <Icons.Eye /> : <Icons.Bolt />}
onRemove={() => handleRemoveStep(index)}
>
<div className={styles.value}>
<div className={styles.type}>
<Icon>{step.type === 'url' ? <Icons.Eye /> : <Icons.Bolt />}</Icon>
</div>
<div>{step.value}</div>
</div>
</ParameterList.Item>

View File

@ -0,0 +1,7 @@
.dropdown {
width: 140px;
}
.input {
width: 200px;
}

View File

@ -0,0 +1,93 @@
import { useMessages } from 'components/hooks';
import { useState } from 'react';
import { Button, Dropdown, Flexbox, FormRow, Item, TextField } from 'react-basics';
import styles from './GoalsAddForm.module.css';
export function GoalsAddForm({
type: defaultType = 'url',
value: defaultValue = '',
goal: defaultGoal = 10,
onChange,
}: {
type?: string;
value?: string;
goal?: number;
onChange?: (step: { type: string; value: string; goal: number }) => void;
}) {
const [type, setType] = useState(defaultType);
const [value, setValue] = useState(defaultValue);
const [goal, setGoal] = useState(defaultGoal);
const { formatMessage, labels } = useMessages();
const items = [
{ label: formatMessage(labels.url), value: 'url' },
{ label: formatMessage(labels.event), value: 'event' },
];
const isDisabled = !type || !value;
const handleSave = () => {
onChange({ type, value, goal });
setValue('');
setGoal(10);
};
const handleChange = (e, set) => {
set(e.target.value);
};
const handleKeyDown = e => {
if (e.key === 'Enter') {
e.stopPropagation();
handleSave();
}
};
const renderTypeValue = (value: any) => {
return items.find(item => item.value === value)?.label;
};
return (
<Flexbox direction="column" gap={10}>
<FormRow label={formatMessage(defaultValue ? labels.update : labels.add)}>
<Flexbox gap={10}>
<Dropdown
className={styles.dropdown}
items={items}
value={type}
renderValue={renderTypeValue}
onChange={(value: any) => setType(value)}
>
{({ value, label }) => {
return <Item key={value}>{label}</Item>;
}}
</Dropdown>
<TextField
className={styles.input}
value={value}
onChange={e => handleChange(e, setValue)}
autoFocus={true}
autoComplete="off"
onKeyDown={handleKeyDown}
/>
</Flexbox>
</FormRow>
<FormRow label={formatMessage(labels.goal)}>
<Flexbox gap={10}>
<TextField
className={styles.input}
value={goal?.toString()}
onChange={e => handleChange(e, setGoal)}
autoComplete="off"
onKeyDown={handleKeyDown}
/>
</Flexbox>
</FormRow>
<FormRow>
<Button variant="primary" onClick={handleSave} disabled={isDisabled}>
{formatMessage(defaultValue ? labels.update : labels.add)}
</Button>
</FormRow>
</Flexbox>
);
}
export default GoalsAddForm;

View File

@ -0,0 +1,95 @@
.chart {
display: grid;
gap: 30px;
}
.goal {
padding-bottom: 40px;
border-bottom: 1px solid var(--base400);
}
.goal:last-child {
border: 0;
}
.card {
display: grid;
gap: 20px;
margin-top: 14px;
}
.header {
display: flex;
flex-direction: column;
gap: 20px;
}
.label {
color: var(--base600);
font-weight: 700;
text-transform: uppercase;
}
.item {
font-size: 20px;
color: var(--base900);
font-weight: 700;
}
.metric {
color: var(--base700);
display: flex;
justify-content: space-between;
gap: 10px;
margin: 10px 0;
text-transform: lowercase;
}
.value {
color: var(--base900);
font-size: 24px;
font-weight: 900;
margin-right: 10px;
}
.percent {
font-size: 20px;
font-weight: 700;
align-self: flex-end;
}
.total {
color: var(--base700);
}
.bar {
display: flex;
align-items: center;
justify-content: flex-end;
background: var(--base900);
height: 10px;
border-radius: 5px;
overflow: hidden;
position: relative;
}
.bar.level1 {
background: var(--red800);
}
.bar.level2 {
background: var(--orange200);
}
.bar.level3 {
background: var(--orange400);
}
.bar.level4 {
background: var(--orange600);
}
.bar.level5 {
background: var(--green600);
}
.track {
background-color: var(--base100);
border-radius: 5px;
}

View File

@ -0,0 +1,57 @@
import { useContext } from 'react';
import classNames from 'classnames';
import { useMessages } from 'components/hooks';
import { ReportContext } from '../[reportId]/Report';
import { formatLongNumber } from 'lib/format';
import styles from './GoalsChart.module.css';
export function GoalsChart({ className }: { className?: string; isLoading?: boolean }) {
const { report } = useContext(ReportContext);
const { formatMessage, labels } = useMessages();
const { data } = report || {};
return (
<div className={classNames(styles.chart, className)}>
{data?.map(({ type, value, goal, result }, index: number) => {
const percent = result > goal ? 100 : (result / goal) * 100;
return (
<div key={index} className={styles.goal}>
<div className={styles.card}>
<div className={styles.header}>
<span className={styles.label}>
{formatMessage(type === 'url' ? labels.viewedPage : labels.triggeredEvent)}
</span>
<span className={styles.item}>{value}</span>
</div>
<div className={styles.track}>
<div
className={classNames(
classNames(styles.bar, {
[styles.level1]: percent <= 20,
[styles.level2]: percent > 20 && percent <= 40,
[styles.level3]: percent > 40 && percent <= 60,
[styles.level4]: percent > 60 && percent <= 80,
[styles.level5]: percent > 80,
}),
)}
style={{ width: `${percent}%` }}
></div>
</div>
<div className={styles.metric}>
<div className={styles.value}>
{formatLongNumber(result)}
<span className={styles.total}> / {formatLongNumber(goal)}</span>
</div>
<div className={styles.percent}>{((result / goal) * 100).toFixed(2)}%</div>
</div>
</div>
</div>
);
})}
</div>
);
}
export default GoalsChart;

View File

@ -0,0 +1,14 @@
.value {
width: 100%;
margin-bottom: 8px;
font-weight: 600;
}
.goal {
color: var(--blue900);
background-color: var(--blue100);
font-size: 12px;
font-weight: 900;
padding: 2px 8px;
border-radius: 5px;
}

View File

@ -0,0 +1,120 @@
import { useMessages } from 'components/hooks';
import Icons from 'components/icons';
import { formatNumber } from 'lib/format';
import { useContext } from 'react';
import {
Button,
Form,
FormButtons,
FormRow,
Icon,
Popup,
PopupTrigger,
SubmitButton,
} from 'react-basics';
import BaseParameters from '../[reportId]/BaseParameters';
import ParameterList from '../[reportId]/ParameterList';
import PopupForm from '../[reportId]/PopupForm';
import { ReportContext } from '../[reportId]/Report';
import GoalsAddForm from './GoalsAddForm';
import styles from './GoalsParameters.module.css';
export function GoalsParameters() {
const { report, runReport, updateReport, isRunning } = useContext(ReportContext);
const { formatMessage, labels } = useMessages();
const { id, parameters } = report || {};
const { websiteId, dateRange, goals } = parameters || {};
const queryDisabled = !websiteId || !dateRange || goals?.length < 1;
const handleSubmit = (data: any, e: any) => {
e.stopPropagation();
e.preventDefault();
if (!queryDisabled) {
runReport(data);
}
};
const handleAddGoals = (goal: { type: string; value: string }) => {
updateReport({ parameters: { goals: parameters.goals.concat(goal) } });
};
const handleUpdateGoals = (
close: () => void,
index: number,
goal: { type: string; value: string },
) => {
const goals = [...parameters.goals];
goals[index] = goal;
updateReport({ parameters: { goals } });
close();
};
const handleRemoveGoals = (index: number) => {
const goals = [...parameters.goals];
delete goals[index];
updateReport({ parameters: { goals: goals.filter(n => n) } });
};
const AddGoalsButton = () => {
return (
<PopupTrigger>
<Button>
<Icon>
<Icons.Plus />
</Icon>
</Button>
<Popup alignment="start">
<PopupForm>
<GoalsAddForm onChange={handleAddGoals} />
</PopupForm>
</Popup>
</PopupTrigger>
);
};
return (
<Form values={parameters} onSubmit={handleSubmit} preventSubmit={true}>
<BaseParameters allowWebsiteSelect={!id} />
<FormRow label={formatMessage(labels.goals)} action={<AddGoalsButton />}>
<ParameterList>
{goals.map((goal: { type: string; value: string; goal: number }, index: number) => {
return (
<PopupTrigger key={index}>
<ParameterList.Item
icon={goal.type === 'url' ? <Icons.Eye /> : <Icons.Bolt />}
onRemove={() => handleRemoveGoals(index)}
>
<div className={styles.value}>{goal.value}</div>
<div className={styles.goal}>
{formatMessage(labels.goal)}: {formatNumber(goal.goal)}
</div>
</ParameterList.Item>
<Popup alignment="start">
{(close: () => void) => (
<PopupForm>
<GoalsAddForm
type={goal.type}
value={goal.value}
goal={goal.goal}
onChange={handleUpdateGoals.bind(null, close, index)}
/>
</PopupForm>
)}
</Popup>
</PopupTrigger>
);
})}
</ParameterList>
</FormRow>
<FormButtons>
<SubmitButton variant="primary" disabled={queryDisabled} isLoading={isRunning}>
{formatMessage(labels.runQuery)}
</SubmitButton>
</FormButtons>
</Form>
);
}
export default GoalsParameters;

View File

@ -0,0 +1,10 @@
.filters {
display: flex;
flex-direction: column;
justify-content: space-between;
border: 1px solid var(--base400);
border-radius: var(--border-radius);
line-height: 32px;
padding: 10px;
overflow: hidden;
}

View File

@ -0,0 +1,27 @@
import GoalsChart from './GoalsChart';
import GoalsParameters from './GoalsParameters';
import Report from '../[reportId]/Report';
import ReportHeader from '../[reportId]/ReportHeader';
import ReportMenu from '../[reportId]/ReportMenu';
import ReportBody from '../[reportId]/ReportBody';
import Target from 'assets/target.svg';
import { REPORT_TYPES } from 'lib/constants';
const defaultParameters = {
type: REPORT_TYPES.goals,
parameters: { goals: [] },
};
export default function GoalsReport({ reportId }: { reportId?: string }) {
return (
<Report reportId={reportId} defaultParameters={defaultParameters}>
<ReportHeader icon={<Target />} />
<ReportMenu>
<GoalsParameters />
</ReportMenu>
<ReportBody>
<GoalsChart />
</ReportBody>
</Report>
);
}

View File

@ -0,0 +1,6 @@
'use client';
import GoalReport from './GoalsReport';
export default function GoalReportPage() {
return <GoalReport />;
}

View File

@ -0,0 +1,10 @@
import GoalsReportPage from './GoalsReportPage';
import { Metadata } from 'next';
export default function () {
return <GoalsReportPage />;
}
export const metadata: Metadata = {
title: 'Goals Report',
};

View File

@ -6,5 +6,5 @@ export default function () {
}
export const metadata: Metadata = {
title: 'UTM Report',
title: 'Goals Report',
};

View File

@ -1,17 +1,24 @@
import DataTable from 'components/common/DataTable';
import TeamsTable from 'app/(main)/settings/teams/TeamsTable';
import { useLogin, useTeams } from 'components/hooks';
import { ReactNode } from 'react';
export function TeamsDataTable({
allowEdit,
showActions,
children,
}: {
allowEdit?: boolean;
showActions?: boolean;
children?: ReactNode;
}) {
const { user } = useLogin();
const queryResult = useTeams(user.id);
if (queryResult?.result?.data?.length === 0) {
return children;
}
return (
<DataTable queryResult={queryResult}>
{({ data }) => {

View File

@ -1,10 +1,21 @@
import DataTable from 'components/common/DataTable';
import { useUsers } from 'components/hooks';
import UsersTable from './UsersTable';
import { ReactNode } from 'react';
export function UsersDataTable({ showActions }: { showActions?: boolean }) {
export function UsersDataTable({
showActions,
children,
}: {
showActions?: boolean;
children?: ReactNode;
}) {
const queryResult = useUsers();
if (queryResult?.result?.data?.length === 0) {
return children;
}
return (
<DataTable queryResult={queryResult}>
{({ data }) => <UsersTable data={data} showActions={showActions} />}

View File

@ -18,6 +18,10 @@ export function WebsitesDataTable({
}) {
const queryResult = useWebsites({ teamId });
if (queryResult?.result?.data?.length === 0) {
return children;
}
return (
<DataTable queryResult={queryResult}>
{({ data }) => (
@ -27,9 +31,7 @@ export function WebsitesDataTable({
showActions={showActions}
allowEdit={allowEdit}
allowView={allowView}
>
{children}
</WebsitesTable>
/>
)}
</DataTable>
);

View File

@ -23,6 +23,10 @@ export function WebsitesTable({
const breakpoint = useBreakpoint();
const { renderTeamUrl } = useTeamUrl();
if (!data?.length) {
return children;
}
return (
<GridTable data={data} cardMode={['xs', 'sm', 'md'].includes(breakpoint)}>
<GridColumn name="name" label={formatMessage(labels.name)} />
@ -55,7 +59,6 @@ export function WebsitesTable({
}}
</GridColumn>
)}
{children}
</GridTable>
);
}

View File

@ -15,14 +15,7 @@ import { WebsiteContext } from 'app/(main)/websites/[websiteId]/WebsiteProvider'
const generateId = () => getRandomChars(16);
export function ShareUrl({
hostUrl,
onSave,
}: {
websiteId: string;
hostUrl?: string;
onSave?: () => void;
}) {
export function ShareUrl({ hostUrl, onSave }: { hostUrl?: string; onSave?: () => void }) {
const website = useContext(WebsiteContext);
const { domain, shareId } = website;
const { formatMessage, labels, messages } = useMessages();
@ -33,8 +26,8 @@ export function ShareUrl({
});
const { touch } = useModified();
const url = `${hostUrl || process.env.hostUrl || window?.location.origin}${
process.env.basePath
const url = `${hostUrl || window?.location.origin || ''}${
process.env.basePath || ''
}/share/${id}/${domain}`;
const handleGenerate = () => {

View File

@ -12,8 +12,8 @@ export function TrackingCode({ websiteId, hostUrl }: { websiteId: string; hostUr
const url = trackerScriptName?.startsWith('http')
? trackerScriptName
: `${hostUrl || process.env.hostUrl || window?.location.origin}${
process.env.basePath
: `${hostUrl || window?.location.origin || ''}${
process.env.basePath || ''
}/${trackerScriptName}`;
const code = `<script defer src="${url}" data-website-id="${websiteId}"></script>`;

View File

@ -13,11 +13,9 @@ import WebsiteEditForm from './WebsiteEditForm';
export function WebsiteSettings({
websiteId,
hostUrl,
openExternal = false,
}: {
websiteId: string;
hostUrl?: string;
openExternal?: boolean;
}) {
const website = useContext(WebsiteContext);
@ -62,8 +60,8 @@ export function WebsiteSettings({
<Item key="data">{formatMessage(labels.data)}</Item>
</Tabs>
{tab === 'details' && <WebsiteEditForm websiteId={websiteId} onSave={handleSave} />}
{tab === 'tracking' && <TrackingCode websiteId={websiteId} hostUrl={hostUrl} />}
{tab === 'share' && <ShareUrl websiteId={websiteId} hostUrl={hostUrl} onSave={handleSave} />}
{tab === 'tracking' && <TrackingCode websiteId={websiteId} />}
{tab === 'share' && <ShareUrl websiteId={websiteId} onSave={handleSave} />}
{tab === 'data' && <WebsiteData websiteId={websiteId} onSave={handleSave} />}
</>
);

View File

@ -13,7 +13,7 @@ export function RealtimeCountries({ data }) {
({ x: code }) => (
<span className={classNames(locale, styles.row)}>
<img
src={`${process.env.basePath}/images/flags/${code?.toLowerCase() || 'xx'}.png`}
src={`${process.env.basePath || ''}/images/flags/${code?.toLowerCase() || 'xx'}.png`}
alt={code}
/>
{countryNames[code]}

View File

@ -3,7 +3,7 @@ import LoginForm from './LoginForm';
import styles from './LoginPage.module.css';
export function LoginPage() {
if (process.env.loginDisabled) {
if (process.env.disableLogin) {
return null;
}

1
src/assets/target.svg Normal file
View File

@ -0,0 +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"><g id="Icon"><path d="m19.393 10.825c-.097-.403.151-.808.553-.905.402-.098.808.15.905.553.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.277.403.097.651.503.553.905-.097.402-.502.65-.905.553-.637-.154-1.302-.235-1.986-.235-4.658 0-8.439 3.781-8.439 8.439s3.781 8.439 8.439 8.439 8.439-3.781 8.439-8.439c0-.684-.081-1.349-.235-1.986z"/><path d="m14.764 12.811c0-.414.336-.75.75-.75.413 0 .75.336.75.75 0 2.8-2.274 5.074-5.075 5.074-2.8 0-5.074-2.274-5.074-5.074 0-2.801 2.274-5.075 5.074-5.075.414 0 .75.337.75.75 0 .414-.336.75-.75.75-1.973 0-3.574 1.602-3.574 3.575s1.601 3.574 3.574 3.574 3.575-1.601 3.575-3.574z"/><path d="m22.53 5.588-3.057 3.058c-.141.141-.332.22-.531.22h-3.058c-.414 0-.75-.336-.75-.75v-3.058c0-.199.079-.39.22-.531l3.058-3.057c.184-.184.45-.26.703-.2s.457.246.539.493l.646 1.937 1.937.646c.247.082.433.286.493.539s-.016.519-.2.703zm-1.918-.202-1.142-.381c-.224-.075-.4-.251-.475-.475l-.381-1.142-1.98 1.98v1.998h1.998z"/><path d="m15.354 7.585c.293-.293.768-.293 1.061 0s.293.768 0 1.061l-4.587 4.586c-.293.293-.768.293-1.06 0-.293-.292-.293-.767 0-1.06z"/></g></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -1,22 +1,8 @@
.table {
grid-template-rows: repeat(auto-fit, max-content);
}
.table td {
align-items: center;
max-height: max-content;
}
.search {
max-width: 300px;
margin: 20px 0;
}
.action {
justify-content: flex-end;
gap: 5px;
}
.body {
display: flex;
flex-direction: column;

View File

@ -4,8 +4,8 @@ import { Banner, Loading, SearchField } from 'react-basics';
import { useMessages } from 'components/hooks';
import Empty from 'components/common/Empty';
import Pager from 'components/common/Pager';
import styles from './DataTable.module.css';
import { FilterQueryResult } from 'lib/types';
import styles from './DataTable.module.css';
const DEFAULT_SEARCH_DELAY = 600;

View File

@ -1,6 +1,6 @@
import { useMemo, useRef } from 'react';
import { RealtimeData } from 'lib/types';
import { useApi } from 'components/hooks';
import { useApi } from './useApi';
import { REALTIME_INTERVAL, REALTIME_RANGE } from 'lib/constants';
import { startOfMinute, subMinutes } from 'date-fns';
import { percentFilter } from 'lib/filters';

View File

@ -1,4 +1,4 @@
import { useApi } from 'components/hooks';
import { useApi } from './useApi';
export function useWebsiteValues({
websiteId,

View File

@ -10,7 +10,7 @@ export function useCountryNames(locale: string) {
const [list, setList] = useState(countryNames[locale] || enUS);
async function loadData(locale: string) {
const { data } = await httpGet(`${process.env.basePath}/intl/country/${locale}.json`);
const { data } = await httpGet(`${process.env.basePath || ''}/intl/country/${locale}.json`);
if (data) {
countryNames[locale] = data;

View File

@ -10,7 +10,7 @@ export function useLanguageNames(locale) {
const [list, setList] = useState(languageNames[locale] || enUS);
async function loadData(locale) {
const { data } = await httpGet(`${process.env.basePath}/intl/language/${locale}.json`);
const { data } = await httpGet(`${process.env.basePath || ''}/intl/language/${locale}.json`);
if (data) {
languageNames[locale] = data;

View File

@ -19,7 +19,9 @@ export function useLocale() {
const dateLocale = getDateLocale(locale);
async function loadMessages(locale: string) {
const { ok, data } = await httpGet(`${process.env.basePath}/intl/messages/${locale}.json`);
const { ok, data } = await httpGet(
`${process.env.basePath || ''}/intl/messages/${locale}.json`,
);
if (ok) {
messages[locale] = data;

View File

@ -235,6 +235,13 @@ export const labels = defineMessages({
},
steps: { id: 'label.steps', defaultMessage: 'Steps' },
addStep: { id: 'label.add-step', defaultMessage: 'Add step' },
goal: { id: 'label.goal', defaultMessage: 'Goal' },
goals: { id: 'label.goals', defaultMessage: 'Goals' },
goalsDescription: {
id: 'label.goals-description',
defaultMessage: 'Track your goals for pageviews or events.',
},
count: { id: 'label.count', defaultMessage: 'Count' },
});
export const messages = defineMessages({

View File

@ -11,7 +11,7 @@ export function BrowsersTable(props: MetricsTableProps) {
return (
<FilterLink id="browser" value={browser} label={formatBrowser(browser)}>
<img
src={`${process.env.basePath}/images/browsers/${browser || 'unknown'}.png`}
src={`${process.env.basePath || ''}/images/browsers/${browser || 'unknown'}.png`}
alt={browser}
width={16}
height={16}

View File

@ -20,7 +20,7 @@ export function CitiesTable(props: MetricsTableProps) {
<FilterLink id="city" value={city} label={renderLabel(city, country)}>
{country && (
<img
src={`${process.env.basePath}/images/flags/${country?.toLowerCase() || 'xx'}.png`}
src={`${process.env.basePath || ''}/images/flags/${country?.toLowerCase() || 'xx'}.png`}
alt={country}
/>
)}

View File

@ -27,7 +27,7 @@ export function CountriesTable({
label={formatCountry(code)}
>
<img
src={`${process.env.basePath}/images/flags/${code?.toLowerCase() || 'xx'}.png`}
src={`${process.env.basePath || ''}/images/flags/${code?.toLowerCase() || 'xx'}.png`}
alt={code}
/>
</FilterLink>

View File

@ -11,7 +11,9 @@ export function DevicesTable(props: MetricsTableProps) {
return (
<FilterLink id="device" value={labels[device] && device} label={formatDevice(device)}>
<img
src={`${process.env.basePath}/images/device/${device?.toLowerCase() || 'unknown'}.png`}
src={`${process.env.basePath || ''}/images/device/${
device?.toLowerCase() || 'unknown'
}.png`}
alt={device}
width={16}
height={16}

View File

@ -20,7 +20,7 @@ export function RegionsTable(props: MetricsTableProps) {
return (
<FilterLink id="region" className={locale} value={code} label={renderLabel(code, country)}>
<img
src={`${process.env.basePath}/images/flags/${country?.toLowerCase() || 'xx'}.png`}
src={`${process.env.basePath || ''}/images/flags/${country?.toLowerCase() || 'xx'}.png`}
alt={code}
/>
</FilterLink>

View File

@ -54,7 +54,7 @@ export function WorldMap({ data = [], className }: { data?: any[]; className?: s
>
<ComposableMap projection="geoMercator">
<ZoomableGroup zoom={0.8} minZoom={0.7} center={[0, 40]}>
<Geographies geography={`${process.env.basePath}${MAP_FILE}`}>
<Geographies geography={`${process.env.basePath || ''}${MAP_FILE}`}>
{({ geographies }) => {
return geographies.map(geo => {
const code = ISO_COUNTRIES[geo.id];

View File

@ -1,246 +1,246 @@
{
"label.access-code": "Código de acesso",
"label.actions": "Ações",
"label.activity-log": "Log de atividade",
"label.add": "Add",
"label.add-description": "Add description",
"label.add-member": "Add member",
"label.add-step": "Add step",
"label.actions": "Ações do usuário",
"label.activity-log": "Registro de atividades",
"label.add": "Adicionar",
"label.add-description": "Adicionar descrição",
"label.add-member": "Adicionar membro",
"label.add-step": "Adicionar etapa",
"label.add-website": "Adicionar site",
"label.admin": "Administrador",
"label.after": "Depois",
"label.all": "Todos",
"label.all-time": "Todo o período",
"label.analytics": "Estatísticas",
"label.average": "Average",
"label.average-visit-time": "Tempo médio da visita",
"label.all-time": "Todos os períodos",
"label.analytics": "Análise",
"label.average": "Média",
"label.average-visit-time": "Tempo médio de visita",
"label.back": "Voltar",
"label.before": "Antes",
"label.bounce-rate": "Taxa de rejeição",
"label.breakdown": "Breakdown",
"label.browser": "Browser",
"label.breakdown": "Detalhamento",
"label.browser": "Navegador",
"label.browsers": "Navegadores",
"label.cancel": "Cancelar",
"label.change-password": "Alterar a senha",
"label.change-password": "Alterar senha",
"label.cities": "Cidades",
"label.city": "City",
"label.city": "Cidade",
"label.clear-all": "Limpar tudo",
"label.confirm": "Confirmar",
"label.confirm-password": "Confirme a nova senha",
"label.contains": "Contains",
"label.confirm-password": "Confirmar senha",
"label.contains": "Contém",
"label.continue": "Continuar",
"label.countries": "Países",
"label.country": "Country",
"label.create": "Create",
"label.country": "País",
"label.create": "Criar",
"label.create-report": "Criar relatório",
"label.create-team": "Criar time",
"label.create-team": "Criar equipe",
"label.create-user": "Criar usuário",
"label.created": "Criado",
"label.created-by": "Created By",
"label.created-by": "Criado por",
"label.current-password": "Senha atual",
"label.custom-range": "Intervalo personalizado",
"label.custom-range": "Período personalizado",
"label.dashboard": "Painel",
"label.data": "Data",
"label.date": "Date",
"label.date-range": "Intervalo de datas",
"label.day": "Day",
"label.default-date-range": "Intervalo de datas predefinido",
"label.delete": "Remover",
"label.delete-report": "Delete report",
"label.delete-team": "Remover time",
"label.delete-user": "Remover usuário",
"label.delete-website": "Remover site",
"label.data": "Dados",
"label.date": "Data",
"label.date-range": "Período",
"label.day": "Dia",
"label.default-date-range": "Período padrão",
"label.delete": "Excluir",
"label.delete-report": "Excluir relatório",
"label.delete-team": "Excluir equipe",
"label.delete-user": "Excluir usuário",
"label.delete-website": "Excluir site",
"label.description": "Descrição",
"label.desktop": "Computador",
"label.desktop": "Desktop",
"label.details": "Detalhes",
"label.device": "Device",
"label.device": "Dispositivo",
"label.devices": "Dispositivos",
"label.dismiss": "Dispensar",
"label.does-not-contain": "Does not contain",
"label.dismiss": "Fechar",
"label.does-not-contain": "Não contém",
"label.domain": "Domínio",
"label.dropoff": "Dropoff",
"label.dropoff": "Abandono",
"label.edit": "Editar",
"label.edit-dashboard": "Editar painel",
"label.edit-member": "Edit member",
"label.enable-share-url": "Ativar link de compartilhamento",
"label.edit-member": "Editar membro",
"label.enable-share-url": "Ativar link para compartilhar",
"label.event": "Evento",
"label.event-data": "Event data",
"label.events": "Eventos",
"label.false": "False",
"label.event-data": "Dados do evento",
"label.events": "Tipos de eventos",
"label.false": "Não",
"label.field": "Campo",
"label.fields": "Campos",
"label.filter": "Filter",
"label.filter": "Filtro",
"label.filter-combined": "Combinado",
"label.filter-raw": "Dados brutos",
"label.filters": "Filters",
"label.filter-raw": "Bruto",
"label.filters": "Filtros",
"label.funnel": "Funil",
"label.funnel-description": "Understand the conversion and drop-off rate of users.",
"label.funnel-description": "Entenda a taxa de conversão e abandono dos seus usuários.",
"label.greater-than": "Maior que",
"label.greater-than-equals": "Maior que ou igual",
"label.greater-than-equals": "Maior ou igual a",
"label.insights": "Insights",
"label.insights-description": "Dive deeper into your data by using segments and filters.",
"label.is": "Is",
"label.is-not": "Is not",
"label.is-not-set": "Is not set",
"label.is-set": "Is set",
"label.join": "Entrar",
"label.join-team": "Entrar no time",
"label.language": "Idioma",
"label.insights-description": "Explore seus dados em mais detalhes usando filtros",
"label.is": "É igual a",
"label.is-not": "Não é igual a",
"label.is-not-set": "Não definido",
"label.is-set": "Definido",
"label.join": "Participar",
"label.join-team": "Participar da equipe",
"label.language": "Idioma",
"label.languages": "Idiomas",
"label.laptop": "Notebook",
"label.last-days": "Últimos {x} dias",
"label.last-hours": "Últimas {x} horas",
"label.last-months": "Last {x} months",
"label.leave": "Sair",
"label.leave-team": "Sair do time",
"label.last-months": "Últimos {x} meses",
"label.leave": "Sair",
"label.leave-team": "Sair da equipe",
"label.less-than": "Menor que",
"label.less-than-equals": "Menor que ou igual",
"label.login": "Iniciar sessão",
"label.less-than-equals": "Menor ou igual a",
"label.login": "Entrar",
"label.logout": "Sair",
"label.manage": "Manage",
"label.max": "Max",
"label.member": "Member",
"label.manage": "Gerenciar",
"label.max": "Máximo",
"label.member": "Membro",
"label.members": "Membros",
"label.min": "Min",
"label.mobile": "Celular",
"label.min": "Mínimo",
"label.mobile": "Celular",
"label.more": "Mais",
"label.my-account": "My account",
"label.my-websites": "My websites",
"label.my-account": "Minha conta",
"label.my-websites": "Meus sites",
"label.name": "Nome",
"label.new-password": "Nova senha",
"label.none": "Nenhum",
"label.number-of-records": "{x} {x, plural, one {record} other {records}}",
"label.number-of-records": "{x} {x, plural, one {registro} other {registros}}",
"label.ok": "OK",
"label.os": "OS",
"label.overview": "Overview",
"label.os": "Sistema operacional",
"label.overview": "Visão geral",
"label.owner": "Proprietário",
"label.page-of": "Page {current} of {total}",
"label.page-of": "Página {current} de {total}",
"label.page-views": "Visualizações de página",
"label.pageTitle": "Page title",
"label.pageTitle": "Título",
"label.pages": "Páginas",
"label.password": "Senha",
"label.powered-by": "Distribuído por {name}",
"label.password": "Senha",
"label.powered-by": "Desenvolvido por {name}",
"label.profile": "Perfil",
"label.queries": "Parâmetros",
"label.query": "Query",
"label.query-parameters": "Parâmetros de Consulta",
"label.queries": "Consultas",
"label.query": "Consulta",
"label.query-parameters": "Parâmetros da consulta",
"label.realtime": "Tempo real",
"label.referrer": "Referrer",
"label.referrer": "Referência",
"label.referrers": "Referências",
"label.refresh": "Atualizar",
"label.regenerate": "Regerar",
"label.region": "Region",
"label.regions": "Regiões",
"label.regenerate": "Gerar novamente",
"label.region": "Estado",
"label.regions": "Estados",
"label.remove": "Remover",
"label.remove-member": "Remove member",
"label.reports": "Reports",
"label.remove-member": "Remover membro",
"label.reports": "Relatórios",
"label.required": "Obrigatório",
"label.reset": "Redefinir",
"label.reset-website": "Redefinir estatísticas",
"label.retention": "Retention",
"label.retention-description": "Measure your website stickiness by tracking how often users return.",
"label.role": "Papel",
"label.run-query": "Executar query",
"label.reset-website": "Redefinir dados",
"label.retention": "Retenção",
"label.retention-description": "Avalie a fidelidade dos seus usuários medindo a frequência com que eles retornam.",
"label.role": "Função",
"label.run-query": "Executar consulta",
"label.save": "Salvar",
"label.screens": "Telas",
"label.search": "Search",
"label.select": "Select",
"label.screens": "Tamanhos de tela",
"label.search": "Pesquisar",
"label.select": "Selecionar",
"label.select-date": "Selecionar data",
"label.select-role": "Select role",
"label.select-role": "Selecionar função",
"label.select-website": "Selecionar site",
"label.sessions": "Sessões",
"label.settings": "Configurações",
"label.share-url": "Link de compartilhamento",
"label.single-day": "Dia específico",
"label.steps": "Steps",
"label.sum": "Sum",
"label.share-url": "Link para compartilhar",
"label.single-day": "Apenas um dia",
"label.steps": "Etapas",
"label.sum": "Soma",
"label.tablet": "Tablet",
"label.team": "Time",
"label.team-id": "ID do Time",
"label.team-member": "Membro",
"label.team-name": "Team name",
"label.team-owner": "Proprietário",
"label.team-view-only": "Team view only",
"label.team-websites": "Team websites",
"label.teams": "Times",
"label.team": "Equipe",
"label.team-id": "ID da equipe",
"label.team-member": "Membro da equipe",
"label.team-name": "Nome da equipe",
"label.team-owner": "Proprietário da equipe",
"label.team-view-only": "Apenas visualização da equipe",
"label.team-websites": "Sites da equipe",
"label.teams": "Equipes",
"label.theme": "Tema",
"label.this-month": "Este mês",
"label.this-week": "Esta semana",
"label.this-month": "Este mês",
"label.this-week": "Esta semana",
"label.this-year": "Este ano",
"label.timezone": "Fuso horário",
"label.title": "Título",
"label.today": "Hoje",
"label.toggle-charts": "Mostrar/Esconder gráficos",
"label.today": "Hoje",
"label.toggle-charts": "Alternar gráficos",
"label.total": "Total",
"label.total-records": "Total records",
"label.total-records": "Total de registros",
"label.tracking-code": "Código de rastreamento",
"label.transfer": "Transfer",
"label.transfer-website": "Transfer website",
"label.true": "True",
"label.type": "Tipo",
"label.unique": "Único",
"label.transfer": "Transferir",
"label.transfer-website": "Transferir site",
"label.true": "Sim",
"label.type": "Tipo",
"label.unique": "Únicos",
"label.unique-visitors": "Visitantes únicos",
"label.unknown": "Desconhecido",
"label.untitled": "Sem título",
"label.update": "Update",
"label.url": "URL",
"label.update": "Atualizar",
"label.url": "URL",
"label.urls": "URLs",
"label.user": "Usuário",
"label.username": "Nome de usuário",
"label.username": "Nome de usuário",
"label.users": "Usuários",
"label.utm": "UTM",
"label.utm-description": "Track your campaigns through UTM parameters.",
"label.value": "Valor",
"label.view": "Ver",
"label.view-details": "Ver detalhes",
"label.utm-description": "Acompanhe suas campanhas de publicidade através de parâmetros UTM.",
"label.value": "Valor",
"label.view": "Visualizar",
"label.view-details": "Ver mais",
"label.view-only": "Somente visualização",
"label.views": "Visualizações",
"label.views-per-visit": "Views per visit",
"label.visitors": "Visitantes",
"label.visits": "Visits",
"label.website": "Website",
"label.website-id": "ID do Site",
"label.views-per-visit": "Visualizações por visita",
"label.visitors": "Visitantes",
"label.visits": "Visitas",
"label.website": "Site",
"label.website-id": "ID do site",
"label.websites": "Sites",
"label.window": "Janela",
"label.yesterday": "Ontem",
"message.action-confirmation": "Type {confirmation} in the box below to confirm.",
"message.active-users": "{x} {x, plural, one {visitante} other {visitantes}} neste momento",
"message.confirm-delete": "Deseja realmente remover {target}?",
"message.confirm-leave": "Você tem certeza que deseja sair de {target}?",
"message.confirm-remove": "Are you sure you want to remove {target}?",
"message.confirm-reset": "Você tem certeza que deseja redefinir as estatísticas de {target}?",
"message.delete-team-warning": "Deleting a team will also delete all team websites.",
"message.delete-website-warning": "Todos os dados associados também serão eliminados.",
"label.yesterday": "Ontem",
"message.action-confirmation": "Digite {confirmation} na caixa abaixo para confirmar.",
"message.active-users": " Atualmente {x} usuários ativos",
"message.confirm-delete": "Tem certeza de que deseja excluir {target}?",
"message.confirm-leave": "Tem certeza de que deseja sair de {target}?",
"message.confirm-remove": "Tem certeza que deseja remover {target}?",
"message.confirm-reset": "Tem certeza que deseja redefinir os dados de {target}?",
"message.delete-team-warning": "Excluir a equipe também excluirá todos os sites da equipe.",
"message.delete-website-warning": "Todos os dados relacionados serão excluídos.",
"message.error": "Ocorreu um erro.",
"message.event-log": "{event} em {url}",
"message.go-to-settings": "Ir para as configurações",
"message.incorrect-username-password": "O nome de usuário e/ou senha está incorreto.",
"message.incorrect-username-password": "Nome de usuário ou senha incorretos.",
"message.invalid-domain": "Domínio inválido",
"message.min-password-length": "Quantidade mínima de {n} caracteres",
"message.new-version-available": "Uma nova versão do Umami {version} está disponível!",
"message.no-data-available": "Sem dados disponíveis.",
"message.no-event-data": "Nenhum dado de evento está disponível.",
"message.no-match-password": "As senhas não correspondem",
"message.no-results-found": "Nenhum resultado foi encontrado.",
"message.no-team-websites": "Este time não possui nenhum site.",
"message.no-teams": "Você não criou nenhum time.",
"message.no-users": "Não há nenhum usuário.",
"message.no-websites-configured": "Nenhum site foi configurado ainda.",
"message.min-password-length": "A senha deve ter no mínimo {n} caracteres",
"message.new-version-available": "Uma nova versão {version} do Umami está disponível!",
"message.no-data-available": "Não há dados disponíveis.",
"message.no-event-data": "Não há eventos disponíveis.",
"message.no-match-password": "As senhas não coincidem.",
"message.no-results-found": "Nenhum resultado encontrado.",
"message.no-team-websites": "Esta equipe não possui sites.",
"message.no-teams": "Você ainda não criou nenhuma equipe.",
"message.no-users": "Não há usuários.",
"message.no-websites-configured": "Você ainda não configurou nenhum site.",
"message.page-not-found": "Página não encontrada.",
"message.reset-website": "Para redefinir este site, digite {confirmation} na caixa abaixo para confirmar.",
"message.reset-website-warning": "Todas as estatísticas deste site serão removidas, mas seu código de rastreamento permanecerá intacto.",
"message.reset-website": "Se você tiver certeza de que deseja redefinir este site, digite {confirmation} na caixa de entrada abaixo para confirmar.",
"message.reset-website-warning": "Todos os dados estatísticos deste site serão excluídos, mas seu código de rastreamento permanecerá o mesmo.",
"message.saved": "Salvo com sucesso.",
"message.share-url": "Este é o link público de compartilhamento para {target}.",
"message.team-already-member": "Você já um membro do time.",
"message.team-not-found": "Time não encontrado.",
"message.team-websites-info": "Os sites podem ser visualizados por qualquer membro da equipe.",
"message.share-url": "Este é o link para compartilhar {target}.",
"message.team-already-member": "Você já é membro desta equipe.",
"message.team-not-found": "Equipe não encontrada.",
"message.team-websites-info": "Qualquer membro da equipe pode visualizar os sites.",
"message.tracking-code": "Código de rastreamento",
"message.transfer-team-website-to-user": "Transfer this website to your account?",
"message.transfer-user-website-to-team": "Select the team to transfer this website to.",
"message.transfer-website": "Transfer website ownership to your account or another team.",
"message.triggered-event": "Triggered event",
"message.user-deleted": "Usuário removido.",
"message.viewed-page": "Viewed page",
"message.visitor-log": "Visitante de {country} usando {browser} no {device} {os}",
"message.visitors-dropped-off": "Visitors dropped off"
}
"message.transfer-team-website-to-user": "Transferir este site para sua conta?",
"message.transfer-user-website-to-team": "Selecione para qual equipe deseja transferir este site.",
"message.transfer-website": "Transfira a propriedade do site para sua conta ou para outra equipe.",
"message.triggered-event": "Evento disparado",
"message.user-deleted": "Usuário excluído.",
"message.viewed-page": "Página visualizada",
"message.visitor-log": "Visitante de {country} usando o navegador {browser} em um {device} com sistema operacional {os}.",
"message.visitors-dropped-off": "Visitantes abandonados"
}

View File

@ -1,122 +1,122 @@
{
"label.access-code": "Access code",
"label.access-code": "Код доступу",
"label.actions": "Дії",
"label.activity-log": "Activity log",
"label.add": "Add",
"label.add-description": "Add description",
"label.add-member": "Add member",
"label.add-step": "Add step",
"label.activity-log": "Журнал активності",
"label.add": "Додати",
"label.add-description": "Додати опис",
"label.add-member": "Додати учасника",
"label.add-step": "Додати крок",
"label.add-website": "Додати сайт",
"label.admin": "Адміністратор",
"label.after": "After",
"label.after": "Після",
"label.all": "Всі",
"label.all-time": "Весь час",
"label.analytics": "Analytics",
"label.average": "Average",
"label.analytics": "Аналітика",
"label.average": "Середнє",
"label.average-visit-time": "Середній час візиту",
"label.back": "Назад",
"label.before": "Before",
"label.before": "Раніше",
"label.bounce-rate": "Показник відмов",
"label.breakdown": "Breakdown",
"label.browser": "Browser",
"label.breakdown": "Розподіл",
"label.browser": "Браузер",
"label.browsers": "Браузери",
"label.cancel": "Відмінити",
"label.change-password": "Змінити пароль",
"label.cities": "Cities",
"label.city": "City",
"label.clear-all": "Clear all",
"label.confirm": "Confirm",
"label.cities": "Міста",
"label.city": "Місто",
"label.clear-all": "Очистити все",
"label.confirm": "Підтвердити",
"label.confirm-password": "Підтвердити пароль",
"label.contains": "Contains",
"label.continue": "Continue",
"label.contains": "Містить",
"label.continue": "Продовжити",
"label.countries": "Країни",
"label.country": "Country",
"label.create": "Create",
"label.create-report": "Create report",
"label.create-team": "Create team",
"label.create-user": "Create user",
"label.created": "Created",
"label.created-by": "Created By",
"label.country": "Країна",
"label.create": "Створити",
"label.create-report": "Створити звіт",
"label.create-team": "Створити команду",
"label.create-user": "Створити користувача",
"label.created": "Створено",
"label.created-by": "Автор",
"label.current-password": "Поточний пароль",
"label.custom-range": "Довільний період",
"label.dashboard": "Інформаційна панель",
"label.data": "Data",
"label.date": "Date",
"label.data": "Дані",
"label.date": "Дата",
"label.date-range": "Діапазон дат",
"label.day": "Day",
"label.day": "День",
"label.default-date-range": "Діапазон дат за замовчуванням",
"label.delete": "Видалити",
"label.delete-report": "Delete report",
"label.delete-team": "Delete team",
"label.delete-user": "Delete user",
"label.delete-report": "Видалити звіт",
"label.delete-team": "Видалити команду",
"label.delete-user": "Видалити користувача",
"label.delete-website": "Видалити сайт",
"label.description": "Description",
"label.description": "Опис",
"label.desktop": "Настільний ПК",
"label.details": "Details",
"label.device": "Device",
"label.details": "Деталі",
"label.device": "Пристрій",
"label.devices": "Пристрої",
"label.dismiss": "Відхилити",
"label.does-not-contain": "Does not contain",
"label.does-not-contain": "Не містить",
"label.domain": "Домен",
"label.dropoff": "Dropoff",
"label.edit": "Редагувати",
"label.edit-dashboard": "Edit dashboard",
"label.edit-member": "Edit member",
"label.edit-dashboard": "Редагувати панель",
"label.edit-member": "Редагувати учасника",
"label.enable-share-url": "Дозволити ділитися посиланням",
"label.event": "Event",
"label.event-data": "Event data",
"label.event": "Подія",
"label.event-data": "Дані події",
"label.events": "Події",
"label.false": "False",
"label.field": "Field",
"label.fields": "Fields",
"label.filter": "Filter",
"label.field": "Поле",
"label.fields": "Поля",
"label.filter": "Фільтр",
"label.filter-combined": "Об'єднані",
"label.filter-raw": "Сирі дані",
"label.filters": "Filters",
"label.filters": "Фільтри",
"label.funnel": "Funnel",
"label.funnel-description": "Understand the conversion and drop-off rate of users.",
"label.greater-than": "Greater than",
"label.greater-than-equals": "Greater than or equals",
"label.greater-than": "Більше ніж",
"label.greater-than-equals": "Більше або рівно",
"label.insights": "Insights",
"label.insights-description": "Dive deeper into your data by using segments and filters.",
"label.is": "Is",
"label.is-not": "Is not",
"label.is-not-set": "Is not set",
"label.is-set": "Is set",
"label.join": "Join",
"label.join-team": "Join team",
"label.language": "Language",
"label.is": "Є",
"label.is-not": "Не є",
"label.is-not-set": "Не встановлено",
"label.is-set": "Встановлено",
"label.join": "Приєднатись",
"label.join-team": "Приєднатись до команди",
"label.language": "Мова",
"label.languages": "Мови",
"label.laptop": "Ноутбук",
"label.last-days": "Останні {x} днів",
"label.last-hours": "Останні {x} годин",
"label.last-months": "Last {x} months",
"label.leave": "Leave",
"label.leave-team": "Leave team",
"label.less-than": "Less than",
"label.less-than-equals": "Less than or equals",
"label.last-months": "Останні {x} місяців",
"label.leave": "Покинути",
"label.leave-team": "Покинути",
"label.less-than": "Менше ніж",
"label.less-than-equals": "Менше або рівно",
"label.login": "Увійти",
"label.logout": "Вийти",
"label.manage": "Manage",
"label.manage": "Керувати",
"label.max": "Max",
"label.member": "Member",
"label.members": "Members",
"label.member": "Учасник",
"label.members": "Учасники",
"label.min": "Min",
"label.mobile": "Мобільний",
"label.more": "Більше",
"label.my-account": "My account",
"label.my-websites": "My websites",
"label.my-account": "Мої аккаунти",
"label.my-websites": "Мої вебсайти",
"label.name": "Ім'я",
"label.new-password": "Новий пароль",
"label.none": "None",
"label.number-of-records": "{x} {x, plural, one {record} other {records}}",
"label.ok": "OK",
"label.os": "OS",
"label.overview": "Overview",
"label.overview": "Огляд",
"label.owner": "Власник",
"label.page-of": "Page {current} of {total}",
"label.page-of": "Сторінка {current} з {total}",
"label.page-views": "Перегляди сторінок",
"label.pageTitle": "Page title",
"label.pageTitle": "Загловок сторінки",
"label.pages": "Сторінки",
"label.password": "Пароль",
"label.powered-by": "На базі {name}",
@ -129,46 +129,46 @@
"label.referrers": "Джерела",
"label.refresh": "Оновити",
"label.regenerate": "Regenerate",
"label.region": "Region",
"label.regions": "Regions",
"label.remove": "Remove",
"label.remove-member": "Remove member",
"label.reports": "Reports",
"label.region": "Регіон",
"label.regions": "Регіони",
"label.remove": "Видалити",
"label.remove-member": "Видалити учасника",
"label.reports": "Звіти",
"label.required": "Обов'язкове",
"label.reset": "Скинути",
"label.reset-website": "Скинути статистику сайту",
"label.retention": "Retention",
"label.retention-description": "Measure your website stickiness by tracking how often users return.",
"label.role": "Role",
"label.role": "Роль",
"label.run-query": "Run query",
"label.save": "Зберегти",
"label.screens": "Screens",
"label.search": "Search",
"label.select": "Select",
"label.screens": "Екрани",
"label.search": "Пошук",
"label.select": "Вибір",
"label.select-date": "Select date",
"label.select-role": "Select role",
"label.select-website": "Select website",
"label.sessions": "Sessions",
"label.sessions": "Сесії",
"label.settings": "Налаштування",
"label.share-url": "Поділитися посилання",
"label.single-day": "Один день",
"label.steps": "Steps",
"label.sum": "Sum",
"label.steps": "Кроки",
"label.sum": "Сума",
"label.tablet": "Планшет",
"label.team": "Team",
"label.team-id": "Team ID",
"label.team-member": "Team member",
"label.team-name": "Team name",
"label.team-owner": "Team owner",
"label.team-view-only": "Team view only",
"label.team-websites": "Team websites",
"label.teams": "Teams",
"label.theme": "Theme",
"label.team": "Команда",
"label.team-id": "ID команди",
"label.team-member": "Учасник команди",
"label.team-name": "Назва команди",
"label.team-owner": "Власник команди",
"label.team-view-only": "Лише для перегляду командою",
"label.team-websites": "Вебсайти команди",
"label.teams": "Команди",
"label.theme": "Теми",
"label.this-month": "Цього місяця",
"label.this-week": "Цього тижня",
"label.this-year": "Цього ріку",
"label.timezone": "Часовий пояс",
"label.title": "Title",
"label.title": "Загловок",
"label.today": "Сьогодні",
"label.toggle-charts": "Переключити графіки",
"label.total": "Total",
@ -177,39 +177,39 @@
"label.transfer": "Transfer",
"label.transfer-website": "Transfer website",
"label.true": "True",
"label.type": "Type",
"label.unique": "Unique",
"label.type": "Типу",
"label.unique": "Унікальний",
"label.unique-visitors": "Унікальні відвідувачі",
"label.unknown": "Невідомо",
"label.untitled": "Untitled",
"label.update": "Update",
"label.untitled": "Без заголовку",
"label.update": "Оновити",
"label.url": "URL",
"label.urls": "URLs",
"label.user": "User",
"label.user": "Користувач",
"label.username": "Ім'я користувача",
"label.users": "Users",
"label.users": "Користувачі",
"label.utm": "UTM",
"label.utm-description": "Track your campaigns through UTM parameters.",
"label.value": "Value",
"label.view": "View",
"label.value": "Значення",
"label.view": "Перегляд",
"label.view-details": "Переглянути деталі",
"label.view-only": "View only",
"label.view-only": "Лише для перегляду",
"label.views": "Перегляди",
"label.views-per-visit": "Views per visit",
"label.views-per-visit": "Перегляди за візит",
"label.visitors": "Відвідувачі",
"label.visits": "Visits",
"label.website": "Website",
"label.website-id": "Website ID",
"label.visits": "Відвідування",
"label.website": "Вебсайт",
"label.website-id": "Вебсайт ID",
"label.websites": "Сайти",
"label.window": "Window",
"label.yesterday": "Yesterday",
"message.action-confirmation": "Type {confirmation} in the box below to confirm.",
"label.window": "Вікно",
"label.yesterday": "Вчора",
"message.action-confirmation": "Введі {confirmation} у поле нижче для підтвердження.",
"message.active-users": "{x} поточних відвідувачів",
"message.confirm-delete": "Ви впевнені, що бажаєте видалити {target}?",
"message.confirm-leave": "Are you sure you want to leave {target}?",
"message.confirm-remove": "Are you sure you want to remove {target}?",
"message.confirm-leave": "Ви впевнені, що хочете покинути {target}?",
"message.confirm-remove": "Ви впевнеі, що хочете видалити {target}?",
"message.confirm-reset": "Ви впевнені, що бажаєте скинути статистику для {target}?",
"message.delete-team-warning": "Deleting a team will also delete all team websites.",
"message.delete-team-warning": "Видалення команди також видалить усі вебсайти команди.",
"message.delete-website-warning": "Усі пов'язані дані будуть видалені також.",
"message.error": "Щось пішло не так.",
"message.event-log": "{event} on {url}",
@ -221,26 +221,26 @@
"message.no-data-available": "Немає даних.",
"message.no-event-data": "No event data is available.",
"message.no-match-password": "Паролі не співпадають",
"message.no-results-found": "No results were found.",
"message.no-team-websites": "This team does not have any websites.",
"message.no-teams": "You have not created any teams.",
"message.no-users": "There are no users.",
"message.no-results-found": "Результатів не знайдено.",
"message.no-team-websites": "Ця команди не має жодних вебсайтів.",
"message.no-teams": "Ви не створили жодної команди.",
"message.no-users": "Користувачів не має.",
"message.no-websites-configured": "У вас немає налаштованих сайтів.",
"message.page-not-found": "Сторінку не знайдено.",
"message.reset-website": "To reset this website, type {confirmation} in the box below to confirm.",
"message.reset-website-warning": "Вся статистика для цього сайту буде видалена, проте код відслідковування буде продовжувати працювати.",
"message.saved": "Збережено успішно.",
"message.share-url": "Це публічне посилання для {target}.",
"message.team-already-member": "You are already a member of the team.",
"message.team-not-found": "Team not found.",
"message.team-websites-info": "Websites can be viewed by anyone on the team.",
"message.team-already-member": "Ви уже є учасником цієї команди.",
"message.team-not-found": "Команду не знайдено.",
"message.team-websites-info": "Вебсайти може переглядати кожен учаник команди.",
"message.tracking-code": "Код для відслідковування",
"message.transfer-team-website-to-user": "Transfer this website to your account?",
"message.transfer-user-website-to-team": "Select the team to transfer this website to.",
"message.transfer-website": "Transfer website ownership to your account or another team.",
"message.triggered-event": "Triggered event",
"message.user-deleted": "User deleted.",
"message.viewed-page": "Viewed page",
"message.user-deleted": "Користувача видалено.",
"message.viewed-page": "Переглянута сторінка",
"message.visitor-log": "Відвідувач з {country} використовуючи {browser} на {os} {device}",
"message.visitors-dropped-off": "Visitors dropped off"
}

View File

@ -119,7 +119,10 @@ async function parseFilters(websiteId: string, filters: QueryFilters = {}, optio
};
}
async function rawQuery(query: string, params: Record<string, unknown> = {}): Promise<unknown> {
async function rawQuery<T = unknown>(
query: string,
params: Record<string, unknown> = {},
): Promise<T> {
if (process.env.LOG_QUERY) {
log('QUERY:\n', query);
log('PARAMETERS:\n', params);

View File

@ -111,6 +111,7 @@ export const DATA_TYPES = {
export const REPORT_TYPES = {
funnel: 'funnel',
goals: 'goals',
insights: 'insights',
retention: 'retention',
utm: 'utm',

View File

@ -27,7 +27,7 @@ const schema: YupRequest = {
websiteId: yup.string().uuid().required(),
type: yup
.string()
.matches(/funnel|insights|retention|utm/i)
.matches(/funnel|insights|retention|utm|goals/i)
.required(),
name: yup.string().max(200).required(),
description: yup.string().max(500),

View File

@ -0,0 +1,70 @@
import { canViewWebsite } from 'lib/auth';
import { useAuth, useCors, useValidate } from 'lib/middleware';
import { NextApiRequestQueryBody } from 'lib/types';
import { TimezoneTest } from 'lib/yup';
import { NextApiResponse } from 'next';
import { methodNotAllowed, ok, unauthorized } from 'next-basics';
import { getGoals } from 'queries/analytics/reports/getGoals';
import * as yup from 'yup';
export interface RetentionRequestBody {
websiteId: string;
dateRange: { startDate: string; endDate: string; timezone: string };
goals: { type: string; value: string; goal: number }[];
}
const schema = {
POST: yup.object().shape({
websiteId: yup.string().uuid().required(),
dateRange: yup
.object()
.shape({
startDate: yup.date().required(),
endDate: yup.date().required(),
timezone: TimezoneTest,
})
.required(),
goals: yup
.array()
.of(
yup.object().shape({
type: yup.string().required(),
value: yup.string().required(),
goal: yup.number().required(),
}),
)
.min(1)
.required(),
}),
};
export default async (
req: NextApiRequestQueryBody<any, RetentionRequestBody>,
res: NextApiResponse,
) => {
await useCors(req, res);
await useAuth(req, res);
await useValidate(schema, req, res);
if (req.method === 'POST') {
const {
websiteId,
dateRange: { startDate, endDate },
goals,
} = req.body;
if (!(await canViewWebsite(req.auth, websiteId))) {
return unauthorized(res);
}
const data = await getGoals(websiteId, {
startDate: new Date(startDate),
endDate: new Date(endDate),
goals,
});
return ok(res, data);
}
return methodNotAllowed(res);
};

View File

@ -27,7 +27,7 @@ const schema = {
name: yup.string().max(200).required(),
type: yup
.string()
.matches(/funnel|insights|retention|utm/i)
.matches(/funnel|insights|retention|utm|goals/i)
.required(),
description: yup.string().max(500),
parameters: yup

View File

@ -0,0 +1,225 @@
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 }[];
},
]
) {
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 }[];
},
): Promise<any> {
const { startDate, endDate, goals } = criteria;
const { rawQuery } = prisma;
const hasUrl = goals.some(a => a.type === 'url');
const hasEvent = goals.some(a => a.type === 'event');
function getParameters(goals: { type: string; value: string; goal: number }[]) {
const urls = goals
.filter(a => a.type === 'url')
.reduce((acc, cv, i) => {
acc[`${cv.type}${i}`] = cv.value;
return acc;
}, {});
const events = goals
.filter(a => a.type === 'event')
.reduce((acc, cv, i) => {
acc[`${cv.type}${i}`] = cv.value;
return acc;
}, {});
return {
urls: { ...urls, startDate, endDate, websiteId },
events: { ...events, startDate, endDate, websiteId },
};
}
function getColumns(goals: { type: string; value: string; goal: number }[]) {
const urls = goals
.filter(a => a.type === 'url')
.map((a, i) => `COUNT(CASE WHEN url_path = {{url${i}}} THEN 1 END) AS URL${i}`)
.join('\n');
const events = goals
.filter(a => a.type === 'event')
.map((a, i) => `COUNT(CASE WHEN url_path = {{event${i}}} THEN 1 END) AS EVENT${i}`)
.join('\n');
return { urls, events };
}
function getWhere(goals: { type: string; value: string; goal: number }[]) {
const urls = goals
.filter(a => a.type === 'url')
.map((a, i) => `{{url${i}}}`)
.join(',');
const events = goals
.filter(a => a.type === 'event')
.map((a, i) => `{{event${i}}}`)
.join(',');
return { urls: `and url_path in (${urls})`, events: `and event_name in (${events})` };
}
const parameters = getParameters(goals);
const columns = getColumns(goals);
const where = getWhere(goals);
const urls = hasUrl
? await rawQuery(
`
select
${columns.urls}
from website_event
where websiteId = {{websiteId::uuid}}
${where.urls}
and created_at between {{startDate}} and {{endDate}}
`,
parameters.urls,
)
: [];
const events = hasEvent
? await rawQuery(
`
select
${columns.events}
from website_event
where websiteId = {{websiteId::uuid}}
${where.events}
and created_at between {{startDate}} and {{endDate}}
`,
parameters.events,
)
: [];
return [...urls, ...events];
}
async function clickhouseQuery(
websiteId: string,
criteria: {
startDate: Date;
endDate: Date;
goals: { type: string; value: string; goal: number }[];
},
): 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 hasUrl = urls.length > 0;
const hasEvent = events.length > 0;
function getParameters(
urls: { type: string; value: string; goal: number }[],
events: { type: string; value: string; goal: number }[],
) {
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;
}, {});
return {
urls: { ...urlParam, startDate, endDate, websiteId },
events: { ...eventParam, startDate, endDate, websiteId },
};
}
function getColumns(
urls: { type: string; value: string; goal: number }[],
events: { type: string; value: string; goal: number }[],
) {
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);
return { url: urlColumns, events: eventColumns };
}
function getWhere(
urls: { type: string; value: string; goal: number }[],
events: { type: string; value: string; goal: number }[],
) {
const urlWhere = urls.map((a, i) => `{url${i}:String}`).join(',');
const eventWhere = events.map((a, i) => `{event${i}:String}`).join(',');
return { urls: `and url_path in (${urlWhere})`, events: `and event_name in (${eventWhere})` };
}
const parameters = getParameters(urls, events);
const columns = getColumns(urls, events);
const where = getWhere(urls, events);
const urlResults = hasUrl
? await rawQuery<any>(
`
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<any>(
`
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]) };
});
})
: [];
return [...urlResults, ...eventResults];
}

545
yarn.lock
View File

@ -1127,9 +1127,9 @@
regenerator-runtime "^0.14.0"
"@babel/runtime@^7.23.2":
version "7.24.4"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.4.tgz#de795accd698007a66ba44add6cc86542aff1edd"
integrity sha512-dkxf7+hn8mFBwKjs9bvBlArzLVxVbS8usaPUDd5p2a9JCL9tB8OaOVN1isD4+Xyk4ns89/xeOmbQvgdK7IIVdA==
version "7.24.5"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.5.tgz#230946857c053a36ccc66e1dd03b17dd0c4ed02c"
integrity sha512-Nms86NXrsaeU9vbBJKni6gXiEXZ4CVpYVzEjDH9Sb8vmZ3UljyA1GSOJl/6LGPO8EHLuSF9H+IxNXHPX8QHJ4g==
dependencies:
regenerator-runtime "^0.14.0"
@ -1206,17 +1206,17 @@
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
"@clickhouse/client-common@0.2.10":
version "0.2.10"
resolved "https://registry.yarnpkg.com/@clickhouse/client-common/-/client-common-0.2.10.tgz#62f454d2cc2ee27a325034a2cca47c6f5c90d22e"
integrity sha512-BvTY0IXS96y9RUeNCpKL4HUzHmY80L0lDcGN0lmUD6zjOqYMn78+xyHYJ/AIAX7JQsc+/KwFt2soZutQTKxoGQ==
"@clickhouse/client-common@1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@clickhouse/client-common/-/client-common-1.0.1.tgz#c7dde5eafaad8189649373ecc23354c7a32847b3"
integrity sha512-3L6e0foP6VOktScoi6XWMjJyOpKCWgLUYgPVxP2c7gm6Kotq+iRmmmXtXTSg7B7uozcLZycTtPfIw2d80SYsYw==
"@clickhouse/client@^0.2.2":
version "0.2.10"
resolved "https://registry.yarnpkg.com/@clickhouse/client/-/client-0.2.10.tgz#519561f3a4fff837bb606c52abfe74e5e7e9abb3"
integrity sha512-ZwBgzjEAFN/ogS0ym5KHVbR7Hx/oYCX01qGp2baEyfN2HM73kf/7Vp3GvMHWRy+zUXISONEtFv7UTViOXnmFrg==
"@clickhouse/client@^1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@clickhouse/client/-/client-1.0.1.tgz#364db28d9ef9beaf19104f962c2b06090cb10468"
integrity sha512-fluUNnE2R7COJ6rn6DorYfi4D+AQn3t2qeBtEq37bQV3pD4EbKrBfKAwJ13e1lmMWdQ2B9bJUTMqGsRIDdWhJw==
dependencies:
"@clickhouse/client-common" "0.2.10"
"@clickhouse/client-common" "1.0.1"
"@colors/colors@1.5.0":
version "1.5.0"
@ -1668,17 +1668,17 @@
"@formatjs/ecma402-abstract" "1.4.0"
tslib "^2.0.1"
"@formatjs/intl@2.10.1":
version "2.10.1"
resolved "https://registry.yarnpkg.com/@formatjs/intl/-/intl-2.10.1.tgz#75ae637070553bf7dfd213847ba8219f5ddae2b6"
integrity sha512-dsLG15U7xDi8yzKf4hcAWSsCaez3XrjTO2oaRHPyHtXLm1aEzYbDw6bClo/HMHu+iwS5GbDqT3DV+hYP2ylScg==
"@formatjs/intl@2.10.2":
version "2.10.2"
resolved "https://registry.yarnpkg.com/@formatjs/intl/-/intl-2.10.2.tgz#c074439ac2dbde4c2b3768b8108dfc3932b7fb30"
integrity sha512-raPGWr3JRv3neXV78SqPFrGC05fIbhhNzVghHNxFde27ls2KkXiMhtP7HBybjGpikVSjjhdhaZto+4p1vmm9bQ==
dependencies:
"@formatjs/ecma402-abstract" "1.18.2"
"@formatjs/fast-memoize" "2.2.0"
"@formatjs/icu-messageformat-parser" "2.7.6"
"@formatjs/intl-displaynames" "6.6.6"
"@formatjs/intl-listformat" "7.5.5"
intl-messageformat "10.5.11"
intl-messageformat "10.5.12"
tslib "^2.4.0"
"@formatjs/ts-transformer@3.9.4":
@ -2002,66 +2002,66 @@
integrity sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw==
"@netlify/plugin-nextjs@^5.1.0":
version "5.1.0"
resolved "https://registry.yarnpkg.com/@netlify/plugin-nextjs/-/plugin-nextjs-5.1.0.tgz#12fc0f7815b62cf091ea6bc98bc9f43ab103411d"
integrity sha512-nurSK6pMi36fVbuwLEiPIzMC/N2Dn/tHqA+seoStwHvGewsrXAphrjJ+8wq7eSCe+BEHCtGlwC1mNOeuqVkfbg==
version "5.2.2"
resolved "https://registry.yarnpkg.com/@netlify/plugin-nextjs/-/plugin-nextjs-5.2.2.tgz#3c283d335001f9e0fbcb4db75557e5fe1660db72"
integrity sha512-jV/P7o8+v1XaEGb7wvFfkF1fSLggAxjg7WYoBPkD3R93bsI6xmCDKBcUJ/6g7lqECRXt4dGKApSFtGk/pUmAHw==
"@next/env@14.1.4":
version "14.1.4"
resolved "https://registry.yarnpkg.com/@next/env/-/env-14.1.4.tgz#432e80651733fbd67230bf262aee28be65252674"
integrity sha512-e7X7bbn3Z6DWnDi75UWn+REgAbLEqxI8Tq2pkFOFAMpWAWApz/YCUhtWMWn410h8Q2fYiYL7Yg5OlxMOCfFjJQ==
"@next/env@14.2.3":
version "14.2.3"
resolved "https://registry.yarnpkg.com/@next/env/-/env-14.2.3.tgz#d6def29d1c763c0afb397343a15a82e7d92353a0"
integrity sha512-W7fd7IbkfmeeY2gXrzJYDx8D2lWKbVoTIj1o1ScPHNzvp30s1AuoEFSdr39bC5sjxJaxTtq3OTCZboNp0lNWHA==
"@next/eslint-plugin-next@14.1.4":
version "14.1.4"
resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-14.1.4.tgz#d7372b5ffede0e466af8af2ff534386418827fc8"
integrity sha512-n4zYNLSyCo0Ln5b7qxqQeQ34OZKXwgbdcx6kmkQbywr+0k6M3Vinft0T72R6CDAcDrne2IAgSud4uWCzFgc5HA==
"@next/eslint-plugin-next@14.2.3":
version "14.2.3"
resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-14.2.3.tgz#287ad8620e7061ba01e8d3313d464db6d217b6df"
integrity sha512-L3oDricIIjgj1AVnRdRor21gI7mShlSwU/1ZGHmqM3LzHhXXhdkrfeNY5zif25Bi5Dd7fiJHsbhoZCHfXYvlAw==
dependencies:
glob "10.3.10"
"@next/swc-darwin-arm64@14.1.4":
version "14.1.4"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.1.4.tgz#a3bca0dc4393ac4cf3169bbf24df63441de66bb7"
integrity sha512-ubmUkbmW65nIAOmoxT1IROZdmmJMmdYvXIe8211send9ZYJu+SqxSnJM4TrPj9wmL6g9Atvj0S/2cFmMSS99jg==
"@next/swc-darwin-arm64@14.2.3":
version "14.2.3"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.3.tgz#db1a05eb88c0224089b815ad10ac128ec79c2cdb"
integrity sha512-3pEYo/RaGqPP0YzwnlmPN2puaF2WMLM3apt5jLW2fFdXD9+pqcoTzRk+iZsf8ta7+quAe4Q6Ms0nR0SFGFdS1A==
"@next/swc-darwin-x64@14.1.4":
version "14.1.4"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-14.1.4.tgz#ba3683d4e2d30099f3f2864dd7349a4d9f440140"
integrity sha512-b0Xo1ELj3u7IkZWAKcJPJEhBop117U78l70nfoQGo4xUSvv0PJSTaV4U9xQBLvZlnjsYkc8RwQN1HoH/oQmLlQ==
"@next/swc-darwin-x64@14.2.3":
version "14.2.3"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.3.tgz#a3f8af05b5f9a52ac3082e66ac29e125ab1d7b9c"
integrity sha512-6adp7waE6P1TYFSXpY366xwsOnEXM+y1kgRpjSRVI2CBDOcbRjsJ67Z6EgKIqWIue52d2q/Mx8g9MszARj8IEA==
"@next/swc-linux-arm64-gnu@14.1.4":
version "14.1.4"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.1.4.tgz#3519969293f16379954b7e196deb0c1eecbb2f8b"
integrity sha512-457G0hcLrdYA/u1O2XkRMsDKId5VKe3uKPvrKVOyuARa6nXrdhJOOYU9hkKKyQTMru1B8qEP78IAhf/1XnVqKA==
"@next/swc-linux-arm64-gnu@14.2.3":
version "14.2.3"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.3.tgz#4e63f43879285b52554bfd39e6e0cc78a9b27bbf"
integrity sha512-cuzCE/1G0ZSnTAHJPUT1rPgQx1w5tzSX7POXSLaS7w2nIUJUD+e25QoXD/hMfxbsT9rslEXugWypJMILBj/QsA==
"@next/swc-linux-arm64-musl@14.1.4":
version "14.1.4"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.1.4.tgz#4bb3196bd402b3f84cf5373ff1021f547264d62f"
integrity sha512-l/kMG+z6MB+fKA9KdtyprkTQ1ihlJcBh66cf0HvqGP+rXBbOXX0dpJatjZbHeunvEHoBBS69GYQG5ry78JMy3g==
"@next/swc-linux-arm64-musl@14.2.3":
version "14.2.3"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.3.tgz#ebdaed26214448b1e6f2c3e8b3cd29bfba387990"
integrity sha512-0D4/oMM2Y9Ta3nGuCcQN8jjJjmDPYpHX9OJzqk42NZGJocU2MqhBq5tWkJrUQOQY9N+In9xOdymzapM09GeiZw==
"@next/swc-linux-x64-gnu@14.1.4":
version "14.1.4"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.1.4.tgz#1b3372c98c83dcdab946cdb4ee06e068b8139ba3"
integrity sha512-BapIFZ3ZRnvQ1uWbmqEGJuPT9cgLwvKtxhK/L2t4QYO7l+/DxXuIGjvp1x8rvfa/x1FFSsipERZK70pewbtJtw==
"@next/swc-linux-x64-gnu@14.2.3":
version "14.2.3"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.3.tgz#19e3bcc137c3b582a1ab867106817e5c90a20593"
integrity sha512-ENPiNnBNDInBLyUU5ii8PMQh+4XLr4pG51tOp6aJ9xqFQ2iRI6IH0Ds2yJkAzNV1CfyagcyzPfROMViS2wOZ9w==
"@next/swc-linux-x64-musl@14.1.4":
version "14.1.4"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.1.4.tgz#8459088bdc872648ff78f121db596f2533df5808"
integrity sha512-mqVxTwk4XuBl49qn2A5UmzFImoL1iLm0KQQwtdRJRKl21ylQwwGCxJtIYo2rbfkZHoSKlh/YgztY0qH3wG1xIg==
"@next/swc-linux-x64-musl@14.2.3":
version "14.2.3"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.3.tgz#794a539b98e064169cf0ff7741b2a4fb16adec7d"
integrity sha512-BTAbq0LnCbF5MtoM7I/9UeUu/8ZBY0i8SFjUMCbPDOLv+un67e2JgyN4pmgfXBwy/I+RHu8q+k+MCkDN6P9ViQ==
"@next/swc-win32-arm64-msvc@14.1.4":
version "14.1.4"
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.1.4.tgz#84280a08c00cc3be24ddd3a12f4617b108e6dea6"
integrity sha512-xzxF4ErcumXjO2Pvg/wVGrtr9QQJLk3IyQX1ddAC/fi6/5jZCZ9xpuL9Tzc4KPWMFq8GGWFVDMshZOdHGdkvag==
"@next/swc-win32-arm64-msvc@14.2.3":
version "14.2.3"
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.3.tgz#eda9fa0fbf1ff9113e87ac2668ee67ce9e5add5a"
integrity sha512-AEHIw/dhAMLNFJFJIJIyOFDzrzI5bAjI9J26gbO5xhAKHYTZ9Or04BesFPXiAYXDNdrwTP2dQceYA4dL1geu8A==
"@next/swc-win32-ia32-msvc@14.1.4":
version "14.1.4"
resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.1.4.tgz#23ff7f4bd0a27177428669ef6fa5c3923c738031"
integrity sha512-WZiz8OdbkpRw6/IU/lredZWKKZopUMhcI2F+XiMAcPja0uZYdMTZQRoQ0WZcvinn9xZAidimE7tN9W5v9Yyfyw==
"@next/swc-win32-ia32-msvc@14.2.3":
version "14.2.3"
resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.3.tgz#7c1190e3f640ab16580c6bdbd7d0e766b9920457"
integrity sha512-vga40n1q6aYb0CLrM+eEmisfKCR45ixQYXuBXxOOmmoV8sYST9k7E3US32FsY+CkkF7NtzdcebiFT4CHuMSyZw==
"@next/swc-win32-x64-msvc@14.1.4":
version "14.1.4"
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.1.4.tgz#bccf5beccfde66d6c66fa4e2509118c796385eda"
integrity sha512-4Rto21sPfw555sZ/XNLqfxDUNeLhNYGO2dlPqsnuCg8N8a2a9u1ltqBOPQ4vj1Gf7eJC0W2hHG2eYUHuiXgY2w==
"@next/swc-win32-x64-msvc@14.2.3":
version "14.2.3"
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.3.tgz#2be4e39ee25bfbd85be78eea17c0e7751dc4323c"
integrity sha512-Q1/zm43RWynxrO7lW4ehciQVj+5ePBhOK+/K2P7pLFX3JaJ/IZVC69SHidrmZSOkqz7ECIOhhy7XhAFG4JYyHA==
"@nodelib/fs.scandir@2.1.5":
version "2.1.5"
@ -2089,51 +2089,51 @@
resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33"
integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==
"@prisma/client@5.12.1":
version "5.12.1"
resolved "https://registry.yarnpkg.com/@prisma/client/-/client-5.12.1.tgz#c26a674fea76754b3a9e8b90a11e617f90212f76"
integrity sha512-6/JnizEdlSBxDIdiLbrBdMW5NqDxOmhXAJaNXiPpgzAPr/nLZResT6MMpbOHLo5yAbQ1Vv5UU8PTPRzb0WIxdA==
"@prisma/client@5.13.0":
version "5.13.0"
resolved "https://registry.yarnpkg.com/@prisma/client/-/client-5.13.0.tgz#b9f1d0983d714e982675201d8222a9ecb4bdad4a"
integrity sha512-uYdfpPncbZ/syJyiYBwGZS8Gt1PTNoErNYMuqHDa2r30rNSFtgTA/LXsSk55R7pdRTMi5pHkeP9B14K6nHmwkg==
"@prisma/debug@5.12.1":
version "5.12.1"
resolved "https://registry.yarnpkg.com/@prisma/debug/-/debug-5.12.1.tgz#007c8ad2e466d565bcd0671b8846c27f8700c722"
integrity sha512-kd/wNsR0klrv79o1ITsbWxYyh4QWuBidvxsXSParPsYSu0ircUmNk3q4ojsgNc3/81b0ozg76iastOG43tbf8A==
"@prisma/debug@5.13.0":
version "5.13.0"
resolved "https://registry.yarnpkg.com/@prisma/debug/-/debug-5.13.0.tgz#d88b0f6fafa0c216e20e284ed9fc30f1cbe45786"
integrity sha512-699iqlEvzyCj9ETrXhs8o8wQc/eVW+FigSsHpiskSFydhjVuwTJEfj/nIYqTaWFYuxiWQRfm3r01meuW97SZaQ==
"@prisma/engines-version@5.12.0-21.473ed3124229e22d881cb7addf559799debae1ab":
version "5.12.0-21.473ed3124229e22d881cb7addf559799debae1ab"
resolved "https://registry.yarnpkg.com/@prisma/engines-version/-/engines-version-5.12.0-21.473ed3124229e22d881cb7addf559799debae1ab.tgz#c78d099a3fe86d446db7442e64e56987e39e7f32"
integrity sha512-6yvO8s80Tym61aB4QNtYZfWVmE3pwqe807jEtzm8C5VDe7nw8O1FGX3TXUaXmWV0fQTIAfRbeL2Gwrndabp/0g==
"@prisma/engines-version@5.13.0-23.b9a39a7ee606c28e3455d0fd60e78c3ba82b1a2b":
version "5.13.0-23.b9a39a7ee606c28e3455d0fd60e78c3ba82b1a2b"
resolved "https://registry.yarnpkg.com/@prisma/engines-version/-/engines-version-5.13.0-23.b9a39a7ee606c28e3455d0fd60e78c3ba82b1a2b.tgz#a72a4fb83ba1fd01ad45f795aa55168f60d34723"
integrity sha512-AyUuhahTINGn8auyqYdmxsN+qn0mw3eg+uhkp8zwknXYIqoT3bChG4RqNY/nfDkPvzWAPBa9mrDyBeOnWSgO6A==
"@prisma/engines@5.12.1":
version "5.12.1"
resolved "https://registry.yarnpkg.com/@prisma/engines/-/engines-5.12.1.tgz#a50649427d627a9af962a188a84c65d61c6e2b3f"
integrity sha512-HQDdglLw2bZR/TXD2Y+YfDMvi5Q8H+acbswqOsWyq9pPjBLYJ6gzM+ptlTU/AV6tl0XSZLU1/7F4qaWa8bqpJA==
"@prisma/engines@5.13.0":
version "5.13.0"
resolved "https://registry.yarnpkg.com/@prisma/engines/-/engines-5.13.0.tgz#8994ebf7b4e35aee7746a8465ec22738379bcab6"
integrity sha512-hIFLm4H1boj6CBZx55P4xKby9jgDTeDG0Jj3iXtwaaHmlD5JmiDkZhh8+DYWkTGchu+rRF36AVROLnk0oaqhHw==
dependencies:
"@prisma/debug" "5.12.1"
"@prisma/engines-version" "5.12.0-21.473ed3124229e22d881cb7addf559799debae1ab"
"@prisma/fetch-engine" "5.12.1"
"@prisma/get-platform" "5.12.1"
"@prisma/debug" "5.13.0"
"@prisma/engines-version" "5.13.0-23.b9a39a7ee606c28e3455d0fd60e78c3ba82b1a2b"
"@prisma/fetch-engine" "5.13.0"
"@prisma/get-platform" "5.13.0"
"@prisma/extension-read-replicas@^0.3.0":
version "0.3.0"
resolved "https://registry.yarnpkg.com/@prisma/extension-read-replicas/-/extension-read-replicas-0.3.0.tgz#2842a7c928f957c1dd58a6256104797596d43426"
integrity sha512-F9+rSmYday6GT2qjhJtkZcBOpLO5LtpvFcMGqrBDHf+78LEdSuxfFjOxYlNuqk4B+th62yxpbhfpmB9/Mca14Q==
"@prisma/fetch-engine@5.12.1":
version "5.12.1"
resolved "https://registry.yarnpkg.com/@prisma/fetch-engine/-/fetch-engine-5.12.1.tgz#c38e9fa17fdc535b4c83cbb7645569ad0a511fa9"
integrity sha512-qSs3KcX1HKcea1A+hlJVK/ljj0PNIUHDxAayGMvgJBqmaN32P9tCidlKz1EGv6WoRFICYnk3Dd/YFLBwnFIozA==
"@prisma/fetch-engine@5.13.0":
version "5.13.0"
resolved "https://registry.yarnpkg.com/@prisma/fetch-engine/-/fetch-engine-5.13.0.tgz#9b6945c7b38bb59e840f8905b20ea7a3d059ca55"
integrity sha512-Yh4W+t6YKyqgcSEB3odBXt7QyVSm0OQlBSldQF2SNXtmOgMX8D7PF/fvH6E6qBCpjB/yeJLy/FfwfFijoHI6sA==
dependencies:
"@prisma/debug" "5.12.1"
"@prisma/engines-version" "5.12.0-21.473ed3124229e22d881cb7addf559799debae1ab"
"@prisma/get-platform" "5.12.1"
"@prisma/debug" "5.13.0"
"@prisma/engines-version" "5.13.0-23.b9a39a7ee606c28e3455d0fd60e78c3ba82b1a2b"
"@prisma/get-platform" "5.13.0"
"@prisma/get-platform@5.12.1":
version "5.12.1"
resolved "https://registry.yarnpkg.com/@prisma/get-platform/-/get-platform-5.12.1.tgz#33f427f6d744dee62a9e06858889691d78b50804"
integrity sha512-pgIR+pSvhYHiUcqXVEZS31NrFOTENC9yFUdEAcx7cdQBoZPmHVjtjN4Ss6NzVDMYPrKJJ51U14EhEoeuBlMioQ==
"@prisma/get-platform@5.13.0":
version "5.13.0"
resolved "https://registry.yarnpkg.com/@prisma/get-platform/-/get-platform-5.13.0.tgz#99ef909a52b9d79b64d72d2d3d8210c4892b6572"
integrity sha512-B/WrQwYTzwr7qCLifQzYOmQhZcFmIFhR81xC45gweInSUn2hTEbfKUPd2keAog+y5WI5xLAFNJ3wkXplvSVkSw==
dependencies:
"@prisma/debug" "5.12.1"
"@prisma/debug" "5.13.0"
"@react-spring/animated@~9.7.3":
version "9.7.3"
@ -2273,9 +2273,9 @@
picomatch "^2.3.1"
"@rushstack/eslint-patch@^1.3.3":
version "1.10.1"
resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.10.1.tgz#7ca168b6937818e9a74b47ac4e2112b2e1a024cf"
integrity sha512-S3Kq8e7LqxkA9s7HKLqXGTGck1uwis5vAXan3FnU5yw1Ec5hsSGnq4s/UCaSqABPOnOTg7zASLyst7+ohgWexg==
version "1.10.2"
resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.10.2.tgz#053f1540703faa81dea2966b768ee5581c66aeda"
integrity sha512-hw437iINopmQuxWPSUEvqE56NCPsiU8N4AYtfHmJFckclktzK9YQJieD3XkDCDH4OjL+C7zgPUh73R/nrcHrqw==
"@sinclair/typebox@^0.27.8":
version "0.27.8"
@ -2417,24 +2417,30 @@
"@svgr/plugin-jsx" "8.1.0"
"@svgr/plugin-svgo" "8.1.0"
"@swc/helpers@0.5.2":
version "0.5.2"
resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.2.tgz#85ea0c76450b61ad7d10a37050289eded783c27d"
integrity sha512-E4KcWTpoLHqwPHLxidpOqQbcrZVgi0rsmmZXUle1jXmJfuIf/UWpczUJ7MZZ5tlxytgJXyp0w4PGkkeLiuIdZw==
"@swc/counter@^0.1.3":
version "0.1.3"
resolved "https://registry.yarnpkg.com/@swc/counter/-/counter-0.1.3.tgz#cc7463bd02949611c6329596fccd2b0ec782b0e9"
integrity sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==
"@swc/helpers@0.5.5":
version "0.5.5"
resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.5.tgz#12689df71bfc9b21c4f4ca00ae55f2f16c8b77c0"
integrity sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==
dependencies:
"@swc/counter" "^0.1.3"
tslib "^2.4.0"
"@tanstack/query-core@5.29.0":
version "5.29.0"
resolved "https://registry.yarnpkg.com/@tanstack/query-core/-/query-core-5.29.0.tgz#d0b3d12c07d5a47f42ab0c1ed4f317106f3d4b20"
integrity sha512-WgPTRs58hm9CMzEr5jpISe8HXa3qKQ8CxewdYZeVnA54JrPY9B1CZiwsCoLpLkf0dGRZq+LcX5OiJb0bEsOFww==
"@tanstack/query-core@5.35.5":
version "5.35.5"
resolved "https://registry.yarnpkg.com/@tanstack/query-core/-/query-core-5.35.5.tgz#7b4100dc9cc7fee314b8a1bcbf502a236d43ffe3"
integrity sha512-OMWvlEqG01RfGj+XZb/piDzPp0eZkkHWSDHt2LvE/fd1zWburP/xwm0ghk6Iv8cuPlP+ACFkZviKXK0OVt6lhg==
"@tanstack/react-query@^5.28.6":
version "5.29.0"
resolved "https://registry.yarnpkg.com/@tanstack/react-query/-/react-query-5.29.0.tgz#42b3a2de4ed1d63666f0af04392a34b5e70d49c0"
integrity sha512-yxlhHB73jaBla6h5B6zPaGmQjokkzAhMHN4veotkPNiQ3Ac/mCxgABRZPsJJrgCTvhpcncBZcDBFxaR2B37vug==
version "5.35.5"
resolved "https://registry.yarnpkg.com/@tanstack/react-query/-/react-query-5.35.5.tgz#d41a087d58f42418824fa04aaca00ba93c99075c"
integrity sha512-sppX7L+PVn5GBV3In6zzj0zcKfnZRKhXbX1MfIfKo1OjIq2GMaopvAFOP0x1bRYTUk2ikrdYcQYOozX7PWkb8A==
dependencies:
"@tanstack/query-core" "5.29.0"
"@tanstack/query-core" "5.35.5"
"@trysound/sax@0.2.0":
version "0.2.0"
@ -2647,9 +2653,9 @@
integrity sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==
"@types/node@*", "@types/node@^20.9.0":
version "20.12.6"
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.12.6.tgz#72d068870518d7da1d97b49db401e2d6a1805294"
integrity sha512-3KurE8taB8GCvZBPngVbp0lk5CKi8M9f9k1rsADh0Evdz5SzJ+Q+Hx9uHoFGsLnLnd1xmkDQr2hVhlA0Mn0lKQ==
version "20.12.11"
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.12.11.tgz#c4ef00d3507000d17690643278a60dc55a9dc9be"
integrity sha512-vDg9PZ/zi+Nqp6boSOT7plNuthRugEKixDv5sFTIpkE89MmNtEArAShI4mxuX2+UrLEe9pxC1vm2cjm9YlWbJw==
dependencies:
undici-types "~5.26.4"
@ -2674,9 +2680,9 @@
integrity sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==
"@types/react-dom@^18.2.17":
version "18.2.24"
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.2.24.tgz#8dda8f449ae436a7a6e91efed8035d4ab03ff759"
integrity sha512-cN6upcKd8zkGy4HU9F1+/s98Hrp6D4MOcippK4PoE8OZRngohHZpbJn1GsaDLz87MqvHNoT13nHvNqM9ocRHZg==
version "18.3.0"
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.3.0.tgz#0cbc818755d87066ab6ca74fbedb2547d74a82b0"
integrity sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==
dependencies:
"@types/react" "*"
@ -2698,9 +2704,9 @@
"@types/react" "*"
"@types/react@*", "@types/react@16 || 17 || 18", "@types/react@^18.2.41":
version "18.2.75"
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.75.tgz#45d18f384939306d35312def1bf532eb38a68562"
integrity sha512-+DNnF7yc5y0bHkBTiLKqXFe+L4B3nvOphiMY3tuA5X10esmjqk7smyBZzbGTy2vsiy/Bnzj8yFIBL8xhRacoOg==
version "18.3.1"
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.3.1.tgz#fed43985caa834a2084d002e4771e15dfcbdbe8e"
integrity sha512-V0kuGBX3+prX+DQ/7r2qsv1NsdfnCLnTgnRJ1pYnxykBhGMz+qj+box5lq7XsO5mtZsBqpjwwTu/7wszPfMBcw==
dependencies:
"@types/prop-types" "*"
csstype "^3.0.2"
@ -2773,7 +2779,18 @@
semver "^7.5.4"
ts-api-utils "^1.0.1"
"@typescript-eslint/parser@^5.4.2 || ^6.0.0", "@typescript-eslint/parser@^6.7.3":
"@typescript-eslint/parser@^5.4.2 || ^6.0.0 || 7.0.0 - 7.2.0":
version "7.2.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-7.2.0.tgz#44356312aea8852a3a82deebdacd52ba614ec07a"
integrity sha512-5FKsVcHTk6TafQKQbuIVkXq58Fnbkd2wDL4LB7AURN7RUOu1utVP+G8+6u3ZhEroW3DF6hyo3ZEXxgKgp4KeCg==
dependencies:
"@typescript-eslint/scope-manager" "7.2.0"
"@typescript-eslint/types" "7.2.0"
"@typescript-eslint/typescript-estree" "7.2.0"
"@typescript-eslint/visitor-keys" "7.2.0"
debug "^4.3.4"
"@typescript-eslint/parser@^6.7.3":
version "6.21.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.21.0.tgz#af8fcf66feee2edc86bc5d1cf45e33b0630bf35b"
integrity sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==
@ -2800,6 +2817,14 @@
"@typescript-eslint/types" "6.21.0"
"@typescript-eslint/visitor-keys" "6.21.0"
"@typescript-eslint/scope-manager@7.2.0":
version "7.2.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.2.0.tgz#cfb437b09a84f95a0930a76b066e89e35d94e3da"
integrity sha512-Qh976RbQM/fYtjx9hs4XkayYujB/aPwglw2choHmf3zBjB4qOywWSdt9+KLRdHubGcoSwBnXUH2sR3hkyaERRg==
dependencies:
"@typescript-eslint/types" "7.2.0"
"@typescript-eslint/visitor-keys" "7.2.0"
"@typescript-eslint/type-utils@6.21.0":
version "6.21.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz#6473281cfed4dacabe8004e8521cee0bd9d4c01e"
@ -2820,6 +2845,11 @@
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.21.0.tgz#205724c5123a8fef7ecd195075fa6e85bac3436d"
integrity sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==
"@typescript-eslint/types@7.2.0":
version "7.2.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.2.0.tgz#0feb685f16de320e8520f13cca30779c8b7c403f"
integrity sha512-XFtUHPI/abFhm4cbCDc5Ykc8npOKBSJePY3a3s+lwumt7XWJuzP5cZcfZ610MIPHjQjNsOLlYK8ASPaNG8UiyA==
"@typescript-eslint/typescript-estree@5.62.0":
version "5.62.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz#7d17794b77fabcac615d6a48fb143330d962eb9b"
@ -2847,6 +2877,20 @@
semver "^7.5.4"
ts-api-utils "^1.0.1"
"@typescript-eslint/typescript-estree@7.2.0":
version "7.2.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.2.0.tgz#5beda2876c4137f8440c5a84b4f0370828682556"
integrity sha512-cyxS5WQQCoBwSakpMrvMXuMDEbhOo9bNHHrNcEWis6XHx6KF518tkF1wBvKIn/tpq5ZpUYK7Bdklu8qY0MsFIA==
dependencies:
"@typescript-eslint/types" "7.2.0"
"@typescript-eslint/visitor-keys" "7.2.0"
debug "^4.3.4"
globby "^11.1.0"
is-glob "^4.0.3"
minimatch "9.0.3"
semver "^7.5.4"
ts-api-utils "^1.0.1"
"@typescript-eslint/utils@6.21.0":
version "6.21.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.21.0.tgz#4714e7a6b39e773c1c8e97ec587f520840cd8134"
@ -2890,6 +2934,14 @@
"@typescript-eslint/types" "6.21.0"
eslint-visitor-keys "^3.4.1"
"@typescript-eslint/visitor-keys@7.2.0":
version "7.2.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.2.0.tgz#5035f177752538a5750cca1af6044b633610bf9e"
integrity sha512-c6EIQRHhcpl6+tO8EMR+kjkkV+ugUNXOmeASA1rlzkd8EPIriavpWoiEz1HR/VLhbVIdhqnV6E7JZm00cBDx2A==
dependencies:
"@typescript-eslint/types" "7.2.0"
eslint-visitor-keys "^3.4.1"
"@umami/prisma-client@^0.14.0":
version "0.14.0"
resolved "https://registry.yarnpkg.com/@umami/prisma-client/-/prisma-client-0.14.0.tgz#8489f23e7d766fdecb94790246b0b77b9d65223b"
@ -2899,10 +2951,10 @@
chalk "^4.1.2"
debug "^4.3.4"
"@umami/redis-client@^0.20.0":
version "0.20.0"
resolved "https://registry.yarnpkg.com/@umami/redis-client/-/redis-client-0.20.0.tgz#93b4598d68983b1ad266a0a527c56533c6248bf2"
integrity sha512-ACpoO+M/J2eLWEtusjbslhR4le+rPN4h9x7TXjaVJ905icVE0Qgu5y+A7nxXjcYvlgkHk+8HPeVeeaw5P+rxqw==
"@umami/redis-client@^0.21.0":
version "0.21.0"
resolved "https://registry.yarnpkg.com/@umami/redis-client/-/redis-client-0.21.0.tgz#96426b28860b8b06fae8825fc2f2d9575b64e863"
integrity sha512-PpdJunvT4sAsVWIeEl+cHU6iSV2r/Df9dof2gdUwSigfD88ACsVs1/BvlWERxk/T93rTgVJWSpLvdw/oMYvkcw==
dependencies:
debug "^4.3.4"
redis "^4.5.1"
@ -4215,9 +4267,9 @@ cypress@*:
yauzl "^2.10.0"
cypress@^13.6.6:
version "13.7.2"
resolved "https://registry.yarnpkg.com/cypress/-/cypress-13.7.2.tgz#61e841382abb20e0a9a063086ee0d850af3ef6bc"
integrity sha512-FF5hFI5wlRIHY8urLZjJjj/YvfCBrRpglbZCLr/cYcL9MdDe0+5usa8kTIrDHthlEc9lwihbkb5dmwqBDNS2yw==
version "13.9.0"
resolved "https://registry.yarnpkg.com/cypress/-/cypress-13.9.0.tgz#b529cfa8f8c39ba163ed0501a25bb5b09c143652"
integrity sha512-atNjmYfHsvTuCaxTxLZr9xGoHz53LLui3266WWxXJHY7+N6OdwJdg/feEa3T+buez9dmUXHT1izCOklqG82uCQ==
dependencies:
"@cypress/request" "^3.0.0"
"@cypress/xvfb" "^1.2.4"
@ -4400,9 +4452,9 @@ dateformat@^5.0.3:
integrity sha512-Kvr6HmPXUMerlLcLF+Pwq3K7apHpYmGDVqrxcDasBg86UcKeTSNWbEzU8bwdXnxnR44FtMhJAxI4Bov6Y/KUfA==
dayjs@^1.10.4:
version "1.11.10"
resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.10.tgz#68acea85317a6e164457d6d6947564029a6a16a0"
integrity sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==
version "1.11.11"
resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.11.tgz#dfe0e9d54c5f8b68ccf8ca5f72ac603e7e5ed59e"
integrity sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg==
debounce@^1.2.1:
version "1.2.1"
@ -4465,7 +4517,7 @@ define-data-property@^1.0.1, define-data-property@^1.1.4:
es-errors "^1.3.0"
gopd "^1.0.1"
define-properties@^1.1.3, define-properties@^1.2.0, define-properties@^1.2.1:
define-properties@^1.2.0, define-properties@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c"
integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==
@ -4679,9 +4731,9 @@ end-of-stream@^1.1.0:
once "^1.4.0"
enhanced-resolve@^5.12.0:
version "5.16.0"
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.16.0.tgz#65ec88778083056cb32487faa9aef82ed0864787"
integrity sha512-O+QWCviPNSSLAD9Ucn8Awv+poAkqn3T1XY5/N7kR7rQO9yfSGWkYZDwpJ+iKF7B8rxaQKWngSqACpgzeapSyoA==
version "5.16.1"
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.16.1.tgz#e8bc63d51b826d6f1cbc0a150ecb5a8b0c62e567"
integrity sha512-4U5pNsuDl0EhuZpq46M5xPslstkviJuhrdobaRDBk2Jy2KO37FDAJl4lb2KlNabxT0m4MTK2UHNrsAcphE8nyw==
dependencies:
graceful-fs "^4.2.4"
tapable "^2.2.0"
@ -4711,7 +4763,7 @@ error-ex@^1.3.1:
dependencies:
is-arrayish "^0.2.1"
es-abstract@^1.22.1, es-abstract@^1.22.3, es-abstract@^1.23.0, es-abstract@^1.23.1, es-abstract@^1.23.2:
es-abstract@^1.22.1, es-abstract@^1.22.3, es-abstract@^1.23.0, es-abstract@^1.23.1, es-abstract@^1.23.2, es-abstract@^1.23.3:
version "1.23.3"
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.23.3.tgz#8f0c5a35cd215312573c5a27c87dfd6c881a0aa0"
integrity sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==
@ -4776,13 +4828,13 @@ es-errors@^1.1.0, es-errors@^1.2.1, es-errors@^1.3.0:
integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==
es-iterator-helpers@^1.0.15, es-iterator-helpers@^1.0.17:
version "1.0.18"
resolved "https://registry.yarnpkg.com/es-iterator-helpers/-/es-iterator-helpers-1.0.18.tgz#4d3424f46b24df38d064af6fbbc89274e29ea69d"
integrity sha512-scxAJaewsahbqTYrGKJihhViaM6DDZDDoucfvzNbK0pOren1g/daDQ3IAhzn+1G14rBG7w+i5N+qul60++zlKA==
version "1.0.19"
resolved "https://registry.yarnpkg.com/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz#117003d0e5fec237b4b5c08aded722e0c6d50ca8"
integrity sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==
dependencies:
call-bind "^1.0.7"
define-properties "^1.2.1"
es-abstract "^1.23.0"
es-abstract "^1.23.3"
es-errors "^1.3.0"
es-set-tostringtag "^2.0.3"
function-bind "^1.1.2"
@ -4881,13 +4933,13 @@ escape-string-regexp@^4.0.0:
integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
eslint-config-next@^14.0.4:
version "14.1.4"
resolved "https://registry.yarnpkg.com/eslint-config-next/-/eslint-config-next-14.1.4.tgz#22f2ba4c0993e991249d863656a64c204bae542c"
integrity sha512-cihIahbhYAWwXJwZkAaRPpUi5t9aOi/HdfWXOjZeUOqNWXHD8X22kd1KG58Dc3MVaRx3HoR/oMGk2ltcrqDn8g==
version "14.2.3"
resolved "https://registry.yarnpkg.com/eslint-config-next/-/eslint-config-next-14.2.3.tgz#2fb0f7c4eccda530a4b5054438162b2303786d4f"
integrity sha512-ZkNztm3Q7hjqvB1rRlOX8P9E/cXRL9ajRcs8jufEtwMfTVYRqnmtnaSu57QqHyBlovMuiB8LEzfLBkh5RYV6Fg==
dependencies:
"@next/eslint-plugin-next" "14.1.4"
"@next/eslint-plugin-next" "14.2.3"
"@rushstack/eslint-patch" "^1.3.3"
"@typescript-eslint/parser" "^5.4.2 || ^6.0.0"
"@typescript-eslint/parser" "^5.4.2 || ^6.0.0 || 7.0.0 - 7.2.0"
eslint-import-resolver-node "^0.3.6"
eslint-import-resolver-typescript "^3.5.2"
eslint-plugin-import "^2.28.1"
@ -4943,9 +4995,9 @@ eslint-plugin-css-modules@^2.12.0:
lodash "^4.17.2"
eslint-plugin-cypress@^2.15.1:
version "2.15.1"
resolved "https://registry.yarnpkg.com/eslint-plugin-cypress/-/eslint-plugin-cypress-2.15.1.tgz#336afa7e8e27451afaf65aa359c9509e0a4f3a7b"
integrity sha512-eLHLWP5Q+I4j2AWepYq0PgFEei9/s5LvjuSqWrxurkg1YZ8ltxdvMNmdSf0drnsNo57CTgYY/NIHHLRSWejR7w==
version "2.15.2"
resolved "https://registry.yarnpkg.com/eslint-plugin-cypress/-/eslint-plugin-cypress-2.15.2.tgz#f22e12fad4c434edad7b298ef92bac8fa087ffa0"
integrity sha512-CtcFEQTDKyftpI22FVGpx8bkpKyYXBlNge6zSo0pl5/qJvBAnzaD76Vu2AsP16d6mTj478Ldn2mhgrWV+Xr0vQ==
dependencies:
globals "^13.20.0"
@ -5014,9 +5066,9 @@ eslint-plugin-promise@^6.1.1:
integrity sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==
"eslint-plugin-react-hooks@^4.5.0 || 5.0.0-canary-7118f5dd7-20230705":
version "4.6.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz#4c3e697ad95b77e93f8646aaa1630c1ba607edd3"
integrity sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==
version "4.6.2"
resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz#c829eb06c0e6f484b3fbb85a97e57784f328c596"
integrity sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==
eslint-plugin-react@^7.33.2:
version "7.34.1"
@ -5595,9 +5647,9 @@ get-symbol-description@^1.0.2:
get-intrinsic "^1.2.4"
get-tsconfig@^4.5.0:
version "4.7.3"
resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.7.3.tgz#0498163d98f7b58484dd4906999c0c9d5f103f83"
integrity sha512-ZvkrzoUA0PQZM6fy6+/Hce561s+faD1rsNwhnO5FelNjyy7EMGJ3Rz1AQ8GYDWjhRs/7dBLOEJvhK8MiEJOAFg==
version "4.7.5"
resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.7.5.tgz#5e012498579e9a6947511ed0cd403272c7acbbaf"
integrity sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw==
dependencies:
resolve-pkg-maps "^1.0.0"
@ -5699,11 +5751,12 @@ globals@^13.19.0, globals@^13.20.0:
type-fest "^0.20.2"
globalthis@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf"
integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==
version "1.0.4"
resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.4.tgz#7430ed3a975d97bfb59bcce41f5cabbafa651236"
integrity sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==
dependencies:
define-properties "^1.1.3"
define-properties "^1.2.1"
gopd "^1.0.1"
globby@10.0.1:
version "10.0.1"
@ -6015,10 +6068,10 @@ intl-messageformat-parser@^5.3.7:
dependencies:
"@formatjs/intl-numberformat" "^5.5.2"
intl-messageformat@10.5.11:
version "10.5.11"
resolved "https://registry.yarnpkg.com/intl-messageformat/-/intl-messageformat-10.5.11.tgz#95d6a3b0b303f924d5d8c3f8d3ad057d1dc73c64"
integrity sha512-eYq5fkFBVxc7GIFDzpFQkDOZgNayNTQn4Oufe8jw6YY6OHVw70/4pA3FyCsQ0Gb2DnvEJEMmN2tOaXUGByM+kg==
intl-messageformat@10.5.12:
version "10.5.12"
resolved "https://registry.yarnpkg.com/intl-messageformat/-/intl-messageformat-10.5.12.tgz#a0c1a20da896b7a1f4ba1b59c8ba5d9943c29c3f"
integrity sha512-izl0uxhy/melhw8gP2r8pGiVieviZmM4v5Oqx3c1/R7g9cwER2smmGfSjcIsp8Y3Q53bfciL/gkxacJRx/dUvg==
dependencies:
"@formatjs/ecma402-abstract" "1.18.2"
"@formatjs/fast-memoize" "2.2.0"
@ -6026,9 +6079,9 @@ intl-messageformat@10.5.11:
tslib "^2.4.0"
ipaddr.js@^2.0.1:
version "2.1.0"
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.1.0.tgz#2119bc447ff8c257753b196fc5f1ce08a4cdf39f"
integrity sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ==
version "2.2.0"
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.2.0.tgz#d33fa7bac284f4de7af949638c9d68157c6b92e8"
integrity sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==
is-array-buffer@^3.0.4:
version "3.0.4"
@ -6320,9 +6373,9 @@ isarray@^2.0.5:
integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==
isbot@^5.1.1:
version "5.1.4"
resolved "https://registry.yarnpkg.com/isbot/-/isbot-5.1.4.tgz#3123c0fbf98ae867dc74ab95e47a809c13621a82"
integrity sha512-KuqD/TAG/qtgCDnO8Ab1v5rGRK3jl9hb+2KfJt+roIPE7R4Hiq99VinR0qrLGFptdUNIkClYjuXEpVTGkD9V/A==
version "5.1.6"
resolved "https://registry.yarnpkg.com/isbot/-/isbot-5.1.6.tgz#579a48515e92a3e064da63a41709815d8e641a30"
integrity sha512-Phksj1A0dBP/M/5xeOx0zWemKlZRQvrbNzI19/HWso0uodiOcR8YYCXN60IdzwbKsGj5LnxPkMy6FuBtgckMNw==
isexe@^2.0.0:
version "2.0.0"
@ -7237,9 +7290,9 @@ lower-case@^2.0.2:
tslib "^2.0.3"
lru-cache@^10.2.0:
version "10.2.0"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.0.tgz#0bd445ca57363465900f4d1f9bd8db343a4d95c3"
integrity sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==
version "10.2.2"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.2.tgz#48206bc114c1252940c41b25b41af5b545aca878"
integrity sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==
lru-cache@^5.1.1:
version "5.1.1"
@ -7304,12 +7357,12 @@ mathml-tag-names@^2.1.3:
integrity sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==
maxmind@^4.3.6:
version "4.3.18"
resolved "https://registry.yarnpkg.com/maxmind/-/maxmind-4.3.18.tgz#ad83f38d718ca5395c5d722933a109b7cb009226"
integrity sha512-5b9utU7ZxcGYTBaO7hCF0FXyfw3IpankLn+FnLW4RZS1zi97RBeSdfXJFJlk5UxNsMiFZlsdMT3lzvD+bD8MLQ==
version "4.3.19"
resolved "https://registry.yarnpkg.com/maxmind/-/maxmind-4.3.19.tgz#da97391185b41373961685419f0f12dfd7b97ff9"
integrity sha512-Bu/VEN7ZWAOCjifdZaXJQuN6/yO7+OK35pnJsqmz8sOndK3KQFvJoY+6HX09/MmLLqtCfa+sMK0iaQOaTejGNA==
dependencies:
mmdb-lib "2.1.0"
tiny-lru "11.2.5"
tiny-lru "11.2.6"
md5@^2.3.0:
version "2.3.0"
@ -7480,9 +7533,9 @@ minipass@^5.0.0:
integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==
"minipass@^5.0.0 || ^6.0.2 || ^7.0.0":
version "7.0.4"
resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.0.4.tgz#dbce03740f50a4786ba994c1fb908844d27b038c"
integrity sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==
version "7.1.1"
resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.1.tgz#f7f85aff59aa22f110b20e27692465cf3bf89481"
integrity sha512-UZ7eQ+h8ywIRAW1hIEl2AqdwzJucU/Kp59+8kkZeSvafXhZjul247BvIJjEVFVeON6d7lM46XX1HXCduKAS8VA==
minizlib@^2.1.1:
version "2.1.2"
@ -7548,28 +7601,28 @@ next-basics@^0.39.0:
jsonwebtoken "^9.0.0"
pure-rand "^6.0.2"
next@14.1.4:
version "14.1.4"
resolved "https://registry.yarnpkg.com/next/-/next-14.1.4.tgz#203310f7310578563fd5c961f0db4729ce7a502d"
integrity sha512-1WTaXeSrUwlz/XcnhGTY7+8eiaFvdet5z9u3V2jb+Ek1vFo0VhHKSAIJvDWfQpttWjnyw14kBeq28TPq7bTeEQ==
next@14.2.3:
version "14.2.3"
resolved "https://registry.yarnpkg.com/next/-/next-14.2.3.tgz#f117dd5d5f20c307e7b8e4f9c1c97d961008925d"
integrity sha512-dowFkFTR8v79NPJO4QsBUtxv0g9BrS/phluVpMAt2ku7H+cbcBJlopXjkWlwxrk/xGqMemr7JkGPGemPrLLX7A==
dependencies:
"@next/env" "14.1.4"
"@swc/helpers" "0.5.2"
"@next/env" "14.2.3"
"@swc/helpers" "0.5.5"
busboy "1.6.0"
caniuse-lite "^1.0.30001579"
graceful-fs "^4.2.11"
postcss "8.4.31"
styled-jsx "5.1.1"
optionalDependencies:
"@next/swc-darwin-arm64" "14.1.4"
"@next/swc-darwin-x64" "14.1.4"
"@next/swc-linux-arm64-gnu" "14.1.4"
"@next/swc-linux-arm64-musl" "14.1.4"
"@next/swc-linux-x64-gnu" "14.1.4"
"@next/swc-linux-x64-musl" "14.1.4"
"@next/swc-win32-arm64-msvc" "14.1.4"
"@next/swc-win32-ia32-msvc" "14.1.4"
"@next/swc-win32-x64-msvc" "14.1.4"
"@next/swc-darwin-arm64" "14.2.3"
"@next/swc-darwin-x64" "14.2.3"
"@next/swc-linux-arm64-gnu" "14.2.3"
"@next/swc-linux-arm64-musl" "14.2.3"
"@next/swc-linux-x64-gnu" "14.2.3"
"@next/swc-linux-x64-musl" "14.2.3"
"@next/swc-win32-arm64-msvc" "14.2.3"
"@next/swc-win32-ia32-msvc" "14.2.3"
"@next/swc-win32-x64-msvc" "14.2.3"
nice-try@^1.0.4:
version "1.0.5"
@ -7916,9 +7969,9 @@ path-parse@^1.0.7:
integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
path-scurry@^1.10.1:
version "1.10.2"
resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.10.2.tgz#8f6357eb1239d5fa1da8b9f70e9c080675458ba7"
integrity sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==
version "1.11.0"
resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.0.tgz#332d64e9726bf667fb348e5a1c71005c09ad741a"
integrity sha512-LNHTaVkzaYaLGlO+0u3rQTz7QrHTFOuKyba9JMTQutkmtNew8dw8wOD7mTU/5fCPZzCWpfW0XnQKzY61P0aTaw==
dependencies:
lru-cache "^10.2.0"
minipass "^5.0.0 || ^6.0.2 || ^7.0.0"
@ -8606,12 +8659,12 @@ pretty-format@^29.0.0, pretty-format@^29.7.0:
ansi-styles "^5.0.0"
react-is "^18.0.0"
prisma@5.12.1:
version "5.12.1"
resolved "https://registry.yarnpkg.com/prisma/-/prisma-5.12.1.tgz#db4596253bb066afc9f08744642f200a398d8d51"
integrity sha512-SkMnb6wyIxTv9ACqiHBI2u9gD6y98qXRoCoLEnZsF6yee5Qg828G+ARrESN+lQHdw4maSZFFSBPPDpvSiVTo0Q==
prisma@5.13.0:
version "5.13.0"
resolved "https://registry.yarnpkg.com/prisma/-/prisma-5.13.0.tgz#1f06e20ccfb6038ad68869e6eacd3b346f9d0851"
integrity sha512-kGtcJaElNRAdAGsCNykFSZ7dBKpL14Cbs+VaQ8cECxQlRPDjBlMHNFYeYt0SKovAVy2Y65JXQwB3A5+zIQwnTg==
dependencies:
"@prisma/engines" "5.12.1"
"@prisma/engines" "5.13.0"
process@^0.11.10:
version "0.11.10"
@ -8737,12 +8790,12 @@ react-beautiful-dnd@^13.1.0:
use-memo-one "^1.1.1"
react-dom@^18.2.0:
version "18.2.0"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d"
integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==
version "18.3.1"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.3.1.tgz#c2265d79511b57d479b3dd3fdfa51536494c5cb4"
integrity sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==
dependencies:
loose-envify "^1.1.0"
scheduler "^0.23.0"
scheduler "^0.23.2"
react-error-boundary@^4.0.4:
version "4.0.13"
@ -8757,19 +8810,19 @@ react-hook-form@^7.34.2:
integrity sha512-F/TroLjTICipmHeFlMrLtNLceO2xr1jU3CyiNla5zdwsGUGu2UOxxR4UyJgLlhMwLW/Wzp4cpJ7CPfgJIeKdSg==
react-intl@^6.5.5:
version "6.6.5"
resolved "https://registry.yarnpkg.com/react-intl/-/react-intl-6.6.5.tgz#3dee5c4a9f866aebc8384a540a6d132a3fc694eb"
integrity sha512-OErDPbGqus0QKVj77MGCC9Plbnys3CDQrq6Lw41c60pmeTdn41AhoS1SIzXG6SUlyF7qNN2AVqfrrIvHUgSyLQ==
version "6.6.6"
resolved "https://registry.yarnpkg.com/react-intl/-/react-intl-6.6.6.tgz#67979f790263c5ebd95b6ea581110eea3e7b550f"
integrity sha512-dKXQNUrhZTlCp8uelYW8PHiM4saNKyLmHCfsJYWK0N/kZ/Ien35wjPHB8x9yQcTJbeN/hBOmb4x16iKUrdL9MA==
dependencies:
"@formatjs/ecma402-abstract" "1.18.2"
"@formatjs/icu-messageformat-parser" "2.7.6"
"@formatjs/intl" "2.10.1"
"@formatjs/intl" "2.10.2"
"@formatjs/intl-displaynames" "6.6.6"
"@formatjs/intl-listformat" "7.5.5"
"@types/hoist-non-react-statics" "^3.3.1"
"@types/react" "16 || 17 || 18"
hoist-non-react-statics "^3.3.2"
intl-messageformat "10.5.11"
intl-messageformat "10.5.12"
tslib "^2.4.0"
react-is@^16.13.1, react-is@^16.7.0:
@ -8825,9 +8878,9 @@ react-window@^1.8.6:
memoize-one ">=3.1.1 <6"
react@^18.2.0:
version "18.2.0"
resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5"
integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==
version "18.3.1"
resolved "https://registry.yarnpkg.com/react/-/react-18.3.1.tgz#49ab892009c53933625bd16b2533fc754cab2891"
integrity sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==
dependencies:
loose-envify "^1.1.0"
@ -9243,10 +9296,10 @@ safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
scheduler@^0.23.0:
version "0.23.0"
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe"
integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==
scheduler@^0.23.2:
version "0.23.2"
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.2.tgz#414ba64a3b282892e944cf2108ecc078d115cdc3"
integrity sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==
dependencies:
loose-envify "^1.1.0"
@ -9279,13 +9332,18 @@ semver@^6.0.0, semver@^6.3.0, semver@^6.3.1:
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
semver@^7.3.4, semver@^7.3.7, semver@^7.5.3, semver@^7.5.4:
semver@^7.3.4, semver@^7.3.7:
version "7.6.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d"
integrity sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==
dependencies:
lru-cache "^6.0.0"
semver@^7.5.3, semver@^7.5.4:
version "7.6.2"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13"
integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==
serialize-javascript@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa"
@ -9532,7 +9590,16 @@ string-length@^4.0.1:
char-regex "^1.0.2"
strip-ansi "^6.0.0"
"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
"string-width-cjs@npm:string-width@^4.2.0":
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
dependencies:
emoji-regex "^8.0.0"
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.1"
string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@ -9605,7 +9672,14 @@ string.prototype.trimstart@^1.0.8:
define-properties "^1.2.1"
es-object-atoms "^1.0.0"
"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
dependencies:
ansi-regex "^5.0.1"
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
@ -9898,10 +9972,10 @@ tiny-invariant@^1.0.6:
resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.1.tgz#8560808c916ef02ecfd55e66090df23a4b7aa642"
integrity sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==
tiny-lru@11.2.5:
version "11.2.5"
resolved "https://registry.yarnpkg.com/tiny-lru/-/tiny-lru-11.2.5.tgz#b138b99022aa26c567fa51a8dbf9e3e2959b2b30"
integrity sha512-JpqM0K33lG6iQGKiigcwuURAKZlq6rHXfrgeL4/I8/REoyJTGU+tEMszvT/oTRVHG2OiylhGDjqPp1jWMlr3bw==
tiny-lru@11.2.6:
version "11.2.6"
resolved "https://registry.yarnpkg.com/tiny-lru/-/tiny-lru-11.2.6.tgz#86a4fd0ad615eac1639adf92010e8b944e209fdb"
integrity sha512-0PU3c9PjMnltZaFo2sGYv/nnJsMjG0Cxx8X6FXHPPGjFyoo1SJDxvUXW1207rdiSxYizf31roo+GrkIByQeZoA==
tmp@~0.2.1:
version "0.2.3"
@ -9938,9 +10012,9 @@ toposort@^2.0.2:
integrity sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==
tough-cookie@^4.1.3:
version "4.1.3"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.3.tgz#97b9adb0728b42280aa3d814b6b999b2ff0318bf"
integrity sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==
version "4.1.4"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.4.tgz#945f1461b45b5a8c76821c33ea49c3ac192c1b36"
integrity sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==
dependencies:
psl "^1.1.33"
punycode "^2.1.1"
@ -10133,9 +10207,9 @@ typescript@^4.0, typescript@^4.5:
integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==
typescript@^5.4.3:
version "5.4.4"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.4.tgz#eb2471e7b0a5f1377523700a21669dce30c2d952"
integrity sha512-dGE2Vv8cpVvw28v8HCPqyb08EzbBURxDpuhJvTrusShUfGnhHBafDsLdS1EhhxyL6BJQE+2cT3dDPAv+MQ6oLw==
version "5.4.5"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.5.tgz#42ccef2c571fdbd0f6718b1d1f5e6e5ef006f611"
integrity sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==
unbox-primitive@^1.0.2:
version "1.0.2"
@ -10366,7 +10440,7 @@ which@^2.0.1:
dependencies:
isexe "^2.0.0"
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
@ -10384,6 +10458,15 @@ wrap-ansi@^6.2.0:
string-width "^4.1.0"
strip-ansi "^6.0.0"
wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
dependencies:
ansi-styles "^4.0.0"
string-width "^4.1.0"
strip-ansi "^6.0.0"
wrap-ansi@^8.0.1, wrap-ansi@^8.1.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"