From 87cf5d52985e1dbeb0a2b07c86ef443bb4bb2c6d Mon Sep 17 00:00:00 2001 From: Brian Cao Date: Fri, 18 Aug 2023 11:10:44 -0700 Subject: [PATCH 001/113] Fix UserWebsites. --- .../pages/settings/users/UserWebsites.js | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/components/pages/settings/users/UserWebsites.js b/components/pages/settings/users/UserWebsites.js index 144fae444..d61df4d8a 100644 --- a/components/pages/settings/users/UserWebsites.js +++ b/components/pages/settings/users/UserWebsites.js @@ -2,12 +2,19 @@ import { Loading } from 'react-basics'; import useApi from 'hooks/useApi'; import WebsitesTable from 'components/pages/settings/websites/WebsitesTable'; import useMessages from 'hooks/useMessages'; +import useApiFilter from 'hooks/useApiFilter'; export function UserWebsites({ userId }) { const { formatMessage, messages } = useMessages(); + const { filter, page, pageSize, handleFilterChange, handlePageChange, handlePageSizeChange } = + useApiFilter(); const { get, useQuery } = useApi(); - const { data, isLoading } = useQuery(['user:websites', userId], () => - get(`/users/${userId}/websites`), + const { data, isLoading } = useQuery(['user:websites', userId, filter, page, pageSize], () => + get(`/users/${userId}/websites`, { + filter, + page, + pageSize, + }), ); const hasData = data && data.length !== 0; @@ -17,7 +24,15 @@ export function UserWebsites({ userId }) { return (
- {hasData && } + {hasData && ( + + )} {!hasData && formatMessage(messages.noDataAvailable)}
); From 1aa407027ee234711bb60dfbe163ddd3f3fc4699 Mon Sep 17 00:00:00 2001 From: Brian Cao Date: Fri, 18 Aug 2023 11:16:03 -0700 Subject: [PATCH 002/113] Remove password. --- queries/admin/user.ts | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/queries/admin/user.ts b/queries/admin/user.ts index dfb923f31..ca459b9fd 100644 --- a/queries/admin/user.ts +++ b/queries/admin/user.ts @@ -37,7 +37,7 @@ export async function getUserByUsername(username: string, options: GetUserOption } export async function getUsers( - UserSearchFilter: UserSearchFilter = {}, + UserSearchFilter: UserSearchFilter, options?: { include?: Prisma.UserInclude }, ): Promise> { const { teamId, filter, filterType = USER_FILTER_TYPES.all } = UserSearchFilter; @@ -72,14 +72,22 @@ export async function getUsers( ...UserSearchFilter, }); - const users = await prisma.client.user.findMany({ - where: { - ...where, - deletedAt: null, - }, - ...pageFilters, - ...(options?.include && { include: options.include }), - }); + const users = await prisma.client.user + .findMany({ + where: { + ...where, + deletedAt: null, + }, + ...pageFilters, + ...(options?.include && { include: options.include }), + }) + .then(a => { + return a.map(a => { + const { password, ...rest } = a; + + return rest; + }); + }); const count = await prisma.client.user.count({ where: { ...where, From a296ecb96b321b4c3821d600d30b38632a735de3 Mon Sep 17 00:00:00 2001 From: Yash Khandelwal Date: Sat, 19 Aug 2023 00:29:06 +0530 Subject: [PATCH 003/113] Fixed error when opening user websites in the settings. --- .../pages/settings/users/UserWebsites.js | 33 +++++++++++++------ 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/components/pages/settings/users/UserWebsites.js b/components/pages/settings/users/UserWebsites.js index 144fae444..8189ad8dd 100644 --- a/components/pages/settings/users/UserWebsites.js +++ b/components/pages/settings/users/UserWebsites.js @@ -1,25 +1,38 @@ -import { Loading } from 'react-basics'; import useApi from 'hooks/useApi'; import WebsitesTable from 'components/pages/settings/websites/WebsitesTable'; import useMessages from 'hooks/useMessages'; +import useApiFilter from 'hooks/useApiFilter'; +import Page from 'components/layout/Page'; +import useConfig from 'hooks/useConfig'; export function UserWebsites({ userId }) { + const { cloudMode } = useConfig(); const { formatMessage, messages } = useMessages(); + const { filter, page, pageSize, handlePageSizeChange, handleFilterChange, handlePageChange } = useApiFilter(); const { get, useQuery } = useApi(); - const { data, isLoading } = useQuery(['user:websites', userId], () => - get(`/users/${userId}/websites`), + const { data, isLoading, error } = useQuery(['user:websites', userId, filter, page, pageSize], () => + get(`/users/${userId}/websites`, { + filter, + page, + pageSize, + }), ); const hasData = data && data.length !== 0; - if (isLoading) { - return ; - } - return ( -
- {hasData && } + + {hasData && ( + ) + } {!hasData && formatMessage(messages.noDataAvailable)} -
+ ); } From c213b6414f0943dac8050fbc1db33f2d2c7203c6 Mon Sep 17 00:00:00 2001 From: Brian Cao Date: Fri, 18 Aug 2023 12:39:31 -0700 Subject: [PATCH 004/113] Default list size. --- lib/prisma.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/prisma.ts b/lib/prisma.ts index 12bafa513..8fa7e8ae4 100644 --- a/lib/prisma.ts +++ b/lib/prisma.ts @@ -185,7 +185,9 @@ function getPageFilters(filters: SearchFilter): [ orderBy: string; }, ] { - const { pageSize = 10, page = 1, orderBy } = filters; + const pageSize = filters?.pageSize || 10; + const page = filters?.page || 1; + const orderBy = filters?.orderBy; return [ { From 7d5a24044a475717b36931c8f4dd724be3563c5b Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Fri, 18 Aug 2023 21:52:59 -0700 Subject: [PATCH 005/113] Code cleanup. --- .eslintrc.json | 3 ++- components/common/SettingsTable.js | 6 ++--- components/pages/reports/ReportTemplates.js | 4 ++-- components/pages/reports/ReportsPage.js | 6 ++--- .../pages/settings/teams/TeamWebsitesTable.js | 6 +---- .../pages/settings/users/UserWebsites.js | 22 +++++++++---------- .../pages/settings/websites/WebsitesTable.js | 6 ++--- .../pages/websites/WebsiteReportsPage.js | 6 ++--- lib/prisma.ts | 4 +--- queries/admin/user.ts | 14 +++++------- 10 files changed, 34 insertions(+), 43 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 25e83d5ac..f6d90ccab 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -51,7 +51,8 @@ "@typescript-eslint/no-empty-function": "off", "@typescript-eslint/no-explicit-any": "off", "@typescript-eslint/no-var-requires": "off", - "@typescript-eslint/no-empty-interface": "off" + "@typescript-eslint/no-empty-interface": "off", + "@typescript-eslint/no-unused-vars": ["error", { "ignoreRestSiblings": true }] }, "globals": { "React": "writable" diff --git a/components/common/SettingsTable.js b/components/common/SettingsTable.js index e9491331e..eb7a64112 100644 --- a/components/common/SettingsTable.js +++ b/components/common/SettingsTable.js @@ -1,4 +1,4 @@ -import EmptyPlaceholder from 'components/common/EmptyPlaceholder'; +import Empty from 'components/common/Empty'; import useMessages from 'hooks/useMessages'; import { useState } from 'react'; import { @@ -36,7 +36,7 @@ export function SettingsTable({ return ( <> - {showSearch && ( + {showSearch && !!value.length && ( )} {value.length === 0 && filterValue && ( - + )} {value.length > 0 && ( diff --git a/components/pages/reports/ReportTemplates.js b/components/pages/reports/ReportTemplates.js index 0f5e710d5..57cb113ee 100644 --- a/components/pages/reports/ReportTemplates.js +++ b/components/pages/reports/ReportTemplates.js @@ -30,7 +30,7 @@ function ReportItem({ title, description, url, icon }) { ); } -export function ReportTemplates() { +export function ReportTemplates({ showHeader = true }) { const { formatMessage, labels } = useMessages(); const reports = [ @@ -56,7 +56,7 @@ export function ReportTemplates() { return ( - + {showHeader && }
{reports.map(({ title, description, url, icon }) => { return ( diff --git a/components/pages/reports/ReportsPage.js b/components/pages/reports/ReportsPage.js index 95959832e..7ae102b02 100644 --- a/components/pages/reports/ReportsPage.js +++ b/components/pages/reports/ReportsPage.js @@ -7,7 +7,7 @@ import { Button, Icon, Icons, Text } from 'react-basics'; import ReportsTable from './ReportsTable'; export function ReportsPage() { - const { formatMessage, labels, messages } = useMessages(); + const { formatMessage, labels } = useMessages(); const { reports, error, @@ -47,9 +47,7 @@ export function ReportsPage() { showDomain={true} /> )} - {!hasData && ( - - )} + {!hasData && } ); } diff --git a/components/pages/settings/teams/TeamWebsitesTable.js b/components/pages/settings/teams/TeamWebsitesTable.js index 564c8a782..f89a91661 100644 --- a/components/pages/settings/teams/TeamWebsitesTable.js +++ b/components/pages/settings/teams/TeamWebsitesTable.js @@ -55,11 +55,7 @@ export function TeamWebsitesTable({ {canRemove && ( - + )} ); diff --git a/components/pages/settings/users/UserWebsites.js b/components/pages/settings/users/UserWebsites.js index 709f6e4d2..df8c9f572 100644 --- a/components/pages/settings/users/UserWebsites.js +++ b/components/pages/settings/users/UserWebsites.js @@ -1,24 +1,25 @@ +import Page from 'components/layout/Page'; import useApi from 'hooks/useApi'; import WebsitesTable from 'components/pages/settings/websites/WebsitesTable'; -import useMessages from 'hooks/useMessages'; import useApiFilter from 'hooks/useApiFilter'; export function UserWebsites({ userId }) { - const { formatMessage, messages } = useMessages(); const { filter, page, pageSize, handleFilterChange, handlePageChange, handlePageSizeChange } = useApiFilter(); const { get, useQuery } = useApi(); - const { data, isLoading } = useQuery(['user:websites', userId, filter, page, pageSize], () => - get(`/users/${userId}/websites`, { - filter, - page, - pageSize, - }), + const { data, isLoading, error } = useQuery( + ['user:websites', userId, filter, page, pageSize], + () => + get(`/users/${userId}/websites`, { + filter, + page, + pageSize, + }), ); const hasData = data && data.length !== 0; return ( -
+ {hasData && ( )} - {!hasData && formatMessage(messages.noDataAvailable)} -
+ ); } diff --git a/components/pages/settings/websites/WebsitesTable.js b/components/pages/settings/websites/WebsitesTable.js index 08c906aa0..89898c811 100644 --- a/components/pages/settings/websites/WebsitesTable.js +++ b/components/pages/settings/websites/WebsitesTable.js @@ -1,7 +1,7 @@ -import EmptyPlaceholder from 'components/common/EmptyPlaceholder'; import Link from 'next/link'; import { Button, Text, Icon, Icons } from 'react-basics'; import SettingsTable from 'components/common/SettingsTable'; +import Empty from 'components/common/Empty'; import useMessages from 'hooks/useMessages'; import useConfig from 'hooks/useConfig'; import useUser from 'hooks/useUser'; @@ -15,7 +15,7 @@ export function WebsitesTable({ showTeam, showEditButton, }) { - const { formatMessage, labels, messages } = useMessages(); + const { formatMessage, labels } = useMessages(); const { openExternal } = useConfig(); const { user } = useUser(); @@ -82,7 +82,7 @@ export function WebsitesTable({ }} )} - {!showTable && } + {!showTable && } ); } diff --git a/components/pages/websites/WebsiteReportsPage.js b/components/pages/websites/WebsiteReportsPage.js index b04c50d1d..be4ee8002 100644 --- a/components/pages/websites/WebsiteReportsPage.js +++ b/components/pages/websites/WebsiteReportsPage.js @@ -1,5 +1,5 @@ -import EmptyPlaceholder from 'components/common/EmptyPlaceholder'; import Page from 'components/layout/Page'; +import Empty from 'components/common/Empty'; import ReportsTable from 'components/pages/reports/ReportsTable'; import { useMessages, useWebsiteReports } from 'hooks'; import Link from 'next/link'; @@ -7,7 +7,7 @@ import { Button, Flexbox, Icon, Icons, Text } from 'react-basics'; import WebsiteHeader from './WebsiteHeader'; export function WebsiteReportsPage({ websiteId }) { - const { formatMessage, labels, messages } = useMessages(); + const { formatMessage, labels } = useMessages(); const { reports, error, @@ -48,7 +48,7 @@ export function WebsiteReportsPage({ websiteId }) { filterValue={filter} /> )} - {!hasData && } + {!hasData && } ); } diff --git a/lib/prisma.ts b/lib/prisma.ts index 8fa7e8ae4..a9832c28c 100644 --- a/lib/prisma.ts +++ b/lib/prisma.ts @@ -185,9 +185,7 @@ function getPageFilters(filters: SearchFilter): [ orderBy: string; }, ] { - const pageSize = filters?.pageSize || 10; - const page = filters?.page || 1; - const orderBy = filters?.orderBy; + const { pageSize = 10, page = 1, orderBy } = filters || {}; return [ { diff --git a/queries/admin/user.ts b/queries/admin/user.ts index ca459b9fd..dfe8ea283 100644 --- a/queries/admin/user.ts +++ b/queries/admin/user.ts @@ -37,10 +37,10 @@ export async function getUserByUsername(username: string, options: GetUserOption } export async function getUsers( - UserSearchFilter: UserSearchFilter, + searchFilter: UserSearchFilter, options?: { include?: Prisma.UserInclude }, ): Promise> { - const { teamId, filter, filterType = USER_FILTER_TYPES.all } = UserSearchFilter; + const { teamId, filter, filterType = USER_FILTER_TYPES.all } = searchFilter; const mode = prisma.getSearchMode(); const where: Prisma.UserWhereInput = { @@ -67,9 +67,10 @@ export async function getUsers( }, }), }; + const [pageFilters, getParameters] = prisma.getPageFilters({ orderBy: 'username', - ...UserSearchFilter, + ...searchFilter, }); const users = await prisma.client.user @@ -82,12 +83,9 @@ export async function getUsers( ...(options?.include && { include: options.include }), }) .then(a => { - return a.map(a => { - const { password, ...rest } = a; - - return rest; - }); + return a.map(({ password, ...rest }) => rest); }); + const count = await prisma.client.user.count({ where: { ...where, From 7a7233ead4630d12aea291ed44a4caeffaa7b00f Mon Sep 17 00:00:00 2001 From: Brian Cao Date: Sat, 19 Aug 2023 22:23:15 -0700 Subject: [PATCH 006/113] Add api validations. --- lib/middleware.ts | 33 +++++++--- lib/types.ts | 17 ++++- lib/yup.ts | 19 ++++++ pages/api/auth/login.ts | 31 +++++---- pages/api/event-data/events.ts | 29 ++++++--- pages/api/event-data/fields.ts | 23 +++++-- pages/api/event-data/stats.ts | 23 +++++-- pages/api/me/password.ts | 16 ++++- pages/api/me/teams.ts | 19 +++++- pages/api/me/websites.ts | 18 +++++- pages/api/realtime/[id].ts | 16 ++++- pages/api/reports/[id].ts | 36 +++++++++-- pages/api/reports/funnel.ts | 23 ++++++- pages/api/reports/index.ts | 33 ++++++++-- pages/api/reports/insights.ts | 39 ++++++++++- pages/api/reports/retention.ts | 31 +++++---- pages/api/send.ts | 68 +++++++++++--------- pages/api/share/[id].ts | 13 +++- pages/api/teams/[id]/index.ts | 22 ++++++- pages/api/teams/[id]/users/[userId].ts | 14 +++- pages/api/teams/[id]/users/index.ts | 25 +------ pages/api/teams/[id]/websites/[websiteId].ts | 13 +++- pages/api/teams/[id]/websites/index.ts | 21 +++++- pages/api/teams/index.ts | 20 +++++- pages/api/teams/join.ts | 21 ++++-- pages/api/users/[id]/index.ts | 20 +++++- pages/api/users/[id]/teams.ts | 15 ++++- pages/api/users/[id]/usage.ts | 14 +++- pages/api/users/[id]/websites.ts | 25 +++++-- pages/api/users/index.ts | 24 ++++++- pages/api/websites/[id]/active.ts | 12 +++- pages/api/websites/[id]/daterange.ts | 12 +++- pages/api/websites/[id]/events.ts | 22 +++++-- pages/api/websites/[id]/index.ts | 12 +++- pages/api/websites/[id]/metrics.ts | 12 +++- pages/api/websites/[id]/pageviews.ts | 12 +++- pages/api/websites/[id]/reports.ts | 12 +++- pages/api/websites/[id]/reset.ts | 12 +++- pages/api/websites/[id]/stats.ts | 12 +++- pages/api/websites/[id]/values.ts | 12 +++- pages/api/websites/index.ts | 19 +++++- 41 files changed, 690 insertions(+), 180 deletions(-) create mode 100644 lib/yup.ts diff --git a/lib/middleware.ts b/lib/middleware.ts index 414cab239..0cb0cb880 100644 --- a/lib/middleware.ts +++ b/lib/middleware.ts @@ -1,19 +1,20 @@ +import redis from '@umami/redis-client'; +import cors from 'cors'; +import debug from 'debug'; +import { getAuthToken, parseShareToken } from 'lib/auth'; +import { ROLES } from 'lib/constants'; +import { isUuid, secret } from 'lib/crypto'; +import { findSession } from 'lib/session'; import { - createMiddleware, - unauthorized, badRequest, + createMiddleware, parseSecureToken, tooManyRequest, + unauthorized, } from 'next-basics'; -import debug from 'debug'; -import cors from 'cors'; -import redis from '@umami/redis-client'; -import { findSession } from 'lib/session'; -import { getAuthToken, parseShareToken } from 'lib/auth'; -import { secret, isUuid } from 'lib/crypto'; -import { ROLES } from 'lib/constants'; -import { getUserById } from '../queries'; import { NextApiRequestCollect } from 'pages/api/send'; +import { getUserById } from '../queries'; +import { NextApiRequestQueryBody } from './types'; const log = debug('umami:middleware'); @@ -75,3 +76,15 @@ export const useAuth = createMiddleware(async (req, res, next) => { next(); }); + +export const useValidate = createMiddleware(async (req: any, res, next) => { + try { + const { yup } = req as NextApiRequestQueryBody; + + yup[req.method].validateSync({ ...req.query, ...req.body }); + } catch (e: any) { + return badRequest(res, e.message); + } + + next(); +}); diff --git a/lib/types.ts b/lib/types.ts index 3f3ac5337..3f3839a4d 100644 --- a/lib/types.ts +++ b/lib/types.ts @@ -5,11 +5,13 @@ import { EVENT_TYPE, KAFKA_TOPIC, REPORT_FILTER_TYPES, + REPORT_TYPES, ROLES, TEAM_FILTER_TYPES, USER_FILTER_TYPES, WEBSITE_FILTER_TYPES, } from './constants'; +import * as yup from 'yup'; type ObjectValues = T[keyof T]; @@ -18,6 +20,8 @@ export type Role = ObjectValues; export type EventType = ObjectValues; export type DynamicDataType = ObjectValues; export type KafkaTopic = ObjectValues; +export type ReportType = ObjectValues; + export type ReportSearchFilterType = ObjectValues; export type UserSearchFilterType = ObjectValues; export type WebsiteSearchFilterType = ObjectValues; @@ -47,8 +51,8 @@ export interface ReportSearchFilter extends SearchFilter export interface SearchFilter { filter?: string; filterType?: T; - pageSize?: number; - page?: number; + pageSize: number; + page: number; orderBy?: string; } @@ -76,11 +80,19 @@ export interface Auth { }; } +export interface YupRequest { + GET?: yup.ObjectSchema; + POST?: yup.ObjectSchema; + PUT?: yup.ObjectSchema; + DELETE?: yup.ObjectSchema; +} + export interface NextApiRequestQueryBody extends NextApiRequest { auth?: Auth; query: TQuery & { [key: string]: string | string[] }; body: TBody; headers: any; + yup: YupRequest; } export interface NextApiRequestAuth extends NextApiRequest { @@ -168,7 +180,6 @@ export interface RealtimeUpdate { export interface DateRange { startDate: Date; endDate: Date; - unit: string; value: string; } diff --git a/lib/yup.ts b/lib/yup.ts new file mode 100644 index 000000000..a9d210285 --- /dev/null +++ b/lib/yup.ts @@ -0,0 +1,19 @@ +import * as yup from 'yup'; + +export function getDateRangeValidation() { + return { + startAt: yup.number().integer().required(), + endAt: yup.number().integer().moreThan(yup.ref('startAt')).required(), + }; +} + +// ex: /funnel|insights|retention/i +export function getFilterValidation(matchRegex) { + return { + filter: yup.string(), + filterType: yup.string().matches(matchRegex), + pageSize: yup.number().integer().positive().max(200), + page: yup.number().integer().positive(), + orderBy: yup.string(), + }; +} diff --git a/pages/api/auth/login.ts b/pages/api/auth/login.ts index b9a2be000..47521084b 100644 --- a/pages/api/auth/login.ts +++ b/pages/api/auth/login.ts @@ -1,19 +1,20 @@ +import redis from '@umami/redis-client'; import debug from 'debug'; +import { setAuthKey } from 'lib/auth'; +import { secret } from 'lib/crypto'; +import { useValidate } from 'lib/middleware'; +import { NextApiRequestQueryBody, User } from 'lib/types'; import { NextApiResponse } from 'next'; import { - ok, - unauthorized, - badRequest, checkPassword, createSecureToken, - methodNotAllowed, forbidden, + methodNotAllowed, + ok, + unauthorized, } from 'next-basics'; -import redis from '@umami/redis-client'; import { getUserByUsername } from 'queries'; -import { secret } from 'lib/crypto'; -import { NextApiRequestQueryBody, User } from 'lib/types'; -import { setAuthKey } from 'lib/auth'; +import * as yup from 'yup'; const log = debug('umami:auth'); @@ -27,6 +28,13 @@ export interface LoginResponse { user: User; } +const schema = { + POST: yup.object().shape({ + username: yup.string().required(), + password: yup.string().required(), + }), +}; + export default async ( req: NextApiRequestQueryBody, res: NextApiResponse, @@ -35,13 +43,12 @@ export default async ( return forbidden(res); } + req.yup = schema; + await useValidate(req, res); + if (req.method === 'POST') { const { username, password } = req.body; - if (!username || !password) { - return badRequest(res); - } - const user = await getUserByUsername(username, { includePassword: true }); if (user && checkPassword(password, user.password)) { diff --git a/pages/api/event-data/events.ts b/pages/api/event-data/events.ts index 9f8f964b3..da0afc65d 100644 --- a/pages/api/event-data/events.ts +++ b/pages/api/event-data/events.ts @@ -1,26 +1,37 @@ import { canViewWebsite } from 'lib/auth'; -import { useCors, useAuth } from 'lib/middleware'; +import { useAuth, useCors, useValidate } from 'lib/middleware'; import { NextApiRequestQueryBody } from 'lib/types'; import { NextApiResponse } from 'next'; -import { ok, methodNotAllowed, unauthorized } from 'next-basics'; +import { methodNotAllowed, ok, unauthorized } from 'next-basics'; import { getEventDataEvents } from 'queries'; +import * as yup from 'yup'; -export interface EventDataEventsRequestQuery { +export interface EventDataFieldsRequestQuery { websiteId: string; - dateRange: { - startDate: string; - endDate: string; - }; - event?: string; + startAt: string; + endAt: string; + event: string; } +const schema = { + GET: yup.object().shape({ + websiteId: yup.string().uuid().required(), + startAt: yup.number().integer().required(), + endAt: yup.number().integer().moreThan(yup.ref('startAt')).required(), + event: yup.string().required(), + }), +}; + export default async ( - req: NextApiRequestQueryBody, + req: NextApiRequestQueryBody, res: NextApiResponse, ) => { await useCors(req, res); await useAuth(req, res); + req.yup = schema; + await useValidate(req, res); + if (req.method === 'GET') { const { websiteId, startAt, endAt, event } = req.query; diff --git a/pages/api/event-data/fields.ts b/pages/api/event-data/fields.ts index b6a731336..1cd24fe65 100644 --- a/pages/api/event-data/fields.ts +++ b/pages/api/event-data/fields.ts @@ -1,19 +1,27 @@ import { canViewWebsite } from 'lib/auth'; -import { useCors, useAuth } from 'lib/middleware'; +import { useAuth, useCors, useValidate } from 'lib/middleware'; import { NextApiRequestQueryBody } from 'lib/types'; import { NextApiResponse } from 'next'; -import { ok, methodNotAllowed, unauthorized } from 'next-basics'; +import { methodNotAllowed, ok, unauthorized } from 'next-basics'; import { getEventDataFields } from 'queries'; +import * as yup from 'yup'; export interface EventDataFieldsRequestQuery { websiteId: string; - dateRange: { - startDate: string; - endDate: string; - }; + startAt: string; + endAt: string; field?: string; } +const schema = { + GET: yup.object().shape({ + websiteId: yup.string().uuid().required(), + startAt: yup.number().integer().required(), + endAt: yup.number().integer().moreThan(yup.ref('startAt')).required(), + field: yup.string(), + }), +}; + export default async ( req: NextApiRequestQueryBody, res: NextApiResponse, @@ -21,6 +29,9 @@ export default async ( await useCors(req, res); await useAuth(req, res); + req.yup = schema; + await useValidate(req, res); + if (req.method === 'GET') { const { websiteId, startAt, endAt, field } = req.query; diff --git a/pages/api/event-data/stats.ts b/pages/api/event-data/stats.ts index 4ba843bef..b7b70dbfe 100644 --- a/pages/api/event-data/stats.ts +++ b/pages/api/event-data/stats.ts @@ -1,18 +1,24 @@ import { canViewWebsite } from 'lib/auth'; -import { useCors, useAuth } from 'lib/middleware'; +import { useAuth, useCors, useValidate } from 'lib/middleware'; import { NextApiRequestQueryBody } from 'lib/types'; import { NextApiResponse } from 'next'; -import { ok, methodNotAllowed, unauthorized } from 'next-basics'; -import { getEventDataStats } from 'queries'; +import { methodNotAllowed, ok, unauthorized } from 'next-basics'; +import * as yup from 'yup'; export interface EventDataStatsRequestQuery { websiteId: string; - dateRange: { - startDate: string; - endDate: string; - }; + startAt: string; + endAt: string; } +const schema = { + GET: yup.object().shape({ + websiteId: yup.string().uuid().required(), + startAt: yup.number().integer().required(), + endAt: yup.number().integer().moreThan(yup.ref('startAt')).required(), + }), +}; + export default async ( req: NextApiRequestQueryBody, res: NextApiResponse, @@ -20,6 +26,9 @@ export default async ( await useCors(req, res); await useAuth(req, res); + req.yup = schema; + await useValidate(req, res); + if (req.method === 'GET') { const { websiteId, startAt, endAt } = req.query; diff --git a/pages/api/me/password.ts b/pages/api/me/password.ts index f9f60fc53..6f49a182e 100644 --- a/pages/api/me/password.ts +++ b/pages/api/me/password.ts @@ -1,15 +1,16 @@ +import { useAuth, useValidate } from 'lib/middleware'; import { NextApiRequestQueryBody, User } from 'lib/types'; -import { useAuth } from 'lib/middleware'; import { NextApiResponse } from 'next'; import { badRequest, checkPassword, + forbidden, hashPassword, methodNotAllowed, - forbidden, ok, } from 'next-basics'; import { getUserById, updateUser } from 'queries'; +import * as yup from 'yup'; export interface UserPasswordRequestQuery { id: string; @@ -20,6 +21,14 @@ export interface UserPasswordRequestBody { newPassword: string; } +const schema = { + POST: yup.object().shape({ + id: yup.string().uuid().required(), + currentPassword: yup.string().required(), + newPassword: yup.string().min(8).required(), + }), +}; + export default async ( req: NextApiRequestQueryBody, res: NextApiResponse, @@ -30,6 +39,9 @@ export default async ( await useAuth(req, res); + req.yup = schema; + await useValidate(req, res); + const { currentPassword, newPassword } = req.body; const { id } = req.auth.user; diff --git a/pages/api/me/teams.ts b/pages/api/me/teams.ts index d323043b0..d394ef07d 100644 --- a/pages/api/me/teams.ts +++ b/pages/api/me/teams.ts @@ -1,10 +1,20 @@ -import { useCors } from 'lib/middleware'; +import { useCors, useValidate } from 'lib/middleware'; import { NextApiRequestQueryBody, SearchFilter, TeamSearchFilterType } from 'lib/types'; +import { getFilterValidation } from 'lib/yup'; import { NextApiResponse } from 'next'; import { methodNotAllowed } from 'next-basics'; import userTeams from 'pages/api/users/[id]/teams'; +import * as yup from 'yup'; -export interface MyTeamsRequestQuery extends SearchFilter {} +export interface MyTeamsRequestQuery extends SearchFilter { + id: string; +} + +const schema = { + GET: yup.object().shape({ + ...getFilterValidation(/All|Name|Owner/i), + }), +}; export default async ( req: NextApiRequestQueryBody, @@ -12,7 +22,12 @@ export default async ( ) => { await useCors(req, res); + req.yup = schema; + await useValidate(req, res); + if (req.method === 'GET') { + req.query.id = req.auth.user.id; + return userTeams(req, res); } diff --git a/pages/api/me/websites.ts b/pages/api/me/websites.ts index 238d1b6e2..d4a803a0d 100644 --- a/pages/api/me/websites.ts +++ b/pages/api/me/websites.ts @@ -1,11 +1,20 @@ -import { useAuth, useCors } from 'lib/middleware'; +import { useAuth, useCors, useValidate } from 'lib/middleware'; import { NextApiRequestQueryBody, SearchFilter, WebsiteSearchFilterType } from 'lib/types'; +import { getFilterValidation } from 'lib/yup'; import { NextApiResponse } from 'next'; import { methodNotAllowed } from 'next-basics'; - import userWebsites from 'pages/api/users/[id]/websites'; +import * as yup from 'yup'; -export interface MyWebsitesRequestQuery extends SearchFilter {} +export interface MyWebsitesRequestQuery extends SearchFilter { + id: string; +} + +const schema = { + GET: yup.object().shape({ + ...getFilterValidation(/All|Name|Domain/i), + }), +}; export default async ( req: NextApiRequestQueryBody, @@ -14,6 +23,9 @@ export default async ( await useCors(req, res); await useAuth(req, res); + req.yup = schema; + await useValidate(req, res); + if (req.method === 'GET') { req.query.id = req.auth.user.id; diff --git a/pages/api/realtime/[id].ts b/pages/api/realtime/[id].ts index e78599c6d..ab7bb4060 100644 --- a/pages/api/realtime/[id].ts +++ b/pages/api/realtime/[id].ts @@ -1,22 +1,34 @@ import { subMinutes } from 'date-fns'; import { canViewWebsite } from 'lib/auth'; -import { useAuth } from 'lib/middleware'; +import { useAuth, useValidate } from 'lib/middleware'; import { NextApiRequestQueryBody, RealtimeInit } from 'lib/types'; import { NextApiResponse } from 'next'; import { methodNotAllowed, ok, unauthorized } from 'next-basics'; import { getRealtimeData } from 'queries'; - +import * as yup from 'yup'; export interface RealtimeRequestQuery { id: string; startAt: number; } +const currentDate = new Date().getTime(); + +const schema = { + GET: yup.object().shape({ + id: yup.string().uuid().required(), + startAt: yup.number().integer().max(currentDate).required(), + }), +}; + export default async ( req: NextApiRequestQueryBody, res: NextApiResponse, ) => { await useAuth(req, res); + req.yup = schema; + await useValidate(req, res); + if (req.method === 'GET') { const { id: websiteId, startAt } = req.query; diff --git a/pages/api/reports/[id].ts b/pages/api/reports/[id].ts index 85bc302c8..eb4199bcd 100644 --- a/pages/api/reports/[id].ts +++ b/pages/api/reports/[id].ts @@ -1,9 +1,10 @@ -import { canUpdateReport, canViewReport, canDeleteReport } from 'lib/auth'; -import { useAuth, useCors } from 'lib/middleware'; -import { NextApiRequestQueryBody } from 'lib/types'; +import { canDeleteReport, canUpdateReport, canViewReport } from 'lib/auth'; +import { useAuth, useCors, useValidate } from 'lib/middleware'; +import { NextApiRequestQueryBody, ReportType, YupRequest } from 'lib/types'; import { NextApiResponse } from 'next'; import { methodNotAllowed, ok, unauthorized } from 'next-basics'; -import { getReportById, updateReport, deleteReport } from 'queries'; +import { deleteReport, getReportById, updateReport } from 'queries'; +import * as yup from 'yup'; export interface ReportRequestQuery { id: string; @@ -11,12 +12,34 @@ export interface ReportRequestQuery { export interface ReportRequestBody { websiteId: string; - type: string; + type: ReportType; name: string; description: string; parameters: string; } +const schema: YupRequest = { + GET: yup.object().shape({ + id: yup.string().uuid().required(), + }), + POST: yup.object().shape({ + id: yup.string().uuid().required(), + websiteId: yup.string().uuid().required(), + type: yup + .string() + .matches(/funnel|insights|retention/i) + .required(), + name: yup.string().max(200).required(), + description: yup.string().max(500), + parameters: yup + .object() + .test('len', 'Must not exceed 6000 characters.', val => JSON.stringify(val).length < 6000), + }), + DELETE: yup.object().shape({ + id: yup.string().uuid().required(), + }), +}; + export default async ( req: NextApiRequestQueryBody, res: NextApiResponse, @@ -24,6 +47,9 @@ export default async ( await useCors(req, res); await useAuth(req, res); + req.yup = schema; + await useValidate(req, res); + const { id: reportId } = req.query; const { user: { id: userId }, diff --git a/pages/api/reports/funnel.ts b/pages/api/reports/funnel.ts index 33882e03f..a51817bf4 100644 --- a/pages/api/reports/funnel.ts +++ b/pages/api/reports/funnel.ts @@ -1,9 +1,10 @@ import { canViewWebsite } from 'lib/auth'; -import { useCors, useAuth } from 'lib/middleware'; +import { useAuth, useCors, useValidate } from 'lib/middleware'; import { NextApiRequestQueryBody } from 'lib/types'; import { NextApiResponse } from 'next'; -import { ok, methodNotAllowed, unauthorized } from 'next-basics'; +import { methodNotAllowed, ok, unauthorized } from 'next-basics'; import { getFunnel } from 'queries'; +import * as yup from 'yup'; export interface FunnelRequestBody { websiteId: string; @@ -22,6 +23,21 @@ export interface FunnelResponse { endAt: number; } +const schema = { + POST: yup.object().shape({ + websiteId: yup.string().uuid().required(), + urls: yup.array().min(2).of(yup.string()).required(), + window: yup.number().positive().required(), + dateRange: yup + .object() + .shape({ + startDate: yup.date().required(), + endDate: yup.date().required(), + }) + .required(), + }), +}; + export default async ( req: NextApiRequestQueryBody, res: NextApiResponse, @@ -29,6 +45,9 @@ export default async ( await useCors(req, res); await useAuth(req, res); + req.yup = schema; + await useValidate(req, res); + if (req.method === 'POST') { const { websiteId, diff --git a/pages/api/reports/index.ts b/pages/api/reports/index.ts index 762f297c7..e62a1cc57 100644 --- a/pages/api/reports/index.ts +++ b/pages/api/reports/index.ts @@ -1,10 +1,11 @@ -import { canViewWebsite } from 'lib/auth'; import { uuid } from 'lib/crypto'; -import { useAuth, useCors } from 'lib/middleware'; +import { useAuth, useCors, useValidate } from 'lib/middleware'; import { NextApiRequestQueryBody, ReportSearchFilterType, SearchFilter } from 'lib/types'; +import { getFilterValidation } from 'lib/yup'; import { NextApiResponse } from 'next'; -import { methodNotAllowed, ok, unauthorized } from 'next-basics'; -import { createReport, getReportsByUserId, getReportsByWebsiteId } from 'queries'; +import { methodNotAllowed, ok } from 'next-basics'; +import { createReport, getReportsByUserId } from 'queries'; +import * as yup from 'yup'; export interface ReportsRequestQuery extends SearchFilter {} @@ -14,11 +15,28 @@ export interface ReportRequestBody { type: string; description: string; parameters: { - window: string; - urls: string[]; + [key: string]: any; }; } +const schema = { + GET: yup.object().shape({ + ...getFilterValidation(/All|Name|Description|Type|Username|Website Name|Website Domain/i), + }), + POST: yup.object().shape({ + websiteId: yup.string().uuid().required(), + name: yup.string().max(200).required(), + type: yup + .string() + .matches(/funnel|insights|retention/i) + .required(), + description: yup.string().max(500), + parameters: yup + .object() + .test('len', 'Must not exceed 6000 characters.', val => JSON.stringify(val).length < 6000), + }), +}; + export default async ( req: NextApiRequestQueryBody, res: NextApiResponse, @@ -26,6 +44,9 @@ export default async ( await useCors(req, res); await useAuth(req, res); + req.yup = schema; + await useValidate(req, res); + const { user: { id: userId }, } = req.auth; diff --git a/pages/api/reports/insights.ts b/pages/api/reports/insights.ts index 09a07d2fb..04e51d4ca 100644 --- a/pages/api/reports/insights.ts +++ b/pages/api/reports/insights.ts @@ -1,9 +1,10 @@ import { canViewWebsite } from 'lib/auth'; -import { useCors, useAuth } from 'lib/middleware'; +import { useAuth, useCors, useValidate } from 'lib/middleware'; import { NextApiRequestQueryBody } from 'lib/types'; import { NextApiResponse } from 'next'; -import { ok, methodNotAllowed, unauthorized } from 'next-basics'; +import { methodNotAllowed, ok, unauthorized } from 'next-basics'; import { getInsights } from 'queries'; +import * as yup from 'yup'; export interface InsightsRequestBody { websiteId: string; @@ -16,6 +17,37 @@ export interface InsightsRequestBody { groups: { name: string; type: string }[]; } +const schema = { + POST: yup.object().shape({ + websiteId: yup.string().uuid().required(), + dateRange: yup + .object() + .shape({ + startDate: yup.date().required(), + endDate: yup.date().required(), + }) + .required(), + fields: yup + .array() + .of( + yup.object().shape({ + name: yup.string().required(), + type: yup.string().required(), + value: yup.string().required(), + }), + ) + .min(1) + .required(), + filters: yup.array().of(yup.string()).min(1).required(), + groups: yup.array().of( + yup.object().shape({ + name: yup.string().required(), + type: yup.string().required(), + }), + ), + }), +}; + function convertFilters(filters) { return filters.reduce((obj, { name, ...value }) => { obj[name] = value; @@ -31,6 +63,9 @@ export default async ( await useCors(req, res); await useAuth(req, res); + req.yup = schema; + await useValidate(req, res); + if (req.method === 'POST') { const { websiteId, diff --git a/pages/api/reports/retention.ts b/pages/api/reports/retention.ts index 40b3266bd..4006ab128 100644 --- a/pages/api/reports/retention.ts +++ b/pages/api/reports/retention.ts @@ -1,33 +1,43 @@ import { canViewWebsite } from 'lib/auth'; -import { useCors, useAuth } from 'lib/middleware'; +import { useAuth, useCors, useValidate } from 'lib/middleware'; import { NextApiRequestQueryBody } from 'lib/types'; import { NextApiResponse } from 'next'; -import { ok, methodNotAllowed, unauthorized } from 'next-basics'; +import { methodNotAllowed, ok, unauthorized } from 'next-basics'; import { getRetention } from 'queries'; +import * as yup from 'yup'; export interface RetentionRequestBody { websiteId: string; - dateRange: { window; startDate: string; endDate: string }; - timezone: string; + dateRange: { startDate: string; endDate: string }; } -export interface RetentionResponse { - startAt: number; - endAt: number; -} +const schema = { + POST: yup.object().shape({ + websiteId: yup.string().uuid().required(), + dateRange: yup + .object() + .shape({ + startDate: yup.date().required(), + endDate: yup.date().required(), + }) + .required(), + }), +}; export default async ( req: NextApiRequestQueryBody, - res: NextApiResponse, + res: NextApiResponse, ) => { await useCors(req, res); await useAuth(req, res); + req.yup = schema; + await useValidate(req, res); + if (req.method === 'POST') { const { websiteId, dateRange: { startDate, endDate }, - timezone, } = req.body; if (!(await canViewWebsite(req.auth, websiteId))) { @@ -37,7 +47,6 @@ export default async ( const data = await getRetention(websiteId, { startDate: new Date(startDate), endDate: new Date(endDate), - timezone, }); return ok(res, data); diff --git a/pages/api/send.ts b/pages/api/send.ts index f90ded772..a379f261f 100644 --- a/pages/api/send.ts +++ b/pages/api/send.ts @@ -1,14 +1,15 @@ -import isbot from 'isbot'; -import ipaddr from 'ipaddr.js'; -import { createToken, ok, send, badRequest, forbidden } from 'next-basics'; -import { saveEvent, saveSessionData } from 'queries'; -import { useCors, useSession } from 'lib/middleware'; -import { getJsonBody, getIpAddress } from 'lib/detect'; -import { secret } from 'lib/crypto'; -import { NextApiRequest, NextApiResponse } from 'next'; import { Resolver } from 'dns/promises'; -import { CollectionType } from 'lib/types'; -import { COLLECTION_TYPE } from 'lib/constants'; +import ipaddr from 'ipaddr.js'; +import isbot from 'isbot'; +import { COLLECTION_TYPE, HOSTNAME_REGEX } from 'lib/constants'; +import { secret } from 'lib/crypto'; +import { getIpAddress, getJsonBody } from 'lib/detect'; +import { useCors, useSession, useValidate } from 'lib/middleware'; +import { CollectionType, YupRequest } from 'lib/types'; +import { NextApiRequest, NextApiResponse } from 'next'; +import { badRequest, createToken, forbidden, ok, send } from 'next-basics'; +import { saveEvent, saveSessionData } from 'queries'; +import * as yup from 'yup'; export interface CollectRequestBody { payload: { @@ -43,8 +44,32 @@ export interface NextApiRequestCollect extends NextApiRequest { city: string; }; headers: { [key: string]: any }; + yup: YupRequest; } +const schema = { + POST: yup.object().shape({ + payload: yup + .object() + .shape({ + data: yup.object(), + hostname: yup.string().matches(HOSTNAME_REGEX).max(100), + language: yup.string().max(35), + referrer: yup.string().max(500), + screen: yup.string().max(11), + title: yup.string().max(500), + url: yup.string().max(500), + website: yup.string().uuid().required(), + name: yup.string().max(50), + }) + .required(), + type: yup + .string() + .matches(/event|identify/i) + .required(), + }), +}; + export default async (req: NextApiRequestCollect, res: NextApiResponse) => { await useCors(req, res); @@ -54,11 +79,8 @@ export default async (req: NextApiRequestCollect, res: NextApiResponse) => { const { type, payload } = getJsonBody(req); - const error = validateBody({ type, payload }); - - if (error) { - return badRequest(res, error); - } + req.yup = schema; + await useValidate(req, res); if (await hasBlockedIp(req)) { return forbidden(res); @@ -118,22 +140,6 @@ export default async (req: NextApiRequestCollect, res: NextApiResponse) => { return send(res, token); }; -function validateBody({ type, payload }: CollectRequestBody) { - if (!type || !payload) { - return 'Invalid payload.'; - } - - if (type !== COLLECTION_TYPE.event && type !== COLLECTION_TYPE.identify) { - return 'Wrong payload type.'; - } - - const { data } = payload; - - if (data && !(typeof data === 'object' && !Array.isArray(data))) { - return 'Invalid event data.'; - } -} - async function hasBlockedIp(req: NextApiRequestCollect) { const ignoreIps = process.env.IGNORE_IP; const ignoreHostnames = process.env.IGNORE_HOSTNAME; diff --git a/pages/api/share/[id].ts b/pages/api/share/[id].ts index 0592d2167..ad6422835 100644 --- a/pages/api/share/[id].ts +++ b/pages/api/share/[id].ts @@ -1,8 +1,10 @@ -import { NextApiRequestQueryBody } from 'lib/types'; import { secret } from 'lib/crypto'; +import { useValidate } from 'lib/middleware'; +import { NextApiRequestQueryBody } from 'lib/types'; import { NextApiResponse } from 'next'; import { createToken, methodNotAllowed, notFound, ok } from 'next-basics'; import { getWebsiteByShareId } from 'queries'; +import * as yup from 'yup'; export interface ShareRequestQuery { id: string; @@ -13,10 +15,19 @@ export interface ShareResponse { token: string; } +const schema = { + GET: yup.object().shape({ + id: yup.string().uuid().required(), + }), +}; + export default async ( req: NextApiRequestQueryBody, res: NextApiResponse, ) => { + req.yup = schema; + await useValidate(req, res); + const { id: shareId } = req.query; if (req.method === 'GET') { diff --git a/pages/api/teams/[id]/index.ts b/pages/api/teams/[id]/index.ts index 7fb664a01..31c47b2f1 100644 --- a/pages/api/teams/[id]/index.ts +++ b/pages/api/teams/[id]/index.ts @@ -1,10 +1,11 @@ import { Team } from '@prisma/client'; -import { NextApiRequestQueryBody } from 'lib/types'; import { canDeleteTeam, canUpdateTeam, canViewTeam } from 'lib/auth'; -import { useAuth } from 'lib/middleware'; +import { useAuth, useValidate } from 'lib/middleware'; +import { NextApiRequestQueryBody } from 'lib/types'; import { NextApiResponse } from 'next'; import { methodNotAllowed, ok, unauthorized } from 'next-basics'; import { deleteTeam, getTeamById, updateTeam } from 'queries'; +import * as yup from 'yup'; export interface TeamRequestQuery { id: string; @@ -15,12 +16,29 @@ export interface TeamRequestBody { accessCode: string; } +const schema = { + GET: yup.object().shape({ + id: yup.string().uuid().required(), + }), + POST: yup.object().shape({ + id: yup.string().uuid().required(), + name: yup.string().max(50).required(), + accessCode: yup.string().max(50).required(), + }), + DELETE: yup.object().shape({ + id: yup.string().uuid().required(), + }), +}; + export default async ( req: NextApiRequestQueryBody, res: NextApiResponse, ) => { await useAuth(req, res); + req.yup = schema; + await useValidate(req, res); + const { id: teamId } = req.query; if (req.method === 'GET') { diff --git a/pages/api/teams/[id]/users/[userId].ts b/pages/api/teams/[id]/users/[userId].ts index 1e4ca6239..adb635d52 100644 --- a/pages/api/teams/[id]/users/[userId].ts +++ b/pages/api/teams/[id]/users/[userId].ts @@ -1,18 +1,28 @@ import { canDeleteTeamUser } from 'lib/auth'; -import { useAuth } from 'lib/middleware'; +import { useAuth, useValidate } from 'lib/middleware'; import { NextApiRequestQueryBody } from 'lib/types'; import { NextApiResponse } from 'next'; import { methodNotAllowed, ok, unauthorized } from 'next-basics'; import { deleteTeamUser } from 'queries'; - +import * as yup from 'yup'; export interface TeamUserRequestQuery { id: string; userId: string; } +const schema = { + DELETE: yup.object().shape({ + id: yup.string().uuid().required(), + userId: yup.string().uuid().required(), + }), +}; + export default async (req: NextApiRequestQueryBody, res: NextApiResponse) => { await useAuth(req, res); + req.yup = schema; + await useValidate(req, res); + if (req.method === 'DELETE') { const { id: teamId, userId } = req.query; diff --git a/pages/api/teams/[id]/users/index.ts b/pages/api/teams/[id]/users/index.ts index 6f8b077e0..52b25da68 100644 --- a/pages/api/teams/[id]/users/index.ts +++ b/pages/api/teams/[id]/users/index.ts @@ -1,9 +1,9 @@ -import { canUpdateTeam, canViewTeam } from 'lib/auth'; +import { canViewTeam } from 'lib/auth'; import { useAuth } from 'lib/middleware'; import { NextApiRequestQueryBody, SearchFilter, TeamSearchFilterType } from 'lib/types'; import { NextApiResponse } from 'next'; -import { badRequest, methodNotAllowed, ok, unauthorized } from 'next-basics'; -import { createTeamUser, getUserByUsername, getUsersByTeamId } from 'queries'; +import { methodNotAllowed, ok, unauthorized } from 'next-basics'; +import { getUsersByTeamId } from 'queries'; export interface TeamUserRequestQuery extends SearchFilter { id: string; @@ -38,24 +38,5 @@ export default async ( return ok(res, users); } - if (req.method === 'POST') { - if (!(await canUpdateTeam(req.auth, teamId))) { - return unauthorized(res, 'You must be the owner of this team.'); - } - - const { email, roleId: roleId } = req.body; - - // Check for User - const user = await getUserByUsername(email); - - if (!user) { - return badRequest(res, 'The User does not exists.'); - } - - const updated = await createTeamUser(user.id, teamId, roleId); - - return ok(res, updated); - } - return methodNotAllowed(res); }; diff --git a/pages/api/teams/[id]/websites/[websiteId].ts b/pages/api/teams/[id]/websites/[websiteId].ts index 795295d36..ada1efdc0 100644 --- a/pages/api/teams/[id]/websites/[websiteId].ts +++ b/pages/api/teams/[id]/websites/[websiteId].ts @@ -1,21 +1,32 @@ import { canDeleteTeamWebsite } from 'lib/auth'; -import { useAuth } from 'lib/middleware'; +import { useAuth, useValidate } from 'lib/middleware'; import { NextApiRequestQueryBody } from 'lib/types'; import { NextApiResponse } from 'next'; import { methodNotAllowed, ok, unauthorized } from 'next-basics'; import { deleteTeamWebsite } from 'queries/admin/teamWebsite'; +import * as yup from 'yup'; export interface TeamWebsitesRequestQuery { id: string; websiteId: string; } +const schema = { + DELETE: yup.object().shape({ + id: yup.string().uuid().required(), + websiteId: yup.string().uuid().required(), + }), +}; + export default async ( req: NextApiRequestQueryBody, res: NextApiResponse, ) => { await useAuth(req, res); + req.yup = schema; + await useValidate(req, res); + const { id: teamId, websiteId } = req.query; if (req.method === 'DELETE') { diff --git a/pages/api/teams/[id]/websites/index.ts b/pages/api/teams/[id]/websites/index.ts index dcd08939a..4de327092 100644 --- a/pages/api/teams/[id]/websites/index.ts +++ b/pages/api/teams/[id]/websites/index.ts @@ -1,9 +1,10 @@ import { canViewTeam } from 'lib/auth'; -import { useAuth } from 'lib/middleware'; +import { useAuth, useValidate } from 'lib/middleware'; import { NextApiRequestQueryBody, SearchFilter, WebsiteSearchFilterType } from 'lib/types'; +import { getFilterValidation } from 'lib/yup'; import { NextApiResponse } from 'next'; import { methodNotAllowed, ok, unauthorized } from 'next-basics'; -import { getWebsites, getWebsitesByTeamId } from 'queries'; +import { getWebsitesByTeamId } from 'queries'; import { createTeamWebsites } from 'queries/admin/teamWebsite'; export interface TeamWebsiteRequestQuery extends SearchFilter { @@ -14,12 +15,28 @@ export interface TeamWebsiteRequestBody { websiteIds?: string[]; } +import * as yup from 'yup'; + +const schema = { + GET: yup.object().shape({ + id: yup.string().uuid().required(), + ...getFilterValidation(/All|Name|Domain/i), + }), + POST: yup.object().shape({ + id: yup.string().uuid().required(), + websiteIds: yup.array().of(yup.string()).min(1).required(), + }), +}; + export default async ( req: NextApiRequestQueryBody, res: NextApiResponse, ) => { await useAuth(req, res); + req.yup = schema; + await useValidate(req, res); + const { id: teamId } = req.query; if (req.method === 'GET') { diff --git a/pages/api/teams/index.ts b/pages/api/teams/index.ts index 997ed8854..dd742b9e2 100644 --- a/pages/api/teams/index.ts +++ b/pages/api/teams/index.ts @@ -1,23 +1,39 @@ import { Team } from '@prisma/client'; import { canCreateTeam } from 'lib/auth'; import { uuid } from 'lib/crypto'; -import { useAuth } from 'lib/middleware'; +import { useAuth, useValidate } from 'lib/middleware'; import { NextApiRequestQueryBody, SearchFilter, TeamSearchFilterType } from 'lib/types'; +import { getFilterValidation } from 'lib/yup'; import { NextApiResponse } from 'next'; import { getRandomChars, methodNotAllowed, ok, unauthorized } from 'next-basics'; import { createTeam, getTeamsByUserId } from 'queries'; +import * as yup from 'yup'; export interface TeamsRequestQuery extends SearchFilter {} -export interface TeamsRequestBody extends SearchFilter { +export interface TeamsRequestBody { name: string; } +export interface MyTeamsRequestQuery extends SearchFilter {} + +const schema = { + GET: yup.object().shape({ + ...getFilterValidation(/All|Name|Owner/i), + }), + POST: yup.object().shape({ + name: yup.string().max(50).required(), + }), +}; + export default async ( req: NextApiRequestQueryBody, res: NextApiResponse, ) => { await useAuth(req, res); + req.yup = schema; + await useValidate(req, res); + const { user: { id: userId }, } = req.auth; diff --git a/pages/api/teams/join.ts b/pages/api/teams/join.ts index ce7367a0c..06feda8a6 100644 --- a/pages/api/teams/join.ts +++ b/pages/api/teams/join.ts @@ -1,21 +1,30 @@ import { Team } from '@prisma/client'; -import { NextApiRequestQueryBody } from 'lib/types'; -import { useAuth } from 'lib/middleware'; -import { NextApiResponse } from 'next'; -import { methodNotAllowed, ok, notFound } from 'next-basics'; -import { createTeamUser, getTeamByAccessCode, getTeamUser } from 'queries'; import { ROLES } from 'lib/constants'; - +import { useAuth, useValidate } from 'lib/middleware'; +import { NextApiRequestQueryBody } from 'lib/types'; +import { NextApiResponse } from 'next'; +import { methodNotAllowed, notFound, ok } from 'next-basics'; +import { createTeamUser, getTeamByAccessCode, getTeamUser } from 'queries'; +import * as yup from 'yup'; export interface TeamsJoinRequestBody { accessCode: string; } +const schema = { + POST: yup.object().shape({ + accessCode: yup.string().max(50).required(), + }), +}; + export default async ( req: NextApiRequestQueryBody, res: NextApiResponse, ) => { await useAuth(req, res); + req.yup = schema; + await useValidate(req, res); + if (req.method === 'POST') { const { accessCode } = req.body; diff --git a/pages/api/users/[id]/index.ts b/pages/api/users/[id]/index.ts index e09b1b5f8..3ac560ede 100644 --- a/pages/api/users/[id]/index.ts +++ b/pages/api/users/[id]/index.ts @@ -1,9 +1,10 @@ -import { NextApiRequestQueryBody, Role, User } from 'lib/types'; import { canDeleteUser, canUpdateUser, canViewUser } from 'lib/auth'; -import { useAuth } from 'lib/middleware'; +import { useAuth, useValidate } from 'lib/middleware'; +import { NextApiRequestQueryBody, Role, User } from 'lib/types'; import { NextApiResponse } from 'next'; import { badRequest, hashPassword, methodNotAllowed, ok, unauthorized } from 'next-basics'; import { deleteUser, getUserById, getUserByUsername, updateUser } from 'queries'; +import * as yup from 'yup'; export interface UserRequestQuery { id: string; @@ -15,12 +16,27 @@ export interface UserRequestBody { role: Role; } +const schema = { + GET: yup.object().shape({ + id: yup.string().uuid().required(), + }), + POST: yup.object().shape({ + id: yup.string().uuid().required(), + username: yup.string().max(255), + password: yup.string(), + role: yup.string().matches(/admin|user|view-only/i), + }), +}; + export default async ( req: NextApiRequestQueryBody, res: NextApiResponse, ) => { await useAuth(req, res); + req.yup = schema; + await useValidate(req, res); + const { user: { id: userId, isAdmin }, } = req.auth; diff --git a/pages/api/users/[id]/teams.ts b/pages/api/users/[id]/teams.ts index 831a992d8..eb34410cb 100644 --- a/pages/api/users/[id]/teams.ts +++ b/pages/api/users/[id]/teams.ts @@ -1,9 +1,10 @@ -import { useAuth, useCors } from 'lib/middleware'; +import { useAuth, useCors, useValidate } from 'lib/middleware'; import { NextApiRequestQueryBody, SearchFilter, TeamSearchFilterType } from 'lib/types'; +import { getFilterValidation } from 'lib/yup'; import { NextApiResponse } from 'next'; import { methodNotAllowed, ok, unauthorized } from 'next-basics'; import { getTeamsByUserId } from 'queries'; - +import * as yup from 'yup'; export interface UserTeamsRequestQuery extends SearchFilter { id: string; } @@ -14,6 +15,13 @@ export interface UserTeamsRequestBody { shareId: string; } +const schema = { + GET: yup.object().shape({ + id: yup.string().uuid().required(), + ...getFilterValidation('/All|Name|Owner/i'), + }), +}; + export default async ( req: NextApiRequestQueryBody, res: NextApiResponse, @@ -21,6 +29,9 @@ export default async ( await useCors(req, res); await useAuth(req, res); + req.yup = schema; + await useValidate(req, res); + const { user } = req.auth; const { id: userId } = req.query; diff --git a/pages/api/users/[id]/usage.ts b/pages/api/users/[id]/usage.ts index 0118df92b..b0fc2055b 100644 --- a/pages/api/users/[id]/usage.ts +++ b/pages/api/users/[id]/usage.ts @@ -1,8 +1,9 @@ -import { useAuth, useCors } from 'lib/middleware'; +import { useAuth, useCors, useValidate } from 'lib/middleware'; import { NextApiRequestQueryBody } from 'lib/types'; import { NextApiResponse } from 'next'; import { methodNotAllowed, ok, unauthorized } from 'next-basics'; import { getEventDataUsage, getEventUsage, getUserWebsites } from 'queries'; +import * as yup from 'yup'; export interface UserUsageRequestQuery { id: string; @@ -21,6 +22,14 @@ export interface UserUsageRequestResponse { }[]; } +const schema = { + GET: yup.object().shape({ + id: yup.string().uuid().required(), + startAt: yup.number().integer().required(), + endAt: yup.number().integer().moreThan(yup.ref('startAt')).required(), + }), +}; + export default async ( req: NextApiRequestQueryBody, res: NextApiResponse, @@ -28,6 +37,9 @@ export default async ( await useCors(req, res); await useAuth(req, res); + req.yup = schema; + await useValidate(req, res); + const { user } = req.auth; if (req.method === 'GET') { diff --git a/pages/api/users/[id]/websites.ts b/pages/api/users/[id]/websites.ts index 0e9231f73..65e9a0e8a 100644 --- a/pages/api/users/[id]/websites.ts +++ b/pages/api/users/[id]/websites.ts @@ -1,25 +1,36 @@ -import { useAuth, useCors } from 'lib/middleware'; +import { useAuth, useCors, useValidate } from 'lib/middleware'; import { NextApiRequestQueryBody, SearchFilter, WebsiteSearchFilterType } from 'lib/types'; +import { getFilterValidation } from 'lib/yup'; import { NextApiResponse } from 'next'; import { methodNotAllowed, ok, unauthorized } from 'next-basics'; import { getWebsitesByUserId } from 'queries'; +import * as yup from 'yup'; export interface UserWebsitesRequestQuery extends SearchFilter { id: string; -} -export interface UserWebsitesRequestBody { - name: string; - domain: string; - shareId: string; + includeTeams?: boolean; + onlyTeams?: boolean; } +const schema = { + GET: yup.object().shape({ + id: yup.string().uuid().required(), + includeTeams: yup.boolean(), + onlyTeams: yup.boolean(), + ...getFilterValidation(/All|Name|Domain/i), + }), +}; + export default async ( - req: NextApiRequestQueryBody, + req: NextApiRequestQueryBody, res: NextApiResponse, ) => { await useCors(req, res); await useAuth(req, res); + req.yup = schema; + await useValidate(req, res); + const { user } = req.auth; const { id: userId, page, filter, pageSize, includeTeams, onlyTeams } = req.query; diff --git a/pages/api/users/index.ts b/pages/api/users/index.ts index 5e913c027..0b523c70c 100644 --- a/pages/api/users/index.ts +++ b/pages/api/users/index.ts @@ -1,8 +1,9 @@ import { canCreateUser, canViewUsers } from 'lib/auth'; import { ROLES } from 'lib/constants'; import { uuid } from 'lib/crypto'; -import { useAuth } from 'lib/middleware'; +import { useAuth, useValidate } from 'lib/middleware'; import { NextApiRequestQueryBody, Role, SearchFilter, User, UserSearchFilterType } from 'lib/types'; +import { getFilterValidation } from 'lib/yup'; import { NextApiResponse } from 'next'; import { badRequest, hashPassword, methodNotAllowed, ok, unauthorized } from 'next-basics'; import { createUser, getUserByUsername, getUsers } from 'queries'; @@ -15,12 +16,31 @@ export interface UsersRequestBody { role?: Role; } +import * as yup from 'yup'; +const schema = { + GET: yup.object().shape({ + ...getFilterValidation(/All|Username/i), + }), + POST: yup.object().shape({ + username: yup.string().max(255).required(), + password: yup.string().required(), + id: yup.string().uuid(), + role: yup + .string() + .matches(/admin|user|view-only/i) + .required(), + }), +}; + export default async ( req: NextApiRequestQueryBody, res: NextApiResponse, ) => { await useAuth(req, res); + req.yup = schema; + await useValidate(req, res); + if (req.method === 'GET') { if (!(await canViewUsers(req.auth))) { return unauthorized(res); @@ -28,7 +48,7 @@ export default async ( const { page, filter, pageSize } = req.query; - const users = await getUsers({ page, filter, pageSize: +pageSize || null }); + const users = await getUsers({ page, filter, pageSize: pageSize ? +pageSize : null }); return ok(res, users); } diff --git a/pages/api/websites/[id]/active.ts b/pages/api/websites/[id]/active.ts index 99c8d9990..abc23dd78 100644 --- a/pages/api/websites/[id]/active.ts +++ b/pages/api/websites/[id]/active.ts @@ -1,14 +1,21 @@ import { WebsiteActive, NextApiRequestQueryBody } from 'lib/types'; import { canViewWebsite } from 'lib/auth'; -import { useAuth, useCors } from 'lib/middleware'; +import { useAuth, useCors, useValidate } from 'lib/middleware'; import { NextApiResponse } from 'next'; import { methodNotAllowed, ok, unauthorized } from 'next-basics'; import { getActiveVisitors } from 'queries'; +import * as yup from 'yup'; export interface WebsiteActiveRequestQuery { id: string; } +const schema = { + GET: yup.object().shape({ + id: yup.string().uuid().required(), + }), +}; + export default async ( req: NextApiRequestQueryBody, res: NextApiResponse, @@ -16,6 +23,9 @@ export default async ( await useCors(req, res); await useAuth(req, res); + req.yup = schema; + await useValidate(req, res); + const { id: websiteId } = req.query; if (req.method === 'GET') { diff --git a/pages/api/websites/[id]/daterange.ts b/pages/api/websites/[id]/daterange.ts index dc0435600..bfa5338e4 100644 --- a/pages/api/websites/[id]/daterange.ts +++ b/pages/api/websites/[id]/daterange.ts @@ -1,14 +1,21 @@ import { WebsiteActive, NextApiRequestQueryBody } from 'lib/types'; import { canViewWebsite } from 'lib/auth'; -import { useAuth, useCors } from 'lib/middleware'; +import { useAuth, useCors, useValidate } from 'lib/middleware'; import { NextApiResponse } from 'next'; import { methodNotAllowed, ok, unauthorized } from 'next-basics'; import { getWebsiteDateRange } from 'queries'; +import * as yup from 'yup'; export interface WebsiteDateRangeRequestQuery { id: string; } +const schema = { + GET: yup.object().shape({ + id: yup.string().uuid().required(), + }), +}; + export default async ( req: NextApiRequestQueryBody, res: NextApiResponse, @@ -16,6 +23,9 @@ export default async ( await useCors(req, res); await useAuth(req, res); + req.yup = schema; + await useValidate(req, res); + const { id: websiteId } = req.query; if (req.method === 'GET') { diff --git a/pages/api/websites/[id]/events.ts b/pages/api/websites/[id]/events.ts index 7d4f999f6..427cb40ea 100644 --- a/pages/api/websites/[id]/events.ts +++ b/pages/api/websites/[id]/events.ts @@ -1,6 +1,6 @@ import { WebsiteMetric, NextApiRequestQueryBody } from 'lib/types'; import { canViewWebsite } from 'lib/auth'; -import { useAuth, useCors } from 'lib/middleware'; +import { useAuth, useCors, useValidate } from 'lib/middleware'; import moment from 'moment-timezone'; import { NextApiResponse } from 'next'; import { badRequest, methodNotAllowed, ok, unauthorized } from 'next-basics'; @@ -16,9 +16,21 @@ export interface WebsiteEventsRequestQuery { unit: string; timezone: string; url: string; - eventName: string; } +import * as yup from 'yup'; + +const schema = { + GET: yup.object().shape({ + id: yup.string().uuid().required(), + startAt: yup.number().integer().required(), + endAt: yup.number().integer().moreThan(yup.ref('startAt')).required(), + unit: yup.string().required(), + timezone: yup.string().required(), + url: yup.string(), + }), +}; + export default async ( req: NextApiRequestQueryBody, res: NextApiResponse, @@ -26,7 +38,10 @@ export default async ( await useCors(req, res); await useAuth(req, res); - const { id: websiteId, timezone, url, eventName } = req.query; + req.yup = schema; + await useValidate(req, res); + + const { id: websiteId, timezone, url } = req.query; const { startDate, endDate, unit } = await parseDateRangeQuery(req); if (req.method === 'GET') { @@ -44,7 +59,6 @@ export default async ( timezone, unit, url, - eventName, }); return ok(res, events); diff --git a/pages/api/websites/[id]/index.ts b/pages/api/websites/[id]/index.ts index 3d053d0eb..597568de5 100644 --- a/pages/api/websites/[id]/index.ts +++ b/pages/api/websites/[id]/index.ts @@ -2,7 +2,7 @@ import { NextApiResponse } from 'next'; import { methodNotAllowed, ok, serverError, unauthorized } from 'next-basics'; import { Website, NextApiRequestQueryBody } from 'lib/types'; import { canViewWebsite, canUpdateWebsite, canDeleteWebsite } from 'lib/auth'; -import { useAuth, useCors } from 'lib/middleware'; +import { useAuth, useCors, useValidate } from 'lib/middleware'; import { deleteWebsite, getWebsiteById, updateWebsite } from 'queries'; import { SHARE_ID_REGEX } from 'lib/constants'; @@ -16,6 +16,13 @@ export interface WebsiteRequestBody { shareId: string; } +import * as yup from 'yup'; + +const schema = { + GET: yup.object().shape({ + id: yup.string().uuid().required(), + }), +}; export default async ( req: NextApiRequestQueryBody, res: NextApiResponse, @@ -23,6 +30,9 @@ export default async ( await useCors(req, res); await useAuth(req, res); + req.yup = schema; + await useValidate(req, res); + const { id: websiteId } = req.query; if (req.method === 'GET') { diff --git a/pages/api/websites/[id]/metrics.ts b/pages/api/websites/[id]/metrics.ts index 7c84583c2..67c15ecae 100644 --- a/pages/api/websites/[id]/metrics.ts +++ b/pages/api/websites/[id]/metrics.ts @@ -2,10 +2,11 @@ import { NextApiResponse } from 'next'; import { badRequest, methodNotAllowed, ok, unauthorized } from 'next-basics'; import { WebsiteMetric, NextApiRequestQueryBody } from 'lib/types'; import { canViewWebsite } from 'lib/auth'; -import { useAuth, useCors } from 'lib/middleware'; +import { useAuth, useCors, useValidate } from 'lib/middleware'; import { SESSION_COLUMNS, EVENT_COLUMNS, FILTER_COLUMNS } from 'lib/constants'; import { getPageviewMetrics, getSessionMetrics } from 'queries'; import { parseDateRangeQuery } from 'lib/query'; +import * as yup from 'yup'; export interface WebsiteMetricsRequestQuery { id: string; @@ -26,6 +27,12 @@ export interface WebsiteMetricsRequestQuery { language: string; } +const schema = { + GET: yup.object().shape({ + id: yup.string().uuid().required(), + }), +}; + export default async ( req: NextApiRequestQueryBody, res: NextApiResponse, @@ -33,6 +40,9 @@ export default async ( await useCors(req, res); await useAuth(req, res); + req.yup = schema; + await useValidate(req, res); + const { id: websiteId, type, diff --git a/pages/api/websites/[id]/pageviews.ts b/pages/api/websites/[id]/pageviews.ts index c5532e76e..9985ca892 100644 --- a/pages/api/websites/[id]/pageviews.ts +++ b/pages/api/websites/[id]/pageviews.ts @@ -3,7 +3,7 @@ import { NextApiResponse } from 'next'; import { badRequest, methodNotAllowed, ok, unauthorized } from 'next-basics'; import { NextApiRequestQueryBody, WebsitePageviews } from 'lib/types'; import { canViewWebsite } from 'lib/auth'; -import { useAuth, useCors } from 'lib/middleware'; +import { useAuth, useCors, useValidate } from 'lib/middleware'; import { getPageviewStats, getSessionStats } from 'queries'; import { parseDateRangeQuery } from 'lib/query'; @@ -24,6 +24,13 @@ export interface WebsitePageviewRequestQuery { city?: string; } +import * as yup from 'yup'; +const schema = { + GET: yup.object().shape({ + id: yup.string().uuid().required(), + }), +}; + export default async ( req: NextApiRequestQueryBody, res: NextApiResponse, @@ -31,6 +38,9 @@ export default async ( await useCors(req, res); await useAuth(req, res); + req.yup = schema; + await useValidate(req, res); + const { id: websiteId, timezone, diff --git a/pages/api/websites/[id]/reports.ts b/pages/api/websites/[id]/reports.ts index 60c6f7140..738f6b372 100644 --- a/pages/api/websites/[id]/reports.ts +++ b/pages/api/websites/[id]/reports.ts @@ -1,5 +1,5 @@ import { canViewWebsite } from 'lib/auth'; -import { useAuth, useCors } from 'lib/middleware'; +import { useAuth, useCors, useValidate } from 'lib/middleware'; import { NextApiRequestQueryBody, ReportSearchFilterType, SearchFilter } from 'lib/types'; import { NextApiResponse } from 'next'; import { methodNotAllowed, ok, unauthorized } from 'next-basics'; @@ -9,6 +9,13 @@ export interface ReportsRequestQuery extends SearchFilter, res: NextApiResponse, @@ -16,6 +23,9 @@ export default async ( await useCors(req, res); await useAuth(req, res); + req.yup = schema; + await useValidate(req, res); + const { id: websiteId } = req.query; if (req.method === 'GET') { diff --git a/pages/api/websites/[id]/reset.ts b/pages/api/websites/[id]/reset.ts index 23b5305db..cfd5e7679 100644 --- a/pages/api/websites/[id]/reset.ts +++ b/pages/api/websites/[id]/reset.ts @@ -1,6 +1,6 @@ import { NextApiRequestQueryBody } from 'lib/types'; import { canUpdateWebsite } from 'lib/auth'; -import { useAuth, useCors } from 'lib/middleware'; +import { useAuth, useCors, useValidate } from 'lib/middleware'; import { NextApiResponse } from 'next'; import { methodNotAllowed, ok, unauthorized } from 'next-basics'; import { resetWebsite } from 'queries'; @@ -9,6 +9,13 @@ export interface WebsiteResetRequestQuery { id: string; } +import * as yup from 'yup'; +const schema = { + GET: yup.object().shape({ + id: yup.string().uuid().required(), + }), +}; + export default async ( req: NextApiRequestQueryBody, res: NextApiResponse, @@ -16,6 +23,9 @@ export default async ( await useCors(req, res); await useAuth(req, res); + req.yup = schema; + await useValidate(req, res); + const { id: websiteId } = req.query; if (req.method === 'POST') { diff --git a/pages/api/websites/[id]/stats.ts b/pages/api/websites/[id]/stats.ts index a77c7eaf8..caf549103 100644 --- a/pages/api/websites/[id]/stats.ts +++ b/pages/api/websites/[id]/stats.ts @@ -2,7 +2,7 @@ import { subMinutes, differenceInMinutes } from 'date-fns'; import { NextApiResponse } from 'next'; import { methodNotAllowed, ok, unauthorized } from 'next-basics'; import { canViewWebsite } from 'lib/auth'; -import { useAuth, useCors } from 'lib/middleware'; +import { useAuth, useCors, useValidate } from 'lib/middleware'; import { NextApiRequestQueryBody, WebsiteStats } from 'lib/types'; import { parseDateRangeQuery } from 'lib/query'; import { getWebsiteStats } from 'queries'; @@ -24,6 +24,13 @@ export interface WebsiteStatsRequestQuery { city: string; } +import * as yup from 'yup'; +const schema = { + GET: yup.object().shape({ + id: yup.string().uuid().required(), + }), +}; + export default async ( req: NextApiRequestQueryBody, res: NextApiResponse, @@ -31,6 +38,9 @@ export default async ( await useCors(req, res); await useAuth(req, res); + req.yup = schema; + await useValidate(req, res); + const { id: websiteId, url, diff --git a/pages/api/websites/[id]/values.ts b/pages/api/websites/[id]/values.ts index ad8625bd4..d90a16822 100644 --- a/pages/api/websites/[id]/values.ts +++ b/pages/api/websites/[id]/values.ts @@ -1,6 +1,6 @@ import { NextApiRequestQueryBody } from 'lib/types'; import { canViewWebsite } from 'lib/auth'; -import { useAuth, useCors } from 'lib/middleware'; +import { useAuth, useCors, useValidate } from 'lib/middleware'; import { NextApiResponse } from 'next'; import { badRequest, methodNotAllowed, ok, unauthorized } from 'next-basics'; import { EVENT_COLUMNS, FILTER_COLUMNS, SESSION_COLUMNS } from 'lib/constants'; @@ -10,6 +10,13 @@ export interface WebsiteResetRequestQuery { id: string; } +import * as yup from 'yup'; +const schema = { + GET: yup.object().shape({ + id: yup.string().uuid().required(), + }), +}; + export default async ( req: NextApiRequestQueryBody, res: NextApiResponse, @@ -17,6 +24,9 @@ export default async ( await useCors(req, res); await useAuth(req, res); + req.yup = schema; + await useValidate(req, res); + const { id: websiteId, type } = req.query; if (req.method === 'GET') { diff --git a/pages/api/websites/index.ts b/pages/api/websites/index.ts index f94fa0378..d724f12f4 100644 --- a/pages/api/websites/index.ts +++ b/pages/api/websites/index.ts @@ -1,11 +1,13 @@ import { canCreateWebsite } from 'lib/auth'; import { uuid } from 'lib/crypto'; -import { useAuth, useCors } from 'lib/middleware'; +import { useAuth, useCors, useValidate } from 'lib/middleware'; import { NextApiRequestQueryBody, SearchFilter, WebsiteSearchFilterType } from 'lib/types'; import { NextApiResponse } from 'next'; import { methodNotAllowed, ok, unauthorized } from 'next-basics'; import { createWebsite } from 'queries'; import userWebsites from 'pages/api/users/[id]/websites'; +import * as yup from 'yup'; +import { getFilterValidation } from 'lib/yup'; export interface WebsitesRequestQuery extends SearchFilter {} @@ -15,12 +17,25 @@ export interface WebsitesRequestBody { shareId: string; } +const schema = { + GET: yup.object().shape({ + ...getFilterValidation(/All|Name|Domain/i), + }), + POST: yup.object().shape({ + name: yup.string().max(100).required(), + domain: yup.string().max(500).required(), + shareId: yup.string().max(50), + }), +}; + export default async ( req: NextApiRequestQueryBody, res: NextApiResponse, ) => { await useCors(req, res); await useAuth(req, res); + req.yup = schema; + await useValidate(req, res); const { user: { id: userId }, @@ -30,7 +45,7 @@ export default async ( req.query.id = userId; req.query.pageSize = 100; - return userWebsites(req, res); + return userWebsites(req as any, res); } if (req.method === 'POST') { From ede658771e952ae03a3479d3bb0aed4916cae64c Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Mon, 21 Aug 2023 02:06:09 -0700 Subject: [PATCH 007/113] Moved code into src folder. Added build for component library. --- .eslintrc.json | 17 +- jsconfig.json | 4 +- package.components.json | 10 + package.json | 25 +- rollup.components.config.mjs | 99 +++++ ...ker.config.js => rollup.tracker.config.mjs | 2 +- scripts/check-lang.js | 2 +- {assets => src/assets}/add-user.svg | 0 {assets => src/assets}/bar-chart.svg | 0 {assets => src/assets}/bars.svg | 0 {assets => src/assets}/bolt.svg | 0 {assets => src/assets}/calendar.svg | 0 {assets => src/assets}/clock.svg | 0 {assets => src/assets}/dashboard.svg | 0 {assets => src/assets}/expand.svg | 0 {assets => src/assets}/eye.svg | 0 {assets => src/assets}/funnel.svg | 0 {assets => src/assets}/gear.svg | 0 {assets => src/assets}/globe.svg | 0 {assets => src/assets}/lightbulb.svg | 0 {assets => src/assets}/link.svg | 0 {assets => src/assets}/lock.svg | 0 {assets => src/assets}/logo.svg | 0 {assets => src/assets}/magnet.svg | 0 {assets => src/assets}/moon.svg | 0 {assets => src/assets}/nodes.svg | 0 {assets => src/assets}/overview.svg | 0 {assets => src/assets}/profile.svg | 0 {assets => src/assets}/redo.svg | 0 {assets => src/assets}/reports.svg | 0 {assets => src/assets}/sun.svg | 0 {assets => src/assets}/user.svg | 0 {assets => src/assets}/users.svg | 0 {assets => src/assets}/visitor.svg | 0 {assets => src/assets}/website.svg | 0 .../components}/common/ConfirmDeleteForm.js | 2 +- .../components}/common/Empty.js | 2 +- .../components}/common/Empty.module.css | 0 .../components}/common/EmptyPlaceholder.js | 0 .../components}/common/ErrorBoundary.js | 2 +- .../common/ErrorBoundry.module.css | 0 .../components}/common/ErrorMessage.js | 2 +- .../common/ErrorMessage.module.css | 0 .../components}/common/Favicon.js | 0 .../components}/common/Favicon.module.css | 0 .../components}/common/FilterButtons.js | 0 .../components}/common/FilterLink.js | 4 +- .../components}/common/FilterLink.module.css | 0 .../components}/common/HamburgerButton.js | 4 +- .../common/HamburgerButton.module.css | 0 .../components}/common/HoverTooltip.js | 0 .../common/HoverTooltip.module.css | 0 .../components}/common/LinkButton.js | 4 +- .../components}/common/LinkButton.module.css | 0 .../components}/common/MobileMenu.js | 0 .../components}/common/MobileMenu.module.css | 0 .../components}/common/Pager.js | 2 +- .../components}/common/Pager.module.css | 0 .../components}/common/SettingsTable.js | 2 +- .../common/SettingsTable.module.css | 0 .../components}/common/UpdateNotice.js | 2 +- .../common/UpdateNotice.module.css | 0 .../components}/common/WorldMap.js | 6 +- .../components}/common/WorldMap.module.css | 0 .../components}/declarations.d.ts | 0 {hooks => src/components/hooks}/index.js | 0 {hooks => src/components/hooks}/useApi.ts | 0 .../components/hooks}/useApiFilter.ts | 0 {hooks => src/components/hooks}/useConfig.js | 2 +- .../components/hooks}/useCountryNames.js | 0 .../components/hooks}/useDateRange.js | 0 .../components/hooks}/useDocumentClick.js | 0 .../components/hooks}/useEscapeKey.js | 0 {hooks => src/components/hooks}/useFilters.js | 2 +- .../components/hooks}/useForceUpdate.js | 0 {hooks => src/components/hooks}/useFormat.js | 0 .../components/hooks}/useLanguageNames.js | 0 {hooks => src/components/hooks}/useLocale.js | 2 +- .../components/hooks}/useMessages.js | 0 .../components/hooks}/usePageQuery.js | 0 {hooks => src/components/hooks}/useReport.js | 0 {hooks => src/components/hooks}/useReports.js | 2 +- .../components/hooks}/useRequireLogin.js | 4 +- .../components/hooks}/useShareToken.js | 0 {hooks => src/components/hooks}/useSticky.js | 0 {hooks => src/components/hooks}/useTheme.js | 0 .../components/hooks}/useTimezone.js | 0 {hooks => src/components/hooks}/useUser.js | 0 {hooks => src/components/hooks}/useWebsite.js | 0 .../components/hooks}/useWebsiteReports.js | 2 +- {components => src/components}/icons.ts | 2 +- .../components}/input/DateFilter.js | 4 +- .../components}/input/LanguageButton.js | 2 +- .../input/LanguageButton.module.css | 0 .../components}/input/LogoutButton.js | 4 +- .../components}/input/MonthSelect.js | 2 +- .../components}/input/MonthSelect.module.css | 0 .../components}/input/ProfileButton.js | 8 +- .../input/ProfileButton.module.css | 0 .../components}/input/RefreshButton.js | 4 +- .../components}/input/SettingsButton.js | 2 +- .../input/SettingsButton.module.css | 0 .../components}/input/ThemeButton.js | 2 +- .../components}/input/ThemeButton.module.css | 0 .../components}/input/WebsiteDateFilter.js | 6 +- .../input/WebsiteDateFilter.module.css | 0 .../components}/input/WebsiteSelect.js | 4 +- .../components}/layout/AppLayout.js | 2 +- .../components}/layout/AppLayout.module.css | 0 .../components}/layout/Footer.js | 0 .../components}/layout/Footer.module.css | 0 {components => src/components}/layout/Grid.js | 0 .../components}/layout/Grid.module.css | 0 .../components}/layout/Header.js | 0 .../components}/layout/Header.module.css | 0 .../components}/layout/NavBar.js | 4 +- .../components}/layout/NavBar.module.css | 0 .../components}/layout/NavGroup.js | 0 .../components}/layout/NavGroup.module.css | 0 {components => src/components}/layout/Page.js | 2 +- .../components}/layout/Page.module.css | 0 .../components}/layout/PageHeader.js | 0 .../components}/layout/PageHeader.module.css | 0 .../components}/layout/ReportsLayout.js | 4 +- .../layout/ReportsLayout.module.css | 0 .../components}/layout/SettingsLayout.js | 6 +- .../layout/SettingsLayout.module.css | 0 .../components}/layout/ShareLayout.js | 0 .../components}/layout/SideNav.js | 0 .../components}/layout/SideNav.module.css | 0 {components => src/components}/messages.js | 0 .../components}/metrics/ActiveUsers.js | 4 +- .../metrics/ActiveUsers.module.css | 0 .../components}/metrics/BarChart.js | 4 +- .../components}/metrics/BarChart.module.css | 0 .../components}/metrics/BrowsersTable.js | 4 +- .../components}/metrics/CitiesTable.js | 4 +- .../components}/metrics/CountriesTable.js | 4 +- .../components}/metrics/DataTable.js | 2 +- .../components}/metrics/DataTable.module.css | 0 .../components}/metrics/DatePickerForm.js | 4 +- .../metrics/DatePickerForm.module.css | 0 .../components}/metrics/DevicesTable.js | 4 +- .../components}/metrics/EventsChart.js | 2 +- .../metrics/EventsChart.module.css | 0 .../components}/metrics/EventsTable.js | 2 +- .../components}/metrics/FilterTags.js | 4 +- .../components}/metrics/FilterTags.module.css | 0 .../components}/metrics/LanguagesTable.js | 6 +- .../components}/metrics/Legend.js | 6 +- .../components}/metrics/Legend.module.css | 0 .../components}/metrics/MetricCard.js | 0 .../components}/metrics/MetricCard.module.css | 0 .../components}/metrics/MetricsBar.js | 0 .../components}/metrics/MetricsBar.module.css | 0 .../components}/metrics/MetricsTable.js | 14 +- .../metrics/MetricsTable.module.css | 0 .../components}/metrics/OSTable.js | 2 +- .../components}/metrics/PagesTable.js | 4 +- .../components}/metrics/PageviewsChart.js | 4 +- .../metrics/QueryParametersTable.js | 2 +- .../metrics/QueryParametersTable.module.css | 0 .../components}/metrics/RealtimeChart.js | 2 +- .../components}/metrics/ReferrersTable.js | 2 +- .../components}/metrics/RegionsTable.js | 6 +- .../components}/metrics/ScreenTable.js | 2 +- .../components}/pages/console/TestConsole.js | 2 +- .../pages/console/TestConsole.module.css | 0 .../components}/pages/dashboard/Dashboard.js | 6 +- .../pages/dashboard/DashboardEdit.js | 2 +- .../pages/dashboard/DashboardEdit.module.css | 0 .../dashboard/DashboardSettingsButton.js | 4 +- .../DashboardSettingsButton.module.css | 0 .../pages/event-data/EventDataMetricsBar.js | 4 +- .../event-data/EventDataMetricsBar.module.css | 0 .../pages/event-data/EventDataTable.js | 2 +- .../pages/event-data/EventDataValueTable.js | 2 +- .../components}/pages/login/LoginForm.js | 4 +- .../pages/login/LoginForm.module.css | 0 .../components}/pages/login/LoginLayout.js | 2 +- .../pages/login/LoginLayout.module.css | 0 .../pages/realtime/RealtimeCountries.js | 6 +- .../realtime/RealtimeCountries.module.css | 0 .../pages/realtime/RealtimeHeader.js | 2 +- .../pages/realtime/RealtimeHeader.module.css | 0 .../pages/realtime/RealtimeHome.js | 4 +- .../components}/pages/realtime/RealtimeLog.js | 6 +- .../pages/realtime/RealtimeLog.module.css | 0 .../pages/realtime/RealtimePage.js | 4 +- .../pages/realtime/RealtimePage.module.css | 0 .../pages/realtime/RealtimeUrls.js | 2 +- .../pages/reports/BaseParameters.js | 2 +- .../components}/pages/reports/FieldAddForm.js | 0 .../pages/reports/FieldAddForm.module.css | 0 .../pages/reports/FieldAggregateForm.js | 2 +- .../pages/reports/FieldFilterForm.js | 2 +- .../pages/reports/FieldFilterForm.module.css | 0 .../pages/reports/FieldSelectForm.js | 2 +- .../pages/reports/FieldSelectForm.module.css | 0 .../pages/reports/FilterSelectForm.js | 2 +- .../pages/reports/ParameterList.js | 2 +- .../pages/reports/ParameterList.module.css | 0 .../components}/pages/reports/PopupForm.js | 0 .../pages/reports/PopupForm.module.css | 0 .../components}/pages/reports/Report.js | 2 +- .../components}/pages/reports/ReportBody.js | 0 .../pages/reports/ReportDetails.js | 0 .../components}/pages/reports/ReportHeader.js | 2 +- .../pages/reports/ReportHeader.module.css | 0 .../components}/pages/reports/ReportMenu.js | 0 .../pages/reports/ReportTemplates.js | 2 +- .../pages/reports/ReportTemplates.module.css | 0 .../components}/pages/reports/ReportsPage.js | 2 +- .../components}/pages/reports/ReportsTable.js | 4 +- .../reports/event-data/EventDataParameters.js | 2 +- .../event-data/EventDataParameters.module.css | 0 .../reports/event-data/EventDataReport.js | 0 .../reports/event-data/EventDataTable.js | 2 +- .../pages/reports/funnel/FunnelChart.js | 6 +- .../reports/funnel/FunnelChart.module.css | 0 .../pages/reports/funnel/FunnelParameters.js | 2 +- .../pages/reports/funnel/FunnelReport.js | 0 .../reports/funnel/FunnelReport.module.css | 0 .../pages/reports/funnel/FunnelTable.js | 2 +- .../pages/reports/funnel/UrlAddForm.js | 2 +- .../reports/funnel/UrlAddForm.module.css | 0 .../reports/insights/InsightsParameters.js | 2 +- .../insights/InsightsParameters.module.css | 0 .../pages/reports/insights/InsightsReport.js | 0 .../pages/reports/insights/InsightsTable.js | 2 +- .../pages/reports/reports.module.css | 0 .../reports/retention/RetentionParameters.js | 2 +- .../reports/retention/RetentionReport.js | 0 .../retention/RetentionReport.module.css | 0 .../pages/reports/retention/RetentionTable.js | 2 +- .../retention/RetentionTable.module.css | 0 .../settings/profile/DateRangeSetting.js | 4 +- .../pages/settings/profile/LanguageSetting.js | 4 +- .../settings/profile/PasswordChangeButton.js | 2 +- .../settings/profile/PasswordEditForm.js | 4 +- .../pages/settings/profile/ProfileDetails.js | 6 +- .../pages/settings/profile/ProfileSettings.js | 2 +- .../pages/settings/profile/ThemeSetting.js | 2 +- .../settings/profile/ThemeSetting.module.css | 0 .../pages/settings/profile/TimezoneSetting.js | 4 +- .../pages/settings/teams/TeamAddForm.js | 4 +- .../settings/teams/TeamAddWebsiteForm.js | 4 +- .../pages/settings/teams/TeamDeleteForm.js | 4 +- .../pages/settings/teams/TeamEditForm.js | 4 +- .../pages/settings/teams/TeamJoinForm.js | 4 +- .../pages/settings/teams/TeamLeaveForm.js | 4 +- .../settings/teams/TeamMemberRemoveButton.js | 4 +- .../pages/settings/teams/TeamMembers.js | 6 +- .../pages/settings/teams/TeamMembersTable.js | 4 +- .../pages/settings/teams/TeamSettings.js | 6 +- .../settings/teams/TeamWebsiteRemoveButton.js | 4 +- .../pages/settings/teams/TeamWebsites.js | 6 +- .../pages/settings/teams/TeamWebsitesTable.js | 6 +- .../pages/settings/teams/TeamsList.js | 8 +- .../pages/settings/teams/TeamsTable.js | 6 +- .../pages/settings/teams/WebsiteTags.js | 0 .../settings/teams/WebsiteTags.module.css | 0 .../pages/settings/users/UserAddButton.js | 2 +- .../pages/settings/users/UserAddForm.js | 4 +- .../pages/settings/users/UserDeleteForm.js | 4 +- .../pages/settings/users/UserEditForm.js | 4 +- .../pages/settings/users/UserSettings.js | 6 +- .../pages/settings/users/UserWebsites.js | 4 +- .../pages/settings/users/UsersList.js | 8 +- .../pages/settings/users/UsersTable.js | 8 +- .../pages/settings/websites/ShareUrl.js | 6 +- .../pages/settings/websites/TrackingCode.js | 4 +- .../pages/settings/websites/WebsiteAddForm.js | 4 +- .../pages/settings/websites/WebsiteData.js | 2 +- .../settings/websites/WebsiteDeleteForm.js | 4 +- .../settings/websites/WebsiteEditForm.js | 4 +- .../settings/websites/WebsiteResetForm.js | 4 +- .../settings/websites/WebsiteSettings.js | 6 +- .../pages/settings/websites/WebsitesList.js | 8 +- .../pages/settings/websites/WebsitesTable.js | 6 +- .../websites/WebsitesTable.module.css | 0 .../pages/websites/WebsiteChart.js | 2 +- .../pages/websites/WebsiteChart.module.css | 0 .../pages/websites/WebsiteChartList.js | 2 +- .../pages/websites/WebsiteDetailsPage.js | 4 +- .../pages/websites/WebsiteEventData.js | 2 +- .../websites/WebsiteEventData.module.css | 0 .../pages/websites/WebsiteEventDataPage.js | 0 .../pages/websites/WebsiteHeader.js | 4 +- .../pages/websites/WebsiteHeader.module.css | 0 .../pages/websites/WebsiteList.module.css | 0 .../pages/websites/WebsiteMenuView.js | 6 +- .../pages/websites/WebsiteMenuView.module.css | 0 .../pages/websites/WebsiteMetricsBar.js | 2 +- .../websites/WebsiteMetricsBar.module.css | 0 .../pages/websites/WebsiteReportsPage.js | 2 +- .../pages/websites/WebsiteTableView.js | 0 .../websites/WebsiteTableView.module.css | 0 .../pages/websites/WebsitesPage.js | 6 +- src/index.ts | 61 +++ {lang => src/lang}/am-ET.json | 0 {lang => src/lang}/ar-SA.json | 0 {lang => src/lang}/be-BY.json | 0 {lang => src/lang}/bn-BD.json | 0 {lang => src/lang}/ca-ES.json | 0 {lang => src/lang}/cs-CZ.json | 0 {lang => src/lang}/da-DK.json | 0 {lang => src/lang}/de-CH.json | 0 {lang => src/lang}/de-DE.json | 0 {lang => src/lang}/el-GR.json | 0 {lang => src/lang}/en-GB.json | 0 {lang => src/lang}/en-US.json | 0 {lang => src/lang}/es-ES.json | 0 {lang => src/lang}/es-MX.json | 0 {lang => src/lang}/fa-IR.json | 0 {lang => src/lang}/fi-FI.json | 0 {lang => src/lang}/fo-FO.json | 0 {lang => src/lang}/fr-FR.json | 0 {lang => src/lang}/ga-ES.json | 0 {lang => src/lang}/he-IL.json | 0 {lang => src/lang}/hi-IN.json | 0 {lang => src/lang}/hr-HR.json | 0 {lang => src/lang}/hu-HU.json | 0 {lang => src/lang}/id-ID.json | 0 {lang => src/lang}/it-IT.json | 0 {lang => src/lang}/ja-JP.json | 0 {lang => src/lang}/km-KH.json | 0 {lang => src/lang}/ko-KR.json | 0 {lang => src/lang}/lt-LT.json | 0 {lang => src/lang}/mn-MN.json | 0 {lang => src/lang}/ms-MY.json | 0 {lang => src/lang}/my-MM.json | 0 {lang => src/lang}/nb-NO.json | 0 {lang => src/lang}/nl-NL.json | 0 {lang => src/lang}/pl-PL.json | 0 {lang => src/lang}/pt-BR.json | 0 {lang => src/lang}/pt-PT.json | 0 {lang => src/lang}/ro-RO.json | 0 {lang => src/lang}/ru-RU.json | 0 {lang => src/lang}/si-LK.json | 0 {lang => src/lang}/sk-SK.json | 0 {lang => src/lang}/sl-SI.json | 0 {lang => src/lang}/sv-SE.json | 0 {lang => src/lang}/ta-IN.json | 0 {lang => src/lang}/th-TH.json | 0 {lang => src/lang}/tr-TR.json | 0 {lang => src/lang}/uk-UA.json | 0 {lang => src/lang}/ur-PK.json | 0 {lang => src/lang}/vi-VN.json | 0 {lang => src/lang}/zh-CN.json | 0 {lang => src/lang}/zh-TW.json | 0 {lib => src/lib}/auth.ts | 0 {lib => src/lib}/cache.ts | 0 {lib => src/lib}/charts.js | 0 {lib => src/lib}/clickhouse.ts | 0 {lib => src/lib}/client.ts | 0 {lib => src/lib}/constants.ts | 0 {lib => src/lib}/crypto.js | 0 {lib => src/lib}/data.ts | 0 {lib => src/lib}/date.js | 0 {lib => src/lib}/db.js | 0 {lib => src/lib}/detect.ts | 0 {lib => src/lib}/filters.js | 0 {lib => src/lib}/format.js | 0 {lib => src/lib}/kafka.ts | 0 {lib => src/lib}/lang.js | 0 {lib => src/lib}/load.ts | 0 {lib => src/lib}/middleware.ts | 0 {lib => src/lib}/prisma.ts | 0 {lib => src/lib}/query.ts | 0 {lib => src/lib}/session.ts | 0 {lib => src/lib}/sql.ts | 0 {lib => src/lib}/types.ts | 0 {lib => src/lib}/yup.ts | 0 {pages => src/pages}/404.js | 2 +- {pages => src/pages}/_app.js | 4 +- {pages => src/pages}/api/auth/login.ts | 0 {pages => src/pages}/api/auth/logout.ts | 0 {pages => src/pages}/api/auth/sso.ts | 0 {pages => src/pages}/api/auth/verify.ts | 0 {pages => src/pages}/api/config.ts | 0 {pages => src/pages}/api/event-data/events.ts | 0 {pages => src/pages}/api/event-data/fields.ts | 0 {pages => src/pages}/api/event-data/stats.ts | 0 {pages => src/pages}/api/heartbeat.ts | 0 {pages => src/pages}/api/me/index.ts | 0 {pages => src/pages}/api/me/password.ts | 0 {pages => src/pages}/api/me/teams.ts | 0 {pages => src/pages}/api/me/websites.ts | 0 {pages => src/pages}/api/realtime/[id].ts | 0 {pages => src/pages}/api/reports/[id].ts | 0 {pages => src/pages}/api/reports/funnel.ts | 0 {pages => src/pages}/api/reports/index.ts | 0 {pages => src/pages}/api/reports/insights.ts | 0 {pages => src/pages}/api/reports/retention.ts | 0 {pages => src/pages}/api/scripts/telemetry.js | 0 {pages => src/pages}/api/send.ts | 0 {pages => src/pages}/api/share/[id].ts | 0 {pages => src/pages}/api/teams/[id]/index.ts | 0 .../pages}/api/teams/[id]/users/[userId].ts | 0 .../pages}/api/teams/[id]/users/index.ts | 0 .../api/teams/[id]/websites/[websiteId].ts | 0 .../pages}/api/teams/[id]/websites/index.ts | 0 {pages => src/pages}/api/teams/index.ts | 0 {pages => src/pages}/api/teams/join.ts | 0 {pages => src/pages}/api/users/[id]/index.ts | 0 {pages => src/pages}/api/users/[id]/teams.ts | 0 {pages => src/pages}/api/users/[id]/usage.ts | 0 .../pages}/api/users/[id]/websites.ts | 0 {pages => src/pages}/api/users/index.ts | 0 .../pages}/api/websites/[id]/active.ts | 0 .../pages}/api/websites/[id]/daterange.ts | 0 .../pages}/api/websites/[id]/events.ts | 0 .../pages}/api/websites/[id]/index.ts | 0 .../pages}/api/websites/[id]/metrics.ts | 0 .../pages}/api/websites/[id]/pageviews.ts | 0 .../pages}/api/websites/[id]/reports.ts | 0 .../pages}/api/websites/[id]/reset.ts | 0 .../pages}/api/websites/[id]/stats.ts | 0 .../pages}/api/websites/[id]/values.ts | 0 {pages => src/pages}/api/websites/index.ts | 0 {pages => src/pages}/console/[[...id]].js | 0 {pages => src/pages}/dashboard/index.js | 2 +- {pages => src/pages}/index.js | 0 {pages => src/pages}/login.js | 0 {pages => src/pages}/logout.js | 2 +- {pages => src/pages}/reports/[id].js | 2 +- {pages => src/pages}/reports/create.js | 2 +- {pages => src/pages}/reports/funnel.js | 2 +- {pages => src/pages}/reports/index.js | 2 +- {pages => src/pages}/reports/insights.js | 2 +- {pages => src/pages}/reports/retention.js | 2 +- .../pages}/settings/profile/index.js | 2 +- {pages => src/pages}/settings/teams/[id].js | 2 +- {pages => src/pages}/settings/teams/index.js | 2 +- {pages => src/pages}/settings/users/[id].js | 2 +- {pages => src/pages}/settings/users/index.js | 2 +- .../pages}/settings/websites/[id].js | 2 +- .../pages}/settings/websites/index.js | 2 +- {pages => src/pages}/share/[...id].js | 2 +- {pages => src/pages}/sso.js | 0 .../pages}/websites/[id]/event-data.js | 2 +- {pages => src/pages}/websites/[id]/index.js | 2 +- .../pages}/websites/[id]/realtime.js | 0 {pages => src/pages}/websites/[id]/reports.js | 0 {pages => src/pages}/websites/index.js | 2 +- {queries => src/queries}/admin/report.ts | 0 {queries => src/queries}/admin/team.ts | 0 {queries => src/queries}/admin/teamUser.ts | 0 {queries => src/queries}/admin/teamWebsite.ts | 0 {queries => src/queries}/admin/user.ts | 0 {queries => src/queries}/admin/website.ts | 0 .../analytics/eventData/getEventDataEvents.ts | 0 .../analytics/eventData/getEventDataFields.ts | 0 .../analytics/eventData/getEventDataStats.ts | 0 .../analytics/eventData/getEventDataUsage.ts | 0 .../analytics/eventData/saveEventData.ts | 0 .../analytics/events/getEventMetrics.ts | 0 .../analytics/events/getEventUsage.ts | 0 .../queries}/analytics/events/getEvents.ts | 0 .../queries}/analytics/events/saveEvent.ts | 0 .../queries}/analytics/getActiveVisitors.ts | 0 .../queries}/analytics/getRealtimeData.ts | 0 .../queries}/analytics/getValues.ts | 0 .../queries}/analytics/getWebsiteDateRange.ts | 0 .../queries}/analytics/getWebsiteStats.ts | 0 .../analytics/pageviews/getPageviewMetrics.ts | 0 .../analytics/pageviews/getPageviewStats.ts | 0 .../queries}/analytics/reports/getFunnel.ts | 0 .../queries}/analytics/reports/getInsights.ts | 0 .../analytics/reports/getRetention.ts | 0 .../analytics/sessions/createSession.ts | 0 .../queries}/analytics/sessions/getSession.ts | 0 .../analytics/sessions/getSessionMetrics.ts | 0 .../analytics/sessions/getSessionStats.ts | 0 .../analytics/sessions/getSessions.ts | 0 .../analytics/sessions/saveSessionData.ts | 0 {queries => src/queries}/index.js | 0 {store => src/store}/app.js | 0 {store => src/store}/dashboard.js | 0 {store => src/store}/queries.js | 0 {store => src/store}/version.js | 0 {store => src/store}/websites.ts | 0 {styles => src/styles}/index.css | 0 {styles => src/styles}/locale.css | 0 {styles => src/styles}/variables.css | 0 {tracker => src/tracker}/index.d.ts | 0 {tracker => src/tracker}/index.js | 0 tsconfig.json | 6 +- yarn.lock | 409 ++++++++++++------ 490 files changed, 749 insertions(+), 442 deletions(-) create mode 100644 package.components.json create mode 100644 rollup.components.config.mjs rename rollup.tracker.config.js => rollup.tracker.config.mjs (93%) rename {assets => src/assets}/add-user.svg (100%) rename {assets => src/assets}/bar-chart.svg (100%) rename {assets => src/assets}/bars.svg (100%) rename {assets => src/assets}/bolt.svg (100%) rename {assets => src/assets}/calendar.svg (100%) rename {assets => src/assets}/clock.svg (100%) rename {assets => src/assets}/dashboard.svg (100%) rename {assets => src/assets}/expand.svg (100%) rename {assets => src/assets}/eye.svg (100%) rename {assets => src/assets}/funnel.svg (100%) rename {assets => src/assets}/gear.svg (100%) rename {assets => src/assets}/globe.svg (100%) rename {assets => src/assets}/lightbulb.svg (100%) rename {assets => src/assets}/link.svg (100%) rename {assets => src/assets}/lock.svg (100%) rename {assets => src/assets}/logo.svg (100%) rename {assets => src/assets}/magnet.svg (100%) rename {assets => src/assets}/moon.svg (100%) rename {assets => src/assets}/nodes.svg (100%) rename {assets => src/assets}/overview.svg (100%) rename {assets => src/assets}/profile.svg (100%) rename {assets => src/assets}/redo.svg (100%) rename {assets => src/assets}/reports.svg (100%) rename {assets => src/assets}/sun.svg (100%) rename {assets => src/assets}/user.svg (100%) rename {assets => src/assets}/users.svg (100%) rename {assets => src/assets}/visitor.svg (100%) rename {assets => src/assets}/website.svg (100%) rename {components => src/components}/common/ConfirmDeleteForm.js (93%) rename {components => src/components}/common/Empty.js (86%) rename {components => src/components}/common/Empty.module.css (100%) rename {components => src/components}/common/EmptyPlaceholder.js (100%) rename {components => src/components}/common/ErrorBoundary.js (93%) rename {components => src/components}/common/ErrorBoundry.module.css (100%) rename {components => src/components}/common/ErrorMessage.js (88%) rename {components => src/components}/common/ErrorMessage.module.css (100%) rename {components => src/components}/common/Favicon.js (100%) rename {components => src/components}/common/Favicon.module.css (100%) rename {components => src/components}/common/FilterButtons.js (100%) rename {components => src/components}/common/FilterLink.js (91%) rename {components => src/components}/common/FilterLink.module.css (100%) rename {components => src/components}/common/HamburgerButton.js (93%) rename {components => src/components}/common/HamburgerButton.module.css (100%) rename {components => src/components}/common/HoverTooltip.js (100%) rename {components => src/components}/common/HoverTooltip.module.css (100%) rename {components => src/components}/common/LinkButton.js (77%) rename {components => src/components}/common/LinkButton.module.css (100%) rename {components => src/components}/common/MobileMenu.js (100%) rename {components => src/components}/common/MobileMenu.module.css (100%) rename {components => src/components}/common/Pager.js (95%) rename {components => src/components}/common/Pager.module.css (100%) rename {components => src/components}/common/SettingsTable.js (98%) rename {components => src/components}/common/SettingsTable.module.css (100%) rename {components => src/components}/common/UpdateNotice.js (96%) rename {components => src/components}/common/UpdateNotice.module.css (100%) rename {components => src/components}/common/WorldMap.js (94%) rename {components => src/components}/common/WorldMap.module.css (100%) rename {components => src/components}/declarations.d.ts (100%) rename {hooks => src/components/hooks}/index.js (100%) rename {hooks => src/components/hooks}/useApi.ts (100%) rename {hooks => src/components/hooks}/useApiFilter.ts (100%) rename {hooks => src/components/hooks}/useConfig.js (91%) rename {hooks => src/components/hooks}/useCountryNames.js (100%) rename {hooks => src/components/hooks}/useDateRange.js (100%) rename {hooks => src/components/hooks}/useDocumentClick.js (100%) rename {hooks => src/components/hooks}/useEscapeKey.js (100%) rename {hooks => src/components/hooks}/useFilters.js (97%) rename {hooks => src/components/hooks}/useForceUpdate.js (100%) rename {hooks => src/components/hooks}/useFormat.js (100%) rename {hooks => src/components/hooks}/useLanguageNames.js (100%) rename {hooks => src/components/hooks}/useLocale.js (96%) rename {hooks => src/components/hooks}/useMessages.js (100%) rename {hooks => src/components/hooks}/usePageQuery.js (100%) rename {hooks => src/components/hooks}/useReport.js (100%) rename {hooks => src/components/hooks}/useReports.js (94%) rename {hooks => src/components/hooks}/useRequireLogin.js (84%) rename {hooks => src/components/hooks}/useShareToken.js (100%) rename {hooks => src/components/hooks}/useSticky.js (100%) rename {hooks => src/components/hooks}/useTheme.js (100%) rename {hooks => src/components/hooks}/useTimezone.js (100%) rename {hooks => src/components/hooks}/useUser.js (100%) rename {hooks => src/components/hooks}/useWebsite.js (100%) rename {hooks => src/components/hooks}/useWebsiteReports.js (94%) rename {components => src/components}/icons.ts (98%) rename {components => src/components}/input/DateFilter.js (96%) rename {components => src/components}/input/LanguageButton.js (96%) rename {components => src/components}/input/LanguageButton.module.css (100%) rename {components => src/components}/input/LogoutButton.js (84%) rename {components => src/components}/input/MonthSelect.js (97%) rename {components => src/components}/input/MonthSelect.module.css (100%) rename {components => src/components}/input/ProfileButton.js (88%) rename {components => src/components}/input/ProfileButton.module.css (100%) rename {components => src/components}/input/RefreshButton.js (86%) rename {components => src/components}/input/SettingsButton.js (94%) rename {components => src/components}/input/SettingsButton.module.css (100%) rename {components => src/components}/input/ThemeButton.js (95%) rename {components => src/components}/input/ThemeButton.module.css (100%) rename {components => src/components}/input/WebsiteDateFilter.js (76%) rename {components => src/components}/input/WebsiteDateFilter.module.css (100%) rename {components => src/components}/input/WebsiteSelect.js (87%) rename {components => src/components}/layout/AppLayout.js (92%) rename {components => src/components}/layout/AppLayout.module.css (100%) rename {components => src/components}/layout/Footer.js (100%) rename {components => src/components}/layout/Footer.module.css (100%) rename {components => src/components}/layout/Grid.js (100%) rename {components => src/components}/layout/Grid.module.css (100%) rename {components => src/components}/layout/Header.js (100%) rename {components => src/components}/layout/Header.module.css (100%) rename {components => src/components}/layout/NavBar.js (94%) rename {components => src/components}/layout/NavBar.module.css (100%) rename {components => src/components}/layout/NavGroup.js (100%) rename {components => src/components}/layout/NavGroup.module.css (100%) rename {components => src/components}/layout/Page.js (90%) rename {components => src/components}/layout/Page.module.css (100%) rename {components => src/components}/layout/PageHeader.js (100%) rename {components => src/components}/layout/PageHeader.module.css (100%) rename {components => src/components}/layout/ReportsLayout.js (83%) rename {components => src/components}/layout/ReportsLayout.module.css (100%) rename {components => src/components}/layout/SettingsLayout.js (88%) rename {components => src/components}/layout/SettingsLayout.module.css (100%) rename {components => src/components}/layout/ShareLayout.js (100%) rename {components => src/components}/layout/SideNav.js (100%) rename {components => src/components}/layout/SideNav.module.css (100%) rename {components => src/components}/messages.js (100%) rename {components => src/components}/metrics/ActiveUsers.js (89%) rename {components => src/components}/metrics/ActiveUsers.module.css (100%) rename {components => src/components}/metrics/BarChart.js (97%) rename {components => src/components}/metrics/BarChart.module.css (100%) rename {components => src/components}/metrics/BrowsersTable.js (89%) rename {components => src/components}/metrics/CitiesTable.js (86%) rename {components => src/components}/metrics/CountriesTable.js (88%) rename {components => src/components}/metrics/DataTable.js (98%) rename {components => src/components}/metrics/DataTable.module.css (100%) rename {components => src/components}/metrics/DatePickerForm.js (96%) rename {components => src/components}/metrics/DatePickerForm.module.css (100%) rename {components => src/components}/metrics/DevicesTable.js (90%) rename {components => src/components}/metrics/EventsChart.js (98%) rename {components => src/components}/metrics/EventsChart.module.css (100%) rename {components => src/components}/metrics/EventsTable.js (89%) rename {components => src/components}/metrics/FilterTags.js (92%) rename {components => src/components}/metrics/FilterTags.module.css (100%) rename {components => src/components}/metrics/LanguagesTable.js (81%) rename {components => src/components}/metrics/Legend.js (89%) rename {components => src/components}/metrics/Legend.module.css (100%) rename {components => src/components}/metrics/MetricCard.js (100%) rename {components => src/components}/metrics/MetricCard.module.css (100%) rename {components => src/components}/metrics/MetricsBar.js (100%) rename {components => src/components}/metrics/MetricsBar.module.css (100%) rename {components => src/components}/metrics/MetricsTable.js (90%) rename {components => src/components}/metrics/MetricsTable.module.css (100%) rename {components => src/components}/metrics/OSTable.js (93%) rename {components => src/components}/metrics/PagesTable.js (91%) rename {components => src/components}/metrics/PageviewsChart.js (90%) rename {components => src/components}/metrics/QueryParametersTable.js (96%) rename {components => src/components}/metrics/QueryParametersTable.module.css (100%) rename {components => src/components}/metrics/RealtimeChart.js (98%) rename {components => src/components}/metrics/ReferrersTable.js (93%) rename {components => src/components}/metrics/RegionsTable.js (87%) rename {components => src/components}/metrics/ScreenTable.js (87%) rename {components => src/components}/pages/console/TestConsole.js (99%) rename {components => src/components}/pages/console/TestConsole.module.css (100%) rename {components => src/components}/pages/dashboard/Dashboard.js (93%) rename {components => src/components}/pages/dashboard/DashboardEdit.js (98%) rename {components => src/components}/pages/dashboard/DashboardEdit.module.css (100%) rename {components => src/components}/pages/dashboard/DashboardSettingsButton.js (86%) rename {components => src/components}/pages/dashboard/DashboardSettingsButton.module.css (100%) rename {components => src/components}/pages/event-data/EventDataMetricsBar.js (94%) rename {components => src/components}/pages/event-data/EventDataMetricsBar.module.css (100%) rename {components => src/components}/pages/event-data/EventDataTable.js (94%) rename {components => src/components}/pages/event-data/EventDataValueTable.js (96%) rename {components => src/components}/pages/login/LoginForm.js (94%) rename {components => src/components}/pages/login/LoginForm.module.css (100%) rename {components => src/components}/pages/login/LoginLayout.js (86%) rename {components => src/components}/pages/login/LoginLayout.module.css (100%) rename {components => src/components}/pages/realtime/RealtimeCountries.js (84%) rename {components => src/components}/pages/realtime/RealtimeCountries.module.css (100%) rename {components => src/components}/pages/realtime/RealtimeHeader.js (95%) rename {components => src/components}/pages/realtime/RealtimeHeader.module.css (100%) rename {components => src/components}/pages/realtime/RealtimeHome.js (90%) rename {components => src/components}/pages/realtime/RealtimeLog.js (96%) rename {components => src/components}/pages/realtime/RealtimeLog.module.css (100%) rename {components => src/components}/pages/realtime/RealtimePage.js (97%) rename {components => src/components}/pages/realtime/RealtimePage.module.css (100%) rename {components => src/components}/pages/realtime/RealtimeUrls.js (97%) rename {components => src/components}/pages/reports/BaseParameters.js (97%) rename {components => src/components}/pages/reports/FieldAddForm.js (100%) rename {components => src/components}/pages/reports/FieldAddForm.module.css (100%) rename {components => src/components}/pages/reports/FieldAggregateForm.js (96%) rename {components => src/components}/pages/reports/FieldFilterForm.js (96%) rename {components => src/components}/pages/reports/FieldFilterForm.module.css (100%) rename {components => src/components}/pages/reports/FieldSelectForm.js (94%) rename {components => src/components}/pages/reports/FieldSelectForm.module.css (100%) rename {components => src/components}/pages/reports/FilterSelectForm.js (96%) rename {components => src/components}/pages/reports/ParameterList.js (95%) rename {components => src/components}/pages/reports/ParameterList.module.css (100%) rename {components => src/components}/pages/reports/PopupForm.js (100%) rename {components => src/components}/pages/reports/PopupForm.module.css (100%) rename {components => src/components}/pages/reports/Report.js (92%) rename {components => src/components}/pages/reports/ReportBody.js (100%) rename {components => src/components}/pages/reports/ReportDetails.js (100%) rename {components => src/components}/pages/reports/ReportHeader.js (97%) rename {components => src/components}/pages/reports/ReportHeader.module.css (100%) rename {components => src/components}/pages/reports/ReportMenu.js (100%) rename {components => src/components}/pages/reports/ReportTemplates.js (97%) rename {components => src/components}/pages/reports/ReportTemplates.module.css (100%) rename {components => src/components}/pages/reports/ReportsPage.js (96%) rename {components => src/components}/pages/reports/ReportsTable.js (95%) rename {components => src/components}/pages/reports/event-data/EventDataParameters.js (98%) rename {components => src/components}/pages/reports/event-data/EventDataParameters.module.css (100%) rename {components => src/components}/pages/reports/event-data/EventDataReport.js (100%) rename {components => src/components}/pages/reports/event-data/EventDataTable.js (92%) rename {components => src/components}/pages/reports/funnel/FunnelChart.js (92%) rename {components => src/components}/pages/reports/funnel/FunnelChart.module.css (100%) rename {components => src/components}/pages/reports/funnel/FunnelParameters.js (98%) rename {components => src/components}/pages/reports/funnel/FunnelReport.js (100%) rename {components => src/components}/pages/reports/funnel/FunnelReport.module.css (100%) rename {components => src/components}/pages/reports/funnel/FunnelTable.js (90%) rename {components => src/components}/pages/reports/funnel/UrlAddForm.js (95%) rename {components => src/components}/pages/reports/funnel/UrlAddForm.module.css (100%) rename {components => src/components}/pages/reports/insights/InsightsParameters.js (98%) rename {components => src/components}/pages/reports/insights/InsightsParameters.module.css (100%) rename {components => src/components}/pages/reports/insights/InsightsReport.js (100%) rename {components => src/components}/pages/reports/insights/InsightsTable.js (95%) rename {components => src/components}/pages/reports/reports.module.css (100%) rename {components => src/components}/pages/reports/retention/RetentionParameters.js (96%) rename {components => src/components}/pages/reports/retention/RetentionReport.js (100%) rename {components => src/components}/pages/reports/retention/RetentionReport.module.css (100%) rename {components => src/components}/pages/reports/retention/RetentionTable.js (97%) rename {components => src/components}/pages/reports/retention/RetentionTable.module.css (100%) rename {components => src/components}/pages/settings/profile/DateRangeSetting.js (87%) rename {components => src/components}/pages/settings/profile/LanguageSetting.js (89%) rename {components => src/components}/pages/settings/profile/PasswordChangeButton.js (94%) rename {components => src/components}/pages/settings/profile/PasswordEditForm.js (95%) rename {components => src/components}/pages/settings/profile/ProfileDetails.js (91%) rename {components => src/components}/pages/settings/profile/ProfileSettings.js (87%) rename {components => src/components}/pages/settings/profile/ThemeSetting.js (93%) rename {components => src/components}/pages/settings/profile/ThemeSetting.module.css (100%) rename {components => src/components}/pages/settings/profile/TimezoneSetting.js (87%) rename {components => src/components}/pages/settings/teams/TeamAddForm.js (92%) rename {components => src/components}/pages/settings/teams/TeamAddWebsiteForm.js (95%) rename {components => src/components}/pages/settings/teams/TeamDeleteForm.js (90%) rename {components => src/components}/pages/settings/teams/TeamEditForm.js (95%) rename {components => src/components}/pages/settings/teams/TeamJoinForm.js (91%) rename {components => src/components}/pages/settings/teams/TeamLeaveForm.js (90%) rename {components => src/components}/pages/settings/teams/TeamMemberRemoveButton.js (88%) rename {components => src/components}/pages/settings/teams/TeamMembers.js (88%) rename {components => src/components}/pages/settings/teams/TeamMembersTable.js (93%) rename {components => src/components}/pages/settings/teams/TeamSettings.js (93%) rename {components => src/components}/pages/settings/teams/TeamWebsiteRemoveButton.js (87%) rename {components => src/components}/pages/settings/teams/TeamWebsites.js (92%) rename {components => src/components}/pages/settings/teams/TeamWebsitesTable.js (92%) rename {components => src/components}/pages/settings/teams/TeamsList.js (94%) rename {components => src/components}/pages/settings/teams/TeamsTable.js (95%) rename {components => src/components}/pages/settings/teams/WebsiteTags.js (100%) rename {components => src/components}/pages/settings/teams/WebsiteTags.module.css (100%) rename {components => src/components}/pages/settings/users/UserAddButton.js (92%) rename {components => src/components}/pages/settings/users/UserAddForm.js (95%) rename {components => src/components}/pages/settings/users/UserDeleteForm.js (91%) rename {components => src/components}/pages/settings/users/UserEditForm.js (95%) rename {components => src/components}/pages/settings/users/UserSettings.js (91%) rename {components => src/components}/pages/settings/users/UserWebsites.js (90%) rename {components => src/components}/pages/settings/users/UsersList.js (90%) rename {components => src/components}/pages/settings/users/UsersTable.js (93%) rename {components => src/components}/pages/settings/websites/ShareUrl.js (94%) rename {components => src/components}/pages/settings/websites/TrackingCode.js (85%) rename {components => src/components}/pages/settings/websites/WebsiteAddForm.js (93%) rename {components => src/components}/pages/settings/websites/WebsiteData.js (96%) rename {components => src/components}/pages/settings/websites/WebsiteDeleteForm.js (92%) rename {components => src/components}/pages/settings/websites/WebsiteEditForm.js (94%) rename {components => src/components}/pages/settings/websites/WebsiteResetForm.js (92%) rename {components => src/components}/pages/settings/websites/WebsiteSettings.js (95%) rename {components => src/components}/pages/settings/websites/WebsitesList.js (91%) rename {components => src/components}/pages/settings/websites/WebsitesTable.js (94%) rename {components => src/components}/pages/settings/websites/WebsitesTable.module.css (100%) rename {components => src/components}/pages/websites/WebsiteChart.js (98%) rename {components => src/components}/pages/websites/WebsiteChart.module.css (100%) rename {components => src/components}/pages/websites/WebsiteChartList.js (96%) rename {components => src/components}/pages/websites/WebsiteDetailsPage.js (93%) rename {components => src/components}/pages/websites/WebsiteEventData.js (94%) rename {components => src/components}/pages/websites/WebsiteEventData.module.css (100%) rename {components => src/components}/pages/websites/WebsiteEventDataPage.js (100%) rename {components => src/components}/pages/websites/WebsiteHeader.js (94%) rename {components => src/components}/pages/websites/WebsiteHeader.module.css (100%) rename {components => src/components}/pages/websites/WebsiteList.module.css (100%) rename {components => src/components}/pages/websites/WebsiteMenuView.js (96%) rename {components => src/components}/pages/websites/WebsiteMenuView.module.css (100%) rename {components => src/components}/pages/websites/WebsiteMetricsBar.js (99%) rename {components => src/components}/pages/websites/WebsiteMetricsBar.module.css (100%) rename {components => src/components}/pages/websites/WebsiteReportsPage.js (95%) rename {components => src/components}/pages/websites/WebsiteTableView.js (100%) rename {components => src/components}/pages/websites/WebsiteTableView.module.css (100%) rename {components => src/components}/pages/websites/WebsitesPage.js (93%) create mode 100644 src/index.ts rename {lang => src/lang}/am-ET.json (100%) rename {lang => src/lang}/ar-SA.json (100%) rename {lang => src/lang}/be-BY.json (100%) rename {lang => src/lang}/bn-BD.json (100%) rename {lang => src/lang}/ca-ES.json (100%) rename {lang => src/lang}/cs-CZ.json (100%) rename {lang => src/lang}/da-DK.json (100%) rename {lang => src/lang}/de-CH.json (100%) rename {lang => src/lang}/de-DE.json (100%) rename {lang => src/lang}/el-GR.json (100%) rename {lang => src/lang}/en-GB.json (100%) rename {lang => src/lang}/en-US.json (100%) rename {lang => src/lang}/es-ES.json (100%) rename {lang => src/lang}/es-MX.json (100%) rename {lang => src/lang}/fa-IR.json (100%) rename {lang => src/lang}/fi-FI.json (100%) rename {lang => src/lang}/fo-FO.json (100%) rename {lang => src/lang}/fr-FR.json (100%) rename {lang => src/lang}/ga-ES.json (100%) rename {lang => src/lang}/he-IL.json (100%) rename {lang => src/lang}/hi-IN.json (100%) rename {lang => src/lang}/hr-HR.json (100%) rename {lang => src/lang}/hu-HU.json (100%) rename {lang => src/lang}/id-ID.json (100%) rename {lang => src/lang}/it-IT.json (100%) rename {lang => src/lang}/ja-JP.json (100%) rename {lang => src/lang}/km-KH.json (100%) rename {lang => src/lang}/ko-KR.json (100%) rename {lang => src/lang}/lt-LT.json (100%) rename {lang => src/lang}/mn-MN.json (100%) rename {lang => src/lang}/ms-MY.json (100%) rename {lang => src/lang}/my-MM.json (100%) rename {lang => src/lang}/nb-NO.json (100%) rename {lang => src/lang}/nl-NL.json (100%) rename {lang => src/lang}/pl-PL.json (100%) rename {lang => src/lang}/pt-BR.json (100%) rename {lang => src/lang}/pt-PT.json (100%) rename {lang => src/lang}/ro-RO.json (100%) rename {lang => src/lang}/ru-RU.json (100%) rename {lang => src/lang}/si-LK.json (100%) rename {lang => src/lang}/sk-SK.json (100%) rename {lang => src/lang}/sl-SI.json (100%) rename {lang => src/lang}/sv-SE.json (100%) rename {lang => src/lang}/ta-IN.json (100%) rename {lang => src/lang}/th-TH.json (100%) rename {lang => src/lang}/tr-TR.json (100%) rename {lang => src/lang}/uk-UA.json (100%) rename {lang => src/lang}/ur-PK.json (100%) rename {lang => src/lang}/vi-VN.json (100%) rename {lang => src/lang}/zh-CN.json (100%) rename {lang => src/lang}/zh-TW.json (100%) rename {lib => src/lib}/auth.ts (100%) rename {lib => src/lib}/cache.ts (100%) rename {lib => src/lib}/charts.js (100%) rename {lib => src/lib}/clickhouse.ts (100%) rename {lib => src/lib}/client.ts (100%) rename {lib => src/lib}/constants.ts (100%) rename {lib => src/lib}/crypto.js (100%) rename {lib => src/lib}/data.ts (100%) rename {lib => src/lib}/date.js (100%) rename {lib => src/lib}/db.js (100%) rename {lib => src/lib}/detect.ts (100%) rename {lib => src/lib}/filters.js (100%) rename {lib => src/lib}/format.js (100%) rename {lib => src/lib}/kafka.ts (100%) rename {lib => src/lib}/lang.js (100%) rename {lib => src/lib}/load.ts (100%) rename {lib => src/lib}/middleware.ts (100%) rename {lib => src/lib}/prisma.ts (100%) rename {lib => src/lib}/query.ts (100%) rename {lib => src/lib}/session.ts (100%) rename {lib => src/lib}/sql.ts (100%) rename {lib => src/lib}/types.ts (100%) rename {lib => src/lib}/yup.ts (100%) rename {pages => src/pages}/404.js (90%) rename {pages => src/pages}/_app.js (96%) rename {pages => src/pages}/api/auth/login.ts (100%) rename {pages => src/pages}/api/auth/logout.ts (100%) rename {pages => src/pages}/api/auth/sso.ts (100%) rename {pages => src/pages}/api/auth/verify.ts (100%) rename {pages => src/pages}/api/config.ts (100%) rename {pages => src/pages}/api/event-data/events.ts (100%) rename {pages => src/pages}/api/event-data/fields.ts (100%) rename {pages => src/pages}/api/event-data/stats.ts (100%) rename {pages => src/pages}/api/heartbeat.ts (100%) rename {pages => src/pages}/api/me/index.ts (100%) rename {pages => src/pages}/api/me/password.ts (100%) rename {pages => src/pages}/api/me/teams.ts (100%) rename {pages => src/pages}/api/me/websites.ts (100%) rename {pages => src/pages}/api/realtime/[id].ts (100%) rename {pages => src/pages}/api/reports/[id].ts (100%) rename {pages => src/pages}/api/reports/funnel.ts (100%) rename {pages => src/pages}/api/reports/index.ts (100%) rename {pages => src/pages}/api/reports/insights.ts (100%) rename {pages => src/pages}/api/reports/retention.ts (100%) rename {pages => src/pages}/api/scripts/telemetry.js (100%) rename {pages => src/pages}/api/send.ts (100%) rename {pages => src/pages}/api/share/[id].ts (100%) rename {pages => src/pages}/api/teams/[id]/index.ts (100%) rename {pages => src/pages}/api/teams/[id]/users/[userId].ts (100%) rename {pages => src/pages}/api/teams/[id]/users/index.ts (100%) rename {pages => src/pages}/api/teams/[id]/websites/[websiteId].ts (100%) rename {pages => src/pages}/api/teams/[id]/websites/index.ts (100%) rename {pages => src/pages}/api/teams/index.ts (100%) rename {pages => src/pages}/api/teams/join.ts (100%) rename {pages => src/pages}/api/users/[id]/index.ts (100%) rename {pages => src/pages}/api/users/[id]/teams.ts (100%) rename {pages => src/pages}/api/users/[id]/usage.ts (100%) rename {pages => src/pages}/api/users/[id]/websites.ts (100%) rename {pages => src/pages}/api/users/index.ts (100%) rename {pages => src/pages}/api/websites/[id]/active.ts (100%) rename {pages => src/pages}/api/websites/[id]/daterange.ts (100%) rename {pages => src/pages}/api/websites/[id]/events.ts (100%) rename {pages => src/pages}/api/websites/[id]/index.ts (100%) rename {pages => src/pages}/api/websites/[id]/metrics.ts (100%) rename {pages => src/pages}/api/websites/[id]/pageviews.ts (100%) rename {pages => src/pages}/api/websites/[id]/reports.ts (100%) rename {pages => src/pages}/api/websites/[id]/reset.ts (100%) rename {pages => src/pages}/api/websites/[id]/stats.ts (100%) rename {pages => src/pages}/api/websites/[id]/values.ts (100%) rename {pages => src/pages}/api/websites/index.ts (100%) rename {pages => src/pages}/console/[[...id]].js (100%) rename {pages => src/pages}/dashboard/index.js (85%) rename {pages => src/pages}/index.js (100%) rename {pages => src/pages}/login.js (100%) rename {pages => src/pages}/logout.js (93%) rename {pages => src/pages}/reports/[id].js (92%) rename {pages => src/pages}/reports/create.js (87%) rename {pages => src/pages}/reports/funnel.js (86%) rename {pages => src/pages}/reports/index.js (86%) rename {pages => src/pages}/reports/insights.js (88%) rename {pages => src/pages}/reports/retention.js (86%) rename {pages => src/pages}/settings/profile/index.js (89%) rename {pages => src/pages}/settings/teams/[id].js (93%) rename {pages => src/pages}/settings/teams/index.js (91%) rename {pages => src/pages}/settings/users/[id].js (93%) rename {pages => src/pages}/settings/users/index.js (91%) rename {pages => src/pages}/settings/websites/[id].js (93%) rename {pages => src/pages}/settings/websites/index.js (92%) rename {pages => src/pages}/share/[...id].js (89%) rename {pages => src/pages}/sso.js (100%) rename {pages => src/pages}/websites/[id]/event-data.js (89%) rename {pages => src/pages}/websites/[id]/index.js (89%) rename {pages => src/pages}/websites/[id]/realtime.js (100%) rename {pages => src/pages}/websites/[id]/reports.js (100%) rename {pages => src/pages}/websites/index.js (84%) rename {queries => src/queries}/admin/report.ts (100%) rename {queries => src/queries}/admin/team.ts (100%) rename {queries => src/queries}/admin/teamUser.ts (100%) rename {queries => src/queries}/admin/teamWebsite.ts (100%) rename {queries => src/queries}/admin/user.ts (100%) rename {queries => src/queries}/admin/website.ts (100%) rename {queries => src/queries}/analytics/eventData/getEventDataEvents.ts (100%) rename {queries => src/queries}/analytics/eventData/getEventDataFields.ts (100%) rename {queries => src/queries}/analytics/eventData/getEventDataStats.ts (100%) rename {queries => src/queries}/analytics/eventData/getEventDataUsage.ts (100%) rename {queries => src/queries}/analytics/eventData/saveEventData.ts (100%) rename {queries => src/queries}/analytics/events/getEventMetrics.ts (100%) rename {queries => src/queries}/analytics/events/getEventUsage.ts (100%) rename {queries => src/queries}/analytics/events/getEvents.ts (100%) rename {queries => src/queries}/analytics/events/saveEvent.ts (100%) rename {queries => src/queries}/analytics/getActiveVisitors.ts (100%) rename {queries => src/queries}/analytics/getRealtimeData.ts (100%) rename {queries => src/queries}/analytics/getValues.ts (100%) rename {queries => src/queries}/analytics/getWebsiteDateRange.ts (100%) rename {queries => src/queries}/analytics/getWebsiteStats.ts (100%) rename {queries => src/queries}/analytics/pageviews/getPageviewMetrics.ts (100%) rename {queries => src/queries}/analytics/pageviews/getPageviewStats.ts (100%) rename {queries => src/queries}/analytics/reports/getFunnel.ts (100%) rename {queries => src/queries}/analytics/reports/getInsights.ts (100%) rename {queries => src/queries}/analytics/reports/getRetention.ts (100%) rename {queries => src/queries}/analytics/sessions/createSession.ts (100%) rename {queries => src/queries}/analytics/sessions/getSession.ts (100%) rename {queries => src/queries}/analytics/sessions/getSessionMetrics.ts (100%) rename {queries => src/queries}/analytics/sessions/getSessionStats.ts (100%) rename {queries => src/queries}/analytics/sessions/getSessions.ts (100%) rename {queries => src/queries}/analytics/sessions/saveSessionData.ts (100%) rename {queries => src/queries}/index.js (100%) rename {store => src/store}/app.js (100%) rename {store => src/store}/dashboard.js (100%) rename {store => src/store}/queries.js (100%) rename {store => src/store}/version.js (100%) rename {store => src/store}/websites.ts (100%) rename {styles => src/styles}/index.css (100%) rename {styles => src/styles}/locale.css (100%) rename {styles => src/styles}/variables.css (100%) rename {tracker => src/tracker}/index.d.ts (100%) rename {tracker => src/tracker}/index.js (100%) diff --git a/.eslintrc.json b/.eslintrc.json index f6d90ccab..a77ed5bd8 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -19,22 +19,21 @@ "plugin:@typescript-eslint/recommended", "next" ], - "plugins": ["@typescript-eslint", "prettier"], "settings": { "import/resolver": { "alias": { "map": [ - ["assets", "./assets"], - ["components", "./components"], + ["assets", "./src/assets"], + ["components", "./src/components"], ["db", "./db"], - ["hooks", "./hooks"], - ["lang", "./lang"], - ["lib", "./lib"], + ["hooks", "./src/components/hooks"], + ["lang", "./src/lang"], + ["lib", "./src/lib"], ["public", "./public"], - ["queries", "./queries"], - ["store", "./store"], - ["styles", "./styles"] + ["queries", "./src/queries"], + ["store", "./src/store"], + ["styles", "./src/styles"] ], "extensions": [".ts", ".tsx", ".js", ".jsx", ".json"] } diff --git a/jsconfig.json b/jsconfig.json index b639b0f8f..738e8a465 100644 --- a/jsconfig.json +++ b/jsconfig.json @@ -1,5 +1,5 @@ { "compilerOptions": { - "baseUrl": "." + "baseUrl": "./src" } -} \ No newline at end of file +} diff --git a/package.components.json b/package.components.json new file mode 100644 index 000000000..4596caa23 --- /dev/null +++ b/package.components.json @@ -0,0 +1,10 @@ +{ + "name": "@umami/components", + "version": "0.1.0", + "description": "Umami React components.", + "author": "Mike Cao ", + "license": "MIT", + "main": "dist/index.js", + "module": "dist/index.mjs", + "types": "dist/index.d.ts" +} diff --git a/package.json b/package.json index e1361d208..4f1eaa795 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,8 @@ "start-env": "node scripts/start-env.js", "start-server": "node server.js", "build-app": "next build", - "build-tracker": "rollup -c rollup.tracker.config.js", + "build-components": "rollup -c rollup.components.config.mjs", + "build-tracker": "rollup -c rollup.tracker.config.mjs", "build-db": "npm-run-all copy-db-files build-db-client", "build-lang": "npm-run-all format-lang compile-lang download-country-names download-language-names", "build-geo": "node scripts/build-geo.js", @@ -115,13 +116,16 @@ "@formatjs/cli": "^4.2.29", "@netlify/plugin-nextjs": "^4.27.3", "@rollup/plugin-alias": "^5.0.0", - "@rollup/plugin-buble": "^0.21.3", - "@rollup/plugin-commonjs": "^24.1.0", + "@rollup/plugin-buble": "^1.0.2", + "@rollup/plugin-commonjs": "^25.0.4", "@rollup/plugin-json": "^6.0.0", - "@rollup/plugin-node-resolve": "^15.0.2", - "@rollup/plugin-replace": "^4.0.0", - "@svgr/rollup": "^7.0.0", + "@rollup/plugin-node-resolve": "^15.2.0", + "@rollup/plugin-replace": "^5.0.2", + "@svgr/rollup": "^8.1.0", "@svgr/webpack": "^6.2.1", + "@types/node": "^18.11.9", + "@types/react": "^18.0.25", + "@types/react-dom": "^18.0.8", "@typescript-eslint/eslint-plugin": "^5.50.0", "@typescript-eslint/parser": "^5.50.0", "cross-env": "^7.0.3", @@ -143,11 +147,12 @@ "prettier": "^2.6.2", "prisma": "5.0.0", "prompts": "2.4.2", - "rollup": "^2.70.1", + "rollup": "^3.28.0", + "rollup-plugin-copy": "^3.4.0", "rollup-plugin-delete": "^2.0.0", - "rollup-plugin-dts": "^5.3.0", + "rollup-plugin-dts": "^6.0.0", "rollup-plugin-esbuild": "^5.0.0", - "rollup-plugin-node-externals": "^5.1.2", + "rollup-plugin-node-externals": "^6.1.1", "rollup-plugin-postcss": "^4.0.2", "rollup-plugin-terser": "^7.0.2", "stylelint": "^15.10.1", @@ -156,6 +161,6 @@ "stylelint-config-recommended": "^9.0.0", "tar": "^6.1.2", "ts-node": "^10.9.1", - "typescript": "^4.9.5" + "typescript": "^5.1.6" } } diff --git a/rollup.components.config.mjs b/rollup.components.config.mjs new file mode 100644 index 000000000..5c8722b4c --- /dev/null +++ b/rollup.components.config.mjs @@ -0,0 +1,99 @@ +import path from 'path'; +import crypto from 'crypto'; +import resolve from '@rollup/plugin-node-resolve'; +import alias from '@rollup/plugin-alias'; +import json from '@rollup/plugin-json'; +import postcss from 'rollup-plugin-postcss'; +import copy from 'rollup-plugin-copy'; +import del from 'rollup-plugin-delete'; +import nodeExternals from 'rollup-plugin-node-externals'; +import esbuild from 'rollup-plugin-esbuild'; +import dts from 'rollup-plugin-dts'; +import svgr from '@svgr/rollup'; + +const md5 = str => crypto.createHash('md5').update(str).digest('hex'); + +const customResolver = resolve({ + extensions: ['.js', '.jsx', '.ts', '.tsx'], +}); + +const aliasConfig = { + entries: [ + { find: /^components/, replacement: path.resolve('./src/components') }, + { find: /^hooks/, replacement: path.resolve('./src/hooks') }, + { find: /^lib/, replacement: path.resolve('./src/lib') }, + { find: /^store/, replacement: path.resolve('./src/store') }, + { find: /^public/, replacement: path.resolve('./public') }, + { find: /^assets/, replacement: path.resolve('./src/assets') }, + ], + customResolver, +}; + +const external = [ + 'react', + 'react-dom', + 'react/jsx-runtime', + 'react-intl', + 'react-basics', + 'classnames', + 'next', +]; + +const jsBundle = { + input: 'src/index.ts', + output: [ + { + file: 'dist/index.js', + format: 'cjs', + sourcemap: true, + }, + { + file: 'dist/index.mjs', + format: 'es', + sourcemap: true, + }, + ], + plugins: [ + del({ targets: 'dist/*', runOnce: true }), + copy({ targets: [{ src: './package.components.json', dest: 'dist', rename: 'package.json' }] }), + postcss({ + config: false, + extract: 'styles.css', + sourceMap: true, + minimize: true, + modules: { + generateScopedName: function (name, filename, css) { + const file = path.basename(filename, '.css').replace('.module', ''); + const hash = Buffer.from(md5(`${name}:${filename}:${css}`)) + .toString('base64') + .substring(0, 5); + + return `${file}-${name}--${hash}`; + }, + }, + }), + svgr({ icon: true }), + nodeExternals(), + json(), + alias(aliasConfig), + esbuild({ + target: 'es6', + jsx: 'transform', + loaders: { + '.js': 'jsx', + }, + }), + ], +}; + +const dtsBundle = { + input: 'src/index.ts', + output: { + file: 'dist/index.d.ts', + format: 'es', + }, + plugins: [alias(aliasConfig), nodeExternals(), json(), dts()], + external: [/\.css/], +}; + +export default [jsBundle, dtsBundle]; diff --git a/rollup.tracker.config.js b/rollup.tracker.config.mjs similarity index 93% rename from rollup.tracker.config.js rename to rollup.tracker.config.mjs index f4e7223c6..465e1af36 100644 --- a/rollup.tracker.config.js +++ b/rollup.tracker.config.mjs @@ -4,7 +4,7 @@ import replace from '@rollup/plugin-replace'; import { terser } from 'rollup-plugin-terser'; export default { - input: 'tracker/index.js', + input: 'src/tracker/index.js', output: { file: 'public/script.js', format: 'iife', diff --git a/scripts/check-lang.js b/scripts/check-lang.js index e5a0bf095..a1b604310 100644 --- a/scripts/check-lang.js +++ b/scripts/check-lang.js @@ -2,7 +2,7 @@ const fs = require('fs'); const path = require('path'); const chalk = require('chalk'); -const messages = require('../lang/en-US.json'); +const messages = require('../src/lang/en-US.json'); const ignore = require('../lang-ignore.json'); const dir = path.resolve(__dirname, '../lang'); diff --git a/assets/add-user.svg b/src/assets/add-user.svg similarity index 100% rename from assets/add-user.svg rename to src/assets/add-user.svg diff --git a/assets/bar-chart.svg b/src/assets/bar-chart.svg similarity index 100% rename from assets/bar-chart.svg rename to src/assets/bar-chart.svg diff --git a/assets/bars.svg b/src/assets/bars.svg similarity index 100% rename from assets/bars.svg rename to src/assets/bars.svg diff --git a/assets/bolt.svg b/src/assets/bolt.svg similarity index 100% rename from assets/bolt.svg rename to src/assets/bolt.svg diff --git a/assets/calendar.svg b/src/assets/calendar.svg similarity index 100% rename from assets/calendar.svg rename to src/assets/calendar.svg diff --git a/assets/clock.svg b/src/assets/clock.svg similarity index 100% rename from assets/clock.svg rename to src/assets/clock.svg diff --git a/assets/dashboard.svg b/src/assets/dashboard.svg similarity index 100% rename from assets/dashboard.svg rename to src/assets/dashboard.svg diff --git a/assets/expand.svg b/src/assets/expand.svg similarity index 100% rename from assets/expand.svg rename to src/assets/expand.svg diff --git a/assets/eye.svg b/src/assets/eye.svg similarity index 100% rename from assets/eye.svg rename to src/assets/eye.svg diff --git a/assets/funnel.svg b/src/assets/funnel.svg similarity index 100% rename from assets/funnel.svg rename to src/assets/funnel.svg diff --git a/assets/gear.svg b/src/assets/gear.svg similarity index 100% rename from assets/gear.svg rename to src/assets/gear.svg diff --git a/assets/globe.svg b/src/assets/globe.svg similarity index 100% rename from assets/globe.svg rename to src/assets/globe.svg diff --git a/assets/lightbulb.svg b/src/assets/lightbulb.svg similarity index 100% rename from assets/lightbulb.svg rename to src/assets/lightbulb.svg diff --git a/assets/link.svg b/src/assets/link.svg similarity index 100% rename from assets/link.svg rename to src/assets/link.svg diff --git a/assets/lock.svg b/src/assets/lock.svg similarity index 100% rename from assets/lock.svg rename to src/assets/lock.svg diff --git a/assets/logo.svg b/src/assets/logo.svg similarity index 100% rename from assets/logo.svg rename to src/assets/logo.svg diff --git a/assets/magnet.svg b/src/assets/magnet.svg similarity index 100% rename from assets/magnet.svg rename to src/assets/magnet.svg diff --git a/assets/moon.svg b/src/assets/moon.svg similarity index 100% rename from assets/moon.svg rename to src/assets/moon.svg diff --git a/assets/nodes.svg b/src/assets/nodes.svg similarity index 100% rename from assets/nodes.svg rename to src/assets/nodes.svg diff --git a/assets/overview.svg b/src/assets/overview.svg similarity index 100% rename from assets/overview.svg rename to src/assets/overview.svg diff --git a/assets/profile.svg b/src/assets/profile.svg similarity index 100% rename from assets/profile.svg rename to src/assets/profile.svg diff --git a/assets/redo.svg b/src/assets/redo.svg similarity index 100% rename from assets/redo.svg rename to src/assets/redo.svg diff --git a/assets/reports.svg b/src/assets/reports.svg similarity index 100% rename from assets/reports.svg rename to src/assets/reports.svg diff --git a/assets/sun.svg b/src/assets/sun.svg similarity index 100% rename from assets/sun.svg rename to src/assets/sun.svg diff --git a/assets/user.svg b/src/assets/user.svg similarity index 100% rename from assets/user.svg rename to src/assets/user.svg diff --git a/assets/users.svg b/src/assets/users.svg similarity index 100% rename from assets/users.svg rename to src/assets/users.svg diff --git a/assets/visitor.svg b/src/assets/visitor.svg similarity index 100% rename from assets/visitor.svg rename to src/assets/visitor.svg diff --git a/assets/website.svg b/src/assets/website.svg similarity index 100% rename from assets/website.svg rename to src/assets/website.svg diff --git a/components/common/ConfirmDeleteForm.js b/src/components/common/ConfirmDeleteForm.js similarity index 93% rename from components/common/ConfirmDeleteForm.js rename to src/components/common/ConfirmDeleteForm.js index 3496a3053..fed618da9 100644 --- a/components/common/ConfirmDeleteForm.js +++ b/src/components/common/ConfirmDeleteForm.js @@ -1,6 +1,6 @@ import { useState } from 'react'; import { Button, LoadingButton, Form, FormButtons } from 'react-basics'; -import useMessages from 'hooks/useMessages'; +import useMessages from 'components/hooks/useMessages'; export function ConfirmDeleteForm({ name, onConfirm, onClose }) { const [loading, setLoading] = useState(false); diff --git a/components/common/Empty.js b/src/components/common/Empty.js similarity index 86% rename from components/common/Empty.js rename to src/components/common/Empty.js index 95681b167..c0be761a0 100644 --- a/components/common/Empty.js +++ b/src/components/common/Empty.js @@ -1,6 +1,6 @@ import classNames from 'classnames'; import styles from './Empty.module.css'; -import useMessages from 'hooks/useMessages'; +import useMessages from 'components/hooks/useMessages'; export function Empty({ message, className }) { const { formatMessage, messages } = useMessages(); diff --git a/components/common/Empty.module.css b/src/components/common/Empty.module.css similarity index 100% rename from components/common/Empty.module.css rename to src/components/common/Empty.module.css diff --git a/components/common/EmptyPlaceholder.js b/src/components/common/EmptyPlaceholder.js similarity index 100% rename from components/common/EmptyPlaceholder.js rename to src/components/common/EmptyPlaceholder.js diff --git a/components/common/ErrorBoundary.js b/src/components/common/ErrorBoundary.js similarity index 93% rename from components/common/ErrorBoundary.js rename to src/components/common/ErrorBoundary.js index f97fd92c2..32cedb398 100644 --- a/components/common/ErrorBoundary.js +++ b/src/components/common/ErrorBoundary.js @@ -1,7 +1,7 @@ /* eslint-disable no-console */ import { ErrorBoundary as Boundary } from 'react-error-boundary'; import { Button } from 'react-basics'; -import useMessages from 'hooks/useMessages'; +import useMessages from 'components/hooks/useMessages'; import styles from './ErrorBoundry.module.css'; const logError = (error, info) => { diff --git a/components/common/ErrorBoundry.module.css b/src/components/common/ErrorBoundry.module.css similarity index 100% rename from components/common/ErrorBoundry.module.css rename to src/components/common/ErrorBoundry.module.css diff --git a/components/common/ErrorMessage.js b/src/components/common/ErrorMessage.js similarity index 88% rename from components/common/ErrorMessage.js rename to src/components/common/ErrorMessage.js index e2b227478..f8129c6b0 100644 --- a/components/common/ErrorMessage.js +++ b/src/components/common/ErrorMessage.js @@ -1,6 +1,6 @@ import { Icon, Icons, Text } from 'react-basics'; import styles from './ErrorMessage.module.css'; -import useMessages from 'hooks/useMessages'; +import useMessages from 'components/hooks/useMessages'; export function ErrorMessage() { const { formatMessage, messages } = useMessages(); diff --git a/components/common/ErrorMessage.module.css b/src/components/common/ErrorMessage.module.css similarity index 100% rename from components/common/ErrorMessage.module.css rename to src/components/common/ErrorMessage.module.css diff --git a/components/common/Favicon.js b/src/components/common/Favicon.js similarity index 100% rename from components/common/Favicon.js rename to src/components/common/Favicon.js diff --git a/components/common/Favicon.module.css b/src/components/common/Favicon.module.css similarity index 100% rename from components/common/Favicon.module.css rename to src/components/common/Favicon.module.css diff --git a/components/common/FilterButtons.js b/src/components/common/FilterButtons.js similarity index 100% rename from components/common/FilterButtons.js rename to src/components/common/FilterButtons.js diff --git a/components/common/FilterLink.js b/src/components/common/FilterLink.js similarity index 91% rename from components/common/FilterLink.js rename to src/components/common/FilterLink.js index 30cdc025b..2a95e011d 100644 --- a/components/common/FilterLink.js +++ b/src/components/common/FilterLink.js @@ -2,8 +2,8 @@ import { Icon, Icons } from 'react-basics'; import classNames from 'classnames'; import Link from 'next/link'; import { safeDecodeURI } from 'next-basics'; -import usePageQuery from 'hooks/usePageQuery'; -import useMessages from 'hooks/useMessages'; +import usePageQuery from 'components/hooks/usePageQuery'; +import useMessages from 'components/hooks/useMessages'; import styles from './FilterLink.module.css'; export function FilterLink({ id, value, label, externalUrl, children, className }) { diff --git a/components/common/FilterLink.module.css b/src/components/common/FilterLink.module.css similarity index 100% rename from components/common/FilterLink.module.css rename to src/components/common/FilterLink.module.css diff --git a/components/common/HamburgerButton.js b/src/components/common/HamburgerButton.js similarity index 93% rename from components/common/HamburgerButton.js rename to src/components/common/HamburgerButton.js index 48c807708..9feee67b7 100644 --- a/components/common/HamburgerButton.js +++ b/src/components/common/HamburgerButton.js @@ -2,8 +2,8 @@ import { Button, Icon } from 'react-basics'; import { useState } from 'react'; import MobileMenu from './MobileMenu'; import Icons from 'components/icons'; -import useMessages from 'hooks/useMessages'; -import useConfig from 'hooks/useConfig'; +import useMessages from 'components/hooks/useMessages'; +import useConfig from 'components/hooks/useConfig'; export function HamburgerButton() { const { formatMessage, labels } = useMessages(); diff --git a/components/common/HamburgerButton.module.css b/src/components/common/HamburgerButton.module.css similarity index 100% rename from components/common/HamburgerButton.module.css rename to src/components/common/HamburgerButton.module.css diff --git a/components/common/HoverTooltip.js b/src/components/common/HoverTooltip.js similarity index 100% rename from components/common/HoverTooltip.js rename to src/components/common/HoverTooltip.js diff --git a/components/common/HoverTooltip.module.css b/src/components/common/HoverTooltip.module.css similarity index 100% rename from components/common/HoverTooltip.module.css rename to src/components/common/HoverTooltip.module.css diff --git a/components/common/LinkButton.js b/src/components/common/LinkButton.js similarity index 77% rename from components/common/LinkButton.js rename to src/components/common/LinkButton.js index 8c0501475..54c7fa631 100644 --- a/components/common/LinkButton.js +++ b/src/components/common/LinkButton.js @@ -2,7 +2,7 @@ import Link from 'next/link'; import { Icon, Icons, Text } from 'react-basics'; import styles from './LinkButton.module.css'; -export default function LinkButton({ href, icon, children }) { +export function LinkButton({ href, icon, children }) { return ( {icon || } @@ -10,3 +10,5 @@ export default function LinkButton({ href, icon, children }) { ); } + +export default LinkButton; diff --git a/components/common/LinkButton.module.css b/src/components/common/LinkButton.module.css similarity index 100% rename from components/common/LinkButton.module.css rename to src/components/common/LinkButton.module.css diff --git a/components/common/MobileMenu.js b/src/components/common/MobileMenu.js similarity index 100% rename from components/common/MobileMenu.js rename to src/components/common/MobileMenu.js diff --git a/components/common/MobileMenu.module.css b/src/components/common/MobileMenu.module.css similarity index 100% rename from components/common/MobileMenu.module.css rename to src/components/common/MobileMenu.module.css diff --git a/components/common/Pager.js b/src/components/common/Pager.js similarity index 95% rename from components/common/Pager.js rename to src/components/common/Pager.js index aaeffbaec..7a5e7ed5f 100644 --- a/components/common/Pager.js +++ b/src/components/common/Pager.js @@ -1,6 +1,6 @@ import styles from './Pager.module.css'; import { Button, Flexbox, Icon, Icons } from 'react-basics'; -import useMessages from 'hooks/useMessages'; +import useMessages from 'components/hooks/useMessages'; export function Pager({ page, pageSize, count, onPageChange }) { const { formatMessage, labels } = useMessages(); diff --git a/components/common/Pager.module.css b/src/components/common/Pager.module.css similarity index 100% rename from components/common/Pager.module.css rename to src/components/common/Pager.module.css diff --git a/components/common/SettingsTable.js b/src/components/common/SettingsTable.js similarity index 98% rename from components/common/SettingsTable.js rename to src/components/common/SettingsTable.js index eb7a64112..2df3b391b 100644 --- a/components/common/SettingsTable.js +++ b/src/components/common/SettingsTable.js @@ -1,5 +1,5 @@ import Empty from 'components/common/Empty'; -import useMessages from 'hooks/useMessages'; +import useMessages from 'components/hooks/useMessages'; import { useState } from 'react'; import { SearchField, diff --git a/components/common/SettingsTable.module.css b/src/components/common/SettingsTable.module.css similarity index 100% rename from components/common/SettingsTable.module.css rename to src/components/common/SettingsTable.module.css diff --git a/components/common/UpdateNotice.js b/src/components/common/UpdateNotice.js similarity index 96% rename from components/common/UpdateNotice.js rename to src/components/common/UpdateNotice.js index bef6be982..e3edc70c1 100644 --- a/components/common/UpdateNotice.js +++ b/src/components/common/UpdateNotice.js @@ -4,7 +4,7 @@ import { setItem } from 'next-basics'; import useStore, { checkVersion } from 'store/version'; import { REPO_URL, VERSION_CHECK } from 'lib/constants'; import styles from './UpdateNotice.module.css'; -import useMessages from 'hooks/useMessages'; +import useMessages from 'components/hooks/useMessages'; import { useRouter } from 'next/router'; export function UpdateNotice({ user, config }) { diff --git a/components/common/UpdateNotice.module.css b/src/components/common/UpdateNotice.module.css similarity index 100% rename from components/common/UpdateNotice.module.css rename to src/components/common/UpdateNotice.module.css diff --git a/components/common/WorldMap.js b/src/components/common/WorldMap.js similarity index 94% rename from components/common/WorldMap.js rename to src/components/common/WorldMap.js index 9c91e4a47..b593099b7 100644 --- a/components/common/WorldMap.js +++ b/src/components/common/WorldMap.js @@ -5,9 +5,9 @@ import classNames from 'classnames'; import { colord } from 'colord'; import HoverTooltip from 'components/common/HoverTooltip'; import { ISO_COUNTRIES, MAP_FILE } from 'lib/constants'; -import useTheme from 'hooks/useTheme'; -import useCountryNames from 'hooks/useCountryNames'; -import useLocale from 'hooks/useLocale'; +import useTheme from 'components/hooks/useTheme'; +import useCountryNames from 'components/hooks/useCountryNames'; +import useLocale from 'components/hooks/useLocale'; import { formatLongNumber } from 'lib/format'; import { percentFilter } from 'lib/filters'; import styles from './WorldMap.module.css'; diff --git a/components/common/WorldMap.module.css b/src/components/common/WorldMap.module.css similarity index 100% rename from components/common/WorldMap.module.css rename to src/components/common/WorldMap.module.css diff --git a/components/declarations.d.ts b/src/components/declarations.d.ts similarity index 100% rename from components/declarations.d.ts rename to src/components/declarations.d.ts diff --git a/hooks/index.js b/src/components/hooks/index.js similarity index 100% rename from hooks/index.js rename to src/components/hooks/index.js diff --git a/hooks/useApi.ts b/src/components/hooks/useApi.ts similarity index 100% rename from hooks/useApi.ts rename to src/components/hooks/useApi.ts diff --git a/hooks/useApiFilter.ts b/src/components/hooks/useApiFilter.ts similarity index 100% rename from hooks/useApiFilter.ts rename to src/components/hooks/useApiFilter.ts diff --git a/hooks/useConfig.js b/src/components/hooks/useConfig.js similarity index 91% rename from hooks/useConfig.js rename to src/components/hooks/useConfig.js index 2dead15a8..6b37c87b0 100644 --- a/hooks/useConfig.js +++ b/src/components/hooks/useConfig.js @@ -1,6 +1,6 @@ import { useEffect } from 'react'; import useStore, { setConfig } from 'store/app'; -import useApi from 'hooks/useApi'; +import useApi from 'components/hooks/useApi'; let loading = false; diff --git a/hooks/useCountryNames.js b/src/components/hooks/useCountryNames.js similarity index 100% rename from hooks/useCountryNames.js rename to src/components/hooks/useCountryNames.js diff --git a/hooks/useDateRange.js b/src/components/hooks/useDateRange.js similarity index 100% rename from hooks/useDateRange.js rename to src/components/hooks/useDateRange.js diff --git a/hooks/useDocumentClick.js b/src/components/hooks/useDocumentClick.js similarity index 100% rename from hooks/useDocumentClick.js rename to src/components/hooks/useDocumentClick.js diff --git a/hooks/useEscapeKey.js b/src/components/hooks/useEscapeKey.js similarity index 100% rename from hooks/useEscapeKey.js rename to src/components/hooks/useEscapeKey.js diff --git a/hooks/useFilters.js b/src/components/hooks/useFilters.js similarity index 97% rename from hooks/useFilters.js rename to src/components/hooks/useFilters.js index 089f2ee84..e1a9a8858 100644 --- a/hooks/useFilters.js +++ b/src/components/hooks/useFilters.js @@ -1,4 +1,4 @@ -import { useMessages } from 'hooks'; +import { useMessages } from './useMessages'; import { OPERATORS } from 'lib/constants'; export function useFilters() { diff --git a/hooks/useForceUpdate.js b/src/components/hooks/useForceUpdate.js similarity index 100% rename from hooks/useForceUpdate.js rename to src/components/hooks/useForceUpdate.js diff --git a/hooks/useFormat.js b/src/components/hooks/useFormat.js similarity index 100% rename from hooks/useFormat.js rename to src/components/hooks/useFormat.js diff --git a/hooks/useLanguageNames.js b/src/components/hooks/useLanguageNames.js similarity index 100% rename from hooks/useLanguageNames.js rename to src/components/hooks/useLanguageNames.js diff --git a/hooks/useLocale.js b/src/components/hooks/useLocale.js similarity index 96% rename from hooks/useLocale.js rename to src/components/hooks/useLocale.js index 86ca99042..6353b0333 100644 --- a/hooks/useLocale.js +++ b/src/components/hooks/useLocale.js @@ -4,7 +4,7 @@ import { httpGet, setItem } from 'next-basics'; import { LOCALE_CONFIG } from 'lib/constants'; import { getDateLocale, getTextDirection } from 'lib/lang'; import useStore, { setLocale } from 'store/app'; -import useForceUpdate from 'hooks/useForceUpdate'; +import useForceUpdate from 'components/hooks/useForceUpdate'; import enUS from 'public/intl/messages/en-US.json'; const messages = { diff --git a/hooks/useMessages.js b/src/components/hooks/useMessages.js similarity index 100% rename from hooks/useMessages.js rename to src/components/hooks/useMessages.js diff --git a/hooks/usePageQuery.js b/src/components/hooks/usePageQuery.js similarity index 100% rename from hooks/usePageQuery.js rename to src/components/hooks/usePageQuery.js diff --git a/hooks/useReport.js b/src/components/hooks/useReport.js similarity index 100% rename from hooks/useReport.js rename to src/components/hooks/useReport.js diff --git a/hooks/useReports.js b/src/components/hooks/useReports.js similarity index 94% rename from hooks/useReports.js rename to src/components/hooks/useReports.js index 932fa6dc4..d9292aeb4 100644 --- a/hooks/useReports.js +++ b/src/components/hooks/useReports.js @@ -1,6 +1,6 @@ import { useState } from 'react'; import useApi from './useApi'; -import useApiFilter from 'hooks/useApiFilter'; +import useApiFilter from 'components/hooks/useApiFilter'; export function useReports() { const [modified, setModified] = useState(Date.now()); diff --git a/hooks/useRequireLogin.js b/src/components/hooks/useRequireLogin.js similarity index 84% rename from hooks/useRequireLogin.js rename to src/components/hooks/useRequireLogin.js index 3a95c9888..82a6d220a 100644 --- a/hooks/useRequireLogin.js +++ b/src/components/hooks/useRequireLogin.js @@ -1,7 +1,7 @@ import { useEffect } from 'react'; import { useRouter } from 'next/router'; -import useApi from 'hooks/useApi'; -import useUser from 'hooks/useUser'; +import useApi from 'components/hooks/useApi'; +import useUser from 'components/hooks/useUser'; export function useRequireLogin() { const router = useRouter(); diff --git a/hooks/useShareToken.js b/src/components/hooks/useShareToken.js similarity index 100% rename from hooks/useShareToken.js rename to src/components/hooks/useShareToken.js diff --git a/hooks/useSticky.js b/src/components/hooks/useSticky.js similarity index 100% rename from hooks/useSticky.js rename to src/components/hooks/useSticky.js diff --git a/hooks/useTheme.js b/src/components/hooks/useTheme.js similarity index 100% rename from hooks/useTheme.js rename to src/components/hooks/useTheme.js diff --git a/hooks/useTimezone.js b/src/components/hooks/useTimezone.js similarity index 100% rename from hooks/useTimezone.js rename to src/components/hooks/useTimezone.js diff --git a/hooks/useUser.js b/src/components/hooks/useUser.js similarity index 100% rename from hooks/useUser.js rename to src/components/hooks/useUser.js diff --git a/hooks/useWebsite.js b/src/components/hooks/useWebsite.js similarity index 100% rename from hooks/useWebsite.js rename to src/components/hooks/useWebsite.js diff --git a/hooks/useWebsiteReports.js b/src/components/hooks/useWebsiteReports.js similarity index 94% rename from hooks/useWebsiteReports.js rename to src/components/hooks/useWebsiteReports.js index 3b7ec4155..c637bc76a 100644 --- a/hooks/useWebsiteReports.js +++ b/src/components/hooks/useWebsiteReports.js @@ -1,6 +1,6 @@ import { useState } from 'react'; import useApi from './useApi'; -import useApiFilter from 'hooks/useApiFilter'; +import useApiFilter from 'components/hooks/useApiFilter'; export function useWebsiteReports(websiteId) { const [modified, setModified] = useState(Date.now()); diff --git a/components/icons.ts b/src/components/icons.ts similarity index 98% rename from components/icons.ts rename to src/components/icons.ts index 01d7caf5a..8eb1f8b05 100644 --- a/components/icons.ts +++ b/src/components/icons.ts @@ -22,7 +22,7 @@ import User from 'assets/user.svg'; import Users from 'assets/users.svg'; import Visitor from 'assets/visitor.svg'; -const icons = { +const icons: any = { ...Icons, AddUser, Bars, diff --git a/components/input/DateFilter.js b/src/components/input/DateFilter.js similarity index 96% rename from components/input/DateFilter.js rename to src/components/input/DateFilter.js index af4b69dde..ffbcff690 100644 --- a/components/input/DateFilter.js +++ b/src/components/input/DateFilter.js @@ -2,10 +2,10 @@ import { useState } from 'react'; import { Icon, Modal, Dropdown, Item, Text, Flexbox } from 'react-basics'; import { endOfYear, isSameDay } from 'date-fns'; import DatePickerForm from 'components/metrics/DatePickerForm'; -import useLocale from 'hooks/useLocale'; +import useLocale from 'components/hooks/useLocale'; import { formatDate } from 'lib/date'; import Icons from 'components/icons'; -import useMessages from 'hooks/useMessages'; +import useMessages from 'components/hooks/useMessages'; export function DateFilter({ value, diff --git a/components/input/LanguageButton.js b/src/components/input/LanguageButton.js similarity index 96% rename from components/input/LanguageButton.js rename to src/components/input/LanguageButton.js index d4c1cbc39..3c0d0cd6f 100644 --- a/components/input/LanguageButton.js +++ b/src/components/input/LanguageButton.js @@ -1,7 +1,7 @@ import { Icon, Button, PopupTrigger, Popup, Text } from 'react-basics'; import classNames from 'classnames'; import { languages } from 'lib/lang'; -import useLocale from 'hooks/useLocale'; +import useLocale from 'components/hooks/useLocale'; import Icons from 'components/icons'; import styles from './LanguageButton.module.css'; diff --git a/components/input/LanguageButton.module.css b/src/components/input/LanguageButton.module.css similarity index 100% rename from components/input/LanguageButton.module.css rename to src/components/input/LanguageButton.module.css diff --git a/components/input/LogoutButton.js b/src/components/input/LogoutButton.js similarity index 84% rename from components/input/LogoutButton.js rename to src/components/input/LogoutButton.js index 4a15cd68b..2b04a78a2 100644 --- a/components/input/LogoutButton.js +++ b/src/components/input/LogoutButton.js @@ -1,11 +1,11 @@ import { Button, Icon, Icons, TooltipPopup } from 'react-basics'; import Link from 'next/link'; -import useMessages from 'hooks/useMessages'; +import useMessages from 'components/hooks/useMessages'; export function LogoutButton({ tooltipPosition = 'top' }) { const { formatMessage, labels } = useMessages(); return ( - + + + + + ); } diff --git a/src/components/pages/websites/WebsiteMetricsBar.js b/src/components/pages/websites/WebsiteMetricsBar.js index ad68a9fa3..c625e239a 100644 --- a/src/components/pages/websites/WebsiteMetricsBar.js +++ b/src/components/pages/websites/WebsiteMetricsBar.js @@ -110,8 +110,8 @@ export function WebsiteMetricsBar({ websiteId, sticky }) {
- +
diff --git a/src/lib/date.js b/src/lib/date.js index 49bff8970..02f6053dc 100644 --- a/src/lib/date.js +++ b/src/lib/date.js @@ -29,9 +29,19 @@ import { max, min, isDate, + subWeeks, } from 'date-fns'; import { getDateLocale } from 'lib/lang'; +export const TIME_UNIT = { + minute: 'minute', + hour: 'hour', + day: 'day', + week: 'week', + month: 'month', + year: 'year', +}; + const dateFuncs = { minute: [differenceInMinutes, addMinutes, startOfMinute], hour: [differenceInHours, addHours, startOfHour], @@ -81,6 +91,7 @@ export function parseDateRange(value, locale = 'en-US') { if (!match) return null; const { num, unit } = match.groups; + const selectedUnit = { num, unit }; if (+num === 1) { switch (unit) { @@ -90,6 +101,7 @@ export function parseDateRange(value, locale = 'en-US') { endDate: endOfDay(now), unit: 'hour', value, + selectedUnit, }; case 'week': return { @@ -97,6 +109,7 @@ export function parseDateRange(value, locale = 'en-US') { endDate: endOfWeek(now, { locale: dateLocale }), unit: 'day', value, + selectedUnit, }; case 'month': return { @@ -104,6 +117,7 @@ export function parseDateRange(value, locale = 'en-US') { endDate: endOfMonth(now), unit: 'day', value, + selectedUnit, }; case 'year': return { @@ -111,6 +125,7 @@ export function parseDateRange(value, locale = 'en-US') { endDate: endOfYear(now), unit: 'month', value, + selectedUnit, }; } } @@ -123,6 +138,7 @@ export function parseDateRange(value, locale = 'en-US') { endDate: subDays(endOfDay(now), 1), unit: 'hour', value, + selectedUnit, }; case 'week': return { @@ -130,6 +146,7 @@ export function parseDateRange(value, locale = 'en-US') { endDate: subDays(endOfWeek(now, { locale: dateLocale }), 1), unit: 'day', value, + selectedUnit, }; case 'month': return { @@ -137,6 +154,7 @@ export function parseDateRange(value, locale = 'en-US') { endDate: subMonths(endOfMonth(now), 1), unit: 'day', value, + selectedUnit, }; case 'year': return { @@ -144,6 +162,7 @@ export function parseDateRange(value, locale = 'en-US') { endDate: subYears(endOfYear(now), 1), unit: 'month', value, + selectedUnit, }; } } @@ -155,6 +174,7 @@ export function parseDateRange(value, locale = 'en-US') { endDate: endOfDay(now), unit, value, + selectedUnit, }; case 'hour': return { @@ -162,6 +182,46 @@ export function parseDateRange(value, locale = 'en-US') { endDate: endOfHour(now), unit, value, + selectedUnit, + }; + } +} + +export function incrementDateRange(value, increment) { + const { startDate, endDate, selectedUnit } = value; + + const { num, unit } = selectedUnit; + + const sub = num * increment; + + switch (unit) { + case 'day': + return { + ...value, + startDate: subDays(startDate, sub), + endDate: subDays(endDate, sub), + value: 'range', + }; + case 'week': + return { + ...value, + startDate: subWeeks(startDate, sub), + endDate: subWeeks(endDate, sub), + value: 'range', + }; + case 'month': + return { + ...value, + startDate: subMonths(startDate, sub), + endDate: subMonths(endDate, sub), + value: 'range', + }; + case 'year': + return { + ...value, + startDate: subYears(startDate, sub), + endDate: subYears(endDate, sub), + value: 'range', }; } } @@ -237,7 +297,7 @@ export function getDateLength(startDate, endDate, unit) { return diff(endDate, startDate) + 1; } -export const customFormats = { +export const CUSTOM_FORMATS = { 'en-US': { p: 'ha', pp: 'h:mm:ss', @@ -252,7 +312,7 @@ export const customFormats = { export function formatDate(date, str, locale = 'en-US') { return format( typeof date === 'string' ? new Date(date) : date, - customFormats?.[locale]?.[str] || str, + CUSTOM_FORMATS?.[locale]?.[str] || str, { locale: getDateLocale(locale), }, diff --git a/src/lib/types.ts b/src/lib/types.ts index 3f3839a4d..e1e9da29f 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -12,9 +12,12 @@ import { WEBSITE_FILTER_TYPES, } from './constants'; import * as yup from 'yup'; +import { TIME_UNIT } from './date'; type ObjectValues = T[keyof T]; +export type TimeUnit = ObjectValues; + export type CollectionType = ObjectValues; export type Role = ObjectValues; export type EventType = ObjectValues; @@ -181,6 +184,8 @@ export interface DateRange { startDate: Date; endDate: Date; value: string; + unit?: TimeUnit; + selectedUnit?: TimeUnit; } export interface QueryFilters { diff --git a/tsconfig.json b/tsconfig.json index 37457b401..78b225f49 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -20,7 +20,8 @@ "baseUrl": "./src", "strictNullChecks": false, "noEmit": true, - "jsx": "preserve" + "jsx": "preserve", + "incremental": true }, "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], "exclude": ["node_modules"] From 51014f6ce62e07fb8da45e8f1b862821894069f2 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Mon, 21 Aug 2023 19:32:17 -0700 Subject: [PATCH 012/113] Fixed path alias. --- jsconfig.json | 5 ++++- src/components/hooks/useCountryNames.js | 2 +- src/components/hooks/useLanguageNames.js | 2 +- src/components/hooks/useLocale.js | 2 +- src/components/metrics/RegionsTable.js | 2 +- 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/jsconfig.json b/jsconfig.json index 738e8a465..f8124a205 100644 --- a/jsconfig.json +++ b/jsconfig.json @@ -1,5 +1,8 @@ { "compilerOptions": { - "baseUrl": "./src" + "baseUrl": "./src", + "paths": { + "public/*": ["./public/*"] + } } } diff --git a/src/components/hooks/useCountryNames.js b/src/components/hooks/useCountryNames.js index cd46ee442..51cabf34c 100644 --- a/src/components/hooks/useCountryNames.js +++ b/src/components/hooks/useCountryNames.js @@ -1,7 +1,7 @@ import { useState, useEffect } from 'react'; import { useRouter } from 'next/router'; import { httpGet } from 'next-basics'; -import enUS from '../../../public/intl/country/en-US.json'; +import enUS from 'public/intl/country/en-US.json'; const countryNames = { 'en-US': enUS, diff --git a/src/components/hooks/useLanguageNames.js b/src/components/hooks/useLanguageNames.js index b684667a8..afcb0ba65 100644 --- a/src/components/hooks/useLanguageNames.js +++ b/src/components/hooks/useLanguageNames.js @@ -1,7 +1,7 @@ import { useState, useEffect } from 'react'; import { useRouter } from 'next/router'; import { httpGet } from 'next-basics'; -import enUS from '../../../public/intl/country/en-US.json'; +import enUS from 'public/intl/country/en-US.json'; const languageNames = { 'en-US': enUS, diff --git a/src/components/hooks/useLocale.js b/src/components/hooks/useLocale.js index d84e1b4bb..1374af81f 100644 --- a/src/components/hooks/useLocale.js +++ b/src/components/hooks/useLocale.js @@ -5,7 +5,7 @@ import { LOCALE_CONFIG } from 'lib/constants'; import { getDateLocale, getTextDirection } from 'lib/lang'; import useStore, { setLocale } from 'store/app'; import useForceUpdate from 'components/hooks/useForceUpdate'; -import enUS from '../../../public/intl/country/en-US.json'; +import enUS from 'public/intl/country/en-US.json'; const messages = { 'en-US': enUS, diff --git a/src/components/metrics/RegionsTable.js b/src/components/metrics/RegionsTable.js index eee57a147..2e260e41d 100644 --- a/src/components/metrics/RegionsTable.js +++ b/src/components/metrics/RegionsTable.js @@ -5,7 +5,7 @@ import useLocale from 'components/hooks/useLocale'; import useMessages from 'components/hooks/useMessages'; import useCountryNames from 'components/hooks/useCountryNames'; import MetricsTable from './MetricsTable'; -import regions from '../../../public/iso-3166-2.json'; +import regions from 'public/iso-3166-2.json'; export function RegionsTable({ websiteId, ...props }) { const { locale } = useLocale(); From f62d23c9bc888da7a1f029efa62f2603dbe4418f Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Tue, 22 Aug 2023 03:36:49 -0700 Subject: [PATCH 013/113] Added alias for public folder. --- jsconfig.json | 5 +---- next.config.js | 3 +++ tsconfig.json | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/jsconfig.json b/jsconfig.json index f8124a205..738e8a465 100644 --- a/jsconfig.json +++ b/jsconfig.json @@ -1,8 +1,5 @@ { "compilerOptions": { - "baseUrl": "./src", - "paths": { - "public/*": ["./public/*"] - } + "baseUrl": "./src" } } diff --git a/next.config.js b/next.config.js index 2165a6e01..4ab775107 100644 --- a/next.config.js +++ b/next.config.js @@ -1,5 +1,6 @@ /* eslint-disable @typescript-eslint/no-var-requires */ require('dotenv').config(); +const path = require('path'); const pkg = require('./package.json'); const contentSecurityPolicy = ` @@ -92,6 +93,8 @@ const config = { use: ['@svgr/webpack'], }); + config.resolve.alias['public'] = path.resolve('./public'); + return config; }, async headers() { diff --git a/tsconfig.json b/tsconfig.json index 78b225f49..0faf5fbc2 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -21,7 +21,7 @@ "strictNullChecks": false, "noEmit": true, "jsx": "preserve", - "incremental": true + "incremental": false }, "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], "exclude": ["node_modules"] From 84236c0cd9ef3599aab00bd3e8a6647e26c12827 Mon Sep 17 00:00:00 2001 From: Brian Cao Date: Tue, 22 Aug 2023 12:32:36 -0700 Subject: [PATCH 014/113] Fix date filter. --- src/components/input/WebsiteDateFilter.js | 29 +++++++++++++---------- src/lib/date.js | 7 ++++++ 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/src/components/input/WebsiteDateFilter.js b/src/components/input/WebsiteDateFilter.js index e56eba4f9..db8d141ab 100644 --- a/src/components/input/WebsiteDateFilter.js +++ b/src/components/input/WebsiteDateFilter.js @@ -9,7 +9,8 @@ export function WebsiteDateFilter({ websiteId }) { const [dateRange, setDateRange] = useDateRange(websiteId); const { value, startDate, endDate, selectedUnit } = dateRange; - const isFutureDate = isAfter(incrementDateRange(dateRange, -1).startDate, new Date()); + const isFutureDate = + value !== 'all' && isAfter(incrementDateRange(dateRange, -1).startDate, new Date()); const handleChange = async value => { setDateRange(value); @@ -32,19 +33,21 @@ export function WebsiteDateFilter({ websiteId }) { onChange={handleChange} showAllTime={true} /> - - + {value !== 'all' && ( + + - - + + + )} ); } diff --git a/src/lib/date.js b/src/lib/date.js index 02f6053dc..14f0e13ce 100644 --- a/src/lib/date.js +++ b/src/lib/date.js @@ -195,6 +195,13 @@ export function incrementDateRange(value, increment) { const sub = num * increment; switch (unit) { + case 'hour': + return { + ...value, + startDate: subHours(startDate, sub), + endDate: subHours(endDate, sub), + value: 'range', + }; case 'day': return { ...value, From 280f6a9113877d189e89c3ff45e0050b029808df Mon Sep 17 00:00:00 2001 From: Brian Cao Date: Tue, 22 Aug 2023 15:37:22 -0700 Subject: [PATCH 015/113] Add grant to create website/team. --- src/lib/auth.ts | 23 ++++++++++++++++++++--- src/lib/middleware.ts | 10 ++++++++-- src/lib/types.ts | 3 +++ 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/src/lib/auth.ts b/src/lib/auth.ts index 10f7fbcac..a93f89c76 100644 --- a/src/lib/auth.ts +++ b/src/lib/auth.ts @@ -4,11 +4,12 @@ import debug from 'debug'; import { PERMISSIONS, ROLE_PERMISSIONS, SHARE_TOKEN_HEADER } from 'lib/constants'; import { secret } from 'lib/crypto'; import { createSecureToken, ensureArray, getRandomChars, parseToken } from 'next-basics'; -import { getTeamUser, getTeamWebsite, findTeamWebsiteByUserId } from 'queries'; +import { findTeamWebsiteByUserId, getTeamUser, getTeamWebsite, getWebsitesByUserId } from 'queries'; import { loadWebsite } from './load'; import { Auth } from './types'; const log = debug('umami:auth'); +const cloudMode = process.env.CLOUD_MODE; export async function setAuthKey(user, expire = 0) { const authKey = `auth:${getRandomChars(32)}`; @@ -57,7 +58,15 @@ export async function canViewWebsite({ user, shareToken }: Auth, websiteId: stri return !!(await findTeamWebsiteByUserId(websiteId, user.id)); } -export async function canCreateWebsite({ user }: Auth) { +export async function canCreateWebsite({ user, grant }: Auth) { + if (cloudMode) { + if (grant.find(a => a === PERMISSIONS.websiteCreate)) { + return true; + } + + return (await getWebsitesByUserId(user.id)).count < Number(process.env.WEBSITE_LIMIT); + } + if (user.isAdmin) { return true; } @@ -109,7 +118,15 @@ export async function canDeleteReport(auth: Auth, report: Report) { return canUpdateReport(auth, report); } -export async function canCreateTeam({ user }: Auth) { +export async function canCreateTeam({ user, grant }: Auth) { + if (cloudMode) { + if (grant.find(a => a === PERMISSIONS.teamCreate)) { + return true; + } + + return false; + } + if (user.isAdmin) { return true; } diff --git a/src/lib/middleware.ts b/src/lib/middleware.ts index 0cb0cb880..18f6cc467 100644 --- a/src/lib/middleware.ts +++ b/src/lib/middleware.ts @@ -51,7 +51,7 @@ export const useAuth = createMiddleware(async (req, res, next) => { const shareToken = await parseShareToken(req); let user = null; - const { userId, authKey } = payload || {}; + const { userId, authKey, grant } = payload || {}; if (isUuid(userId)) { user = await getUserById(userId); @@ -72,7 +72,13 @@ export const useAuth = createMiddleware(async (req, res, next) => { user.isAdmin = user.role === ROLES.admin; } - (req as any).auth = { user, token, shareToken, authKey }; + (req as any).auth = { + user, + grant, + token, + shareToken, + authKey, + }; next(); }); diff --git a/src/lib/types.ts b/src/lib/types.ts index e1e9da29f..3685753e9 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -4,6 +4,7 @@ import { DATA_TYPE, EVENT_TYPE, KAFKA_TOPIC, + PERMISSIONS, REPORT_FILTER_TYPES, REPORT_TYPES, ROLES, @@ -17,6 +18,7 @@ import { TIME_UNIT } from './date'; type ObjectValues = T[keyof T]; export type TimeUnit = ObjectValues; +export type Permission = ObjectValues; export type CollectionType = ObjectValues; export type Role = ObjectValues; @@ -78,6 +80,7 @@ export interface Auth { role: string; isAdmin: boolean; }; + grant?: Permission[]; shareToken?: { websiteId: string; }; From c5345b01bb756c6055d529f0bc5e61db47a887a2 Mon Sep 17 00:00:00 2001 From: Brian Cao Date: Wed, 23 Aug 2023 10:25:57 -0700 Subject: [PATCH 016/113] Update tsconfig. --- tsconfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tsconfig.json b/tsconfig.json index 0faf5fbc2..9d860a224 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -23,6 +23,6 @@ "jsx": "preserve", "incremental": false }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], + "include": ["**/*.ts", "**/*.tsx", "**/*.js", "**/*.jsx", "next-env.d.ts"], "exclude": ["node_modules"] } From f794b5674b3b7d6124515fb4f5f090add29f30a2 Mon Sep 17 00:00:00 2001 From: Brian Cao Date: Wed, 23 Aug 2023 11:26:41 -0700 Subject: [PATCH 017/113] Update team/website permission check. --- src/lib/auth.ts | 8 ++++---- src/lib/{date.js => date.ts} | 0 2 files changed, 4 insertions(+), 4 deletions(-) rename src/lib/{date.js => date.ts} (100%) diff --git a/src/lib/auth.ts b/src/lib/auth.ts index a93f89c76..4a42d85de 100644 --- a/src/lib/auth.ts +++ b/src/lib/auth.ts @@ -4,7 +4,7 @@ import debug from 'debug'; import { PERMISSIONS, ROLE_PERMISSIONS, SHARE_TOKEN_HEADER } from 'lib/constants'; import { secret } from 'lib/crypto'; import { createSecureToken, ensureArray, getRandomChars, parseToken } from 'next-basics'; -import { findTeamWebsiteByUserId, getTeamUser, getTeamWebsite, getWebsitesByUserId } from 'queries'; +import { findTeamWebsiteByUserId, getTeamUser, getTeamWebsite } from 'queries'; import { loadWebsite } from './load'; import { Auth } from './types'; @@ -60,11 +60,11 @@ export async function canViewWebsite({ user, shareToken }: Auth, websiteId: stri export async function canCreateWebsite({ user, grant }: Auth) { if (cloudMode) { - if (grant.find(a => a === PERMISSIONS.websiteCreate)) { + if (grant?.find(a => a === PERMISSIONS.websiteCreate)) { return true; } - return (await getWebsitesByUserId(user.id)).count < Number(process.env.WEBSITE_LIMIT); + return false; } if (user.isAdmin) { @@ -120,7 +120,7 @@ export async function canDeleteReport(auth: Auth, report: Report) { export async function canCreateTeam({ user, grant }: Auth) { if (cloudMode) { - if (grant.find(a => a === PERMISSIONS.teamCreate)) { + if (grant?.find(a => a === PERMISSIONS.teamCreate)) { return true; } diff --git a/src/lib/date.js b/src/lib/date.ts similarity index 100% rename from src/lib/date.js rename to src/lib/date.ts From d43ab3e5593572895c2d6c443291fd4073f1ec9e Mon Sep 17 00:00:00 2001 From: Brian Cao Date: Wed, 23 Aug 2023 11:55:45 -0700 Subject: [PATCH 018/113] Roll back session insert. --- src/lib/session.ts | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/src/lib/session.ts b/src/lib/session.ts index 5eb7398a9..85c173c52 100644 --- a/src/lib/session.ts +++ b/src/lib/session.ts @@ -1,12 +1,27 @@ -import { secret, uuid, isUuid } from 'lib/crypto'; +import { isUuid, secret, uuid } from 'lib/crypto'; import { getClientInfo, getJsonBody } from 'lib/detect'; import { parseToken } from 'next-basics'; import { CollectRequestBody, NextApiRequestCollect } from 'pages/api/send'; import { createSession } from 'queries'; import cache from './cache'; +import clickhouse from './clickhouse'; import { loadSession, loadWebsite } from './load'; -export async function findSession(req: NextApiRequestCollect) { +export async function findSession(req: NextApiRequestCollect): Promise<{ + id: any; + websiteId: string; + hostname: string; + browser: string; + os: any; + device: string; + screen: string; + language: string; + country: any; + subdivision1: any; + subdivision2: any; + city: any; + ownerId: string; +}> { const { payload } = getJsonBody(req); if (!payload) { @@ -53,6 +68,25 @@ export async function findSession(req: NextApiRequestCollect) { const sessionId = uuid(websiteId, hostname, ip, userAgent); + // Clickhouse does not require session lookup + if (clickhouse.enabled) { + return { + id: sessionId, + websiteId, + hostname, + browser, + os: os as any, + device, + screen, + language, + country, + subdivision1, + subdivision2, + city, + ownerId: website.userId, + }; + } + // Find session let session = await loadSession(sessionId); From 06de67ec55821051480f5ca1ad3e612cb0cb7809 Mon Sep 17 00:00:00 2001 From: Brian Cao Date: Wed, 23 Aug 2023 12:17:32 -0700 Subject: [PATCH 019/113] Add 1 day cache limit to user/website/session --- src/lib/cache.ts | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/lib/cache.ts b/src/lib/cache.ts index bc46c23d1..c54eda2ee 100644 --- a/src/lib/cache.ts +++ b/src/lib/cache.ts @@ -2,17 +2,20 @@ import { User, Website } from '@prisma/client'; import redis from '@umami/redis-client'; import { getSession, getUserById, getWebsiteById } from '../queries'; -const { fetchObject, storeObject, deleteObject } = redis; +const { fetchObject, storeObject, deleteObject, expire } = redis; async function fetchWebsite(id): Promise { - return fetchObject(`website:${id}`, () => getWebsiteById(id)); + return fetchObject(`website:${id}`, () => getWebsiteById(id), 86400); } async function storeWebsite(data) { const { id } = data; const key = `website:${id}`; - return storeObject(key, data); + const obj = await storeObject(key, data); + await expire(key, 86400); + + return obj; } async function deleteWebsite(id) { @@ -20,14 +23,17 @@ async function deleteWebsite(id) { } async function fetchUser(id): Promise { - return fetchObject(`user:${id}`, () => getUserById(id, { includePassword: true })); + return fetchObject(`user:${id}`, () => getUserById(id, { includePassword: true }), 86400); } async function storeUser(data) { const { id } = data; const key = `user:${id}`; - return storeObject(key, data); + const obj = await storeObject(key, data); + await expire(key, 86400); + + return obj; } async function deleteUser(id) { @@ -35,14 +41,17 @@ async function deleteUser(id) { } async function fetchSession(id) { - return fetchObject(`session:${id}`, () => getSession(id)); + return fetchObject(`session:${id}`, () => getSession(id), 86400); } async function storeSession(data) { const { id } = data; const key = `session:${id}`; - return storeObject(key, data); + const obj = await storeObject(key, data); + await expire(key, 86400); + + return obj; } async function deleteSession(id) { From 89db57a38091f44c8e077c1f43b89deee3cb21b9 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Wed, 23 Aug 2023 12:50:18 -0700 Subject: [PATCH 020/113] Updated component library build. --- package.components.json | 21 ++- package.json | 4 +- rollup.components.config.mjs | 7 +- ...{useRequireLogin.js => useRequireLogin.ts} | 6 +- .../hooks/{useUser.js => useUser.ts} | 0 src/components/input/WebsiteDateFilter.js | 8 +- .../pages/settings/teams/TeamWebsitesTable.js | 3 +- .../settings/websites/WebsiteSettings.js | 4 +- .../pages/settings/websites/WebsitesTable.js | 5 +- src/index.ts | 25 +++ src/lib/middleware.ts | 2 +- src/store/version.js | 2 +- src/store/websites.ts | 2 +- yarn.lock | 156 ++++++++++-------- 14 files changed, 146 insertions(+), 99 deletions(-) rename src/components/hooks/{useRequireLogin.js => useRequireLogin.ts} (71%) rename src/components/hooks/{useUser.js => useUser.ts} (100%) diff --git a/package.components.json b/package.components.json index 4596caa23..feb3fc2e6 100644 --- a/package.components.json +++ b/package.components.json @@ -1,10 +1,23 @@ { "name": "@umami/components", - "version": "0.1.0", + "version": "0.11.0", "description": "Umami React components.", "author": "Mike Cao ", "license": "MIT", - "main": "dist/index.js", - "module": "dist/index.mjs", - "types": "dist/index.d.ts" + "type": "module", + "main": "./index.js", + "types": "./index.d.ts", + "peerDependencies": { + "@tanstack/react-query": "^4.33.0", + "classnames": "^2.3.1", + "colord": "^2.9.2", + "immer": "^9.0.12", + "moment-timezone": "^0.5.35", + "next": "^13.4.0", + "next-basics": "^0.36.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-intl": "^5.24.7", + "zustand": "^4.3.8" + } } diff --git a/package.json b/package.json index 118c92697..1ff1730d1 100644 --- a/package.json +++ b/package.json @@ -62,7 +62,7 @@ "dependencies": { "@fontsource/inter": "^4.5.15", "@prisma/client": "5.0.0", - "@tanstack/react-query": "^4.16.1", + "@tanstack/react-query": "^4.33.0", "@umami/prisma-client": "^0.2.0", "@umami/redis-client": "^0.5.0", "chalk": "^4.1.1", @@ -90,7 +90,7 @@ "kafkajs": "^2.1.0", "maxmind": "^4.3.6", "moment-timezone": "^0.5.35", - "next": "13.3.1", + "next": "13.4.19", "next-basics": "^0.36.0", "node-fetch": "^3.2.8", "npm-run-all": "^4.1.5", diff --git a/rollup.components.config.mjs b/rollup.components.config.mjs index 5c8722b4c..a0b8efbd6 100644 --- a/rollup.components.config.mjs +++ b/rollup.components.config.mjs @@ -44,11 +44,6 @@ const jsBundle = { output: [ { file: 'dist/index.js', - format: 'cjs', - sourcemap: true, - }, - { - file: 'dist/index.mjs', format: 'es', sourcemap: true, }, @@ -78,7 +73,7 @@ const jsBundle = { alias(aliasConfig), esbuild({ target: 'es6', - jsx: 'transform', + jsx: 'automatic', loaders: { '.js': 'jsx', }, diff --git a/src/components/hooks/useRequireLogin.js b/src/components/hooks/useRequireLogin.ts similarity index 71% rename from src/components/hooks/useRequireLogin.js rename to src/components/hooks/useRequireLogin.ts index 82a6d220a..950bb60ac 100644 --- a/src/components/hooks/useRequireLogin.js +++ b/src/components/hooks/useRequireLogin.ts @@ -3,7 +3,7 @@ import { useRouter } from 'next/router'; import useApi from 'components/hooks/useApi'; import useUser from 'components/hooks/useUser'; -export function useRequireLogin() { +export function useRequireLogin(handler: (data?: object) => void) { const router = useRouter(); const { get } = useApi(); const { user, setUser } = useUser(); @@ -11,9 +11,9 @@ export function useRequireLogin() { useEffect(() => { async function loadUser() { try { - const { user } = await get('/auth/verify'); + const data = await get('/auth/verify'); - setUser(user); + setUser(typeof handler === 'function' ? handler(data) : (data as any)?.user); } catch { await router.push('/login'); } diff --git a/src/components/hooks/useUser.js b/src/components/hooks/useUser.ts similarity index 100% rename from src/components/hooks/useUser.js rename to src/components/hooks/useUser.ts diff --git a/src/components/input/WebsiteDateFilter.js b/src/components/input/WebsiteDateFilter.js index db8d141ab..5ab19e605 100644 --- a/src/components/input/WebsiteDateFilter.js +++ b/src/components/input/WebsiteDateFilter.js @@ -12,14 +12,12 @@ export function WebsiteDateFilter({ websiteId }) { const isFutureDate = value !== 'all' && isAfter(incrementDateRange(dateRange, -1).startDate, new Date()); - const handleChange = async value => { + const handleChange = value => { setDateRange(value); }; - const handleIncrement = async value => { - const newValue = incrementDateRange(dateRange, value); - - setDateRange(newValue); + const handleIncrement = value => { + setDateRange(incrementDateRange(dateRange, value)); }; return ( diff --git a/src/components/pages/settings/teams/TeamWebsitesTable.js b/src/components/pages/settings/teams/TeamWebsitesTable.js index 848f82078..5ce08f355 100644 --- a/src/components/pages/settings/teams/TeamWebsitesTable.js +++ b/src/components/pages/settings/teams/TeamWebsitesTable.js @@ -4,7 +4,6 @@ import Link from 'next/link'; import { Button, Icon, Icons, Text } from 'react-basics'; import TeamWebsiteRemoveButton from './TeamWebsiteRemoveButton'; import SettingsTable from 'components/common/SettingsTable'; -import useConfig from 'components/hooks/useConfig'; export function TeamWebsitesTable({ data = [], @@ -13,9 +12,9 @@ export function TeamWebsitesTable({ onFilterChange, onPageChange, onPageSizeChange, + openExternal = false, }) { const { formatMessage, labels } = useMessages(); - const { openExternal } = useConfig(); const { user } = useUser(); const columns = [ diff --git a/src/components/pages/settings/websites/WebsiteSettings.js b/src/components/pages/settings/websites/WebsiteSettings.js index cdd0fe041..ac8cd87cc 100644 --- a/src/components/pages/settings/websites/WebsiteSettings.js +++ b/src/components/pages/settings/websites/WebsiteSettings.js @@ -10,12 +10,10 @@ import TrackingCode from 'components/pages/settings/websites/TrackingCode'; import ShareUrl from 'components/pages/settings/websites/ShareUrl'; import useApi from 'components/hooks/useApi'; import useMessages from 'components/hooks/useMessages'; -import useConfig from 'components/hooks/useConfig'; -export function WebsiteSettings({ websiteId }) { +export function WebsiteSettings({ websiteId, openExternal = false }) { const router = useRouter(); const { formatMessage, labels, messages } = useMessages(); - const { openExternal } = useConfig(); const { get, useQuery } = useApi(); const { showToast } = useToasts(); const { data, isLoading } = useQuery( diff --git a/src/components/pages/settings/websites/WebsitesTable.js b/src/components/pages/settings/websites/WebsitesTable.js index d35da7575..7fa507168 100644 --- a/src/components/pages/settings/websites/WebsitesTable.js +++ b/src/components/pages/settings/websites/WebsitesTable.js @@ -3,7 +3,6 @@ import { Button, Text, Icon, Icons } from 'react-basics'; import SettingsTable from 'components/common/SettingsTable'; import Empty from 'components/common/Empty'; import useMessages from 'components/hooks/useMessages'; -import useConfig from 'components/hooks/useConfig'; import useUser from 'components/hooks/useUser'; export function WebsitesTable({ @@ -14,12 +13,12 @@ export function WebsitesTable({ onPageSizeChange, showTeam, showEditButton, + openExternal = false, }) { const { formatMessage, labels } = useMessages(); - const { openExternal } = useConfig(); const { user } = useUser(); - const showTable = data && (filterValue || data?.data.length !== 0); + const showTable = data && (filterValue || data?.data?.length !== 0); const teamColumns = [ { name: 'teamName', label: formatMessage(labels.teamName) }, diff --git a/src/index.ts b/src/index.ts index 6ca70afad..f2ef13cab 100644 --- a/src/index.ts +++ b/src/index.ts @@ -64,6 +64,31 @@ export * from 'components/layout/SettingsLayout'; export * from 'components/layout/ShareLayout'; export * from 'components/layout/SideNav'; */ + +export * from 'components/hooks/useApi'; +export * from 'components/hooks/useConfig'; +export * from 'components/hooks/useCountryNames'; +export * from 'components/hooks/useDateRange'; +export * from 'components/hooks/useDocumentClick'; +export * from 'components/hooks/useEscapeKey'; +export * from 'components/hooks/useFilters'; +export * from 'components/hooks/useForceUpdate'; +export * from 'components/hooks/useFormat'; +export * from 'components/hooks/useLanguageNames'; +export * from 'components/hooks/useLocale'; +export * from 'components/hooks/useMessages'; +export * from 'components/hooks/usePageQuery'; +export * from 'components/hooks/useReport'; +export * from 'components/hooks/useReports'; +export * from 'components/hooks/useRequireLogin'; +export * from 'components/hooks/useShareToken'; +export * from 'components/hooks/useSticky'; +export * from 'components/hooks/useTheme'; +export * from 'components/hooks/useTimezone'; +export * from 'components/hooks/useUser'; +export * from 'components/hooks/useWebsite'; +export * from 'components/hooks/useWebsiteReports'; + export * from 'components/pages/settings/teams/TeamAddForm'; export * from 'components/pages/settings/teams/TeamAddWebsiteForm'; export * from 'components/pages/settings/teams/TeamDeleteForm'; diff --git a/src/lib/middleware.ts b/src/lib/middleware.ts index 18f6cc467..0efb9762e 100644 --- a/src/lib/middleware.ts +++ b/src/lib/middleware.ts @@ -60,7 +60,7 @@ export const useAuth = createMiddleware(async (req, res, next) => { } if (process.env.NODE_ENV === 'development') { - log({ token, shareToken, payload, user }); + log({ token, shareToken, payload, user, grant }); } if (!user?.id && !shareToken) { diff --git a/src/store/version.js b/src/store/version.js index c232c7fa5..3b5afaac5 100644 --- a/src/store/version.js +++ b/src/store/version.js @@ -1,5 +1,5 @@ import { create } from 'zustand'; -import produce from 'immer'; +import { produce } from 'immer'; import semver from 'semver'; import { CURRENT_VERSION, VERSION_CHECK, UPDATES_URL } from 'lib/constants'; import { getItem } from 'next-basics'; diff --git a/src/store/websites.ts b/src/store/websites.ts index 0d210af6d..5d0eeccd3 100644 --- a/src/store/websites.ts +++ b/src/store/websites.ts @@ -1,5 +1,5 @@ import { create } from 'zustand'; -import produce from 'immer'; +import { produce } from 'immer'; import { DateRange } from 'lib/types'; const store = create(() => ({})); diff --git a/yarn.lock b/yarn.lock index 5bec68b24..c20730f3f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1754,10 +1754,10 @@ slash "^3.0.0" tiny-glob "^0.2.9" -"@next/env@13.3.1": - version "13.3.1" - resolved "https://registry.yarnpkg.com/@next/env/-/env-13.3.1.tgz#589707043065f6b71d411ed9b8f1ffd057c0fd4a" - integrity sha512-EDtCoedIZC7JlUQ3uaQpSc4aVmyhbLHmQVALg7pFfQgOTjgSnn7mKtA0DiCMkYvvsx6aFb5octGMtWrOtGXW9A== +"@next/env@13.4.19": + version "13.4.19" + resolved "https://registry.yarnpkg.com/@next/env/-/env-13.4.19.tgz#46905b4e6f62da825b040343cbc233144e9578d3" + integrity sha512-FsAT5x0jF2kkhNkKkukhsyYOrRqtSxrEhfliniIq0bwWbuXLgyt3Gv0Ml+b91XwjwArmuP7NxCiGd++GGKdNMQ== "@next/eslint-plugin-next@12.3.4": version "12.3.4" @@ -1766,50 +1766,50 @@ dependencies: glob "7.1.7" -"@next/swc-darwin-arm64@13.3.1": - version "13.3.1" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.3.1.tgz#2c9719dd10a9cdf63bf50a7576b05dcf78999fe8" - integrity sha512-UXPtriEc/pBP8luSLSCZBcbzPeVv+SSjs9cH/KygTbhmACye8/OOXRZO13Z2Wq1G0gLmEAIHQAOuF+vafPd2lw== +"@next/swc-darwin-arm64@13.4.19": + version "13.4.19" + resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.19.tgz#77ad462b5ced4efdc26cb5a0053968d2c7dac1b6" + integrity sha512-vv1qrjXeGbuF2mOkhkdxMDtv9np7W4mcBtaDnHU+yJG+bBwa6rYsYSCI/9Xm5+TuF5SbZbrWO6G1NfTh1TMjvQ== -"@next/swc-darwin-x64@13.3.1": - version "13.3.1" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-13.3.1.tgz#0be90342c89e53a390ccd9bece15f7f5cd480049" - integrity sha512-lT36yYxosCfLtplFzJWgo0hrPu6/do8+msgM7oQkPeohDNdhjtjFUgOOwdSnPublLR6Mo2Ym4P/wl5OANuD2bw== +"@next/swc-darwin-x64@13.4.19": + version "13.4.19" + resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-13.4.19.tgz#aebe38713a4ce536ee5f2a291673e14b715e633a" + integrity sha512-jyzO6wwYhx6F+7gD8ddZfuqO4TtpJdw3wyOduR4fxTUCm3aLw7YmHGYNjS0xRSYGAkLpBkH1E0RcelyId6lNsw== -"@next/swc-linux-arm64-gnu@13.3.1": - version "13.3.1" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.3.1.tgz#a7353265839f8b8569a346a444dc3ab3770d297e" - integrity sha512-wRb76nLWJhonH8s3kxC/1tFguEkeOPayIwe9mkaz1G/yeS3OrjeyKMJsb4+Kdg0zbTo53bNCOl59NNtDM7yyyw== +"@next/swc-linux-arm64-gnu@13.4.19": + version "13.4.19" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.4.19.tgz#ec54db65b587939c7b94f9a84800f003a380f5a6" + integrity sha512-vdlnIlaAEh6H+G6HrKZB9c2zJKnpPVKnA6LBwjwT2BTjxI7e0Hx30+FoWCgi50e+YO49p6oPOtesP9mXDRiiUg== -"@next/swc-linux-arm64-musl@13.3.1": - version "13.3.1" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.3.1.tgz#24552e6102c350e372f83f505a1d93c880551a50" - integrity sha512-qz3BzjJRZ16Iq/jrp+pjiYOc0jTjHlfmxQmZk9x/+5uhRP6/eWQSTAPVJ33BMo6oK5O5N4644OgTAbzXzorecg== +"@next/swc-linux-arm64-musl@13.4.19": + version "13.4.19" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.4.19.tgz#1f5e2c1ea6941e7d530d9f185d5d64be04279d86" + integrity sha512-aU0HkH2XPgxqrbNRBFb3si9Ahu/CpaR5RPmN2s9GiM9qJCiBBlZtRTiEca+DC+xRPyCThTtWYgxjWHgU7ZkyvA== -"@next/swc-linux-x64-gnu@13.3.1": - version "13.3.1" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.3.1.tgz#5f335a683b6eafa52307b12af97782993b6c45ff" - integrity sha512-6mgkLmwlyWlomQmpl21I3hxgqE5INoW4owTlcLpNsd1V4wP+J46BlI/5zV5KWWbzjfncIqzXoeGs5Eg+1GHODA== +"@next/swc-linux-x64-gnu@13.4.19": + version "13.4.19" + resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.4.19.tgz#96b0882492a2f7ffcce747846d3680730f69f4d1" + integrity sha512-htwOEagMa/CXNykFFeAHHvMJeqZfNQEoQvHfsA4wgg5QqGNqD5soeCer4oGlCol6NGUxknrQO6VEustcv+Md+g== -"@next/swc-linux-x64-musl@13.3.1": - version "13.3.1" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.3.1.tgz#58e5aad6f97203a0788783f66324456c8f9cdb50" - integrity sha512-uqm5sielhQmKJM+qayIhgZv1KlS5pqTdQ99b+Z7hMWryXS96qE0DftTmMZowBcUL6x7s2vSXyH5wPtO1ON7LBg== +"@next/swc-linux-x64-musl@13.4.19": + version "13.4.19" + resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.4.19.tgz#f276b618afa321d2f7b17c81fc83f429fb0fd9d8" + integrity sha512-4Gj4vvtbK1JH8ApWTT214b3GwUh9EKKQjY41hH/t+u55Knxi/0wesMzwQRhppK6Ddalhu0TEttbiJ+wRcoEj5Q== -"@next/swc-win32-arm64-msvc@13.3.1": - version "13.3.1" - resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.3.1.tgz#f8ed1badab57ed4503969758754e6fb0cf326753" - integrity sha512-WomIiTj/v3LevltlibNQKmvrOymNRYL+a0dp5R73IwPWN5FvXWwSELN/kiNALig/+T3luc4qHNTyvMCp9L6U5Q== +"@next/swc-win32-arm64-msvc@13.4.19": + version "13.4.19" + resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.4.19.tgz#1599ae0d401da5ffca0947823dac577697cce577" + integrity sha512-bUfDevQK4NsIAHXs3/JNgnvEY+LRyneDN788W2NYiRIIzmILjba7LaQTfihuFawZDhRtkYCv3JDC3B4TwnmRJw== -"@next/swc-win32-ia32-msvc@13.3.1": - version "13.3.1" - resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.3.1.tgz#7f599c8975b09ee5527cc49b9e5a4d13be50635a" - integrity sha512-M+PoH+0+q658wRUbs285RIaSTYnGBSTdweH/0CdzDgA6Q4rBM0sQs4DHmO3BPP0ltCO/vViIoyG7ks66XmCA5g== +"@next/swc-win32-ia32-msvc@13.4.19": + version "13.4.19" + resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.4.19.tgz#55cdd7da90818f03e4da16d976f0cb22045d16fd" + integrity sha512-Y5kikILFAr81LYIFaw6j/NrOtmiM4Sf3GtOc0pn50ez2GCkr+oejYuKGcwAwq3jiTKuzF6OF4iT2INPoxRycEA== -"@next/swc-win32-x64-msvc@13.3.1": - version "13.3.1" - resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.3.1.tgz#192d43ab44ebb98bd4f5865d0e1d7ce62703182f" - integrity sha512-Sl1F4Vp5Z1rNXWZYqJwMuWRRol4bqOB6+/d7KqkgQ4AcafKPN1PZmpkCoxv4UFHtFNIB7EotnuIhtXu3zScicQ== +"@next/swc-win32-x64-msvc@13.4.19": + version "13.4.19" + resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.4.19.tgz#648f79c4e09279212ac90d871646ae12d80cdfce" + integrity sha512-YzA78jBDXMYiINdPdJJwGgPNT3YqBNNGhsthsDoWHL9p24tEJn9ViQf/ZqTbwSpX/RrkPupLfuuTH2sf73JBAw== "@nodelib/fs.scandir@2.1.5": version "2.1.5" @@ -2244,24 +2244,24 @@ "@svgr/plugin-jsx" "^6.5.1" "@svgr/plugin-svgo" "^6.5.1" -"@swc/helpers@0.5.0": - version "0.5.0" - resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.0.tgz#bf1d807b60f7290d0ec763feea7ccdeda06e85f1" - integrity sha512-SjY/p4MmECVVEWspzSRpQEM3sjR17sP8PbGxELWrT+YZMBfiUyt1MRUNjMV23zohwlG2HYtCQOsCwsTHguXkyg== +"@swc/helpers@0.5.1": + version "0.5.1" + resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.1.tgz#e9031491aa3f26bfcc974a67f48bd456c8a5357a" + integrity sha512-sJ902EfIzn1Fa+qYmjdQqh8tPsoxyBz+8yBKC2HKUxyezKJFwPGOn7pv4WY6QuQW//ySQi5lJjA/ZT9sNWWNTg== dependencies: tslib "^2.4.0" -"@tanstack/query-core@4.32.0": - version "4.32.0" - resolved "https://registry.yarnpkg.com/@tanstack/query-core/-/query-core-4.32.0.tgz#e0f4a830283612430450c13badd353766423f523" - integrity sha512-ei4IYwL2kmlKSlCw9WgvV7PpXi0MiswVwfQRxawhJA690zWO3dU49igaQ/UMTl+Jy9jj9dK5IKAYvbX7kUvviQ== +"@tanstack/query-core@4.33.0": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@tanstack/query-core/-/query-core-4.33.0.tgz#7756da9a75a424e521622b1d84eb55b7a2b33715" + integrity sha512-qYu73ptvnzRh6se2nyBIDHGBQvPY1XXl3yR769B7B6mIDD7s+EZhdlWHQ67JI6UOTFRaI7wupnTnwJ3gE0Mr/g== -"@tanstack/react-query@^4.16.1": - version "4.32.0" - resolved "https://registry.yarnpkg.com/@tanstack/react-query/-/react-query-4.32.0.tgz#701b45b149cfd4b54a68705f9100973db3ba5d5d" - integrity sha512-B8WUMcByYAH9500ENejDCATOmEZhqjtS9wsfiQ3BNa+s+yAynY8SESI8WWHhSqUmjd0pmCSFRP6BOUGSda3QXA== +"@tanstack/react-query@^4.33.0": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@tanstack/react-query/-/react-query-4.33.0.tgz#e927b0343a6ecaa948fee59e9ca98fe561062638" + integrity sha512-97nGbmDK0/m0B86BdiXzx3EW9RcDYKpnyL2+WwyuLHEgpfThYAnXFaMMmnTDuAO4bQJXEhflumIEUfKmP7ESGA== dependencies: - "@tanstack/query-core" "4.32.0" + "@tanstack/query-core" "4.33.0" use-sync-external-store "^1.2.0" "@trysound/sax@0.2.0": @@ -4982,6 +4982,11 @@ glob-parent@^6.0.2: dependencies: is-glob "^4.0.3" +glob-to-regexp@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" + integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== + glob@7.1.7: version "7.1.7" resolved "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz" @@ -6450,27 +6455,29 @@ next-basics@^0.36.0: jsonwebtoken "^9.0.0" pure-rand "^6.0.2" -next@13.3.1: - version "13.3.1" - resolved "https://registry.yarnpkg.com/next/-/next-13.3.1.tgz#17625f7423db2e059d71b41bd9031756cf2b33bc" - integrity sha512-eByWRxPzKHs2oQz1yE41LX35umhz86ZSZ+mYyXBqn2IBi2hyUqxBA88avywdr4uyH+hCJczegGsDGWbzQA5Rqw== +next@13.4.19: + version "13.4.19" + resolved "https://registry.yarnpkg.com/next/-/next-13.4.19.tgz#2326e02aeedee2c693d4f37b90e4f0ed6882b35f" + integrity sha512-HuPSzzAbJ1T4BD8e0bs6B9C1kWQ6gv8ykZoRWs5AQoiIuqbGHHdQO7Ljuvg05Q0Z24E2ABozHe6FxDvI6HfyAw== dependencies: - "@next/env" "13.3.1" - "@swc/helpers" "0.5.0" + "@next/env" "13.4.19" + "@swc/helpers" "0.5.1" busboy "1.6.0" caniuse-lite "^1.0.30001406" postcss "8.4.14" styled-jsx "5.1.1" + watchpack "2.4.0" + zod "3.21.4" optionalDependencies: - "@next/swc-darwin-arm64" "13.3.1" - "@next/swc-darwin-x64" "13.3.1" - "@next/swc-linux-arm64-gnu" "13.3.1" - "@next/swc-linux-arm64-musl" "13.3.1" - "@next/swc-linux-x64-gnu" "13.3.1" - "@next/swc-linux-x64-musl" "13.3.1" - "@next/swc-win32-arm64-msvc" "13.3.1" - "@next/swc-win32-ia32-msvc" "13.3.1" - "@next/swc-win32-x64-msvc" "13.3.1" + "@next/swc-darwin-arm64" "13.4.19" + "@next/swc-darwin-x64" "13.4.19" + "@next/swc-linux-arm64-gnu" "13.4.19" + "@next/swc-linux-arm64-musl" "13.4.19" + "@next/swc-linux-x64-gnu" "13.4.19" + "@next/swc-linux-x64-musl" "13.4.19" + "@next/swc-win32-arm64-msvc" "13.4.19" + "@next/swc-win32-ia32-msvc" "13.4.19" + "@next/swc-win32-x64-msvc" "13.4.19" nice-try@^1.0.4: version "1.0.5" @@ -9340,6 +9347,14 @@ vue@^3.2.23: "@vue/server-renderer" "3.2.36" "@vue/shared" "3.2.36" +watchpack@2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d" + integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg== + dependencies: + glob-to-regexp "^0.4.1" + graceful-fs "^4.1.2" + web-streams-polyfill@^3.0.3: version "3.2.1" resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz#71c2718c52b45fd49dbeee88634b3a60ceab42a6" @@ -9506,6 +9521,11 @@ yup@^0.32.11: property-expr "^2.0.4" toposort "^2.0.2" +zod@3.21.4: + version "3.21.4" + resolved "https://registry.yarnpkg.com/zod/-/zod-3.21.4.tgz#10882231d992519f0a10b5dd58a38c9dabbb64db" + integrity sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw== + zustand@^4.3.8: version "4.3.9" resolved "https://registry.yarnpkg.com/zustand/-/zustand-4.3.9.tgz#a7d4332bbd75dfd25c6848180b3df1407217f2ad" From 10f92d0178111ae13c3022bd38bec427e74551e0 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Wed, 23 Aug 2023 13:10:12 -0700 Subject: [PATCH 021/113] Fixed tsconfig. --- tsconfig.json | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/tsconfig.json b/tsconfig.json index 9d860a224..08e376bd2 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -17,11 +17,20 @@ "forceConsistentCasingInFileNames": true, "allowJs": true, "strict": true, - "baseUrl": "./src", "strictNullChecks": false, "noEmit": true, "jsx": "preserve", - "incremental": false + "incremental": false, + "baseUrl": ".", + "paths": { + "assets/*": ["./src/assets/*"], + "components/*": ["./src/components/*"], + "lib/*": ["./src/lib/*"], + "pages/*": ["./src/pages/*"], + "queries/*": ["./src/queries/*"], + "store/*": ["./src/store/*"], + "styles/*": ["./src/styles/*"] + } }, "include": ["**/*.ts", "**/*.tsx", "**/*.js", "**/*.jsx", "next-env.d.ts"], "exclude": ["node_modules"] From d4be41a1217f61723d2e5fdff28d56c0a43b2536 Mon Sep 17 00:00:00 2001 From: Brian Cao Date: Wed, 23 Aug 2023 14:39:38 -0700 Subject: [PATCH 022/113] Fixed tsconfig. --- tsconfig.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tsconfig.json b/tsconfig.json index 08e376bd2..71094dd79 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -21,15 +21,15 @@ "noEmit": true, "jsx": "preserve", "incremental": false, - "baseUrl": ".", + "baseUrl": "./src", "paths": { - "assets/*": ["./src/assets/*"], - "components/*": ["./src/components/*"], - "lib/*": ["./src/lib/*"], - "pages/*": ["./src/pages/*"], - "queries/*": ["./src/queries/*"], - "store/*": ["./src/store/*"], - "styles/*": ["./src/styles/*"] + "assets/*": ["./assets/*"], + "components/*": ["./components/*"], + "lib/*": ["./lib/*"], + "pages/*": ["./pages/*"], + "queries/*": ["./queries/*"], + "store/*": ["./store/*"], + "styles/*": ["./styles/*"] } }, "include": ["**/*.ts", "**/*.tsx", "**/*.js", "**/*.jsx", "next-env.d.ts"], From 9180a7008b039bddff899da1acb721b8704f02c8 Mon Sep 17 00:00:00 2001 From: Brian Cao Date: Wed, 23 Aug 2023 16:24:14 -0700 Subject: [PATCH 023/113] Fix insights validation. --- src/pages/api/reports/insights.ts | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/pages/api/reports/insights.ts b/src/pages/api/reports/insights.ts index 04e51d4ca..d10eba3fb 100644 --- a/src/pages/api/reports/insights.ts +++ b/src/pages/api/reports/insights.ts @@ -12,8 +12,8 @@ export interface InsightsRequestBody { startDate: string; endDate: string; }; - fields: { name: string; type: string; value: string }[]; - filters: string[]; + fields: { name: string; type: string; label: string }[]; + filters: { name: string; type: string; filter: string; value: string }[]; groups: { name: string; type: string }[]; } @@ -33,12 +33,23 @@ const schema = { yup.object().shape({ name: yup.string().required(), type: yup.string().required(), + label: yup.string().required(), + }), + ) + .min(1) + .required(), + filters: yup + .array() + .of( + yup.object().shape({ + name: yup.string().required(), + type: yup.string().required(), + filter: yup.string().required(), value: yup.string().required(), }), ) .min(1) .required(), - filters: yup.array().of(yup.string()).min(1).required(), groups: yup.array().of( yup.object().shape({ name: yup.string().required(), From bf8c891c414095d68cd41bccf5c527493e812c57 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Wed, 23 Aug 2023 21:29:16 -0700 Subject: [PATCH 024/113] Fixed mobile menu being hidden. --- src/components/common/MobileMenu.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/common/MobileMenu.js b/src/components/common/MobileMenu.js index 2228a3e95..de1e9ffa8 100644 --- a/src/components/common/MobileMenu.js +++ b/src/components/common/MobileMenu.js @@ -1,3 +1,4 @@ +import { createPortal } from 'react-dom'; import classNames from 'classnames'; import { useRouter } from 'next/router'; import Link from 'next/link'; @@ -28,10 +29,11 @@ export function MobileMenu({ items = [], onClose }) {
); - return ( + return createPortal(
-
+ , + document.body, ); } From e0c00dece8f86e83defe683c5ef87760a5335150 Mon Sep 17 00:00:00 2001 From: Maekawa Minoru <126235344+err931@users.noreply.github.com> Date: Thu, 24 Aug 2023 18:00:00 +0900 Subject: [PATCH 025/113] Update ja-JP.json --- src/lang/ja-JP.json | 316 ++++++++++++++++++++++---------------------- 1 file changed, 158 insertions(+), 158 deletions(-) diff --git a/src/lang/ja-JP.json b/src/lang/ja-JP.json index 0f4d54504..770f6f076 100644 --- a/src/lang/ja-JP.json +++ b/src/lang/ja-JP.json @@ -1,211 +1,211 @@ { - "label.access-code": "Access code", + "label.access-code": "アクセスコード", "label.actions": "アクション", - "label.activity-log": "Activity log", - "label.add": "Add", - "label.add-description": "Add description", + "label.activity-log": "アクティビティログ", + "label.add": "追加", + "label.add-description": "説明を追加", "label.add-website": "Webサイトの追加", "label.admin": "管理者", - "label.after": "After", - "label.all": "すべて表示", - "label.all-time": "All time", - "label.analytics": "Analytics", - "label.average": "Average", + "label.after": "直後", + "label.all": "すべて", + "label.all-time": "すべての時間帯", + "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.confirm-password": "パスワード(確認)", - "label.contains": "Contains", - "label.continue": "Continue", - "label.countries": "国", - "label.country": "Country", - "label.create-report": "Create report", - "label.create-team": "Create team", - "label.create-user": "Create user", - "label.created": "Created", + "label.change-password": "パスワードの変更", + "label.cities": "都市", + "label.city": "都市", + "label.clear-all": "すべてクリア", + "label.confirm": "確認", + "label.confirm-password": "パスワード(確認)", + "label.contains": "コンテンツ", + "label.continue": "続ける", + "label.countries": "国名", + "label.country": "国", + "label.create-report": "レポートの作成", + "label.create-team": "チームの作成", + "label.create-user": "ユーザーの作成", + "label.created": "作成されました", "label.current-password": "現在のパスワード", - "label.custom-range": "期間を指定する", + "label.custom-range": "範囲指定", "label.dashboard": "ダッシュボード", - "label.data": "Data", - "label.date": "Date", - "label.date-range": "範囲指定", - "label.day": "Day", - "label.default-date-range": "最初に表示する期間", + "label.data": "データ", + "label.date": "日付", + "label.date-range": "期間", + "label.day": "日", + "label.default-date-range": "デフォルトの期間", "label.delete": "削除", - "label.delete-team": "Delete team", - "label.delete-user": "Delete user", + "label.delete-team": "チームの削除", + "label.delete-user": "ユーザーの削除", "label.delete-website": "Webサイトの削除", - "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.dismiss": "却下", + "label.does-not-contain": "を含まない", "label.domain": "ドメイン", - "label.dropoff": "Dropoff", + "label.dropoff": "切り捨て", "label.edit": "編集", - "label.edit-dashboard": "Edit dashboard", - "label.enable-share-url": "共有リンクを有効にする", - "label.event": "Event", - "label.event-data": "Event data", + "label.edit-dashboard": "ダッシュボードの編集", + "label.enable-share-url": "共有URLを有効にする", + "label.event": "イベント", + "label.event-data": "イベントデータ", "label.events": "イベント", - "label.false": "False", - "label.field": "Field", - "label.fields": "Fields", - "label.filter-combined": "パスまで", - "label.filter-raw": "すべて表示", - "label.filters": "Filters", - "label.funnel": "Funnel", - "label.greater-than": "Greater than", - "label.greater-than-equals": "Greater than or equals", - "label.insights": "Insights", - "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.languages": "Languages", + "label.false": "偽", + "label.field": "フィールド", + "label.fields": "フィールド", + "label.filter-combined": "統合", + "label.filter-raw": "RAW", + "label.filters": "フィルター", + "label.funnel": "分析", + "label.greater-than": "超過", + "label.greater-than-equals": "以上", + "label.insights": "見通し", + "label.is": "に等しい", + "label.is-not": "に等しくない", + "label.is-not-set": "未設定", + "label.is-set": "設定済み", + "label.join": "参加", + "label.join-team": "チームに参加", + "label.language": "言語", + "label.languages": "言語", "label.laptop": "ノートPC", "label.last-days": "過去{x}日間", "label.last-hours": "過去{x}時間", - "label.leave": "Leave", - "label.leave-team": "Leave team", - "label.less-than": "Less than", - "label.less-than-equals": "Less than or equals", + "label.leave": "離脱", + "label.leave-team": "チームを離脱", + "label.less-than": "未満", + "label.less-than-equals": "以下", "label.login": "ログイン", "label.logout": "ログアウト", - "label.max": "Max", - "label.members": "Members", - "label.min": "Min", + "label.max": "最大", + "label.members": "メンバー", + "label.min": "最小", "label.mobile": "携帯電話", - "label.more": "さらに表示", - "label.my-websites": "My websites", + "label.more": "もっと見る", + "label.my-websites": "マイWebサイト", "label.name": "名前", "label.new-password": "新しいパスワード", - "label.none": "None", + "label.none": "なし", "label.os": "OS", - "label.overview": "Overview", - "label.owner": "Owner", - "label.page-of": "Page {current} of {total}", + "label.overview": "概要", + "label.owner": "所有者", + "label.page-of": "ページ {current}/{total}", "label.page-views": "閲覧数", - "label.pageTitle": "Page title", + "label.pageTitle": "ページタイトル", "label.pages": "ページ", "label.password": "パスワード", - "label.powered-by": "このシステムは {name} で実行されています。", - "label.profile": "プロファイル", - "label.queries": "Queries", - "label.query": "Query", - "label.query-parameters": "Query parameters", + "label.powered-by": "Powered by {name}", + "label.profile": "プロフィール", + "label.queries": "クエリ", + "label.query": "クエリ", + "label.query-parameters": "クエリパラメーター", "label.realtime": "リアルタイム", - "label.referrer": "Referrer", + "label.referrer": "リファラー", "label.referrers": "リファラー", "label.refresh": "更新", - "label.regenerate": "Regenerate", - "label.region": "Region", - "label.regions": "Regions", - "label.remove": "Remove", - "label.reports": "Reports", + "label.regenerate": "再生成", + "label.region": "地域", + "label.regions": "地域", + "label.remove": "削除", + "label.reports": "レポート", "label.required": "必須", "label.reset": "リセット", - "label.reset-website": "Reset statistics", - "label.retention": "Retention", - "label.role": "Role", - "label.run-query": "Run query", + "label.reset-website": "Webサイトをリセットする", + "label.retention": "保持", + "label.role": "ロール", + "label.run-query": "クエリ実行", "label.save": "保存", - "label.screens": "Screens", - "label.select-date": "Select date", - "label.select-website": "Select website", - "label.sessions": "Sessions", + "label.screens": "画面サイズ", + "label.select-date": "日付を選択", + "label.select-website": "Webサイトを選択", + "label.sessions": "セッション", "label.settings": "設定", - "label.share-url": "共有リンク", - "label.single-day": "一日のみ", - "label.sum": "Sum", + "label.share-url": "共有URL", + "label.single-day": "一日", + "label.sum": "合計", "label.tablet": "タブレット", - "label.team": "Team", - "label.team-guest": "Team guest", - "label.team-id": "Team ID", - "label.team-member": "Team member", - "label.team-name": "Team name", - "label.team-owner": "Team owner", - "label.team-websites": "Team websites", - "label.teams": "Teams", - "label.theme": "Theme", + "label.team": "チーム", + "label.team-guest": "チームゲスト", + "label.team-id": "チームID", + "label.team-member": "チームメンバー", + "label.team-name": "チーム名", + "label.team-owner": "チーム所有者", + "label.team-websites": "チームのWebサイト", + "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": "Toggle charts", - "label.total": "Total", - "label.total-records": "Total records", + "label.toggle-charts": "グラフを切り替える", + "label.total": "累計", + "label.total-records": "総記録数", "label.tracking-code": "トラッキングコード", - "label.true": "True", - "label.type": "Type", - "label.unique": "Unique", + "label.true": "真", + "label.type": "種別", + "label.unique": "ユニーク", "label.unique-visitors": "ユニーク訪問者数", "label.unknown": "不明", - "label.untitled": "Untitled", + "label.untitled": "無題", "label.url": "URL", - "label.urls": "URLs", - "label.user": "User", + "label.urls": "URL", + "label.user": "ユーザー", "label.username": "ユーザー名", - "label.users": "Users", - "label.value": "Value", - "label.view": "View", - "label.view-details": "詳細を見る", - "label.view-only": "View only", - "label.views": "閲覧数", - "label.visitors": "訪問者数", - "label.website": "Website", - "label.website-id": "Website ID", + "label.users": "ユーザー", + "label.value": "値", + "label.view": "表示", + "label.view-details": "詳細を表示", + "label.view-only": "表示のみ", + "label.views": "表示", + "label.visitors": "訪問者", + "label.website": "Webサイト", + "label.website-id": "WebサイトID", "label.websites": "Webサイト", - "label.window": "Window", - "label.yesterday": "Yesterday", - "message.active-users": "{x}人が閲覧中です。", + "label.window": "ウィンドウ", + "label.yesterday": "昨日", + "message.active-users": "{x} {x, plural, one {アクティブな訪問者} other {アクティブな訪問者}}", "message.confirm-delete": "{target}を削除してもよろしいですか?", - "message.confirm-leave": "Are you sure you want to leave {target}?", - "message.confirm-reset": "Are your sure you want to reset {target}'s statistics?", - "message.delete-account": "To delete this account, type {confirmation} in the box below to confirm.", - "message.delete-website": "To delete this website, type {confirmation} in the box below to confirm.", - "message.delete-website-warning": "関連するすべてのデータも削除されます。", - "message.error": "問題が発生しました。", - "message.event-log": "{event} on {url}", - "message.go-to-settings": "設定する", - "message.incorrect-username-password": "ユーザー名/パスワードが正しくありません。", - "message.invalid-domain": "無効なドメイン", - "message.min-password-length": "Minimum length of {n} characters", - "message.new-version-available": "A new version of Umami {version} is available!", + "message.confirm-leave": "{target}から離脱してもよろしいですか?", + "message.confirm-reset": "{target}をリセットしてもよろしいですか?", + "message.delete-account": "このアカウントを削除するには、下のフォームに「{confirmation}」と入力してください。", + "message.delete-website": "このWebサイトを削除するには、下のフォームに「{confirmation}」と入力してください。", + "message.delete-website-warning": "Webサイトのデータがすべて削除されます。", + "message.error": "未知のエラーが発生しました。", + "message.event-log": "{url}の{event}", + "message.go-to-settings": "設定に移動する", + "message.incorrect-username-password": "ユーザー名またはパスワードが間違っています。", + "message.invalid-domain": "無効なドメインです。http/httpsを含めないでください。", + "message.min-password-length": "最小文字数は{n}文字です", + "message.new-version-available": "Umamiの新しいバージョン{version}が利用可能です!", "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-event-data": "イベントデータがありません。", + "message.no-match-password": "パスワードが一致しません。", + "message.no-results-found": "結果が見つかりません。", + "message.no-team-websites": "このチームにはWebサイトがありません。", + "message.no-teams": "チームを作成していません。", + "message.no-users": "ユーザーが存在しません。", "message.no-websites-configured": "Webサイトが設定されていません。", - "message.page-not-found": "ページが見つかりません。", - "message.reset-website": "To reset this website, type {confirmation} in the box below to confirm.", - "message.reset-website-warning": "All statistics for this website will be deleted, but your tracking code will remain intact.", - "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.tracking-code": "トラッキングコード", - "message.user-deleted": "User deleted.", - "message.visitor-log": "{os}({device})で{browser}を使用している{country}からの訪問者" + "message.page-not-found": "ページが見つかりません", + "message.reset-website": "このWebサイトをリセットするには、下のフォームに「{confirmation}」と入力してください。", + "message.reset-website-warning": "このWebサイトの統計情報はすべて削除されますが、設定はそのまま残ります。", + "message.saved": "保存されました。", + "message.share-url": "あなたのWebサイトの統計情報は次のURLで公開されています:", + "message.team-already-member": "あなたはすでにチームのメンバーです。", + "message.team-not-found": "チームが見つかりません。", + "message.team-websites-info": "Webサイトはチーム内の誰でも見ることができます。", + "message.tracking-code": "このWebサイトの統計情報を追跡するには、HTMLの...セクションに以下のコードを記述します。", + "message.user-deleted": "ユーザーが削除されました。", + "message.visitor-log": "{os}({device})で{browser}を使用している{country}からの訪問者" } From 2683ff278a59813cff7f4ff6f022c48b044699fe Mon Sep 17 00:00:00 2001 From: Brian Cao Date: Thu, 24 Aug 2023 12:55:15 -0700 Subject: [PATCH 026/113] Fix event-data calls. --- src/pages/api/event-data/events.ts | 4 ++-- src/pages/api/event-data/stats.ts | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/pages/api/event-data/events.ts b/src/pages/api/event-data/events.ts index da0afc65d..1d1d37877 100644 --- a/src/pages/api/event-data/events.ts +++ b/src/pages/api/event-data/events.ts @@ -10,7 +10,7 @@ export interface EventDataFieldsRequestQuery { websiteId: string; startAt: string; endAt: string; - event: string; + event?: string; } const schema = { @@ -18,7 +18,7 @@ const schema = { websiteId: yup.string().uuid().required(), startAt: yup.number().integer().required(), endAt: yup.number().integer().moreThan(yup.ref('startAt')).required(), - event: yup.string().required(), + event: yup.string(), }), }; diff --git a/src/pages/api/event-data/stats.ts b/src/pages/api/event-data/stats.ts index b7b70dbfe..7f694bc62 100644 --- a/src/pages/api/event-data/stats.ts +++ b/src/pages/api/event-data/stats.ts @@ -3,6 +3,7 @@ import { useAuth, useCors, useValidate } from 'lib/middleware'; import { NextApiRequestQueryBody } from 'lib/types'; import { NextApiResponse } from 'next'; import { methodNotAllowed, ok, unauthorized } from 'next-basics'; +import { getEventDataStats } from 'queries/index'; import * as yup from 'yup'; export interface EventDataStatsRequestQuery { From 7107336b491d3634376dcbd26ae77e4a6825268a Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Thu, 24 Aug 2023 16:17:46 -0700 Subject: [PATCH 027/113] Added loading to event data. --- src/components/pages/websites/WebsiteEventData.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/components/pages/websites/WebsiteEventData.js b/src/components/pages/websites/WebsiteEventData.js index ea8e473b0..d38ca1adb 100644 --- a/src/components/pages/websites/WebsiteEventData.js +++ b/src/components/pages/websites/WebsiteEventData.js @@ -1,4 +1,4 @@ -import { Flexbox } from 'react-basics'; +import { Flexbox, Loading } from 'react-basics'; import EventDataTable from 'components/pages/event-data/EventDataTable'; import EventDataValueTable from 'components/pages/event-data/EventDataValueTable'; import { EventDataMetricsBar } from 'components/pages/event-data/EventDataMetricsBar'; @@ -28,13 +28,14 @@ export default function WebsiteEventData({ websiteId }) { const { query: { event }, } = usePageQuery(); - const { data } = useData(websiteId, event); + const { data, isLoading } = useData(websiteId, event); return ( {!event && } - {event && } + {isLoading && } + {event && data && } ); } From fb78202139fe3d62ead5388d32128c7ca5e496a3 Mon Sep 17 00:00:00 2001 From: Brian Cao Date: Fri, 25 Aug 2023 10:45:59 -0700 Subject: [PATCH 028/113] Remove mandatory validation. --- src/lib/middleware.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/middleware.ts b/src/lib/middleware.ts index 0efb9762e..edf3e9292 100644 --- a/src/lib/middleware.ts +++ b/src/lib/middleware.ts @@ -87,7 +87,7 @@ export const useValidate = createMiddleware(async (req: any, res, next) => { try { const { yup } = req as NextApiRequestQueryBody; - yup[req.method].validateSync({ ...req.query, ...req.body }); + yup[req.method] && yup[req.method].validateSync({ ...req.query, ...req.body }); } catch (e: any) { return badRequest(res, e.message); } From 1a47f594c2934ba28f6888d088f0b205f9904bf7 Mon Sep 17 00:00:00 2001 From: Brian Cao Date: Fri, 25 Aug 2023 11:03:58 -0700 Subject: [PATCH 029/113] Add dashboard filter. --- src/components/messages.js | 1 + .../pages/reports/FieldFilterForm.js | 36 +++++++---- .../pages/reports/FilterSelectForm.js | 3 +- .../pages/websites/WebsiteMetricsBar.js | 61 +++++++++++++++++-- src/pages/api/websites/[id]/index.ts | 1 + 5 files changed, 85 insertions(+), 17 deletions(-) diff --git a/src/components/messages.js b/src/components/messages.js index ff6199450..f52ed5c5e 100644 --- a/src/components/messages.js +++ b/src/components/messages.js @@ -140,6 +140,7 @@ export const labels = defineMessages({ description: { id: 'label.description', defaultMessage: 'Description' }, untitled: { id: 'label.untitled', defaultMessage: 'Untitled' }, type: { id: 'label.type', defaultMessage: 'Type' }, + filter: { id: 'label.filter', defaultMessage: 'Filter' }, filters: { id: 'label.filters', defaultMessage: 'Filters' }, breakdown: { id: 'label.breakdown', defaultMessage: 'Breakdown' }, true: { id: 'label.true', defaultMessage: 'True' }, diff --git a/src/components/pages/reports/FieldFilterForm.js b/src/components/pages/reports/FieldFilterForm.js index 96e96697e..01efed3f4 100644 --- a/src/components/pages/reports/FieldFilterForm.js +++ b/src/components/pages/reports/FieldFilterForm.js @@ -3,7 +3,14 @@ import { Form, FormRow, Item, Flexbox, Dropdown, Button } from 'react-basics'; import { useMessages, useFilters, useFormat } from 'components/hooks'; import styles from './FieldFilterForm.module.css'; -export default function FieldFilterForm({ name, label, type, values, onSelect }) { +export default function FieldFilterForm({ + name, + label, + type, + values, + onSelect, + includeOnlyEquals, +}) { const { formatMessage, labels } = useMessages(); const [filter, setFilter] = useState('eq'); const [value, setValue] = useState(); @@ -27,17 +34,19 @@ export default function FieldFilterForm({ name, label, type, values, onSelect })
- - {({ value, label }) => { - return {label}; - }} - + {!includeOnlyEquals && ( + + {({ value, label }) => { + return {label}; + }} + + )} {value => { return {formatValue(value, name)}; diff --git a/src/components/pages/reports/FilterSelectForm.js b/src/components/pages/reports/FilterSelectForm.js index 274a00eae..8e02930ed 100644 --- a/src/components/pages/reports/FilterSelectForm.js +++ b/src/components/pages/reports/FilterSelectForm.js @@ -18,7 +18,7 @@ function useValues(websiteId, type) { return { data, error, isLoading }; } -export default function FilterSelectForm({ websiteId, items, onSelect }) { +export default function FilterSelectForm({ websiteId, items, onSelect, includeOnlyEquals }) { const [field, setField] = useState(); const { data, isLoading } = useValues(websiteId, field?.name); @@ -37,6 +37,7 @@ export default function FilterSelectForm({ websiteId, items, onSelect }) { type={field?.type} values={data} onSelect={onSelect} + includeOnlyEquals={includeOnlyEquals} /> ); } diff --git a/src/components/pages/websites/WebsiteMetricsBar.js b/src/components/pages/websites/WebsiteMetricsBar.js index c625e239a..5297dfcd4 100644 --- a/src/components/pages/websites/WebsiteMetricsBar.js +++ b/src/components/pages/websites/WebsiteMetricsBar.js @@ -1,20 +1,25 @@ import classNames from 'classnames'; -import { Row, Column } from 'react-basics'; -import { formatShortTime } from 'lib/format'; -import MetricCard from 'components/metrics/MetricCard'; +import { useApi, useDateRange, useMessages, usePageQuery, useSticky } from 'components/hooks'; import RefreshButton from 'components/input/RefreshButton'; import WebsiteDateFilter from 'components/input/WebsiteDateFilter'; +import MetricCard from 'components/metrics/MetricCard'; import MetricsBar from 'components/metrics/MetricsBar'; -import { useApi, useDateRange, usePageQuery, useMessages, useSticky } from 'components/hooks'; +import FilterSelectForm from 'components/pages/reports/FilterSelectForm'; +import PopupForm from 'components/pages/reports/PopupForm'; +import { formatShortTime } from 'lib/format'; +import { Button, Column, Icon, Icons, Popup, PopupTrigger, Row, TooltipPopup } from 'react-basics'; import styles from './WebsiteMetricsBar.module.css'; export function WebsiteMetricsBar({ websiteId, sticky }) { const { formatMessage, labels } = useMessages(); + const { get, useQuery } = useApi(); const [dateRange] = useDateRange(websiteId); const { startDate, endDate, modified } = dateRange; const { ref, isSticky } = useSticky({ enabled: sticky }); const { + resolveUrl, + router, query: { url, referrer, title, os, browser, device, country, region, city }, } = usePageQuery(); @@ -39,6 +44,17 @@ export function WebsiteMetricsBar({ websiteId, sticky }) { }), ); + const fieldOptions = [ + { name: 'url', type: 'string', label: formatMessage(labels.url) }, + { name: 'referrer', type: 'string', label: formatMessage(labels.referrer) }, + { name: 'browser', type: 'string', label: formatMessage(labels.browser) }, + { name: 'os', type: 'string', label: formatMessage(labels.os) }, + { name: 'device', type: 'string', label: formatMessage(labels.device) }, + { name: 'country', type: 'string', label: formatMessage(labels.country) }, + { name: 'region', type: 'string', label: formatMessage(labels.region) }, + { name: 'city', type: 'string', label: formatMessage(labels.city) }, + ]; + const { pageviews, uniques, bounces, totaltime } = data || {}; const num = Math.min(data && uniques.value, data && bounces.value); const diffs = data && { @@ -48,6 +64,42 @@ export function WebsiteMetricsBar({ websiteId, sticky }) { totaltime: totaltime.value - totaltime.change, }; + const handleAddFilter = ({ name, value }) => { + router.push(resolveUrl({ [name]: value })); + }; + + const WebsiteFilterButton = () => { + return ( + + + + + + {close => { + return ( + + { + handleAddFilter(value); + close(); + }} + includeOnlyEquals={true} + /> + + ); + }} + + + ); + }; + return (
+
diff --git a/src/pages/api/websites/[id]/index.ts b/src/pages/api/websites/[id]/index.ts index 597568de5..0e5aacceb 100644 --- a/src/pages/api/websites/[id]/index.ts +++ b/src/pages/api/websites/[id]/index.ts @@ -23,6 +23,7 @@ const schema = { id: yup.string().uuid().required(), }), }; + export default async ( req: NextApiRequestQueryBody, res: NextApiResponse, From fe56ed35d5cd736776d8e6e2644fd09ae3afffc3 Mon Sep 17 00:00:00 2001 From: Brian Cao Date: Fri, 25 Aug 2023 11:21:16 -0700 Subject: [PATCH 030/113] Hide filter. --- src/components/pages/websites/WebsiteChartList.js | 2 +- src/components/pages/websites/WebsiteMetricsBar.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/pages/websites/WebsiteChartList.js b/src/components/pages/websites/WebsiteChartList.js index f6f3f7656..56cbe157b 100644 --- a/src/components/pages/websites/WebsiteChartList.js +++ b/src/components/pages/websites/WebsiteChartList.js @@ -40,7 +40,7 @@ export default function WebsiteChartList({ websites, showCharts, limit }) { - + {showCharts && } ) : null; diff --git a/src/components/pages/websites/WebsiteMetricsBar.js b/src/components/pages/websites/WebsiteMetricsBar.js index 5297dfcd4..356058040 100644 --- a/src/components/pages/websites/WebsiteMetricsBar.js +++ b/src/components/pages/websites/WebsiteMetricsBar.js @@ -10,7 +10,7 @@ import { formatShortTime } from 'lib/format'; import { Button, Column, Icon, Icons, Popup, PopupTrigger, Row, TooltipPopup } from 'react-basics'; import styles from './WebsiteMetricsBar.module.css'; -export function WebsiteMetricsBar({ websiteId, sticky }) { +export function WebsiteMetricsBar({ websiteId, showFilter = true, sticky }) { const { formatMessage, labels } = useMessages(); const { get, useQuery } = useApi(); @@ -162,7 +162,7 @@ export function WebsiteMetricsBar({ websiteId, sticky }) {
- + {showFilter && }
From c67deb68e6e44904b838c1ccc4d17a400e18898f Mon Sep 17 00:00:00 2001 From: Brian Cao Date: Fri, 25 Aug 2023 11:33:30 -0700 Subject: [PATCH 031/113] Remove enddate check. --- src/pages/api/realtime/[id].ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/pages/api/realtime/[id].ts b/src/pages/api/realtime/[id].ts index ab7bb4060..5b1e1e057 100644 --- a/src/pages/api/realtime/[id].ts +++ b/src/pages/api/realtime/[id].ts @@ -11,12 +11,10 @@ export interface RealtimeRequestQuery { startAt: number; } -const currentDate = new Date().getTime(); - const schema = { GET: yup.object().shape({ id: yup.string().uuid().required(), - startAt: yup.number().integer().max(currentDate).required(), + startAt: yup.number().integer().required(), }), }; From 30c32dca7d9a35ac48f31bd127a20631a82d0da7 Mon Sep 17 00:00:00 2001 From: Francis Cao Date: Fri, 25 Aug 2023 11:34:59 -0700 Subject: [PATCH 032/113] remove required yup filters on insights report --- src/pages/api/reports/insights.ts | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/pages/api/reports/insights.ts b/src/pages/api/reports/insights.ts index d10eba3fb..4d17c9220 100644 --- a/src/pages/api/reports/insights.ts +++ b/src/pages/api/reports/insights.ts @@ -38,18 +38,14 @@ const schema = { ) .min(1) .required(), - filters: yup - .array() - .of( - yup.object().shape({ - name: yup.string().required(), - type: yup.string().required(), - filter: yup.string().required(), - value: yup.string().required(), - }), - ) - .min(1) - .required(), + filters: yup.array().of( + yup.object().shape({ + name: yup.string().required(), + type: yup.string().required(), + filter: yup.string().required(), + value: yup.string().required(), + }), + ), groups: yup.array().of( yup.object().shape({ name: yup.string().required(), From 75861bda61836a31e07bd3b25f3e73b7f2be58eb Mon Sep 17 00:00:00 2001 From: Brian Cao Date: Fri, 25 Aug 2023 13:01:48 -0700 Subject: [PATCH 033/113] Fix insight. --- src/pages/api/reports/insights.ts | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/pages/api/reports/insights.ts b/src/pages/api/reports/insights.ts index d10eba3fb..4d17c9220 100644 --- a/src/pages/api/reports/insights.ts +++ b/src/pages/api/reports/insights.ts @@ -38,18 +38,14 @@ const schema = { ) .min(1) .required(), - filters: yup - .array() - .of( - yup.object().shape({ - name: yup.string().required(), - type: yup.string().required(), - filter: yup.string().required(), - value: yup.string().required(), - }), - ) - .min(1) - .required(), + filters: yup.array().of( + yup.object().shape({ + name: yup.string().required(), + type: yup.string().required(), + filter: yup.string().required(), + value: yup.string().required(), + }), + ), groups: yup.array().of( yup.object().shape({ name: yup.string().required(), From 6d0b3934ebcf313d1b8784cddfd4dfc31d994c85 Mon Sep 17 00:00:00 2001 From: Francis Cao Date: Fri, 25 Aug 2023 13:32:24 -0700 Subject: [PATCH 034/113] Fix LoadingButton isLoading property --- src/components/common/ConfirmDeleteForm.js | 2 +- src/components/input/RefreshButton.js | 2 +- src/components/pages/reports/ReportHeader.js | 2 +- .../pages/settings/teams/TeamMemberRemoveButton.js | 6 +++++- .../pages/settings/teams/TeamWebsiteRemoveButton.js | 2 +- 5 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/components/common/ConfirmDeleteForm.js b/src/components/common/ConfirmDeleteForm.js index fed618da9..3d2c383d9 100644 --- a/src/components/common/ConfirmDeleteForm.js +++ b/src/components/common/ConfirmDeleteForm.js @@ -17,7 +17,7 @@ export function ConfirmDeleteForm({ name, onConfirm, onClose }) { {name} }} />

- + {formatMessage(labels.delete)} diff --git a/src/components/input/RefreshButton.js b/src/components/input/RefreshButton.js index 81bca45f7..8b40cafa1 100644 --- a/src/components/input/RefreshButton.js +++ b/src/components/input/RefreshButton.js @@ -16,7 +16,7 @@ export function RefreshButton({ websiteId, isLoading }) { return ( - + diff --git a/src/components/pages/reports/ReportHeader.js b/src/components/pages/reports/ReportHeader.js index e81f66fe8..e81d6ece6 100644 --- a/src/components/pages/reports/ReportHeader.js +++ b/src/components/pages/reports/ReportHeader.js @@ -66,7 +66,7 @@ export function ReportHeader({ icon }) { }> diff --git a/src/components/pages/settings/teams/TeamMemberRemoveButton.js b/src/components/pages/settings/teams/TeamMemberRemoveButton.js index 44fd30abe..3ec0f8b36 100644 --- a/src/components/pages/settings/teams/TeamMemberRemoveButton.js +++ b/src/components/pages/settings/teams/TeamMemberRemoveButton.js @@ -19,7 +19,11 @@ export function TeamMemberRemoveButton({ teamId, userId, disabled, onSave }) { }; return ( - handleRemoveTeamMember()} disabled={disabled} loading={isLoading}> + handleRemoveTeamMember()} + disabled={disabled} + isLoading={isLoading} + > diff --git a/src/components/pages/settings/teams/TeamWebsiteRemoveButton.js b/src/components/pages/settings/teams/TeamWebsiteRemoveButton.js index 2ea773fcd..c0ddf95ce 100644 --- a/src/components/pages/settings/teams/TeamWebsiteRemoveButton.js +++ b/src/components/pages/settings/teams/TeamWebsiteRemoveButton.js @@ -19,7 +19,7 @@ export function TeamWebsiteRemoveButton({ teamId, websiteId, onSave }) { }; return ( - handleRemoveTeamMember()} loading={isLoading}> + handleRemoveTeamMember()} isLoading={isLoading}> From 236a26136da65c4a3f199115d9fa18aeb21a520f Mon Sep 17 00:00:00 2001 From: Brian Cao Date: Fri, 25 Aug 2023 13:38:52 -0700 Subject: [PATCH 035/113] Add teamId. --- src/components/pages/settings/teams/TeamMembers.js | 1 + src/components/pages/settings/teams/TeamMembersTable.js | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/pages/settings/teams/TeamMembers.js b/src/components/pages/settings/teams/TeamMembers.js index 1420f6def..207ad72d4 100644 --- a/src/components/pages/settings/teams/TeamMembers.js +++ b/src/components/pages/settings/teams/TeamMembers.js @@ -33,6 +33,7 @@ export function TeamMembers({ teamId, readOnly }) { <> Date: Fri, 25 Aug 2023 15:03:49 -0700 Subject: [PATCH 036/113] update tooltip --- src/components/pages/websites/WebsiteMetricsBar.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/pages/websites/WebsiteMetricsBar.js b/src/components/pages/websites/WebsiteMetricsBar.js index 356058040..75fdab6a0 100644 --- a/src/components/pages/websites/WebsiteMetricsBar.js +++ b/src/components/pages/websites/WebsiteMetricsBar.js @@ -71,7 +71,7 @@ export function WebsiteMetricsBar({ websiteId, showFilter = true, sticky }) { const WebsiteFilterButton = () => { return ( - + - + {close => { return ( From 35f80d9b0055f29a907137d4eebe3a8a6de7d354 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Fri, 25 Aug 2023 15:06:47 -0700 Subject: [PATCH 038/113] Fixed scripts. --- rollup.components.config.mjs | 10 ---------- scripts/download-country-names.js | 2 +- scripts/download-language-names.js | 2 +- scripts/format-lang.js | 4 ++-- 4 files changed, 4 insertions(+), 14 deletions(-) diff --git a/rollup.components.config.mjs b/rollup.components.config.mjs index a0b8efbd6..c4481d0ee 100644 --- a/rollup.components.config.mjs +++ b/rollup.components.config.mjs @@ -29,16 +29,6 @@ const aliasConfig = { customResolver, }; -const external = [ - 'react', - 'react-dom', - 'react/jsx-runtime', - 'react-intl', - 'react-basics', - 'classnames', - 'next', -]; - const jsBundle = { input: 'src/index.ts', output: [ diff --git a/scripts/download-country-names.js b/scripts/download-country-names.js index f56d91f9c..6dbbbbdcc 100644 --- a/scripts/download-country-names.js +++ b/scripts/download-country-names.js @@ -4,7 +4,7 @@ const path = require('path'); const https = require('https'); const chalk = require('chalk'); -const src = path.resolve(__dirname, '../lang'); +const src = path.resolve(__dirname, '../src/lang'); const dest = path.resolve(__dirname, '../public/intl/country'); const files = fs.readdirSync(src); diff --git a/scripts/download-language-names.js b/scripts/download-language-names.js index 5cea88cf8..5478fb8d0 100644 --- a/scripts/download-language-names.js +++ b/scripts/download-language-names.js @@ -4,7 +4,7 @@ const path = require('path'); const https = require('https'); const chalk = require('chalk'); -const src = path.resolve(__dirname, '../lang'); +const src = path.resolve(__dirname, '../src/lang'); const dest = path.resolve(__dirname, '../public/intl/language'); const files = fs.readdirSync(src); diff --git a/scripts/format-lang.js b/scripts/format-lang.js index 941fd6722..593e296d2 100644 --- a/scripts/format-lang.js +++ b/scripts/format-lang.js @@ -3,7 +3,7 @@ const path = require('path'); const del = require('del'); const prettier = require('prettier'); -const src = path.resolve(__dirname, '../lang'); +const src = path.resolve(__dirname, '../src/lang'); const dest = path.resolve(__dirname, '../build/messages'); const files = fs.readdirSync(src); @@ -17,7 +17,7 @@ async function run() { await fs.ensureDir(dest); files.forEach(file => { - const lang = require(`../lang/${file}`); + const lang = require(`../src/lang/${file}`); const keys = Object.keys(lang).sort(); const formatted = keys.reduce((obj, key) => { From 080eb34d579ccd8ab3cdd15899b22acb5561fb52 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Fri, 25 Aug 2023 16:05:02 -0700 Subject: [PATCH 039/113] Update date filter buttons. --- package.json | 2 +- src/components/input/WebsiteDateFilter.js | 34 +++++++++---------- .../input/WebsiteDateFilter.module.css | 11 ++++++ src/components/layout/AppLayout.module.css | 2 +- src/components/metrics/FilterTags.js | 3 +- src/components/metrics/FilterTags.module.css | 12 ++++--- .../pages/websites/WebsiteDetailsPage.js | 4 +-- .../pages/websites/WebsiteMetricsBar.js | 4 +-- 8 files changed, 43 insertions(+), 29 deletions(-) diff --git a/package.json b/package.json index 1ff1730d1..64e09463b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "umami", - "version": "2.5.0", + "version": "2.6.0", "description": "A simple, fast, privacy-focused alternative to Google Analytics.", "author": "Mike Cao ", "license": "MIT", diff --git a/src/components/input/WebsiteDateFilter.js b/src/components/input/WebsiteDateFilter.js index 5ab19e605..a8403db6c 100644 --- a/src/components/input/WebsiteDateFilter.js +++ b/src/components/input/WebsiteDateFilter.js @@ -8,7 +8,6 @@ import styles from './WebsiteDateFilter.module.css'; export function WebsiteDateFilter({ websiteId }) { const [dateRange, setDateRange] = useDateRange(websiteId); const { value, startDate, endDate, selectedUnit } = dateRange; - const isFutureDate = value !== 'all' && isAfter(incrementDateRange(dateRange, -1).startDate, new Date()); @@ -21,7 +20,21 @@ export function WebsiteDateFilter({ websiteId }) { }; return ( - <> + + {value !== 'all' && ( + + + + + )} - {value !== 'all' && ( - - - - - - )} - + ); } diff --git a/src/components/input/WebsiteDateFilter.module.css b/src/components/input/WebsiteDateFilter.module.css index 13234c55c..986f5c178 100644 --- a/src/components/input/WebsiteDateFilter.module.css +++ b/src/components/input/WebsiteDateFilter.module.css @@ -1,3 +1,14 @@ .dropdown { min-width: 200px; } + +.buttons button:first-child { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + +.buttons button:last-child { + border-top-left-radius: 0; + border-bottom-left-radius: 0; + border-left: 1px solid var(--base400) !important; +} diff --git a/src/components/layout/AppLayout.module.css b/src/components/layout/AppLayout.module.css index be51f83cf..bcce963f0 100644 --- a/src/components/layout/AppLayout.module.css +++ b/src/components/layout/AppLayout.module.css @@ -10,7 +10,7 @@ width: 100vw; grid-column: 1; grid-row: 1 / 2; - z-index: 1; + z-index: var(--z-index-popup); } .body { diff --git a/src/components/metrics/FilterTags.js b/src/components/metrics/FilterTags.js index 30857a6b9..cb88a7dba 100644 --- a/src/components/metrics/FilterTags.js +++ b/src/components/metrics/FilterTags.js @@ -1,8 +1,8 @@ import { safeDecodeURI } from 'next-basics'; import { Button, Icon, Icons, Text } from 'react-basics'; import usePageQuery from 'components/hooks/usePageQuery'; -import styles from './FilterTags.module.css'; import useMessages from 'components/hooks/useMessages'; +import styles from './FilterTags.module.css'; export function FilterTags({ params }) { const { formatMessage, labels } = useMessages(); @@ -26,6 +26,7 @@ export function FilterTags({ params }) { return (
+
{formatMessage(labels.filters)}
{Object.keys(params).map(key => { if (!params[key]) { return null; diff --git a/src/components/metrics/FilterTags.module.css b/src/components/metrics/FilterTags.module.css index 1c8458acd..c228dc4e4 100644 --- a/src/components/metrics/FilterTags.module.css +++ b/src/components/metrics/FilterTags.module.css @@ -4,19 +4,23 @@ gap: 10px; } +.label { + font-weight: 700; +} + .tag { display: flex; flex-direction: row; align-items: center; gap: 10px; font-size: var(--font-size-sm); - border: 1px solid var(--base600); + border: 1px solid var(--blue400); border-radius: var(--border-radius); - line-height: 30px; - padding: 0 8px; + padding: 8px 16px; cursor: pointer; + background: var(--blue100); } .tag:hover { - background: var(--base75); + background: var(--blue200); } diff --git a/src/components/pages/websites/WebsiteDetailsPage.js b/src/components/pages/websites/WebsiteDetailsPage.js index c5ac47758..222d94d9e 100644 --- a/src/components/pages/websites/WebsiteDetailsPage.js +++ b/src/components/pages/websites/WebsiteDetailsPage.js @@ -22,12 +22,12 @@ export default function WebsiteDetailsPage({ websiteId }) { return ( - - + + {!website && } {website && ( <> diff --git a/src/components/pages/websites/WebsiteMetricsBar.js b/src/components/pages/websites/WebsiteMetricsBar.js index 41ae859f5..0d1a20f0b 100644 --- a/src/components/pages/websites/WebsiteMetricsBar.js +++ b/src/components/pages/websites/WebsiteMetricsBar.js @@ -10,7 +10,7 @@ import { formatShortTime } from 'lib/format'; import { Button, Column, Icon, Icons, Popup, PopupTrigger, Row } from 'react-basics'; import styles from './WebsiteMetricsBar.module.css'; -export function WebsiteMetricsBar({ websiteId, showFilter = true, sticky }) { +export function WebsiteMetricsBar({ websiteId, showFilter = true, showRefresh = true, sticky }) { const { formatMessage, labels } = useMessages(); const { get, useQuery } = useApi(); @@ -161,8 +161,8 @@ export function WebsiteMetricsBar({ websiteId, showFilter = true, sticky }) {
{showFilter && } + {showRefresh && } -
From cf1dd422fee79c08711be6c05030f3f36093012d Mon Sep 17 00:00:00 2001 From: Brian Cao Date: Fri, 25 Aug 2023 16:23:10 -0700 Subject: [PATCH 040/113] Disable filter on custom range. --- src/components/input/WebsiteDateFilter.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/input/WebsiteDateFilter.js b/src/components/input/WebsiteDateFilter.js index a8403db6c..6903a7085 100644 --- a/src/components/input/WebsiteDateFilter.js +++ b/src/components/input/WebsiteDateFilter.js @@ -9,7 +9,9 @@ export function WebsiteDateFilter({ websiteId }) { const [dateRange, setDateRange] = useDateRange(websiteId); const { value, startDate, endDate, selectedUnit } = dateRange; const isFutureDate = - value !== 'all' && isAfter(incrementDateRange(dateRange, -1).startDate, new Date()); + value !== 'all' && + selectedUnit && + isAfter(incrementDateRange(dateRange, -1).startDate, new Date()); const handleChange = value => { setDateRange(value); @@ -21,7 +23,7 @@ export function WebsiteDateFilter({ websiteId }) { return ( - {value !== 'all' && ( + {value !== 'all' && selectedUnit && (
)} @@ -102,4 +102,4 @@ const AnimatedRow = ({ ); }; -export default DataTable; +export default ListTable; diff --git a/src/components/metrics/MetricsTable.js b/src/components/metrics/MetricsTable.js index 893427a5f..39578381d 100644 --- a/src/components/metrics/MetricsTable.js +++ b/src/components/metrics/MetricsTable.js @@ -8,7 +8,7 @@ import { percentFilter } from 'lib/filters'; import useDateRange from 'components/hooks/useDateRange'; import usePageQuery from 'components/hooks/usePageQuery'; import ErrorMessage from 'components/common/ErrorMessage'; -import DataTable from './DataTable'; +import ListTable from './ListTable'; import { DEFAULT_ANIMATION_DURATION } from 'lib/constants'; import Icons from 'components/icons'; import useMessages from 'components/hooks/useMessages'; @@ -104,7 +104,7 @@ export function MetricsTable({
{!data && isLoading && !isFetched && } {error && } - {data && !error && } + {data && !error && }
{data && !error && limit && ( diff --git a/src/components/pages/realtime/RealtimeCountries.js b/src/components/pages/realtime/RealtimeCountries.js index 3aecad5ff..7a61651a2 100644 --- a/src/components/pages/realtime/RealtimeCountries.js +++ b/src/components/pages/realtime/RealtimeCountries.js @@ -1,6 +1,6 @@ import { useCallback } from 'react'; import { useRouter } from 'next/router'; -import DataTable from 'components/metrics/DataTable'; +import ListTable from 'components/metrics/ListTable'; import useLocale from 'components/hooks/useLocale'; import useCountryNames from 'components/hooks/useCountryNames'; import useMessages from 'components/hooks/useMessages'; @@ -24,7 +24,7 @@ export function RealtimeCountries({ data }) { ); return ( - {filter === FILTER_REFERRERS && ( - )} {filter === FILTER_PAGES && ( - Date: Sat, 26 Aug 2023 16:27:29 -0700 Subject: [PATCH 047/113] Remove required. --- src/pages/api/users/index.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/pages/api/users/index.ts b/src/pages/api/users/index.ts index 0b523c70c..fd1585d44 100644 --- a/src/pages/api/users/index.ts +++ b/src/pages/api/users/index.ts @@ -25,10 +25,7 @@ const schema = { username: yup.string().max(255).required(), password: yup.string().required(), id: yup.string().uuid(), - role: yup - .string() - .matches(/admin|user|view-only/i) - .required(), + role: yup.string().matches(/admin|user|view-only/i), }), }; From fcd7fac2ce635a5e757bcb9e419531663ca599b5 Mon Sep 17 00:00:00 2001 From: Brian Cao Date: Sat, 26 Aug 2023 16:33:22 -0700 Subject: [PATCH 048/113] Re-add required. --- src/pages/api/users/index.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/pages/api/users/index.ts b/src/pages/api/users/index.ts index fd1585d44..0b523c70c 100644 --- a/src/pages/api/users/index.ts +++ b/src/pages/api/users/index.ts @@ -25,7 +25,10 @@ const schema = { username: yup.string().max(255).required(), password: yup.string().required(), id: yup.string().uuid(), - role: yup.string().matches(/admin|user|view-only/i), + role: yup + .string() + .matches(/admin|user|view-only/i) + .required(), }), }; From f2f55170513d9a9735a058a2a800621eb3eab6b8 Mon Sep 17 00:00:00 2001 From: Brian Cao Date: Sat, 26 Aug 2023 16:35:43 -0700 Subject: [PATCH 049/113] fix type. --- src/pages/api/users/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/api/users/index.ts b/src/pages/api/users/index.ts index 0b523c70c..991986e87 100644 --- a/src/pages/api/users/index.ts +++ b/src/pages/api/users/index.ts @@ -13,7 +13,7 @@ export interface UsersRequestBody { username: string; password: string; id: string; - role?: Role; + role: Role; } import * as yup from 'yup'; From cc574e6da4800b5fe6f7eedccb7c180bc49abe08 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Sun, 27 Aug 2023 14:15:02 -0700 Subject: [PATCH 050/113] Added settings redirect for cloud. --- next.config.js | 4 +++- src/components/layout/NavBar.js | 10 ++++------ src/components/pages/reports/FieldFilterForm.js | 4 ++-- src/components/pages/reports/FilterSelectForm.js | 4 ++-- src/components/pages/settings/websites/TrackingCode.js | 4 ++-- src/components/pages/websites/WebsiteMetricsBar.js | 6 ++---- 6 files changed, 15 insertions(+), 17 deletions(-) diff --git a/next.config.js b/next.config.js index 4ab775107..b7a93ace6 100644 --- a/next.config.js +++ b/next.config.js @@ -59,7 +59,9 @@ if (process.env.TRACKER_SCRIPT_NAME) { const redirects = [ { source: '/settings', - destination: process.env.CLOUD_MODE ? '/settings/profile' : '/settings/websites', + destination: process.env.CLOUD_MODE + ? `${process.env.CLOUD_URL}/settings/websites` + : '/settings/websites', permanent: true, }, ]; diff --git a/src/components/layout/NavBar.js b/src/components/layout/NavBar.js index ec0881755..07627e2a2 100644 --- a/src/components/layout/NavBar.js +++ b/src/components/layout/NavBar.js @@ -1,26 +1,24 @@ import { Icon, Text, Row, Column } from 'react-basics'; import Link from 'next/link'; +import { useRouter } from 'next/router'; import classNames from 'classnames'; import Icons from 'components/icons'; import ThemeButton from 'components/input/ThemeButton'; import LanguageButton from 'components/input/LanguageButton'; import ProfileButton from 'components/input/ProfileButton'; -import styles from './NavBar.module.css'; -import useConfig from 'components/hooks/useConfig'; import useMessages from 'components/hooks/useMessages'; -import { useRouter } from 'next/router'; -import HamburgerButton from '../common/HamburgerButton'; +import HamburgerButton from 'components/common/HamburgerButton'; +import styles from './NavBar.module.css'; export function NavBar() { const { pathname } = useRouter(); - const { cloudMode } = useConfig(); const { formatMessage, labels } = useMessages(); const links = [ { label: formatMessage(labels.dashboard), url: '/dashboard' }, { label: formatMessage(labels.websites), url: '/websites' }, { label: formatMessage(labels.reports), url: '/reports' }, - !cloudMode && { label: formatMessage(labels.settings), url: '/settings' }, + { label: formatMessage(labels.settings), url: '/settings' }, ].filter(n => n); return ( diff --git a/src/components/pages/reports/FieldFilterForm.js b/src/components/pages/reports/FieldFilterForm.js index 01efed3f4..96ac06b01 100644 --- a/src/components/pages/reports/FieldFilterForm.js +++ b/src/components/pages/reports/FieldFilterForm.js @@ -9,7 +9,7 @@ export default function FieldFilterForm({ type, values, onSelect, - includeOnlyEquals, + allowFilterSelect = true, }) { const { formatMessage, labels } = useMessages(); const [filter, setFilter] = useState('eq'); @@ -34,7 +34,7 @@ export default function FieldFilterForm({ - {!includeOnlyEquals && ( + {allowFilterSelect && ( ); } diff --git a/src/components/pages/settings/websites/TrackingCode.js b/src/components/pages/settings/websites/TrackingCode.js index 5159ff914..fb4eb9a9e 100644 --- a/src/components/pages/settings/websites/TrackingCode.js +++ b/src/components/pages/settings/websites/TrackingCode.js @@ -4,10 +4,10 @@ import useConfig from 'components/hooks/useConfig'; export function TrackingCode({ websiteId }) { const { formatMessage, messages } = useMessages(); - const { basePath, trackerScriptName } = useConfig(); + const { basePath, trackerScriptName, trackerScriptOrigin } = useConfig(); const url = trackerScriptName?.startsWith('http') ? trackerScriptName - : `${location.origin}${basePath}/${ + : `${trackerScriptOrigin || location.origin}${basePath}/${ trackerScriptName?.split(',')?.map(n => n.trim())?.[0] || 'script.js' }`; diff --git a/src/components/pages/websites/WebsiteMetricsBar.js b/src/components/pages/websites/WebsiteMetricsBar.js index 0d1a20f0b..7ba4a8012 100644 --- a/src/components/pages/websites/WebsiteMetricsBar.js +++ b/src/components/pages/websites/WebsiteMetricsBar.js @@ -1,6 +1,5 @@ import classNames from 'classnames'; import { useApi, useDateRange, useMessages, usePageQuery, useSticky } from 'components/hooks'; -import RefreshButton from 'components/input/RefreshButton'; import WebsiteDateFilter from 'components/input/WebsiteDateFilter'; import MetricCard from 'components/metrics/MetricCard'; import MetricsBar from 'components/metrics/MetricsBar'; @@ -10,7 +9,7 @@ import { formatShortTime } from 'lib/format'; import { Button, Column, Icon, Icons, Popup, PopupTrigger, Row } from 'react-basics'; import styles from './WebsiteMetricsBar.module.css'; -export function WebsiteMetricsBar({ websiteId, showFilter = true, showRefresh = true, sticky }) { +export function WebsiteMetricsBar({ websiteId, showFilter = true, sticky }) { const { formatMessage, labels } = useMessages(); const { get, useQuery } = useApi(); @@ -88,7 +87,7 @@ export function WebsiteMetricsBar({ websiteId, showFilter = true, showRefresh = handleAddFilter(value); close(); }} - includeOnlyEquals={true} + allowFilterSelect={false} /> ); @@ -161,7 +160,6 @@ export function WebsiteMetricsBar({ websiteId, showFilter = true, showRefresh =
{showFilter && } - {showRefresh && }
From 183dab3ddc73dc0c7899f621c94f227f6464542d Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Sun, 27 Aug 2023 19:56:44 -0700 Subject: [PATCH 051/113] Refactored useConfig. --- next.config.js | 3 +++ src/components/common/HamburgerButton.js | 3 +-- src/components/hooks/useConfig.js | 5 +++-- src/components/input/ProfileButton.js | 3 +-- src/components/layout/AppLayout.js | 2 +- src/components/layout/SettingsLayout.js | 3 +-- .../pages/settings/profile/ProfileDetails.js | 3 +-- .../pages/settings/websites/TrackingCode.js | 12 ++++++++---- src/components/pages/websites/WebsitesPage.js | 3 +-- src/pages/_app.js | 15 +-------------- src/pages/api/config.ts | 14 ++++++-------- 11 files changed, 27 insertions(+), 39 deletions(-) diff --git a/next.config.js b/next.config.js index b7a93ace6..cc3cde7c6 100644 --- a/next.config.js +++ b/next.config.js @@ -76,6 +76,9 @@ if (process.env.CLOUD_MODE && process.env.CLOUD_URL && process.env.DISABLE_LOGIN const config = { env: { + cloudMode: process.env.CLOUD_MODE, + cloudUrl: process.env.CLOUD_URL, + configUrl: '/config', currentVersion: pkg.version, defaultLocale: process.env.DEFAULT_LOCALE, isProduction: process.env.NODE_ENV === 'production', diff --git a/src/components/common/HamburgerButton.js b/src/components/common/HamburgerButton.js index 9feee67b7..f97006efd 100644 --- a/src/components/common/HamburgerButton.js +++ b/src/components/common/HamburgerButton.js @@ -3,12 +3,11 @@ import { useState } from 'react'; import MobileMenu from './MobileMenu'; import Icons from 'components/icons'; import useMessages from 'components/hooks/useMessages'; -import useConfig from 'components/hooks/useConfig'; export function HamburgerButton() { const { formatMessage, labels } = useMessages(); const [active, setActive] = useState(false); - const { cloudMode } = useConfig(); + const cloudMode = Boolean(process.env.cloudMode); const menuItems = [ { diff --git a/src/components/hooks/useConfig.js b/src/components/hooks/useConfig.js index 6b37c87b0..5a516abc7 100644 --- a/src/components/hooks/useConfig.js +++ b/src/components/hooks/useConfig.js @@ -7,15 +7,16 @@ let loading = false; export function useConfig() { const { config } = useStore(); const { get } = useApi(); + const configUrl = process.env.configUrl; async function loadConfig() { - const data = await get('/config'); + const data = await get(configUrl); loading = false; setConfig(data); } useEffect(() => { - if (!config && !loading) { + if (!config && !loading && configUrl) { loading = true; loadConfig(); } diff --git a/src/components/input/ProfileButton.js b/src/components/input/ProfileButton.js index cfb89cf80..015c0ad8d 100644 --- a/src/components/input/ProfileButton.js +++ b/src/components/input/ProfileButton.js @@ -3,16 +3,15 @@ import { useRouter } from 'next/router'; import Icons from 'components/icons'; import useMessages from 'components/hooks/useMessages'; import useUser from 'components/hooks/useUser'; -import useConfig from 'components/hooks/useConfig'; import styles from './ProfileButton.module.css'; import useLocale from 'components/hooks/useLocale'; export function ProfileButton() { const { formatMessage, labels } = useMessages(); const { user } = useUser(); - const { cloudMode } = useConfig(); const router = useRouter(); const { dir } = useLocale(); + const cloudMode = Boolean(process.env.cloudMode); const handleSelect = key => { if (key === 'profile') { diff --git a/src/components/layout/AppLayout.js b/src/components/layout/AppLayout.js index 8fd637f36..41e2ec0d7 100644 --- a/src/components/layout/AppLayout.js +++ b/src/components/layout/AppLayout.js @@ -9,7 +9,7 @@ export function AppLayout({ title, children }) { const { user } = useRequireLogin(); const config = useConfig(); - if (!user || !config) { + if (!user || !config || config?.uiDisabled) { return null; } diff --git a/src/components/layout/SettingsLayout.js b/src/components/layout/SettingsLayout.js index 851c366a4..0f4aa5d96 100644 --- a/src/components/layout/SettingsLayout.js +++ b/src/components/layout/SettingsLayout.js @@ -3,14 +3,13 @@ import { useRouter } from 'next/router'; import SideNav from './SideNav'; import useUser from 'components/hooks/useUser'; import useMessages from 'components/hooks/useMessages'; -import useConfig from 'components/hooks/useConfig'; import styles from './SettingsLayout.module.css'; export function SettingsLayout({ children }) { const { user } = useUser(); const { pathname } = useRouter(); const { formatMessage, labels } = useMessages(); - const { cloudMode } = useConfig(); + const cloudMode = Boolean(process.env.cloudMode); const items = [ { key: 'websites', label: formatMessage(labels.websites), url: '/settings/websites' }, diff --git a/src/components/pages/settings/profile/ProfileDetails.js b/src/components/pages/settings/profile/ProfileDetails.js index f9dc652b9..d4a3a7d58 100644 --- a/src/components/pages/settings/profile/ProfileDetails.js +++ b/src/components/pages/settings/profile/ProfileDetails.js @@ -6,13 +6,12 @@ import ThemeSetting from 'components/pages/settings/profile/ThemeSetting'; import PasswordChangeButton from './PasswordChangeButton'; import useUser from 'components/hooks/useUser'; import useMessages from 'components/hooks/useMessages'; -import useConfig from 'components/hooks/useConfig'; import { ROLES } from 'lib/constants'; export function ProfileDetails() { const { user } = useUser(); const { formatMessage, labels } = useMessages(); - const { cloudMode } = useConfig(); + const cloudMode = Boolean(process.env.cloudMode); if (!user) { return null; diff --git a/src/components/pages/settings/websites/TrackingCode.js b/src/components/pages/settings/websites/TrackingCode.js index fb4eb9a9e..d22f0d59e 100644 --- a/src/components/pages/settings/websites/TrackingCode.js +++ b/src/components/pages/settings/websites/TrackingCode.js @@ -1,15 +1,19 @@ import { TextArea } from 'react-basics'; import useMessages from 'components/hooks/useMessages'; import useConfig from 'components/hooks/useConfig'; +import { useRouter } from 'next/router'; export function TrackingCode({ websiteId }) { const { formatMessage, messages } = useMessages(); - const { basePath, trackerScriptName, trackerScriptOrigin } = useConfig(); + const { basePath } = useRouter(); + const config = useConfig(); + + const trackerScriptName = + config?.trackerScriptName?.split(',')?.map(n => n.trim())?.[0] || 'script.js'; + const url = trackerScriptName?.startsWith('http') ? trackerScriptName - : `${trackerScriptOrigin || location.origin}${basePath}/${ - trackerScriptName?.split(',')?.map(n => n.trim())?.[0] || 'script.js' - }`; + : `${process.env.analyticsUrl || location.origin}${basePath}/${trackerScriptName}`; const code = ``; diff --git a/src/components/pages/websites/WebsitesPage.js b/src/components/pages/websites/WebsitesPage.js index 2eb060d31..61c29448a 100644 --- a/src/components/pages/websites/WebsitesPage.js +++ b/src/components/pages/websites/WebsitesPage.js @@ -4,7 +4,6 @@ import WebsiteAddForm from 'components/pages/settings/websites/WebsiteAddForm'; import WebsiteList from 'components/pages/settings/websites/WebsitesList'; import { useMessages } from 'components/hooks'; import useUser from 'components/hooks/useUser'; -import useConfig from 'components/hooks/useConfig'; import { ROLES } from 'lib/constants'; import { useState } from 'react'; import { @@ -24,8 +23,8 @@ export function WebsitesPage() { const [tab, setTab] = useState('my-websites'); const [fetch, setFetch] = useState(1); const { user } = useUser(); - const { cloudMode } = useConfig(); const { showToast } = useToasts(); + const cloudMode = Boolean(process.env.cloudMode); const handleSave = async () => { setFetch(fetch + 1); diff --git a/src/pages/_app.js b/src/pages/_app.js index e88b2d863..7022772c7 100644 --- a/src/pages/_app.js +++ b/src/pages/_app.js @@ -6,7 +6,6 @@ import Script from 'next/script'; import { useRouter } from 'next/router'; import ErrorBoundary from 'components/common/ErrorBoundary'; import useLocale from 'components/hooks/useLocale'; -import useConfig from 'components/hooks/useConfig'; import '@fontsource/inter/400.css'; import '@fontsource/inter/700.css'; import 'react-basics/dist/styles.css'; @@ -27,22 +26,10 @@ const client = new QueryClient({ export default function App({ Component, pageProps }) { const { locale, messages } = useLocale(); const { basePath, pathname } = useRouter(); - const config = useConfig(); - - const Wrapper = ({ children }) => {children}; - - if (config?.uiDisabled) { - return null; - } return ( - null} - > + null}> diff --git a/src/pages/api/config.ts b/src/pages/api/config.ts index bccfd0487..adba894a4 100644 --- a/src/pages/api/config.ts +++ b/src/pages/api/config.ts @@ -2,21 +2,19 @@ import { NextApiRequest, NextApiResponse } from 'next'; import { ok, methodNotAllowed } from 'next-basics'; export interface ConfigResponse { - basePath: string; - trackerScriptName: string; - updatesDisabled: boolean; telemetryDisabled: boolean; - cloudMode: boolean; + trackerScriptName: string; + uiDisabled: boolean; + updatesDisabled: boolean; } export default async (req: NextApiRequest, res: NextApiResponse) => { if (req.method === 'GET') { return ok(res, { - basePath: process.env.BASE_PATH || '', - trackerScriptName: process.env.TRACKER_SCRIPT_NAME, - updatesDisabled: !!process.env.DISABLE_UPDATES, telemetryDisabled: !!process.env.DISABLE_TELEMETRY, - cloudMode: !!process.env.CLOUD_MODE, + trackerScriptName: process.env.TRACKER_SCRIPT_NAME, + uiDisabled: !!process.env.DISABLE_UI, + updatesDisabled: !!process.env.DISABLE_UPDATES, }); } From aaaa44ee16f4ead73c6587787447a236e3348536 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Sun, 27 Aug 2023 21:59:39 -0700 Subject: [PATCH 052/113] Removed breadcrumbs. --- .../pages/settings/teams/TeamSettings.js | 14 ++------------ .../pages/settings/users/UserSettings.js | 14 ++------------ .../pages/settings/websites/WebsiteSettings.js | 13 ++----------- 3 files changed, 6 insertions(+), 35 deletions(-) diff --git a/src/components/pages/settings/teams/TeamSettings.js b/src/components/pages/settings/teams/TeamSettings.js index 245e64b1a..8c4fe8f49 100644 --- a/src/components/pages/settings/teams/TeamSettings.js +++ b/src/components/pages/settings/teams/TeamSettings.js @@ -1,6 +1,5 @@ import { useEffect, useState } from 'react'; -import { Breadcrumbs, Item, Tabs, useToasts } from 'react-basics'; -import Link from 'next/link'; +import { Item, Tabs, useToasts } from 'react-basics'; import Page from 'components/layout/Page'; import PageHeader from 'components/layout/PageHeader'; import { ROLES } from 'lib/constants'; @@ -44,16 +43,7 @@ export function TeamSettings({ teamId }) { return ( - - - {formatMessage(labels.teams)} - - {values?.name} - - } - /> + {formatMessage(labels.details)} {formatMessage(labels.members)} diff --git a/src/components/pages/settings/users/UserSettings.js b/src/components/pages/settings/users/UserSettings.js index 596e09f06..5fadf1a17 100644 --- a/src/components/pages/settings/users/UserSettings.js +++ b/src/components/pages/settings/users/UserSettings.js @@ -1,6 +1,5 @@ import { useEffect, useState } from 'react'; -import { Breadcrumbs, Item, Tabs, useToasts } from 'react-basics'; -import Link from 'next/link'; +import { Item, Tabs, useToasts } from 'react-basics'; import UserEditForm from 'components/pages/settings/users/UserEditForm'; import Page from 'components/layout/Page'; import PageHeader from 'components/layout/PageHeader'; @@ -44,16 +43,7 @@ export function UserSettings({ userId }) { return ( - - - {formatMessage(labels.users)} - - {values?.username} - - } - /> + {formatMessage(labels.details)} {formatMessage(labels.websites)} diff --git a/src/components/pages/settings/websites/WebsiteSettings.js b/src/components/pages/settings/websites/WebsiteSettings.js index ac8cd87cc..f73e0a878 100644 --- a/src/components/pages/settings/websites/WebsiteSettings.js +++ b/src/components/pages/settings/websites/WebsiteSettings.js @@ -1,5 +1,5 @@ import { useEffect, useState } from 'react'; -import { Breadcrumbs, Item, Tabs, useToasts, Button, Text, Icon, Icons } from 'react-basics'; +import { Item, Tabs, useToasts, Button, Text, Icon, Icons } from 'react-basics'; import { useRouter } from 'next/router'; import Link from 'next/link'; import Page from 'components/layout/Page'; @@ -49,16 +49,7 @@ export function WebsiteSettings({ websiteId, openExternal = false }) { return ( - - - {formatMessage(labels.websites)} - - {values?.name} - - } - > + -
+ <> + + + )} )} diff --git a/src/components/pages/dashboard/DashboardEdit.js b/src/components/pages/dashboard/DashboardEdit.js index 4eb259d61..f628599fe 100644 --- a/src/components/pages/dashboard/DashboardEdit.js +++ b/src/components/pages/dashboard/DashboardEdit.js @@ -5,23 +5,33 @@ import { Button } from 'react-basics'; import { firstBy } from 'thenby'; import useDashboard, { saveDashboard } from 'store/dashboard'; import useMessages from 'components/hooks/useMessages'; +import useApi from 'components/hooks/useApi'; import styles from './DashboardEdit.module.css'; +import Page from 'components/layout/Page'; const dragId = 'dashboard-website-ordering'; -export function DashboardEdit({ websites }) { +export function DashboardEdit() { const settings = useDashboard(); const { websiteOrder } = settings; const { formatMessage, labels } = useMessages(); const [order, setOrder] = useState(websiteOrder || []); + const { get, useQuery } = useApi(); + const { + data: result, + isLoading, + error, + } = useQuery(['websites'], () => get('/websites', { includeTeams: 1 })); + const { data: websites } = result || {}; - const ordered = useMemo( - () => - websites + const ordered = useMemo(() => { + if (websites) { + return websites .map(website => ({ ...website, order: order.indexOf(website.id) })) - .sort(firstBy('order')), - [websites, order], - ); + .sort(firstBy('order')); + } + return []; + }, [websites, order]); function handleWebsiteDrag({ destination, source }) { if (!destination || destination.index === source.index) return; @@ -49,7 +59,7 @@ export function DashboardEdit({ websites }) { } return ( - <> +
- +
); } diff --git a/src/pages/api/websites/index.ts b/src/pages/api/websites/index.ts index d724f12f4..d6009caf6 100644 --- a/src/pages/api/websites/index.ts +++ b/src/pages/api/websites/index.ts @@ -42,8 +42,13 @@ export default async ( } = req.auth; if (req.method === 'GET') { - req.query.id = userId; - req.query.pageSize = 100; + if (!req.query.id) { + req.query.id = userId; + } + + if (!req.query.pageSize) { + req.query.pageSize = 100; + } return userWebsites(req as any, res); } diff --git a/src/queries/admin/report.ts b/src/queries/admin/report.ts index a053ba92d..59eb70356 100644 --- a/src/queries/admin/report.ts +++ b/src/queries/admin/report.ts @@ -142,6 +142,7 @@ export async function getReports( ...pageFilters, ...(options?.include && { include: options.include }), }); + const count = await prisma.client.report.count({ where, }); diff --git a/src/queries/admin/team.ts b/src/queries/admin/team.ts index 284b218e2..cf731ad42 100644 --- a/src/queries/admin/team.ts +++ b/src/queries/admin/team.ts @@ -135,6 +135,7 @@ export async function getTeams( ...pageFilters, ...(options?.include && { include: options?.include }), }); + const count = await prisma.client.team.count({ where }); return { data: teams, count, ...getParameters }; diff --git a/src/queries/admin/website.ts b/src/queries/admin/website.ts index 3d0c773b6..cf4570cfc 100644 --- a/src/queries/admin/website.ts +++ b/src/queries/admin/website.ts @@ -107,7 +107,8 @@ export async function getWebsites( ...pageFilters, ...(options?.include && { include: options.include }), }); - const count = await prisma.client.website.count({ where }); + + const count = await prisma.client.website.count({ where: { ...where, deletedAt: null } }); return { data: websites, count, ...getParameters }; } From 61df80112a1396e8826a55b13319e33a925cc277 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Wed, 30 Aug 2023 15:43:39 -0700 Subject: [PATCH 067/113] Updated subdivision check. --- src/lib/detect.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/lib/detect.ts b/src/lib/detect.ts index d60435062..b16bab7ab 100644 --- a/src/lib/detect.ts +++ b/src/lib/detect.ts @@ -57,6 +57,14 @@ export function getDevice(screen, os) { } } +function getRegionCode(country, region) { + if (!country || !region) { + return undefined; + } + + return region.includes('-') ? region : `${country}-${region}`; +} + export async function getLocation(ip, req) { // Ignore local ips if (await isLocalhost(ip)) { @@ -71,7 +79,7 @@ export async function getLocation(ip, req) { return { country, - subdivision1: subdivision1?.includes('-') ? subdivision1 : `${country}-${subdivision1}`, + subdivision1: getRegionCode(country, subdivision1), city, }; } @@ -84,7 +92,7 @@ export async function getLocation(ip, req) { return { country, - subdivision1: subdivision1?.includes('-') ? subdivision1 : `${country}-${subdivision1}`, + subdivision1: getRegionCode(country, subdivision1), city, }; } From 62434a3e0ceb5eb8fd9f32701bb28c0a16a38fb6 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Wed, 30 Aug 2023 15:49:26 -0700 Subject: [PATCH 068/113] Bump version v2.6.1. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4fda0a22f..9745b780e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "umami", - "version": "2.6.0", + "version": "2.6.1", "description": "A simple, fast, privacy-focused alternative to Google Analytics.", "author": "Mike Cao ", "license": "MIT", From fac306328dd75f6a5676addae2c968a0be5a40ee Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Wed, 30 Aug 2023 16:13:05 -0700 Subject: [PATCH 069/113] Updated language. --- public/intl/messages/zh-CN.json | 60 ++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 28 deletions(-) diff --git a/public/intl/messages/zh-CN.json b/public/intl/messages/zh-CN.json index 71234564d..ec5c441b2 100644 --- a/public/intl/messages/zh-CN.json +++ b/public/intl/messages/zh-CN.json @@ -104,7 +104,7 @@ "label.browser": [ { "type": 0, - "value": "Browser" + "value": "浏览器" } ], "label.browsers": [ @@ -134,7 +134,7 @@ "label.city": [ { "type": 0, - "value": "City" + "value": "市/县" } ], "label.clear-all": [ @@ -176,7 +176,7 @@ "label.country": [ { "type": 0, - "value": "Country" + "value": "国家/地区" } ], "label.create-report": [ @@ -230,7 +230,7 @@ "label.date": [ { "type": 0, - "value": "Date" + "value": "日期" } ], "label.date-range": [ @@ -242,7 +242,7 @@ "label.day": [ { "type": 0, - "value": "Day" + "value": "日" } ], "label.default-date-range": [ @@ -296,7 +296,7 @@ "label.device": [ { "type": 0, - "value": "Device" + "value": "设备" } ], "label.devices": [ @@ -440,13 +440,13 @@ "label.is-not-set": [ { "type": 0, - "value": "Is not set" + "value": "未设置" } ], "label.is-set": [ { "type": 0, - "value": "Is set" + "value": "已设置" } ], "label.join": [ @@ -576,7 +576,7 @@ "label.my-websites": [ { "type": 0, - "value": "My websites" + "value": "我的网站" } ], "label.name": [ @@ -618,7 +618,15 @@ "label.page-of": [ { "type": 0, - "value": "Page " + "value": "总" + }, + { + "type": 1, + "value": "total" + }, + { + "type": 0, + "value": "中的第" }, { "type": 1, @@ -626,11 +634,7 @@ }, { "type": 0, - "value": " of " - }, - { - "type": 1, - "value": "total" + "value": "页" } ], "label.page-views": [ @@ -642,7 +646,7 @@ "label.pageTitle": [ { "type": 0, - "value": "Page title" + "value": "标题" } ], "label.pages": [ @@ -704,7 +708,7 @@ "label.referrer": [ { "type": 0, - "value": "Referrer" + "value": "来源" } ], "label.referrers": [ @@ -728,7 +732,7 @@ "label.region": [ { "type": 0, - "value": "Region" + "value": "州/省" } ], "label.regions": [ @@ -770,7 +774,7 @@ "label.retention": [ { "type": 0, - "value": "Retention" + "value": "保留" } ], "label.role": [ @@ -872,7 +876,7 @@ "label.team-name": [ { "type": 0, - "value": "Team name" + "value": "团队名称" } ], "label.team-owner": [ @@ -884,7 +888,7 @@ "label.team-websites": [ { "type": 0, - "value": "Team websites" + "value": "团队网站" } ], "label.teams": [ @@ -974,7 +978,7 @@ "label.unique": [ { "type": 0, - "value": "Unique" + "value": "独立" } ], "label.unique-visitors": [ @@ -998,13 +1002,13 @@ "label.url": [ { "type": 0, - "value": "URL" + "value": "网址" } ], "label.urls": [ { "type": 0, - "value": "URLs" + "value": "网址" } ], "label.user": [ @@ -1046,7 +1050,7 @@ "label.view-only": [ { "type": 0, - "value": "View only" + "value": "仅浏览量" } ], "label.views": [ @@ -1190,15 +1194,15 @@ "message.event-log": [ { "type": 1, - "value": "event" + "value": "url" }, { "type": 0, - "value": " on " + "value": "上的" }, { "type": 1, - "value": "url" + "value": "event" } ], "message.go-to-settings": [ From a7ea2027853be35254039df07422d9e89fa0607c Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Wed, 30 Aug 2023 16:33:06 -0700 Subject: [PATCH 070/113] Check for payload. --- src/pages/api/send.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/pages/api/send.ts b/src/pages/api/send.ts index a379f261f..56a748e13 100644 --- a/src/pages/api/send.ts +++ b/src/pages/api/send.ts @@ -79,6 +79,10 @@ export default async (req: NextApiRequestCollect, res: NextApiResponse) => { const { type, payload } = getJsonBody(req); + if (!type || !payload) { + return badRequest(res); + } + req.yup = schema; await useValidate(req, res); From 620011a837937226b7b25a528a411161c7f10705 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Wed, 30 Aug 2023 16:40:32 -0700 Subject: [PATCH 071/113] Removed getJsonBody. --- src/lib/detect.ts | 8 -------- src/lib/session.ts | 6 +++--- src/pages/api/send.ts | 4 ++-- 3 files changed, 5 insertions(+), 13 deletions(-) diff --git a/src/lib/detect.ts b/src/lib/detect.ts index b16bab7ab..3b2f9021a 100644 --- a/src/lib/detect.ts +++ b/src/lib/detect.ts @@ -130,11 +130,3 @@ export async function getClientInfo(req: NextApiRequestCollect, { screen }) { return { userAgent, browser, os, ip, country, subdivision1, subdivision2, city, device }; } - -export function getJsonBody(req): T { - if ((req.headers['content-type'] || '').indexOf('text/plain') !== -1) { - return JSON.parse(req.body); - } - - return req.body; -} diff --git a/src/lib/session.ts b/src/lib/session.ts index 85c173c52..0f388db9a 100644 --- a/src/lib/session.ts +++ b/src/lib/session.ts @@ -1,7 +1,7 @@ import { isUuid, secret, uuid } from 'lib/crypto'; -import { getClientInfo, getJsonBody } from 'lib/detect'; +import { getClientInfo } from 'lib/detect'; import { parseToken } from 'next-basics'; -import { CollectRequestBody, NextApiRequestCollect } from 'pages/api/send'; +import { NextApiRequestCollect } from 'pages/api/send'; import { createSession } from 'queries'; import cache from './cache'; import clickhouse from './clickhouse'; @@ -22,7 +22,7 @@ export async function findSession(req: NextApiRequestCollect): Promise<{ city: any; ownerId: string; }> { - const { payload } = getJsonBody(req); + const { payload } = req.body; if (!payload) { throw new Error('Invalid payload.'); diff --git a/src/pages/api/send.ts b/src/pages/api/send.ts index 56a748e13..e220711c8 100644 --- a/src/pages/api/send.ts +++ b/src/pages/api/send.ts @@ -3,7 +3,7 @@ import ipaddr from 'ipaddr.js'; import isbot from 'isbot'; import { COLLECTION_TYPE, HOSTNAME_REGEX } from 'lib/constants'; import { secret } from 'lib/crypto'; -import { getIpAddress, getJsonBody } from 'lib/detect'; +import { getIpAddress } from 'lib/detect'; import { useCors, useSession, useValidate } from 'lib/middleware'; import { CollectionType, YupRequest } from 'lib/types'; import { NextApiRequest, NextApiResponse } from 'next'; @@ -77,7 +77,7 @@ export default async (req: NextApiRequestCollect, res: NextApiResponse) => { return ok(res); } - const { type, payload } = getJsonBody(req); + const { type, payload } = req.body; if (!type || !payload) { return badRequest(res); From 68ffa823f8a27490b6005a84e44be0d95e2e767c Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Wed, 30 Aug 2023 23:53:05 -0700 Subject: [PATCH 072/113] Fixed missing docker middleware. --- Dockerfile | 2 +- src/pages/api/send.ts | 124 +++++++++++++++++++++--------------------- 2 files changed, 63 insertions(+), 63 deletions(-) diff --git a/Dockerfile b/Dockerfile index bdc678dac..e0c7e8c37 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,8 +12,8 @@ RUN yarn install --frozen-lockfile FROM node:18-alpine AS builder WORKDIR /app COPY --from=deps /app/node_modules ./node_modules -COPY docker/middleware.js . COPY . . +COPY docker/middleware.js ./src ARG DATABASE_TYPE ARG BASE_PATH diff --git a/src/pages/api/send.ts b/src/pages/api/send.ts index e220711c8..00d721046 100644 --- a/src/pages/api/send.ts +++ b/src/pages/api/send.ts @@ -7,7 +7,7 @@ import { getIpAddress } from 'lib/detect'; import { useCors, useSession, useValidate } from 'lib/middleware'; import { CollectionType, YupRequest } from 'lib/types'; import { NextApiRequest, NextApiResponse } from 'next'; -import { badRequest, createToken, forbidden, ok, send } from 'next-basics'; +import { badRequest, createToken, forbidden, methodNotAllowed, ok, send } from 'next-basics'; import { saveEvent, saveSessionData } from 'queries'; import * as yup from 'yup'; @@ -73,75 +73,75 @@ const schema = { export default async (req: NextApiRequestCollect, res: NextApiResponse) => { await useCors(req, res); - if (isbot(req.headers['user-agent']) && !process.env.DISABLE_BOT_CHECK) { - return ok(res); - } - - const { type, payload } = req.body; - - if (!type || !payload) { - return badRequest(res); - } - - req.yup = schema; - await useValidate(req, res); - - if (await hasBlockedIp(req)) { - return forbidden(res); - } - - const { url, referrer, name: eventName, data: eventData, title: pageTitle } = payload; - - await useSession(req, res); - - const session = req.session; - - if (type === COLLECTION_TYPE.event) { - // eslint-disable-next-line prefer-const - let [urlPath, urlQuery] = url?.split('?') || []; - let [referrerPath, referrerQuery] = referrer?.split('?') || []; - let referrerDomain; - - if (!urlPath) { - urlPath = '/'; + if (req.method === 'POST') { + if (isbot(req.headers['user-agent']) && !process.env.DISABLE_BOT_CHECK) { + return ok(res); } - if (referrerPath?.startsWith('http')) { - const refUrl = new URL(referrer); - referrerPath = refUrl.pathname; - referrerQuery = refUrl.search.substring(1); - referrerDomain = refUrl.hostname.replace(/www\./, ''); + const { type, payload } = req.body; + + req.yup = schema; + await useValidate(req, res); + + if (await hasBlockedIp(req)) { + return forbidden(res); } - if (process.env.REMOVE_TRAILING_SLASH) { - urlPath = urlPath.replace(/.+\/$/, ''); + const { url, referrer, name: eventName, data: eventData, title: pageTitle } = payload; + + await useSession(req, res); + + const session = req.session; + + if (type === COLLECTION_TYPE.event) { + // eslint-disable-next-line prefer-const + let [urlPath, urlQuery] = url?.split('?') || []; + let [referrerPath, referrerQuery] = referrer?.split('?') || []; + let referrerDomain; + + if (!urlPath) { + urlPath = '/'; + } + + if (referrerPath?.startsWith('http')) { + const refUrl = new URL(referrer); + referrerPath = refUrl.pathname; + referrerQuery = refUrl.search.substring(1); + referrerDomain = refUrl.hostname.replace(/www\./, ''); + } + + if (process.env.REMOVE_TRAILING_SLASH) { + urlPath = urlPath.replace(/.+\/$/, ''); + } + + await saveEvent({ + urlPath, + urlQuery, + referrerPath, + referrerQuery, + referrerDomain, + pageTitle, + eventName, + eventData, + ...session, + sessionId: session.id, + }); } - await saveEvent({ - urlPath, - urlQuery, - referrerPath, - referrerQuery, - referrerDomain, - pageTitle, - eventName, - eventData, - ...session, - sessionId: session.id, - }); + if (type === COLLECTION_TYPE.identify) { + if (!eventData) { + return badRequest(res, 'Data required.'); + } + + await saveSessionData({ ...session, sessionData: eventData, sessionId: session.id }); + } + + const token = createToken(session, secret()); + + return send(res, token); } - if (type === COLLECTION_TYPE.identify) { - if (!eventData) { - return badRequest(res, 'Data required.'); - } - - await saveSessionData({ ...session, sessionData: eventData, sessionId: session.id }); - } - - const token = createToken(session, secret()); - - return send(res, token); + return methodNotAllowed(res); }; async function hasBlockedIp(req: NextApiRequestCollect) { From 5b7cfe83b483b1f6bb83c094a02322867f36c3dd Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Thu, 31 Aug 2023 00:08:24 -0700 Subject: [PATCH 073/113] Fixed update notice. --- src/components/common/UpdateNotice.js | 6 ++++-- src/components/common/UpdateNotice.module.css | 5 +++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/components/common/UpdateNotice.js b/src/components/common/UpdateNotice.js index e3edc70c1..23907948c 100644 --- a/src/components/common/UpdateNotice.js +++ b/src/components/common/UpdateNotice.js @@ -1,4 +1,5 @@ import { useEffect, useCallback, useState } from 'react'; +import { createPortal } from 'react-dom'; import { Button, Row, Column } from 'react-basics'; import { setItem } from 'next-basics'; import useStore, { checkVersion } from 'store/version'; @@ -44,7 +45,7 @@ export function UpdateNotice({ user, config }) { return null; } - return ( + return createPortal( {formatMessage(messages.newVersionAvailable, { version: `v${latest}` })} @@ -55,7 +56,8 @@ export function UpdateNotice({ user, config }) { - + , + document.body, ); } diff --git a/src/components/common/UpdateNotice.module.css b/src/components/common/UpdateNotice.module.css index db7a0abdc..261a31698 100644 --- a/src/components/common/UpdateNotice.module.css +++ b/src/components/common/UpdateNotice.module.css @@ -2,13 +2,14 @@ position: absolute; max-width: 800px; gap: 20px; - margin: 20px auto; - justify-self: center; + margin: 80px auto; + align-self: center; background: var(--base50); padding: 20px; border: 1px solid var(--base300); border-radius: var(--border-radius); z-index: var(--z-index-popup); + box-shadow: 4px 4px 8px rgba(0, 0, 0, 0.1); } .message { From aa5c84a6efea4a94af4052e8bf915940575b6f86 Mon Sep 17 00:00:00 2001 From: anzepintar Date: Thu, 31 Aug 2023 11:24:28 +0200 Subject: [PATCH 074/113] Update sl-SI.json --- src/lang/sl-SI.json | 306 ++++++++++++++++++++++---------------------- 1 file changed, 153 insertions(+), 153 deletions(-) diff --git a/src/lang/sl-SI.json b/src/lang/sl-SI.json index aae7888d8..4e7e4ad95 100644 --- a/src/lang/sl-SI.json +++ b/src/lang/sl-SI.json @@ -1,211 +1,211 @@ { - "label.access-code": "Access code", + "label.access-code": "Koda za dostop", "label.actions": "Dejanja", - "label.activity-log": "Activity log", - "label.add": "Add", - "label.add-description": "Add description", + "label.activity-log": "Dnevnik dejavnosti", + "label.add": "Dodaj", + "label.add-description": "Dodaj opis", "label.add-website": "Dodaj spletno mesto", "label.admin": "Administrator", - "label.after": "After", - "label.all": "Vse", - "label.all-time": "All time", - "label.analytics": "Analytics", - "label.average": "Average", + "label.after": "Po", + "label.all": "Vsi", + "label.all-time": "Ves čas", + "label.analytics": "Analitika", + "label.average": "Povprečno", "label.average-visit-time": "Povprečni čas obiska", "label.back": "Nazaj", - "label.before": "Before", - "label.bounce-rate": "Zapustna stopnja", - "label.breakdown": "Breakdown", - "label.browser": "Browser", + "label.before": "Pred", + "label.bounce-rate": "Odbojna stopnja", + "label.breakdown": "Razčlenitev", + "label.browser": "Brskalnik", "label.browsers": "Brskalniki", "label.cancel": "Prekliči", "label.change-password": "Zamenjaj geslo", - "label.cities": "Cities", - "label.city": "City", - "label.clear-all": "Clear all", - "label.confirm": "Confirm", - "label.confirm-password": "Potrditev gesla", - "label.contains": "Contains", - "label.continue": "Continue", + "label.cities": "Mesta", + "label.city": "Mesto", + "label.clear-all": "Počisti vse", + "label.confirm": "Potrdi", + "label.confirm-password": "Potrdi geslo", + "label.contains": "Vsebuje", + "label.continue": "Nadaljuj", "label.countries": "Države", - "label.country": "Country", - "label.create-report": "Create report", - "label.create-team": "Create team", - "label.create-user": "Create user", - "label.created": "Created", + "label.country": "Država", + "label.create-report": "Ustvari poročilo", + "label.create-team": "Ustvari ekipo", + "label.create-user": "Ustvari uporabnika", + "label.created": "Ustvarjeno", "label.current-password": "Trenutno geslo", - "label.custom-range": "Razpon po meri", + "label.custom-range": "Obdobje po meri", "label.dashboard": "Nadzorna plošča", - "label.data": "Data", - "label.date": "Date", - "label.date-range": "Časovni razpon", - "label.day": "Day", - "label.default-date-range": "Privzeti časovni razpon", + "label.data": "Podatki", + "label.date": "Datum", + "label.date-range": "Časovno obdobje", + "label.day": "Dan", + "label.default-date-range": "Privzeto časovno obdobje", "label.delete": "Izbriši", - "label.delete-team": "Delete team", - "label.delete-user": "Delete user", + "label.delete-team": "Izbriši ekipo", + "label.delete-user": "Izbriši uporabnika", "label.delete-website": "Izbriši spletno mesto", - "label.description": "Description", + "label.description": "Opis", "label.desktop": "Namizni računalnik", - "label.details": "Details", - "label.device": "Device", + "label.details": "Podrobnosti", + "label.device": "Naprava", "label.devices": "Naprave", - "label.dismiss": "Opusti", - "label.does-not-contain": "Does not contain", + "label.dismiss": "Prezri", + "label.does-not-contain": "Ne vsebuje", "label.domain": "Domena", - "label.dropoff": "Dropoff", + "label.dropoff": "Zapustitev", "label.edit": "Uredi", - "label.edit-dashboard": "Edit dashboard", - "label.enable-share-url": "Omogoči URL za skupno rabo", - "label.event": "Event", - "label.event-data": "Event data", + "label.edit-dashboard": "Uredi nadzorno ploščo", + "label.enable-share-url": "Uredi povezavo za deljenje", + "label.event": "Dogodek", + "label.event-data": "Podatki dogodka", "label.events": "Dogodki", - "label.false": "False", - "label.field": "Field", - "label.fields": "Fields", - "label.filter-combined": "Skupno", - "label.filter-raw": "Neobdelane meritve", - "label.filters": "Filters", - "label.funnel": "Funnel", - "label.greater-than": "Greater than", - "label.greater-than-equals": "Greater than or equals", - "label.insights": "Insights", - "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.languages": "Languages", + "label.false": "Napačno", + "label.field": "Polje", + "label.fields": "Polja", + "label.filter-combined": "Skupaj", + "label.filter-raw": "Neobdelano", + "label.filters": "Filtri", + "label.funnel": "Prodajni lijak", + "label.greater-than": "Večje od", + "label.greater-than-equals": "Večje ali enako kot", + "label.insights": "Vpogled", + "label.is": "Je", + "label.is-not": "Ni", + "label.is-not-set": "Ni nastavljeno", + "label.is-set": "Je nastavljeno", + "label.join": "Pridruži se", + "label.join-team": "Pridruži se ekipi", + "label.language": "Jezik", + "label.languages": "Jeziki", "label.laptop": "Prenosni računalnik", "label.last-days": "Zadnjih {x} dni", "label.last-hours": "Zadnjih {x} ur", - "label.leave": "Leave", - "label.leave-team": "Leave team", - "label.less-than": "Less than", - "label.less-than-equals": "Less than or equals", + "label.leave": "Zapusti", + "label.leave-team": "Zapusti ekipo", + "label.less-than": "Manjše kot", + "label.less-than-equals": "Manjše ali enako kot", "label.login": "Prijava", "label.logout": "Odjava", - "label.max": "Max", - "label.members": "Members", - "label.min": "Min", - "label.mobile": "Mobilni telefon", + "label.max": "Največ", + "label.members": "Člani", + "label.min": "Najmanj", + "label.mobile": "Mobilne naprave", "label.more": "Več", - "label.my-websites": "My websites", + "label.my-websites": "Moja spletna mesta", "label.name": "Ime", "label.new-password": "Novo geslo", - "label.none": "None", + "label.none": "Brez", "label.os": "OS", - "label.overview": "Overview", - "label.owner": "Owner", - "label.page-of": "Page {current} of {total}", - "label.page-views": "Ogledi strani", - "label.pageTitle": "Page title", + "label.overview": "Pregled", + "label.owner": "Lastnik", + "label.page-of": "Stran {current} od {total}", + "label.page-views": "Obiski strani", + "label.pageTitle": "Naslov strani", "label.pages": "Strani", "label.password": "Geslo", - "label.powered-by": "Zagotavlja {name}", + "label.powered-by": "Poganja {name}", "label.profile": "Profil", - "label.queries": "Queries", - "label.query": "Query", - "label.query-parameters": "Query parameters", - "label.realtime": "V realnem času", - "label.referrer": "Referrer", + "label.queries": "Poizvedbe", + "label.query": "Poizvedba", + "label.query-parameters": "Parametri poizvedbe", + "label.realtime": "V živo", + "label.referrer": "Vir", "label.referrers": "Viri", "label.refresh": "Osveži", - "label.regenerate": "Regenerate", - "label.region": "Region", - "label.regions": "Regions", - "label.remove": "Remove", - "label.reports": "Reports", + "label.regenerate": "Ponovno generiraj", + "label.region": "Regija", + "label.regions": "Regije", + "label.remove": "Odstrani", + "label.reports": "Poročila", "label.required": "Zahtevano", "label.reset": "Ponastavi", - "label.reset-website": "Reset statistics", - "label.retention": "Retention", - "label.role": "Role", - "label.run-query": "Run query", + "label.reset-website": "Ponastavi statistiko", + "label.retention": "Ohranjanje uporabnikov", + "label.role": "Vloga", + "label.run-query": "Izvedi poizvedbo", "label.save": "Shrani", - "label.screens": "Screens", - "label.select-date": "Select date", - "label.select-website": "Select website", - "label.sessions": "Sessions", + "label.screens": "Zasloni", + "label.select-date": "Izberi datum", + "label.select-website": "Izberi spletno mesto", + "label.sessions": "Seje", "label.settings": "Nastavitve", - "label.share-url": "Deli URL", + "label.share-url": "Deli povezavo", "label.single-day": "En dan", - "label.sum": "Sum", + "label.sum": "Seštevek", "label.tablet": "Tablični računalnik", - "label.team": "Team", - "label.team-guest": "Team guest", - "label.team-id": "Team ID", - "label.team-member": "Team member", - "label.team-name": "Team name", - "label.team-owner": "Team owner", - "label.team-websites": "Team websites", - "label.teams": "Teams", - "label.theme": "Theme", + "label.team": "Ekipa", + "label.team-guest": "Gost ekipe", + "label.team-id": "ID ekipe", + "label.team-member": "Član ekipe", + "label.team-name": "Ime ekipe", + "label.team-owner": "Lastnik ekipe", + "label.team-websites": "Spletna mesta ekipe", + "label.teams": "Ekipe", + "label.theme": "Tema", "label.this-month": "Ta mesec", "label.this-week": "Ta teden", - "label.this-year": "Letos", + "label.this-year": "To leto", "label.timezone": "Časovni pas", - "label.title": "Title", + "label.title": "Naslov", "label.today": "Danes", - "label.toggle-charts": "Toggle charts", - "label.total": "Total", - "label.total-records": "Total records", + "label.toggle-charts": "Preklopi grafe", + "label.total": "Skupaj", + "label.total-records": "Skupni zapisi", "label.tracking-code": "Koda za sledenje", - "label.true": "True", - "label.type": "Type", - "label.unique": "Unique", + "label.true": "Pravilno", + "label.type": "Vrsta", + "label.unique": "Unikatni", "label.unique-visitors": "Unikatni obiskovalci", "label.unknown": "Neznano", - "label.untitled": "Untitled", - "label.url": "URL", - "label.urls": "URLs", - "label.user": "User", + "label.untitled": "Brez naslova", + "label.url": "Povezava", + "label.urls": "Povezave", + "label.user": "Uporabnik", "label.username": "Uporabniško ime", - "label.users": "Users", - "label.value": "Value", - "label.view": "View", - "label.view-details": "Prikaži podrobnosti", - "label.view-only": "View only", - "label.views": "Ogledi", + "label.users": "Uporabniki", + "label.value": "Vrednost", + "label.view": "Poglej", + "label.view-details": "Poglej podrobnosti", + "label.view-only": "Samo ogledovanje", + "label.views": "Obiski", "label.visitors": "Obiskovalci", - "label.website": "Website", - "label.website-id": "Website ID", - "label.websites": "Spletna mesta", - "label.window": "Window", - "label.yesterday": "Yesterday", - "message.active-users": "{x} trenutni {x, plural, one {obiskovalec} other {obiskovalcev}}", + "label.website": "Spletno mesto", + "label.website-id": "ID spletnega mesta", + "label.websites": "Spletnih mest", + "label.window": "Okno", + "label.yesterday": "Včeraj", + "message.active-users": "{x} trenutni {x, plural, one {visitor} ostali {visitors}}", "message.confirm-delete": "Ste prepričani, da želite izbrisati {target}?", - "message.confirm-leave": "Are you sure you want to leave {target}?", - "message.confirm-reset": "Are your sure you want to reset {target}'s statistics?", - "message.delete-account": "To delete this account, type {confirmation} in the box below to confirm.", - "message.delete-website": "To delete this website, type {confirmation} in the box below to confirm.", - "message.delete-website-warning": "Izbrisani bodo tudi vsi povezani podatki.", - "message.error": "Prišlo je do napake.", - "message.event-log": "{event} on {url}", + "message.confirm-leave": "Ste prepričani, da želite zapustiti {target}?", + "message.confirm-reset": "Ste prepričani, da želite ponastaviti statistiko {target}?", + "message.delete-account": "Za potrditev izbrisa tega računa vnesite {confirmation} v spodnje polje.", + "message.delete-website": "Za potrditev izbrisa tega spletnega mesta vnesite {confirmation} v spodnje polje.", + "message.delete-website-warning": "Izbrisani bodo tudi vsi pripadajoči podatki.", + "message.error": "Nekaj je šlo narobe.", + "message.event-log": "{event} na {url}", "message.go-to-settings": "Pojdi v nastavitve", - "message.incorrect-username-password": "Nepravilno uporabniško ime/geslo", + "message.incorrect-username-password": "Nepravilno uporabniško ime/geslo.", "message.invalid-domain": "Neveljavna domena", - "message.min-password-length": "Minimum length of {n} characters", - "message.new-version-available": "A new version of Umami {version} is available!", + "message.min-password-length": "Najmanjša dolžina je {n} znakov", + "message.new-version-available": "Na voljo je nova verzija programa Umami {version}!", "message.no-data-available": "Podatki niso na voljo.", - "message.no-event-data": "No event data is available.", + "message.no-event-data": "Podatki o dogodku niso na voljo.", "message.no-match-password": "Gesli se ne ujemata", - "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-websites-configured": "Ni nastavljenih spletnih mest.", + "message.no-results-found": "Rezultatov ni bilo mogoče najti.", + "message.no-team-websites": "Ta ekipa nima spletnih mest.", + "message.no-teams": "Niste še ustvarili nobene ekipe.", + "message.no-users": "Ni uporabnikov.", + "message.no-websites-configured": "Nimate nastavljenih nobenih spletnih mest.", "message.page-not-found": "Stran ni bila najdena.", - "message.reset-website": "To reset this website, type {confirmation} in the box below to confirm.", - "message.reset-website-warning": "All statistics for this website will be deleted, but your tracking code will remain intact.", + "message.reset-website": "Za ponastavitev izbrisa tega spletnega mesta vnesite {confirmation} v spodnje polje.", + "message.reset-website-warning": "Vse statistike za to spletno mesto bodo izbrisane, koda za sledenje pa bo ostala nespremenjena.", "message.saved": "Uspešno shranjeno.", - "message.share-url": "To je javno dostopen naslov URL za {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.share-url": "To je javno dostopna povezava za {target}.", + "message.team-already-member": "Ste že član ekipe.", + "message.team-not-found": "Ekipa ni bila najdena.", + "message.team-websites-info": "Spletne strani si lahko ogleda vsak član ekipe.", "message.tracking-code": "Koda za sledenje", - "message.user-deleted": "User deleted.", + "message.user-deleted": "Uporabnik je izbrisan.", "message.visitor-log": "Obiskovalec iz {country} uporablja {browser} na {os} {device}" } From 338d1c62ea7c978beeb6570793d9be70a214487b Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Thu, 31 Aug 2023 14:32:59 -0700 Subject: [PATCH 075/113] Updated language files. --- public/intl/messages/sl-SI.json | 318 ++++++++++++++++---------------- src/lang/sl-SI.json | 2 +- 2 files changed, 160 insertions(+), 160 deletions(-) diff --git a/public/intl/messages/sl-SI.json b/public/intl/messages/sl-SI.json index a3af95cb8..ee62a3153 100644 --- a/public/intl/messages/sl-SI.json +++ b/public/intl/messages/sl-SI.json @@ -2,7 +2,7 @@ "label.access-code": [ { "type": 0, - "value": "Access code" + "value": "Koda za dostop" } ], "label.actions": [ @@ -14,19 +14,19 @@ "label.activity-log": [ { "type": 0, - "value": "Activity log" + "value": "Dnevnik dejavnosti" } ], "label.add": [ { "type": 0, - "value": "Add" + "value": "Dodaj" } ], "label.add-description": [ { "type": 0, - "value": "Add description" + "value": "Dodaj opis" } ], "label.add-website": [ @@ -44,31 +44,31 @@ "label.after": [ { "type": 0, - "value": "After" + "value": "Po" } ], "label.all": [ { "type": 0, - "value": "Vse" + "value": "Vsi" } ], "label.all-time": [ { "type": 0, - "value": "All time" + "value": "Ves čas" } ], "label.analytics": [ { "type": 0, - "value": "Analytics" + "value": "Analitika" } ], "label.average": [ { "type": 0, - "value": "Average" + "value": "Povprečno" } ], "label.average-visit-time": [ @@ -86,25 +86,25 @@ "label.before": [ { "type": 0, - "value": "Before" + "value": "Pred" } ], "label.bounce-rate": [ { "type": 0, - "value": "Zapustna stopnja" + "value": "Odbojna stopnja" } ], "label.breakdown": [ { "type": 0, - "value": "Breakdown" + "value": "Razčlenitev" } ], "label.browser": [ { "type": 0, - "value": "Browser" + "value": "Brskalnik" } ], "label.browsers": [ @@ -128,43 +128,43 @@ "label.cities": [ { "type": 0, - "value": "Cities" + "value": "Mesta" } ], "label.city": [ { "type": 0, - "value": "City" + "value": "Mesto" } ], "label.clear-all": [ { "type": 0, - "value": "Clear all" + "value": "Počisti vse" } ], "label.confirm": [ { "type": 0, - "value": "Confirm" + "value": "Potrdi" } ], "label.confirm-password": [ { "type": 0, - "value": "Potrditev gesla" + "value": "Potrdi geslo" } ], "label.contains": [ { "type": 0, - "value": "Contains" + "value": "Vsebuje" } ], "label.continue": [ { "type": 0, - "value": "Continue" + "value": "Nadaljuj" } ], "label.countries": [ @@ -176,31 +176,31 @@ "label.country": [ { "type": 0, - "value": "Country" + "value": "Država" } ], "label.create-report": [ { "type": 0, - "value": "Create report" + "value": "Ustvari poročilo" } ], "label.create-team": [ { "type": 0, - "value": "Create team" + "value": "Ustvari ekipo" } ], "label.create-user": [ { "type": 0, - "value": "Create user" + "value": "Ustvari uporabnika" } ], "label.created": [ { "type": 0, - "value": "Created" + "value": "Ustvarjeno" } ], "label.current-password": [ @@ -212,7 +212,7 @@ "label.custom-range": [ { "type": 0, - "value": "Razpon po meri" + "value": "Obdobje po meri" } ], "label.dashboard": [ @@ -224,31 +224,31 @@ "label.data": [ { "type": 0, - "value": "Data" + "value": "Podatki" } ], "label.date": [ { "type": 0, - "value": "Date" + "value": "Datum" } ], "label.date-range": [ { "type": 0, - "value": "Časovni razpon" + "value": "Časovno obdobje" } ], "label.day": [ { "type": 0, - "value": "Day" + "value": "Dan" } ], "label.default-date-range": [ { "type": 0, - "value": "Privzeti časovni razpon" + "value": "Privzeto časovno obdobje" } ], "label.delete": [ @@ -260,13 +260,13 @@ "label.delete-team": [ { "type": 0, - "value": "Delete team" + "value": "Izbriši ekipo" } ], "label.delete-user": [ { "type": 0, - "value": "Delete user" + "value": "Izbriši uporabnika" } ], "label.delete-website": [ @@ -278,7 +278,7 @@ "label.description": [ { "type": 0, - "value": "Description" + "value": "Opis" } ], "label.desktop": [ @@ -290,13 +290,13 @@ "label.details": [ { "type": 0, - "value": "Details" + "value": "Podrobnosti" } ], "label.device": [ { "type": 0, - "value": "Device" + "value": "Naprava" } ], "label.devices": [ @@ -308,13 +308,13 @@ "label.dismiss": [ { "type": 0, - "value": "Opusti" + "value": "Prezri" } ], "label.does-not-contain": [ { "type": 0, - "value": "Does not contain" + "value": "Ne vsebuje" } ], "label.domain": [ @@ -326,7 +326,7 @@ "label.dropoff": [ { "type": 0, - "value": "Dropoff" + "value": "Zapustitev" } ], "label.edit": [ @@ -338,25 +338,25 @@ "label.edit-dashboard": [ { "type": 0, - "value": "Edit dashboard" + "value": "Uredi nadzorno ploščo" } ], "label.enable-share-url": [ { "type": 0, - "value": "Omogoči URL za skupno rabo" + "value": "Uredi povezavo za deljenje" } ], "label.event": [ { "type": 0, - "value": "Event" + "value": "Dogodek" } ], "label.event-data": [ { "type": 0, - "value": "Event data" + "value": "Podatki dogodka" } ], "label.events": [ @@ -368,109 +368,109 @@ "label.false": [ { "type": 0, - "value": "False" + "value": "Napačno" } ], "label.field": [ { "type": 0, - "value": "Field" + "value": "Polje" } ], "label.fields": [ { "type": 0, - "value": "Fields" + "value": "Polja" } ], "label.filter-combined": [ { "type": 0, - "value": "Skupno" + "value": "Skupaj" } ], "label.filter-raw": [ { "type": 0, - "value": "Neobdelane meritve" + "value": "Neobdelano" } ], "label.filters": [ { "type": 0, - "value": "Filters" + "value": "Filtri" } ], "label.funnel": [ { "type": 0, - "value": "Funnel" + "value": "Prodajni lijak" } ], "label.greater-than": [ { "type": 0, - "value": "Greater than" + "value": "Večje od" } ], "label.greater-than-equals": [ { "type": 0, - "value": "Greater than or equals" + "value": "Večje ali enako kot" } ], "label.insights": [ { "type": 0, - "value": "Insights" + "value": "Vpogled" } ], "label.is": [ { "type": 0, - "value": "Is" + "value": "Je" } ], "label.is-not": [ { "type": 0, - "value": "Is not" + "value": "Ni" } ], "label.is-not-set": [ { "type": 0, - "value": "Is not set" + "value": "Ni nastavljeno" } ], "label.is-set": [ { "type": 0, - "value": "Is set" + "value": "Je nastavljeno" } ], "label.join": [ { "type": 0, - "value": "Join" + "value": "Pridruži se" } ], "label.join-team": [ { "type": 0, - "value": "Join team" + "value": "Pridruži se ekipi" } ], "label.language": [ { "type": 0, - "value": "Language" + "value": "Jezik" } ], "label.languages": [ { "type": 0, - "value": "Languages" + "value": "Jeziki" } ], "label.laptop": [ @@ -510,25 +510,25 @@ "label.leave": [ { "type": 0, - "value": "Leave" + "value": "Zapusti" } ], "label.leave-team": [ { "type": 0, - "value": "Leave team" + "value": "Zapusti ekipo" } ], "label.less-than": [ { "type": 0, - "value": "Less than" + "value": "Manjše kot" } ], "label.less-than-equals": [ { "type": 0, - "value": "Less than or equals" + "value": "Manjše ali enako kot" } ], "label.login": [ @@ -546,25 +546,25 @@ "label.max": [ { "type": 0, - "value": "Max" + "value": "Največ" } ], "label.members": [ { "type": 0, - "value": "Members" + "value": "Člani" } ], "label.min": [ { "type": 0, - "value": "Min" + "value": "Najmanj" } ], "label.mobile": [ { "type": 0, - "value": "Mobilni telefon" + "value": "Mobilne naprave" } ], "label.more": [ @@ -576,7 +576,7 @@ "label.my-websites": [ { "type": 0, - "value": "My websites" + "value": "Moja spletna mesta" } ], "label.name": [ @@ -594,7 +594,7 @@ "label.none": [ { "type": 0, - "value": "None" + "value": "Brez" } ], "label.os": [ @@ -606,19 +606,19 @@ "label.overview": [ { "type": 0, - "value": "Overview" + "value": "Pregled" } ], "label.owner": [ { "type": 0, - "value": "Owner" + "value": "Lastnik" } ], "label.page-of": [ { "type": 0, - "value": "Page " + "value": "Stran " }, { "type": 1, @@ -626,7 +626,7 @@ }, { "type": 0, - "value": " of " + "value": " od " }, { "type": 1, @@ -636,13 +636,13 @@ "label.page-views": [ { "type": 0, - "value": "Ogledi strani" + "value": "Obiski strani" } ], "label.pageTitle": [ { "type": 0, - "value": "Page title" + "value": "Naslov strani" } ], "label.pages": [ @@ -660,7 +660,7 @@ "label.powered-by": [ { "type": 0, - "value": "Zagotavlja " + "value": "Poganja " }, { "type": 1, @@ -676,31 +676,31 @@ "label.queries": [ { "type": 0, - "value": "Queries" + "value": "Poizvedbe" } ], "label.query": [ { "type": 0, - "value": "Query" + "value": "Poizvedba" } ], "label.query-parameters": [ { "type": 0, - "value": "Query parameters" + "value": "Parametri poizvedbe" } ], "label.realtime": [ { "type": 0, - "value": "V realnem času" + "value": "V živo" } ], "label.referrer": [ { "type": 0, - "value": "Referrer" + "value": "Vir" } ], "label.referrers": [ @@ -718,31 +718,31 @@ "label.regenerate": [ { "type": 0, - "value": "Regenerate" + "value": "Ponovno generiraj" } ], "label.region": [ { "type": 0, - "value": "Region" + "value": "Regija" } ], "label.regions": [ { "type": 0, - "value": "Regions" + "value": "Regije" } ], "label.remove": [ { "type": 0, - "value": "Remove" + "value": "Odstrani" } ], "label.reports": [ { "type": 0, - "value": "Reports" + "value": "Poročila" } ], "label.required": [ @@ -760,25 +760,25 @@ "label.reset-website": [ { "type": 0, - "value": "Reset statistics" + "value": "Ponastavi statistiko" } ], "label.retention": [ { "type": 0, - "value": "Retention" + "value": "Ohranjanje uporabnikov" } ], "label.role": [ { "type": 0, - "value": "Role" + "value": "Vloga" } ], "label.run-query": [ { "type": 0, - "value": "Run query" + "value": "Izvedi poizvedbo" } ], "label.save": [ @@ -790,25 +790,25 @@ "label.screens": [ { "type": 0, - "value": "Screens" + "value": "Zasloni" } ], "label.select-date": [ { "type": 0, - "value": "Select date" + "value": "Izberi datum" } ], "label.select-website": [ { "type": 0, - "value": "Select website" + "value": "Izberi spletno mesto" } ], "label.sessions": [ { "type": 0, - "value": "Sessions" + "value": "Seje" } ], "label.settings": [ @@ -820,7 +820,7 @@ "label.share-url": [ { "type": 0, - "value": "Deli URL" + "value": "Deli povezavo" } ], "label.single-day": [ @@ -832,7 +832,7 @@ "label.sum": [ { "type": 0, - "value": "Sum" + "value": "Seštevek" } ], "label.tablet": [ @@ -844,55 +844,55 @@ "label.team": [ { "type": 0, - "value": "Team" + "value": "Ekipa" } ], "label.team-guest": [ { "type": 0, - "value": "Team guest" + "value": "Gost ekipe" } ], "label.team-id": [ { "type": 0, - "value": "Team ID" + "value": "ID ekipe" } ], "label.team-member": [ { "type": 0, - "value": "Team member" + "value": "Član ekipe" } ], "label.team-name": [ { "type": 0, - "value": "Team name" + "value": "Ime ekipe" } ], "label.team-owner": [ { "type": 0, - "value": "Team owner" + "value": "Lastnik ekipe" } ], "label.team-websites": [ { "type": 0, - "value": "Team websites" + "value": "Spletna mesta ekipe" } ], "label.teams": [ { "type": 0, - "value": "Teams" + "value": "Ekipe" } ], "label.theme": [ { "type": 0, - "value": "Theme" + "value": "Tema" } ], "label.this-month": [ @@ -910,7 +910,7 @@ "label.this-year": [ { "type": 0, - "value": "Letos" + "value": "To leto" } ], "label.timezone": [ @@ -922,7 +922,7 @@ "label.title": [ { "type": 0, - "value": "Title" + "value": "Naslov" } ], "label.today": [ @@ -934,19 +934,19 @@ "label.toggle-charts": [ { "type": 0, - "value": "Toggle charts" + "value": "Preklopi grafe" } ], "label.total": [ { "type": 0, - "value": "Total" + "value": "Skupaj" } ], "label.total-records": [ { "type": 0, - "value": "Total records" + "value": "Skupni zapisi" } ], "label.tracking-code": [ @@ -958,19 +958,19 @@ "label.true": [ { "type": 0, - "value": "True" + "value": "Pravilno" } ], "label.type": [ { "type": 0, - "value": "Type" + "value": "Vrsta" } ], "label.unique": [ { "type": 0, - "value": "Unique" + "value": "Unikatni" } ], "label.unique-visitors": [ @@ -988,25 +988,25 @@ "label.untitled": [ { "type": 0, - "value": "Untitled" + "value": "Brez naslova" } ], "label.url": [ { "type": 0, - "value": "URL" + "value": "Povezava" } ], "label.urls": [ { "type": 0, - "value": "URLs" + "value": "Povezave" } ], "label.user": [ { "type": 0, - "value": "User" + "value": "Uporabnik" } ], "label.username": [ @@ -1018,37 +1018,37 @@ "label.users": [ { "type": 0, - "value": "Users" + "value": "Uporabniki" } ], "label.value": [ { "type": 0, - "value": "Value" + "value": "Vrednost" } ], "label.view": [ { "type": 0, - "value": "View" + "value": "Poglej" } ], "label.view-details": [ { "type": 0, - "value": "Prikaži podrobnosti" + "value": "Poglej podrobnosti" } ], "label.view-only": [ { "type": 0, - "value": "View only" + "value": "Samo ogledovanje" } ], "label.views": [ { "type": 0, - "value": "Ogledi" + "value": "Obiski" } ], "label.visitors": [ @@ -1060,31 +1060,31 @@ "label.website": [ { "type": 0, - "value": "Website" + "value": "Spletno mesto" } ], "label.website-id": [ { "type": 0, - "value": "Website ID" + "value": "ID spletnega mesta" } ], "label.websites": [ { "type": 0, - "value": "Spletna mesta" + "value": "Spletnih mest" } ], "label.window": [ { "type": 0, - "value": "Window" + "value": "Okno" } ], "label.yesterday": [ { "type": 0, - "value": "Yesterday" + "value": "Včeraj" } ], "message.active-users": [ @@ -1138,7 +1138,7 @@ "message.confirm-leave": [ { "type": 0, - "value": "Are you sure you want to leave " + "value": "Ste prepričani, da želite zapustiti " }, { "type": 1, @@ -1152,7 +1152,7 @@ "message.confirm-reset": [ { "type": 0, - "value": "Are your sure you want to reset " + "value": "Ste prepričani, da želite ponastaviti statistiko " }, { "type": 1, @@ -1160,13 +1160,13 @@ }, { "type": 0, - "value": "'s statistics?" + "value": "?" } ], "message.delete-account": [ { "type": 0, - "value": "To delete this account, type " + "value": "Za potrditev izbrisa tega računa vnesite " }, { "type": 1, @@ -1174,13 +1174,13 @@ }, { "type": 0, - "value": " in the box below to confirm." + "value": " v spodnje polje." } ], "message.delete-website": [ { "type": 0, - "value": "To delete this website, type " + "value": "Za potrditev izbrisa tega spletnega mesta vnesite " }, { "type": 1, @@ -1188,19 +1188,19 @@ }, { "type": 0, - "value": " in the box below to confirm." + "value": " v spodnje polje." } ], "message.delete-website-warning": [ { "type": 0, - "value": "Izbrisani bodo tudi vsi povezani podatki." + "value": "Izbrisani bodo tudi vsi pripadajoči podatki." } ], "message.error": [ { "type": 0, - "value": "Prišlo je do napake." + "value": "Nekaj je šlo narobe." } ], "message.event-log": [ @@ -1210,7 +1210,7 @@ }, { "type": 0, - "value": " on " + "value": " na " }, { "type": 1, @@ -1226,7 +1226,7 @@ "message.incorrect-username-password": [ { "type": 0, - "value": "Nepravilno uporabniško ime/geslo" + "value": "Nepravilno uporabniško ime/geslo." } ], "message.invalid-domain": [ @@ -1238,7 +1238,7 @@ "message.min-password-length": [ { "type": 0, - "value": "Minimum length of " + "value": "Najmanjša dolžina je " }, { "type": 1, @@ -1246,13 +1246,13 @@ }, { "type": 0, - "value": " characters" + "value": " znakov" } ], "message.new-version-available": [ { "type": 0, - "value": "A new version of Umami " + "value": "Na voljo je nova verzija programa Umami " }, { "type": 1, @@ -1260,7 +1260,7 @@ }, { "type": 0, - "value": " is available!" + "value": "!" } ], "message.no-data-available": [ @@ -1272,7 +1272,7 @@ "message.no-event-data": [ { "type": 0, - "value": "No event data is available." + "value": "Podatki o dogodku niso na voljo." } ], "message.no-match-password": [ @@ -1284,31 +1284,31 @@ "message.no-results-found": [ { "type": 0, - "value": "No results were found." + "value": "Rezultatov ni bilo mogoče najti." } ], "message.no-team-websites": [ { "type": 0, - "value": "This team does not have any websites." + "value": "Ta ekipa nima spletnih mest." } ], "message.no-teams": [ { "type": 0, - "value": "You have not created any teams." + "value": "Niste še ustvarili nobene ekipe." } ], "message.no-users": [ { "type": 0, - "value": "There are no users." + "value": "Ni uporabnikov." } ], "message.no-websites-configured": [ { "type": 0, - "value": "Ni nastavljenih spletnih mest." + "value": "Nimate nastavljenih nobenih spletnih mest." } ], "message.page-not-found": [ @@ -1320,7 +1320,7 @@ "message.reset-website": [ { "type": 0, - "value": "To reset this website, type " + "value": "Za ponastavitev izbrisa tega spletnega mesta vnesite " }, { "type": 1, @@ -1328,13 +1328,13 @@ }, { "type": 0, - "value": " in the box below to confirm." + "value": " v spodnje polje." } ], "message.reset-website-warning": [ { "type": 0, - "value": "All statistics for this website will be deleted, but your tracking code will remain intact." + "value": "Vse statistike za to spletno mesto bodo izbrisane, koda za sledenje pa bo ostala nespremenjena." } ], "message.saved": [ @@ -1346,7 +1346,7 @@ "message.share-url": [ { "type": 0, - "value": "To je javno dostopen naslov URL za " + "value": "To je javno dostopna povezava za " }, { "type": 1, @@ -1360,19 +1360,19 @@ "message.team-already-member": [ { "type": 0, - "value": "You are already a member of the team." + "value": "Ste že član ekipe." } ], "message.team-not-found": [ { "type": 0, - "value": "Team not found." + "value": "Ekipa ni bila najdena." } ], "message.team-websites-info": [ { "type": 0, - "value": "Websites can be viewed by anyone on the team." + "value": "Spletne strani si lahko ogleda vsak član ekipe." } ], "message.tracking-code": [ @@ -1384,7 +1384,7 @@ "message.user-deleted": [ { "type": 0, - "value": "User deleted." + "value": "Uporabnik je izbrisan." } ], "message.visitor-log": [ diff --git a/src/lang/sl-SI.json b/src/lang/sl-SI.json index 4e7e4ad95..440b9fcad 100644 --- a/src/lang/sl-SI.json +++ b/src/lang/sl-SI.json @@ -175,7 +175,7 @@ "label.websites": "Spletnih mest", "label.window": "Okno", "label.yesterday": "Včeraj", - "message.active-users": "{x} trenutni {x, plural, one {visitor} ostali {visitors}}", + "message.active-users": "{x} trenutni {x, plural, one {obiskovalec} other {obiskovalcev}}", "message.confirm-delete": "Ste prepričani, da želite izbrisati {target}?", "message.confirm-leave": "Ste prepričani, da želite zapustiti {target}?", "message.confirm-reset": "Ste prepričani, da želite ponastaviti statistiko {target}?", From b652ef3f7391ebdb5c1c7d947da5fa3d92401a2d Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Thu, 31 Aug 2023 14:33:39 -0700 Subject: [PATCH 076/113] Bump version v2.6.2. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9745b780e..9759b2b88 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "umami", - "version": "2.6.1", + "version": "2.6.2", "description": "A simple, fast, privacy-focused alternative to Google Analytics.", "author": "Mike Cao ", "license": "MIT", From 251a5e5a076ac5b601957aeb6813f8b45f22565f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20K=C3=B6ssler?= Date: Fri, 1 Sep 2023 09:26:10 +0200 Subject: [PATCH 077/113] i18n: update de-DE translations --- src/lang/de-DE.json | 110 ++++++++++++++++++++++---------------------- 1 file changed, 55 insertions(+), 55 deletions(-) diff --git a/src/lang/de-DE.json b/src/lang/de-DE.json index 3307dfa40..ba797bbb4 100644 --- a/src/lang/de-DE.json +++ b/src/lang/de-DE.json @@ -2,18 +2,18 @@ "label.access-code": "Zugangscode", "label.actions": "Aktionen", "label.activity-log": "Aktivitätsverlauf", - "label.add": "Add", + "label.add": "Hinzufügen", "label.add-description": "Beschreibung hinzufügen", - "label.add-website": "Webseite hinzufügen", + "label.add-website": "Website hinzufügen", "label.admin": "Administrator", - "label.after": "After", + "label.after": "Nach", "label.all": "Alle", "label.all-time": "Gesamter Zeitraum", "label.analytics": "Analytics", "label.average": "Durchschnitt", "label.average-visit-time": "Durchschn. Besuchszeit", "label.back": "Zurück", - "label.before": "Before", + "label.before": "Vor", "label.bounce-rate": "Absprungrate", "label.breakdown": "Breakdown", "label.browser": "Browser", @@ -21,15 +21,15 @@ "label.cancel": "Abbrechen", "label.change-password": "Passwort ändern", "label.cities": "Städte", - "label.city": "City", + "label.city": "Stadt", "label.clear-all": "Alles löschen", "label.confirm": "Bestätigen", "label.confirm-password": "Passwort wiederholen", - "label.contains": "Contains", + "label.contains": "Enthält", "label.continue": "Weiter", "label.countries": "Länder", - "label.country": "Country", - "label.create-report": "Report erstellen", + "label.country": "Land", + "label.create-report": "Bericht erstellen", "label.create-team": "Team erstellen", "label.create-user": "Benutzer erstellen", "label.created": "Erstellt", @@ -37,43 +37,43 @@ "label.custom-range": "Benutzerdefinierter Bereich", "label.dashboard": "Übersicht", "label.data": "Daten", - "label.date": "Date", + "label.date": "Datum", "label.date-range": "Datumsbereich", - "label.day": "Day", + "label.day": "Tag", "label.default-date-range": "Voreingestellter Datumsbereich", "label.delete": "Löschen", "label.delete-team": "Team löschen", "label.delete-user": "Benutzer löschen", - "label.delete-website": "Webseite löschen", + "label.delete-website": "Website löschen", "label.description": "Beschreibung", "label.desktop": "Desktop", "label.details": "Details", - "label.device": "Device", + "label.device": "Gerät", "label.devices": "Geräte", "label.dismiss": "Verwerfen", - "label.does-not-contain": "Does not contain", + "label.does-not-contain": "Enthält nicht", "label.domain": "Domain", "label.dropoff": "Dropoff", "label.edit": "Bearbeiten", "label.edit-dashboard": "Dashboard bearbeiten", "label.enable-share-url": "Freigabe-URL aktivieren", "label.event": "Event", - "label.event-data": "Event daten", + "label.event-data": "Eventdaten", "label.events": "Ereignisse", - "label.false": "False", - "label.field": "Field", - "label.fields": "Fields", + "label.false": "Falsch", + "label.field": "Feld", + "label.fields": "Felder", "label.filter-combined": "Kombiniert", "label.filter-raw": "Rohdaten", - "label.filters": "Filters", + "label.filters": "Filter", "label.funnel": "Funnel", "label.greater-than": "Größer als", "label.greater-than-equals": "Größer oder gleich", "label.insights": "Insights", - "label.is": "Is", - "label.is-not": "Is not", - "label.is-not-set": "Is not set", - "label.is-set": "Is set", + "label.is": "Ist", + "label.is-not": "Ist nicht", + "label.is-not-set": "Ist nicht gesetzt", + "label.is-set": "Ist gesetzt", "label.join": "Beitreten", "label.join-team": "Team beitreten", "label.language": "Sprache", @@ -92,16 +92,16 @@ "label.min": "Min", "label.mobile": "Handy", "label.more": "Mehr", - "label.my-websites": "My websites", + "label.my-websites": "Meine Websites", "label.name": "Name", "label.new-password": "Neues Passwort", "label.none": "Keine", "label.os": "OS", "label.overview": "Übersicht", "label.owner": "Besitzer", - "label.page-of": "Page {current} of {total}", + "label.page-of": "Seite {current} von {total}", "label.page-views": "Seitenaufrufe", - "label.pageTitle": "Page title", + "label.pageTitle": "Seitentitel", "label.pages": "Seiten", "label.password": "Passwort", "label.powered-by": "Betrieben durch {name}", @@ -117,7 +117,7 @@ "label.region": "Region", "label.regions": "Regionen", "label.remove": "Entfernen", - "label.reports": "Reporte", + "label.reports": "Berichte", "label.required": "Erforderlich", "label.reset": "Zurücksetzen", "label.reset-website": "Statistik zurücksetzen", @@ -128,19 +128,19 @@ "label.screens": "Bildschirmauflösungen", "label.select-date": "Datum auswählen", "label.select-website": "Website auswählen", - "label.sessions": "Sessions", + "label.sessions": "Sitzungen", "label.settings": "Einstellungen", "label.share-url": "Freigabe-URL", "label.single-day": "Ein Tag", "label.sum": "Summe", "label.tablet": "Tablet", "label.team": "Team", - "label.team-guest": "Team Gast", - "label.team-id": "Team ID", - "label.team-member": "Team Mitglied", - "label.team-name": "Team name", - "label.team-owner": "Team Eigentümer", - "label.team-websites": "Team websites", + "label.team-guest": "Gast des Teams", + "label.team-id": "Team-ID", + "label.team-member": "Team-Mitglied", + "label.team-name": "Name des Teams", + "label.team-owner": "Team-Eigentümer", + "label.team-websites": "Team-Websites", "label.teams": "Teams", "label.theme": "Thema", "label.this-month": "Diesen Monat", @@ -150,61 +150,61 @@ "label.title": "Titel", "label.today": "Heute", "label.toggle-charts": "Schaubilder umschalten", - "label.total": "Total", - "label.total-records": "Total records", + "label.total": "Gesamt", + "label.total-records": "Datensätze insgesamt", "label.tracking-code": "Tracking Code", - "label.true": "True", - "label.type": "Type", - "label.unique": "Unique", + "label.true": "Wahr", + "label.type": "Typ", + "label.unique": "Eindeutig", "label.unique-visitors": "Eindeutige Besucher", "label.unknown": "Unbekannt", - "label.untitled": "Untitled", + "label.untitled": "Unbenannt", "label.url": "URL", "label.urls": "URLs", "label.user": "Benutzer", "label.username": "Benutzername", "label.users": "Benutzer", - "label.value": "Value", + "label.value": "Wert", "label.view": "Anzeigen", "label.view-details": "Details anzeigen", - "label.view-only": "View only", + "label.view-only": "Nur ansehen", "label.views": "Aufrufe", "label.visitors": "Besucher", - "label.website": "Webseite", - "label.website-id": "Webseite ID", - "label.websites": "Webseiten", - "label.window": "Window", + "label.website": "Website", + "label.website-id": "Website ID", + "label.websites": "Websites", + "label.window": "Fenster", "label.yesterday": "Gestern", "message.active-users": "{x} {x, plural, one {aktiver Besucher} other {aktive Besucher}}", "message.confirm-delete": "Sind Sie sich sicher, {target} zu löschen?", "message.confirm-leave": "Sind Sie sicher, dass die {target} verlassen möchten?", "message.confirm-reset": "Sind Sie sicher, dass Sie die Statistiken von {target} zurücksetzen wollen?", - "message.delete-account": "To delete this account, type {confirmation} in the box below to confirm.", - "message.delete-website": "To delete this website, type {confirmation} in the box below to confirm.", + "message.delete-account": "Um dieses Konto zu löschen, geben Sie zur Bestätigung {confirmation} in das Feld unten ein.", + "message.delete-website": "Um diese Website zu löschen, geben Sie zur Bestätigung {confirmation} in das Feld unten ein.", "message.delete-website-warning": "Alle zugehörigen Daten werden ebenfalls gelöscht.", "message.error": "Es ist ein Fehler aufgetreten.", "message.event-log": "{event} auf {url}", "message.go-to-settings": "Zu den Einstellungen", "message.incorrect-username-password": "Falsches Passwort oder Benutzername.", "message.invalid-domain": "Ungültige Domain", - "message.min-password-length": "Minimale länge von {n} Zeichen", - "message.new-version-available": "A new version of Umami {version} is available!", + "message.min-password-length": "Minimale Länge von {n} Zeichen", + "message.new-version-available": "Eine neue Version von Umami ist verfügbar: {version}", "message.no-data-available": "Keine Daten vorhanden.", - "message.no-event-data": "No event data is available.", + "message.no-event-data": "Es sind keine Ereignisdaten verfügbar.", "message.no-match-password": "Passwörter stimmen nicht überein", "message.no-results-found": "Keine Ergebnisse gefunden.", "message.no-team-websites": "Diesem Team sind keine Websites zugeordnet.", "message.no-teams": "Bisher wurden keine Teams erstellt.", "message.no-users": "Hier gibt es keine Benutzer.", - "message.no-websites-configured": "Es ist keine Webseite vorhanden.", + "message.no-websites-configured": "Es ist keine Website vorhanden.", "message.page-not-found": "Seite nicht gefunden.", - "message.reset-website": "To reset this website, type {confirmation} in the box below to confirm.", - "message.reset-website-warning": "Alle Daten für diese Webseite werden gelöscht, jedoch bleibt der Tracking Code bestehen.", + "message.reset-website": "Um diese Website zurückzusetzen, geben Sie zur Bestätigung {confirmation} in das Feld unten ein.", + "message.reset-website-warning": "Alle Daten für diese Website werden gelöscht, jedoch bleibt der Tracking Code bestehen.", "message.saved": "Erfolgreich gespeichert.", - "message.share-url": "Ihre Webseitenstatistik ist unter der folgenden URL öffentlich zugänglich:", + "message.share-url": "Die Statistiken Ihrer Website sind unter folgender URL öffentlich zugänglich:", "message.team-already-member": "Sie sind bereits Mitglied des Teams.", "message.team-not-found": "Team nicht gefunden.", - "message.team-websites-info": "Webseiten können von jedem im Team eingesehen werden.", + "message.team-websites-info": "Websites können von jedem im Team eingesehen werden.", "message.tracking-code": "Tracking Code", "message.user-deleted": "Benutzer gelöscht.", "message.visitor-log": "Besucher aus {country} benutzt {browser} auf {os} {device}" From be886db0f271a70dd6136ba94d56e1b288f38507 Mon Sep 17 00:00:00 2001 From: Maxime-J Date: Thu, 31 Aug 2023 16:32:17 +0000 Subject: [PATCH 078/113] update lang scripts --- package.json | 2 +- scripts/merge-messages.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 9759b2b88..8bb372013 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "check-db": "node scripts/check-db.js", "check-env": "node scripts/check-env.js", "copy-db-files": "node scripts/copy-db-files.js", - "extract-messages": "formatjs extract \"{pages,components}/**/*.js\" --out-file build/messages.json", + "extract-messages": "formatjs extract \"src/{pages,components}/**/*.js\" --out-file build/messages.json", "merge-messages": "node scripts/merge-messages.js", "generate-lang": "npm-run-all extract-messages merge-messages", "format-lang": "node scripts/format-lang.js", diff --git a/scripts/merge-messages.js b/scripts/merge-messages.js index a74153146..572e9a7ed 100644 --- a/scripts/merge-messages.js +++ b/scripts/merge-messages.js @@ -4,7 +4,7 @@ const path = require('path'); const prettier = require('prettier'); const messages = require('../build/messages.json'); -const dest = path.resolve(__dirname, '../lang'); +const dest = path.resolve(__dirname, '../src/lang'); const files = fs.readdirSync(dest); const keys = Object.keys(messages).sort(); @@ -14,7 +14,7 @@ with the existing files under `lang`. Any newly added keys will be printed to the console. */ files.forEach(file => { - const lang = require(`../lang/${file}`); + const lang = require(`../src/lang/${file}`); console.log(`Merging ${file}`); From 440676ef210d451f58110d48c3e57b5487930369 Mon Sep 17 00:00:00 2001 From: Maxime-J Date: Fri, 1 Sep 2023 09:14:51 +0000 Subject: [PATCH 079/113] add lang labels --- src/components/common/SettingsTable.js | 4 +- src/components/messages.js | 14 +++ .../pages/reports/ReportTemplates.js | 10 ++- src/lang/am-ET.json | 6 ++ src/lang/ar-SA.json | 6 ++ src/lang/be-BY.json | 6 ++ src/lang/bn-BD.json | 6 ++ src/lang/ca-ES.json | 6 ++ src/lang/cs-CZ.json | 6 ++ src/lang/da-DK.json | 6 ++ src/lang/de-CH.json | 6 ++ src/lang/de-DE.json | 6 ++ src/lang/el-GR.json | 6 ++ src/lang/en-GB.json | 6 ++ src/lang/en-US.json | 6 ++ src/lang/es-ES.json | 6 ++ src/lang/es-MX.json | 6 ++ src/lang/fa-IR.json | 6 ++ src/lang/fi-FI.json | 6 ++ src/lang/fo-FO.json | 6 ++ src/lang/fr-FR.json | 6 ++ src/lang/ga-ES.json | 6 ++ src/lang/he-IL.json | 6 ++ src/lang/hi-IN.json | 6 ++ src/lang/hr-HR.json | 6 ++ src/lang/hu-HU.json | 6 ++ src/lang/id-ID.json | 6 ++ src/lang/it-IT.json | 6 ++ src/lang/ja-JP.json | 6 ++ src/lang/km-KH.json | 6 ++ src/lang/ko-KR.json | 6 ++ src/lang/lt-LT.json | 6 ++ src/lang/mn-MN.json | 6 ++ src/lang/ms-MY.json | 6 ++ src/lang/my-MM.json | 90 ++++++++++++------- src/lang/nb-NO.json | 6 ++ src/lang/nl-NL.json | 6 ++ src/lang/pl-PL.json | 6 ++ src/lang/pt-BR.json | 6 ++ src/lang/pt-PT.json | 6 ++ src/lang/ro-RO.json | 6 ++ src/lang/ru-RU.json | 6 ++ src/lang/si-LK.json | 6 ++ src/lang/sk-SK.json | 6 ++ src/lang/sl-SI.json | 13 ++- src/lang/sv-SE.json | 6 ++ src/lang/ta-IN.json | 6 ++ src/lang/th-TH.json | 6 ++ src/lang/tr-TR.json | 6 ++ src/lang/uk-UA.json | 6 ++ src/lang/ur-PK.json | 6 ++ src/lang/vi-VN.json | 6 ++ src/lang/zh-CN.json | 6 ++ src/lang/zh-TW.json | 6 ++ 54 files changed, 381 insertions(+), 44 deletions(-) diff --git a/src/components/common/SettingsTable.js b/src/components/common/SettingsTable.js index 2df3b391b..a74581cae 100644 --- a/src/components/common/SettingsTable.js +++ b/src/components/common/SettingsTable.js @@ -25,7 +25,7 @@ export function SettingsTable({ onPageSizeChange, filterValue, }) { - const { formatMessage, messages } = useMessages(); + const { formatMessage, labels, messages } = useMessages(); const [filter, setFilter] = useState(filterValue); const { data: value, page, count, pageSize } = data; @@ -42,7 +42,7 @@ export function SettingsTable({ delay={1000} value={filter} autoFocus={true} - placeholder="Search" + placeholder={formatMessage(labels.search)} style={{ maxWidth: '300px', marginBottom: '10px' }} /> )} diff --git a/src/components/messages.js b/src/components/messages.js index f52ed5c5e..01c7e779c 100644 --- a/src/components/messages.js +++ b/src/components/messages.js @@ -129,6 +129,10 @@ export const labels = defineMessages({ reports: { id: 'label.reports', defaultMessage: 'Reports' }, eventData: { id: 'label.event-data', defaultMessage: 'Event data' }, funnel: { id: 'label.funnel', defaultMessage: 'Funnel' }, + funnelDescription: { + id: 'label.funnel-description', + defaultMessage: 'Understand the conversion and drop-off rate of users.', + }, url: { id: 'label.url', defaultMessage: 'URL' }, urls: { id: 'label.urls', defaultMessage: 'URLs' }, add: { id: 'label.add', defaultMessage: 'Add' }, @@ -167,7 +171,15 @@ export const labels = defineMessages({ overview: { id: 'label.overview', defaultMessage: 'Overview' }, totalRecords: { id: 'label.total-records', defaultMessage: 'Total records' }, insights: { id: 'label.insights', defaultMessage: 'Insights' }, + insightsDescription: { + id: 'label.insights-description', + defaultMessage: 'Dive deeper into your data by using segments and filters.', + }, retention: { id: 'label.retention', defaultMessage: 'Retention' }, + retentionDescription: { + id: 'label.retention-description', + defaultMessage: 'Measure you website stickiness by tracking how often users return.', + }, dropoff: { id: 'label.dropoff', defaultMessage: 'Dropoff' }, referrer: { id: 'label.referrer', defaultMessage: 'Referrer' }, country: { id: 'label.country', defaultMessage: 'Country' }, @@ -179,6 +191,8 @@ export const labels = defineMessages({ day: { id: 'label.day', defaultMessage: 'Day' }, date: { id: 'label.date', defaultMessage: 'Date' }, pageOf: { id: 'label.page-of', defaultMessage: 'Page {current} of {total}' }, + create: { id: 'label.create', defaultMessage: 'Create' }, + search: { id: 'label.search', defaultMessage: 'Search' }, }); export const messages = defineMessages({ diff --git a/src/components/pages/reports/ReportTemplates.js b/src/components/pages/reports/ReportTemplates.js index 2b934434e..59cc8b310 100644 --- a/src/components/pages/reports/ReportTemplates.js +++ b/src/components/pages/reports/ReportTemplates.js @@ -9,6 +9,8 @@ import styles from './ReportTemplates.module.css'; import { useMessages } from 'components/hooks'; function ReportItem({ title, description, url, icon }) { + const { formatMessage, labels } = useMessages(); + return (
@@ -22,7 +24,7 @@ function ReportItem({ title, description, url, icon }) { - Create + {formatMessage(labels.create)}
@@ -36,19 +38,19 @@ export function ReportTemplates({ showHeader = true }) { const reports = [ { title: formatMessage(labels.insights), - description: 'Dive deeper into your data by using segments and filters.', + description: formatMessage(labels.insightsDescription), url: '/reports/insights', icon: , }, { title: formatMessage(labels.funnel), - description: 'Understand the conversion and drop-off rate of users.', + description: formatMessage(labels.funnelDescription), url: '/reports/funnel', icon: , }, { title: formatMessage(labels.retention), - description: 'Measure you website stickiness by tracking how often users return.', + description: formatMessage(labels.retentionDescription), url: '/reports/retention', icon: , }, diff --git a/src/lang/am-ET.json b/src/lang/am-ET.json index 7bed14236..3765e5ba6 100644 --- a/src/lang/am-ET.json +++ b/src/lang/am-ET.json @@ -29,6 +29,7 @@ "label.continue": "Continue", "label.countries": "Countries", "label.country": "Country", + "label.create": "Create", "label.create-report": "Create report", "label.create-team": "Create team", "label.create-user": "Create user", @@ -63,13 +64,16 @@ "label.false": "False", "label.field": "Field", "label.fields": "Fields", + "label.filter": "Filter", "label.filter-combined": "Combined", "label.filter-raw": "Raw", "label.filters": "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.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", @@ -122,10 +126,12 @@ "label.reset": "Reset", "label.reset-website": "Reset statistics", "label.retention": "Retention", + "label.retention-description": "Measure you website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Save", "label.screens": "Screens", + "label.search": "Search", "label.select-date": "Select date", "label.select-website": "Select website", "label.sessions": "Sessions", diff --git a/src/lang/ar-SA.json b/src/lang/ar-SA.json index 0efdfee73..ccfee1f33 100644 --- a/src/lang/ar-SA.json +++ b/src/lang/ar-SA.json @@ -29,6 +29,7 @@ "label.continue": "متابعة", "label.countries": "الدول", "label.country": "Country", + "label.create": "Create", "label.create-report": "Create report", "label.create-team": "انشاء مجموعة", "label.create-user": "انشاء مستخدم", @@ -63,13 +64,16 @@ "label.false": "False", "label.field": "Field", "label.fields": "Fields", + "label.filter": "Filter", "label.filter-combined": "مجمعة", "label.filter-raw": "مفصلة", "label.filters": "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.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", @@ -122,10 +126,12 @@ "label.reset": "اعادة تعيين", "label.reset-website": "اعادة تعيين الإحصائيات", "label.retention": "Retention", + "label.retention-description": "Measure you website stickiness by tracking how often users return.", "label.role": "الصلاحية", "label.run-query": "Run query", "label.save": "حفظ", "label.screens": "الشاشات", + "label.search": "Search", "label.select-date": "Select date", "label.select-website": "اختيار موقع", "label.sessions": "الزيارات", diff --git a/src/lang/be-BY.json b/src/lang/be-BY.json index 32693ebd4..88f673b9c 100644 --- a/src/lang/be-BY.json +++ b/src/lang/be-BY.json @@ -29,6 +29,7 @@ "label.continue": "Continue", "label.countries": "Краіны", "label.country": "Country", + "label.create": "Create", "label.create-report": "Create report", "label.create-team": "Create team", "label.create-user": "Create user", @@ -63,13 +64,16 @@ "label.false": "False", "label.field": "Field", "label.fields": "Fields", + "label.filter": "Filter", "label.filter-combined": "Камбініаваны", "label.filter-raw": "Сырыя", "label.filters": "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.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", @@ -122,10 +126,12 @@ "label.reset": "Скінуць", "label.reset-website": "Скінуць статыстыку", "label.retention": "Retention", + "label.retention-description": "Measure you website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Захаваць", "label.screens": "Экраны", + "label.search": "Search", "label.select-date": "Select date", "label.select-website": "Select website", "label.sessions": "Sessions", diff --git a/src/lang/bn-BD.json b/src/lang/bn-BD.json index 483d10080..29e1bb6f6 100644 --- a/src/lang/bn-BD.json +++ b/src/lang/bn-BD.json @@ -29,6 +29,7 @@ "label.continue": "Continue", "label.countries": "দেশ", "label.country": "Country", + "label.create": "Create", "label.create-report": "Create report", "label.create-team": "Create team", "label.create-user": "Create user", @@ -63,13 +64,16 @@ "label.false": "False", "label.field": "Field", "label.fields": "Fields", + "label.filter": "Filter", "label.filter-combined": "সম্মিলিত", "label.filter-raw": "অপরিশোধিত", "label.filters": "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.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", @@ -122,10 +126,12 @@ "label.reset": "রিসেট", "label.reset-website": "ওয়েবসাইট রিসেট করুন", "label.retention": "Retention", + "label.retention-description": "Measure you website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "সংরক্ষণ", "label.screens": "স্ক্রিনগুলি", + "label.search": "Search", "label.select-date": "Select date", "label.select-website": "Select website", "label.sessions": "Sessions", diff --git a/src/lang/ca-ES.json b/src/lang/ca-ES.json index 51aee79dd..271b9245a 100644 --- a/src/lang/ca-ES.json +++ b/src/lang/ca-ES.json @@ -29,6 +29,7 @@ "label.continue": "Continue", "label.countries": "Països", "label.country": "Country", + "label.create": "Create", "label.create-report": "Create report", "label.create-team": "Create team", "label.create-user": "Create user", @@ -63,13 +64,16 @@ "label.false": "False", "label.field": "Field", "label.fields": "Fields", + "label.filter": "Filter", "label.filter-combined": "Combinat", "label.filter-raw": "En cru", "label.filters": "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.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", @@ -122,10 +126,12 @@ "label.reset": "Restableix", "label.reset-website": "Restableix estadístiques", "label.retention": "Retention", + "label.retention-description": "Measure you website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Desa", "label.screens": "Screens", + "label.search": "Search", "label.select-date": "Select date", "label.select-website": "Select website", "label.sessions": "Sessions", diff --git a/src/lang/cs-CZ.json b/src/lang/cs-CZ.json index 548ee817d..73bc15b70 100644 --- a/src/lang/cs-CZ.json +++ b/src/lang/cs-CZ.json @@ -29,6 +29,7 @@ "label.continue": "Continue", "label.countries": "Země", "label.country": "Country", + "label.create": "Create", "label.create-report": "Create report", "label.create-team": "Create team", "label.create-user": "Create user", @@ -63,13 +64,16 @@ "label.false": "False", "label.field": "Field", "label.fields": "Fields", + "label.filter": "Filter", "label.filter-combined": "Kombinace", "label.filter-raw": "Nezpracované", "label.filters": "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.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", @@ -122,10 +126,12 @@ "label.reset": "Reset", "label.reset-website": "Reset statistics", "label.retention": "Retention", + "label.retention-description": "Measure you website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Uložit", "label.screens": "Screens", + "label.search": "Search", "label.select-date": "Select date", "label.select-website": "Select website", "label.sessions": "Sessions", diff --git a/src/lang/da-DK.json b/src/lang/da-DK.json index 9d4fe50ee..2fba4f7a7 100644 --- a/src/lang/da-DK.json +++ b/src/lang/da-DK.json @@ -29,6 +29,7 @@ "label.continue": "Continue", "label.countries": "Lande", "label.country": "Country", + "label.create": "Create", "label.create-report": "Create report", "label.create-team": "Create team", "label.create-user": "Create user", @@ -63,13 +64,16 @@ "label.false": "False", "label.field": "Field", "label.fields": "Fields", + "label.filter": "Filter", "label.filter-combined": "Kombineret", "label.filter-raw": "Rå", "label.filters": "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.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", @@ -122,10 +126,12 @@ "label.reset": "Nulstil", "label.reset-website": "Nulstil statistikker", "label.retention": "Retention", + "label.retention-description": "Measure you website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Gem", "label.screens": "Screens", + "label.search": "Search", "label.select-date": "Select date", "label.select-website": "Select website", "label.sessions": "Sessions", diff --git a/src/lang/de-CH.json b/src/lang/de-CH.json index 5c6c45d14..c07ddd2cb 100644 --- a/src/lang/de-CH.json +++ b/src/lang/de-CH.json @@ -29,6 +29,7 @@ "label.continue": "Wiiter", "label.countries": "Länder", "label.country": "Country", + "label.create": "Create", "label.create-report": "Create report", "label.create-team": "Team erstelle", "label.create-user": "Benutzer erstelle", @@ -63,13 +64,16 @@ "label.false": "False", "label.field": "Field", "label.fields": "Fields", + "label.filter": "Filter", "label.filter-combined": "Kombiniert", "label.filter-raw": "Rohdate", "label.filters": "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.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", @@ -122,10 +126,12 @@ "label.reset": "Zruggsetze", "label.reset-website": "Statistik zruggsetze", "label.retention": "Retention", + "label.retention-description": "Measure you website stickiness by tracking how often users return.", "label.role": "Rollä", "label.run-query": "Run query", "label.save": "Speichere", "label.screens": "Bildschirmuflösige", + "label.search": "Search", "label.select-date": "Select date", "label.select-website": "Websiite uuswähle", "label.sessions": "Sessions", diff --git a/src/lang/de-DE.json b/src/lang/de-DE.json index 3307dfa40..7bac16255 100644 --- a/src/lang/de-DE.json +++ b/src/lang/de-DE.json @@ -29,6 +29,7 @@ "label.continue": "Weiter", "label.countries": "Länder", "label.country": "Country", + "label.create": "Create", "label.create-report": "Report erstellen", "label.create-team": "Team erstellen", "label.create-user": "Benutzer erstellen", @@ -63,13 +64,16 @@ "label.false": "False", "label.field": "Field", "label.fields": "Fields", + "label.filter": "Filter", "label.filter-combined": "Kombiniert", "label.filter-raw": "Rohdaten", "label.filters": "Filters", "label.funnel": "Funnel", + "label.funnel-description": "Understand the conversion and drop-off rate of users.", "label.greater-than": "Größer als", "label.greater-than-equals": "Größer oder gleich", "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", @@ -122,10 +126,12 @@ "label.reset": "Zurücksetzen", "label.reset-website": "Statistik zurücksetzen", "label.retention": "Retention", + "label.retention-description": "Measure you website stickiness by tracking how often users return.", "label.role": "Rolle", "label.run-query": "Abfrage starten", "label.save": "Speichern", "label.screens": "Bildschirmauflösungen", + "label.search": "Search", "label.select-date": "Datum auswählen", "label.select-website": "Website auswählen", "label.sessions": "Sessions", diff --git a/src/lang/el-GR.json b/src/lang/el-GR.json index dd95c7772..c5cea1bee 100644 --- a/src/lang/el-GR.json +++ b/src/lang/el-GR.json @@ -29,6 +29,7 @@ "label.continue": "Continue", "label.countries": "Χώρες", "label.country": "Country", + "label.create": "Create", "label.create-report": "Create report", "label.create-team": "Create team", "label.create-user": "Create user", @@ -63,13 +64,16 @@ "label.false": "False", "label.field": "Field", "label.fields": "Fields", + "label.filter": "Filter", "label.filter-combined": "Σε συνδυασμό", "label.filter-raw": "Ακατέργαστο", "label.filters": "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.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", @@ -122,10 +126,12 @@ "label.reset": "Επαναφορά", "label.reset-website": "Reset statistics", "label.retention": "Retention", + "label.retention-description": "Measure you website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Αποθήκευση", "label.screens": "Screens", + "label.search": "Search", "label.select-date": "Select date", "label.select-website": "Select website", "label.sessions": "Sessions", diff --git a/src/lang/en-GB.json b/src/lang/en-GB.json index 4efaec5df..e93b3b23a 100644 --- a/src/lang/en-GB.json +++ b/src/lang/en-GB.json @@ -29,6 +29,7 @@ "label.continue": "Continue", "label.countries": "Countries", "label.country": "Country", + "label.create": "Create", "label.create-report": "Create report", "label.create-team": "Create team", "label.create-user": "Create user", @@ -63,13 +64,16 @@ "label.false": "False", "label.field": "Field", "label.fields": "Fields", + "label.filter": "Filter", "label.filter-combined": "Combined", "label.filter-raw": "Raw", "label.filters": "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.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", @@ -122,10 +126,12 @@ "label.reset": "Reset", "label.reset-website": "Reset statistics", "label.retention": "Retention", + "label.retention-description": "Measure you website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Save", "label.screens": "Screens", + "label.search": "Search", "label.select-date": "Select date", "label.select-website": "Select website", "label.sessions": "Sessions", diff --git a/src/lang/en-US.json b/src/lang/en-US.json index b7c77a694..16dfa1888 100644 --- a/src/lang/en-US.json +++ b/src/lang/en-US.json @@ -29,6 +29,7 @@ "label.continue": "Continue", "label.countries": "Countries", "label.country": "Country", + "label.create": "Create", "label.create-report": "Create report", "label.create-team": "Create team", "label.create-user": "Create user", @@ -63,13 +64,16 @@ "label.false": "False", "label.field": "Field", "label.fields": "Fields", + "label.filter": "Filter", "label.filter-combined": "Combined", "label.filter-raw": "Raw", "label.filters": "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.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", @@ -122,10 +126,12 @@ "label.reset": "Reset", "label.reset-website": "Reset website", "label.retention": "Retention", + "label.retention-description": "Measure you website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Save", "label.screens": "Screens", + "label.search": "Search", "label.select-date": "Select date", "label.select-website": "Select website", "label.sessions": "Sessions", diff --git a/src/lang/es-ES.json b/src/lang/es-ES.json index 7a401e51d..001b94064 100644 --- a/src/lang/es-ES.json +++ b/src/lang/es-ES.json @@ -29,6 +29,7 @@ "label.continue": "Continuar", "label.countries": "Países", "label.country": "Country", + "label.create": "Create", "label.create-report": "Crear reporte", "label.create-team": "Crear equipo", "label.create-user": "Crear usuario", @@ -63,13 +64,16 @@ "label.false": "False", "label.field": "Campo", "label.fields": "Campos", + "label.filter": "Filter", "label.filter-combined": "Combinado", "label.filter-raw": "En crudo", "label.filters": "Filtros", "label.funnel": "Funnel", + "label.funnel-description": "Understand the conversion and drop-off rate of users.", "label.greater-than": "Mayor que", "label.greater-than-equals": "Mayor que o igual a", "label.insights": "Insights", + "label.insights-description": "Dive deeper into your data by using segments and filters.", "label.is": "Es igual a", "label.is-not": "No es igual a", "label.is-not-set": "Is not set", @@ -122,10 +126,12 @@ "label.reset": "Reiniciar", "label.reset-website": "Reiniciar estadísticas", "label.retention": "Retention", + "label.retention-description": "Measure you website stickiness by tracking how often users return.", "label.role": "Rol", "label.run-query": "Ejecutar consulta", "label.save": "Guardar", "label.screens": "Pantallas", + "label.search": "Search", "label.select-date": "Seleccionar fecha", "label.select-website": "Seleccionar sitio web", "label.sessions": "Sesiones", diff --git a/src/lang/es-MX.json b/src/lang/es-MX.json index 499b2533f..c1dacfa44 100644 --- a/src/lang/es-MX.json +++ b/src/lang/es-MX.json @@ -29,6 +29,7 @@ "label.continue": "Continuar", "label.countries": "Países", "label.country": "Country", + "label.create": "Create", "label.create-report": "Create report", "label.create-team": "Crear equipo", "label.create-user": "Crear usuario", @@ -63,13 +64,16 @@ "label.false": "False", "label.field": "Field", "label.fields": "Fields", + "label.filter": "Filter", "label.filter-combined": "Combinado", "label.filter-raw": "Personalizado", "label.filters": "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.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", @@ -122,10 +126,12 @@ "label.reset": "Reiniciar", "label.reset-website": "Reiniciar estadísticas", "label.retention": "Retention", + "label.retention-description": "Measure you website stickiness by tracking how often users return.", "label.role": "Rol", "label.run-query": "Run query", "label.save": "Guardar", "label.screens": "Pantallas", + "label.search": "Search", "label.select-date": "Select date", "label.select-website": "Seleccionar sitio web", "label.sessions": "Sesiones", diff --git a/src/lang/fa-IR.json b/src/lang/fa-IR.json index b263a7d1a..32d985e3e 100644 --- a/src/lang/fa-IR.json +++ b/src/lang/fa-IR.json @@ -29,6 +29,7 @@ "label.continue": "Continue", "label.countries": "کشورها", "label.country": "Country", + "label.create": "Create", "label.create-report": "Create report", "label.create-team": "Create team", "label.create-user": "Create user", @@ -63,13 +64,16 @@ "label.false": "False", "label.field": "Field", "label.fields": "Fields", + "label.filter": "Filter", "label.filter-combined": "ترکیب شده", "label.filter-raw": "خام", "label.filters": "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.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", @@ -122,10 +126,12 @@ "label.reset": "بازنشانی", "label.reset-website": "بازنشانی آمار", "label.retention": "Retention", + "label.retention-description": "Measure you website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "ذخیره", "label.screens": "Screens", + "label.search": "Search", "label.select-date": "Select date", "label.select-website": "Select website", "label.sessions": "Sessions", diff --git a/src/lang/fi-FI.json b/src/lang/fi-FI.json index 9e9c1de03..8c447f8a1 100644 --- a/src/lang/fi-FI.json +++ b/src/lang/fi-FI.json @@ -29,6 +29,7 @@ "label.continue": "Continue", "label.countries": "Maat", "label.country": "Country", + "label.create": "Create", "label.create-report": "Create report", "label.create-team": "Create team", "label.create-user": "Create user", @@ -63,13 +64,16 @@ "label.false": "False", "label.field": "Field", "label.fields": "Fields", + "label.filter": "Filter", "label.filter-combined": "Yhdistetty", "label.filter-raw": "Käsittelemätön", "label.filters": "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.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", @@ -122,10 +126,12 @@ "label.reset": "Nollaa", "label.reset-website": "Nollaa tilastot", "label.retention": "Retention", + "label.retention-description": "Measure you website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Tallenna", "label.screens": "Screens", + "label.search": "Search", "label.select-date": "Select date", "label.select-website": "Select website", "label.sessions": "Sessions", diff --git a/src/lang/fo-FO.json b/src/lang/fo-FO.json index 6259a5557..e2626f1fb 100644 --- a/src/lang/fo-FO.json +++ b/src/lang/fo-FO.json @@ -29,6 +29,7 @@ "label.continue": "Continue", "label.countries": "Lond", "label.country": "Country", + "label.create": "Create", "label.create-report": "Create report", "label.create-team": "Create team", "label.create-user": "Create user", @@ -63,13 +64,16 @@ "label.false": "False", "label.field": "Field", "label.fields": "Fields", + "label.filter": "Filter", "label.filter-combined": "Samansett", "label.filter-raw": "Óviðgjørt", "label.filters": "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.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", @@ -122,10 +126,12 @@ "label.reset": "Nulstilla", "label.reset-website": "Reset statistics", "label.retention": "Retention", + "label.retention-description": "Measure you website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Goym", "label.screens": "Screens", + "label.search": "Search", "label.select-date": "Select date", "label.select-website": "Select website", "label.sessions": "Sessions", diff --git a/src/lang/fr-FR.json b/src/lang/fr-FR.json index 558c1cd26..878e078aa 100644 --- a/src/lang/fr-FR.json +++ b/src/lang/fr-FR.json @@ -29,6 +29,7 @@ "label.continue": "Continuer", "label.countries": "Pays", "label.country": "Country", + "label.create": "Create", "label.create-report": "Créer un rapport", "label.create-team": "Créer une équipe", "label.create-user": "Créer un utilisateur", @@ -63,13 +64,16 @@ "label.false": "Faux", "label.field": "Champ", "label.fields": "Champs", + "label.filter": "Filter", "label.filter-combined": "Combiné", "label.filter-raw": "Brut", "label.filters": "Filtres", "label.funnel": "Entonnoir", + "label.funnel-description": "Understand the conversion and drop-off rate of users.", "label.greater-than": "Supérieur à", "label.greater-than-equals": "Supérieur ou égal à", "label.insights": "Insights", + "label.insights-description": "Dive deeper into your data by using segments and filters.", "label.is": "Est égal", "label.is-not": "N'est pas égal", "label.is-not-set": "Is not set", @@ -122,10 +126,12 @@ "label.reset": "Réinitialiser", "label.reset-website": "Réinitialiser les statistiques", "label.retention": "Retention", + "label.retention-description": "Measure you website stickiness by tracking how often users return.", "label.role": "Rôle", "label.run-query": "Éxécuter la requête", "label.save": "Enregistrer", "label.screens": "Résolutions d'écran", + "label.search": "Search", "label.select-date": "Choisir une période", "label.select-website": "Choisir un site", "label.sessions": "Sessions", diff --git a/src/lang/ga-ES.json b/src/lang/ga-ES.json index e6ceda8a9..ae46fa2c5 100644 --- a/src/lang/ga-ES.json +++ b/src/lang/ga-ES.json @@ -29,6 +29,7 @@ "label.continue": "Continue", "label.countries": "Países", "label.country": "Country", + "label.create": "Create", "label.create-report": "Create report", "label.create-team": "Create team", "label.create-user": "Create user", @@ -63,13 +64,16 @@ "label.false": "False", "label.field": "Field", "label.fields": "Fields", + "label.filter": "Filter", "label.filter-combined": "Combinado", "label.filter-raw": "Raw", "label.filters": "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.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", @@ -122,10 +126,12 @@ "label.reset": "Restablecer", "label.reset-website": "To reset this website, type {confirmation} in the box below to confirm.", "label.retention": "Retention", + "label.retention-description": "Measure you website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Gardar", "label.screens": "Screens", + "label.search": "Search", "label.select-date": "Select date", "label.select-website": "Select website", "label.sessions": "Sessions", diff --git a/src/lang/he-IL.json b/src/lang/he-IL.json index fd3e0b8b8..b953fda60 100644 --- a/src/lang/he-IL.json +++ b/src/lang/he-IL.json @@ -29,6 +29,7 @@ "label.continue": "Continue", "label.countries": "מדינות", "label.country": "Country", + "label.create": "Create", "label.create-report": "Create report", "label.create-team": "Create team", "label.create-user": "Create user", @@ -63,13 +64,16 @@ "label.false": "False", "label.field": "Field", "label.fields": "Fields", + "label.filter": "Filter", "label.filter-combined": "משותף", "label.filter-raw": "גולמי", "label.filters": "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.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", @@ -122,10 +126,12 @@ "label.reset": "איפוס", "label.reset-website": "Reset statistics", "label.retention": "Retention", + "label.retention-description": "Measure you website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "שמירה", "label.screens": "Screens", + "label.search": "Search", "label.select-date": "Select date", "label.select-website": "Select website", "label.sessions": "Sessions", diff --git a/src/lang/hi-IN.json b/src/lang/hi-IN.json index 6e268aa6e..e296d87bf 100644 --- a/src/lang/hi-IN.json +++ b/src/lang/hi-IN.json @@ -29,6 +29,7 @@ "label.continue": "Continue", "label.countries": "देश", "label.country": "Country", + "label.create": "Create", "label.create-report": "Create report", "label.create-team": "Create team", "label.create-user": "Create user", @@ -63,13 +64,16 @@ "label.false": "False", "label.field": "Field", "label.fields": "Fields", + "label.filter": "Filter", "label.filter-combined": "संयुक्त", "label.filter-raw": "रॉ", "label.filters": "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.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", @@ -122,10 +126,12 @@ "label.reset": "रीसेट", "label.reset-website": "Reset statistics", "label.retention": "Retention", + "label.retention-description": "Measure you website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "सहेजें", "label.screens": "Screens", + "label.search": "Search", "label.select-date": "Select date", "label.select-website": "Select website", "label.sessions": "Sessions", diff --git a/src/lang/hr-HR.json b/src/lang/hr-HR.json index ecde7100e..75bd8a4f3 100644 --- a/src/lang/hr-HR.json +++ b/src/lang/hr-HR.json @@ -29,6 +29,7 @@ "label.continue": "Continue", "label.countries": "Countries", "label.country": "Country", + "label.create": "Create", "label.create-report": "Create report", "label.create-team": "Create team", "label.create-user": "Create user", @@ -63,13 +64,16 @@ "label.false": "False", "label.field": "Field", "label.fields": "Fields", + "label.filter": "Filter", "label.filter-combined": "Combined", "label.filter-raw": "Raw", "label.filters": "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.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", @@ -122,10 +126,12 @@ "label.reset": "Resetirati", "label.reset-website": "Resetirati web stranicu", "label.retention": "Retention", + "label.retention-description": "Measure you website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Spremi", "label.screens": "Screens", + "label.search": "Search", "label.select-date": "Select date", "label.select-website": "Select website", "label.sessions": "Sessions", diff --git a/src/lang/hu-HU.json b/src/lang/hu-HU.json index 0401afff7..c6224b01c 100644 --- a/src/lang/hu-HU.json +++ b/src/lang/hu-HU.json @@ -29,6 +29,7 @@ "label.continue": "Continue", "label.countries": "Országok", "label.country": "Country", + "label.create": "Create", "label.create-report": "Create report", "label.create-team": "Create team", "label.create-user": "Create user", @@ -63,13 +64,16 @@ "label.false": "False", "label.field": "Field", "label.fields": "Fields", + "label.filter": "Filter", "label.filter-combined": "Összevont", "label.filter-raw": "Nyers", "label.filters": "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.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", @@ -122,10 +126,12 @@ "label.reset": "Visszaállítás", "label.reset-website": "Reset statistics", "label.retention": "Retention", + "label.retention-description": "Measure you website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Mentés", "label.screens": "Screens", + "label.search": "Search", "label.select-date": "Select date", "label.select-website": "Select website", "label.sessions": "Sessions", diff --git a/src/lang/id-ID.json b/src/lang/id-ID.json index d0b8a0643..856727650 100644 --- a/src/lang/id-ID.json +++ b/src/lang/id-ID.json @@ -29,6 +29,7 @@ "label.continue": "Continue", "label.countries": "Negara", "label.country": "Country", + "label.create": "Create", "label.create-report": "Create report", "label.create-team": "Create team", "label.create-user": "Create user", @@ -63,13 +64,16 @@ "label.false": "False", "label.field": "Field", "label.fields": "Fields", + "label.filter": "Filter", "label.filter-combined": "Gabungan", "label.filter-raw": "Mentah", "label.filters": "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.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", @@ -122,10 +126,12 @@ "label.reset": "Atur ulang", "label.reset-website": "Atur ulang statistik", "label.retention": "Retention", + "label.retention-description": "Measure you website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Simpan", "label.screens": "Layar", + "label.search": "Search", "label.select-date": "Select date", "label.select-website": "Select website", "label.sessions": "Sessions", diff --git a/src/lang/it-IT.json b/src/lang/it-IT.json index 57d6d5ba3..8bce2f4e0 100644 --- a/src/lang/it-IT.json +++ b/src/lang/it-IT.json @@ -29,6 +29,7 @@ "label.continue": "Continue", "label.countries": "Nazioni", "label.country": "Country", + "label.create": "Create", "label.create-report": "Create report", "label.create-team": "Create team", "label.create-user": "Create user", @@ -63,13 +64,16 @@ "label.false": "False", "label.field": "Field", "label.fields": "Fields", + "label.filter": "Filter", "label.filter-combined": "Aggregati", "label.filter-raw": "Raw", "label.filters": "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.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", @@ -122,10 +126,12 @@ "label.reset": "Reset", "label.reset-website": "Resetta le statistiche", "label.retention": "Retention", + "label.retention-description": "Measure you website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Salva", "label.screens": "Screens", + "label.search": "Search", "label.select-date": "Select date", "label.select-website": "Select website", "label.sessions": "Sessions", diff --git a/src/lang/ja-JP.json b/src/lang/ja-JP.json index 770f6f076..3af2f7b0a 100644 --- a/src/lang/ja-JP.json +++ b/src/lang/ja-JP.json @@ -29,6 +29,7 @@ "label.continue": "続ける", "label.countries": "国名", "label.country": "国", + "label.create": "Create", "label.create-report": "レポートの作成", "label.create-team": "チームの作成", "label.create-user": "ユーザーの作成", @@ -63,13 +64,16 @@ "label.false": "偽", "label.field": "フィールド", "label.fields": "フィールド", + "label.filter": "Filter", "label.filter-combined": "統合", "label.filter-raw": "RAW", "label.filters": "フィルター", "label.funnel": "分析", + "label.funnel-description": "Understand the conversion and drop-off rate of users.", "label.greater-than": "超過", "label.greater-than-equals": "以上", "label.insights": "見通し", + "label.insights-description": "Dive deeper into your data by using segments and filters.", "label.is": "に等しい", "label.is-not": "に等しくない", "label.is-not-set": "未設定", @@ -122,10 +126,12 @@ "label.reset": "リセット", "label.reset-website": "Webサイトをリセットする", "label.retention": "保持", + "label.retention-description": "Measure you website stickiness by tracking how often users return.", "label.role": "ロール", "label.run-query": "クエリ実行", "label.save": "保存", "label.screens": "画面サイズ", + "label.search": "Search", "label.select-date": "日付を選択", "label.select-website": "Webサイトを選択", "label.sessions": "セッション", diff --git a/src/lang/km-KH.json b/src/lang/km-KH.json index 58f7926f3..3f7d089d1 100644 --- a/src/lang/km-KH.json +++ b/src/lang/km-KH.json @@ -29,6 +29,7 @@ "label.continue": "Continue", "label.countries": "ប្រទេស", "label.country": "Country", + "label.create": "Create", "label.create-report": "Create report", "label.create-team": "Create team", "label.create-user": "Create user", @@ -63,13 +64,16 @@ "label.false": "False", "label.field": "Field", "label.fields": "Fields", + "label.filter": "Filter", "label.filter-combined": "រួមបញ្ចូលគ្នា", "label.filter-raw": "ដើម", "label.filters": "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.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", @@ -122,10 +126,12 @@ "label.reset": "កំណត់ឡើងវិញ", "label.reset-website": "កំណត់ស្ថិតិឡើងវិញ", "label.retention": "Retention", + "label.retention-description": "Measure you website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "រក្សាទុក", "label.screens": "ប្រភេទឧបករណ៍", + "label.search": "Search", "label.select-date": "Select date", "label.select-website": "Select website", "label.sessions": "Sessions", diff --git a/src/lang/ko-KR.json b/src/lang/ko-KR.json index 767e8e220..dcbdd77c5 100644 --- a/src/lang/ko-KR.json +++ b/src/lang/ko-KR.json @@ -29,6 +29,7 @@ "label.continue": "Continue", "label.countries": "국가", "label.country": "Country", + "label.create": "Create", "label.create-report": "Create report", "label.create-team": "Create team", "label.create-user": "Create user", @@ -63,13 +64,16 @@ "label.false": "False", "label.field": "Field", "label.fields": "Fields", + "label.filter": "Filter", "label.filter-combined": "합쳐서 보기", "label.filter-raw": "전체 보기", "label.filters": "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.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", @@ -122,10 +126,12 @@ "label.reset": "리셋", "label.reset-website": "Reset statistics", "label.retention": "Retention", + "label.retention-description": "Measure you website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "저장", "label.screens": "Screens", + "label.search": "Search", "label.select-date": "Select date", "label.select-website": "Select website", "label.sessions": "Sessions", diff --git a/src/lang/lt-LT.json b/src/lang/lt-LT.json index c8161f1db..aa75f10f7 100644 --- a/src/lang/lt-LT.json +++ b/src/lang/lt-LT.json @@ -29,6 +29,7 @@ "label.continue": "Continue", "label.countries": "Šalys", "label.country": "Country", + "label.create": "Create", "label.create-report": "Create report", "label.create-team": "Create team", "label.create-user": "Create user", @@ -63,13 +64,16 @@ "label.false": "False", "label.field": "Field", "label.fields": "Fields", + "label.filter": "Filter", "label.filter-combined": "Kombinuoti", "label.filter-raw": "Neapdoroti", "label.filters": "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.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", @@ -122,10 +126,12 @@ "label.reset": "Atstatyti", "label.reset-website": "Atstatyti statistikos duomenis", "label.retention": "Retention", + "label.retention-description": "Measure you website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Išsaugoti", "label.screens": "Screens", + "label.search": "Search", "label.select-date": "Select date", "label.select-website": "Select website", "label.sessions": "Sessions", diff --git a/src/lang/mn-MN.json b/src/lang/mn-MN.json index 1478c0792..aad28ef20 100644 --- a/src/lang/mn-MN.json +++ b/src/lang/mn-MN.json @@ -29,6 +29,7 @@ "label.continue": "Үргэлжлүүлэх", "label.countries": "Улс", "label.country": "Country", + "label.create": "Create", "label.create-report": "Create report", "label.create-team": "Баг үүсгэх", "label.create-user": "Хэрэглэгч үүсгэх", @@ -63,13 +64,16 @@ "label.false": "False", "label.field": "Field", "label.fields": "Fields", + "label.filter": "Filter", "label.filter-combined": "Нэгтгэсэн", "label.filter-raw": "Түүхий", "label.filters": "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.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", @@ -122,10 +126,12 @@ "label.reset": "Дахин эхлүүлэх", "label.reset-website": "Тоон үзүүлэлтийг дахин эхлүүлэх", "label.retention": "Retention", + "label.retention-description": "Measure you website stickiness by tracking how often users return.", "label.role": "Эрх", "label.run-query": "Run query", "label.save": "Хадгалах", "label.screens": "Дэлгэц", + "label.search": "Search", "label.select-date": "Select date", "label.select-website": "Веб сонгох", "label.sessions": "Sessions", diff --git a/src/lang/ms-MY.json b/src/lang/ms-MY.json index 5b8769c58..af5c34f07 100644 --- a/src/lang/ms-MY.json +++ b/src/lang/ms-MY.json @@ -29,6 +29,7 @@ "label.continue": "Continue", "label.countries": "Negara", "label.country": "Country", + "label.create": "Create", "label.create-report": "Create report", "label.create-team": "Create team", "label.create-user": "Create user", @@ -63,13 +64,16 @@ "label.false": "False", "label.field": "Field", "label.fields": "Fields", + "label.filter": "Filter", "label.filter-combined": "Digabungkan", "label.filter-raw": "Mentah", "label.filters": "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.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", @@ -122,10 +126,12 @@ "label.reset": "Tetapkan semula", "label.reset-website": "Reset statistics", "label.retention": "Retention", + "label.retention-description": "Measure you website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Simpan", "label.screens": "Screens", + "label.search": "Search", "label.select-date": "Select date", "label.select-website": "Select website", "label.sessions": "Sessions", diff --git a/src/lang/my-MM.json b/src/lang/my-MM.json index de92b275d..8253705ab 100644 --- a/src/lang/my-MM.json +++ b/src/lang/my-MM.json @@ -6,21 +6,31 @@ "label.add-description": "အကြောင်းအရာဖော်ပြချက် ထည့်မည်", "label.add-website": "ဝက်ဘ်ဆိုဒ်ထည့်မည်", "label.admin": "အက်ဒမင်", + "label.after": "After", "label.all": "အားလုံး", "label.all-time": "အချိန်အစမှအခုထိ", "label.analytics": "အန်နလစ်တစ်", + "label.average": "Average", "label.average-visit-time": "ဝဘက်ဘ်ဆိုဒ်တွင် ပျမ်းမျှကုန်ဆုံးချိန်", "label.back": "နောက်သို့", + "label.before": "Before", "label.bounce-rate": "Bounce နှုန်း", + "label.breakdown": "Breakdown", + "label.browser": "Browser", "label.browsers": "ဝက်ဘ်ဘရောင်ဇာများ", "label.cancel": "မလုပ်တော့ပါ", "label.change-password": "စကားဝှက် ပြောင်းမည်", "label.cities": "မြို့များ", + "label.city": "City", "label.clear-all": "အားလုံးကိုဖျက်မည်", "label.confirm": "အတည်ပြုသည်", "label.confirm-password": "စကားဝှက်အတည်ပြုသည်", + "label.contains": "Contains", "label.continue": "ဆက်သွားမည်", "label.countries": "နိုင်ငံများ", + "label.country": "Country", + "label.create": "Create", + "label.create-report": "Create report", "label.create-team": "Team ပြုလုပ်မည်", "label.create-user": "အသုံးပြုသူထည့်မည်", "label.created": "ပြုလုပ်ပြီးသော", @@ -28,16 +38,21 @@ "label.custom-range": "အချိန်အပိုင်းအခြားရွေးရန်", "label.dashboard": "ဒက်ရှ်ဘုတ်", "label.data": "ဒေတာ", + "label.date": "Date", "label.date-range": "ရက်အပိုင်းအခြား", + "label.day": "Day", "label.default-date-range": "ပုံသေ ရက်အပိုင်းအခြား", "label.delete": "ဖျက်မည်", "label.delete-team": "Team ကိုဖျက်မည်", "label.delete-user": "အသုံးပြုသူကိုဖျက်မည်", "label.delete-website": "ဝက်ဘ်ဆိုဒ်ကိုဖျက်မည်", + "label.description": "Description", "label.desktop": "စားပွဲတင်ကွန်ပျူတာ", "label.details": "အသေးစိတ်", + "label.device": "Device", "label.devices": "အသုံးပြုသည့် ကိရိယာများ", "label.dismiss": "ပိတ်ပါ", + "label.does-not-contain": "Does not contain", "label.domain": "ဒိုမိန်း", "label.dropoff": "Dropoff", "label.edit": "ပြုပြင်မည်", @@ -46,12 +61,23 @@ "label.event": "အဖြစ်အပျက်", "label.event-data": "အဖြစ်အပျက် ဒေတာ", "label.events": "အဖြစ်အပျက်များ", + "label.false": "False", "label.field": "Field အမည်", "label.fields": "Field အမည်များ", + "label.filter": "Filter", "label.filter-combined": "ပေါင်းစပ်ပြီး", "label.filter-raw": "အရှိအတိုင်း", + "label.filters": "Filters", "label.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.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": "ဝင်မည်", "label.join-team": "အသင်းဝင်မည်", "label.language": "ဘာသာစကား", @@ -61,17 +87,25 @@ "label.last-hours": "လွန်ခဲ့သော {x} နာရီက", "label.leave": "ထွက်မည်", "label.leave-team": "အသင်းမှထွက်မည်", + "label.less-than": "Less than", + "label.less-than-equals": "Less than or equals", "label.login": "လော့ဂ်အင်", "label.logout": "လော့ဂ်အောက်လုပ်မည်", + "label.max": "Max", "label.members": "အဖွဲ့ဝင်များ", + "label.min": "Min", "label.mobile": "မိုဘိုင်း", "label.more": "နောက်ထပ်", + "label.my-websites": "My websites", "label.name": "အမည်", "label.new-password": "စကားဝှက်အသစ်", "label.none": "မရှိပါ", - "label.operating-systems": "ကွန်ပျူတာလည်ပတ်မှုစနစ်", + "label.os": "OS", + "label.overview": "Overview", "label.owner": "ပိုင်ဆိုင်သူ", + "label.page-of": "Page {current} of {total}", "label.page-views": "ဝင်ရောက်ကြည့်ရှုသူ", + "label.pageTitle": "Page title", "label.pages": "စာမျက်နှာများ", "label.password": "စကားဝှက်", "label.powered-by": "{name} ထောက်ပံ့သည်", @@ -80,31 +114,39 @@ "label.query": "Query (ကွာရီ)", "label.query-parameters": "Query parameters (ကွာရီပါရာမီတာများ)", "label.realtime": "အချိန်နှင့်တပြေးညီ", + "label.referrer": "Referrer", "label.referrers": "ရည်ညွှန်းမှုများ", "label.refresh": "Refresh လုပ်မည်", "label.regenerate": "ပြန်ထုတ်မည်", + "label.region": "Region", "label.regions": "ဒေသများ", "label.remove": "ဖျက်မည်", "label.reports": "တင်ပြမှုများ", "label.required": "လိုအပ်သည်", "label.reset": "ပြန်စမည်", "label.reset-website": "ဝက်ဘ်ဆိုဒ်ဒေတာကိုဖျက်မည်", + "label.retention": "Retention", + "label.retention-description": "Measure you website stickiness by tracking how often users return.", "label.role": "အခန်းကဏ္ဍ", "label.run-query": "Query ကိုလုပ်ဆောင်မည်", "label.save": "သိမ်းဆည်းမည်", "label.screens": "မြင်ကွင်းများ", + "label.search": "Search", "label.select-date": "ရက်ရွေးပါ", "label.select-website": "ဝဘက်ဘ်ဆိုဒ်ရွေးပါ", "label.sessions": "ဆက်ရှင်များ", "label.settings": "ဆက်တင်များ", "label.share-url": "URL ကိုရှဲမည်", "label.single-day": "တစ်ရက်အတွင်း", + "label.sum": "Sum", "label.tablet": "တက်ဘလက်", "label.team": "အသင်း", "label.team-guest": "အသင်း ဧည့်သည်", "label.team-id": "အသင်း အိုင်ဒီ", "label.team-member": "အသင်းဝင်", + "label.team-name": "Team name", "label.team-owner": "အသင်းကိုပိုင်ဆိုင်သူ", + "label.team-websites": "Team websites", "label.teams": "အသင်းများ", "label.theme": "Theme (အပြင်အဆင်)", "label.this-month": "ယခုလ", @@ -114,14 +156,21 @@ "label.title": "ခေါင်းစဥ်", "label.today": "ယနေ့", "label.toggle-charts": "ဇယားများကို အဖွင့်အပိတ်လုပ်မည်", + "label.total": "Total", + "label.total-records": "Total records", "label.tracking-code": "ထရက်လုပ်သည့် ကုဒ်", + "label.true": "True", + "label.type": "Type", + "label.unique": "Unique", "label.unique-visitors": "ဝင်ရောက်သူ (ထပ်ခြင်းမရှိ)", "label.unknown": "မသိသော", + "label.untitled": "Untitled", "label.url": "URL", "label.urls": "URL များ", "label.user": "အသုံးပြုသူ", "label.username": "အသုံးပြုသူအမည်", "label.users": "အသုံးပြုသူများ", + "label.value": "Value", "label.view": "ဝင်ရောက်ကြည့်ရှုမှု", "label.view-details": "အသေးစိတ်ကို ကြည့်ရှုမည်", "label.view-only": "ဝင်ရောက်ကြည့်ရှုမှုများသာ", @@ -132,33 +181,6 @@ "label.websites": "ဝက်ဘ်ဆိုဒ်များ", "label.window": "ဝင်းဒိုး", "label.yesterday": "မနေ့က", - "labels.after": "ပြီးနောက်", - "labels.average": "ပျမ်းမျှ", - "labels.before": "မတိုင်မီ", - "labels.breakdown": "ခွဲခြမ်းစိတ်ဖြာမှု", - "labels.contains": "ပါဝင်သည်", - "labels.create-report": "ရီပို့လုပ်မည်", - "labels.description": "ရှင်းပြချက်", - "labels.does-not-contain": "မပါဝင်ပါ", - "labels.does-not-equal": "မတူညီပါ", - "labels.equals": "တူညီသည်", - "labels.false": "မှားသည်", - "labels.filters": "Filter များ", - "labels.greater-than": "ထက်ပို၍ကြီးသည်", - "labels.greater-than-equals": "ထက်ပို၍ကြီးသည်သို့မဟုတ်တူသည်", - "labels.less-than": "ထက်ပို၍ငယ်သည်", - "labels.less-than-equals": "ထက်ပို၍ငယ်သည်သို့မဟုတ်တူသည်", - "labels.max": "အများဆုံး", - "labels.min": "အနည်းဆုံး", - "labels.overview": "အပေါ်ယံမြင်ကွင်း", - "labels.sum": "ပေါင်းလဒ်", - "labels.total": "စုစုပေါင်း", - "labels.total-records": "မှတ်တမ်းစုစုပေါင်း", - "labels.true": "မှန်သည်", - "labels.type": "အမျိုးအစား", - "labels.unique": "Unique", - "labels.untitled": "ခေါင်းစဉ်မရှိ", - "labels.value": "တန်ဖိုး", "message.active-users": "{x} လက်ရှိအသုံးပြုနေသူ {x, plural, one {ယောက်} other {ယောက်}}", "message.confirm-delete": "{target} ကို ဖျက်ရန် သေချာပါသလား?", "message.confirm-leave": "{target} ကို ထွက်ရန် သေချာပါသလား?", @@ -172,11 +194,15 @@ "message.incorrect-username-password": "အသုံးပြုသူအမည် သို့မဟုတ် စကားဝှက် မှားနေသည်", "message.invalid-domain": "ဒိုမိန်း မမှန်ပါ http/https. မပါရပါ", "message.min-password-length": "အနည်းဆုံး {n} character ရှိရမည်", + "message.new-version-available": "အူမာမီ {version} အသစ်ထွက်နေပါပြီ", "message.no-data-available": "ဒေတာ မရှိပါ", "message.no-event-data": "အဖြစ်အပျက်ဒေတာ မရှိပါ", "message.no-match-password": "စကားဝှက် မှားနေသည်", + "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": "ဤ ဝက်ဘ်ဆိုဒ်ဒေတာကိုဖျက်၍ ပြန်စလုပ်ရန် အောက်တွင် {confirmation} ကို ရိုက်ထည့်ပေးပါ", "message.reset-website-warning": "ဤဝက်ဘ်ဆိုဒ်က စာရင်းအချက်အလက်များကို ဖျက်မည်၊ ဆက်တင်ဒေတာများ မပါပါ", @@ -184,12 +210,8 @@ "message.share-url": "သင့်ဝက်ဆိုဒ်ဘ်၏ စာရင်းအချက်အလက်များကို အောက်ပါ URL တွင် ဝင်ရောက်ကြည့်ရှုနိုင်သည်", "message.team-already-member": "ဤအသင်းတွင် ဝင်ပြီးသားဖြစ်နေသည်", "message.team-not-found": "အသင်း မရှိပါ", + "message.team-websites-info": "ဤဝက်ဘ်ဆိုဒ်များကို အသင်းထဲမှ လူတိုင်းဝင်ကြည့်နိုင်သည်", "message.tracking-code": "ဤဝက်ဘ်ဆိုဒ်၏ ဒေတာကိုကောက်ခံရန် အောက်ပါ code ကို သင်၏ HTML တွင်ထည့်ပါ", "message.user-deleted": "အသုံးပြုသူ ဖျက်ပြီးပါပြီ", - "message.visitor-log": "{country} မှ {browser} ဖြင့် {os} {device} တွင် ဝင်ရောက်ကြည့်ရှုသူ", - "message.no-results-found": "ရလဒ်မရှိပါ", - "message.no-team-websites": "ဤအသင်းတွင် ဝက်ဘ်ဆိုက်မရှိသေးပါ", - "message.no-websites-configured": "ဝက်ဘ်ဆိုဒ်တစ်ခုမှ မထည့်ရသေးပါ", - "message.team-websites-info": "ဤဝက်ဘ်ဆိုဒ်များကို အသင်းထဲမှ လူတိုင်းဝင်ကြည့်နိုင်သည်", - "message.new-version-available": "အူမာမီ {version} အသစ်ထွက်နေပါပြီ" + "message.visitor-log": "{country} မှ {browser} ဖြင့် {os} {device} တွင် ဝင်ရောက်ကြည့်ရှုသူ" } diff --git a/src/lang/nb-NO.json b/src/lang/nb-NO.json index 654c3c791..18fa765ee 100644 --- a/src/lang/nb-NO.json +++ b/src/lang/nb-NO.json @@ -29,6 +29,7 @@ "label.continue": "Continue", "label.countries": "Land", "label.country": "Country", + "label.create": "Create", "label.create-report": "Create report", "label.create-team": "Create team", "label.create-user": "Create user", @@ -63,13 +64,16 @@ "label.false": "False", "label.field": "Field", "label.fields": "Fields", + "label.filter": "Filter", "label.filter-combined": "Kombinert", "label.filter-raw": "Rå", "label.filters": "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.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", @@ -122,10 +126,12 @@ "label.reset": "Nullstill", "label.reset-website": "Nullstill statistikk", "label.retention": "Retention", + "label.retention-description": "Measure you website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Lagre", "label.screens": "Screens", + "label.search": "Search", "label.select-date": "Select date", "label.select-website": "Select website", "label.sessions": "Sessions", diff --git a/src/lang/nl-NL.json b/src/lang/nl-NL.json index ad30cf36b..d0c3f6782 100644 --- a/src/lang/nl-NL.json +++ b/src/lang/nl-NL.json @@ -29,6 +29,7 @@ "label.continue": "Doorgaan", "label.countries": "Landen", "label.country": "Country", + "label.create": "Create", "label.create-report": "Create report", "label.create-team": "Team aanmaken", "label.create-user": "Gebruiker maken", @@ -63,13 +64,16 @@ "label.false": "False", "label.field": "Field", "label.fields": "Fields", + "label.filter": "Filter", "label.filter-combined": "Gecombineerd", "label.filter-raw": "Ruw", "label.filters": "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.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", @@ -122,10 +126,12 @@ "label.reset": "Opnieuw instellen", "label.reset-website": "Statistieken opnieuw instellen", "label.retention": "Retention", + "label.retention-description": "Measure you website stickiness by tracking how often users return.", "label.role": "Gebruikersrol", "label.run-query": "Run query", "label.save": "Opslaan", "label.screens": "Schermen", + "label.search": "Search", "label.select-date": "Select date", "label.select-website": "Website selecteren", "label.sessions": "Sessies", diff --git a/src/lang/pl-PL.json b/src/lang/pl-PL.json index eb9406139..8045af067 100644 --- a/src/lang/pl-PL.json +++ b/src/lang/pl-PL.json @@ -29,6 +29,7 @@ "label.continue": "Kontynuuj", "label.countries": "Kraje", "label.country": "Country", + "label.create": "Create", "label.create-report": "Stwórz raport", "label.create-team": "Utwórz zespół", "label.create-user": "Utwórz użytkownika", @@ -63,13 +64,16 @@ "label.false": "Fałsz", "label.field": "Pole", "label.fields": "Pola", + "label.filter": "Filter", "label.filter-combined": "Połączone", "label.filter-raw": "Surowe dane", "label.filters": "Filtry", "label.funnel": "Lejek", + "label.funnel-description": "Understand the conversion and drop-off rate of users.", "label.greater-than": "Większe niż", "label.greater-than-equals": "Większe niż lub równe", "label.insights": "Insights", + "label.insights-description": "Dive deeper into your data by using segments and filters.", "label.is": "Równe", "label.is-not": "Nie jest równe", "label.is-not-set": "Is not set", @@ -122,10 +126,12 @@ "label.reset": "Zresetuj", "label.reset-website": "Zresetuj statystyki", "label.retention": "Retention", + "label.retention-description": "Measure you website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Uruchom zapytanie", "label.save": "Zapisz", "label.screens": "Ekrany", + "label.search": "Search", "label.select-date": "Wybierz datę", "label.select-website": "Wybierz witrynę", "label.sessions": "Sesje", diff --git a/src/lang/pt-BR.json b/src/lang/pt-BR.json index b68d96154..22169e3ae 100644 --- a/src/lang/pt-BR.json +++ b/src/lang/pt-BR.json @@ -29,6 +29,7 @@ "label.continue": "Continuar", "label.countries": "Países", "label.country": "Country", + "label.create": "Create", "label.create-report": "Criar relatório", "label.create-team": "Criar time", "label.create-user": "Criar usuário", @@ -63,13 +64,16 @@ "label.false": "False", "label.field": "Campo", "label.fields": "Campos", + "label.filter": "Filter", "label.filter-combined": "Combinado", "label.filter-raw": "Dados brutos", "label.filters": "Filters", "label.funnel": "Funil", + "label.funnel-description": "Understand the conversion and drop-off rate of users.", "label.greater-than": "Maior que", "label.greater-than-equals": "Maior que ou igual", "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", @@ -122,10 +126,12 @@ "label.reset": "Redefinir", "label.reset-website": "Redefinir estatísticas", "label.retention": "Retention", + "label.retention-description": "Measure you website stickiness by tracking how often users return.", "label.role": "Papel", "label.run-query": "Executar query", "label.save": "Salvar", "label.screens": "Telas", + "label.search": "Search", "label.select-date": "Selecionar data", "label.select-website": "Selecionar site", "label.sessions": "Sessões", diff --git a/src/lang/pt-PT.json b/src/lang/pt-PT.json index fcf7ff03f..28a798e31 100644 --- a/src/lang/pt-PT.json +++ b/src/lang/pt-PT.json @@ -29,6 +29,7 @@ "label.continue": "Continue", "label.countries": "Países", "label.country": "Country", + "label.create": "Create", "label.create-report": "Create report", "label.create-team": "Create team", "label.create-user": "Create user", @@ -63,13 +64,16 @@ "label.false": "False", "label.field": "Field", "label.fields": "Fields", + "label.filter": "Filter", "label.filter-combined": "Combinado", "label.filter-raw": "Dados brutos", "label.filters": "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.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", @@ -122,10 +126,12 @@ "label.reset": "Repor", "label.reset-website": "Repor estatísticas", "label.retention": "Retention", + "label.retention-description": "Measure you website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Guardar", "label.screens": "Screens", + "label.search": "Search", "label.select-date": "Select date", "label.select-website": "Select website", "label.sessions": "Sessions", diff --git a/src/lang/ro-RO.json b/src/lang/ro-RO.json index 43a78ecd2..9c8c8c3c1 100644 --- a/src/lang/ro-RO.json +++ b/src/lang/ro-RO.json @@ -29,6 +29,7 @@ "label.continue": "Continue", "label.countries": "Țări", "label.country": "Country", + "label.create": "Create", "label.create-report": "Create report", "label.create-team": "Create team", "label.create-user": "Create user", @@ -63,13 +64,16 @@ "label.false": "False", "label.field": "Field", "label.fields": "Fields", + "label.filter": "Filter", "label.filter-combined": "Combinat", "label.filter-raw": "Brut", "label.filters": "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.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", @@ -122,10 +126,12 @@ "label.reset": "Resetează", "label.reset-website": "Resetează statisticile pentru site", "label.retention": "Retention", + "label.retention-description": "Measure you website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Salvează", "label.screens": "Screens", + "label.search": "Search", "label.select-date": "Select date", "label.select-website": "Select website", "label.sessions": "Sessions", diff --git a/src/lang/ru-RU.json b/src/lang/ru-RU.json index b9129beb4..6eed37257 100644 --- a/src/lang/ru-RU.json +++ b/src/lang/ru-RU.json @@ -29,6 +29,7 @@ "label.continue": "Продолжить", "label.countries": "Страны", "label.country": "Country", + "label.create": "Create", "label.create-report": "Create report", "label.create-team": "Создать команду", "label.create-user": "Создать пользователя", @@ -63,13 +64,16 @@ "label.false": "False", "label.field": "Field", "label.fields": "Fields", + "label.filter": "Filter", "label.filter-combined": "Объединенные", "label.filter-raw": "Сырые данные", "label.filters": "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.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", @@ -122,10 +126,12 @@ "label.reset": "Сбросить", "label.reset-website": "Сбросить статистику", "label.retention": "Retention", + "label.retention-description": "Measure you website stickiness by tracking how often users return.", "label.role": "Роль", "label.run-query": "Run query", "label.save": "Сохранить", "label.screens": "Экраны", + "label.search": "Search", "label.select-date": "Select date", "label.select-website": "Выбрать сайт", "label.sessions": "Сессии", diff --git a/src/lang/si-LK.json b/src/lang/si-LK.json index 6f6dda6d1..92bbe7360 100644 --- a/src/lang/si-LK.json +++ b/src/lang/si-LK.json @@ -29,6 +29,7 @@ "label.continue": "Continue", "label.countries": "Countries", "label.country": "Country", + "label.create": "Create", "label.create-report": "Create report", "label.create-team": "Create team", "label.create-user": "Create user", @@ -63,13 +64,16 @@ "label.false": "False", "label.field": "Field", "label.fields": "Fields", + "label.filter": "Filter", "label.filter-combined": "Combined", "label.filter-raw": "Raw", "label.filters": "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.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", @@ -122,10 +126,12 @@ "label.reset": "යළි පිහිටුවන්න", "label.reset-website": "සංඛ්යා ලේඛන නැවත සකසන්න", "label.retention": "Retention", + "label.retention-description": "Measure you website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "සුරකින්න", "label.screens": "Screens", + "label.search": "Search", "label.select-date": "Select date", "label.select-website": "Select website", "label.sessions": "Sessions", diff --git a/src/lang/sk-SK.json b/src/lang/sk-SK.json index 3f0339236..534ace423 100644 --- a/src/lang/sk-SK.json +++ b/src/lang/sk-SK.json @@ -29,6 +29,7 @@ "label.continue": "Continue", "label.countries": "Zem", "label.country": "Country", + "label.create": "Create", "label.create-report": "Create report", "label.create-team": "Create team", "label.create-user": "Create user", @@ -63,13 +64,16 @@ "label.false": "False", "label.field": "Field", "label.fields": "Fields", + "label.filter": "Filter", "label.filter-combined": "Kombinácie", "label.filter-raw": "Nezpracované", "label.filters": "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.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", @@ -122,10 +126,12 @@ "label.reset": "Reset", "label.reset-website": "Reset statistics", "label.retention": "Retention", + "label.retention-description": "Measure you website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Uložiť", "label.screens": "Screens", + "label.search": "Search", "label.select-date": "Select date", "label.select-website": "Select website", "label.sessions": "Sessions", diff --git a/src/lang/sl-SI.json b/src/lang/sl-SI.json index 440b9fcad..f73aa265f 100644 --- a/src/lang/sl-SI.json +++ b/src/lang/sl-SI.json @@ -29,6 +29,7 @@ "label.continue": "Nadaljuj", "label.countries": "Države", "label.country": "Država", + "label.create": "Create", "label.create-report": "Ustvari poročilo", "label.create-team": "Ustvari ekipo", "label.create-user": "Ustvari uporabnika", @@ -63,13 +64,16 @@ "label.false": "Napačno", "label.field": "Polje", "label.fields": "Polja", + "label.filter": "Filter", "label.filter-combined": "Skupaj", "label.filter-raw": "Neobdelano", "label.filters": "Filtri", "label.funnel": "Prodajni lijak", + "label.funnel-description": "Understand the conversion and drop-off rate of users.", "label.greater-than": "Večje od", "label.greater-than-equals": "Večje ali enako kot", "label.insights": "Vpogled", + "label.insights-description": "Dive deeper into your data by using segments and filters.", "label.is": "Je", "label.is-not": "Ni", "label.is-not-set": "Ni nastavljeno", @@ -122,13 +126,14 @@ "label.reset": "Ponastavi", "label.reset-website": "Ponastavi statistiko", "label.retention": "Ohranjanje uporabnikov", + "label.retention-description": "Measure you website stickiness by tracking how often users return.", "label.role": "Vloga", "label.run-query": "Izvedi poizvedbo", "label.save": "Shrani", - "label.screens": "Zasloni", - "label.select-date": "Izberi datum", - "label.select-website": "Izberi spletno mesto", - "label.sessions": "Seje", + "label.screens": "Screens", + "label.select-date": "Select date", + "label.select-website": "Select website", + "label.sessions": "Sessions", "label.settings": "Nastavitve", "label.share-url": "Deli povezavo", "label.single-day": "En dan", diff --git a/src/lang/sv-SE.json b/src/lang/sv-SE.json index e6abb5bf7..532b9039d 100644 --- a/src/lang/sv-SE.json +++ b/src/lang/sv-SE.json @@ -29,6 +29,7 @@ "label.continue": "Fortsätt", "label.countries": "Länder", "label.country": "Country", + "label.create": "Create", "label.create-report": "Create report", "label.create-team": "Skapa team", "label.create-user": "Skapa användare", @@ -63,13 +64,16 @@ "label.false": "False", "label.field": "Field", "label.fields": "Fields", + "label.filter": "Filter", "label.filter-combined": "Kombinerade", "label.filter-raw": "Rådata", "label.filters": "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.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", @@ -122,10 +126,12 @@ "label.reset": "Återställ", "label.reset-website": "Återställ statistik", "label.retention": "Retention", + "label.retention-description": "Measure you website stickiness by tracking how often users return.", "label.role": "Roll", "label.run-query": "Run query", "label.save": "Spara", "label.screens": "Upplösning", + "label.search": "Search", "label.select-date": "Select date", "label.select-website": "Välj webbsajt", "label.sessions": "Sessions", diff --git a/src/lang/ta-IN.json b/src/lang/ta-IN.json index be3d5e815..64b6bf2ba 100644 --- a/src/lang/ta-IN.json +++ b/src/lang/ta-IN.json @@ -29,6 +29,7 @@ "label.continue": "Continue", "label.countries": "நாடுகள்", "label.country": "Country", + "label.create": "Create", "label.create-report": "Create report", "label.create-team": "Create team", "label.create-user": "Create user", @@ -63,13 +64,16 @@ "label.false": "False", "label.field": "Field", "label.fields": "Fields", + "label.filter": "Filter", "label.filter-combined": "ஒருங்கிணைந்த", "label.filter-raw": "மூல", "label.filters": "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.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", @@ -122,10 +126,12 @@ "label.reset": "மீட்டமை", "label.reset-website": "Reset statistics", "label.retention": "Retention", + "label.retention-description": "Measure you website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "சேமி", "label.screens": "Screens", + "label.search": "Search", "label.select-date": "Select date", "label.select-website": "Select website", "label.sessions": "Sessions", diff --git a/src/lang/th-TH.json b/src/lang/th-TH.json index 43f2f7587..1ddaa4d01 100644 --- a/src/lang/th-TH.json +++ b/src/lang/th-TH.json @@ -29,6 +29,7 @@ "label.continue": "Continue", "label.countries": "ประเทศ", "label.country": "Country", + "label.create": "Create", "label.create-report": "Create report", "label.create-team": "Create team", "label.create-user": "Create user", @@ -63,13 +64,16 @@ "label.false": "False", "label.field": "Field", "label.fields": "Fields", + "label.filter": "Filter", "label.filter-combined": "ข้อมูลรวม", "label.filter-raw": "ข้อมูลดิบ", "label.filters": "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.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", @@ -122,10 +126,12 @@ "label.reset": "รีเซต", "label.reset-website": "รีเซตข้อมูลสถิติ", "label.retention": "Retention", + "label.retention-description": "Measure you website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "บันทึก", "label.screens": "ขนาดหน้าจอ", + "label.search": "Search", "label.select-date": "Select date", "label.select-website": "Select website", "label.sessions": "Sessions", diff --git a/src/lang/tr-TR.json b/src/lang/tr-TR.json index 0ec10e0b9..b333131fb 100644 --- a/src/lang/tr-TR.json +++ b/src/lang/tr-TR.json @@ -29,6 +29,7 @@ "label.continue": "Continue", "label.countries": "Ülkeler", "label.country": "Country", + "label.create": "Create", "label.create-report": "Create report", "label.create-team": "Create team", "label.create-user": "Create user", @@ -63,13 +64,16 @@ "label.false": "False", "label.field": "Field", "label.fields": "Fields", + "label.filter": "Filter", "label.filter-combined": "Birleşik", "label.filter-raw": "Ham", "label.filters": "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.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", @@ -122,10 +126,12 @@ "label.reset": "Sıfırla", "label.reset-website": "Reset statistics", "label.retention": "Retention", + "label.retention-description": "Measure you website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Kaydet", "label.screens": "Ekranlar", + "label.search": "Search", "label.select-date": "Select date", "label.select-website": "Select website", "label.sessions": "Sessions", diff --git a/src/lang/uk-UA.json b/src/lang/uk-UA.json index 89079eff2..e95815f13 100644 --- a/src/lang/uk-UA.json +++ b/src/lang/uk-UA.json @@ -29,6 +29,7 @@ "label.continue": "Continue", "label.countries": "Країни", "label.country": "Country", + "label.create": "Create", "label.create-report": "Create report", "label.create-team": "Create team", "label.create-user": "Create user", @@ -63,13 +64,16 @@ "label.false": "False", "label.field": "Field", "label.fields": "Fields", + "label.filter": "Filter", "label.filter-combined": "Об'єднані", "label.filter-raw": "Сирі дані", "label.filters": "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.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", @@ -122,10 +126,12 @@ "label.reset": "Скинути", "label.reset-website": "Скинути статистику сайту", "label.retention": "Retention", + "label.retention-description": "Measure you website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Зберегти", "label.screens": "Screens", + "label.search": "Search", "label.select-date": "Select date", "label.select-website": "Select website", "label.sessions": "Sessions", diff --git a/src/lang/ur-PK.json b/src/lang/ur-PK.json index 4d585dcbc..9fbfb0797 100644 --- a/src/lang/ur-PK.json +++ b/src/lang/ur-PK.json @@ -29,6 +29,7 @@ "label.continue": "Continue", "label.countries": "ممالک", "label.country": "Country", + "label.create": "Create", "label.create-report": "Create report", "label.create-team": "Create team", "label.create-user": "Create user", @@ -63,13 +64,16 @@ "label.false": "False", "label.field": "Field", "label.fields": "Fields", + "label.filter": "Filter", "label.filter-combined": "مشترکہ", "label.filter-raw": "خام", "label.filters": "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.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", @@ -122,10 +126,12 @@ "label.reset": "دوبارہ ترتیب دیں", "label.reset-website": "اعدادوشمار کو دوبارہ ترتیب دیں", "label.retention": "Retention", + "label.retention-description": "Measure you website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "محفوظ کریں", "label.screens": "Screens", + "label.search": "Search", "label.select-date": "Select date", "label.select-website": "Select website", "label.sessions": "Sessions", diff --git a/src/lang/vi-VN.json b/src/lang/vi-VN.json index e9bce2d3c..ff2915c79 100644 --- a/src/lang/vi-VN.json +++ b/src/lang/vi-VN.json @@ -29,6 +29,7 @@ "label.continue": "Continue", "label.countries": "Quốc gia", "label.country": "Country", + "label.create": "Create", "label.create-report": "Create report", "label.create-team": "Create team", "label.create-user": "Create user", @@ -63,13 +64,16 @@ "label.false": "False", "label.field": "Field", "label.fields": "Fields", + "label.filter": "Filter", "label.filter-combined": "Kết hợp", "label.filter-raw": "Gốc", "label.filters": "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.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", @@ -122,10 +126,12 @@ "label.reset": "Tái thiết lập", "label.reset-website": "Tái thiết lập thống kê", "label.retention": "Retention", + "label.retention-description": "Measure you website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Lưu", "label.screens": "Screens", + "label.search": "Search", "label.select-date": "Select date", "label.select-website": "Select website", "label.sessions": "Sessions", diff --git a/src/lang/zh-CN.json b/src/lang/zh-CN.json index bab833c02..2ebe75f2e 100644 --- a/src/lang/zh-CN.json +++ b/src/lang/zh-CN.json @@ -29,6 +29,7 @@ "label.continue": "继续", "label.countries": "国家/地区", "label.country": "国家/地区", + "label.create": "Create", "label.create-report": "创建报告", "label.create-team": "创建团队", "label.create-user": "创建用户", @@ -63,13 +64,16 @@ "label.false": "否", "label.field": "Field", "label.fields": "Fields", + "label.filter": "Filter", "label.filter-combined": "合并", "label.filter-raw": "原始", "label.filters": "筛选", "label.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.insights": "见解", + "label.insights-description": "Dive deeper into your data by using segments and filters.", "label.is": "等于", "label.is-not": "不等于", "label.is-not-set": "未设置", @@ -122,10 +126,12 @@ "label.reset": "重置", "label.reset-website": "重置统计数据", "label.retention": "保留", + "label.retention-description": "Measure you website stickiness by tracking how often users return.", "label.role": "角色", "label.run-query": "查询", "label.save": "保存", "label.screens": "屏幕尺寸", + "label.search": "Search", "label.select-date": "选择数据", "label.select-website": "选择网站", "label.sessions": "会话", diff --git a/src/lang/zh-TW.json b/src/lang/zh-TW.json index 05b61c806..22291ed06 100644 --- a/src/lang/zh-TW.json +++ b/src/lang/zh-TW.json @@ -29,6 +29,7 @@ "label.continue": "繼續", "label.countries": "國家", "label.country": "國家", + "label.create": "Create", "label.create-report": "建立報告", "label.create-team": "建立團隊", "label.create-user": "建立使用者", @@ -63,13 +64,16 @@ "label.false": "否", "label.field": "欄位", "label.fields": "欄位", + "label.filter": "Filter", "label.filter-combined": "組合", "label.filter-raw": "原始", "label.filters": "篩選器", "label.funnel": "漏斗", + "label.funnel-description": "Understand the conversion and drop-off rate of users.", "label.greater-than": "大於", "label.greater-than-equals": "大於或等於", "label.insights": "洞察", + "label.insights-description": "Dive deeper into your data by using segments and filters.", "label.is": "是", "label.is-not": "不是", "label.is-not-set": "未設定", @@ -122,10 +126,12 @@ "label.reset": "重設", "label.reset-website": "重設網站", "label.retention": "保留", + "label.retention-description": "Measure you website stickiness by tracking how often users return.", "label.role": "角色", "label.run-query": "執行查詢", "label.save": "儲存", "label.screens": "螢幕", + "label.search": "Search", "label.select-date": "選擇日期", "label.select-website": "選擇網站", "label.sessions": "工作階段", From aa341d1dd295d69adb400960ba5f3fb0317e64f2 Mon Sep 17 00:00:00 2001 From: Maxime-J Date: Fri, 1 Sep 2023 09:45:59 +0000 Subject: [PATCH 080/113] ensure translation of default report name --- src/components/hooks/useReport.js | 14 ++++++++------ src/components/pages/reports/ReportHeader.js | 5 +++-- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/components/hooks/useReport.js b/src/components/hooks/useReport.js index 72f90af33..7c698b4e7 100644 --- a/src/components/hooks/useReport.js +++ b/src/components/hooks/useReport.js @@ -2,18 +2,20 @@ import { produce } from 'immer'; import { useCallback, useEffect, useState } from 'react'; import { useTimezone } from './useTimezone'; import useApi from './useApi'; - -const baseParameters = { - name: 'Untitled', - description: '', - parameters: {}, -}; +import useMessages from './useMessages'; export function useReport(reportId, defaultParameters) { const [report, setReport] = useState(null); const [isRunning, setIsRunning] = useState(false); const { get, post } = useApi(); const [timezone] = useTimezone(); + const { formatMessage, labels } = useMessages(); + + const baseParameters = { + name: formatMessage(labels.untitled), + description: '', + parameters: {}, + }; const loadReport = async id => { const data = await get(`/reports/${id}`); diff --git a/src/components/pages/reports/ReportHeader.js b/src/components/pages/reports/ReportHeader.js index e81d6ece6..930f745b9 100644 --- a/src/components/pages/reports/ReportHeader.js +++ b/src/components/pages/reports/ReportHeader.js @@ -20,6 +20,7 @@ export function ReportHeader({ icon }) { const { name, description, parameters } = report || {}; const { websiteId, dateRange } = parameters || {}; + const defaultName = formatMessage(labels.untitled); const handleSave = async () => { if (!report.id) { @@ -39,7 +40,7 @@ export function ReportHeader({ icon }) { }; const handleNameChange = name => { - updateReport({ name: name || 'Untitled' }); + updateReport({ name: name || defaultName }); }; const handleDescriptionChange = description => { @@ -54,7 +55,7 @@ export function ReportHeader({ icon }) { key={name} name="name" value={name} - placeholder={formatMessage(labels.untitled)} + placeholder={defaultName} onCommit={handleNameChange} /> From 34d3d166415aa0037d87baa91e26348c873ee96a Mon Sep 17 00:00:00 2001 From: Maxime-J Date: Fri, 1 Sep 2023 12:25:13 +0000 Subject: [PATCH 081/113] display localized type in reports table --- src/components/pages/reports/ReportsTable.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/components/pages/reports/ReportsTable.js b/src/components/pages/reports/ReportsTable.js index 4073fbec0..52488c11e 100644 --- a/src/components/pages/reports/ReportsTable.js +++ b/src/components/pages/reports/ReportsTable.js @@ -5,6 +5,7 @@ import { useMessages } from 'components/hooks'; import useUser from 'components/hooks/useUser'; import { useState } from 'react'; import { Button, Flexbox, Icon, Icons, Modal, Text } from 'react-basics'; +import { REPORT_TYPES } from 'lib/constants'; export function ReportsTable({ data = [], @@ -34,6 +35,15 @@ export function ReportsTable({ { name: 'action', label: ' ' }, ]; + const cellRender = (row, data, key) => { + if (key === 'type') { + return formatMessage( + labels[Object.keys(REPORT_TYPES).find(key => REPORT_TYPES[key] === row.type)], + ); + } + return data[key]; + }; + const handleConfirm = () => { onDelete(report.id); }; @@ -42,6 +52,7 @@ export function ReportsTable({ <> Date: Fri, 1 Sep 2023 14:15:57 +0000 Subject: [PATCH 082/113] localize date in retention report --- src/components/pages/reports/retention/RetentionTable.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/pages/reports/retention/RetentionTable.js b/src/components/pages/reports/retention/RetentionTable.js index 09ef2948f..ad1eaa6f9 100644 --- a/src/components/pages/reports/retention/RetentionTable.js +++ b/src/components/pages/reports/retention/RetentionTable.js @@ -3,11 +3,13 @@ import classNames from 'classnames'; import { ReportContext } from '../Report'; import EmptyPlaceholder from 'components/common/EmptyPlaceholder'; import { useMessages } from 'components/hooks'; +import { useLocale } from 'components/hooks'; import { formatDate } from 'lib/date'; import styles from './RetentionTable.module.css'; export function RetentionTable() { const { formatMessage, labels } = useMessages(); + const { locale } = useLocale(); const { report } = useContext(ReportContext); const { data } = report || {}; @@ -51,7 +53,7 @@ export function RetentionTable() { {rows.map(({ date, visitors, records }, rowIndex) => { return (
-
{formatDate(`${date} 00:00:00`, 'PP')}
+
{formatDate(`${date} 00:00:00`, 'PP', locale)}
{visitors}
{days.map(day => { if (totalDays - rowIndex < day) { From ee6fcae152405262ff1b65ab0d46421f5e833c75 Mon Sep 17 00:00:00 2001 From: Maxime-J Date: Fri, 1 Sep 2023 14:20:50 +0000 Subject: [PATCH 083/113] fix typo --- src/components/messages.js | 2 +- src/lang/am-ET.json | 2 +- src/lang/ar-SA.json | 2 +- src/lang/be-BY.json | 2 +- src/lang/bn-BD.json | 2 +- src/lang/ca-ES.json | 2 +- src/lang/cs-CZ.json | 2 +- src/lang/da-DK.json | 2 +- src/lang/de-CH.json | 2 +- src/lang/de-DE.json | 2 +- src/lang/el-GR.json | 2 +- src/lang/en-GB.json | 2 +- src/lang/en-US.json | 2 +- src/lang/es-ES.json | 2 +- src/lang/es-MX.json | 2 +- src/lang/fa-IR.json | 2 +- src/lang/fi-FI.json | 2 +- src/lang/fo-FO.json | 2 +- src/lang/fr-FR.json | 2 +- src/lang/ga-ES.json | 2 +- src/lang/he-IL.json | 2 +- src/lang/hi-IN.json | 2 +- src/lang/hr-HR.json | 2 +- src/lang/hu-HU.json | 2 +- src/lang/id-ID.json | 2 +- src/lang/it-IT.json | 2 +- src/lang/ja-JP.json | 2 +- src/lang/km-KH.json | 2 +- src/lang/ko-KR.json | 2 +- src/lang/lt-LT.json | 2 +- src/lang/mn-MN.json | 2 +- src/lang/ms-MY.json | 2 +- src/lang/my-MM.json | 2 +- src/lang/nb-NO.json | 2 +- src/lang/nl-NL.json | 2 +- src/lang/pl-PL.json | 2 +- src/lang/pt-BR.json | 2 +- src/lang/pt-PT.json | 2 +- src/lang/ro-RO.json | 2 +- src/lang/ru-RU.json | 2 +- src/lang/si-LK.json | 2 +- src/lang/sk-SK.json | 2 +- src/lang/sl-SI.json | 2 +- src/lang/sv-SE.json | 2 +- src/lang/ta-IN.json | 2 +- src/lang/th-TH.json | 2 +- src/lang/tr-TR.json | 2 +- src/lang/uk-UA.json | 2 +- src/lang/ur-PK.json | 2 +- src/lang/vi-VN.json | 2 +- src/lang/zh-CN.json | 2 +- src/lang/zh-TW.json | 2 +- 52 files changed, 52 insertions(+), 52 deletions(-) diff --git a/src/components/messages.js b/src/components/messages.js index 01c7e779c..7f432eb3e 100644 --- a/src/components/messages.js +++ b/src/components/messages.js @@ -178,7 +178,7 @@ export const labels = defineMessages({ retention: { id: 'label.retention', defaultMessage: 'Retention' }, retentionDescription: { id: 'label.retention-description', - defaultMessage: 'Measure you website stickiness by tracking how often users return.', + defaultMessage: 'Measure your website stickiness by tracking how often users return.', }, dropoff: { id: 'label.dropoff', defaultMessage: 'Dropoff' }, referrer: { id: 'label.referrer', defaultMessage: 'Referrer' }, diff --git a/src/lang/am-ET.json b/src/lang/am-ET.json index 3765e5ba6..e79afb487 100644 --- a/src/lang/am-ET.json +++ b/src/lang/am-ET.json @@ -126,7 +126,7 @@ "label.reset": "Reset", "label.reset-website": "Reset statistics", "label.retention": "Retention", - "label.retention-description": "Measure you website stickiness by tracking how often users return.", + "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Save", diff --git a/src/lang/ar-SA.json b/src/lang/ar-SA.json index ccfee1f33..311e54305 100644 --- a/src/lang/ar-SA.json +++ b/src/lang/ar-SA.json @@ -126,7 +126,7 @@ "label.reset": "اعادة تعيين", "label.reset-website": "اعادة تعيين الإحصائيات", "label.retention": "Retention", - "label.retention-description": "Measure you website stickiness by tracking how often users return.", + "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.role": "الصلاحية", "label.run-query": "Run query", "label.save": "حفظ", diff --git a/src/lang/be-BY.json b/src/lang/be-BY.json index 88f673b9c..dc0be21d5 100644 --- a/src/lang/be-BY.json +++ b/src/lang/be-BY.json @@ -126,7 +126,7 @@ "label.reset": "Скінуць", "label.reset-website": "Скінуць статыстыку", "label.retention": "Retention", - "label.retention-description": "Measure you website stickiness by tracking how often users return.", + "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Захаваць", diff --git a/src/lang/bn-BD.json b/src/lang/bn-BD.json index 29e1bb6f6..201157ac1 100644 --- a/src/lang/bn-BD.json +++ b/src/lang/bn-BD.json @@ -126,7 +126,7 @@ "label.reset": "রিসেট", "label.reset-website": "ওয়েবসাইট রিসেট করুন", "label.retention": "Retention", - "label.retention-description": "Measure you website stickiness by tracking how often users return.", + "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "সংরক্ষণ", diff --git a/src/lang/ca-ES.json b/src/lang/ca-ES.json index 271b9245a..e55d90da4 100644 --- a/src/lang/ca-ES.json +++ b/src/lang/ca-ES.json @@ -126,7 +126,7 @@ "label.reset": "Restableix", "label.reset-website": "Restableix estadístiques", "label.retention": "Retention", - "label.retention-description": "Measure you website stickiness by tracking how often users return.", + "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Desa", diff --git a/src/lang/cs-CZ.json b/src/lang/cs-CZ.json index 73bc15b70..86f2043a8 100644 --- a/src/lang/cs-CZ.json +++ b/src/lang/cs-CZ.json @@ -126,7 +126,7 @@ "label.reset": "Reset", "label.reset-website": "Reset statistics", "label.retention": "Retention", - "label.retention-description": "Measure you website stickiness by tracking how often users return.", + "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Uložit", diff --git a/src/lang/da-DK.json b/src/lang/da-DK.json index 2fba4f7a7..8df7dd6bf 100644 --- a/src/lang/da-DK.json +++ b/src/lang/da-DK.json @@ -126,7 +126,7 @@ "label.reset": "Nulstil", "label.reset-website": "Nulstil statistikker", "label.retention": "Retention", - "label.retention-description": "Measure you website stickiness by tracking how often users return.", + "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Gem", diff --git a/src/lang/de-CH.json b/src/lang/de-CH.json index c07ddd2cb..95ba3b6a8 100644 --- a/src/lang/de-CH.json +++ b/src/lang/de-CH.json @@ -126,7 +126,7 @@ "label.reset": "Zruggsetze", "label.reset-website": "Statistik zruggsetze", "label.retention": "Retention", - "label.retention-description": "Measure you website stickiness by tracking how often users return.", + "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.role": "Rollä", "label.run-query": "Run query", "label.save": "Speichere", diff --git a/src/lang/de-DE.json b/src/lang/de-DE.json index 7bac16255..0724c181b 100644 --- a/src/lang/de-DE.json +++ b/src/lang/de-DE.json @@ -126,7 +126,7 @@ "label.reset": "Zurücksetzen", "label.reset-website": "Statistik zurücksetzen", "label.retention": "Retention", - "label.retention-description": "Measure you website stickiness by tracking how often users return.", + "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.role": "Rolle", "label.run-query": "Abfrage starten", "label.save": "Speichern", diff --git a/src/lang/el-GR.json b/src/lang/el-GR.json index c5cea1bee..f93742fdd 100644 --- a/src/lang/el-GR.json +++ b/src/lang/el-GR.json @@ -126,7 +126,7 @@ "label.reset": "Επαναφορά", "label.reset-website": "Reset statistics", "label.retention": "Retention", - "label.retention-description": "Measure you website stickiness by tracking how often users return.", + "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Αποθήκευση", diff --git a/src/lang/en-GB.json b/src/lang/en-GB.json index e93b3b23a..b6cb2c9a3 100644 --- a/src/lang/en-GB.json +++ b/src/lang/en-GB.json @@ -126,7 +126,7 @@ "label.reset": "Reset", "label.reset-website": "Reset statistics", "label.retention": "Retention", - "label.retention-description": "Measure you website stickiness by tracking how often users return.", + "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Save", diff --git a/src/lang/en-US.json b/src/lang/en-US.json index 16dfa1888..e1d592303 100644 --- a/src/lang/en-US.json +++ b/src/lang/en-US.json @@ -126,7 +126,7 @@ "label.reset": "Reset", "label.reset-website": "Reset website", "label.retention": "Retention", - "label.retention-description": "Measure you website stickiness by tracking how often users return.", + "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Save", diff --git a/src/lang/es-ES.json b/src/lang/es-ES.json index 001b94064..ef8c31a80 100644 --- a/src/lang/es-ES.json +++ b/src/lang/es-ES.json @@ -126,7 +126,7 @@ "label.reset": "Reiniciar", "label.reset-website": "Reiniciar estadísticas", "label.retention": "Retention", - "label.retention-description": "Measure you website stickiness by tracking how often users return.", + "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.role": "Rol", "label.run-query": "Ejecutar consulta", "label.save": "Guardar", diff --git a/src/lang/es-MX.json b/src/lang/es-MX.json index c1dacfa44..d8110b404 100644 --- a/src/lang/es-MX.json +++ b/src/lang/es-MX.json @@ -126,7 +126,7 @@ "label.reset": "Reiniciar", "label.reset-website": "Reiniciar estadísticas", "label.retention": "Retention", - "label.retention-description": "Measure you website stickiness by tracking how often users return.", + "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.role": "Rol", "label.run-query": "Run query", "label.save": "Guardar", diff --git a/src/lang/fa-IR.json b/src/lang/fa-IR.json index 32d985e3e..0458e3c69 100644 --- a/src/lang/fa-IR.json +++ b/src/lang/fa-IR.json @@ -126,7 +126,7 @@ "label.reset": "بازنشانی", "label.reset-website": "بازنشانی آمار", "label.retention": "Retention", - "label.retention-description": "Measure you website stickiness by tracking how often users return.", + "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "ذخیره", diff --git a/src/lang/fi-FI.json b/src/lang/fi-FI.json index 8c447f8a1..52d882386 100644 --- a/src/lang/fi-FI.json +++ b/src/lang/fi-FI.json @@ -126,7 +126,7 @@ "label.reset": "Nollaa", "label.reset-website": "Nollaa tilastot", "label.retention": "Retention", - "label.retention-description": "Measure you website stickiness by tracking how often users return.", + "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Tallenna", diff --git a/src/lang/fo-FO.json b/src/lang/fo-FO.json index e2626f1fb..ef5b0bc1b 100644 --- a/src/lang/fo-FO.json +++ b/src/lang/fo-FO.json @@ -126,7 +126,7 @@ "label.reset": "Nulstilla", "label.reset-website": "Reset statistics", "label.retention": "Retention", - "label.retention-description": "Measure you website stickiness by tracking how often users return.", + "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Goym", diff --git a/src/lang/fr-FR.json b/src/lang/fr-FR.json index 878e078aa..092837eb5 100644 --- a/src/lang/fr-FR.json +++ b/src/lang/fr-FR.json @@ -126,7 +126,7 @@ "label.reset": "Réinitialiser", "label.reset-website": "Réinitialiser les statistiques", "label.retention": "Retention", - "label.retention-description": "Measure you website stickiness by tracking how often users return.", + "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.role": "Rôle", "label.run-query": "Éxécuter la requête", "label.save": "Enregistrer", diff --git a/src/lang/ga-ES.json b/src/lang/ga-ES.json index ae46fa2c5..2a2d16c9c 100644 --- a/src/lang/ga-ES.json +++ b/src/lang/ga-ES.json @@ -126,7 +126,7 @@ "label.reset": "Restablecer", "label.reset-website": "To reset this website, type {confirmation} in the box below to confirm.", "label.retention": "Retention", - "label.retention-description": "Measure you website stickiness by tracking how often users return.", + "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Gardar", diff --git a/src/lang/he-IL.json b/src/lang/he-IL.json index b953fda60..04912335d 100644 --- a/src/lang/he-IL.json +++ b/src/lang/he-IL.json @@ -126,7 +126,7 @@ "label.reset": "איפוס", "label.reset-website": "Reset statistics", "label.retention": "Retention", - "label.retention-description": "Measure you website stickiness by tracking how often users return.", + "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "שמירה", diff --git a/src/lang/hi-IN.json b/src/lang/hi-IN.json index e296d87bf..c872fd1a9 100644 --- a/src/lang/hi-IN.json +++ b/src/lang/hi-IN.json @@ -126,7 +126,7 @@ "label.reset": "रीसेट", "label.reset-website": "Reset statistics", "label.retention": "Retention", - "label.retention-description": "Measure you website stickiness by tracking how often users return.", + "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "सहेजें", diff --git a/src/lang/hr-HR.json b/src/lang/hr-HR.json index 75bd8a4f3..55feb48bd 100644 --- a/src/lang/hr-HR.json +++ b/src/lang/hr-HR.json @@ -126,7 +126,7 @@ "label.reset": "Resetirati", "label.reset-website": "Resetirati web stranicu", "label.retention": "Retention", - "label.retention-description": "Measure you website stickiness by tracking how often users return.", + "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Spremi", diff --git a/src/lang/hu-HU.json b/src/lang/hu-HU.json index c6224b01c..407687f2e 100644 --- a/src/lang/hu-HU.json +++ b/src/lang/hu-HU.json @@ -126,7 +126,7 @@ "label.reset": "Visszaállítás", "label.reset-website": "Reset statistics", "label.retention": "Retention", - "label.retention-description": "Measure you website stickiness by tracking how often users return.", + "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Mentés", diff --git a/src/lang/id-ID.json b/src/lang/id-ID.json index 856727650..64fed9e1f 100644 --- a/src/lang/id-ID.json +++ b/src/lang/id-ID.json @@ -126,7 +126,7 @@ "label.reset": "Atur ulang", "label.reset-website": "Atur ulang statistik", "label.retention": "Retention", - "label.retention-description": "Measure you website stickiness by tracking how often users return.", + "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Simpan", diff --git a/src/lang/it-IT.json b/src/lang/it-IT.json index 8bce2f4e0..29c664b5b 100644 --- a/src/lang/it-IT.json +++ b/src/lang/it-IT.json @@ -126,7 +126,7 @@ "label.reset": "Reset", "label.reset-website": "Resetta le statistiche", "label.retention": "Retention", - "label.retention-description": "Measure you website stickiness by tracking how often users return.", + "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Salva", diff --git a/src/lang/ja-JP.json b/src/lang/ja-JP.json index 3af2f7b0a..8e26205e4 100644 --- a/src/lang/ja-JP.json +++ b/src/lang/ja-JP.json @@ -126,7 +126,7 @@ "label.reset": "リセット", "label.reset-website": "Webサイトをリセットする", "label.retention": "保持", - "label.retention-description": "Measure you website stickiness by tracking how often users return.", + "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.role": "ロール", "label.run-query": "クエリ実行", "label.save": "保存", diff --git a/src/lang/km-KH.json b/src/lang/km-KH.json index 3f7d089d1..2333fe6b8 100644 --- a/src/lang/km-KH.json +++ b/src/lang/km-KH.json @@ -126,7 +126,7 @@ "label.reset": "កំណត់ឡើងវិញ", "label.reset-website": "កំណត់ស្ថិតិឡើងវិញ", "label.retention": "Retention", - "label.retention-description": "Measure you website stickiness by tracking how often users return.", + "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "រក្សាទុក", diff --git a/src/lang/ko-KR.json b/src/lang/ko-KR.json index dcbdd77c5..b4b7d566b 100644 --- a/src/lang/ko-KR.json +++ b/src/lang/ko-KR.json @@ -126,7 +126,7 @@ "label.reset": "리셋", "label.reset-website": "Reset statistics", "label.retention": "Retention", - "label.retention-description": "Measure you website stickiness by tracking how often users return.", + "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "저장", diff --git a/src/lang/lt-LT.json b/src/lang/lt-LT.json index aa75f10f7..13f2b06b5 100644 --- a/src/lang/lt-LT.json +++ b/src/lang/lt-LT.json @@ -126,7 +126,7 @@ "label.reset": "Atstatyti", "label.reset-website": "Atstatyti statistikos duomenis", "label.retention": "Retention", - "label.retention-description": "Measure you website stickiness by tracking how often users return.", + "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Išsaugoti", diff --git a/src/lang/mn-MN.json b/src/lang/mn-MN.json index aad28ef20..ecb4e1fb2 100644 --- a/src/lang/mn-MN.json +++ b/src/lang/mn-MN.json @@ -126,7 +126,7 @@ "label.reset": "Дахин эхлүүлэх", "label.reset-website": "Тоон үзүүлэлтийг дахин эхлүүлэх", "label.retention": "Retention", - "label.retention-description": "Measure you website stickiness by tracking how often users return.", + "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.role": "Эрх", "label.run-query": "Run query", "label.save": "Хадгалах", diff --git a/src/lang/ms-MY.json b/src/lang/ms-MY.json index af5c34f07..256a4d0b6 100644 --- a/src/lang/ms-MY.json +++ b/src/lang/ms-MY.json @@ -126,7 +126,7 @@ "label.reset": "Tetapkan semula", "label.reset-website": "Reset statistics", "label.retention": "Retention", - "label.retention-description": "Measure you website stickiness by tracking how often users return.", + "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Simpan", diff --git a/src/lang/my-MM.json b/src/lang/my-MM.json index 8253705ab..bdfa3c6ab 100644 --- a/src/lang/my-MM.json +++ b/src/lang/my-MM.json @@ -126,7 +126,7 @@ "label.reset": "ပြန်စမည်", "label.reset-website": "ဝက်ဘ်ဆိုဒ်ဒေတာကိုဖျက်မည်", "label.retention": "Retention", - "label.retention-description": "Measure you website stickiness by tracking how often users return.", + "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.role": "အခန်းကဏ္ဍ", "label.run-query": "Query ကိုလုပ်ဆောင်မည်", "label.save": "သိမ်းဆည်းမည်", diff --git a/src/lang/nb-NO.json b/src/lang/nb-NO.json index 18fa765ee..5744d211c 100644 --- a/src/lang/nb-NO.json +++ b/src/lang/nb-NO.json @@ -126,7 +126,7 @@ "label.reset": "Nullstill", "label.reset-website": "Nullstill statistikk", "label.retention": "Retention", - "label.retention-description": "Measure you website stickiness by tracking how often users return.", + "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Lagre", diff --git a/src/lang/nl-NL.json b/src/lang/nl-NL.json index d0c3f6782..9dfcbb92a 100644 --- a/src/lang/nl-NL.json +++ b/src/lang/nl-NL.json @@ -126,7 +126,7 @@ "label.reset": "Opnieuw instellen", "label.reset-website": "Statistieken opnieuw instellen", "label.retention": "Retention", - "label.retention-description": "Measure you website stickiness by tracking how often users return.", + "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.role": "Gebruikersrol", "label.run-query": "Run query", "label.save": "Opslaan", diff --git a/src/lang/pl-PL.json b/src/lang/pl-PL.json index 8045af067..37a77b2e6 100644 --- a/src/lang/pl-PL.json +++ b/src/lang/pl-PL.json @@ -126,7 +126,7 @@ "label.reset": "Zresetuj", "label.reset-website": "Zresetuj statystyki", "label.retention": "Retention", - "label.retention-description": "Measure you website stickiness by tracking how often users return.", + "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Uruchom zapytanie", "label.save": "Zapisz", diff --git a/src/lang/pt-BR.json b/src/lang/pt-BR.json index 22169e3ae..ae3459863 100644 --- a/src/lang/pt-BR.json +++ b/src/lang/pt-BR.json @@ -126,7 +126,7 @@ "label.reset": "Redefinir", "label.reset-website": "Redefinir estatísticas", "label.retention": "Retention", - "label.retention-description": "Measure you website stickiness by tracking how often users return.", + "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.role": "Papel", "label.run-query": "Executar query", "label.save": "Salvar", diff --git a/src/lang/pt-PT.json b/src/lang/pt-PT.json index 28a798e31..3e1df4de8 100644 --- a/src/lang/pt-PT.json +++ b/src/lang/pt-PT.json @@ -126,7 +126,7 @@ "label.reset": "Repor", "label.reset-website": "Repor estatísticas", "label.retention": "Retention", - "label.retention-description": "Measure you website stickiness by tracking how often users return.", + "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Guardar", diff --git a/src/lang/ro-RO.json b/src/lang/ro-RO.json index 9c8c8c3c1..d3b9d3db8 100644 --- a/src/lang/ro-RO.json +++ b/src/lang/ro-RO.json @@ -126,7 +126,7 @@ "label.reset": "Resetează", "label.reset-website": "Resetează statisticile pentru site", "label.retention": "Retention", - "label.retention-description": "Measure you website stickiness by tracking how often users return.", + "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Salvează", diff --git a/src/lang/ru-RU.json b/src/lang/ru-RU.json index 6eed37257..3063cbfa9 100644 --- a/src/lang/ru-RU.json +++ b/src/lang/ru-RU.json @@ -126,7 +126,7 @@ "label.reset": "Сбросить", "label.reset-website": "Сбросить статистику", "label.retention": "Retention", - "label.retention-description": "Measure you website stickiness by tracking how often users return.", + "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.role": "Роль", "label.run-query": "Run query", "label.save": "Сохранить", diff --git a/src/lang/si-LK.json b/src/lang/si-LK.json index 92bbe7360..d9a61eb0a 100644 --- a/src/lang/si-LK.json +++ b/src/lang/si-LK.json @@ -126,7 +126,7 @@ "label.reset": "යළි පිහිටුවන්න", "label.reset-website": "සංඛ්යා ලේඛන නැවත සකසන්න", "label.retention": "Retention", - "label.retention-description": "Measure you website stickiness by tracking how often users return.", + "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "සුරකින්න", diff --git a/src/lang/sk-SK.json b/src/lang/sk-SK.json index 534ace423..7d9073dd6 100644 --- a/src/lang/sk-SK.json +++ b/src/lang/sk-SK.json @@ -126,7 +126,7 @@ "label.reset": "Reset", "label.reset-website": "Reset statistics", "label.retention": "Retention", - "label.retention-description": "Measure you website stickiness by tracking how often users return.", + "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Uložiť", diff --git a/src/lang/sl-SI.json b/src/lang/sl-SI.json index f73aa265f..1863eb879 100644 --- a/src/lang/sl-SI.json +++ b/src/lang/sl-SI.json @@ -126,7 +126,7 @@ "label.reset": "Ponastavi", "label.reset-website": "Ponastavi statistiko", "label.retention": "Ohranjanje uporabnikov", - "label.retention-description": "Measure you website stickiness by tracking how often users return.", + "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.role": "Vloga", "label.run-query": "Izvedi poizvedbo", "label.save": "Shrani", diff --git a/src/lang/sv-SE.json b/src/lang/sv-SE.json index 532b9039d..1496594f8 100644 --- a/src/lang/sv-SE.json +++ b/src/lang/sv-SE.json @@ -126,7 +126,7 @@ "label.reset": "Återställ", "label.reset-website": "Återställ statistik", "label.retention": "Retention", - "label.retention-description": "Measure you website stickiness by tracking how often users return.", + "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.role": "Roll", "label.run-query": "Run query", "label.save": "Spara", diff --git a/src/lang/ta-IN.json b/src/lang/ta-IN.json index 64b6bf2ba..53b7659e8 100644 --- a/src/lang/ta-IN.json +++ b/src/lang/ta-IN.json @@ -126,7 +126,7 @@ "label.reset": "மீட்டமை", "label.reset-website": "Reset statistics", "label.retention": "Retention", - "label.retention-description": "Measure you website stickiness by tracking how often users return.", + "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "சேமி", diff --git a/src/lang/th-TH.json b/src/lang/th-TH.json index 1ddaa4d01..ee2fc19c4 100644 --- a/src/lang/th-TH.json +++ b/src/lang/th-TH.json @@ -126,7 +126,7 @@ "label.reset": "รีเซต", "label.reset-website": "รีเซตข้อมูลสถิติ", "label.retention": "Retention", - "label.retention-description": "Measure you website stickiness by tracking how often users return.", + "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "บันทึก", diff --git a/src/lang/tr-TR.json b/src/lang/tr-TR.json index b333131fb..6eac527b3 100644 --- a/src/lang/tr-TR.json +++ b/src/lang/tr-TR.json @@ -126,7 +126,7 @@ "label.reset": "Sıfırla", "label.reset-website": "Reset statistics", "label.retention": "Retention", - "label.retention-description": "Measure you website stickiness by tracking how often users return.", + "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Kaydet", diff --git a/src/lang/uk-UA.json b/src/lang/uk-UA.json index e95815f13..959956487 100644 --- a/src/lang/uk-UA.json +++ b/src/lang/uk-UA.json @@ -126,7 +126,7 @@ "label.reset": "Скинути", "label.reset-website": "Скинути статистику сайту", "label.retention": "Retention", - "label.retention-description": "Measure you website stickiness by tracking how often users return.", + "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Зберегти", diff --git a/src/lang/ur-PK.json b/src/lang/ur-PK.json index 9fbfb0797..5edaddd81 100644 --- a/src/lang/ur-PK.json +++ b/src/lang/ur-PK.json @@ -126,7 +126,7 @@ "label.reset": "دوبارہ ترتیب دیں", "label.reset-website": "اعدادوشمار کو دوبارہ ترتیب دیں", "label.retention": "Retention", - "label.retention-description": "Measure you website stickiness by tracking how often users return.", + "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "محفوظ کریں", diff --git a/src/lang/vi-VN.json b/src/lang/vi-VN.json index ff2915c79..9c629100b 100644 --- a/src/lang/vi-VN.json +++ b/src/lang/vi-VN.json @@ -126,7 +126,7 @@ "label.reset": "Tái thiết lập", "label.reset-website": "Tái thiết lập thống kê", "label.retention": "Retention", - "label.retention-description": "Measure you website stickiness by tracking how often users return.", + "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.role": "Role", "label.run-query": "Run query", "label.save": "Lưu", diff --git a/src/lang/zh-CN.json b/src/lang/zh-CN.json index 2ebe75f2e..c41602802 100644 --- a/src/lang/zh-CN.json +++ b/src/lang/zh-CN.json @@ -126,7 +126,7 @@ "label.reset": "重置", "label.reset-website": "重置统计数据", "label.retention": "保留", - "label.retention-description": "Measure you website stickiness by tracking how often users return.", + "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.role": "角色", "label.run-query": "查询", "label.save": "保存", diff --git a/src/lang/zh-TW.json b/src/lang/zh-TW.json index 22291ed06..6a56ea78d 100644 --- a/src/lang/zh-TW.json +++ b/src/lang/zh-TW.json @@ -126,7 +126,7 @@ "label.reset": "重設", "label.reset-website": "重設網站", "label.retention": "保留", - "label.retention-description": "Measure you website stickiness by tracking how often users return.", + "label.retention-description": "Measure your website stickiness by tracking how often users return.", "label.role": "角色", "label.run-query": "執行查詢", "label.save": "儲存", From f4f869f91977b922af0ff962162e7c31e51af605 Mon Sep 17 00:00:00 2001 From: Maxime-J Date: Sat, 2 Sep 2023 08:58:25 +0000 Subject: [PATCH 084/113] localize visitors in map tooltip --- src/components/common/WorldMap.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/common/WorldMap.js b/src/components/common/WorldMap.js index b593099b7..6ae84677e 100644 --- a/src/components/common/WorldMap.js +++ b/src/components/common/WorldMap.js @@ -8,6 +8,7 @@ import { ISO_COUNTRIES, MAP_FILE } from 'lib/constants'; import useTheme from 'components/hooks/useTheme'; import useCountryNames from 'components/hooks/useCountryNames'; import useLocale from 'components/hooks/useLocale'; +import useMessages from 'components/hooks/useMessages'; import { formatLongNumber } from 'lib/format'; import { percentFilter } from 'lib/filters'; import styles from './WorldMap.module.css'; @@ -17,7 +18,9 @@ export function WorldMap({ data, className }) { const [tooltip, setTooltipPopup] = useState(); const { theme, colors } = useTheme(); const { locale } = useLocale(); + const { formatMessage, labels } = useMessages(); const countryNames = useCountryNames(locale); + const visitorsLabel = formatMessage(labels.visitors).toLocaleLowerCase(locale); const metrics = useMemo(() => (data ? percentFilter(data) : []), [data]); function getFillColor(code) { @@ -40,7 +43,7 @@ export function WorldMap({ data, className }) { function handleHover(code) { if (code === 'AQ') return; const country = metrics?.find(({ x }) => x === code); - setTooltipPopup(`${countryNames[code]}: ${formatLongNumber(country?.y || 0)} visitors`); + setTooltipPopup(`${countryNames[code]}: ${formatLongNumber(country?.y || 0)} ${visitorsLabel}`); } return ( From e41a83316adf2e99e750c6ba10afad37f8cf84d2 Mon Sep 17 00:00:00 2001 From: Maxime-J Date: Sat, 2 Sep 2023 11:05:06 +0000 Subject: [PATCH 085/113] update fr-FR --- src/lang/fr-FR.json | 62 ++++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/src/lang/fr-FR.json b/src/lang/fr-FR.json index 092837eb5..bb4a56a55 100644 --- a/src/lang/fr-FR.json +++ b/src/lang/fr-FR.json @@ -16,20 +16,20 @@ "label.before": "Avant", "label.bounce-rate": "Taux de rebond", "label.breakdown": "Répartition", - "label.browser": "Browser", + "label.browser": "Navigateur", "label.browsers": "Navigateurs", "label.cancel": "Annuler", "label.change-password": "Changer le mot de passe", "label.cities": "Villes", - "label.city": "City", + "label.city": "Ville", "label.clear-all": "Réinitialiser", "label.confirm": "Confirmer", "label.confirm-password": "Confirmation du mot de passe", "label.contains": "Contient", "label.continue": "Continuer", "label.countries": "Pays", - "label.country": "Country", - "label.create": "Create", + "label.country": "Pays", + "label.create": "Créer", "label.create-report": "Créer un rapport", "label.create-team": "Créer une équipe", "label.create-user": "Créer un utilisateur", @@ -40,7 +40,7 @@ "label.data": "Données", "label.date": "Date", "label.date-range": "Période", - "label.day": "Day", + "label.day": "Jour", "label.default-date-range": "Période par défaut", "label.delete": "Supprimer", "label.delete-team": "Supprimer l'équipe", @@ -49,35 +49,35 @@ "label.description": "Description", "label.desktop": "Ordinateur", "label.details": "Détails", - "label.device": "Device", + "label.device": "Appareil", "label.devices": "Appareils", "label.dismiss": "Ignorer", "label.does-not-contain": "Ne contient pas", "label.domain": "Domaine", - "label.dropoff": "Dropoff", + "label.dropoff": "Abandons", "label.edit": "Modifier", "label.edit-dashboard": "Modifier le tableau de bord", "label.enable-share-url": "Activer l'URL de partage", - "label.event": "Event", - "label.event-data": "Données d'événements", - "label.events": "Événements", + "label.event": "Évènement", + "label.event-data": "Données d'évènements", + "label.events": "Évènements", "label.false": "Faux", "label.field": "Champ", "label.fields": "Champs", - "label.filter": "Filter", + "label.filter": "Filtrer", "label.filter-combined": "Combiné", "label.filter-raw": "Brut", "label.filters": "Filtres", "label.funnel": "Entonnoir", - "label.funnel-description": "Understand the conversion and drop-off rate of users.", + "label.funnel-description": "Suivi des conversions et des taux d'abandons.", "label.greater-than": "Supérieur à", "label.greater-than-equals": "Supérieur ou égal à", "label.insights": "Insights", - "label.insights-description": "Dive deeper into your data by using segments and filters.", - "label.is": "Est égal", - "label.is-not": "N'est pas égal", - "label.is-not-set": "Is not set", - "label.is-set": "Is set", + "label.insights-description": "Analyse précise des données en utilisant des segments et des filtres.", + "label.is": "Est", + "label.is-not": "N'est pas", + "label.is-not-set": "N'est pas défini", + "label.is-set": "Est défini", "label.join": "Rejoindre", "label.join-team": "Rejoindre une équipe", "label.language": "Langue", @@ -96,42 +96,42 @@ "label.min": "Min", "label.mobile": "Téléphone", "label.more": "Plus", - "label.my-websites": "My websites", + "label.my-websites": "Mes sites", "label.name": "Nom", "label.new-password": "Nouveau mot de passe", "label.none": "Aucun·e", "label.os": "OS", "label.overview": "Vue d'ensemble", "label.owner": "Propriétaire", - "label.page-of": "Page {current} of {total}", + "label.page-of": "Page {current} sur {total}", "label.page-views": "Pages vues", - "label.pageTitle": "Page title", + "label.pageTitle": "Titre de page", "label.pages": "Pages", "label.password": "Mot de passe", "label.powered-by": "Propulsé par {name}", "label.profile": "Profil", "label.queries": "Requêtes", "label.query": "Requête", - "label.query-parameters": "Paramètres d'URL", + "label.query-parameters": "Paramètres de requête", "label.realtime": "Temps réel", - "label.referrer": "Referrer", + "label.referrer": "Site référent", "label.referrers": "Sites référents", "label.refresh": "Rafraîchir", "label.regenerate": "Régénérer", - "label.region": "Region", + "label.region": "Région", "label.regions": "Régions", "label.remove": "Retirer", "label.reports": "Rapports", "label.required": "Requis", "label.reset": "Réinitialiser", "label.reset-website": "Réinitialiser les statistiques", - "label.retention": "Retention", - "label.retention-description": "Measure your website stickiness by tracking how often users return.", + "label.retention": "Rétention", + "label.retention-description": "Mesure de l'atractivité du site en visualisant les taux d'utilisateurs qui reviennent.", "label.role": "Rôle", "label.run-query": "Éxécuter la requête", "label.save": "Enregistrer", "label.screens": "Résolutions d'écran", - "label.search": "Search", + "label.search": "Rechercher", "label.select-date": "Choisir une période", "label.select-website": "Choisir un site", "label.sessions": "Sessions", @@ -144,9 +144,9 @@ "label.team-guest": "Invité dans l'équipe", "label.team-id": "ID d'équipe", "label.team-member": "Membre de l'équipe", - "label.team-name": "Team name", + "label.team-name": "Nom de l'équipe", "label.team-owner": "Propriétaire de l'équipe", - "label.team-websites": "Team websites", + "label.team-websites": "Sites d'équipes", "label.teams": "Équipes", "label.theme": "Thème", "label.this-month": "Ce mois", @@ -176,7 +176,7 @@ "label.view-only": "Consultation", "label.views": "Vues", "label.visitors": "Visiteurs", - "label.website": "Website", + "label.website": "Site", "label.website-id": "ID de site", "label.websites": "Sites", "label.window": "Fenêtre", @@ -194,7 +194,7 @@ "message.incorrect-username-password": "Nom d'utilisateur/Mot de passe incorrect.", "message.invalid-domain": "Domaine invalide", "message.min-password-length": "Taille minimale de {n} caractères", - "message.new-version-available": "A new version of Umami {version} is available!", + "message.new-version-available": "Une nouvelle version d'Umami {version} est disponible !", "message.no-data-available": "Aucune donnée disponible.", "message.no-event-data": "Aucune donnée d'événement disponible.", "message.no-match-password": "Les mots de passe ne correspondent pas", @@ -206,7 +206,7 @@ "message.page-not-found": "Page non trouvée.", "message.reset-website": "Pour réinitialiser ce site, taper {confirmation} ci-dessous pour confirmer.", "message.reset-website-warning": "Toutes les statistiques pour ce site seront supprimées, mais votre code de suivi restera intact.", - "message.saved": "Enregistré avec succès.", + "message.saved": "Enregistré.", "message.share-url": "Les statistiques de votre site sont accessibles publiquement sur cette URL :", "message.team-already-member": "Vous êtes déjà membre de cette équipe.", "message.team-not-found": "Équipe non trouvée.", From 105b3c1e3180a5d3a2ce4eac63a79a91407fc67e Mon Sep 17 00:00:00 2001 From: Maxime-J Date: Sat, 2 Sep 2023 12:39:23 +0000 Subject: [PATCH 086/113] restore lost translations --- src/lang/my-MM.json | 50 ++++++++++++++++++++++----------------------- src/lang/sl-SI.json | 8 ++++---- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/lang/my-MM.json b/src/lang/my-MM.json index bdfa3c6ab..704e29496 100644 --- a/src/lang/my-MM.json +++ b/src/lang/my-MM.json @@ -6,16 +6,16 @@ "label.add-description": "အကြောင်းအရာဖော်ပြချက် ထည့်မည်", "label.add-website": "ဝက်ဘ်ဆိုဒ်ထည့်မည်", "label.admin": "အက်ဒမင်", - "label.after": "After", + "label.after": "ပြီးနောက်", "label.all": "အားလုံး", "label.all-time": "အချိန်အစမှအခုထိ", "label.analytics": "အန်နလစ်တစ်", - "label.average": "Average", + "label.average": "ပျမ်းမျှ", "label.average-visit-time": "ဝဘက်ဘ်ဆိုဒ်တွင် ပျမ်းမျှကုန်ဆုံးချိန်", "label.back": "နောက်သို့", - "label.before": "Before", + "label.before": "မတိုင်မီ", "label.bounce-rate": "Bounce နှုန်း", - "label.breakdown": "Breakdown", + "label.breakdown": "ခွဲခြမ်းစိတ်ဖြာမှု", "label.browser": "Browser", "label.browsers": "ဝက်ဘ်ဘရောင်ဇာများ", "label.cancel": "မလုပ်တော့ပါ", @@ -25,12 +25,12 @@ "label.clear-all": "အားလုံးကိုဖျက်မည်", "label.confirm": "အတည်ပြုသည်", "label.confirm-password": "စကားဝှက်အတည်ပြုသည်", - "label.contains": "Contains", + "label.contains": "ပါဝင်သည်", "label.continue": "ဆက်သွားမည်", "label.countries": "နိုင်ငံများ", "label.country": "Country", "label.create": "Create", - "label.create-report": "Create report", + "label.create-report": "ရီပို့လုပ်မည်", "label.create-team": "Team ပြုလုပ်မည်", "label.create-user": "အသုံးပြုသူထည့်မည်", "label.created": "ပြုလုပ်ပြီးသော", @@ -46,13 +46,13 @@ "label.delete-team": "Team ကိုဖျက်မည်", "label.delete-user": "အသုံးပြုသူကိုဖျက်မည်", "label.delete-website": "ဝက်ဘ်ဆိုဒ်ကိုဖျက်မည်", - "label.description": "Description", + "label.description": "ရှင်းပြချက်", "label.desktop": "စားပွဲတင်ကွန်ပျူတာ", "label.details": "အသေးစိတ်", "label.device": "Device", "label.devices": "အသုံးပြုသည့် ကိရိယာများ", "label.dismiss": "ပိတ်ပါ", - "label.does-not-contain": "Does not contain", + "label.does-not-contain": "မပါဝင်ပါ", "label.domain": "ဒိုမိန်း", "label.dropoff": "Dropoff", "label.edit": "ပြုပြင်မည်", @@ -61,17 +61,17 @@ "label.event": "အဖြစ်အပျက်", "label.event-data": "အဖြစ်အပျက် ဒေတာ", "label.events": "အဖြစ်အပျက်များ", - "label.false": "False", + "label.false": "မှားသည်", "label.field": "Field အမည်", "label.fields": "Field အမည်များ", "label.filter": "Filter", "label.filter-combined": "ပေါင်းစပ်ပြီး", "label.filter-raw": "အရှိအတိုင်း", - "label.filters": "Filters", + "label.filters": "Filter များ", "label.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": "အသေးစိတ်သိမြင်နိုင်ရန်", "label.insights-description": "Dive deeper into your data by using segments and filters.", "label.is": "Is", @@ -87,21 +87,21 @@ "label.last-hours": "လွန်ခဲ့သော {x} နာရီက", "label.leave": "ထွက်မည်", "label.leave-team": "အသင်းမှထွက်မည်", - "label.less-than": "Less than", - "label.less-than-equals": "Less than or equals", + "label.less-than": "ထက်ပို၍ငယ်သည်", + "label.less-than-equals": "ထက်ပို၍ငယ်သည်သို့မဟုတ်တူသည်", "label.login": "လော့ဂ်အင်", "label.logout": "လော့ဂ်အောက်လုပ်မည်", - "label.max": "Max", + "label.max": "အများဆုံး", "label.members": "အဖွဲ့ဝင်များ", - "label.min": "Min", + "label.min": "အနည်းဆုံး", "label.mobile": "မိုဘိုင်း", "label.more": "နောက်ထပ်", "label.my-websites": "My websites", "label.name": "အမည်", "label.new-password": "စကားဝှက်အသစ်", "label.none": "မရှိပါ", - "label.os": "OS", - "label.overview": "Overview", + "label.os": "ကွန်ပျူတာလည်ပတ်မှုစနစ်", + "label.overview": "အပေါ်ယံမြင်ကွင်း", "label.owner": "ပိုင်ဆိုင်သူ", "label.page-of": "Page {current} of {total}", "label.page-views": "ဝင်ရောက်ကြည့်ရှုသူ", @@ -138,7 +138,7 @@ "label.settings": "ဆက်တင်များ", "label.share-url": "URL ကိုရှဲမည်", "label.single-day": "တစ်ရက်အတွင်း", - "label.sum": "Sum", + "label.sum": "ပေါင်းလဒ်", "label.tablet": "တက်ဘလက်", "label.team": "အသင်း", "label.team-guest": "အသင်း ဧည့်သည်", @@ -156,21 +156,21 @@ "label.title": "ခေါင်းစဥ်", "label.today": "ယနေ့", "label.toggle-charts": "ဇယားများကို အဖွင့်အပိတ်လုပ်မည်", - "label.total": "Total", - "label.total-records": "Total records", + "label.total": "စုစုပေါင်း", + "label.total-records": "မှတ်တမ်းစုစုပေါင်း", "label.tracking-code": "ထရက်လုပ်သည့် ကုဒ်", - "label.true": "True", - "label.type": "Type", + "label.true": "မှန်သည်", + "label.type": "အမျိုးအစား", "label.unique": "Unique", "label.unique-visitors": "ဝင်ရောက်သူ (ထပ်ခြင်းမရှိ)", "label.unknown": "မသိသော", - "label.untitled": "Untitled", + "label.untitled": "ခေါင်းစဉ်မရှိ", "label.url": "URL", "label.urls": "URL များ", "label.user": "အသုံးပြုသူ", "label.username": "အသုံးပြုသူအမည်", "label.users": "အသုံးပြုသူများ", - "label.value": "Value", + "label.value": "တန်ဖိုး", "label.view": "ဝင်ရောက်ကြည့်ရှုမှု", "label.view-details": "အသေးစိတ်ကို ကြည့်ရှုမည်", "label.view-only": "ဝင်ရောက်ကြည့်ရှုမှုများသာ", diff --git a/src/lang/sl-SI.json b/src/lang/sl-SI.json index 1863eb879..e7347bc43 100644 --- a/src/lang/sl-SI.json +++ b/src/lang/sl-SI.json @@ -130,10 +130,10 @@ "label.role": "Vloga", "label.run-query": "Izvedi poizvedbo", "label.save": "Shrani", - "label.screens": "Screens", - "label.select-date": "Select date", - "label.select-website": "Select website", - "label.sessions": "Sessions", + "label.screens": "Zasloni", + "label.select-date": "Izberi datum", + "label.select-website": "Izberi spletno mesto", + "label.sessions": "Seje", "label.settings": "Nastavitve", "label.share-url": "Deli povezavo", "label.single-day": "En dan", From a591eb867dcad30fddeabd07492c3138beeec0b9 Mon Sep 17 00:00:00 2001 From: Maxime-J Date: Sat, 2 Sep 2023 12:50:18 +0000 Subject: [PATCH 087/113] follow-up: add missing new label in sl-SI --- src/lang/sl-SI.json | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lang/sl-SI.json b/src/lang/sl-SI.json index e7347bc43..66ce08e08 100644 --- a/src/lang/sl-SI.json +++ b/src/lang/sl-SI.json @@ -131,6 +131,7 @@ "label.run-query": "Izvedi poizvedbo", "label.save": "Shrani", "label.screens": "Zasloni", + "label.search": "Search", "label.select-date": "Izberi datum", "label.select-website": "Izberi spletno mesto", "label.sessions": "Seje", From 4bce72350b234e4baebc5215246df66b7c41eff2 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Sat, 2 Sep 2023 16:53:26 -0700 Subject: [PATCH 088/113] Include HOSTNAME variable. --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index e0c7e8c37..6674163a2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -53,6 +53,7 @@ USER nextjs EXPOSE 3000 +ENV HOSTNAME 0.0.0.0 ENV PORT 3000 CMD ["yarn", "start-docker"] From cec186e4c177ccfaa1a141de236802b3cd216d8d Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Mon, 4 Sep 2023 13:42:39 -0700 Subject: [PATCH 089/113] Added version to menu. --- src/components/input/ProfileButton.js | 4 +++- src/components/input/ProfileButton.module.css | 8 ++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/components/input/ProfileButton.js b/src/components/input/ProfileButton.js index 015c0ad8d..35b0eb454 100644 --- a/src/components/input/ProfileButton.js +++ b/src/components/input/ProfileButton.js @@ -3,8 +3,9 @@ import { useRouter } from 'next/router'; import Icons from 'components/icons'; import useMessages from 'components/hooks/useMessages'; import useUser from 'components/hooks/useUser'; -import styles from './ProfileButton.module.css'; import useLocale from 'components/hooks/useLocale'; +import { CURRENT_VERSION } from 'lib/constants'; +import styles from './ProfileButton.module.css'; export function ProfileButton() { const { formatMessage, labels } = useMessages(); @@ -51,6 +52,7 @@ export function ProfileButton() { {formatMessage(labels.logout)} )} +
{`v${CURRENT_VERSION}`}
diff --git a/src/components/input/ProfileButton.module.css b/src/components/input/ProfileButton.module.css index 8b1897bd5..e78433448 100644 --- a/src/components/input/ProfileButton.module.css +++ b/src/components/input/ProfileButton.module.css @@ -8,3 +8,11 @@ gap: 12px; background: var(--base50); } + +.version { + font-family: monospace; + font-size: 11px; + color: var(--base600); + text-align: right; + margin-right: 10px; +} From ea43872dd0ea82c66325b92f2686e217c0d978b0 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Mon, 4 Sep 2023 22:50:53 -0700 Subject: [PATCH 090/113] Update message bundles. --- public/intl/messages/am-ET.json | 36 +++ public/intl/messages/ar-SA.json | 36 +++ public/intl/messages/be-BY.json | 36 +++ public/intl/messages/bn-BD.json | 36 +++ public/intl/messages/ca-ES.json | 36 +++ public/intl/messages/cs-CZ.json | 36 +++ public/intl/messages/da-DK.json | 36 +++ public/intl/messages/de-CH.json | 36 +++ public/intl/messages/de-DE.json | 158 ++++++----- public/intl/messages/el-GR.json | 36 +++ public/intl/messages/en-GB.json | 36 +++ public/intl/messages/en-US.json | 36 +++ public/intl/messages/es-ES.json | 36 +++ public/intl/messages/es-MX.json | 36 +++ public/intl/messages/fa-IR.json | 36 +++ public/intl/messages/fi-FI.json | 36 +++ public/intl/messages/fo-FO.json | 36 +++ public/intl/messages/fr-FR.json | 88 ++++-- public/intl/messages/ga-ES.json | 36 +++ public/intl/messages/he-IL.json | 36 +++ public/intl/messages/hi-IN.json | 36 +++ public/intl/messages/hr-HR.json | 36 +++ public/intl/messages/hu-HU.json | 36 +++ public/intl/messages/id-ID.json | 36 +++ public/intl/messages/it-IT.json | 36 +++ public/intl/messages/ja-JP.json | 36 +++ public/intl/messages/km-KH.json | 36 +++ public/intl/messages/ko-KR.json | 36 +++ public/intl/messages/lt-LT.json | 36 +++ public/intl/messages/mn-MN.json | 36 +++ public/intl/messages/ms-MY.json | 36 +++ public/intl/messages/my-MM.json | 470 +++++++++++++++++++++----------- public/intl/messages/nb-NO.json | 36 +++ public/intl/messages/nl-NL.json | 36 +++ public/intl/messages/pl-PL.json | 36 +++ public/intl/messages/pt-BR.json | 36 +++ public/intl/messages/pt-PT.json | 36 +++ public/intl/messages/ro-RO.json | 36 +++ public/intl/messages/ru-RU.json | 36 +++ public/intl/messages/si-LK.json | 36 +++ public/intl/messages/sk-SK.json | 36 +++ public/intl/messages/sl-SI.json | 36 +++ public/intl/messages/sv-SE.json | 36 +++ public/intl/messages/ta-IN.json | 36 +++ public/intl/messages/th-TH.json | 36 +++ public/intl/messages/tr-TR.json | 36 +++ public/intl/messages/uk-UA.json | 36 +++ public/intl/messages/ur-PK.json | 36 +++ public/intl/messages/vi-VN.json | 36 +++ public/intl/messages/zh-CN.json | 36 +++ public/intl/messages/zh-TW.json | 36 +++ src/lang/de-DE.json | 4 +- 52 files changed, 2195 insertions(+), 253 deletions(-) diff --git a/public/intl/messages/am-ET.json b/public/intl/messages/am-ET.json index f48fe83c4..cb9ff4f99 100644 --- a/public/intl/messages/am-ET.json +++ b/public/intl/messages/am-ET.json @@ -179,6 +179,12 @@ "value": "Country" } ], + "label.create": [ + { + "type": 0, + "value": "Create" + } + ], "label.create-report": [ { "type": 0, @@ -383,6 +389,12 @@ "value": "Fields" } ], + "label.filter": [ + { + "type": 0, + "value": "Filter" + } + ], "label.filter-combined": [ { "type": 0, @@ -407,6 +419,12 @@ "value": "Funnel" } ], + "label.funnel-description": [ + { + "type": 0, + "value": "Understand the conversion and drop-off rate of users." + } + ], "label.greater-than": [ { "type": 0, @@ -425,6 +443,12 @@ "value": "Insights" } ], + "label.insights-description": [ + { + "type": 0, + "value": "Dive deeper into your data by using segments and filters." + } + ], "label.is": [ { "type": 0, @@ -769,6 +793,12 @@ "value": "Retention" } ], + "label.retention-description": [ + { + "type": 0, + "value": "Measure your website stickiness by tracking how often users return." + } + ], "label.role": [ { "type": 0, @@ -793,6 +823,12 @@ "value": "Screens" } ], + "label.search": [ + { + "type": 0, + "value": "Search" + } + ], "label.select-date": [ { "type": 0, diff --git a/public/intl/messages/ar-SA.json b/public/intl/messages/ar-SA.json index a9a12404e..17a859167 100644 --- a/public/intl/messages/ar-SA.json +++ b/public/intl/messages/ar-SA.json @@ -179,6 +179,12 @@ "value": "Country" } ], + "label.create": [ + { + "type": 0, + "value": "Create" + } + ], "label.create-report": [ { "type": 0, @@ -383,6 +389,12 @@ "value": "Fields" } ], + "label.filter": [ + { + "type": 0, + "value": "Filter" + } + ], "label.filter-combined": [ { "type": 0, @@ -407,6 +419,12 @@ "value": "Funnel" } ], + "label.funnel-description": [ + { + "type": 0, + "value": "Understand the conversion and drop-off rate of users." + } + ], "label.greater-than": [ { "type": 0, @@ -425,6 +443,12 @@ "value": "Insights" } ], + "label.insights-description": [ + { + "type": 0, + "value": "Dive deeper into your data by using segments and filters." + } + ], "label.is": [ { "type": 0, @@ -769,6 +793,12 @@ "value": "Retention" } ], + "label.retention-description": [ + { + "type": 0, + "value": "Measure your website stickiness by tracking how often users return." + } + ], "label.role": [ { "type": 0, @@ -793,6 +823,12 @@ "value": "الشاشات" } ], + "label.search": [ + { + "type": 0, + "value": "Search" + } + ], "label.select-date": [ { "type": 0, diff --git a/public/intl/messages/be-BY.json b/public/intl/messages/be-BY.json index 4978aa45c..c8081e373 100644 --- a/public/intl/messages/be-BY.json +++ b/public/intl/messages/be-BY.json @@ -179,6 +179,12 @@ "value": "Country" } ], + "label.create": [ + { + "type": 0, + "value": "Create" + } + ], "label.create-report": [ { "type": 0, @@ -383,6 +389,12 @@ "value": "Fields" } ], + "label.filter": [ + { + "type": 0, + "value": "Filter" + } + ], "label.filter-combined": [ { "type": 0, @@ -407,6 +419,12 @@ "value": "Funnel" } ], + "label.funnel-description": [ + { + "type": 0, + "value": "Understand the conversion and drop-off rate of users." + } + ], "label.greater-than": [ { "type": 0, @@ -425,6 +443,12 @@ "value": "Insights" } ], + "label.insights-description": [ + { + "type": 0, + "value": "Dive deeper into your data by using segments and filters." + } + ], "label.is": [ { "type": 0, @@ -769,6 +793,12 @@ "value": "Retention" } ], + "label.retention-description": [ + { + "type": 0, + "value": "Measure your website stickiness by tracking how often users return." + } + ], "label.role": [ { "type": 0, @@ -793,6 +823,12 @@ "value": "Экраны" } ], + "label.search": [ + { + "type": 0, + "value": "Search" + } + ], "label.select-date": [ { "type": 0, diff --git a/public/intl/messages/bn-BD.json b/public/intl/messages/bn-BD.json index 938f6f98f..6b8875adf 100644 --- a/public/intl/messages/bn-BD.json +++ b/public/intl/messages/bn-BD.json @@ -179,6 +179,12 @@ "value": "Country" } ], + "label.create": [ + { + "type": 0, + "value": "Create" + } + ], "label.create-report": [ { "type": 0, @@ -383,6 +389,12 @@ "value": "Fields" } ], + "label.filter": [ + { + "type": 0, + "value": "Filter" + } + ], "label.filter-combined": [ { "type": 0, @@ -407,6 +419,12 @@ "value": "Funnel" } ], + "label.funnel-description": [ + { + "type": 0, + "value": "Understand the conversion and drop-off rate of users." + } + ], "label.greater-than": [ { "type": 0, @@ -425,6 +443,12 @@ "value": "Insights" } ], + "label.insights-description": [ + { + "type": 0, + "value": "Dive deeper into your data by using segments and filters." + } + ], "label.is": [ { "type": 0, @@ -769,6 +793,12 @@ "value": "Retention" } ], + "label.retention-description": [ + { + "type": 0, + "value": "Measure your website stickiness by tracking how often users return." + } + ], "label.role": [ { "type": 0, @@ -793,6 +823,12 @@ "value": "স্ক্রিনগুলি" } ], + "label.search": [ + { + "type": 0, + "value": "Search" + } + ], "label.select-date": [ { "type": 0, diff --git a/public/intl/messages/ca-ES.json b/public/intl/messages/ca-ES.json index 694b49c22..f21a739cc 100644 --- a/public/intl/messages/ca-ES.json +++ b/public/intl/messages/ca-ES.json @@ -179,6 +179,12 @@ "value": "Country" } ], + "label.create": [ + { + "type": 0, + "value": "Create" + } + ], "label.create-report": [ { "type": 0, @@ -383,6 +389,12 @@ "value": "Fields" } ], + "label.filter": [ + { + "type": 0, + "value": "Filter" + } + ], "label.filter-combined": [ { "type": 0, @@ -407,6 +419,12 @@ "value": "Funnel" } ], + "label.funnel-description": [ + { + "type": 0, + "value": "Understand the conversion and drop-off rate of users." + } + ], "label.greater-than": [ { "type": 0, @@ -425,6 +443,12 @@ "value": "Insights" } ], + "label.insights-description": [ + { + "type": 0, + "value": "Dive deeper into your data by using segments and filters." + } + ], "label.is": [ { "type": 0, @@ -769,6 +793,12 @@ "value": "Retention" } ], + "label.retention-description": [ + { + "type": 0, + "value": "Measure your website stickiness by tracking how often users return." + } + ], "label.role": [ { "type": 0, @@ -793,6 +823,12 @@ "value": "Screens" } ], + "label.search": [ + { + "type": 0, + "value": "Search" + } + ], "label.select-date": [ { "type": 0, diff --git a/public/intl/messages/cs-CZ.json b/public/intl/messages/cs-CZ.json index 3fd34c31d..e316e9731 100644 --- a/public/intl/messages/cs-CZ.json +++ b/public/intl/messages/cs-CZ.json @@ -179,6 +179,12 @@ "value": "Country" } ], + "label.create": [ + { + "type": 0, + "value": "Create" + } + ], "label.create-report": [ { "type": 0, @@ -383,6 +389,12 @@ "value": "Fields" } ], + "label.filter": [ + { + "type": 0, + "value": "Filter" + } + ], "label.filter-combined": [ { "type": 0, @@ -407,6 +419,12 @@ "value": "Funnel" } ], + "label.funnel-description": [ + { + "type": 0, + "value": "Understand the conversion and drop-off rate of users." + } + ], "label.greater-than": [ { "type": 0, @@ -425,6 +443,12 @@ "value": "Insights" } ], + "label.insights-description": [ + { + "type": 0, + "value": "Dive deeper into your data by using segments and filters." + } + ], "label.is": [ { "type": 0, @@ -769,6 +793,12 @@ "value": "Retention" } ], + "label.retention-description": [ + { + "type": 0, + "value": "Measure your website stickiness by tracking how often users return." + } + ], "label.role": [ { "type": 0, @@ -793,6 +823,12 @@ "value": "Screens" } ], + "label.search": [ + { + "type": 0, + "value": "Search" + } + ], "label.select-date": [ { "type": 0, diff --git a/public/intl/messages/da-DK.json b/public/intl/messages/da-DK.json index d8da1c3eb..05b0c572a 100644 --- a/public/intl/messages/da-DK.json +++ b/public/intl/messages/da-DK.json @@ -179,6 +179,12 @@ "value": "Country" } ], + "label.create": [ + { + "type": 0, + "value": "Create" + } + ], "label.create-report": [ { "type": 0, @@ -383,6 +389,12 @@ "value": "Fields" } ], + "label.filter": [ + { + "type": 0, + "value": "Filter" + } + ], "label.filter-combined": [ { "type": 0, @@ -407,6 +419,12 @@ "value": "Funnel" } ], + "label.funnel-description": [ + { + "type": 0, + "value": "Understand the conversion and drop-off rate of users." + } + ], "label.greater-than": [ { "type": 0, @@ -425,6 +443,12 @@ "value": "Insights" } ], + "label.insights-description": [ + { + "type": 0, + "value": "Dive deeper into your data by using segments and filters." + } + ], "label.is": [ { "type": 0, @@ -769,6 +793,12 @@ "value": "Retention" } ], + "label.retention-description": [ + { + "type": 0, + "value": "Measure your website stickiness by tracking how often users return." + } + ], "label.role": [ { "type": 0, @@ -793,6 +823,12 @@ "value": "Screens" } ], + "label.search": [ + { + "type": 0, + "value": "Search" + } + ], "label.select-date": [ { "type": 0, diff --git a/public/intl/messages/de-CH.json b/public/intl/messages/de-CH.json index aa0b2d942..ecc153361 100644 --- a/public/intl/messages/de-CH.json +++ b/public/intl/messages/de-CH.json @@ -179,6 +179,12 @@ "value": "Country" } ], + "label.create": [ + { + "type": 0, + "value": "Create" + } + ], "label.create-report": [ { "type": 0, @@ -383,6 +389,12 @@ "value": "Fields" } ], + "label.filter": [ + { + "type": 0, + "value": "Filter" + } + ], "label.filter-combined": [ { "type": 0, @@ -407,6 +419,12 @@ "value": "Funnel" } ], + "label.funnel-description": [ + { + "type": 0, + "value": "Understand the conversion and drop-off rate of users." + } + ], "label.greater-than": [ { "type": 0, @@ -425,6 +443,12 @@ "value": "Insights" } ], + "label.insights-description": [ + { + "type": 0, + "value": "Dive deeper into your data by using segments and filters." + } + ], "label.is": [ { "type": 0, @@ -769,6 +793,12 @@ "value": "Retention" } ], + "label.retention-description": [ + { + "type": 0, + "value": "Measure your website stickiness by tracking how often users return." + } + ], "label.role": [ { "type": 0, @@ -793,6 +823,12 @@ "value": "Bildschirmuflösige" } ], + "label.search": [ + { + "type": 0, + "value": "Search" + } + ], "label.select-date": [ { "type": 0, diff --git a/public/intl/messages/de-DE.json b/public/intl/messages/de-DE.json index 136cd31dd..5e74647c1 100644 --- a/public/intl/messages/de-DE.json +++ b/public/intl/messages/de-DE.json @@ -20,7 +20,7 @@ "label.add": [ { "type": 0, - "value": "Add" + "value": "Hinzufügen" } ], "label.add-description": [ @@ -32,7 +32,7 @@ "label.add-website": [ { "type": 0, - "value": "Webseite hinzufügen" + "value": "Website hinzufügen" } ], "label.admin": [ @@ -44,7 +44,7 @@ "label.after": [ { "type": 0, - "value": "After" + "value": "Nach" } ], "label.all": [ @@ -86,7 +86,7 @@ "label.before": [ { "type": 0, - "value": "Before" + "value": "Vor" } ], "label.bounce-rate": [ @@ -134,7 +134,7 @@ "label.city": [ { "type": 0, - "value": "City" + "value": "Stadt" } ], "label.clear-all": [ @@ -158,7 +158,7 @@ "label.contains": [ { "type": 0, - "value": "Contains" + "value": "Enthält" } ], "label.continue": [ @@ -176,13 +176,19 @@ "label.country": [ { "type": 0, - "value": "Country" + "value": "Land" + } + ], + "label.create": [ + { + "type": 0, + "value": "Create" } ], "label.create-report": [ { "type": 0, - "value": "Report erstellen" + "value": "Bericht erstellen" } ], "label.create-team": [ @@ -230,7 +236,7 @@ "label.date": [ { "type": 0, - "value": "Date" + "value": "Datum" } ], "label.date-range": [ @@ -242,7 +248,7 @@ "label.day": [ { "type": 0, - "value": "Day" + "value": "Tag" } ], "label.default-date-range": [ @@ -272,7 +278,7 @@ "label.delete-website": [ { "type": 0, - "value": "Webseite löschen" + "value": "Website löschen" } ], "label.description": [ @@ -296,7 +302,7 @@ "label.device": [ { "type": 0, - "value": "Device" + "value": "Gerät" } ], "label.devices": [ @@ -314,7 +320,7 @@ "label.does-not-contain": [ { "type": 0, - "value": "Does not contain" + "value": "Enthält nicht" } ], "label.domain": [ @@ -356,7 +362,7 @@ "label.event-data": [ { "type": 0, - "value": "Event daten" + "value": "Eventdaten" } ], "label.events": [ @@ -368,19 +374,25 @@ "label.false": [ { "type": 0, - "value": "False" + "value": "Falsch" } ], "label.field": [ { "type": 0, - "value": "Field" + "value": "Feld" } ], "label.fields": [ { "type": 0, - "value": "Fields" + "value": "Felder" + } + ], + "label.filter": [ + { + "type": 0, + "value": "Filter" } ], "label.filter-combined": [ @@ -398,7 +410,7 @@ "label.filters": [ { "type": 0, - "value": "Filters" + "value": "Filter" } ], "label.funnel": [ @@ -407,6 +419,12 @@ "value": "Funnel" } ], + "label.funnel-description": [ + { + "type": 0, + "value": "Understand the conversion and drop-off rate of users." + } + ], "label.greater-than": [ { "type": 0, @@ -425,28 +443,34 @@ "value": "Insights" } ], + "label.insights-description": [ + { + "type": 0, + "value": "Dive deeper into your data by using segments and filters." + } + ], "label.is": [ { "type": 0, - "value": "Is" + "value": "Ist" } ], "label.is-not": [ { "type": 0, - "value": "Is not" + "value": "Ist nicht" } ], "label.is-not-set": [ { "type": 0, - "value": "Is not set" + "value": "Ist nicht gesetzt" } ], "label.is-set": [ { "type": 0, - "value": "Is set" + "value": "Ist gesetzt" } ], "label.join": [ @@ -576,7 +600,7 @@ "label.my-websites": [ { "type": 0, - "value": "My websites" + "value": "Meine Websites" } ], "label.name": [ @@ -618,7 +642,7 @@ "label.page-of": [ { "type": 0, - "value": "Page " + "value": "Seite " }, { "type": 1, @@ -626,7 +650,7 @@ }, { "type": 0, - "value": " of " + "value": " von " }, { "type": 1, @@ -642,7 +666,7 @@ "label.pageTitle": [ { "type": 0, - "value": "Page title" + "value": "Seitentitel" } ], "label.pages": [ @@ -742,7 +766,7 @@ "label.reports": [ { "type": 0, - "value": "Reporte" + "value": "Berichte" } ], "label.required": [ @@ -769,6 +793,12 @@ "value": "Retention" } ], + "label.retention-description": [ + { + "type": 0, + "value": "Measure your website stickiness by tracking how often users return." + } + ], "label.role": [ { "type": 0, @@ -793,6 +823,12 @@ "value": "Bildschirmauflösungen" } ], + "label.search": [ + { + "type": 0, + "value": "Search" + } + ], "label.select-date": [ { "type": 0, @@ -808,7 +844,7 @@ "label.sessions": [ { "type": 0, - "value": "Sessions" + "value": "Sitzungen" } ], "label.settings": [ @@ -850,37 +886,37 @@ "label.team-guest": [ { "type": 0, - "value": "Team Gast" + "value": "Gast des Teams" } ], "label.team-id": [ { "type": 0, - "value": "Team ID" + "value": "Team-ID" } ], "label.team-member": [ { "type": 0, - "value": "Team Mitglied" + "value": "Team-Mitglied" } ], "label.team-name": [ { "type": 0, - "value": "Team name" + "value": "Name des Teams" } ], "label.team-owner": [ { "type": 0, - "value": "Team Eigentümer" + "value": "Team-Eigentümer" } ], "label.team-websites": [ { "type": 0, - "value": "Team websites" + "value": "Team-Websites" } ], "label.teams": [ @@ -940,13 +976,13 @@ "label.total": [ { "type": 0, - "value": "Total" + "value": "Gesamt" } ], "label.total-records": [ { "type": 0, - "value": "Total records" + "value": "Datensätze insgesamt" } ], "label.tracking-code": [ @@ -958,19 +994,19 @@ "label.true": [ { "type": 0, - "value": "True" + "value": "Wahr" } ], "label.type": [ { "type": 0, - "value": "Type" + "value": "Typ" } ], "label.unique": [ { "type": 0, - "value": "Unique" + "value": "Eindeutig" } ], "label.unique-visitors": [ @@ -988,7 +1024,7 @@ "label.untitled": [ { "type": 0, - "value": "Untitled" + "value": "Unbenannt" } ], "label.url": [ @@ -1024,7 +1060,7 @@ "label.value": [ { "type": 0, - "value": "Value" + "value": "Wert" } ], "label.view": [ @@ -1042,7 +1078,7 @@ "label.view-only": [ { "type": 0, - "value": "View only" + "value": "Nur ansehen" } ], "label.views": [ @@ -1060,25 +1096,25 @@ "label.website": [ { "type": 0, - "value": "Webseite" + "value": "Website" } ], "label.website-id": [ { "type": 0, - "value": "Webseite ID" + "value": "Website ID" } ], "label.websites": [ { "type": 0, - "value": "Webseiten" + "value": "Websites" } ], "label.window": [ { "type": 0, - "value": "Window" + "value": "Fenster" } ], "label.yesterday": [ @@ -1166,7 +1202,7 @@ "message.delete-account": [ { "type": 0, - "value": "To delete this account, type " + "value": "Um dieses Konto zu löschen, geben Sie zur Bestätigung " }, { "type": 1, @@ -1174,13 +1210,13 @@ }, { "type": 0, - "value": " in the box below to confirm." + "value": " in das Feld unten ein." } ], "message.delete-website": [ { "type": 0, - "value": "To delete this website, type " + "value": "Um diese Website zu löschen, geben Sie zur Bestätigung " }, { "type": 1, @@ -1188,7 +1224,7 @@ }, { "type": 0, - "value": " in the box below to confirm." + "value": " in das Feld unten ein." } ], "message.delete-website-warning": [ @@ -1238,7 +1274,7 @@ "message.min-password-length": [ { "type": 0, - "value": "Minimale länge von " + "value": "Minimale Länge von " }, { "type": 1, @@ -1252,15 +1288,11 @@ "message.new-version-available": [ { "type": 0, - "value": "A new version of Umami " + "value": "Eine neue Version von Umami ist verfügbar: " }, { "type": 1, "value": "version" - }, - { - "type": 0, - "value": " is available!" } ], "message.no-data-available": [ @@ -1272,7 +1304,7 @@ "message.no-event-data": [ { "type": 0, - "value": "No event data is available." + "value": "Es sind keine Ereignisdaten verfügbar." } ], "message.no-match-password": [ @@ -1308,7 +1340,7 @@ "message.no-websites-configured": [ { "type": 0, - "value": "Es ist keine Webseite vorhanden." + "value": "Es ist keine Website vorhanden." } ], "message.page-not-found": [ @@ -1320,7 +1352,7 @@ "message.reset-website": [ { "type": 0, - "value": "To reset this website, type " + "value": "Um diese Website zurückzusetzen, geben Sie zur Bestätigung " }, { "type": 1, @@ -1328,13 +1360,13 @@ }, { "type": 0, - "value": " in the box below to confirm." + "value": " in das Feld unten ein." } ], "message.reset-website-warning": [ { "type": 0, - "value": "Alle Daten für diese Webseite werden gelöscht, jedoch bleibt der Tracking Code bestehen." + "value": "Alle Daten für diese Website werden gelöscht, jedoch bleibt der Tracking Code bestehen." } ], "message.saved": [ @@ -1346,7 +1378,7 @@ "message.share-url": [ { "type": 0, - "value": "Ihre Webseitenstatistik ist unter der folgenden URL öffentlich zugänglich:" + "value": "Die Statistiken Ihrer Website sind unter folgender URL öffentlich zugänglich:" } ], "message.team-already-member": [ @@ -1364,7 +1396,7 @@ "message.team-websites-info": [ { "type": 0, - "value": "Webseiten können von jedem im Team eingesehen werden." + "value": "Websites können von jedem im Team eingesehen werden." } ], "message.tracking-code": [ diff --git a/public/intl/messages/el-GR.json b/public/intl/messages/el-GR.json index d3ff5e424..eb6b73ce0 100644 --- a/public/intl/messages/el-GR.json +++ b/public/intl/messages/el-GR.json @@ -179,6 +179,12 @@ "value": "Country" } ], + "label.create": [ + { + "type": 0, + "value": "Create" + } + ], "label.create-report": [ { "type": 0, @@ -383,6 +389,12 @@ "value": "Fields" } ], + "label.filter": [ + { + "type": 0, + "value": "Filter" + } + ], "label.filter-combined": [ { "type": 0, @@ -407,6 +419,12 @@ "value": "Funnel" } ], + "label.funnel-description": [ + { + "type": 0, + "value": "Understand the conversion and drop-off rate of users." + } + ], "label.greater-than": [ { "type": 0, @@ -425,6 +443,12 @@ "value": "Insights" } ], + "label.insights-description": [ + { + "type": 0, + "value": "Dive deeper into your data by using segments and filters." + } + ], "label.is": [ { "type": 0, @@ -769,6 +793,12 @@ "value": "Retention" } ], + "label.retention-description": [ + { + "type": 0, + "value": "Measure your website stickiness by tracking how often users return." + } + ], "label.role": [ { "type": 0, @@ -793,6 +823,12 @@ "value": "Screens" } ], + "label.search": [ + { + "type": 0, + "value": "Search" + } + ], "label.select-date": [ { "type": 0, diff --git a/public/intl/messages/en-GB.json b/public/intl/messages/en-GB.json index 0e6ac6149..68f242481 100644 --- a/public/intl/messages/en-GB.json +++ b/public/intl/messages/en-GB.json @@ -179,6 +179,12 @@ "value": "Country" } ], + "label.create": [ + { + "type": 0, + "value": "Create" + } + ], "label.create-report": [ { "type": 0, @@ -383,6 +389,12 @@ "value": "Fields" } ], + "label.filter": [ + { + "type": 0, + "value": "Filter" + } + ], "label.filter-combined": [ { "type": 0, @@ -407,6 +419,12 @@ "value": "Funnel" } ], + "label.funnel-description": [ + { + "type": 0, + "value": "Understand the conversion and drop-off rate of users." + } + ], "label.greater-than": [ { "type": 0, @@ -425,6 +443,12 @@ "value": "Insights" } ], + "label.insights-description": [ + { + "type": 0, + "value": "Dive deeper into your data by using segments and filters." + } + ], "label.is": [ { "type": 0, @@ -769,6 +793,12 @@ "value": "Retention" } ], + "label.retention-description": [ + { + "type": 0, + "value": "Measure your website stickiness by tracking how often users return." + } + ], "label.role": [ { "type": 0, @@ -793,6 +823,12 @@ "value": "Screens" } ], + "label.search": [ + { + "type": 0, + "value": "Search" + } + ], "label.select-date": [ { "type": 0, diff --git a/public/intl/messages/en-US.json b/public/intl/messages/en-US.json index 64a99ae1b..0ee5b1e64 100644 --- a/public/intl/messages/en-US.json +++ b/public/intl/messages/en-US.json @@ -179,6 +179,12 @@ "value": "Country" } ], + "label.create": [ + { + "type": 0, + "value": "Create" + } + ], "label.create-report": [ { "type": 0, @@ -383,6 +389,12 @@ "value": "Fields" } ], + "label.filter": [ + { + "type": 0, + "value": "Filter" + } + ], "label.filter-combined": [ { "type": 0, @@ -407,6 +419,12 @@ "value": "Funnel" } ], + "label.funnel-description": [ + { + "type": 0, + "value": "Understand the conversion and drop-off rate of users." + } + ], "label.greater-than": [ { "type": 0, @@ -425,6 +443,12 @@ "value": "Insights" } ], + "label.insights-description": [ + { + "type": 0, + "value": "Dive deeper into your data by using segments and filters." + } + ], "label.is": [ { "type": 0, @@ -769,6 +793,12 @@ "value": "Retention" } ], + "label.retention-description": [ + { + "type": 0, + "value": "Measure your website stickiness by tracking how often users return." + } + ], "label.role": [ { "type": 0, @@ -793,6 +823,12 @@ "value": "Screens" } ], + "label.search": [ + { + "type": 0, + "value": "Search" + } + ], "label.select-date": [ { "type": 0, diff --git a/public/intl/messages/es-ES.json b/public/intl/messages/es-ES.json index 43e101709..0e1316218 100644 --- a/public/intl/messages/es-ES.json +++ b/public/intl/messages/es-ES.json @@ -179,6 +179,12 @@ "value": "Country" } ], + "label.create": [ + { + "type": 0, + "value": "Create" + } + ], "label.create-report": [ { "type": 0, @@ -383,6 +389,12 @@ "value": "Campos" } ], + "label.filter": [ + { + "type": 0, + "value": "Filter" + } + ], "label.filter-combined": [ { "type": 0, @@ -407,6 +419,12 @@ "value": "Funnel" } ], + "label.funnel-description": [ + { + "type": 0, + "value": "Understand the conversion and drop-off rate of users." + } + ], "label.greater-than": [ { "type": 0, @@ -425,6 +443,12 @@ "value": "Insights" } ], + "label.insights-description": [ + { + "type": 0, + "value": "Dive deeper into your data by using segments and filters." + } + ], "label.is": [ { "type": 0, @@ -769,6 +793,12 @@ "value": "Retention" } ], + "label.retention-description": [ + { + "type": 0, + "value": "Measure your website stickiness by tracking how often users return." + } + ], "label.role": [ { "type": 0, @@ -793,6 +823,12 @@ "value": "Pantallas" } ], + "label.search": [ + { + "type": 0, + "value": "Search" + } + ], "label.select-date": [ { "type": 0, diff --git a/public/intl/messages/es-MX.json b/public/intl/messages/es-MX.json index c238951fe..c3ef099df 100644 --- a/public/intl/messages/es-MX.json +++ b/public/intl/messages/es-MX.json @@ -179,6 +179,12 @@ "value": "Country" } ], + "label.create": [ + { + "type": 0, + "value": "Create" + } + ], "label.create-report": [ { "type": 0, @@ -383,6 +389,12 @@ "value": "Fields" } ], + "label.filter": [ + { + "type": 0, + "value": "Filter" + } + ], "label.filter-combined": [ { "type": 0, @@ -407,6 +419,12 @@ "value": "Funnel" } ], + "label.funnel-description": [ + { + "type": 0, + "value": "Understand the conversion and drop-off rate of users." + } + ], "label.greater-than": [ { "type": 0, @@ -425,6 +443,12 @@ "value": "Insights" } ], + "label.insights-description": [ + { + "type": 0, + "value": "Dive deeper into your data by using segments and filters." + } + ], "label.is": [ { "type": 0, @@ -769,6 +793,12 @@ "value": "Retention" } ], + "label.retention-description": [ + { + "type": 0, + "value": "Measure your website stickiness by tracking how often users return." + } + ], "label.role": [ { "type": 0, @@ -793,6 +823,12 @@ "value": "Pantallas" } ], + "label.search": [ + { + "type": 0, + "value": "Search" + } + ], "label.select-date": [ { "type": 0, diff --git a/public/intl/messages/fa-IR.json b/public/intl/messages/fa-IR.json index 757b5ae8e..e09b155b6 100644 --- a/public/intl/messages/fa-IR.json +++ b/public/intl/messages/fa-IR.json @@ -179,6 +179,12 @@ "value": "Country" } ], + "label.create": [ + { + "type": 0, + "value": "Create" + } + ], "label.create-report": [ { "type": 0, @@ -383,6 +389,12 @@ "value": "Fields" } ], + "label.filter": [ + { + "type": 0, + "value": "Filter" + } + ], "label.filter-combined": [ { "type": 0, @@ -407,6 +419,12 @@ "value": "Funnel" } ], + "label.funnel-description": [ + { + "type": 0, + "value": "Understand the conversion and drop-off rate of users." + } + ], "label.greater-than": [ { "type": 0, @@ -425,6 +443,12 @@ "value": "Insights" } ], + "label.insights-description": [ + { + "type": 0, + "value": "Dive deeper into your data by using segments and filters." + } + ], "label.is": [ { "type": 0, @@ -769,6 +793,12 @@ "value": "Retention" } ], + "label.retention-description": [ + { + "type": 0, + "value": "Measure your website stickiness by tracking how often users return." + } + ], "label.role": [ { "type": 0, @@ -793,6 +823,12 @@ "value": "Screens" } ], + "label.search": [ + { + "type": 0, + "value": "Search" + } + ], "label.select-date": [ { "type": 0, diff --git a/public/intl/messages/fi-FI.json b/public/intl/messages/fi-FI.json index 5fdf5b193..2130f82cd 100644 --- a/public/intl/messages/fi-FI.json +++ b/public/intl/messages/fi-FI.json @@ -179,6 +179,12 @@ "value": "Country" } ], + "label.create": [ + { + "type": 0, + "value": "Create" + } + ], "label.create-report": [ { "type": 0, @@ -383,6 +389,12 @@ "value": "Fields" } ], + "label.filter": [ + { + "type": 0, + "value": "Filter" + } + ], "label.filter-combined": [ { "type": 0, @@ -407,6 +419,12 @@ "value": "Funnel" } ], + "label.funnel-description": [ + { + "type": 0, + "value": "Understand the conversion and drop-off rate of users." + } + ], "label.greater-than": [ { "type": 0, @@ -425,6 +443,12 @@ "value": "Insights" } ], + "label.insights-description": [ + { + "type": 0, + "value": "Dive deeper into your data by using segments and filters." + } + ], "label.is": [ { "type": 0, @@ -769,6 +793,12 @@ "value": "Retention" } ], + "label.retention-description": [ + { + "type": 0, + "value": "Measure your website stickiness by tracking how often users return." + } + ], "label.role": [ { "type": 0, @@ -793,6 +823,12 @@ "value": "Screens" } ], + "label.search": [ + { + "type": 0, + "value": "Search" + } + ], "label.select-date": [ { "type": 0, diff --git a/public/intl/messages/fo-FO.json b/public/intl/messages/fo-FO.json index 3eb3f452c..bc11c56e1 100644 --- a/public/intl/messages/fo-FO.json +++ b/public/intl/messages/fo-FO.json @@ -179,6 +179,12 @@ "value": "Country" } ], + "label.create": [ + { + "type": 0, + "value": "Create" + } + ], "label.create-report": [ { "type": 0, @@ -383,6 +389,12 @@ "value": "Fields" } ], + "label.filter": [ + { + "type": 0, + "value": "Filter" + } + ], "label.filter-combined": [ { "type": 0, @@ -407,6 +419,12 @@ "value": "Funnel" } ], + "label.funnel-description": [ + { + "type": 0, + "value": "Understand the conversion and drop-off rate of users." + } + ], "label.greater-than": [ { "type": 0, @@ -425,6 +443,12 @@ "value": "Insights" } ], + "label.insights-description": [ + { + "type": 0, + "value": "Dive deeper into your data by using segments and filters." + } + ], "label.is": [ { "type": 0, @@ -769,6 +793,12 @@ "value": "Retention" } ], + "label.retention-description": [ + { + "type": 0, + "value": "Measure your website stickiness by tracking how often users return." + } + ], "label.role": [ { "type": 0, @@ -793,6 +823,12 @@ "value": "Screens" } ], + "label.search": [ + { + "type": 0, + "value": "Search" + } + ], "label.select-date": [ { "type": 0, diff --git a/public/intl/messages/fr-FR.json b/public/intl/messages/fr-FR.json index 326c99a46..99937de70 100644 --- a/public/intl/messages/fr-FR.json +++ b/public/intl/messages/fr-FR.json @@ -104,7 +104,7 @@ "label.browser": [ { "type": 0, - "value": "Browser" + "value": "Navigateur" } ], "label.browsers": [ @@ -134,7 +134,7 @@ "label.city": [ { "type": 0, - "value": "City" + "value": "Ville" } ], "label.clear-all": [ @@ -176,7 +176,13 @@ "label.country": [ { "type": 0, - "value": "Country" + "value": "Pays" + } + ], + "label.create": [ + { + "type": 0, + "value": "Créer" } ], "label.create-report": [ @@ -242,7 +248,7 @@ "label.day": [ { "type": 0, - "value": "Day" + "value": "Jour" } ], "label.default-date-range": [ @@ -296,7 +302,7 @@ "label.device": [ { "type": 0, - "value": "Device" + "value": "Appareil" } ], "label.devices": [ @@ -326,7 +332,7 @@ "label.dropoff": [ { "type": 0, - "value": "Dropoff" + "value": "Abandons" } ], "label.edit": [ @@ -350,19 +356,19 @@ "label.event": [ { "type": 0, - "value": "Event" + "value": "Évènement" } ], "label.event-data": [ { "type": 0, - "value": "Données d'événements" + "value": "Données d'évènements" } ], "label.events": [ { "type": 0, - "value": "Événements" + "value": "Évènements" } ], "label.false": [ @@ -383,6 +389,12 @@ "value": "Champs" } ], + "label.filter": [ + { + "type": 0, + "value": "Filtrer" + } + ], "label.filter-combined": [ { "type": 0, @@ -407,6 +419,12 @@ "value": "Entonnoir" } ], + "label.funnel-description": [ + { + "type": 0, + "value": "Suivi des conversions et des taux d'abandons." + } + ], "label.greater-than": [ { "type": 0, @@ -425,28 +443,34 @@ "value": "Insights" } ], + "label.insights-description": [ + { + "type": 0, + "value": "Analyse précise des données en utilisant des segments et des filtres." + } + ], "label.is": [ { "type": 0, - "value": "Est égal" + "value": "Est" } ], "label.is-not": [ { "type": 0, - "value": "N'est pas égal" + "value": "N'est pas" } ], "label.is-not-set": [ { "type": 0, - "value": "Is not set" + "value": "N'est pas défini" } ], "label.is-set": [ { "type": 0, - "value": "Is set" + "value": "Est défini" } ], "label.join": [ @@ -568,7 +592,7 @@ "label.my-websites": [ { "type": 0, - "value": "My websites" + "value": "Mes sites" } ], "label.name": [ @@ -618,7 +642,7 @@ }, { "type": 0, - "value": " of " + "value": " sur " }, { "type": 1, @@ -634,7 +658,7 @@ "label.pageTitle": [ { "type": 0, - "value": "Page title" + "value": "Titre de page" } ], "label.pages": [ @@ -680,7 +704,7 @@ "label.query-parameters": [ { "type": 0, - "value": "Paramètres d'URL" + "value": "Paramètres de requête" } ], "label.realtime": [ @@ -692,7 +716,7 @@ "label.referrer": [ { "type": 0, - "value": "Referrer" + "value": "Site référent" } ], "label.referrers": [ @@ -716,7 +740,7 @@ "label.region": [ { "type": 0, - "value": "Region" + "value": "Région" } ], "label.regions": [ @@ -758,7 +782,13 @@ "label.retention": [ { "type": 0, - "value": "Retention" + "value": "Rétention" + } + ], + "label.retention-description": [ + { + "type": 0, + "value": "Mesure de l'atractivité du site en visualisant les taux d'utilisateurs qui reviennent." } ], "label.role": [ @@ -785,6 +815,12 @@ "value": "Résolutions d'écran" } ], + "label.search": [ + { + "type": 0, + "value": "Rechercher" + } + ], "label.select-date": [ { "type": 0, @@ -860,7 +896,7 @@ "label.team-name": [ { "type": 0, - "value": "Team name" + "value": "Nom de l'équipe" } ], "label.team-owner": [ @@ -872,7 +908,7 @@ "label.team-websites": [ { "type": 0, - "value": "Team websites" + "value": "Sites d'équipes" } ], "label.teams": [ @@ -1052,7 +1088,7 @@ "label.website": [ { "type": 0, - "value": "Website" + "value": "Site" } ], "label.website-id": [ @@ -1248,7 +1284,7 @@ "message.new-version-available": [ { "type": 0, - "value": "A new version of Umami " + "value": "Une nouvelle version d'Umami " }, { "type": 1, @@ -1256,7 +1292,7 @@ }, { "type": 0, - "value": " is available!" + "value": " est disponible !" } ], "message.no-data-available": [ @@ -1336,7 +1372,7 @@ "message.saved": [ { "type": 0, - "value": "Enregistré avec succès." + "value": "Enregistré." } ], "message.share-url": [ diff --git a/public/intl/messages/ga-ES.json b/public/intl/messages/ga-ES.json index d086b57f8..b5fabeffe 100644 --- a/public/intl/messages/ga-ES.json +++ b/public/intl/messages/ga-ES.json @@ -179,6 +179,12 @@ "value": "Country" } ], + "label.create": [ + { + "type": 0, + "value": "Create" + } + ], "label.create-report": [ { "type": 0, @@ -383,6 +389,12 @@ "value": "Fields" } ], + "label.filter": [ + { + "type": 0, + "value": "Filter" + } + ], "label.filter-combined": [ { "type": 0, @@ -407,6 +419,12 @@ "value": "Funnel" } ], + "label.funnel-description": [ + { + "type": 0, + "value": "Understand the conversion and drop-off rate of users." + } + ], "label.greater-than": [ { "type": 0, @@ -425,6 +443,12 @@ "value": "Insights" } ], + "label.insights-description": [ + { + "type": 0, + "value": "Dive deeper into your data by using segments and filters." + } + ], "label.is": [ { "type": 0, @@ -777,6 +801,12 @@ "value": "Retention" } ], + "label.retention-description": [ + { + "type": 0, + "value": "Measure your website stickiness by tracking how often users return." + } + ], "label.role": [ { "type": 0, @@ -801,6 +831,12 @@ "value": "Screens" } ], + "label.search": [ + { + "type": 0, + "value": "Search" + } + ], "label.select-date": [ { "type": 0, diff --git a/public/intl/messages/he-IL.json b/public/intl/messages/he-IL.json index dc206268c..16f625257 100644 --- a/public/intl/messages/he-IL.json +++ b/public/intl/messages/he-IL.json @@ -179,6 +179,12 @@ "value": "Country" } ], + "label.create": [ + { + "type": 0, + "value": "Create" + } + ], "label.create-report": [ { "type": 0, @@ -383,6 +389,12 @@ "value": "Fields" } ], + "label.filter": [ + { + "type": 0, + "value": "Filter" + } + ], "label.filter-combined": [ { "type": 0, @@ -407,6 +419,12 @@ "value": "Funnel" } ], + "label.funnel-description": [ + { + "type": 0, + "value": "Understand the conversion and drop-off rate of users." + } + ], "label.greater-than": [ { "type": 0, @@ -425,6 +443,12 @@ "value": "Insights" } ], + "label.insights-description": [ + { + "type": 0, + "value": "Dive deeper into your data by using segments and filters." + } + ], "label.is": [ { "type": 0, @@ -761,6 +785,12 @@ "value": "Retention" } ], + "label.retention-description": [ + { + "type": 0, + "value": "Measure your website stickiness by tracking how often users return." + } + ], "label.role": [ { "type": 0, @@ -785,6 +815,12 @@ "value": "Screens" } ], + "label.search": [ + { + "type": 0, + "value": "Search" + } + ], "label.select-date": [ { "type": 0, diff --git a/public/intl/messages/hi-IN.json b/public/intl/messages/hi-IN.json index 91f1f0267..df3bcb401 100644 --- a/public/intl/messages/hi-IN.json +++ b/public/intl/messages/hi-IN.json @@ -179,6 +179,12 @@ "value": "Country" } ], + "label.create": [ + { + "type": 0, + "value": "Create" + } + ], "label.create-report": [ { "type": 0, @@ -383,6 +389,12 @@ "value": "Fields" } ], + "label.filter": [ + { + "type": 0, + "value": "Filter" + } + ], "label.filter-combined": [ { "type": 0, @@ -407,6 +419,12 @@ "value": "Funnel" } ], + "label.funnel-description": [ + { + "type": 0, + "value": "Understand the conversion and drop-off rate of users." + } + ], "label.greater-than": [ { "type": 0, @@ -425,6 +443,12 @@ "value": "Insights" } ], + "label.insights-description": [ + { + "type": 0, + "value": "Dive deeper into your data by using segments and filters." + } + ], "label.is": [ { "type": 0, @@ -769,6 +793,12 @@ "value": "Retention" } ], + "label.retention-description": [ + { + "type": 0, + "value": "Measure your website stickiness by tracking how often users return." + } + ], "label.role": [ { "type": 0, @@ -793,6 +823,12 @@ "value": "Screens" } ], + "label.search": [ + { + "type": 0, + "value": "Search" + } + ], "label.select-date": [ { "type": 0, diff --git a/public/intl/messages/hr-HR.json b/public/intl/messages/hr-HR.json index cd8d4d38b..8388dd486 100644 --- a/public/intl/messages/hr-HR.json +++ b/public/intl/messages/hr-HR.json @@ -179,6 +179,12 @@ "value": "Country" } ], + "label.create": [ + { + "type": 0, + "value": "Create" + } + ], "label.create-report": [ { "type": 0, @@ -383,6 +389,12 @@ "value": "Fields" } ], + "label.filter": [ + { + "type": 0, + "value": "Filter" + } + ], "label.filter-combined": [ { "type": 0, @@ -407,6 +419,12 @@ "value": "Funnel" } ], + "label.funnel-description": [ + { + "type": 0, + "value": "Understand the conversion and drop-off rate of users." + } + ], "label.greater-than": [ { "type": 0, @@ -425,6 +443,12 @@ "value": "Insights" } ], + "label.insights-description": [ + { + "type": 0, + "value": "Dive deeper into your data by using segments and filters." + } + ], "label.is": [ { "type": 0, @@ -769,6 +793,12 @@ "value": "Retention" } ], + "label.retention-description": [ + { + "type": 0, + "value": "Measure your website stickiness by tracking how often users return." + } + ], "label.role": [ { "type": 0, @@ -793,6 +823,12 @@ "value": "Screens" } ], + "label.search": [ + { + "type": 0, + "value": "Search" + } + ], "label.select-date": [ { "type": 0, diff --git a/public/intl/messages/hu-HU.json b/public/intl/messages/hu-HU.json index e39182b18..c3da1af06 100644 --- a/public/intl/messages/hu-HU.json +++ b/public/intl/messages/hu-HU.json @@ -179,6 +179,12 @@ "value": "Country" } ], + "label.create": [ + { + "type": 0, + "value": "Create" + } + ], "label.create-report": [ { "type": 0, @@ -383,6 +389,12 @@ "value": "Fields" } ], + "label.filter": [ + { + "type": 0, + "value": "Filter" + } + ], "label.filter-combined": [ { "type": 0, @@ -407,6 +419,12 @@ "value": "Funnel" } ], + "label.funnel-description": [ + { + "type": 0, + "value": "Understand the conversion and drop-off rate of users." + } + ], "label.greater-than": [ { "type": 0, @@ -425,6 +443,12 @@ "value": "Insights" } ], + "label.insights-description": [ + { + "type": 0, + "value": "Dive deeper into your data by using segments and filters." + } + ], "label.is": [ { "type": 0, @@ -769,6 +793,12 @@ "value": "Retention" } ], + "label.retention-description": [ + { + "type": 0, + "value": "Measure your website stickiness by tracking how often users return." + } + ], "label.role": [ { "type": 0, @@ -793,6 +823,12 @@ "value": "Screens" } ], + "label.search": [ + { + "type": 0, + "value": "Search" + } + ], "label.select-date": [ { "type": 0, diff --git a/public/intl/messages/id-ID.json b/public/intl/messages/id-ID.json index 97526840b..eda5c0b3e 100644 --- a/public/intl/messages/id-ID.json +++ b/public/intl/messages/id-ID.json @@ -179,6 +179,12 @@ "value": "Country" } ], + "label.create": [ + { + "type": 0, + "value": "Create" + } + ], "label.create-report": [ { "type": 0, @@ -383,6 +389,12 @@ "value": "Fields" } ], + "label.filter": [ + { + "type": 0, + "value": "Filter" + } + ], "label.filter-combined": [ { "type": 0, @@ -407,6 +419,12 @@ "value": "Funnel" } ], + "label.funnel-description": [ + { + "type": 0, + "value": "Understand the conversion and drop-off rate of users." + } + ], "label.greater-than": [ { "type": 0, @@ -425,6 +443,12 @@ "value": "Insights" } ], + "label.insights-description": [ + { + "type": 0, + "value": "Dive deeper into your data by using segments and filters." + } + ], "label.is": [ { "type": 0, @@ -761,6 +785,12 @@ "value": "Retention" } ], + "label.retention-description": [ + { + "type": 0, + "value": "Measure your website stickiness by tracking how often users return." + } + ], "label.role": [ { "type": 0, @@ -785,6 +815,12 @@ "value": "Layar" } ], + "label.search": [ + { + "type": 0, + "value": "Search" + } + ], "label.select-date": [ { "type": 0, diff --git a/public/intl/messages/it-IT.json b/public/intl/messages/it-IT.json index a93715d3d..bdc015f5a 100644 --- a/public/intl/messages/it-IT.json +++ b/public/intl/messages/it-IT.json @@ -179,6 +179,12 @@ "value": "Country" } ], + "label.create": [ + { + "type": 0, + "value": "Create" + } + ], "label.create-report": [ { "type": 0, @@ -383,6 +389,12 @@ "value": "Fields" } ], + "label.filter": [ + { + "type": 0, + "value": "Filter" + } + ], "label.filter-combined": [ { "type": 0, @@ -407,6 +419,12 @@ "value": "Funnel" } ], + "label.funnel-description": [ + { + "type": 0, + "value": "Understand the conversion and drop-off rate of users." + } + ], "label.greater-than": [ { "type": 0, @@ -425,6 +443,12 @@ "value": "Insights" } ], + "label.insights-description": [ + { + "type": 0, + "value": "Dive deeper into your data by using segments and filters." + } + ], "label.is": [ { "type": 0, @@ -769,6 +793,12 @@ "value": "Retention" } ], + "label.retention-description": [ + { + "type": 0, + "value": "Measure your website stickiness by tracking how often users return." + } + ], "label.role": [ { "type": 0, @@ -793,6 +823,12 @@ "value": "Screens" } ], + "label.search": [ + { + "type": 0, + "value": "Search" + } + ], "label.select-date": [ { "type": 0, diff --git a/public/intl/messages/ja-JP.json b/public/intl/messages/ja-JP.json index 63b49aa59..4e2a8fc47 100644 --- a/public/intl/messages/ja-JP.json +++ b/public/intl/messages/ja-JP.json @@ -179,6 +179,12 @@ "value": "国" } ], + "label.create": [ + { + "type": 0, + "value": "Create" + } + ], "label.create-report": [ { "type": 0, @@ -383,6 +389,12 @@ "value": "フィールド" } ], + "label.filter": [ + { + "type": 0, + "value": "Filter" + } + ], "label.filter-combined": [ { "type": 0, @@ -407,6 +419,12 @@ "value": "分析" } ], + "label.funnel-description": [ + { + "type": 0, + "value": "Understand the conversion and drop-off rate of users." + } + ], "label.greater-than": [ { "type": 0, @@ -425,6 +443,12 @@ "value": "見通し" } ], + "label.insights-description": [ + { + "type": 0, + "value": "Dive deeper into your data by using segments and filters." + } + ], "label.is": [ { "type": 0, @@ -769,6 +793,12 @@ "value": "保持" } ], + "label.retention-description": [ + { + "type": 0, + "value": "Measure your website stickiness by tracking how often users return." + } + ], "label.role": [ { "type": 0, @@ -793,6 +823,12 @@ "value": "画面サイズ" } ], + "label.search": [ + { + "type": 0, + "value": "Search" + } + ], "label.select-date": [ { "type": 0, diff --git a/public/intl/messages/km-KH.json b/public/intl/messages/km-KH.json index 1f7b82ca4..68c71ebbd 100644 --- a/public/intl/messages/km-KH.json +++ b/public/intl/messages/km-KH.json @@ -179,6 +179,12 @@ "value": "Country" } ], + "label.create": [ + { + "type": 0, + "value": "Create" + } + ], "label.create-report": [ { "type": 0, @@ -383,6 +389,12 @@ "value": "Fields" } ], + "label.filter": [ + { + "type": 0, + "value": "Filter" + } + ], "label.filter-combined": [ { "type": 0, @@ -407,6 +419,12 @@ "value": "Funnel" } ], + "label.funnel-description": [ + { + "type": 0, + "value": "Understand the conversion and drop-off rate of users." + } + ], "label.greater-than": [ { "type": 0, @@ -425,6 +443,12 @@ "value": "Insights" } ], + "label.insights-description": [ + { + "type": 0, + "value": "Dive deeper into your data by using segments and filters." + } + ], "label.is": [ { "type": 0, @@ -761,6 +785,12 @@ "value": "Retention" } ], + "label.retention-description": [ + { + "type": 0, + "value": "Measure your website stickiness by tracking how often users return." + } + ], "label.role": [ { "type": 0, @@ -785,6 +815,12 @@ "value": "ប្រភេទឧបករណ៍" } ], + "label.search": [ + { + "type": 0, + "value": "Search" + } + ], "label.select-date": [ { "type": 0, diff --git a/public/intl/messages/ko-KR.json b/public/intl/messages/ko-KR.json index 26413708b..5a3c90348 100644 --- a/public/intl/messages/ko-KR.json +++ b/public/intl/messages/ko-KR.json @@ -179,6 +179,12 @@ "value": "Country" } ], + "label.create": [ + { + "type": 0, + "value": "Create" + } + ], "label.create-report": [ { "type": 0, @@ -383,6 +389,12 @@ "value": "Fields" } ], + "label.filter": [ + { + "type": 0, + "value": "Filter" + } + ], "label.filter-combined": [ { "type": 0, @@ -407,6 +419,12 @@ "value": "Funnel" } ], + "label.funnel-description": [ + { + "type": 0, + "value": "Understand the conversion and drop-off rate of users." + } + ], "label.greater-than": [ { "type": 0, @@ -425,6 +443,12 @@ "value": "Insights" } ], + "label.insights-description": [ + { + "type": 0, + "value": "Dive deeper into your data by using segments and filters." + } + ], "label.is": [ { "type": 0, @@ -773,6 +797,12 @@ "value": "Retention" } ], + "label.retention-description": [ + { + "type": 0, + "value": "Measure your website stickiness by tracking how often users return." + } + ], "label.role": [ { "type": 0, @@ -797,6 +827,12 @@ "value": "Screens" } ], + "label.search": [ + { + "type": 0, + "value": "Search" + } + ], "label.select-date": [ { "type": 0, diff --git a/public/intl/messages/lt-LT.json b/public/intl/messages/lt-LT.json index 21610b7bd..6369cd3c1 100644 --- a/public/intl/messages/lt-LT.json +++ b/public/intl/messages/lt-LT.json @@ -179,6 +179,12 @@ "value": "Country" } ], + "label.create": [ + { + "type": 0, + "value": "Create" + } + ], "label.create-report": [ { "type": 0, @@ -383,6 +389,12 @@ "value": "Fields" } ], + "label.filter": [ + { + "type": 0, + "value": "Filter" + } + ], "label.filter-combined": [ { "type": 0, @@ -407,6 +419,12 @@ "value": "Funnel" } ], + "label.funnel-description": [ + { + "type": 0, + "value": "Understand the conversion and drop-off rate of users." + } + ], "label.greater-than": [ { "type": 0, @@ -425,6 +443,12 @@ "value": "Insights" } ], + "label.insights-description": [ + { + "type": 0, + "value": "Dive deeper into your data by using segments and filters." + } + ], "label.is": [ { "type": 0, @@ -874,6 +898,12 @@ "value": "Retention" } ], + "label.retention-description": [ + { + "type": 0, + "value": "Measure your website stickiness by tracking how often users return." + } + ], "label.role": [ { "type": 0, @@ -898,6 +928,12 @@ "value": "Screens" } ], + "label.search": [ + { + "type": 0, + "value": "Search" + } + ], "label.select-date": [ { "type": 0, diff --git a/public/intl/messages/mn-MN.json b/public/intl/messages/mn-MN.json index 013e5c88c..fd7294f3b 100644 --- a/public/intl/messages/mn-MN.json +++ b/public/intl/messages/mn-MN.json @@ -179,6 +179,12 @@ "value": "Country" } ], + "label.create": [ + { + "type": 0, + "value": "Create" + } + ], "label.create-report": [ { "type": 0, @@ -383,6 +389,12 @@ "value": "Fields" } ], + "label.filter": [ + { + "type": 0, + "value": "Filter" + } + ], "label.filter-combined": [ { "type": 0, @@ -407,6 +419,12 @@ "value": "Funnel" } ], + "label.funnel-description": [ + { + "type": 0, + "value": "Understand the conversion and drop-off rate of users." + } + ], "label.greater-than": [ { "type": 0, @@ -425,6 +443,12 @@ "value": "Insights" } ], + "label.insights-description": [ + { + "type": 0, + "value": "Dive deeper into your data by using segments and filters." + } + ], "label.is": [ { "type": 0, @@ -769,6 +793,12 @@ "value": "Retention" } ], + "label.retention-description": [ + { + "type": 0, + "value": "Measure your website stickiness by tracking how often users return." + } + ], "label.role": [ { "type": 0, @@ -793,6 +823,12 @@ "value": "Дэлгэц" } ], + "label.search": [ + { + "type": 0, + "value": "Search" + } + ], "label.select-date": [ { "type": 0, diff --git a/public/intl/messages/ms-MY.json b/public/intl/messages/ms-MY.json index e022e1227..874f3a3dd 100644 --- a/public/intl/messages/ms-MY.json +++ b/public/intl/messages/ms-MY.json @@ -179,6 +179,12 @@ "value": "Country" } ], + "label.create": [ + { + "type": 0, + "value": "Create" + } + ], "label.create-report": [ { "type": 0, @@ -383,6 +389,12 @@ "value": "Fields" } ], + "label.filter": [ + { + "type": 0, + "value": "Filter" + } + ], "label.filter-combined": [ { "type": 0, @@ -407,6 +419,12 @@ "value": "Funnel" } ], + "label.funnel-description": [ + { + "type": 0, + "value": "Understand the conversion and drop-off rate of users." + } + ], "label.greater-than": [ { "type": 0, @@ -425,6 +443,12 @@ "value": "Insights" } ], + "label.insights-description": [ + { + "type": 0, + "value": "Dive deeper into your data by using segments and filters." + } + ], "label.is": [ { "type": 0, @@ -761,6 +785,12 @@ "value": "Retention" } ], + "label.retention-description": [ + { + "type": 0, + "value": "Measure your website stickiness by tracking how often users return." + } + ], "label.role": [ { "type": 0, @@ -785,6 +815,12 @@ "value": "Screens" } ], + "label.search": [ + { + "type": 0, + "value": "Search" + } + ], "label.select-date": [ { "type": 0, diff --git a/public/intl/messages/my-MM.json b/public/intl/messages/my-MM.json index 3995a22b0..33b449793 100644 --- a/public/intl/messages/my-MM.json +++ b/public/intl/messages/my-MM.json @@ -41,6 +41,12 @@ "value": "အက်ဒမင်" } ], + "label.after": [ + { + "type": 0, + "value": "ပြီးနောက်" + } + ], "label.all": [ { "type": 0, @@ -59,6 +65,12 @@ "value": "အန်နလစ်တစ်" } ], + "label.average": [ + { + "type": 0, + "value": "ပျမ်းမျှ" + } + ], "label.average-visit-time": [ { "type": 0, @@ -71,12 +83,30 @@ "value": "နောက်သို့" } ], + "label.before": [ + { + "type": 0, + "value": "မတိုင်မီ" + } + ], "label.bounce-rate": [ { "type": 0, "value": "Bounce နှုန်း" } ], + "label.breakdown": [ + { + "type": 0, + "value": "ခွဲခြမ်းစိတ်ဖြာမှု" + } + ], + "label.browser": [ + { + "type": 0, + "value": "Browser" + } + ], "label.browsers": [ { "type": 0, @@ -101,6 +131,12 @@ "value": "မြို့များ" } ], + "label.city": [ + { + "type": 0, + "value": "City" + } + ], "label.clear-all": [ { "type": 0, @@ -119,6 +155,12 @@ "value": "စကားဝှက်အတည်ပြုသည်" } ], + "label.contains": [ + { + "type": 0, + "value": "ပါဝင်သည်" + } + ], "label.continue": [ { "type": 0, @@ -131,6 +173,24 @@ "value": "နိုင်ငံများ" } ], + "label.country": [ + { + "type": 0, + "value": "Country" + } + ], + "label.create": [ + { + "type": 0, + "value": "Create" + } + ], + "label.create-report": [ + { + "type": 0, + "value": "ရီပို့လုပ်မည်" + } + ], "label.create-team": [ { "type": 0, @@ -173,12 +233,24 @@ "value": "ဒေတာ" } ], + "label.date": [ + { + "type": 0, + "value": "Date" + } + ], "label.date-range": [ { "type": 0, "value": "ရက်အပိုင်းအခြား" } ], + "label.day": [ + { + "type": 0, + "value": "Day" + } + ], "label.default-date-range": [ { "type": 0, @@ -209,6 +281,12 @@ "value": "ဝက်ဘ်ဆိုဒ်ကိုဖျက်မည်" } ], + "label.description": [ + { + "type": 0, + "value": "ရှင်းပြချက်" + } + ], "label.desktop": [ { "type": 0, @@ -221,6 +299,12 @@ "value": "အသေးစိတ်" } ], + "label.device": [ + { + "type": 0, + "value": "Device" + } + ], "label.devices": [ { "type": 0, @@ -233,6 +317,12 @@ "value": "ပိတ်ပါ" } ], + "label.does-not-contain": [ + { + "type": 0, + "value": "မပါဝင်ပါ" + } + ], "label.domain": [ { "type": 0, @@ -281,6 +371,12 @@ "value": "အဖြစ်အပျက်များ" } ], + "label.false": [ + { + "type": 0, + "value": "မှားသည်" + } + ], "label.field": [ { "type": 0, @@ -293,6 +389,12 @@ "value": "Field အမည်များ" } ], + "label.filter": [ + { + "type": 0, + "value": "Filter" + } + ], "label.filter-combined": [ { "type": 0, @@ -305,18 +407,72 @@ "value": "အရှိအတိုင်း" } ], + "label.filters": [ + { + "type": 0, + "value": "Filter များ" + } + ], "label.funnel": [ { "type": 0, "value": "ဖန်နယ်" } ], + "label.funnel-description": [ + { + "type": 0, + "value": "Understand the conversion and drop-off rate of users." + } + ], + "label.greater-than": [ + { + "type": 0, + "value": "ထက်ပို၍ကြီးသည်" + } + ], + "label.greater-than-equals": [ + { + "type": 0, + "value": "ထက်ပို၍ကြီးသည်သို့မဟုတ်တူသည်" + } + ], "label.insights": [ { "type": 0, "value": "အသေးစိတ်သိမြင်နိုင်ရန်" } ], + "label.insights-description": [ + { + "type": 0, + "value": "Dive deeper into your data by using segments and filters." + } + ], + "label.is": [ + { + "type": 0, + "value": "Is" + } + ], + "label.is-not": [ + { + "type": 0, + "value": "Is not" + } + ], + "label.is-not-set": [ + { + "type": 0, + "value": "Is not set" + } + ], + "label.is-set": [ + { + "type": 0, + "value": "Is set" + } + ], "label.join": [ { "type": 0, @@ -387,6 +543,18 @@ "value": "အသင်းမှထွက်မည်" } ], + "label.less-than": [ + { + "type": 0, + "value": "ထက်ပို၍ငယ်သည်" + } + ], + "label.less-than-equals": [ + { + "type": 0, + "value": "ထက်ပို၍ငယ်သည်သို့မဟုတ်တူသည်" + } + ], "label.login": [ { "type": 0, @@ -399,12 +567,24 @@ "value": "လော့ဂ်အောက်လုပ်မည်" } ], + "label.max": [ + { + "type": 0, + "value": "အများဆုံး" + } + ], "label.members": [ { "type": 0, "value": "အဖွဲ့ဝင်များ" } ], + "label.min": [ + { + "type": 0, + "value": "အနည်းဆုံး" + } + ], "label.mobile": [ { "type": 0, @@ -417,6 +597,12 @@ "value": "နောက်ထပ်" } ], + "label.my-websites": [ + { + "type": 0, + "value": "My websites" + } + ], "label.name": [ { "type": 0, @@ -435,24 +621,54 @@ "value": "မရှိပါ" } ], - "label.operating-systems": [ + "label.os": [ { "type": 0, "value": "ကွန်ပျူတာလည်ပတ်မှုစနစ်" } ], + "label.overview": [ + { + "type": 0, + "value": "အပေါ်ယံမြင်ကွင်း" + } + ], "label.owner": [ { "type": 0, "value": "ပိုင်ဆိုင်သူ" } ], + "label.page-of": [ + { + "type": 0, + "value": "Page " + }, + { + "type": 1, + "value": "current" + }, + { + "type": 0, + "value": " of " + }, + { + "type": 1, + "value": "total" + } + ], "label.page-views": [ { "type": 0, "value": "ဝင်ရောက်ကြည့်ရှုသူ" } ], + "label.pageTitle": [ + { + "type": 0, + "value": "Page title" + } + ], "label.pages": [ { "type": 0, @@ -505,6 +721,12 @@ "value": "အချိန်နှင့်တပြေးညီ" } ], + "label.referrer": [ + { + "type": 0, + "value": "Referrer" + } + ], "label.referrers": [ { "type": 0, @@ -523,6 +745,12 @@ "value": "ပြန်ထုတ်မည်" } ], + "label.region": [ + { + "type": 0, + "value": "Region" + } + ], "label.regions": [ { "type": 0, @@ -559,6 +787,18 @@ "value": "ဝက်ဘ်ဆိုဒ်ဒေတာကိုဖျက်မည်" } ], + "label.retention": [ + { + "type": 0, + "value": "Retention" + } + ], + "label.retention-description": [ + { + "type": 0, + "value": "Measure your website stickiness by tracking how often users return." + } + ], "label.role": [ { "type": 0, @@ -583,6 +823,12 @@ "value": "မြင်ကွင်းများ" } ], + "label.search": [ + { + "type": 0, + "value": "Search" + } + ], "label.select-date": [ { "type": 0, @@ -619,6 +865,12 @@ "value": "တစ်ရက်အတွင်း" } ], + "label.sum": [ + { + "type": 0, + "value": "ပေါင်းလဒ်" + } + ], "label.tablet": [ { "type": 0, @@ -649,12 +901,24 @@ "value": "အသင်းဝင်" } ], + "label.team-name": [ + { + "type": 0, + "value": "Team name" + } + ], "label.team-owner": [ { "type": 0, "value": "အသင်းကိုပိုင်ဆိုင်သူ" } ], + "label.team-websites": [ + { + "type": 0, + "value": "Team websites" + } + ], "label.teams": [ { "type": 0, @@ -709,12 +973,42 @@ "value": "ဇယားများကို အဖွင့်အပိတ်လုပ်မည်" } ], + "label.total": [ + { + "type": 0, + "value": "စုစုပေါင်း" + } + ], + "label.total-records": [ + { + "type": 0, + "value": "မှတ်တမ်းစုစုပေါင်း" + } + ], "label.tracking-code": [ { "type": 0, "value": "ထရက်လုပ်သည့် ကုဒ်" } ], + "label.true": [ + { + "type": 0, + "value": "မှန်သည်" + } + ], + "label.type": [ + { + "type": 0, + "value": "အမျိုးအစား" + } + ], + "label.unique": [ + { + "type": 0, + "value": "Unique" + } + ], "label.unique-visitors": [ { "type": 0, @@ -727,6 +1021,12 @@ "value": "မသိသော" } ], + "label.untitled": [ + { + "type": 0, + "value": "ခေါင်းစဉ်မရှိ" + } + ], "label.url": [ { "type": 0, @@ -757,6 +1057,12 @@ "value": "အသုံးပြုသူများ" } ], + "label.value": [ + { + "type": 0, + "value": "တန်ဖိုး" + } + ], "label.view": [ { "type": 0, @@ -817,168 +1123,6 @@ "value": "မနေ့က" } ], - "labels.after": [ - { - "type": 0, - "value": "ပြီးနောက်" - } - ], - "labels.average": [ - { - "type": 0, - "value": "ပျမ်းမျှ" - } - ], - "labels.before": [ - { - "type": 0, - "value": "မတိုင်မီ" - } - ], - "labels.breakdown": [ - { - "type": 0, - "value": "ခွဲခြမ်းစိတ်ဖြာမှု" - } - ], - "labels.contains": [ - { - "type": 0, - "value": "ပါဝင်သည်" - } - ], - "labels.create-report": [ - { - "type": 0, - "value": "ရီပို့လုပ်မည်" - } - ], - "labels.description": [ - { - "type": 0, - "value": "ရှင်းပြချက်" - } - ], - "labels.does-not-contain": [ - { - "type": 0, - "value": "မပါဝင်ပါ" - } - ], - "labels.does-not-equal": [ - { - "type": 0, - "value": "မတူညီပါ" - } - ], - "labels.equals": [ - { - "type": 0, - "value": "တူညီသည်" - } - ], - "labels.false": [ - { - "type": 0, - "value": "မှားသည်" - } - ], - "labels.filters": [ - { - "type": 0, - "value": "Filter များ" - } - ], - "labels.greater-than": [ - { - "type": 0, - "value": "ထက်ပို၍ကြီးသည်" - } - ], - "labels.greater-than-equals": [ - { - "type": 0, - "value": "ထက်ပို၍ကြီးသည်သို့မဟုတ်တူသည်" - } - ], - "labels.less-than": [ - { - "type": 0, - "value": "ထက်ပို၍ငယ်သည်" - } - ], - "labels.less-than-equals": [ - { - "type": 0, - "value": "ထက်ပို၍ငယ်သည်သို့မဟုတ်တူသည်" - } - ], - "labels.max": [ - { - "type": 0, - "value": "အများဆုံး" - } - ], - "labels.min": [ - { - "type": 0, - "value": "အနည်းဆုံး" - } - ], - "labels.overview": [ - { - "type": 0, - "value": "အပေါ်ယံမြင်ကွင်း" - } - ], - "labels.sum": [ - { - "type": 0, - "value": "ပေါင်းလဒ်" - } - ], - "labels.total": [ - { - "type": 0, - "value": "စုစုပေါင်း" - } - ], - "labels.total-records": [ - { - "type": 0, - "value": "မှတ်တမ်းစုစုပေါင်း" - } - ], - "labels.true": [ - { - "type": 0, - "value": "မှန်သည်" - } - ], - "labels.type": [ - { - "type": 0, - "value": "အမျိုးအစား" - } - ], - "labels.unique": [ - { - "type": 0, - "value": "Unique" - } - ], - "labels.untitled": [ - { - "type": 0, - "value": "ခေါင်းစဉ်မရှိ" - } - ], - "labels.value": [ - { - "type": 0, - "value": "တန်ဖိုး" - } - ], "message.active-users": [ { "type": 1, diff --git a/public/intl/messages/nb-NO.json b/public/intl/messages/nb-NO.json index 82576ff89..010bd2ad4 100644 --- a/public/intl/messages/nb-NO.json +++ b/public/intl/messages/nb-NO.json @@ -179,6 +179,12 @@ "value": "Country" } ], + "label.create": [ + { + "type": 0, + "value": "Create" + } + ], "label.create-report": [ { "type": 0, @@ -383,6 +389,12 @@ "value": "Fields" } ], + "label.filter": [ + { + "type": 0, + "value": "Filter" + } + ], "label.filter-combined": [ { "type": 0, @@ -407,6 +419,12 @@ "value": "Funnel" } ], + "label.funnel-description": [ + { + "type": 0, + "value": "Understand the conversion and drop-off rate of users." + } + ], "label.greater-than": [ { "type": 0, @@ -425,6 +443,12 @@ "value": "Insights" } ], + "label.insights-description": [ + { + "type": 0, + "value": "Dive deeper into your data by using segments and filters." + } + ], "label.is": [ { "type": 0, @@ -769,6 +793,12 @@ "value": "Retention" } ], + "label.retention-description": [ + { + "type": 0, + "value": "Measure your website stickiness by tracking how often users return." + } + ], "label.role": [ { "type": 0, @@ -793,6 +823,12 @@ "value": "Screens" } ], + "label.search": [ + { + "type": 0, + "value": "Search" + } + ], "label.select-date": [ { "type": 0, diff --git a/public/intl/messages/nl-NL.json b/public/intl/messages/nl-NL.json index 5ee25206b..66c5f4faf 100644 --- a/public/intl/messages/nl-NL.json +++ b/public/intl/messages/nl-NL.json @@ -179,6 +179,12 @@ "value": "Country" } ], + "label.create": [ + { + "type": 0, + "value": "Create" + } + ], "label.create-report": [ { "type": 0, @@ -383,6 +389,12 @@ "value": "Fields" } ], + "label.filter": [ + { + "type": 0, + "value": "Filter" + } + ], "label.filter-combined": [ { "type": 0, @@ -407,6 +419,12 @@ "value": "Funnel" } ], + "label.funnel-description": [ + { + "type": 0, + "value": "Understand the conversion and drop-off rate of users." + } + ], "label.greater-than": [ { "type": 0, @@ -425,6 +443,12 @@ "value": "Insights" } ], + "label.insights-description": [ + { + "type": 0, + "value": "Dive deeper into your data by using segments and filters." + } + ], "label.is": [ { "type": 0, @@ -769,6 +793,12 @@ "value": "Retention" } ], + "label.retention-description": [ + { + "type": 0, + "value": "Measure your website stickiness by tracking how often users return." + } + ], "label.role": [ { "type": 0, @@ -793,6 +823,12 @@ "value": "Schermen" } ], + "label.search": [ + { + "type": 0, + "value": "Search" + } + ], "label.select-date": [ { "type": 0, diff --git a/public/intl/messages/pl-PL.json b/public/intl/messages/pl-PL.json index 6da1ff7ad..4621a918d 100644 --- a/public/intl/messages/pl-PL.json +++ b/public/intl/messages/pl-PL.json @@ -179,6 +179,12 @@ "value": "Country" } ], + "label.create": [ + { + "type": 0, + "value": "Create" + } + ], "label.create-report": [ { "type": 0, @@ -383,6 +389,12 @@ "value": "Pola" } ], + "label.filter": [ + { + "type": 0, + "value": "Filter" + } + ], "label.filter-combined": [ { "type": 0, @@ -407,6 +419,12 @@ "value": "Lejek" } ], + "label.funnel-description": [ + { + "type": 0, + "value": "Understand the conversion and drop-off rate of users." + } + ], "label.greater-than": [ { "type": 0, @@ -425,6 +443,12 @@ "value": "Insights" } ], + "label.insights-description": [ + { + "type": 0, + "value": "Dive deeper into your data by using segments and filters." + } + ], "label.is": [ { "type": 0, @@ -769,6 +793,12 @@ "value": "Retention" } ], + "label.retention-description": [ + { + "type": 0, + "value": "Measure your website stickiness by tracking how often users return." + } + ], "label.role": [ { "type": 0, @@ -793,6 +823,12 @@ "value": "Ekrany" } ], + "label.search": [ + { + "type": 0, + "value": "Search" + } + ], "label.select-date": [ { "type": 0, diff --git a/public/intl/messages/pt-BR.json b/public/intl/messages/pt-BR.json index ba508a504..790e13161 100644 --- a/public/intl/messages/pt-BR.json +++ b/public/intl/messages/pt-BR.json @@ -179,6 +179,12 @@ "value": "Country" } ], + "label.create": [ + { + "type": 0, + "value": "Create" + } + ], "label.create-report": [ { "type": 0, @@ -383,6 +389,12 @@ "value": "Campos" } ], + "label.filter": [ + { + "type": 0, + "value": "Filter" + } + ], "label.filter-combined": [ { "type": 0, @@ -407,6 +419,12 @@ "value": "Funil" } ], + "label.funnel-description": [ + { + "type": 0, + "value": "Understand the conversion and drop-off rate of users." + } + ], "label.greater-than": [ { "type": 0, @@ -425,6 +443,12 @@ "value": "Insights" } ], + "label.insights-description": [ + { + "type": 0, + "value": "Dive deeper into your data by using segments and filters." + } + ], "label.is": [ { "type": 0, @@ -769,6 +793,12 @@ "value": "Retention" } ], + "label.retention-description": [ + { + "type": 0, + "value": "Measure your website stickiness by tracking how often users return." + } + ], "label.role": [ { "type": 0, @@ -793,6 +823,12 @@ "value": "Telas" } ], + "label.search": [ + { + "type": 0, + "value": "Search" + } + ], "label.select-date": [ { "type": 0, diff --git a/public/intl/messages/pt-PT.json b/public/intl/messages/pt-PT.json index a6431fb3b..511d74fc6 100644 --- a/public/intl/messages/pt-PT.json +++ b/public/intl/messages/pt-PT.json @@ -179,6 +179,12 @@ "value": "Country" } ], + "label.create": [ + { + "type": 0, + "value": "Create" + } + ], "label.create-report": [ { "type": 0, @@ -383,6 +389,12 @@ "value": "Fields" } ], + "label.filter": [ + { + "type": 0, + "value": "Filter" + } + ], "label.filter-combined": [ { "type": 0, @@ -407,6 +419,12 @@ "value": "Funnel" } ], + "label.funnel-description": [ + { + "type": 0, + "value": "Understand the conversion and drop-off rate of users." + } + ], "label.greater-than": [ { "type": 0, @@ -425,6 +443,12 @@ "value": "Insights" } ], + "label.insights-description": [ + { + "type": 0, + "value": "Dive deeper into your data by using segments and filters." + } + ], "label.is": [ { "type": 0, @@ -769,6 +793,12 @@ "value": "Retention" } ], + "label.retention-description": [ + { + "type": 0, + "value": "Measure your website stickiness by tracking how often users return." + } + ], "label.role": [ { "type": 0, @@ -793,6 +823,12 @@ "value": "Screens" } ], + "label.search": [ + { + "type": 0, + "value": "Search" + } + ], "label.select-date": [ { "type": 0, diff --git a/public/intl/messages/ro-RO.json b/public/intl/messages/ro-RO.json index 1438ab413..9181c1035 100644 --- a/public/intl/messages/ro-RO.json +++ b/public/intl/messages/ro-RO.json @@ -179,6 +179,12 @@ "value": "Country" } ], + "label.create": [ + { + "type": 0, + "value": "Create" + } + ], "label.create-report": [ { "type": 0, @@ -383,6 +389,12 @@ "value": "Fields" } ], + "label.filter": [ + { + "type": 0, + "value": "Filter" + } + ], "label.filter-combined": [ { "type": 0, @@ -407,6 +419,12 @@ "value": "Funnel" } ], + "label.funnel-description": [ + { + "type": 0, + "value": "Understand the conversion and drop-off rate of users." + } + ], "label.greater-than": [ { "type": 0, @@ -425,6 +443,12 @@ "value": "Insights" } ], + "label.insights-description": [ + { + "type": 0, + "value": "Dive deeper into your data by using segments and filters." + } + ], "label.is": [ { "type": 0, @@ -769,6 +793,12 @@ "value": "Retention" } ], + "label.retention-description": [ + { + "type": 0, + "value": "Measure your website stickiness by tracking how often users return." + } + ], "label.role": [ { "type": 0, @@ -793,6 +823,12 @@ "value": "Screens" } ], + "label.search": [ + { + "type": 0, + "value": "Search" + } + ], "label.select-date": [ { "type": 0, diff --git a/public/intl/messages/ru-RU.json b/public/intl/messages/ru-RU.json index b3213e679..93b89291d 100644 --- a/public/intl/messages/ru-RU.json +++ b/public/intl/messages/ru-RU.json @@ -179,6 +179,12 @@ "value": "Country" } ], + "label.create": [ + { + "type": 0, + "value": "Create" + } + ], "label.create-report": [ { "type": 0, @@ -383,6 +389,12 @@ "value": "Fields" } ], + "label.filter": [ + { + "type": 0, + "value": "Filter" + } + ], "label.filter-combined": [ { "type": 0, @@ -407,6 +419,12 @@ "value": "Funnel" } ], + "label.funnel-description": [ + { + "type": 0, + "value": "Understand the conversion and drop-off rate of users." + } + ], "label.greater-than": [ { "type": 0, @@ -425,6 +443,12 @@ "value": "Insights" } ], + "label.insights-description": [ + { + "type": 0, + "value": "Dive deeper into your data by using segments and filters." + } + ], "label.is": [ { "type": 0, @@ -769,6 +793,12 @@ "value": "Retention" } ], + "label.retention-description": [ + { + "type": 0, + "value": "Measure your website stickiness by tracking how often users return." + } + ], "label.role": [ { "type": 0, @@ -793,6 +823,12 @@ "value": "Экраны" } ], + "label.search": [ + { + "type": 0, + "value": "Search" + } + ], "label.select-date": [ { "type": 0, diff --git a/public/intl/messages/si-LK.json b/public/intl/messages/si-LK.json index f4e5bca2f..578a8abed 100644 --- a/public/intl/messages/si-LK.json +++ b/public/intl/messages/si-LK.json @@ -179,6 +179,12 @@ "value": "Country" } ], + "label.create": [ + { + "type": 0, + "value": "Create" + } + ], "label.create-report": [ { "type": 0, @@ -383,6 +389,12 @@ "value": "Fields" } ], + "label.filter": [ + { + "type": 0, + "value": "Filter" + } + ], "label.filter-combined": [ { "type": 0, @@ -407,6 +419,12 @@ "value": "Funnel" } ], + "label.funnel-description": [ + { + "type": 0, + "value": "Understand the conversion and drop-off rate of users." + } + ], "label.greater-than": [ { "type": 0, @@ -425,6 +443,12 @@ "value": "Insights" } ], + "label.insights-description": [ + { + "type": 0, + "value": "Dive deeper into your data by using segments and filters." + } + ], "label.is": [ { "type": 0, @@ -769,6 +793,12 @@ "value": "Retention" } ], + "label.retention-description": [ + { + "type": 0, + "value": "Measure your website stickiness by tracking how often users return." + } + ], "label.role": [ { "type": 0, @@ -793,6 +823,12 @@ "value": "Screens" } ], + "label.search": [ + { + "type": 0, + "value": "Search" + } + ], "label.select-date": [ { "type": 0, diff --git a/public/intl/messages/sk-SK.json b/public/intl/messages/sk-SK.json index b7e2914a9..6b375afed 100644 --- a/public/intl/messages/sk-SK.json +++ b/public/intl/messages/sk-SK.json @@ -179,6 +179,12 @@ "value": "Country" } ], + "label.create": [ + { + "type": 0, + "value": "Create" + } + ], "label.create-report": [ { "type": 0, @@ -383,6 +389,12 @@ "value": "Fields" } ], + "label.filter": [ + { + "type": 0, + "value": "Filter" + } + ], "label.filter-combined": [ { "type": 0, @@ -407,6 +419,12 @@ "value": "Funnel" } ], + "label.funnel-description": [ + { + "type": 0, + "value": "Understand the conversion and drop-off rate of users." + } + ], "label.greater-than": [ { "type": 0, @@ -425,6 +443,12 @@ "value": "Insights" } ], + "label.insights-description": [ + { + "type": 0, + "value": "Dive deeper into your data by using segments and filters." + } + ], "label.is": [ { "type": 0, @@ -769,6 +793,12 @@ "value": "Retention" } ], + "label.retention-description": [ + { + "type": 0, + "value": "Measure your website stickiness by tracking how often users return." + } + ], "label.role": [ { "type": 0, @@ -793,6 +823,12 @@ "value": "Screens" } ], + "label.search": [ + { + "type": 0, + "value": "Search" + } + ], "label.select-date": [ { "type": 0, diff --git a/public/intl/messages/sl-SI.json b/public/intl/messages/sl-SI.json index ee62a3153..6d435020c 100644 --- a/public/intl/messages/sl-SI.json +++ b/public/intl/messages/sl-SI.json @@ -179,6 +179,12 @@ "value": "Država" } ], + "label.create": [ + { + "type": 0, + "value": "Create" + } + ], "label.create-report": [ { "type": 0, @@ -383,6 +389,12 @@ "value": "Polja" } ], + "label.filter": [ + { + "type": 0, + "value": "Filter" + } + ], "label.filter-combined": [ { "type": 0, @@ -407,6 +419,12 @@ "value": "Prodajni lijak" } ], + "label.funnel-description": [ + { + "type": 0, + "value": "Understand the conversion and drop-off rate of users." + } + ], "label.greater-than": [ { "type": 0, @@ -425,6 +443,12 @@ "value": "Vpogled" } ], + "label.insights-description": [ + { + "type": 0, + "value": "Dive deeper into your data by using segments and filters." + } + ], "label.is": [ { "type": 0, @@ -769,6 +793,12 @@ "value": "Ohranjanje uporabnikov" } ], + "label.retention-description": [ + { + "type": 0, + "value": "Measure your website stickiness by tracking how often users return." + } + ], "label.role": [ { "type": 0, @@ -793,6 +823,12 @@ "value": "Zasloni" } ], + "label.search": [ + { + "type": 0, + "value": "Search" + } + ], "label.select-date": [ { "type": 0, diff --git a/public/intl/messages/sv-SE.json b/public/intl/messages/sv-SE.json index 4a7f4130c..9824be155 100644 --- a/public/intl/messages/sv-SE.json +++ b/public/intl/messages/sv-SE.json @@ -179,6 +179,12 @@ "value": "Country" } ], + "label.create": [ + { + "type": 0, + "value": "Create" + } + ], "label.create-report": [ { "type": 0, @@ -383,6 +389,12 @@ "value": "Fields" } ], + "label.filter": [ + { + "type": 0, + "value": "Filter" + } + ], "label.filter-combined": [ { "type": 0, @@ -407,6 +419,12 @@ "value": "Funnel" } ], + "label.funnel-description": [ + { + "type": 0, + "value": "Understand the conversion and drop-off rate of users." + } + ], "label.greater-than": [ { "type": 0, @@ -425,6 +443,12 @@ "value": "Insights" } ], + "label.insights-description": [ + { + "type": 0, + "value": "Dive deeper into your data by using segments and filters." + } + ], "label.is": [ { "type": 0, @@ -769,6 +793,12 @@ "value": "Retention" } ], + "label.retention-description": [ + { + "type": 0, + "value": "Measure your website stickiness by tracking how often users return." + } + ], "label.role": [ { "type": 0, @@ -793,6 +823,12 @@ "value": "Upplösning" } ], + "label.search": [ + { + "type": 0, + "value": "Search" + } + ], "label.select-date": [ { "type": 0, diff --git a/public/intl/messages/ta-IN.json b/public/intl/messages/ta-IN.json index 90fb9ebf1..9726b46d5 100644 --- a/public/intl/messages/ta-IN.json +++ b/public/intl/messages/ta-IN.json @@ -179,6 +179,12 @@ "value": "Country" } ], + "label.create": [ + { + "type": 0, + "value": "Create" + } + ], "label.create-report": [ { "type": 0, @@ -383,6 +389,12 @@ "value": "Fields" } ], + "label.filter": [ + { + "type": 0, + "value": "Filter" + } + ], "label.filter-combined": [ { "type": 0, @@ -407,6 +419,12 @@ "value": "Funnel" } ], + "label.funnel-description": [ + { + "type": 0, + "value": "Understand the conversion and drop-off rate of users." + } + ], "label.greater-than": [ { "type": 0, @@ -425,6 +443,12 @@ "value": "Insights" } ], + "label.insights-description": [ + { + "type": 0, + "value": "Dive deeper into your data by using segments and filters." + } + ], "label.is": [ { "type": 0, @@ -769,6 +793,12 @@ "value": "Retention" } ], + "label.retention-description": [ + { + "type": 0, + "value": "Measure your website stickiness by tracking how often users return." + } + ], "label.role": [ { "type": 0, @@ -793,6 +823,12 @@ "value": "Screens" } ], + "label.search": [ + { + "type": 0, + "value": "Search" + } + ], "label.select-date": [ { "type": 0, diff --git a/public/intl/messages/th-TH.json b/public/intl/messages/th-TH.json index c30a9d61f..6988c653b 100644 --- a/public/intl/messages/th-TH.json +++ b/public/intl/messages/th-TH.json @@ -179,6 +179,12 @@ "value": "Country" } ], + "label.create": [ + { + "type": 0, + "value": "Create" + } + ], "label.create-report": [ { "type": 0, @@ -383,6 +389,12 @@ "value": "Fields" } ], + "label.filter": [ + { + "type": 0, + "value": "Filter" + } + ], "label.filter-combined": [ { "type": 0, @@ -407,6 +419,12 @@ "value": "Funnel" } ], + "label.funnel-description": [ + { + "type": 0, + "value": "Understand the conversion and drop-off rate of users." + } + ], "label.greater-than": [ { "type": 0, @@ -425,6 +443,12 @@ "value": "Insights" } ], + "label.insights-description": [ + { + "type": 0, + "value": "Dive deeper into your data by using segments and filters." + } + ], "label.is": [ { "type": 0, @@ -761,6 +785,12 @@ "value": "Retention" } ], + "label.retention-description": [ + { + "type": 0, + "value": "Measure your website stickiness by tracking how often users return." + } + ], "label.role": [ { "type": 0, @@ -785,6 +815,12 @@ "value": "ขนาดหน้าจอ" } ], + "label.search": [ + { + "type": 0, + "value": "Search" + } + ], "label.select-date": [ { "type": 0, diff --git a/public/intl/messages/tr-TR.json b/public/intl/messages/tr-TR.json index 138681adb..f15a3b732 100644 --- a/public/intl/messages/tr-TR.json +++ b/public/intl/messages/tr-TR.json @@ -179,6 +179,12 @@ "value": "Country" } ], + "label.create": [ + { + "type": 0, + "value": "Create" + } + ], "label.create-report": [ { "type": 0, @@ -383,6 +389,12 @@ "value": "Fields" } ], + "label.filter": [ + { + "type": 0, + "value": "Filter" + } + ], "label.filter-combined": [ { "type": 0, @@ -407,6 +419,12 @@ "value": "Funnel" } ], + "label.funnel-description": [ + { + "type": 0, + "value": "Understand the conversion and drop-off rate of users." + } + ], "label.greater-than": [ { "type": 0, @@ -425,6 +443,12 @@ "value": "Insights" } ], + "label.insights-description": [ + { + "type": 0, + "value": "Dive deeper into your data by using segments and filters." + } + ], "label.is": [ { "type": 0, @@ -769,6 +793,12 @@ "value": "Retention" } ], + "label.retention-description": [ + { + "type": 0, + "value": "Measure your website stickiness by tracking how often users return." + } + ], "label.role": [ { "type": 0, @@ -793,6 +823,12 @@ "value": "Ekranlar" } ], + "label.search": [ + { + "type": 0, + "value": "Search" + } + ], "label.select-date": [ { "type": 0, diff --git a/public/intl/messages/uk-UA.json b/public/intl/messages/uk-UA.json index bdc2d345b..2c602c947 100644 --- a/public/intl/messages/uk-UA.json +++ b/public/intl/messages/uk-UA.json @@ -179,6 +179,12 @@ "value": "Country" } ], + "label.create": [ + { + "type": 0, + "value": "Create" + } + ], "label.create-report": [ { "type": 0, @@ -383,6 +389,12 @@ "value": "Fields" } ], + "label.filter": [ + { + "type": 0, + "value": "Filter" + } + ], "label.filter-combined": [ { "type": 0, @@ -407,6 +419,12 @@ "value": "Funnel" } ], + "label.funnel-description": [ + { + "type": 0, + "value": "Understand the conversion and drop-off rate of users." + } + ], "label.greater-than": [ { "type": 0, @@ -425,6 +443,12 @@ "value": "Insights" } ], + "label.insights-description": [ + { + "type": 0, + "value": "Dive deeper into your data by using segments and filters." + } + ], "label.is": [ { "type": 0, @@ -769,6 +793,12 @@ "value": "Retention" } ], + "label.retention-description": [ + { + "type": 0, + "value": "Measure your website stickiness by tracking how often users return." + } + ], "label.role": [ { "type": 0, @@ -793,6 +823,12 @@ "value": "Screens" } ], + "label.search": [ + { + "type": 0, + "value": "Search" + } + ], "label.select-date": [ { "type": 0, diff --git a/public/intl/messages/ur-PK.json b/public/intl/messages/ur-PK.json index 2005bc719..23195ffc0 100644 --- a/public/intl/messages/ur-PK.json +++ b/public/intl/messages/ur-PK.json @@ -179,6 +179,12 @@ "value": "Country" } ], + "label.create": [ + { + "type": 0, + "value": "Create" + } + ], "label.create-report": [ { "type": 0, @@ -383,6 +389,12 @@ "value": "Fields" } ], + "label.filter": [ + { + "type": 0, + "value": "Filter" + } + ], "label.filter-combined": [ { "type": 0, @@ -407,6 +419,12 @@ "value": "Funnel" } ], + "label.funnel-description": [ + { + "type": 0, + "value": "Understand the conversion and drop-off rate of users." + } + ], "label.greater-than": [ { "type": 0, @@ -425,6 +443,12 @@ "value": "Insights" } ], + "label.insights-description": [ + { + "type": 0, + "value": "Dive deeper into your data by using segments and filters." + } + ], "label.is": [ { "type": 0, @@ -769,6 +793,12 @@ "value": "Retention" } ], + "label.retention-description": [ + { + "type": 0, + "value": "Measure your website stickiness by tracking how often users return." + } + ], "label.role": [ { "type": 0, @@ -793,6 +823,12 @@ "value": "Screens" } ], + "label.search": [ + { + "type": 0, + "value": "Search" + } + ], "label.select-date": [ { "type": 0, diff --git a/public/intl/messages/vi-VN.json b/public/intl/messages/vi-VN.json index 9fe0dd4ed..4c3ef05cb 100644 --- a/public/intl/messages/vi-VN.json +++ b/public/intl/messages/vi-VN.json @@ -179,6 +179,12 @@ "value": "Country" } ], + "label.create": [ + { + "type": 0, + "value": "Create" + } + ], "label.create-report": [ { "type": 0, @@ -383,6 +389,12 @@ "value": "Fields" } ], + "label.filter": [ + { + "type": 0, + "value": "Filter" + } + ], "label.filter-combined": [ { "type": 0, @@ -407,6 +419,12 @@ "value": "Funnel" } ], + "label.funnel-description": [ + { + "type": 0, + "value": "Understand the conversion and drop-off rate of users." + } + ], "label.greater-than": [ { "type": 0, @@ -425,6 +443,12 @@ "value": "Insights" } ], + "label.insights-description": [ + { + "type": 0, + "value": "Dive deeper into your data by using segments and filters." + } + ], "label.is": [ { "type": 0, @@ -761,6 +785,12 @@ "value": "Retention" } ], + "label.retention-description": [ + { + "type": 0, + "value": "Measure your website stickiness by tracking how often users return." + } + ], "label.role": [ { "type": 0, @@ -785,6 +815,12 @@ "value": "Screens" } ], + "label.search": [ + { + "type": 0, + "value": "Search" + } + ], "label.select-date": [ { "type": 0, diff --git a/public/intl/messages/zh-CN.json b/public/intl/messages/zh-CN.json index ec5c441b2..acc98be29 100644 --- a/public/intl/messages/zh-CN.json +++ b/public/intl/messages/zh-CN.json @@ -179,6 +179,12 @@ "value": "国家/地区" } ], + "label.create": [ + { + "type": 0, + "value": "Create" + } + ], "label.create-report": [ { "type": 0, @@ -383,6 +389,12 @@ "value": "Fields" } ], + "label.filter": [ + { + "type": 0, + "value": "Filter" + } + ], "label.filter-combined": [ { "type": 0, @@ -407,6 +419,12 @@ "value": "分析" } ], + "label.funnel-description": [ + { + "type": 0, + "value": "Understand the conversion and drop-off rate of users." + } + ], "label.greater-than": [ { "type": 0, @@ -425,6 +443,12 @@ "value": "见解" } ], + "label.insights-description": [ + { + "type": 0, + "value": "Dive deeper into your data by using segments and filters." + } + ], "label.is": [ { "type": 0, @@ -777,6 +801,12 @@ "value": "保留" } ], + "label.retention-description": [ + { + "type": 0, + "value": "Measure your website stickiness by tracking how often users return." + } + ], "label.role": [ { "type": 0, @@ -801,6 +831,12 @@ "value": "屏幕尺寸" } ], + "label.search": [ + { + "type": 0, + "value": "Search" + } + ], "label.select-date": [ { "type": 0, diff --git a/public/intl/messages/zh-TW.json b/public/intl/messages/zh-TW.json index c980c4bb9..49e438216 100644 --- a/public/intl/messages/zh-TW.json +++ b/public/intl/messages/zh-TW.json @@ -179,6 +179,12 @@ "value": "國家" } ], + "label.create": [ + { + "type": 0, + "value": "Create" + } + ], "label.create-report": [ { "type": 0, @@ -383,6 +389,12 @@ "value": "欄位" } ], + "label.filter": [ + { + "type": 0, + "value": "Filter" + } + ], "label.filter-combined": [ { "type": 0, @@ -407,6 +419,12 @@ "value": "漏斗" } ], + "label.funnel-description": [ + { + "type": 0, + "value": "Understand the conversion and drop-off rate of users." + } + ], "label.greater-than": [ { "type": 0, @@ -425,6 +443,12 @@ "value": "洞察" } ], + "label.insights-description": [ + { + "type": 0, + "value": "Dive deeper into your data by using segments and filters." + } + ], "label.is": [ { "type": 0, @@ -773,6 +797,12 @@ "value": "保留" } ], + "label.retention-description": [ + { + "type": 0, + "value": "Measure your website stickiness by tracking how often users return." + } + ], "label.role": [ { "type": 0, @@ -797,6 +827,12 @@ "value": "螢幕" } ], + "label.search": [ + { + "type": 0, + "value": "Search" + } + ], "label.select-date": [ { "type": 0, diff --git a/src/lang/de-DE.json b/src/lang/de-DE.json index 688898033..1e98b14cc 100644 --- a/src/lang/de-DE.json +++ b/src/lang/de-DE.json @@ -29,6 +29,7 @@ "label.continue": "Weiter", "label.countries": "Länder", "label.country": "Land", + "label.create": "Create", "label.create-report": "Bericht erstellen", "label.create-team": "Team erstellen", "label.create-user": "Benutzer erstellen", @@ -62,7 +63,8 @@ "label.events": "Ereignisse", "label.false": "Falsch", "label.field": "Feld", - "label.fields": "Felder", "label.filter": "Filter", + "label.fields": "Felder", + "label.filter": "Filter", "label.filter-combined": "Kombiniert", "label.filter-raw": "Rohdaten", "label.filters": "Filter", From 661fc9223097a24d841f86661d8d84da7476b60b Mon Sep 17 00:00:00 2001 From: Francis Cao Date: Tue, 5 Sep 2023 11:09:27 -0700 Subject: [PATCH 091/113] fix session metrics to show visitors instead of views --- src/queries/analytics/sessions/getSessionMetrics.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/queries/analytics/sessions/getSessionMetrics.ts b/src/queries/analytics/sessions/getSessionMetrics.ts index af358c525..43d9ef5a4 100644 --- a/src/queries/analytics/sessions/getSessionMetrics.ts +++ b/src/queries/analytics/sessions/getSessionMetrics.ts @@ -31,7 +31,7 @@ async function relationalQuery(websiteId: string, column: string, filters: Query ` select ${column} x, - count(*) y + count(distinct website_event.session_id) y ${includeCountry ? ', country' : ''} from website_event ${joinSession} From 99cfc68e88222b2452a9cb989d55794f3571953f Mon Sep 17 00:00:00 2001 From: Francis Cao Date: Tue, 5 Sep 2023 12:22:51 -0700 Subject: [PATCH 092/113] exclude website domain from referrers table --- .../analytics/pageviews/getPageviewMetrics.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/queries/analytics/pageviews/getPageviewMetrics.ts b/src/queries/analytics/pageviews/getPageviewMetrics.ts index b365d3f6b..3cf6c122d 100644 --- a/src/queries/analytics/pageviews/getPageviewMetrics.ts +++ b/src/queries/analytics/pageviews/getPageviewMetrics.ts @@ -24,6 +24,12 @@ async function relationalQuery(websiteId: string, column: string, filters: Query { joinSession: SESSION_COLUMNS.includes(column) }, ); + let excludeDomain = ''; + if (column === 'referrer_domain') { + excludeDomain = + 'and (website_event.referrer_domain != {{websiteDomain}} or website_event.referrer_domain is null)'; + } + return rawQuery( ` select ${column} x, count(*) y @@ -32,6 +38,7 @@ async function relationalQuery(websiteId: string, column: string, filters: Query where website_event.website_id = {{websiteId::uuid}} and website_event.created_at between {{startDate}} and {{endDate}} and event_type = {{eventType}} + ${excludeDomain} ${filterQuery} group by 1 order by 2 desc @@ -48,6 +55,11 @@ async function clickhouseQuery(websiteId: string, column: string, filters: Query eventType: column === 'event_name' ? EVENT_TYPE.customEvent : EVENT_TYPE.pageView, }); + let excludeDomain = ''; + if (column === 'referrer_domain') { + excludeDomain = 'and referrer_domain != {websiteDomain:String}'; + } + return rawQuery( ` select ${column} x, count(*) y @@ -55,6 +67,7 @@ async function clickhouseQuery(websiteId: string, column: string, filters: Query where website_id = {websiteId:UUID} and created_at between {startDate:DateTime} and {endDate:DateTime} and event_type = {eventType:UInt32} + ${excludeDomain} ${filterQuery} group by x order by y desc From da3cc9b06567c17ae6c7726a99c9bdc3be9ab040 Mon Sep 17 00:00:00 2001 From: Francis Cao Date: Tue, 5 Sep 2023 13:53:58 -0700 Subject: [PATCH 093/113] fix isLoading param for SubmitButton --- src/components/pages/reports/event-data/EventDataParameters.js | 2 +- src/components/pages/reports/funnel/FunnelParameters.js | 2 +- src/components/pages/reports/insights/InsightsParameters.js | 2 +- src/components/pages/reports/retention/RetentionParameters.js | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/pages/reports/event-data/EventDataParameters.js b/src/components/pages/reports/event-data/EventDataParameters.js index a01a29722..e0fadb8b8 100644 --- a/src/components/pages/reports/event-data/EventDataParameters.js +++ b/src/components/pages/reports/event-data/EventDataParameters.js @@ -134,7 +134,7 @@ export function EventDataParameters() { ); })} - + {formatMessage(labels.runQuery)} diff --git a/src/components/pages/reports/funnel/FunnelParameters.js b/src/components/pages/reports/funnel/FunnelParameters.js index 2c99a032e..a3fbe6634 100644 --- a/src/components/pages/reports/funnel/FunnelParameters.js +++ b/src/components/pages/reports/funnel/FunnelParameters.js @@ -80,7 +80,7 @@ export function FunnelParameters() { - + {formatMessage(labels.runQuery)} diff --git a/src/components/pages/reports/insights/InsightsParameters.js b/src/components/pages/reports/insights/InsightsParameters.js index db0c1d4ea..3ddc0367d 100644 --- a/src/components/pages/reports/insights/InsightsParameters.js +++ b/src/components/pages/reports/insights/InsightsParameters.js @@ -137,7 +137,7 @@ export function InsightsParameters() { ); })} - + {formatMessage(labels.runQuery)} diff --git a/src/components/pages/reports/retention/RetentionParameters.js b/src/components/pages/reports/retention/RetentionParameters.js index aa81cf472..e87108d13 100644 --- a/src/components/pages/reports/retention/RetentionParameters.js +++ b/src/components/pages/reports/retention/RetentionParameters.js @@ -35,7 +35,7 @@ export function RetentionParameters() { - + {formatMessage(labels.runQuery)} From acb7fdcae8eba2152d8246517d711e4af67bf4bf Mon Sep 17 00:00:00 2001 From: Francis Cao Date: Tue, 5 Sep 2023 14:27:06 -0700 Subject: [PATCH 094/113] add version endpoint --- src/pages/api/version.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 src/pages/api/version.ts diff --git a/src/pages/api/version.ts b/src/pages/api/version.ts new file mode 100644 index 000000000..4453b56f0 --- /dev/null +++ b/src/pages/api/version.ts @@ -0,0 +1,17 @@ +import { NextApiRequest, NextApiResponse } from 'next'; +import { ok, methodNotAllowed } from 'next-basics'; +import { CURRENT_VERSION } from 'lib/constants'; + +export interface VersionResponse { + version: string; +} + +export default async (req: NextApiRequest, res: NextApiResponse) => { + if (req.method === 'GET') { + return ok(res, { + version: CURRENT_VERSION, + }); + } + + return methodNotAllowed(res); +}; From 0e0788b0a1b13e133840fe7c12576cfba2e4325c Mon Sep 17 00:00:00 2001 From: Francis Cao Date: Wed, 6 Sep 2023 11:34:12 -0700 Subject: [PATCH 095/113] Fix v1 check error showing in postgres logs --- scripts/check-db.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/scripts/check-db.js b/scripts/check-db.js index a84a775ce..757843ac3 100644 --- a/scripts/check-db.js +++ b/scripts/check-db.js @@ -66,12 +66,16 @@ async function checkDatabaseVersion() { async function checkV1Tables() { try { - await prisma.$queryRaw`select * from account limit 1`; + // check for v1 migrations before v2 release date + const record = + await prisma.$queryRaw`select * from _prisma_migrations where started_at < '2023-04-17'`; - error( - 'Umami v1 tables detected. For how to upgrade from v1 to v2 go to https://umami.is/docs/migrate-v1-v2.', - ); - process.exit(1); + if (record.length > 0) { + error( + 'Umami v1 tables detected. For how to upgrade from v1 to v2 go to https://umami.is/docs/migrate-v1-v2.', + ); + process.exit(1); + } } catch (e) { // Ignore } From c5dd3390d61cc77169f17a92463d59f2b05710de Mon Sep 17 00:00:00 2001 From: Brian Cao Date: Wed, 6 Sep 2023 11:37:41 -0700 Subject: [PATCH 096/113] Fix teamRole showing. --- .../pages/settings/teams/TeamMembersTable.js | 4 +++- src/pages/api/teams/[id]/index.ts | 4 ++-- src/queries/admin/user.ts | 13 ++++++++++++- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/components/pages/settings/teams/TeamMembersTable.js b/src/components/pages/settings/teams/TeamMembersTable.js index 4f620cf77..0755c1932 100644 --- a/src/components/pages/settings/teams/TeamMembersTable.js +++ b/src/components/pages/settings/teams/TeamMembersTable.js @@ -29,7 +29,9 @@ export function TeamMembersTable({ } if (key === 'role') { return formatMessage( - labels[Object.keys(ROLES).find(key => ROLES[key] === row.role) || labels.unknown], + labels[ + Object.keys(ROLES).find(key => ROLES[key] === row?.teamUser[0]?.role) || labels.unknown + ], ); } return data[key]; diff --git a/src/pages/api/teams/[id]/index.ts b/src/pages/api/teams/[id]/index.ts index 31c47b2f1..a5527580d 100644 --- a/src/pages/api/teams/[id]/index.ts +++ b/src/pages/api/teams/[id]/index.ts @@ -22,8 +22,8 @@ const schema = { }), POST: yup.object().shape({ id: yup.string().uuid().required(), - name: yup.string().max(50).required(), - accessCode: yup.string().max(50).required(), + name: yup.string().max(50), + accessCode: yup.string().max(50), }), DELETE: yup.object().shape({ id: yup.string().uuid().required(), diff --git a/src/queries/admin/user.ts b/src/queries/admin/user.ts index dfe8ea283..ee6f778b0 100644 --- a/src/queries/admin/user.ts +++ b/src/queries/admin/user.ts @@ -97,7 +97,18 @@ export async function getUsers( } export async function getUsersByTeamId(teamId: string, filter?: UserSearchFilter) { - return getUsers({ teamId, ...filter }); + return getUsers( + { teamId, ...filter }, + { + include: { + teamUser: { + select: { + role: true, + }, + }, + }, + }, + ); } export async function createUser(data: { From 36bae3f709d7fa8b3f26b123afa4410a38e37436 Mon Sep 17 00:00:00 2001 From: Brian Cao Date: Wed, 6 Sep 2023 12:52:08 -0700 Subject: [PATCH 097/113] Fix default page size. --- src/pages/api/reports/index.ts | 2 +- src/pages/api/teams/[id]/users/index.ts | 2 +- src/pages/api/teams/[id]/websites/index.ts | 2 +- src/pages/api/teams/index.ts | 6 +++++- src/pages/api/users/[id]/teams.ts | 2 +- src/pages/api/users/[id]/websites.ts | 2 +- src/pages/api/websites/[id]/reports.ts | 2 +- 7 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/pages/api/reports/index.ts b/src/pages/api/reports/index.ts index e62a1cc57..b36c5638d 100644 --- a/src/pages/api/reports/index.ts +++ b/src/pages/api/reports/index.ts @@ -57,7 +57,7 @@ export default async ( const data = await getReportsByUserId(userId, { page, filter, - pageSize: +pageSize || null, + pageSize: +pageSize || undefined, includeTeams: true, }); diff --git a/src/pages/api/teams/[id]/users/index.ts b/src/pages/api/teams/[id]/users/index.ts index 52b25da68..d0efba25f 100644 --- a/src/pages/api/teams/[id]/users/index.ts +++ b/src/pages/api/teams/[id]/users/index.ts @@ -32,7 +32,7 @@ export default async ( const users = await getUsersByTeamId(teamId, { page, filter, - pageSize: +pageSize || null, + pageSize: +pageSize || undefined, }); return ok(res, users); diff --git a/src/pages/api/teams/[id]/websites/index.ts b/src/pages/api/teams/[id]/websites/index.ts index 4de327092..d4b70b7f4 100644 --- a/src/pages/api/teams/[id]/websites/index.ts +++ b/src/pages/api/teams/[id]/websites/index.ts @@ -49,7 +49,7 @@ export default async ( const websites = await getWebsitesByTeamId(teamId, { page, filter, - pageSize: +pageSize || null, + pageSize: +pageSize || undefined, }); return ok(res, websites); diff --git a/src/pages/api/teams/index.ts b/src/pages/api/teams/index.ts index dd742b9e2..7ef6f533e 100644 --- a/src/pages/api/teams/index.ts +++ b/src/pages/api/teams/index.ts @@ -41,7 +41,11 @@ export default async ( if (req.method === 'GET') { const { page, filter, pageSize } = req.query; - const results = await getTeamsByUserId(userId, { page, filter, pageSize: +pageSize || null }); + const results = await getTeamsByUserId(userId, { + page, + filter, + pageSize: +pageSize || undefined, + }); return ok(res, results); } diff --git a/src/pages/api/users/[id]/teams.ts b/src/pages/api/users/[id]/teams.ts index eb34410cb..72b99b869 100644 --- a/src/pages/api/users/[id]/teams.ts +++ b/src/pages/api/users/[id]/teams.ts @@ -45,7 +45,7 @@ export default async ( const teams = await getTeamsByUserId(userId, { page, filter, - pageSize: +pageSize || null, + pageSize: +pageSize || undefined, }); return ok(res, teams); diff --git a/src/pages/api/users/[id]/websites.ts b/src/pages/api/users/[id]/websites.ts index 65e9a0e8a..ab7d88ef6 100644 --- a/src/pages/api/users/[id]/websites.ts +++ b/src/pages/api/users/[id]/websites.ts @@ -42,7 +42,7 @@ export default async ( const websites = await getWebsitesByUserId(userId, { page, filter, - pageSize: +pageSize || null, + pageSize: +pageSize || undefined, includeTeams, onlyTeams, }); diff --git a/src/pages/api/websites/[id]/reports.ts b/src/pages/api/websites/[id]/reports.ts index 738f6b372..2c7707e8d 100644 --- a/src/pages/api/websites/[id]/reports.ts +++ b/src/pages/api/websites/[id]/reports.ts @@ -38,7 +38,7 @@ export default async ( const data = await getReportsByWebsiteId(websiteId, { page, filter, - pageSize: +pageSize || null, + pageSize: +pageSize || undefined, }); return ok(res, data); From 9b501d03e9b60ecb1d56e3862db7a7bd3c8e3fb7 Mon Sep 17 00:00:00 2001 From: Maxime-J Date: Sat, 9 Sep 2023 09:38:16 +0000 Subject: [PATCH 098/113] update date range parser and date picker --- src/components/metrics/DatePickerForm.js | 6 +++--- src/lib/date.ts | 12 +++--------- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/src/components/metrics/DatePickerForm.js b/src/components/metrics/DatePickerForm.js index fa45b64ac..9eb3c52e9 100644 --- a/src/components/metrics/DatePickerForm.js +++ b/src/components/metrics/DatePickerForm.js @@ -1,6 +1,6 @@ import { useState } from 'react'; import { Button, ButtonGroup, Calendar } from 'react-basics'; -import { isAfter, isBefore, isSameDay } from 'date-fns'; +import { isAfter, isBefore, isSameDay, startOfDay, endOfDay } from 'date-fns'; import useLocale from 'components/hooks/useLocale'; import { getDateLocale } from 'lib/lang'; import { FILTER_DAY, FILTER_RANGE } from 'lib/constants'; @@ -31,9 +31,9 @@ export function DatePickerForm({ const handleSave = () => { if (selected === FILTER_DAY) { - onChange(`range:${singleDate.getTime()}:${singleDate.getTime()}`); + onChange(`range:${startOfDay(singleDate).getTime()}:${endOfDay(singleDate).getTime()}`); } else { - onChange(`range:${startDate.getTime()}:${endDate.getTime()}`); + onChange(`range:${startOfDay(startDate).getTime()}:${endOfDay(endDate).getTime()}`); } }; diff --git a/src/lib/date.ts b/src/lib/date.ts index 14f0e13ce..bfbfc0b91 100644 --- a/src/lib/date.ts +++ b/src/lib/date.ts @@ -78,7 +78,9 @@ export function parseDateRange(value, locale = 'en-US') { const endDate = new Date(+endTime); return { - ...getDateRangeValues(startDate, endDate), + startDate, + endDate, + unit: getMinimumUnit(startDate, endDate), value, }; } @@ -255,14 +257,6 @@ export function getMinimumUnit(startDate, endDate) { return 'year'; } -export function getDateRangeValues(startDate, endDate) { - return { - startDate: startOfDay(startDate), - endDate: endOfDay(endDate), - unit: getMinimumUnit(startDate, endDate), - }; -} - export function getDateFromString(str) { const [ymd, hms] = str.split(' '); const [year, month, day] = ymd.split('-'); From eec871dc4aff6a67e8fda4a757a856b179d329c7 Mon Sep 17 00:00:00 2001 From: Maxime-J Date: Sat, 9 Sep 2023 09:51:58 +0000 Subject: [PATCH 099/113] use available dateLocale --- src/components/input/MonthSelect.js | 7 +++---- src/components/metrics/DatePickerForm.js | 7 +++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/components/input/MonthSelect.js b/src/components/input/MonthSelect.js index fb1bf5354..312c6854a 100644 --- a/src/components/input/MonthSelect.js +++ b/src/components/input/MonthSelect.js @@ -12,11 +12,10 @@ import { startOfMonth, endOfMonth } from 'date-fns'; import Icons from 'components/icons'; import { useLocale } from 'components/hooks'; import { formatDate } from 'lib/date'; -import { getDateLocale } from 'lib/lang'; import styles from './MonthSelect.module.css'; export function MonthSelect({ date = new Date(), onChange }) { - const { locale } = useLocale(); + const { locale, dateLocale } = useLocale(); const month = formatDate(date, 'MMMM', locale); const year = date.getFullYear(); const ref = useRef(); @@ -40,7 +39,7 @@ export function MonthSelect({ date = new Date(), onChange }) { {close => ( )} @@ -57,7 +56,7 @@ export function MonthSelect({ date = new Date(), onChange }) { {close => ( )} diff --git a/src/components/metrics/DatePickerForm.js b/src/components/metrics/DatePickerForm.js index 9eb3c52e9..2dcca77a1 100644 --- a/src/components/metrics/DatePickerForm.js +++ b/src/components/metrics/DatePickerForm.js @@ -2,7 +2,6 @@ import { useState } from 'react'; import { Button, ButtonGroup, Calendar } from 'react-basics'; import { isAfter, isBefore, isSameDay, startOfDay, endOfDay } from 'date-fns'; import useLocale from 'components/hooks/useLocale'; -import { getDateLocale } from 'lib/lang'; import { FILTER_DAY, FILTER_RANGE } from 'lib/constants'; import useMessages from 'components/hooks/useMessages'; import styles from './DatePickerForm.module.css'; @@ -21,7 +20,7 @@ export function DatePickerForm({ const [singleDate, setSingleDate] = useState(defaultStartDate); const [startDate, setStartDate] = useState(defaultStartDate); const [endDate, setEndDate] = useState(defaultEndDate); - const { locale } = useLocale(); + const { dateLocale } = useLocale(); const { formatMessage, labels } = useMessages(); const disabled = @@ -60,14 +59,14 @@ export function DatePickerForm({ date={startDate} minDate={minDate} maxDate={endDate} - locale={getDateLocale(locale)} + locale={dateLocale} onChange={setStartDate} /> From d457e6ea16f8861a8e8ff1ccc9848dbc88137bdd Mon Sep 17 00:00:00 2001 From: Maxime-J Date: Sat, 9 Sep 2023 09:53:22 +0000 Subject: [PATCH 100/113] localize single day calendar in date picker --- src/components/metrics/DatePickerForm.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/metrics/DatePickerForm.js b/src/components/metrics/DatePickerForm.js index 2dcca77a1..5e1906c3c 100644 --- a/src/components/metrics/DatePickerForm.js +++ b/src/components/metrics/DatePickerForm.js @@ -50,6 +50,7 @@ export function DatePickerForm({ date={singleDate} minDate={minDate} maxDate={maxDate} + locale={dateLocale} onChange={setSingleDate} /> )} From 7b97209d56761d128c6c1d044c25c57ed3564bba Mon Sep 17 00:00:00 2001 From: Brian Cao Date: Wed, 13 Sep 2023 13:27:07 -0700 Subject: [PATCH 101/113] Fix CH script. --- db/clickhouse/schema.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/clickhouse/schema.sql b/db/clickhouse/schema.sql index 94b560c3e..44428e94c 100644 --- a/db/clickhouse/schema.sql +++ b/db/clickhouse/schema.sql @@ -66,7 +66,7 @@ CREATE TABLE umami.website_event_queue ( ) ENGINE = Kafka SETTINGS kafka_broker_list = 'domain:9092,domain:9093,domain:9094', -- input broker list - kafka_topic_list = 'events', + kafka_topic_list = 'event', kafka_group_name = 'event_consumer_group', kafka_format = 'JSONEachRow', kafka_max_block_size = 1048576, From e73865b880a4f4d502f2dcd44c0cf935ce6937f3 Mon Sep 17 00:00:00 2001 From: AkashRajpurohit Date: Sun, 17 Sep 2023 19:34:35 +0530 Subject: [PATCH 102/113] fix: :bug: gulp error so that error in sending data does not affect the action triggering it --- src/tracker/index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/tracker/index.js b/src/tracker/index.js index 1686df429..491eef7da 100644 --- a/src/tracker/index.js +++ b/src/tracker/index.js @@ -187,7 +187,8 @@ headers, }) .then(res => res.text()) - .then(text => (cache = text)); + .then(text => (cache = text)) + .catch(() => {}); // no-op, gulp error }; const track = (obj, data) => { From 84e13a2a105ee74c02420c54586624cf3470540c Mon Sep 17 00:00:00 2001 From: Brian Cao Date: Mon, 18 Sep 2023 09:51:43 -0700 Subject: [PATCH 103/113] Add external analytics url. --- .gitignore | 5 +---- src/components/pages/settings/websites/TrackingCode.js | 6 ++++-- src/components/pages/settings/websites/WebsiteSettings.js | 4 ++-- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index 99087ab50..32e3ef0b8 100644 --- a/.gitignore +++ b/.gitignore @@ -33,10 +33,7 @@ yarn-debug.log* yarn-error.log* # local env files -.env -.env.development.local -.env.test.local -.env.production.local +*.env *.dev.yml diff --git a/src/components/pages/settings/websites/TrackingCode.js b/src/components/pages/settings/websites/TrackingCode.js index d22f0d59e..a666476d9 100644 --- a/src/components/pages/settings/websites/TrackingCode.js +++ b/src/components/pages/settings/websites/TrackingCode.js @@ -3,7 +3,7 @@ import useMessages from 'components/hooks/useMessages'; import useConfig from 'components/hooks/useConfig'; import { useRouter } from 'next/router'; -export function TrackingCode({ websiteId }) { +export function TrackingCode({ websiteId, analyticsUrl }) { const { formatMessage, messages } = useMessages(); const { basePath } = useRouter(); const config = useConfig(); @@ -13,7 +13,9 @@ export function TrackingCode({ websiteId }) { const url = trackerScriptName?.startsWith('http') ? trackerScriptName - : `${process.env.analyticsUrl || location.origin}${basePath}/${trackerScriptName}`; + : `${ + analyticsUrl || process.env.analyticsUrl || location.origin + }${basePath}/${trackerScriptName}`; const code = ``; diff --git a/src/components/pages/settings/websites/WebsiteSettings.js b/src/components/pages/settings/websites/WebsiteSettings.js index f73e0a878..3cd4185c9 100644 --- a/src/components/pages/settings/websites/WebsiteSettings.js +++ b/src/components/pages/settings/websites/WebsiteSettings.js @@ -11,7 +11,7 @@ import ShareUrl from 'components/pages/settings/websites/ShareUrl'; import useApi from 'components/hooks/useApi'; import useMessages from 'components/hooks/useMessages'; -export function WebsiteSettings({ websiteId, openExternal = false }) { +export function WebsiteSettings({ websiteId, openExternal = false, analyticsUrl }) { const router = useRouter(); const { formatMessage, labels, messages } = useMessages(); const { get, useQuery } = useApi(); @@ -68,7 +68,7 @@ export function WebsiteSettings({ websiteId, openExternal = false }) { {tab === 'details' && ( )} - {tab === 'tracking' && } + {tab === 'tracking' && } {tab === 'share' && } {tab === 'data' && } From 3f6fb4654b4aaf72747bae9452c33de1dde78601 Mon Sep 17 00:00:00 2001 From: Francis Cao Date: Wed, 20 Sep 2023 12:43:59 -0700 Subject: [PATCH 104/113] Fix resetAt date parsing error for CH --- src/lib/clickhouse.ts | 2 +- src/queries/admin/website.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/clickhouse.ts b/src/lib/clickhouse.ts index bc10a6d4e..186a085d1 100644 --- a/src/lib/clickhouse.ts +++ b/src/lib/clickhouse.ts @@ -112,7 +112,7 @@ async function parseFilters(websiteId: string, filters: QueryFilters = {}, optio params: { ...normalizeFilters(filters), websiteId, - startDate: maxDate(filters.startDate, website.resetAt), + startDate: maxDate(filters.startDate, new Date(website.resetAt)), websiteDomain: website.domain, }, }; diff --git a/src/queries/admin/website.ts b/src/queries/admin/website.ts index cf4570cfc..6417ade6f 100644 --- a/src/queries/admin/website.ts +++ b/src/queries/admin/website.ts @@ -297,7 +297,7 @@ export async function resetWebsite( }), ]).then(async data => { if (cache.enabled) { - await cache.storeWebsite(data[2]); + await cache.storeWebsite(data[3]); } return data; From e9ae4903d452dfe120f956c9b869da97501dbd47 Mon Sep 17 00:00:00 2001 From: Francis Cao Date: Wed, 20 Sep 2023 14:36:18 -0700 Subject: [PATCH 105/113] add regions to useFormat --- src/components/hooks/useFormat.js | 9 ++++++++- src/pages/api/websites/[id]/values.ts | 7 ++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/components/hooks/useFormat.js b/src/components/hooks/useFormat.js index 3fd10ec8e..0e609c488 100644 --- a/src/components/hooks/useFormat.js +++ b/src/components/hooks/useFormat.js @@ -2,6 +2,7 @@ import useMessages from './useMessages'; import { BROWSERS } from 'lib/constants'; import useLocale from './useLocale'; import useCountryNames from './useCountryNames'; +import regions from 'public/iso-3166-2.json'; export function useFormat() { const { formatMessage, labels } = useMessages(); @@ -16,6 +17,10 @@ export function useFormat() { return countryNames[value] || value; }; + const formatRegion = value => { + return regions[value] ? regions[value] : value; + }; + const formatDevice = value => { return formatMessage(labels[value] || labels.unknown); }; @@ -26,6 +31,8 @@ export function useFormat() { return formatBrowser(value); case 'country': return formatCountry(value); + case 'region': + return formatRegion(value); case 'device': return formatDevice(value); default: @@ -33,7 +40,7 @@ export function useFormat() { } }; - return { formatBrowser, formatCountry, formatDevice, formatValue }; + return { formatBrowser, formatCountry, formatRegion, formatDevice, formatValue }; } export default useFormat; diff --git a/src/pages/api/websites/[id]/values.ts b/src/pages/api/websites/[id]/values.ts index d90a16822..1f479aebe 100644 --- a/src/pages/api/websites/[id]/values.ts +++ b/src/pages/api/websites/[id]/values.ts @@ -6,7 +6,7 @@ import { badRequest, methodNotAllowed, ok, unauthorized } from 'next-basics'; import { EVENT_COLUMNS, FILTER_COLUMNS, SESSION_COLUMNS } from 'lib/constants'; import { getValues } from 'queries'; -export interface WebsiteResetRequestQuery { +export interface ValuesRequestQuery { id: string; } @@ -17,10 +17,7 @@ const schema = { }), }; -export default async ( - req: NextApiRequestQueryBody, - res: NextApiResponse, -) => { +export default async (req: NextApiRequestQueryBody, res: NextApiResponse) => { await useCors(req, res); await useAuth(req, res); From f7b2f50e4f234e0752c48d8147fab808ad252df0 Mon Sep 17 00:00:00 2001 From: Brian Cao Date: Wed, 20 Sep 2023 15:26:49 -0700 Subject: [PATCH 106/113] Fix TS error. --- src/lib/middleware.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/middleware.ts b/src/lib/middleware.ts index edf3e9292..8259677dc 100644 --- a/src/lib/middleware.ts +++ b/src/lib/middleware.ts @@ -21,7 +21,7 @@ const log = debug('umami:middleware'); export const useCors = createMiddleware( cors({ // Cache CORS preflight request 24 hours by default - maxAge: process.env.CORS_MAX_AGE || 86400, + maxAge: Number(process.env.CORS_MAX_AGE) || 86400, }), ); From b3f9dfa01a0525eafdd298742e0c9dc86c0c433d Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Thu, 21 Sep 2023 01:01:58 -0700 Subject: [PATCH 107/113] Update packages. --- package.json | 8 +- src/lib/prisma.ts | 2 +- yarn.lock | 1300 +++++++++++++++++++++++++++------------------ 3 files changed, 795 insertions(+), 515 deletions(-) diff --git a/package.json b/package.json index 8bb372013..8350a060f 100644 --- a/package.json +++ b/package.json @@ -62,7 +62,7 @@ ], "dependencies": { "@fontsource/inter": "^4.5.15", - "@prisma/client": "5.2.0", + "@prisma/client": "5.3.1", "@tanstack/react-query": "^4.33.0", "@umami/prisma-client": "^0.2.0", "@umami/redis-client": "^0.5.0", @@ -91,12 +91,12 @@ "kafkajs": "^2.1.0", "maxmind": "^4.3.6", "moment-timezone": "^0.5.35", - "next": "13.4.19", + "next": "13.5.2", "next-basics": "^0.36.0", "node-fetch": "^3.2.8", "npm-run-all": "^4.1.5", "react": "^18.2.0", - "react-basics": "^0.98.0", + "react-basics": "^0.100.0", "react-beautiful-dnd": "^13.1.0", "react-dom": "^18.2.0", "react-error-boundary": "^4.0.4", @@ -146,7 +146,7 @@ "postcss-preset-env": "7.8.3", "postcss-rtlcss": "^4.0.1", "prettier": "^2.6.2", - "prisma": "5.2.0", + "prisma": "5.3.1", "prompts": "2.4.2", "rollup": "^3.28.0", "rollup-plugin-copy": "^3.4.0", diff --git a/src/lib/prisma.ts b/src/lib/prisma.ts index a9832c28c..59638dbd6 100644 --- a/src/lib/prisma.ts +++ b/src/lib/prisma.ts @@ -161,7 +161,7 @@ async function rawQuery(sql: string, data: object): Promise { return Promise.reject(new Error('Unknown database.')); } - const query = sql?.replaceAll(/\{\{\s*(\w+)(::\w+)?\s*\}\}/g, (...args) => { + const query = sql?.replaceAll(/\{\{\s*(\w+)(::\w+)?\s*}}/g, (...args) => { const [, name, type] = args; params.push(data[name]); diff --git a/yarn.lock b/yarn.lock index 5d99a1355..8687c4326 100644 --- a/yarn.lock +++ b/yarn.lock @@ -15,7 +15,15 @@ "@jridgewell/gen-mapping" "^0.3.0" "@jridgewell/trace-mapping" "^0.3.9" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.22.5": +"@babel/code-frame@^7.0.0": + version "7.22.13" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.13.tgz#e3c1c099402598483b7a8c46a721d1038803755e" + integrity sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w== + dependencies: + "@babel/highlight" "^7.22.13" + chalk "^2.4.2" + +"@babel/code-frame@^7.10.4", "@babel/code-frame@^7.22.5": version "7.22.5" resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz" integrity sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ== @@ -272,11 +280,16 @@ resolved "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz" integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw== -"@babel/helper-validator-identifier@^7.19.1", "@babel/helper-validator-identifier@^7.22.5": +"@babel/helper-validator-identifier@^7.19.1": version "7.22.5" resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz" integrity sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ== +"@babel/helper-validator-identifier@^7.22.20", "@babel/helper-validator-identifier@^7.22.5": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" + integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== + "@babel/helper-validator-option@^7.18.6", "@babel/helper-validator-option@^7.21.0", "@babel/helper-validator-option@^7.22.5": version "7.22.5" resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz" @@ -301,13 +314,13 @@ "@babel/traverse" "^7.22.5" "@babel/types" "^7.22.5" -"@babel/highlight@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.5.tgz#aa6c05c5407a67ebce408162b7ede789b4d22031" - integrity sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw== +"@babel/highlight@^7.22.13", "@babel/highlight@^7.22.5": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.20.tgz#4ca92b71d80554b01427815e06f2df965b9c1f54" + integrity sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg== dependencies: - "@babel/helper-validator-identifier" "^7.22.5" - chalk "^2.0.0" + "@babel/helper-validator-identifier" "^7.22.20" + chalk "^2.4.2" js-tokens "^4.0.0" "@babel/parser@^7.1.0", "@babel/parser@^7.16.4", "@babel/parser@^7.22.5": @@ -1023,11 +1036,11 @@ regenerator-runtime "^0.13.11" "@babel/runtime@^7.12.5": - version "7.22.5" - resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.5.tgz" - integrity sha512-ecjvYlnAaZ/KVneE/OdKYBYfgXV3Ptu6zQWmgEF7vwKhQnvVS6bjMD2XYgj+SNvQ1GfK/pjgokfPkC/2CO8CuA== + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.15.tgz#38f46494ccf6cf020bd4eed7124b425e83e523b8" + integrity sha512-T0O+aa+4w0u06iNmapipJXMV4HoUir03hpx3/YqXXhu9xim3w+dVphjFWl1OH8NbZHw5Lbm9k45drDkgq2VNNA== dependencies: - regenerator-runtime "^0.13.11" + regenerator-runtime "^0.14.0" "@babel/runtime@^7.21.0": version "7.21.5" @@ -1077,20 +1090,20 @@ dependencies: "@jridgewell/trace-mapping" "0.3.9" -"@csstools/css-parser-algorithms@^2.3.0": +"@csstools/css-parser-algorithms@^2.3.1": version "2.3.1" resolved "https://registry.yarnpkg.com/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.3.1.tgz#ec4fc764ba45d2bb7ee2774667e056aa95003f3a" integrity sha512-xrvsmVUtefWMWQsGgFffqWSK03pZ1vfDki4IVIIUxxDKnGBzqNgv0A7SB1oXtVNEkcVO8xi1ZrTL29HhSu5kGA== -"@csstools/css-tokenizer@^2.1.1": +"@csstools/css-tokenizer@^2.2.0": version "2.2.0" resolved "https://registry.yarnpkg.com/@csstools/css-tokenizer/-/css-tokenizer-2.2.0.tgz#9d70e6dcbe94e44c7400a2929928db35c4de32b5" integrity sha512-wErmsWCbsmig8sQKkM6pFhr/oPha1bHfvxsUY5CYSQxwyhA9Ulrs8EqCgClhg4Tgg2XapVstGqSVcz0xOYizZA== -"@csstools/media-query-list-parser@^2.1.2": - version "2.1.3" - resolved "https://registry.yarnpkg.com/@csstools/media-query-list-parser/-/media-query-list-parser-2.1.3.tgz#4471ebd436a22019378fe9c8ac8c0f30c4fbb796" - integrity sha512-ATul1u+pic4aVpstgueqxEv4MsObEbszAxfTXpx9LHaeD3LAh+wFqdCteyegWmjk0k5rkSCAvIOaJe9U3DD09w== +"@csstools/media-query-list-parser@^2.1.4": + version "2.1.4" + resolved "https://registry.yarnpkg.com/@csstools/media-query-list-parser/-/media-query-list-parser-2.1.4.tgz#0017f99945f6c16dd81a7aacf6821770933c3a5c" + integrity sha512-V/OUXYX91tAC1CDsiY+HotIcJR+vPtzrX8pCplCpT++i8ThZZsq5F5dzZh/bDM3WUOjrvC1ljed1oSJxMfjqhw== "@csstools/postcss-cascade-layers@^1.1.1": version "1.1.1" @@ -1325,15 +1338,20 @@ dependencies: eslint-visitor-keys "^3.3.0" -"@eslint-community/regexpp@^4.4.0", "@eslint-community/regexpp@^4.6.1": +"@eslint-community/regexpp@^4.4.0": version "4.6.2" resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.6.2.tgz#1816b5f6948029c5eaacb0703b850ee0cb37d8f8" integrity sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw== -"@eslint/eslintrc@^2.1.1": - version "2.1.1" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.1.tgz#18d635e24ad35f7276e8a49d135c7d3ca6a46f93" - integrity sha512-9t7ZA7NGGK8ckelF0PQCfcxIUzs1Md5rrO6U/c+FIQNanea5UZC0wqKXH4vHBccmu4ZJgZ2idtPeW7+Q2npOEA== +"@eslint-community/regexpp@^4.6.1": + version "4.8.1" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.8.1.tgz#8c4bb756cc2aa7eaf13cfa5e69c83afb3260c20c" + integrity sha512-PWiOzLIUAjN/w5K17PoF4n6sKBw0gqLHPhywmYHP4t1VFQQVYeb1yWsJwnMVEMl3tUHME7X/SJPZLmtG7XBDxQ== + +"@eslint/eslintrc@^2.1.2": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.2.tgz#c6936b4b328c64496692f76944e755738be62396" + integrity sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g== dependencies: ajv "^6.12.4" debug "^4.3.2" @@ -1345,10 +1363,10 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@eslint/js@^8.46.0": - version "8.46.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.46.0.tgz#3f7802972e8b6fe3f88ed1aabc74ec596c456db6" - integrity sha512-a8TLtmPi8xzPkCbp/OGFUo5yhRkHM2Ko9kOWP4znJr0WAhWyThaw3PnwX4vOTWOAMsV2uRt32PPDcEz63esSaA== +"@eslint/js@8.49.0": + version "8.49.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.49.0.tgz#86f79756004a97fa4df866835093f1df3d03c333" + integrity sha512-1S8uAY/MTJqVx0SC4epBq+N2yhuwtNwLbJYNZyhL2pO1ZVKn5HFXav5T41Ryzy9K9V7ZId2JB2oy/W4aCd9/2w== "@fastify/accept-negotiator@^1.1.0": version "1.1.0" @@ -1494,10 +1512,10 @@ tslib "^2.0.1" typescript "^4.0" -"@humanwhocodes/config-array@^0.11.10": - version "0.11.10" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.10.tgz#5a3ffe32cc9306365fb3fd572596cd602d5e12d2" - integrity sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ== +"@humanwhocodes/config-array@^0.11.11": + version "0.11.11" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.11.tgz#88a04c570dbbc7dd943e4712429c3df09bc32844" + integrity sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA== dependencies: "@humanwhocodes/object-schema" "^1.2.1" debug "^4.1.1" @@ -1709,30 +1727,43 @@ dependencies: is-promise "^4.0.0" -"@netlify/ipx@^1.4.1": - version "1.4.1" - resolved "https://registry.yarnpkg.com/@netlify/ipx/-/ipx-1.4.1.tgz#5b0e7508e343b960e7e97d2094089dd1585c88f6" - integrity sha512-wOuemSttKv8h4XMC9+RNNv21tn0uIC5avvnwmuFOyPOGzI1nsip01UkxS5lHRX+KX7TdIQxwBzSqde15h/jdRA== +"@netlify/functions@^2.0.1": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@netlify/functions/-/functions-2.0.2.tgz#b5162058434fd00e280e4b28283f6bb8a2840c5c" + integrity sha512-goWRtaIPUK/q47qLYtfGGj7HgJIRaT0snw7zZ0yeoNTfQfCRwQwvRrMAsXkCsCtq2N2Oo81L26SpkMxEQMk9hg== dependencies: - "@netlify/functions" "^1.6.0" + "@netlify/serverless-functions-api" "1.7.3" + is-promise "^4.0.0" + +"@netlify/ipx@^1.4.3": + version "1.4.4" + resolved "https://registry.yarnpkg.com/@netlify/ipx/-/ipx-1.4.4.tgz#b939e18639749f444eac1b88cb2a85790e7d13a1" + integrity sha512-UM2pFatBDg9ehrUwA/PwpAo/PpF447uXFgKR/2QtqlPriwJlNXJ7sj/YPEblC/8UzNJjhSIv2gA6T9bcVqxe7Q== + dependencies: + "@netlify/functions" "^2.0.1" etag "^1.8.1" fs-extra "^11.0.0" ipx "^1.0.0" micromatch "^4.0.5" - mkdirp "^1.0.4" + mkdirp "^3.0.0" murmurhash "^2.0.0" node-fetch "^2.0.0" ufo "^1.0.0" unstorage "^1.0.0" +"@netlify/node-cookies@^0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@netlify/node-cookies/-/node-cookies-0.1.0.tgz#dda912ba618527695cf519fafa221c5e6777c612" + integrity sha512-OAs1xG+FfLX0LoRASpqzVntVV/RpYkgpI0VrUnw2u0Q1qiZUzcPffxRK8HF3gc4GjuhG5ahOEMJ9bswBiZPq0g== + "@netlify/plugin-nextjs@^4.27.3": - version "4.39.1" - resolved "https://registry.yarnpkg.com/@netlify/plugin-nextjs/-/plugin-nextjs-4.39.1.tgz#e9d5abe281389e30d59cf5839496bb2a14a196db" - integrity sha512-gdpTDRYJg8g55MQBy1JMcVJ3UgHC71M/u7BccI9oqvizVtV7ESgyCdJgGFPfZJJGCgWe2ANfQCk1wgA0yosnow== + version "4.40.1" + resolved "https://registry.yarnpkg.com/@netlify/plugin-nextjs/-/plugin-nextjs-4.40.1.tgz#ccb10b08fe9081df29437f709ad4448cae2bd329" + integrity sha512-FVXQEzBCymJHu2JYnJs03hUXjJAIAHcLMsrbcrnSjqmib4yF65YZ9yJYmrajV2D6LRqN/TxWhzTEgGr9eYpRHQ== dependencies: "@netlify/esbuild" "0.14.39" "@netlify/functions" "^1.6.0" - "@netlify/ipx" "^1.4.1" + "@netlify/ipx" "^1.4.3" "@vercel/node-bridge" "^2.1.0" chalk "^4.1.2" chokidar "^3.5.3" @@ -1754,10 +1785,18 @@ slash "^3.0.0" tiny-glob "^0.2.9" -"@next/env@13.4.19": - version "13.4.19" - resolved "https://registry.yarnpkg.com/@next/env/-/env-13.4.19.tgz#46905b4e6f62da825b040343cbc233144e9578d3" - integrity sha512-FsAT5x0jF2kkhNkKkukhsyYOrRqtSxrEhfliniIq0bwWbuXLgyt3Gv0Ml+b91XwjwArmuP7NxCiGd++GGKdNMQ== +"@netlify/serverless-functions-api@1.7.3": + version "1.7.3" + resolved "https://registry.yarnpkg.com/@netlify/serverless-functions-api/-/serverless-functions-api-1.7.3.tgz#74efc650fcbca7c25211bb49df826795cf53f072" + integrity sha512-n6/7cJlSWvvbBlUOEAbkGyEld80S6KbG/ldQI9OhLfe1lTatgKmrTNIgqVNpaWpUdTgP2OHWFjmFBzkxxBWs5w== + dependencies: + "@netlify/node-cookies" "^0.1.0" + urlpattern-polyfill "8.0.2" + +"@next/env@13.5.2": + version "13.5.2" + resolved "https://registry.yarnpkg.com/@next/env/-/env-13.5.2.tgz#1c09e6cf1df8b1edf3cf0ca9c0e0119a49802a5d" + integrity sha512-dUseBIQVax+XtdJPzhwww4GetTjlkRSsXeQnisIJWBaHsnxYcN2RGzsPHi58D6qnkATjnhuAtQTJmR1hKYQQPg== "@next/eslint-plugin-next@12.3.4": version "12.3.4" @@ -1766,50 +1805,50 @@ dependencies: glob "7.1.7" -"@next/swc-darwin-arm64@13.4.19": - version "13.4.19" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.19.tgz#77ad462b5ced4efdc26cb5a0053968d2c7dac1b6" - integrity sha512-vv1qrjXeGbuF2mOkhkdxMDtv9np7W4mcBtaDnHU+yJG+bBwa6rYsYSCI/9Xm5+TuF5SbZbrWO6G1NfTh1TMjvQ== +"@next/swc-darwin-arm64@13.5.2": + version "13.5.2" + resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.5.2.tgz#f099a36fdd06b1949eb4e190aee95a52b97d3885" + integrity sha512-7eAyunAWq6yFwdSQliWMmGhObPpHTesiKxMw4DWVxhm5yLotBj8FCR4PXGkpRP2tf8QhaWuVba+/fyAYggqfQg== -"@next/swc-darwin-x64@13.4.19": - version "13.4.19" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-13.4.19.tgz#aebe38713a4ce536ee5f2a291673e14b715e633a" - integrity sha512-jyzO6wwYhx6F+7gD8ddZfuqO4TtpJdw3wyOduR4fxTUCm3aLw7YmHGYNjS0xRSYGAkLpBkH1E0RcelyId6lNsw== +"@next/swc-darwin-x64@13.5.2": + version "13.5.2" + resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-13.5.2.tgz#b8950fbe150db6f82961619e31fc6e9232fce8f4" + integrity sha512-WxXYWE7zF1ch8rrNh5xbIWzhMVas6Vbw+9BCSyZvu7gZC5EEiyZNJsafsC89qlaSA7BnmsDXVWQmc+s1feSYbQ== -"@next/swc-linux-arm64-gnu@13.4.19": - version "13.4.19" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.4.19.tgz#ec54db65b587939c7b94f9a84800f003a380f5a6" - integrity sha512-vdlnIlaAEh6H+G6HrKZB9c2zJKnpPVKnA6LBwjwT2BTjxI7e0Hx30+FoWCgi50e+YO49p6oPOtesP9mXDRiiUg== +"@next/swc-linux-arm64-gnu@13.5.2": + version "13.5.2" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.5.2.tgz#8134d31fa9ad6848561b6969d27a8c07ab090974" + integrity sha512-URSwhRYrbj/4MSBjLlefPTK3/tvg95TTm6mRaiZWBB6Za3hpHKi8vSdnCMw5D2aP6k0sQQIEG6Pzcfwm+C5vrg== -"@next/swc-linux-arm64-musl@13.4.19": - version "13.4.19" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.4.19.tgz#1f5e2c1ea6941e7d530d9f185d5d64be04279d86" - integrity sha512-aU0HkH2XPgxqrbNRBFb3si9Ahu/CpaR5RPmN2s9GiM9qJCiBBlZtRTiEca+DC+xRPyCThTtWYgxjWHgU7ZkyvA== +"@next/swc-linux-arm64-musl@13.5.2": + version "13.5.2" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.5.2.tgz#56233fe5140ed437c638194f0a01a3f89821ca89" + integrity sha512-HefiwAdIygFyNmyVsQeiJp+j8vPKpIRYDlmTlF9/tLdcd3qEL/UEBswa1M7cvO8nHcr27ZTKXz5m7dkd56/Esg== -"@next/swc-linux-x64-gnu@13.4.19": - version "13.4.19" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.4.19.tgz#96b0882492a2f7ffcce747846d3680730f69f4d1" - integrity sha512-htwOEagMa/CXNykFFeAHHvMJeqZfNQEoQvHfsA4wgg5QqGNqD5soeCer4oGlCol6NGUxknrQO6VEustcv+Md+g== +"@next/swc-linux-x64-gnu@13.5.2": + version "13.5.2" + resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.5.2.tgz#1947a9dc603e6d5d5a8e99db7d42e2240c78e713" + integrity sha512-htGVVroW0tdHgMYwKWkxWvVoG2RlAdDXRO1RQxYDvOBQsaV0nZsgKkw0EJJJ3urTYnwKskn/MXm305cOgRxD2w== -"@next/swc-linux-x64-musl@13.4.19": - version "13.4.19" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.4.19.tgz#f276b618afa321d2f7b17c81fc83f429fb0fd9d8" - integrity sha512-4Gj4vvtbK1JH8ApWTT214b3GwUh9EKKQjY41hH/t+u55Knxi/0wesMzwQRhppK6Ddalhu0TEttbiJ+wRcoEj5Q== +"@next/swc-linux-x64-musl@13.5.2": + version "13.5.2" + resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.5.2.tgz#83eea3985eed84fbbbb1004a555d2f093d4ed245" + integrity sha512-UBD333GxbHVGi7VDJPPDD1bKnx30gn2clifNJbla7vo5nmBV+x5adyARg05RiT9amIpda6yzAEEUu+s774ldkw== -"@next/swc-win32-arm64-msvc@13.4.19": - version "13.4.19" - resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.4.19.tgz#1599ae0d401da5ffca0947823dac577697cce577" - integrity sha512-bUfDevQK4NsIAHXs3/JNgnvEY+LRyneDN788W2NYiRIIzmILjba7LaQTfihuFawZDhRtkYCv3JDC3B4TwnmRJw== +"@next/swc-win32-arm64-msvc@13.5.2": + version "13.5.2" + resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.5.2.tgz#c3734235e85458b76ec170dd0d6c13c2fdfac5ed" + integrity sha512-Em9ApaSFIQnWXRT3K6iFnr9uBXymixLc65Xw4eNt7glgH0eiXpg+QhjmgI2BFyc7k4ZIjglfukt9saNpEyolWA== -"@next/swc-win32-ia32-msvc@13.4.19": - version "13.4.19" - resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.4.19.tgz#55cdd7da90818f03e4da16d976f0cb22045d16fd" - integrity sha512-Y5kikILFAr81LYIFaw6j/NrOtmiM4Sf3GtOc0pn50ez2GCkr+oejYuKGcwAwq3jiTKuzF6OF4iT2INPoxRycEA== +"@next/swc-win32-ia32-msvc@13.5.2": + version "13.5.2" + resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.5.2.tgz#cf16184af9be8b8f7750833a441c116b7a76b273" + integrity sha512-TBACBvvNYU+87X0yklSuAseqdpua8m/P79P0SG1fWUvWDDA14jASIg7kr86AuY5qix47nZLEJ5WWS0L20jAUNw== -"@next/swc-win32-x64-msvc@13.4.19": - version "13.4.19" - resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.4.19.tgz#648f79c4e09279212ac90d871646ae12d80cdfce" - integrity sha512-YzA78jBDXMYiINdPdJJwGgPNT3YqBNNGhsthsDoWHL9p24tEJn9ViQf/ZqTbwSpX/RrkPupLfuuTH2sf73JBAw== +"@next/swc-win32-x64-msvc@13.5.2": + version "13.5.2" + resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.5.2.tgz#cf8db00763d9219567655b90853b7d484f3fcad6" + integrity sha512-LfTHt+hTL8w7F9hnB3H4nRasCzLD/fP+h4/GUVBTxrkMJOnh/7OZ0XbYDKO/uuWwryJS9kZjhxcruBiYwc5UDw== "@nodelib/fs.scandir@2.1.5": version "2.1.5" @@ -1832,22 +1871,114 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@prisma/client@5.2.0": - version "5.2.0" - resolved "https://registry.yarnpkg.com/@prisma/client/-/client-5.2.0.tgz#cbfdd440614b38736563a7999f39922fcde0ed50" - integrity sha512-AiTjJwR4J5Rh6Z/9ZKrBBLel3/5DzUNntMohOy7yObVnVoTNVFi2kvpLZlFuKO50d7yDspOtW6XBpiAd0BVXbQ== +"@parcel/watcher-android-arm64@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.3.0.tgz#d82e74bb564ebd4d8a88791d273a3d2bd61e27ab" + integrity sha512-f4o9eA3dgk0XRT3XhB0UWpWpLnKgrh1IwNJKJ7UJek7eTYccQ8LR7XUWFKqw6aEq5KUNlCcGvSzKqSX/vtWVVA== + +"@parcel/watcher-darwin-arm64@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.3.0.tgz#c9cd03f8f233d512fcfc873d5b4e23f1569a82ad" + integrity sha512-mKY+oijI4ahBMc/GygVGvEdOq0L4DxhYgwQqYAz/7yPzuGi79oXrZG52WdpGA1wLBPrYb0T8uBaGFo7I6rvSKw== + +"@parcel/watcher-darwin-x64@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.3.0.tgz#83c902994a2a49b9e1ab5050dba24876fdc2c219" + integrity sha512-20oBj8LcEOnLE3mgpy6zuOq8AplPu9NcSSSfyVKgfOhNAc4eF4ob3ldj0xWjGGbOF7Dcy1Tvm6ytvgdjlfUeow== + +"@parcel/watcher-freebsd-x64@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.3.0.tgz#7a0f4593a887e2752b706aff2dae509aef430cf6" + integrity sha512-7LftKlaHunueAEiojhCn+Ef2CTXWsLgTl4hq0pkhkTBFI3ssj2bJXmH2L67mKpiAD5dz66JYk4zS66qzdnIOgw== + +"@parcel/watcher-linux-arm-glibc@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.3.0.tgz#3fc90c3ebe67de3648ed2f138068722f9b1d47da" + integrity sha512-1apPw5cD2xBv1XIHPUlq0cO6iAaEUQ3BcY0ysSyD9Kuyw4MoWm1DV+W9mneWI+1g6OeP6dhikiFE6BlU+AToTQ== + +"@parcel/watcher-linux-arm64-glibc@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.3.0.tgz#f7bbbf2497d85fd11e4c9e9c26ace8f10ea9bcbc" + integrity sha512-mQ0gBSQEiq1k/MMkgcSB0Ic47UORZBmWoAWlMrTW6nbAGoLZP+h7AtUM7H3oDu34TBFFvjy4JCGP43JlylkTQA== + +"@parcel/watcher-linux-arm64-musl@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.3.0.tgz#de131a9fcbe1fa0854e9cbf4c55bed3b35bcff43" + integrity sha512-LXZAExpepJew0Gp8ZkJ+xDZaTQjLHv48h0p0Vw2VMFQ8A+RKrAvpFuPVCVwKJCr5SE+zvaG+Etg56qXvTDIedw== + +"@parcel/watcher-linux-x64-glibc@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.3.0.tgz#193dd1c798003cdb5a1e59470ff26300f418a943" + integrity sha512-P7Wo91lKSeSgMTtG7CnBS6WrA5otr1K7shhSjKHNePVmfBHDoAOHYRXgUmhiNfbcGk0uMCHVcdbfxtuiZCHVow== + +"@parcel/watcher-linux-x64-musl@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.3.0.tgz#6dbdb86d96e955ab0fe4a4b60734ec0025a689dd" + integrity sha512-+kiRE1JIq8QdxzwoYY+wzBs9YbJ34guBweTK8nlzLKimn5EQ2b2FSC+tAOpq302BuIMjyuUGvBiUhEcLIGMQ5g== + +"@parcel/watcher-wasm@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-wasm/-/watcher-wasm-2.3.0.tgz#73b66c6fbd2a3326ae86a1ec77eab7139d0dd725" + integrity sha512-ejBAX8H0ZGsD8lSICDNyMbSEtPMWgDL0WFCt/0z7hyf5v8Imz4rAM8xY379mBsECkq/Wdqa5WEDLqtjZ+6NxfA== dependencies: - "@prisma/engines-version" "5.2.0-25.2804dc98259d2ea960602aca6b8e7fdc03c1758f" + is-glob "^4.0.3" + micromatch "^4.0.5" + napi-wasm "^1.1.0" -"@prisma/engines-version@5.2.0-25.2804dc98259d2ea960602aca6b8e7fdc03c1758f": - version "5.2.0-25.2804dc98259d2ea960602aca6b8e7fdc03c1758f" - resolved "https://registry.yarnpkg.com/@prisma/engines-version/-/engines-version-5.2.0-25.2804dc98259d2ea960602aca6b8e7fdc03c1758f.tgz#11366e7ff031c908debf4983248d40046016de37" - integrity sha512-jsnKT5JIDIE01lAeCj2ghY9IwxkedhKNvxQeoyLs6dr4ZXynetD0vTy7u6wMJt8vVPv8I5DPy/I4CFaoXAgbtg== +"@parcel/watcher-win32-arm64@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.3.0.tgz#59da26a431da946e6c74fa6b0f30b120ea6650b6" + integrity sha512-35gXCnaz1AqIXpG42evcoP2+sNL62gZTMZne3IackM+6QlfMcJLy3DrjuL6Iks7Czpd3j4xRBzez3ADCj1l7Aw== -"@prisma/engines@5.2.0": - version "5.2.0" - resolved "https://registry.yarnpkg.com/@prisma/engines/-/engines-5.2.0.tgz#e5dff48eb324c8137393933292d44ea5c3bc2ce7" - integrity sha512-dT7FOLUCdZmq+AunLqB1Iz+ZH/IIS1Fz2THmKZQ6aFONrQD/BQ5ecJ7g2wGS2OgyUFf4OaLam6/bxmgdOBDqig== +"@parcel/watcher-win32-ia32@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.3.0.tgz#3ee6a18b08929cd3b788e8cc9547fd9a540c013a" + integrity sha512-FJS/IBQHhRpZ6PiCjFt1UAcPr0YmCLHRbTc00IBTrelEjlmmgIVLeOx4MSXzx2HFEy5Jo5YdhGpxCuqCyDJ5ow== + +"@parcel/watcher-win32-x64@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.3.0.tgz#14e7246289861acc589fd608de39fe5d8b4bb0a7" + integrity sha512-dLx+0XRdMnVI62kU3wbXvbIRhLck4aE28bIGKbRGS7BJNt54IIj9+c/Dkqb+7DJEbHUZAX1bwaoM8PqVlHJmCA== + +"@parcel/watcher@^2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher/-/watcher-2.3.0.tgz#803517abbc3981a1a1221791d9f59dc0590d50f9" + integrity sha512-pW7QaFiL11O0BphO+bq3MgqeX/INAk9jgBldVDYjlQPO4VddoZnF22TcF9onMhnLVHuNqBJeRf+Fj7eezi/+rQ== + dependencies: + detect-libc "^1.0.3" + is-glob "^4.0.3" + micromatch "^4.0.5" + node-addon-api "^7.0.0" + optionalDependencies: + "@parcel/watcher-android-arm64" "2.3.0" + "@parcel/watcher-darwin-arm64" "2.3.0" + "@parcel/watcher-darwin-x64" "2.3.0" + "@parcel/watcher-freebsd-x64" "2.3.0" + "@parcel/watcher-linux-arm-glibc" "2.3.0" + "@parcel/watcher-linux-arm64-glibc" "2.3.0" + "@parcel/watcher-linux-arm64-musl" "2.3.0" + "@parcel/watcher-linux-x64-glibc" "2.3.0" + "@parcel/watcher-linux-x64-musl" "2.3.0" + "@parcel/watcher-win32-arm64" "2.3.0" + "@parcel/watcher-win32-ia32" "2.3.0" + "@parcel/watcher-win32-x64" "2.3.0" + +"@prisma/client@5.3.1": + version "5.3.1" + resolved "https://registry.yarnpkg.com/@prisma/client/-/client-5.3.1.tgz#fc7fc2d91e814cc4fe18a4bc5e78bf851c26985e" + integrity sha512-ArOKjHwdFZIe1cGU56oIfy7wRuTn0FfZjGuU/AjgEBOQh+4rDkB6nF+AGHP8KaVpkBIiHGPQh3IpwQ3xDMdO0Q== + dependencies: + "@prisma/engines-version" "5.3.1-2.61e140623197a131c2a6189271ffee05a7aa9a59" + +"@prisma/engines-version@5.3.1-2.61e140623197a131c2a6189271ffee05a7aa9a59": + version "5.3.1-2.61e140623197a131c2a6189271ffee05a7aa9a59" + resolved "https://registry.yarnpkg.com/@prisma/engines-version/-/engines-version-5.3.1-2.61e140623197a131c2a6189271ffee05a7aa9a59.tgz#7eb6f5c6b7628b8b39df55c903f411528a6f761c" + integrity sha512-y5qbUi3ql2Xg7XraqcXEdMHh0MocBfnBzDn5GbV1xk23S3Mq8MGs+VjacTNiBh3dtEdUERCrUUG7Z3QaJ+h79w== + +"@prisma/engines@5.3.1": + version "5.3.1" + resolved "https://registry.yarnpkg.com/@prisma/engines/-/engines-5.3.1.tgz#53cc72a5ed176dc27d22305fe5569c64cc78b381" + integrity sha512-6QkILNyfeeN67BNEPEtkgh3Xo2tm6D7V+UhrkBbRHqKw9CTaz/vvTP/ROwYSP/3JT2MtIutZm/EnhxUiuOPVDA== "@react-spring/animated@~9.7.3": version "9.7.3" @@ -1998,9 +2129,9 @@ "@rollup/pluginutils" "^5.0.1" "@rollup/plugin-node-resolve@^15.2.0": - version "15.2.0" - resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.2.0.tgz#982053b237f81471aace570472e88a456d211621" - integrity sha512-mKur03xNGT8O9ODO6FtT43ITGqHWZbKPdVJHZb+iV9QYcdlhUUB0wgknvA4KCUmC5oHJF6O2W1EgmyOQyVUI4Q== + version "15.2.1" + resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.2.1.tgz#a15b14fb7969229e26a30feff2816d39eff503f0" + integrity sha512-nsbUg588+GDSu8/NS8T4UAshO6xeaOfINNuXeVHcKV02LJtoRaM1SiOacClw4kws1SFiNhdLGxlbMY9ga/zs/w== dependencies: "@rollup/pluginutils" "^5.0.1" "@types/resolve" "1.20.2" @@ -2017,7 +2148,16 @@ "@rollup/pluginutils" "^5.0.1" magic-string "^0.27.0" -"@rollup/pluginutils@^5.0.1", "@rollup/pluginutils@^5.0.2": +"@rollup/pluginutils@^5.0.1": + version "5.0.4" + resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-5.0.4.tgz#74f808f9053d33bafec0cc98e7b835c9667d32ba" + integrity sha512-0KJnIoRI8A+a1dqOYLxH8vBf8bphDmty5QvIm2hqm7oFCFYKCAZWWd2hXgMibaPsNDhI0AtpYfQZJG47pt/k4g== + dependencies: + "@types/estree" "^1.0.0" + estree-walker "^2.0.2" + picomatch "^2.3.1" + +"@rollup/pluginutils@^5.0.2": version "5.0.2" resolved "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.2.tgz" integrity sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA== @@ -2244,24 +2384,24 @@ "@svgr/plugin-jsx" "^6.5.1" "@svgr/plugin-svgo" "^6.5.1" -"@swc/helpers@0.5.1": - version "0.5.1" - resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.1.tgz#e9031491aa3f26bfcc974a67f48bd456c8a5357a" - integrity sha512-sJ902EfIzn1Fa+qYmjdQqh8tPsoxyBz+8yBKC2HKUxyezKJFwPGOn7pv4WY6QuQW//ySQi5lJjA/ZT9sNWWNTg== +"@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== dependencies: tslib "^2.4.0" -"@tanstack/query-core@4.33.0": - version "4.33.0" - resolved "https://registry.yarnpkg.com/@tanstack/query-core/-/query-core-4.33.0.tgz#7756da9a75a424e521622b1d84eb55b7a2b33715" - integrity sha512-qYu73ptvnzRh6se2nyBIDHGBQvPY1XXl3yR769B7B6mIDD7s+EZhdlWHQ67JI6UOTFRaI7wupnTnwJ3gE0Mr/g== +"@tanstack/query-core@4.35.3": + version "4.35.3" + resolved "https://registry.yarnpkg.com/@tanstack/query-core/-/query-core-4.35.3.tgz#1c127e66b4ad1beeac052db83a812d7cb67369e1" + integrity sha512-PS+WEjd9wzKTyNjjQymvcOe1yg8f3wYc6mD+vb6CKyZAKvu4sIJwryfqfBULITKCla7P9C4l5e9RXePHvZOZeQ== "@tanstack/react-query@^4.33.0": - version "4.33.0" - resolved "https://registry.yarnpkg.com/@tanstack/react-query/-/react-query-4.33.0.tgz#e927b0343a6ecaa948fee59e9ca98fe561062638" - integrity sha512-97nGbmDK0/m0B86BdiXzx3EW9RcDYKpnyL2+WwyuLHEgpfThYAnXFaMMmnTDuAO4bQJXEhflumIEUfKmP7ESGA== + version "4.35.3" + resolved "https://registry.yarnpkg.com/@tanstack/react-query/-/react-query-4.35.3.tgz#03d726ef6a19d426166427c6539b003dd9606d1b" + integrity sha512-UgTPioip/rGG3EQilXfA2j4BJkhEQsR+KAbF+KIuvQ7j4MkgnTCJF01SfRpIRNtQTlEfz/+IL7+jP8WA8bFbsw== dependencies: - "@tanstack/query-core" "4.33.0" + "@tanstack/query-core" "4.35.3" use-sync-external-store "^1.2.0" "@trysound/sax@0.2.0": @@ -2331,7 +2471,7 @@ "@types/estree@*", "@types/estree@^1.0.0": version "1.0.1" - resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.1.tgz#aa22750962f3bf0e79d753d3cc067f010c95f194" integrity sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA== "@types/estree@^0.0.50": @@ -2340,9 +2480,9 @@ integrity sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw== "@types/fs-extra@^8.0.1": - version "8.1.2" - resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-8.1.2.tgz#7125cc2e4bdd9bd2fc83005ffdb1d0ba00cca61f" - integrity sha512-SvSrYXfWSc7R4eqnOzbQF4TZmfpNSM9FrSWLU3EUnWBuyZqNBOrv1B1JA3byUDPUl9z4Ab3jeZG2eDdySlgNMg== + version "8.1.3" + resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-8.1.3.tgz#4807768c0b0a5a5f4746d8fde2f7ab0137076eea" + integrity sha512-7IdV01N0u/CaVO0fuY1YmEg14HQN3+EW8mpNgg6NEfxEl/lzCa5OxlBu3iFsCAdamnYOcTQ7oEi43Xc/67Rgzw== dependencies: "@types/node" "*" @@ -2355,7 +2495,7 @@ "@types/glob@^7.1.1": version "7.2.0" - resolved "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz" + resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.2.0.tgz#bc1b5bf3aa92f25bd5dd39f35c57361bdce5b2eb" integrity sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA== dependencies: "@types/minimatch" "*" @@ -2391,7 +2531,7 @@ "@types/minimatch@*": version "5.1.2" - resolved "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz" + resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-5.1.2.tgz#07508b45797cb81ec3f273011b054cd0755eddca" integrity sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA== "@types/minimist@^1.2.0", "@types/minimist@^1.2.2": @@ -2400,9 +2540,9 @@ integrity sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ== "@types/node@*": - version "18.15.10" - resolved "https://registry.npmjs.org/@types/node/-/node-18.15.10.tgz" - integrity sha512-9avDaQJczATcXgfmMAW3MIWArOO7A+m90vuCFLr8AotWf8igO/mRoYukrk2cqZVtv38tHs33retzHEilM7FpeQ== + version "20.6.3" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.6.3.tgz#5b763b321cd3b80f6b8dde7a37e1a77ff9358dd9" + integrity sha512-HksnYH4Ljr4VQgEy2lTStbCKv/P590tmPe5HqOnv9Gprffgv5WXAY+Y5Gqniu0GGqeTCUdBnzC3QSrzPkBkAMA== "@types/node@14": version "14.18.20" @@ -2415,9 +2555,9 @@ integrity sha512-5jY9RhV7c0Z4Jy09G+NIDTsCZ5G0L5n+Z+p+Y7t5VJHM30bgwzSjVtlcBxqAj+6L/swIlvtOSzr8rBk/aNyV2g== "@types/node@^18.11.9": - version "18.17.6" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.17.6.tgz#0296e9a30b22d2a8fcaa48d3c45afe51474ca55b" - integrity sha512-fGmT/P7z7ecA6bv/ia5DlaWCH4YeZvAQMNpUhrJjtAhOhZfoxS1VLUgU2pdk63efSjQaOJWdXMuAJsws+8I6dg== + version "18.17.18" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.17.18.tgz#acae19ad9011a2ab3d792232501c95085ba1838f" + integrity sha512-/4QOuy3ZpV7Ya1GTRz5CYSz3DgkKpyUptXuQ5PPce7uuyJAOR7r9FhkmxJfvcNUXyklbC63a+YvB3jxy7s9ngw== "@types/normalize-package-data@^2.4.0": version "2.4.1" @@ -2430,9 +2570,9 @@ integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== "@types/prop-types@*": - version "15.7.5" - resolved "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz" - integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w== + version "15.7.6" + resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.6.tgz#bbf819813d6be21011b8f5801058498bec555572" + integrity sha512-RK/kBbYOQQHLYj9Z95eh7S6t7gq4Ojt/NT8HTk8bWVhA5DaF+5SMnxHKkP4gPNN3wAZkKP+VjAf0ebtYzf+fxg== "@types/react-dom@^18.0.8": version "18.2.7" @@ -2461,9 +2601,9 @@ csstype "^3.0.2" "@types/react@^18.0.25": - version "18.2.20" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.20.tgz#1605557a83df5c8a2cc4eeb743b3dfc0eb6aaeb2" - integrity sha512-WKNtmsLWJM/3D5mG4U84cysVY31ivmyw85dE84fOCk5Hx78wezB/XEjVPWl2JTZ5FkEeaTJf+VgUAUn3PE7Isw== + version "18.2.22" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.22.tgz#abe778a1c95a07fa70df40a52d7300a40b949ccb" + integrity sha512-60fLTOLqzarLED2O3UQImc/lsNRgG0jE/a1mPW9KjMemY0LMITWEsbS4VvZ4p6rorEHd5YKxxmMKSDK505GHpA== dependencies: "@types/prop-types" "*" "@types/scheduler" "*" @@ -2471,13 +2611,13 @@ "@types/resolve@1.20.2": version "1.20.2" - resolved "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz" + resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.20.2.tgz#97d26e00cd4a0423b4af620abecf3e6f442b7975" integrity sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q== "@types/scheduler@*": - version "0.16.2" - resolved "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz" - integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew== + version "0.16.3" + resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.3.tgz#cef09e3ec9af1d63d2a6cc5b383a737e24e6dcf5" + integrity sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ== "@types/schema-utils@^2.4.0": version "2.4.0" @@ -2757,6 +2897,11 @@ acorn@^6.4.1: resolved "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz" integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ== +acorn@^8.10.0, acorn@^8.9.0: + version "8.10.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5" + integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== + acorn@^8.4.1: version "8.8.2" resolved "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz" @@ -2767,11 +2912,6 @@ acorn@^8.8.2: resolved "https://registry.npmjs.org/acorn/-/acorn-8.9.0.tgz" integrity sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ== -acorn@^8.9.0: - version "8.10.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5" - integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== - aggregate-error@^3.0.0: version "3.1.0" resolved "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz" @@ -2911,7 +3051,7 @@ array-find-index@^1.0.1: resolved "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz" integrity sha512-M1HQyIXcBGtVywBt8WVdim+lrNaK7VHp99Qt5pSNziXznKHViIBbXWtfRTpEFpF/c4FdfxNAsCCwPp5phBYJtw== -array-includes@^3.1.5, array-includes@^3.1.6: +array-includes@^3.1.5: version "3.1.6" resolved "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz" integrity sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw== @@ -2922,40 +3062,51 @@ array-includes@^3.1.5, array-includes@^3.1.6: get-intrinsic "^1.1.3" is-string "^1.0.7" +array-includes@^3.1.6: + version "3.1.7" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.7.tgz#8cd2e01b26f7a3086cbc87271593fe921c62abda" + integrity sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + get-intrinsic "^1.2.1" + is-string "^1.0.7" + array-union@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== array.prototype.findlastindex@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.2.tgz#bc229aef98f6bd0533a2bc61ff95209875526c9b" - integrity sha512-tb5thFFlUcp7NdNF6/MpDk/1r/4awWG1FIz3YqDf+/zJSTezBb+/5WViH41obXULHVpDzoiCLpJ/ZO9YbJMsdw== + version "1.2.3" + resolved "https://registry.yarnpkg.com/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz#b37598438f97b579166940814e2c0493a4f50207" + integrity sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA== dependencies: call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" + define-properties "^1.2.0" + es-abstract "^1.22.1" es-shim-unscopables "^1.0.0" - get-intrinsic "^1.1.3" + get-intrinsic "^1.2.1" array.prototype.flat@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz#ffc6576a7ca3efc2f46a143b9d1dda9b4b3cf5e2" - integrity sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA== + version "1.3.2" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz#1476217df8cff17d72ee8f3ba06738db5b387d18" + integrity sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA== dependencies: call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" + define-properties "^1.2.0" + es-abstract "^1.22.1" es-shim-unscopables "^1.0.0" array.prototype.flatmap@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz#1aae7903c2100433cb8261cd4ed310aab5c4a183" - integrity sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ== + version "1.3.2" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz#c9a7c6831db8e719d6ce639190146c24bbd3e527" + integrity sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ== dependencies: call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" + define-properties "^1.2.0" + es-abstract "^1.22.1" es-shim-unscopables "^1.0.0" array.prototype.tosorted@^1.1.1: @@ -2969,14 +3120,15 @@ array.prototype.tosorted@^1.1.1: es-shim-unscopables "^1.0.0" get-intrinsic "^1.1.3" -arraybuffer.prototype.slice@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.1.tgz#9b5ea3868a6eebc30273da577eb888381c0044bb" - integrity sha512-09x0ZWFEjj4WD8PDbykUwo3t9arLn8NIzmmYEJFpYekOAQjpkGSyrQhNoRTcwwcFRu+ycWF78QZ63oWTqSjBcw== +arraybuffer.prototype.slice@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz#98bd561953e3e74bb34938e77647179dfe6e9f12" + integrity sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw== dependencies: array-buffer-byte-length "^1.0.0" call-bind "^1.0.2" define-properties "^1.2.0" + es-abstract "^1.22.1" get-intrinsic "^1.2.1" is-array-buffer "^3.0.2" is-shared-array-buffer "^1.0.2" @@ -3211,7 +3363,7 @@ buffer@^5.5.0: builtin-modules@^3.3.0: version "3.3.0" - resolved "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz" + resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.3.0.tgz#cae62812b89801e9656336e46223e030386be7b6" integrity sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw== busboy@1.6.0: @@ -3283,7 +3435,7 @@ caseless@~0.12.0: resolved "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz" integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== -chalk@^2.0.0, chalk@^2.4.1, chalk@^2.4.2: +chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -3301,9 +3453,9 @@ chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1, chalk@^4.1.2: supports-color "^7.1.0" chart.js@^4.2.1: - version "4.3.2" - resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-4.3.2.tgz#904ebe0376eb368a659a92d2050df47336847e4c" - integrity sha512-pvQNyFOY1QmbmIr8oDORL16/FFivfxj8V26VFpFilMo4cNvkV5WXLJetDio365pd9gKUHGdirUTbqJfw8tr+Dg== + version "4.4.0" + resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-4.4.0.tgz#df843fdd9ec6bd88d7f07e2b95348d221bd2698c" + integrity sha512-vQEj6d+z0dcsKLlQvbKIMYFHd3t8W/7L2vfJIbYcfyPcRx92CsHqECpueN8qVGNlKyDcr5wBrYAYKnfu/9Q1hQ== dependencies: "@kurkle/color" "^0.3.0" @@ -3334,7 +3486,7 @@ chownr@^1.1.1: chownr@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== ci-info@^3.2.0: @@ -3342,10 +3494,10 @@ ci-info@^3.2.0: resolved "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz" integrity sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw== -citty@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/citty/-/citty-0.1.2.tgz#bae07bfd1962439735d7698c7954f76025690603" - integrity sha512-Me9nf0/BEmMOnuQzMOVXgpzkMUNbd0Am8lTl/13p0aRGAoLGk5T5sdet/42CrIGmWdG67BgHUhcKK1my1ujUEg== +citty@^0.1.3, citty@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/citty/-/citty-0.1.4.tgz#91091be06ae4951dffa42fd443de7fe72245f2e0" + integrity sha512-Q3bK1huLxzQrvj7hImJ7Z1vKYJRPQCDnd0EjXfHMidcjecGOMuLrmuQmtWmFkuKLcMThlGh1yCKG8IEc6VeNXQ== dependencies: consola "^3.2.3" @@ -3511,7 +3663,7 @@ concat-with-sourcemaps@^1.1.0: dependencies: source-map "^0.6.1" -consola@^3.1.0, consola@^3.2.3: +consola@^3.2.3: version "3.2.3" resolved "https://registry.yarnpkg.com/consola/-/consola-3.2.3.tgz#0741857aa88cfa0d6fd53f1cff0375136e98502f" integrity sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ== @@ -3573,13 +3725,13 @@ cosmiconfig@^8.1.3: path-type "^4.0.0" cosmiconfig@^8.2.0: - version "8.2.0" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-8.2.0.tgz#f7d17c56a590856cd1e7cee98734dca272b0d8fd" - integrity sha512-3rTMnFJA1tCOPwRxtgF4wd7Ab2qvDbL8jX+3smjIbS4HlZBagTlpERbdN7iAbWlrfxE3M8c27kTwTawQ7st+OQ== + version "8.3.6" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-8.3.6.tgz#060a2b871d66dba6c8538ea1118ba1ac16f5fae3" + integrity sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA== dependencies: - import-fresh "^3.2.1" + import-fresh "^3.3.0" js-yaml "^4.1.0" - parse-json "^5.0.0" + parse-json "^5.2.0" path-type "^4.0.0" create-require@^1.1.0: @@ -3785,9 +3937,9 @@ csstype@^2.6.8: integrity sha512-/WwNkdXfckNgw6S5R125rrW8ez139lBHWouiBvX8dfMFtcn6V81REDqnH7+CRpRipfYlyU1CmOnOxrmGcFOjeA== csstype@^3.0.2: - version "3.1.1" - resolved "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz" - integrity sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw== + version "3.1.2" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.2.tgz#1d4bf9d572f11c14031f0436e1c10bc1f571f50b" + integrity sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ== currently-unhandled@^0.4.1: version "0.4.1" @@ -3965,11 +4117,21 @@ deepmerge@^4.2.2, deepmerge@^4.3.1: resolved "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz" integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== -define-properties@^1.1.3, define-properties@^1.1.4, define-properties@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.0.tgz#52988570670c9eacedd8064f4a990f2405849bd5" - integrity sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA== +define-data-property@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.0.tgz#0db13540704e1d8d479a0656cf781267531b9451" + integrity sha512-UzGwzcjyv3OtAvolTj1GoyNYzfFR+iqbGjcnBEENZVCpM4/Ng1yhGNvS3lR/xDS74Tb2wGG9WzNSNIOS9UVb2g== dependencies: + get-intrinsic "^1.2.1" + gopd "^1.0.1" + has-property-descriptors "^1.0.0" + +define-properties@^1.1.3, define-properties@^1.1.4, define-properties@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" + integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== + dependencies: + define-data-property "^1.0.1" has-property-descriptors "^1.0.0" object-keys "^1.1.1" @@ -4016,15 +4178,15 @@ denque@^2.1.0: resolved "https://registry.yarnpkg.com/denque/-/denque-2.1.0.tgz#e93e1a6569fb5e66f16a3c2a2964617d349d6ab1" integrity sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw== -destr@^1.1.1, destr@^1.2.2: +destr@^1.1.1: version "1.2.2" resolved "https://registry.yarnpkg.com/destr/-/destr-1.2.2.tgz#7ba9befcafb645a50e76b260449c63927b51e22f" integrity sha512-lrbCJwD9saUQrqUfXvl6qoM+QN3W7tLV5pAOs+OqOmopCCz/JkE05MHedJR1xfk4IAnZuJXPVuN5+7jNA2ZCiA== -destr@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/destr/-/destr-2.0.0.tgz#60847d02b211de6e252fc72806f4ec39ec257e7b" - integrity sha512-FJ9RDpf3GicEBvzI3jxc2XhHzbqD8p4ANw/1kPsFBfTvP1b7Gn/Lg1vO7R9J4IVgoMbyUmFrFGZafJ1hPZpvlg== +destr@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/destr/-/destr-2.0.1.tgz#2fc7bddc256fed1183e03f8d148391dde4023cb2" + integrity sha512-M1Ob1zPSIvlARiJUkKqvAZ3VAqQY6Jcuth/pBKQ2b1dX/Qx0OnJ8Vux6J2H5PTMQeRzWrrbTu70VxBfv/OPDJA== detect-browser@^5.2.0: version "5.3.0" @@ -4036,6 +4198,11 @@ detect-indent@^6.0.0: resolved "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz" integrity sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA== +detect-libc@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + integrity sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg== + detect-libc@^2.0.0, detect-libc@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.2.tgz#8ccf2ba9315350e1241b88d0ac3b0e1fbd99605d" @@ -4201,51 +4368,6 @@ error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-abstract@^1.19.0, es-abstract@^1.20.4, es-abstract@^1.21.2: - version "1.22.1" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.22.1.tgz#8b4e5fc5cefd7f1660f0f8e1a52900dfbc9d9ccc" - integrity sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw== - dependencies: - array-buffer-byte-length "^1.0.0" - arraybuffer.prototype.slice "^1.0.1" - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - es-set-tostringtag "^2.0.1" - es-to-primitive "^1.2.1" - function.prototype.name "^1.1.5" - get-intrinsic "^1.2.1" - get-symbol-description "^1.0.0" - globalthis "^1.0.3" - gopd "^1.0.1" - has "^1.0.3" - has-property-descriptors "^1.0.0" - has-proto "^1.0.1" - has-symbols "^1.0.3" - internal-slot "^1.0.5" - is-array-buffer "^3.0.2" - is-callable "^1.2.7" - is-negative-zero "^2.0.2" - is-regex "^1.1.4" - is-shared-array-buffer "^1.0.2" - is-string "^1.0.7" - is-typed-array "^1.1.10" - is-weakref "^1.0.2" - object-inspect "^1.12.3" - object-keys "^1.1.1" - object.assign "^4.1.4" - regexp.prototype.flags "^1.5.0" - safe-array-concat "^1.0.0" - safe-regex-test "^1.0.0" - string.prototype.trim "^1.2.7" - string.prototype.trimend "^1.0.6" - string.prototype.trimstart "^1.0.6" - typed-array-buffer "^1.0.0" - typed-array-byte-length "^1.0.0" - typed-array-byte-offset "^1.0.0" - typed-array-length "^1.0.4" - unbox-primitive "^1.0.2" - which-typed-array "^1.1.10" - es-abstract@^1.19.1: version "1.21.1" resolved "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.1.tgz" @@ -4285,6 +4407,51 @@ es-abstract@^1.19.1: unbox-primitive "^1.0.2" which-typed-array "^1.1.9" +es-abstract@^1.20.4, es-abstract@^1.22.1: + version "1.22.2" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.22.2.tgz#90f7282d91d0ad577f505e423e52d4c1d93c1b8a" + integrity sha512-YoxfFcDmhjOgWPWsV13+2RNjq1F6UQnfs+8TftwNqtzlmFzEXvlUwdrNrYeaizfjQzRMxkZ6ElWMOJIFKdVqwA== + dependencies: + array-buffer-byte-length "^1.0.0" + arraybuffer.prototype.slice "^1.0.2" + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + es-set-tostringtag "^2.0.1" + es-to-primitive "^1.2.1" + function.prototype.name "^1.1.6" + get-intrinsic "^1.2.1" + get-symbol-description "^1.0.0" + globalthis "^1.0.3" + gopd "^1.0.1" + has "^1.0.3" + has-property-descriptors "^1.0.0" + has-proto "^1.0.1" + has-symbols "^1.0.3" + internal-slot "^1.0.5" + is-array-buffer "^3.0.2" + is-callable "^1.2.7" + is-negative-zero "^2.0.2" + is-regex "^1.1.4" + is-shared-array-buffer "^1.0.2" + is-string "^1.0.7" + is-typed-array "^1.1.12" + is-weakref "^1.0.2" + object-inspect "^1.12.3" + object-keys "^1.1.1" + object.assign "^4.1.4" + regexp.prototype.flags "^1.5.1" + safe-array-concat "^1.0.1" + safe-regex-test "^1.0.0" + string.prototype.trim "^1.2.8" + string.prototype.trimend "^1.0.7" + string.prototype.trimstart "^1.0.7" + typed-array-buffer "^1.0.0" + typed-array-byte-length "^1.0.0" + typed-array-byte-offset "^1.0.0" + typed-array-length "^1.0.4" + unbox-primitive "^1.0.2" + which-typed-array "^1.1.11" + es-module-lexer@^1.0.5: version "1.2.1" resolved "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.2.1.tgz" @@ -4345,7 +4512,7 @@ esbuild@^0.17.17: escalade@^3.1.1: version "3.1.1" - resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== escape-string-regexp@^1.0.5: @@ -4374,16 +4541,16 @@ eslint-config-next@^12.2.4: eslint-plugin-react-hooks "^4.5.0" eslint-config-prettier@^8.5.0: - version "8.9.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.9.0.tgz#094b6254b2804b0544f7cee535f802b6d29ee10b" - integrity sha512-+sbni7NfVXnOpnRadUA8S28AUlsZt9GjgFvABIRL9Hkn8KqNzOp+7Lw4QWtrwn20KzU3wqu1QoOj2m+7rKRqkA== + version "8.10.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz#3a06a662130807e2502fc3ff8b4143d8a0658e11" + integrity sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg== eslint-import-resolver-alias@^1.1.2: version "1.1.2" resolved "https://registry.npmjs.org/eslint-import-resolver-alias/-/eslint-import-resolver-alias-1.1.2.tgz" integrity sha512-WdviM1Eu834zsfjHtcGHtGfcu+F30Od3V7I9Fi57uhBEwPkjDcii7/yW8jAT+gOhn4P/vOxxNAXbFAKsrrc15w== -eslint-import-resolver-node@^0.3.6, eslint-import-resolver-node@^0.3.7: +eslint-import-resolver-node@^0.3.6: version "0.3.7" resolved "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz" integrity sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA== @@ -4392,6 +4559,15 @@ eslint-import-resolver-node@^0.3.6, eslint-import-resolver-node@^0.3.7: is-core-module "^2.11.0" resolve "^1.22.1" +eslint-import-resolver-node@^0.3.7: + version "0.3.9" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz#d4eaac52b8a2e7c3cd1903eb00f7e053356118ac" + integrity sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g== + dependencies: + debug "^3.2.7" + is-core-module "^2.13.0" + resolve "^1.22.4" + eslint-import-resolver-typescript@^2.7.1: version "2.7.1" resolved "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-2.7.1.tgz" @@ -4411,9 +4587,9 @@ eslint-module-utils@^2.8.0: debug "^3.2.7" eslint-plugin-import@^2.26.0: - version "2.28.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.28.0.tgz#8d66d6925117b06c4018d491ae84469eb3cb1005" - integrity sha512-B8s/n+ZluN7sxj9eUf7/pRFERX0r5bnFA2dCaLHy2ZeaQEAz0k+ZZkFWRFHJAqxfxQDx6KLv9LeIki7cFdwW+Q== + version "2.28.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.28.1.tgz#63b8b5b3c409bfc75ebaf8fb206b07ab435482c4" + integrity sha512-9I9hFlITvOV55alzoKBI+K9q74kv0iKMeY6av5+umsNwayt59fz692daGyjR+oStBQgx6nwR9rXldDev3Clw+A== dependencies: array-includes "^3.1.6" array.prototype.findlastindex "^1.2.2" @@ -4424,13 +4600,12 @@ eslint-plugin-import@^2.26.0: eslint-import-resolver-node "^0.3.7" eslint-module-utils "^2.8.0" has "^1.0.3" - is-core-module "^2.12.1" + is-core-module "^2.13.0" is-glob "^4.0.3" minimatch "^3.1.2" object.fromentries "^2.0.6" object.groupby "^1.0.0" object.values "^1.1.6" - resolve "^1.22.3" semver "^6.3.1" tsconfig-paths "^3.14.2" @@ -4502,21 +4677,21 @@ eslint-scope@^7.2.2: esrecurse "^4.3.0" estraverse "^5.2.0" -eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.2: - version "3.4.2" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.2.tgz#8c2095440eca8c933bedcadf16fefa44dbe9ba5f" - integrity sha512-8drBzUEyZ2llkpCA67iYrgEssKDUu68V8ChqqOfFupIaG/LCVPUT+CoGJpT77zJprs4T/W7p07LP7zAIMuweVw== +eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: + version "3.4.3" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" + integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== eslint@^8.33.0: - version "8.46.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.46.0.tgz#a06a0ff6974e53e643acc42d1dcf2e7f797b3552" - integrity sha512-cIO74PvbW0qU8e0mIvk5IV3ToWdCq5FYG6gWPHHkx6gNdjlbAYvtfHmlCMXxjcoVaIdwy/IAt3+mDkZkfvb2Dg== + version "8.49.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.49.0.tgz#09d80a89bdb4edee2efcf6964623af1054bf6d42" + integrity sha512-jw03ENfm6VJI0jA9U+8H5zfl5b+FvuU3YYvZRdZHOlU2ggJkxrlkJH4HcDrZpj6YwD8kuYqvQM8LyesoazrSOQ== dependencies: "@eslint-community/eslint-utils" "^4.2.0" "@eslint-community/regexpp" "^4.6.1" - "@eslint/eslintrc" "^2.1.1" - "@eslint/js" "^8.46.0" - "@humanwhocodes/config-array" "^0.11.10" + "@eslint/eslintrc" "^2.1.2" + "@eslint/js" "8.49.0" + "@humanwhocodes/config-array" "^0.11.11" "@humanwhocodes/module-importer" "^1.0.1" "@nodelib/fs.walk" "^1.2.8" ajv "^6.12.4" @@ -4526,7 +4701,7 @@ eslint@^8.33.0: doctrine "^3.0.0" escape-string-regexp "^4.0.0" eslint-scope "^7.2.2" - eslint-visitor-keys "^3.4.2" + eslint-visitor-keys "^3.4.3" espree "^9.6.1" esquery "^1.4.2" esutils "^2.0.2" @@ -4595,7 +4770,7 @@ estree-walker@^0.6.1: estree-walker@^2.0.2: version "2.0.2" - resolved "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== esutils@^2.0.2: @@ -4685,14 +4860,14 @@ fast-equals@^3.0.1: integrity sha512-NCe8qxnZFARSHGztGMZOO/PC1qa5MIFB5Hp66WdzbCRAz8U8US3bx1UTgLS49efBQPcUtO9gf5oVEY8o7y/7Kg== fast-fifo@^1.1.0, fast-fifo@^1.2.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/fast-fifo/-/fast-fifo-1.3.0.tgz#03e381bcbfb29932d7c3afde6e15e83e05ab4d8b" - integrity sha512-IgfweLvEpwyA4WgiQe9Nx6VV2QkML2NkvZnk1oKnIzXgXdWxuhF7zw4DvLTPZJn6PIUneiAXPF24QmoEqHTjyw== + version "1.3.2" + resolved "https://registry.yarnpkg.com/fast-fifo/-/fast-fifo-1.3.2.tgz#286e31de96eb96d38a97899815740ba2a4f3640c" + integrity sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ== -fast-glob@^3.0.3, fast-glob@^3.2.7: - version "3.2.12" - resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz" - integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== +fast-glob@^3.0.3, fast-glob@^3.2.9, fast-glob@^3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.1.tgz#784b4e897340f3dbbef17413b3f11acf03c874c4" + integrity sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg== dependencies: "@nodelib/fs.stat" "^2.0.2" "@nodelib/fs.walk" "^1.2.3" @@ -4700,10 +4875,10 @@ fast-glob@^3.0.3, fast-glob@^3.2.7: merge2 "^1.3.0" micromatch "^4.0.4" -fast-glob@^3.2.9, fast-glob@^3.3.0: - version "3.3.1" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.1.tgz#784b4e897340f3dbbef17413b3f11acf03c874c4" - integrity sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg== +fast-glob@^3.2.7: + version "3.2.12" + resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz" + integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== dependencies: "@nodelib/fs.stat" "^2.0.2" "@nodelib/fs.walk" "^1.2.3" @@ -4772,11 +4947,12 @@ find-up@^5.0.0: path-exists "^4.0.0" flat-cache@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" - integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== + version "3.1.0" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.1.0.tgz#0e54ab4a1a60fe87e2946b6b00657f1c99e1af3f" + integrity sha512-OHx4Qwrrt0E4jEIcI5/Xb+f+QmJYNj2rrK8wiIdQOIrB9WrrJL8cjZvXdXuBTkkEwEqLycb5BeZDV1o2i9bTew== dependencies: - flatted "^3.1.0" + flatted "^3.2.7" + keyv "^4.5.3" rimraf "^3.0.2" flat@^5.0.0: @@ -4784,15 +4960,15 @@ flat@^5.0.0: resolved "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz" integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== -flatted@^3.1.0: - version "3.2.7" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787" - integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ== +flatted@^3.2.7: + version "3.2.9" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.9.tgz#7eb4c67ca1ba34232ca9d2d93e9886e611ad7daf" + integrity sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ== follow-redirects@^1.15.2: - version "1.15.2" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" - integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== + version "1.15.3" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.3.tgz#fe2f3ef2690afce7e82ed0b44db08165b207123a" + integrity sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q== for-each@^0.3.3: version "0.3.3" @@ -4871,7 +5047,7 @@ fs-extra@^9.0.0: fs-minipass@^2.0.0: version "2.1.0" - resolved "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== dependencies: minipass "^3.0.0" @@ -4882,26 +5058,26 @@ fs.realpath@^1.0.0: integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== fsevents@~2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" - integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== function-bind@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== -function.prototype.name@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621" - integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA== +function.prototype.name@^1.1.5, function.prototype.name@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.6.tgz#cdf315b7d90ee77a4c6ee216c3c3362da07533fd" + integrity sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg== dependencies: call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.0" - functions-have-names "^1.2.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + functions-have-names "^1.2.3" -functions-have-names@^1.2.2, functions-have-names@^1.2.3: +functions-have-names@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== @@ -4938,10 +5114,10 @@ get-own-enumerable-property-symbols@^3.0.0: resolved "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz" integrity sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g== -get-port-please@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/get-port-please/-/get-port-please-3.0.1.tgz#a24953a41dc249f76869ac25e81d6623e61ab010" - integrity sha512-R5pcVO8Z1+pVDu8Ml3xaJCEkBiiy1VQN9za0YqH8GIi1nIqD4IzQhzY6dDzMRtdS1lyiGlucRzm8IN8wtLIXng== +get-port-please@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/get-port-please/-/get-port-please-3.1.1.tgz#2556623cddb4801d823c0a6a15eec038abb483be" + integrity sha512-3UBAyM3u4ZBVYDsxOQfJDxEa6XTbpBDrOjp4mf7ExFRt5BKs/QywQQiJsh2B+hxcZLSapWqCRvElUe8DnKcFHA== get-stream@^6.0.0: version "6.0.1" @@ -5044,9 +5220,9 @@ globals@^11.1.0: integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== globals@^13.19.0: - version "13.20.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.20.0.tgz#ea276a1e508ffd4f1612888f9d1bad1e2717bf82" - integrity sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ== + version "13.22.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.22.0.tgz#0c9fcb9c48a2494fbb5edbfee644285543eba9d8" + integrity sha512-H1Ddc/PbZHTDVJSnj8kWptIRSD6AM3pK+mKytuIVF4uoBV7rshFlhhvA58ceJ5wp3Er58w6zj7bykMpYXt3ETw== dependencies: type-fest "^0.20.2" @@ -5129,18 +5305,19 @@ graphemer@^1.4.0: resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== -h3@^1.7.1: - version "1.7.1" - resolved "https://registry.yarnpkg.com/h3/-/h3-1.7.1.tgz#fc9328adf5da1d29cbb2d97b81ae3dd9b426463e" - integrity sha512-A9V2NEDNHet7v1gCg7CMwerSigLi0SRbhTy7C3lGb0N4YKIpPmLDjedTUopqp4dnn7COHfqUjjaz3zbtz4QduA== +h3@^1.7.1, h3@^1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/h3/-/h3-1.8.1.tgz#e36371407982b0a37475412d64697c521dd3ce43" + integrity sha512-m5rFuu+5bpwBBHqqS0zexjK+Q8dhtFRvO9JXQG0RvSPL6QrIT6vv42vuBM22SLOgGMoZYsHk0y7VPidt9s+nkw== dependencies: cookie-es "^1.0.0" defu "^6.1.2" - destr "^2.0.0" - iron-webcrypto "^0.7.0" - radix3 "^1.0.1" - ufo "^1.1.2" + destr "^2.0.1" + iron-webcrypto "^0.8.0" + radix3 "^1.1.0" + ufo "^1.3.0" uncrypto "^0.1.3" + unenv "^1.7.4" har-schema@^2.0.0: version "2.0.0" @@ -5291,7 +5468,7 @@ import-cwd@^3.0.0: dependencies: import-from "^3.0.0" -import-fresh@^3.2.1: +import-fresh@^3.2.1, import-fresh@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== @@ -5413,27 +5590,27 @@ ipaddr.js@^2.0.1: integrity sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ== ipx@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/ipx/-/ipx-1.2.0.tgz#23130eed071a786158b86774980deca6e5d5fa9e" - integrity sha512-FkEP56C08HdlqlWKm3pMhatywPtDBTlePTdzskksCR1+7xnB6fQs6pXOTXPTG5i+gGPgCOxbNMUSZEH/DQcWDA== + version "1.3.0" + resolved "https://registry.yarnpkg.com/ipx/-/ipx-1.3.0.tgz#bd70e3c3ce45995cf50d9a01ece819736374e36c" + integrity sha512-Jfu+zQ0NGZwSeZ11CGMOnqWFlIyVcT8dW48e5UxKnMjQXXDy8VLTl8FIP7vRIJ9hd3ZPaJ/RIXXLJfZmBqRXWQ== dependencies: "@fastify/accept-negotiator" "^1.1.0" - consola "^3.1.0" + consola "^3.2.3" defu "^6.1.2" - destr "^1.2.2" + destr "^2.0.1" etag "^1.8.1" image-meta "^0.1.1" - listhen "^1.0.4" - node-fetch-native "^1.1.1" + listhen "^1.4.4" + node-fetch-native "^1.4.0" pathe "^1.1.1" - sharp "^0.32.1" - ufo "^1.1.2" + sharp "^0.32.5" + ufo "^1.3.0" xss "^1.0.14" -iron-webcrypto@^0.7.0: - version "0.7.1" - resolved "https://registry.yarnpkg.com/iron-webcrypto/-/iron-webcrypto-0.7.1.tgz#7323e1f32fbc5d3e1f25a228fdbf0bcde3c276c6" - integrity sha512-K/UmlEhPCPXEHV5hAtH5C0tI5JnFuOrv4yO/j7ODPl3HaiiHBLbOLTde+ieUaAyfCATe4LoAnclyF+hmSCOVmQ== +iron-webcrypto@^0.8.0: + version "0.8.2" + resolved "https://registry.yarnpkg.com/iron-webcrypto/-/iron-webcrypto-0.8.2.tgz#c7b60c20ffc22f880f12540ba44b4db615ce515e" + integrity sha512-jGiwmpgTuF19Vt4hn3+AzaVFGpVZt7A1ysd5ivFel2r4aNVFwqaYa6aU6qsF1PM7b+WFivZHz3nipwUOXaOnHg== is-array-buffer@^3.0.1, is-array-buffer@^3.0.2: version "3.0.2" @@ -5478,7 +5655,7 @@ is-boolean-object@^1.1.0: is-builtin-module@^3.2.1: version "3.2.1" - resolved "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz" + resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-3.2.1.tgz#f03271717d8654cfcaf07ab0463faa3571581169" integrity sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A== dependencies: builtin-modules "^3.3.0" @@ -5495,7 +5672,14 @@ is-ci@^3.0.1: dependencies: ci-info "^3.2.0" -is-core-module@^2.11.0, is-core-module@^2.12.0, is-core-module@^2.12.1, is-core-module@^2.5.0, is-core-module@^2.9.0: +is-core-module@^2.11.0, is-core-module@^2.13.0, is-core-module@^2.5.0: + version "2.13.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.0.tgz#bb52aa6e2cbd49a30c2ba68c42bf3435ba6072db" + integrity sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ== + dependencies: + has "^1.0.3" + +is-core-module@^2.9.0: version "2.12.1" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.12.1.tgz#0c0b6885b6f80011c71541ce15c8d66cf5a4f9fd" integrity sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg== @@ -5543,7 +5727,7 @@ is-localhost-ip@^1.4.0: is-module@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" integrity sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g== is-negative-zero@^2.0.2: @@ -5649,7 +5833,7 @@ is-symbol@^1.0.2, is-symbol@^1.0.3: dependencies: has-symbols "^1.0.2" -is-typed-array@^1.1.10, is-typed-array@^1.1.9: +is-typed-array@^1.1.10, is-typed-array@^1.1.12, is-typed-array@^1.1.9: version "1.1.12" resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.12.tgz#d0bab5686ef4a76f7a73097b95470ab199c57d4a" integrity sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg== @@ -5681,9 +5865,9 @@ isarray@^2.0.5: integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== isbot@^3.4.5: - version "3.6.13" - resolved "https://registry.yarnpkg.com/isbot/-/isbot-3.6.13.tgz#e060f727cb53475a4dab1569321ced0f84633d63" - integrity sha512-uoP4uK5Dc2CrabmK+Gue1jTL+scHiCc1c9rblRpJwG8CPxjLIv8jmGyyGRGkbPOweayhkskdZsEQXG6p+QCQrg== + version "3.7.0" + resolved "https://registry.yarnpkg.com/isbot/-/isbot-3.7.0.tgz#c68eb005c03e3d225a0ea559211da2bff94bb1ce" + integrity sha512-9BcjlI89966BqWJmYdTnRub85sit931MyCthSIPtgoOsTjoW7A2MVa09HzPpYE2+G4vyAxfDvR0AbUGV0FInQg== isexe@^2.0.0: version "2.0.0" @@ -5704,10 +5888,10 @@ jest-worker@^26.2.1: merge-stream "^2.0.0" supports-color "^7.0.0" -jiti@^1.19.1: - version "1.19.1" - resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.19.1.tgz#fa99e4b76a23053e0e7cde098efe1704a14c16f1" - integrity sha512-oVhqoRDaBXf7sjkll95LHVS6Myyyb1zaunVwk4Z0+WPSW4gjS0pl01zYKHScTuyEhQsFxV5L4DR5r+YqSyqyyg== +jiti@^1.20.0: + version "1.20.0" + resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.20.0.tgz#2d823b5852ee8963585c8dd8b7992ffc1ae83b42" + integrity sha512-3TV69ZbrvV6U5DfQimop50jE9Dl6J8O1ja1dvBbMba/sZ3YBEQqJ2VZRoQPVnhlzjNtU1vaXRZVrVjU4qtm8yA== joycon@^3.1.1: version "3.1.1" @@ -5749,6 +5933,11 @@ jsesc@~0.5.0: resolved "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz" integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA== +json-buffer@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== + json-parse-better-errors@^1.0.1: version "1.0.2" resolved "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz" @@ -5810,7 +5999,7 @@ json5@^2.2.2: jsonc-parser@^3.2.0: version "3.2.0" - resolved "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz" + resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.2.0.tgz#31ff3f4c2b9793f89c67212627c51c6394f88e76" integrity sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w== jsonfile@^4.0.0: @@ -5889,6 +6078,13 @@ kafkajs@^2.1.0: resolved "https://registry.npmjs.org/kafkajs/-/kafkajs-2.2.4.tgz" integrity sha512-j/YeapB1vfPT2iOIUn/vxdyKEuhuY2PxMBvf5JWux6iSaukAccrMtXEY/Lb7OvavDhOWME589bpLrEdnVHjfjA== +keyv@^4.5.3: + version "4.5.3" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.3.tgz#00873d2b046df737963157bd04f294ca818c9c25" + integrity sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug== + dependencies: + json-buffer "3.0.1" + kind-of@^6.0.2, kind-of@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" @@ -5899,10 +6095,10 @@ kleur@^3.0.3: resolved "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz" integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== -known-css-properties@^0.27.0: - version "0.27.0" - resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.27.0.tgz#82a9358dda5fe7f7bd12b5e7142c0a205393c0c5" - integrity sha512-uMCj6+hZYDoffuvAJjFAPz56E9uoowFHmTkqRtRq5WyC5Q6Cu/fTZKNQpX/RbzChBYLLl3lo8CjFZBAZXq9qFg== +known-css-properties@^0.28.0: + version "0.28.0" + resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.28.0.tgz#8a8be010f368b3036fe6ab0ef4bbbed972bd6274" + integrity sha512-9pSL5XB4J+ifHP0e0jmmC98OGC1nL8/JjS+fi6mnTlIf//yt/MfVLtKg7S6nCtj/8KTcWX7nRlY0XywoYY1ISQ== language-subtag-registry@^0.3.20: version "0.3.22" @@ -5954,22 +6150,28 @@ lint-staged@^11.0.0: stringify-object "3.3.0" supports-color "8.1.1" -listhen@^1.0.4: - version "1.1.2" - resolved "https://registry.yarnpkg.com/listhen/-/listhen-1.1.2.tgz#c95082b0fdbd50d73abeab748893768dbefa7db8" - integrity sha512-rLX5V57oonazmc6zoZ2LzfbSOfGzDOLdQ/eTEh/d3f1xYMACH1yIU8nr0YGl2WiR+l31o3QCN4/VH2dUNyYvTA== +listhen@^1.2.2, listhen@^1.4.4: + version "1.5.5" + resolved "https://registry.yarnpkg.com/listhen/-/listhen-1.5.5.tgz#58915512af70f770aa3e9fb19367adf479bb58c4" + integrity sha512-LXe8Xlyh3gnxdv4tSjTjscD1vpr/2PRpzq8YIaMJgyKzRG8wdISlWVWnGThJfHnlJ6hmLt2wq1yeeix0TEbuoA== dependencies: - citty "^0.1.2" + "@parcel/watcher" "^2.3.0" + "@parcel/watcher-wasm" "2.3.0" + citty "^0.1.4" clipboardy "^3.0.0" consola "^3.2.3" defu "^6.1.2" - get-port-please "^3.0.1" + get-port-please "^3.1.1" + h3 "^1.8.1" http-shutdown "^1.2.2" - jiti "^1.19.1" - mlly "^1.4.0" + jiti "^1.20.0" + mlly "^1.4.2" node-forge "^1.3.1" pathe "^1.1.1" - ufo "^1.1.2" + std-env "^3.4.3" + ufo "^1.3.0" + untun "^0.1.2" + uqr "^0.1.2" listr2@^3.12.2: version "3.14.0" @@ -6117,9 +6319,9 @@ lower-case@^2.0.2: tslib "^2.0.3" lru-cache@^10.0.0: - version "10.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.0.0.tgz#b9e2a6a72a129d81ab317202d93c7691df727e61" - integrity sha512-svTf/fzsKHffP42sujkO/Rjs37BCIsQVRCeNYIm9WN8rgT7ffoUnRtZCqU+6BqcSBdv8gwJeTz8knJpgACeQMw== + version "10.0.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.0.1.tgz#0a3be479df549cca0e5d693ac402ff19537a6b7a" + integrity sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g== lru-cache@^5.1.1: version "5.1.1" @@ -6286,6 +6488,11 @@ mime-types@^2.1.12, mime-types@~2.1.19: dependencies: mime-db "1.52.0" +mime@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-3.0.0.tgz#b374550dca3a0c18443b0c950a6a58f1931cf7a7" + integrity sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A== + mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" @@ -6331,19 +6538,19 @@ minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5, minimist@^1.2.6: minipass@^3.0.0: version "3.3.6" - resolved "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.6.tgz#7bba384db3a1520d18c9c0e5251c3444e95dd94a" integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw== dependencies: yallist "^4.0.0" minipass@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d" integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ== minizlib@^2.1.1: version "2.1.2" - resolved "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== dependencies: minipass "^3.0.0" @@ -6354,20 +6561,25 @@ mkdirp-classic@^0.5.2, mkdirp-classic@^0.5.3: resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== -mkdirp@^1.0.3, mkdirp@^1.0.4: +mkdirp@^1.0.3: version "1.0.4" - resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== -mlly@^1.2.0, mlly@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/mlly/-/mlly-1.4.0.tgz#830c10d63f1f97bd8785377b24dc2a15d972832b" - integrity sha512-ua8PAThnTwpprIaU47EPeZ/bPUVp2QYBbWMphUQpVdBI3Lgqzm5KZQ45Agm3YJedHXaIHl6pBGabaLSUPPSptg== +mkdirp@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-3.0.1.tgz#e44e4c5607fb279c168241713cc6e0fea9adcb50" + integrity sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg== + +mlly@^1.2.0, mlly@^1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/mlly/-/mlly-1.4.2.tgz#7cf406aa319ff6563d25da6b36610a93f2a8007e" + integrity sha512-i/Ykufi2t1EZ6NaPLdfnZk2AX8cs0d+mTzVKuPfqPKPatxLApaBoxJQ9x1/uckXtrS/U5oisPMDkNs0yQTaBRg== dependencies: - acorn "^8.9.0" + acorn "^8.10.0" pathe "^1.1.1" pkg-types "^1.0.3" - ufo "^1.1.2" + ufo "^1.3.0" mmdb-lib@2.0.2: version "2.0.2" @@ -6436,6 +6648,11 @@ napi-build-utils@^1.0.1: resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-1.0.2.tgz#b1fddc0b2c46e380a0b7a76f984dd47c41a13806" integrity sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg== +napi-wasm@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/napi-wasm/-/napi-wasm-1.1.0.tgz#bbe617823765ae9c1bc12ff5942370eae7b2ba4e" + integrity sha512-lHwIAJbmLSjF9VDRm9GoVOy9AGp3aIvkjv+Kvz9h16QR3uSVYH78PNQUnT2U4X53mhlnV2M7wrhibQ3GHicDmg== + natural-compare-lite@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz#17b09581988979fddafe0201e931ba933c96cbb4" @@ -6455,13 +6672,13 @@ next-basics@^0.36.0: jsonwebtoken "^9.0.0" pure-rand "^6.0.2" -next@13.4.19: - version "13.4.19" - resolved "https://registry.yarnpkg.com/next/-/next-13.4.19.tgz#2326e02aeedee2c693d4f37b90e4f0ed6882b35f" - integrity sha512-HuPSzzAbJ1T4BD8e0bs6B9C1kWQ6gv8ykZoRWs5AQoiIuqbGHHdQO7Ljuvg05Q0Z24E2ABozHe6FxDvI6HfyAw== +next@13.5.2: + version "13.5.2" + resolved "https://registry.yarnpkg.com/next/-/next-13.5.2.tgz#809dd84e481049e298fe79d28b1d66b587483fca" + integrity sha512-vog4UhUaMYAzeqfiAAmgB/QWLW7p01/sg+2vn6bqc/CxHFYizMzLv6gjxKzl31EVFkfl/F+GbxlKizlkTE9RdA== dependencies: - "@next/env" "13.4.19" - "@swc/helpers" "0.5.1" + "@next/env" "13.5.2" + "@swc/helpers" "0.5.2" busboy "1.6.0" caniuse-lite "^1.0.30001406" postcss "8.4.14" @@ -6469,15 +6686,15 @@ next@13.4.19: watchpack "2.4.0" zod "3.21.4" optionalDependencies: - "@next/swc-darwin-arm64" "13.4.19" - "@next/swc-darwin-x64" "13.4.19" - "@next/swc-linux-arm64-gnu" "13.4.19" - "@next/swc-linux-arm64-musl" "13.4.19" - "@next/swc-linux-x64-gnu" "13.4.19" - "@next/swc-linux-x64-musl" "13.4.19" - "@next/swc-win32-arm64-msvc" "13.4.19" - "@next/swc-win32-ia32-msvc" "13.4.19" - "@next/swc-win32-x64-msvc" "13.4.19" + "@next/swc-darwin-arm64" "13.5.2" + "@next/swc-darwin-x64" "13.5.2" + "@next/swc-linux-arm64-gnu" "13.5.2" + "@next/swc-linux-arm64-musl" "13.5.2" + "@next/swc-linux-x64-gnu" "13.5.2" + "@next/swc-linux-x64-musl" "13.5.2" + "@next/swc-win32-arm64-msvc" "13.5.2" + "@next/swc-win32-ia32-msvc" "13.5.2" + "@next/swc-win32-x64-msvc" "13.5.2" nice-try@^1.0.4: version "1.0.5" @@ -6493,9 +6710,9 @@ no-case@^3.0.4: tslib "^2.0.3" node-abi@^3.3.0: - version "3.45.0" - resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-3.45.0.tgz#f568f163a3bfca5aacfce1fbeee1fa2cc98441f5" - integrity sha512-iwXuFrMAcFVi/ZoZiqq8BzAdsLw9kxDfTC0HMyjXfSL/6CSDAGD5UmR7azrAgWV1zKYq7dUUMj4owusBWKLsiQ== + version "3.47.0" + resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-3.47.0.tgz#6cbfa2916805ae25c2b7156ca640131632eb05e8" + integrity sha512-2s6B2CWZM//kPgwnuI0KrYwNjfdByE25zvAaEpq9IH4zcNsarH8Ihu/UuX6XMPEogDAxkuUFeZn60pXNHAqn3A== dependencies: semver "^7.3.5" @@ -6504,20 +6721,25 @@ node-addon-api@^6.1.0: resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-6.1.0.tgz#ac8470034e58e67d0c6f1204a18ae6995d9c0d76" integrity sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA== +node-addon-api@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-7.0.0.tgz#8136add2f510997b3b94814f4af1cce0b0e3962e" + integrity sha512-vgbBJTS4m5/KkE16t5Ly0WW9hz46swAstv0hYYwMtbG7AznRhNyfLRe8HZAiWIpcHzoO7HxhLuBQj9rJ/Ho0ZA== + node-domexception@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== -node-fetch-native@^1.1.1, node-fetch-native@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/node-fetch-native/-/node-fetch-native-1.2.0.tgz#13ec6df98f33168958dbfb6945f10aedf42e7ea8" - integrity sha512-5IAMBTl9p6PaAjYCnMv5FmqIF6GcZnawAVnzaCG0rX2aYZJ4CxEkZNtVPuTRug7fL7wyM5BQYTlAzcyMPi6oTQ== +node-fetch-native@^1.2.0, node-fetch-native@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/node-fetch-native/-/node-fetch-native-1.4.0.tgz#fbe8ac033cb6aa44bd106b5e4fd2b6277ba70fa1" + integrity sha512-F5kfEj95kX8tkDhUCYdV8dg3/8Olx/94zB8+ZNthFs6Bz31UpUi8Xh40TN3thLwXgrwXry1pEg9lJ++tLWTcqA== node-fetch@^2.0.0, node-fetch@^2.6.6: - version "2.6.12" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.12.tgz#02eb8e22074018e3d5a83016649d04df0e348fba" - integrity sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g== + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== dependencies: whatwg-url "^5.0.0" @@ -6649,22 +6871,22 @@ object.entries@^1.1.6: es-abstract "^1.20.4" object.fromentries@^2.0.6: - version "2.0.6" - resolved "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.6.tgz" - integrity sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" - -object.groupby@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/object.groupby/-/object.groupby-1.0.0.tgz#cb29259cf90f37e7bac6437686c1ea8c916d12a9" - integrity sha512-70MWG6NfRH9GnbZOikuhPPYzpUpof9iW2J9E4dW7FXTqPNb6rllE6u39SKwwiNh8lCwX3DDb5OgcKGiEBrTTyw== + version "2.0.7" + resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.7.tgz#71e95f441e9a0ea6baf682ecaaf37fa2a8d7e616" + integrity sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA== dependencies: call-bind "^1.0.2" define-properties "^1.2.0" - es-abstract "^1.21.2" + es-abstract "^1.22.1" + +object.groupby@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object.groupby/-/object.groupby-1.0.1.tgz#d41d9f3c8d6c778d9cbac86b4ee9f5af103152ee" + integrity sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" get-intrinsic "^1.2.1" object.hasown@^1.1.2: @@ -6676,22 +6898,22 @@ object.hasown@^1.1.2: es-abstract "^1.20.4" object.values@^1.1.6: - version "1.1.6" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.6.tgz#4abbaa71eba47d63589d402856f908243eea9b1d" - integrity sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw== + version "1.1.7" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.7.tgz#617ed13272e7e1071b43973aa1655d9291b8442a" + integrity sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng== dependencies: call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" + define-properties "^1.2.0" + es-abstract "^1.22.1" ofetch@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ofetch/-/ofetch-1.1.1.tgz#a0e5117500f4ac02e2c61ec1bb754bc54d5ba44d" - integrity sha512-SSMoktrp9SNLi20BWfB/BnnKcL0RDigXThD/mZBeQxkIRv1xrd9183MtLdsqRYLYSqW0eTr5t8w8MqjNhvoOQQ== + version "1.3.3" + resolved "https://registry.yarnpkg.com/ofetch/-/ofetch-1.3.3.tgz#588cb806a28e5c66c2c47dd8994f9059a036d8c0" + integrity sha512-s1ZCMmQWXy4b5K/TW9i/DtiN8Ku+xCiHcjQ6/J/nDdssirrQNOoB165Zu8EqLMA2lln1JUth9a0aW9Ap2ctrUg== dependencies: - destr "^2.0.0" - node-fetch-native "^1.2.0" - ufo "^1.1.2" + destr "^2.0.1" + node-fetch-native "^1.4.0" + ufo "^1.3.0" once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" @@ -7402,9 +7624,9 @@ postcss-resolve-nested-selector@^0.1.1: integrity sha512-HvExULSwLqHLgUy1rl3ANIqCsvMS0WHss2UOsXhXnQaZ9VCc2oBvIpXrl00IUFT5ZDITME0o6oiXeiHr2SAIfw== postcss-rtlcss@^4.0.1: - version "4.0.6" - resolved "https://registry.npmjs.org/postcss-rtlcss/-/postcss-rtlcss-4.0.6.tgz" - integrity sha512-YNm6g2Y7Gngqtrpq3GC7cUkzH5Gq7aB+Lw9MSgF9s2ro1BDY7W4zqnd15g2ueatUUpSTg2/F5KDjQoTdjhbAKg== + version "4.0.8" + resolved "https://registry.yarnpkg.com/postcss-rtlcss/-/postcss-rtlcss-4.0.8.tgz#d5e2923dcee7bec54e9ab0db7357b0bc3f6a8ae3" + integrity sha512-CR2sY889PHnX6K8rjW9FG4Qvm9UJsIekDakMtEYGH3zgFp9XADMeaKcA0hPOmkClNh0jWbkaPBm0jZ6fHmqkJQ== dependencies: rtlcss "4.1.0" @@ -7474,10 +7696,10 @@ postcss@^8.1.10: picocolors "^1.0.0" source-map-js "^1.0.2" -postcss@^8.4.21, postcss@^8.4.25: - version "8.4.27" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.27.tgz#234d7e4b72e34ba5a92c29636734349e0d9c3057" - integrity sha512-gY/ACJtJPSmUFPDCHtX78+01fHa64FaU4zaaWfuh1MhGJISufJAH4cun6k/8fwsHYeK4UQmENQK+tRLCFJE8JQ== +postcss@^8.4.21, postcss@^8.4.27: + version "8.4.30" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.30.tgz#0e0648d551a606ef2192a26da4cabafcc09c1aa7" + integrity sha512-7ZEao1g4kd68l97aWG/etQKPKq07us0ieSZ2TnFDk11i0ZfDW2AwKHYU8qv4MZKqN2fdBfg+7q0ES06UA73C1g== dependencies: nanoid "^3.3.6" picocolors "^1.0.0" @@ -7523,12 +7745,12 @@ pretty-bytes@^5.6.0: resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb" integrity sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg== -prisma@5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/prisma/-/prisma-5.2.0.tgz#a302dc2635cdec1d22d552ece837fb29a03563b9" - integrity sha512-FfFlpjVCkZwrqxDnP4smlNYSH1so+CbfjgdpioFzGGqlQAEm6VHAYSzV7jJgC3ebtY9dNOhDMS2+4/1DDSM7bQ== +prisma@5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/prisma/-/prisma-5.3.1.tgz#a0932c1c1a5ed4ff449d064b193d9c7e94e8bf77" + integrity sha512-Wp2msQIlMPHe+5k5Od6xnsI/WNG7UJGgFUJgqv/ygc7kOECZapcSz/iU4NIEzISs3H1W9sFLjAPbg/gOqqtB7A== dependencies: - "@prisma/engines" "5.2.0" + "@prisma/engines" "5.3.1" promise.series@^0.2.0: version "0.2.0" @@ -7615,10 +7837,10 @@ quick-lru@^5.1.1: resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932" integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== -radix3@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/radix3/-/radix3-1.0.1.tgz#de0ac16234f8a63288645854a54fc26e45a4a8eb" - integrity sha512-y+AcwZ3HcUIGc9zGsNVf5+BY/LxL+z+4h4J3/pp8jxSmy1STaCocPS3qrj4tA5ehUSzqtqK+0Aygvz/r/8vy4g== +radix3@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/radix3/-/radix3-1.1.0.tgz#9745df67a49c522e94a33d0a93cf743f104b6e0d" + integrity sha512-pNsHDxbGORSvuSScqNJ+3Km6QAVqk8CfsCBIEoDgpqLrkD2f3QM4I7d1ozJJ172OmIcoUcerZaNWqtLkRXTV3A== raf-schd@^4.0.2: version "4.0.3" @@ -7642,10 +7864,10 @@ rc@^1.2.7: minimist "^1.2.0" strip-json-comments "~2.0.1" -react-basics@^0.98.0: - version "0.98.0" - resolved "https://registry.yarnpkg.com/react-basics/-/react-basics-0.98.0.tgz#b207bedbd9dac749d28ea6de2197a0efe648b78c" - integrity sha512-ebUigu+s6Iusq14EZTFTTUzdDPYFQEZjeD4feeq3o7dE+ndOVnajEdQ2va/x6CsRBUsWgjLJipfQi0XIrxYupA== +react-basics@^0.100.0: + version "0.100.0" + resolved "https://registry.yarnpkg.com/react-basics/-/react-basics-0.100.0.tgz#14a36769af89f3e01641997f897e4073f16f5035" + integrity sha512-ET6DX/FYAcjGRauBE4jwqwVpd/hKmA2Nu/fi1dakwsv17hkyV5FEAhdWhQAxJX3VnaCH//QysN8+ae12KuNA9g== dependencies: classnames "^2.3.1" date-fns "^2.29.3" @@ -7675,9 +7897,9 @@ react-dom@^18.2.0: scheduler "^0.23.0" react-error-boundary@^4.0.4: - version "4.0.10" - resolved "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-4.0.10.tgz" - integrity sha512-pvVKdi77j2OoPHo+p3rorgE43OjDWiqFkaqkJz8sJKK6uf/u8xtzuaVfj5qJ2JnDLIgF1De3zY5AJDijp+LVPA== + version "4.0.11" + resolved "https://registry.yarnpkg.com/react-error-boundary/-/react-error-boundary-4.0.11.tgz#36bf44de7746714725a814630282fee83a7c9a1c" + integrity sha512-U13ul67aP5DOSPNSCWQ/eO0AQEYzEFkVljULQIjMV0KlffTAhxuDoBKdO0pb/JZ8mDhMKFZ9NZi0BmLGUiNphw== dependencies: "@babel/runtime" "^7.12.5" @@ -7926,9 +8148,14 @@ regenerate@^1.4.0, regenerate@^1.4.2: regenerator-runtime@^0.13.10, regenerator-runtime@^0.13.11: version "0.13.11" - resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== +regenerator-runtime@^0.14.0: + version "0.14.0" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz#5e19d68eb12d486f797e15a3c6a918f7cec5eb45" + integrity sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA== + regenerator-transform@^0.15.1: version "0.15.1" resolved "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.1.tgz" @@ -7941,7 +8168,7 @@ regexp-tree@^0.1.24: resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.27.tgz#2198f0ef54518ffa743fe74d983b56ffd631b6cd" integrity sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA== -regexp.prototype.flags@^1.4.3, regexp.prototype.flags@^1.5.0: +regexp.prototype.flags@^1.4.3: version "1.5.0" resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz#fe7ce25e7e4cca8db37b6634c8a2c7009199b9cb" integrity sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA== @@ -7950,6 +8177,15 @@ regexp.prototype.flags@^1.4.3, regexp.prototype.flags@^1.5.0: define-properties "^1.2.0" functions-have-names "^1.2.3" +regexp.prototype.flags@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz#90ce989138db209f81492edd734183ce99f9677e" + integrity sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + set-function-name "^2.0.0" + regexpu-core@4.5.4: version "4.5.4" resolved "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.5.4.tgz" @@ -8056,7 +8292,7 @@ resolve-from@^5.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== -resolve@^1.1.7, resolve@^1.10.0, resolve@^1.14.2, resolve@^1.19.0, resolve@^1.22.0, resolve@^1.22.1: +resolve@^1.1.7, resolve@^1.10.0, resolve@^1.14.2, resolve@^1.19.0, resolve@^1.22.0: version "1.22.2" resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz" integrity sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g== @@ -8065,12 +8301,12 @@ resolve@^1.1.7, resolve@^1.10.0, resolve@^1.14.2, resolve@^1.19.0, resolve@^1.22 path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" -resolve@^1.22.3: - version "1.22.3" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.3.tgz#4b4055349ffb962600972da1fdc33c46a4eb3283" - integrity sha512-P8ur/gp/AmbEzjr729bZnLjXK5Z+4P0zhIJgBgzqRih7hL7BOukHGtSTA3ACMY467GRFz3duQsi0bDZdR7DKdw== +resolve@^1.22.1, resolve@^1.22.4: + version "1.22.6" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.6.tgz#dd209739eca3aef739c626fea1b4f3c506195362" + integrity sha512-njhxM7mV12JfufShqGy3Rz8j11RPdLy4xi15UurGJeoHLfJpVXKdh3ueuOqbYUcDZnffr6X739JBo5LzyahEsw== dependencies: - is-core-module "^2.12.0" + is-core-module "^2.13.0" path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" @@ -8109,9 +8345,9 @@ rimraf@^3.0.0, rimraf@^3.0.2: glob "^7.1.3" rollup-plugin-copy@^3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/rollup-plugin-copy/-/rollup-plugin-copy-3.4.0.tgz#f1228a3ffb66ffad8606e2f3fb7ff23141ed3286" - integrity sha512-rGUmYYsYsceRJRqLVlE9FivJMxJ7X6jDlP79fmFkL8sJs7VVMSVyA2yfyL+PGyO/vJs4A87hwhgVfz61njI+uQ== + version "3.5.0" + resolved "https://registry.yarnpkg.com/rollup-plugin-copy/-/rollup-plugin-copy-3.5.0.tgz#7ffa2a7a8303e143876fa64fb5eed9022d304eeb" + integrity sha512-wI8D5dvYovRMx/YYKtUNt3Yxaw4ORC9xo6Gt9t22kveWz1enG9QrhVlagzwrxSC455xD1dHMKhIJkbsQ7d48BA== dependencies: "@types/fs-extra" "^8.0.1" colorette "^1.1.0" @@ -8188,15 +8424,15 @@ rollup-pluginutils@^2.8.2: estree-walker "^0.6.1" rollup@^3.28.0: - version "3.28.0" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-3.28.0.tgz#a3c70004b01934760c0cb8df717c7a1d932389a2" - integrity sha512-d7zhvo1OUY2SXSM6pfNjgD5+d0Nz87CUp4mt8l/GgVP3oBsPwzNvSzyu1me6BSG9JIgWNTVcafIXBIyM8yQ3yw== + version "3.29.2" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-3.29.2.tgz#cbc76cd5b03b9f9e93be991d23a1dff9c6d5b740" + integrity sha512-CJouHoZ27v6siztc21eEQGo0kIcE5D1gVPA571ez0mMYb25LGYGKnVNXpEj5MGlepmDWGXNjDB5q7uNiPHC11A== optionalDependencies: fsevents "~2.3.2" rtlcss@4.1.0: version "4.1.0" - resolved "https://registry.npmjs.org/rtlcss/-/rtlcss-4.1.0.tgz" + resolved "https://registry.yarnpkg.com/rtlcss/-/rtlcss-4.1.0.tgz#f69b78d9752c970ddfe2aa590896f44353ab1c98" integrity sha512-W+N4hh0nVqVrrn3mRkHakxpB+c9cQ4CRT67O39kgA+1DjyhrdsqyCqIuHXyvWaXn4/835n+oX3fYJCi4+G/06A== dependencies: escalade "^3.1.1" @@ -8218,13 +8454,13 @@ rxjs@^7.5.1: dependencies: tslib "^2.1.0" -safe-array-concat@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.0.0.tgz#2064223cba3c08d2ee05148eedbc563cd6d84060" - integrity sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ== +safe-array-concat@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.0.1.tgz#91686a63ce3adbea14d61b14c99572a8ff84754c" + integrity sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q== dependencies: call-bind "^1.0.2" - get-intrinsic "^1.2.0" + get-intrinsic "^1.2.1" has-symbols "^1.0.3" isarray "^2.0.5" @@ -8319,10 +8555,19 @@ serialize-javascript@^4.0.0: dependencies: randombytes "^2.1.0" -sharp@^0.32.1: - version "0.32.4" - resolved "https://registry.yarnpkg.com/sharp/-/sharp-0.32.4.tgz#0354653b7924f2520b2264ac9bcd10a58bf411b6" - integrity sha512-exUnZewqVZC6UXqXuQ8fyJJv0M968feBi04jb9GcUHrWtkRoAKnbJt8IfwT4NJs7FskArbJ14JAFGVuooszoGg== +set-function-name@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.1.tgz#12ce38b7954310b9f61faa12701620a0c882793a" + integrity sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA== + dependencies: + define-data-property "^1.0.1" + functions-have-names "^1.2.3" + has-property-descriptors "^1.0.0" + +sharp@^0.32.5: + version "0.32.6" + resolved "https://registry.yarnpkg.com/sharp/-/sharp-0.32.6.tgz#6ad30c0b7cd910df65d5f355f774aa4fce45732a" + integrity sha512-KyLTWwgcR9Oe4d9HwCwNM2l7+J0dUQwn/yf7S0EnTtb0eVS4RxO0eUSvxPtzT4F3SY+C4K6fqdv/DO27sJ/v/w== dependencies: color "^4.2.3" detect-libc "^2.0.2" @@ -8377,9 +8622,9 @@ signal-exit@^3.0.2, signal-exit@^3.0.3: integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== signal-exit@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.0.2.tgz#ff55bb1d9ff2114c13b400688fa544ac63c36967" - integrity sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q== + version "4.1.0" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" + integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== simple-concat@^1.0.0: version "1.0.1" @@ -8495,9 +8740,9 @@ spdx-expression-parse@^3.0.0: spdx-license-ids "^3.0.0" spdx-license-ids@^3.0.0: - version "3.0.13" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz#7189a474c46f8d47c7b0da4b987bb45e908bd2d5" - integrity sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w== + version "3.0.15" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.15.tgz#142460aabaca062bc7cd4cc87b7d50725ed6a4ba" + integrity sha512-lpT8hSQp9jAKp9mhtBU4Xjon8LPGBvLIuBiSVhMEtmLecTh2mO0tlqrAMp47tBXzMr13NJMQ2lf7RpQGLJ3HsQ== sprintf-js@~1.0.2: version "1.0.3" @@ -8529,6 +8774,11 @@ standard-as-callback@^2.1.0: resolved "https://registry.yarnpkg.com/standard-as-callback/-/standard-as-callback-2.1.0.tgz#8953fc05359868a77b5b9739a665c5977bb7df45" integrity sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A== +std-env@^3.4.3: + version "3.4.3" + resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.4.3.tgz#326f11db518db751c83fd58574f449b7c3060910" + integrity sha512-f9aPhy8fYBuMN+sNfakZV18U39PbalgjXG3lLB9WkaYTxijru61wb57V9wxxNthXM5Sd88ETBWi29qLAsHO52Q== + stream2asynciter@1.0.3: version "1.0.3" resolved "https://registry.npmjs.org/stream2asynciter/-/stream2asynciter-1.0.3.tgz" @@ -8540,9 +8790,9 @@ streamsearch@^1.1.0: integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg== streamx@^2.15.0: - version "2.15.0" - resolved "https://registry.yarnpkg.com/streamx/-/streamx-2.15.0.tgz#f58c92e6f726b5390dcabd6dd9094d29a854d698" - integrity sha512-HcxY6ncGjjklGs1xsP1aR71INYcsXFJet5CU1CHqihQ2J5nOsbd4OjgjHO42w/4QNv9gZb3BueV+Vxok5pLEXg== + version "2.15.1" + resolved "https://registry.yarnpkg.com/streamx/-/streamx-2.15.1.tgz#396ad286d8bc3eeef8f5cea3f029e81237c024c6" + integrity sha512-fQMzy2O/Q47rgwErk/eGeLu/roaFWV0jVsogDmrszM9uIw8L5OA+t+V93MgYlufNptfjmYR1tOMWhei/Eh7TQA== dependencies: fast-fifo "^1.1.0" queue-tick "^1.0.1" @@ -8589,32 +8839,32 @@ string.prototype.padend@^3.0.0: define-properties "^1.1.3" es-abstract "^1.19.1" -string.prototype.trim@^1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz#a68352740859f6893f14ce3ef1bb3037f7a90533" - integrity sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg== +string.prototype.trim@^1.2.8: + version "1.2.8" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz#f9ac6f8af4bd55ddfa8895e6aea92a96395393bd" + integrity sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ== dependencies: call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" + define-properties "^1.2.0" + es-abstract "^1.22.1" -string.prototype.trimend@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz#c4a27fa026d979d79c04f17397f250a462944533" - integrity sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ== +string.prototype.trimend@^1.0.6, string.prototype.trimend@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz#1bb3afc5008661d73e2dc015cd4853732d6c471e" + integrity sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA== dependencies: call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" + define-properties "^1.2.0" + es-abstract "^1.22.1" -string.prototype.trimstart@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz#e90ab66aa8e4007d92ef591bbf3cd422c56bdcf4" - integrity sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA== +string.prototype.trimstart@^1.0.6, string.prototype.trimstart@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz#d4cdb44b83a4737ffbac2d406e405d43d0184298" + integrity sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg== dependencies: call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" + define-properties "^1.2.0" + es-abstract "^1.22.1" string_decoder@^1.1.1: version "1.3.0" @@ -8731,13 +8981,13 @@ stylelint-config-recommended@^9.0.0: postcss-value-parser "^4.2.0" stylelint@^15.10.1: - version "15.10.2" - resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-15.10.2.tgz#0ee5a8371d3a2e1ff27fefd48309d3ddef7c3405" - integrity sha512-UxqSb3hB74g4DTO45QhUHkJMjKKU//lNUAOWyvPBVPZbCknJ5HjOWWZo+UDuhHa9FLeVdHBZXxu43eXkjyIPWg== + version "15.10.3" + resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-15.10.3.tgz#995e4512fdad450fb83e13f3472001f6edb6469c" + integrity sha512-aBQMMxYvFzJJwkmg+BUUg3YfPyeuCuKo2f+LOw7yYbU8AZMblibwzp9OV4srHVeQldxvSFdz0/Xu8blq2AesiA== dependencies: - "@csstools/css-parser-algorithms" "^2.3.0" - "@csstools/css-tokenizer" "^2.1.1" - "@csstools/media-query-list-parser" "^2.1.2" + "@csstools/css-parser-algorithms" "^2.3.1" + "@csstools/css-tokenizer" "^2.2.0" + "@csstools/media-query-list-parser" "^2.1.4" "@csstools/selector-specificity" "^3.0.0" balanced-match "^2.0.0" colord "^2.9.3" @@ -8745,7 +8995,7 @@ stylelint@^15.10.1: css-functions-list "^3.2.0" css-tree "^2.3.1" debug "^4.3.4" - fast-glob "^3.3.0" + fast-glob "^3.3.1" fastest-levenshtein "^1.0.16" file-entry-cache "^6.0.1" global-modules "^2.0.0" @@ -8756,13 +9006,13 @@ stylelint@^15.10.1: import-lazy "^4.0.0" imurmurhash "^0.1.4" is-plain-object "^5.0.0" - known-css-properties "^0.27.0" + known-css-properties "^0.28.0" mathml-tag-names "^2.1.3" meow "^10.1.5" micromatch "^4.0.5" normalize-path "^3.0.0" picocolors "^1.0.0" - postcss "^8.4.25" + postcss "^8.4.27" postcss-resolve-nested-selector "^0.1.1" postcss-safe-parser "^6.0.0" postcss-selector-parser "^6.0.13" @@ -8896,9 +9146,9 @@ tar-stream@^3.1.5: streamx "^2.15.0" tar@^6.1.2: - version "6.1.15" - resolved "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz" - integrity sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A== + version "6.2.0" + resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.0.tgz#b14ce49a79cb1cd23bc9b016302dea5474493f73" + integrity sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ== dependencies: chownr "^2.0.0" fs-minipass "^2.0.0" @@ -9167,14 +9417,14 @@ typescript@^4.0, typescript@^4.5: integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== typescript@^5.1.6: - version "5.1.6" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.1.6.tgz#02f8ac202b6dad2c0dd5e0913745b47a37998274" - integrity sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA== + version "5.2.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.2.2.tgz#5ebb5e5a5b75f085f22bc3f8460fba308310fa78" + integrity sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w== -ufo@^1.0.0, ufo@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/ufo/-/ufo-1.1.2.tgz#d0d9e0fa09dece0c31ffd57bd363f030a35cfe76" - integrity sha512-TrY6DsjTQQgyS3E3dBaOXf0TpPD8u9FVrVYmKVegJuFw51n/YB9XPt+U6ydzFG5ZIN7+DIjPbNmXoBj9esYhgQ== +ufo@^1.0.0, ufo@^1.2.0, ufo@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/ufo/-/ufo-1.3.0.tgz#c92f8ac209daff607c57bbd75029e190930a0019" + integrity sha512-bRn3CsoojyNStCZe0BG0Mt4Nr/4KF+rhFlnNXybgqt5pXHNFRlqinSoQaTrGyzE4X8aHplSb+TorH+COin9Yxw== unbox-primitive@^1.0.2: version "1.0.2" @@ -9191,6 +9441,17 @@ uncrypto@^0.1.3: resolved "https://registry.yarnpkg.com/uncrypto/-/uncrypto-0.1.3.tgz#e1288d609226f2d02d8d69ee861fa20d8348ef2b" integrity sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q== +unenv@^1.7.4: + version "1.7.4" + resolved "https://registry.yarnpkg.com/unenv/-/unenv-1.7.4.tgz#a0e5a78de2c7c3c4563c06ba9763c96c59db3333" + integrity sha512-fjYsXYi30It0YCQYqLOcT6fHfMXsBr2hw9XC7ycf8rTG7Xxpe3ZssiqUnD0khrjiZEmkBXWLwm42yCSCH46fMw== + dependencies: + consola "^3.2.3" + defu "^6.1.2" + mime "^3.0.0" + node-fetch-native "^1.4.0" + pathe "^1.1.1" + unicode-canonical-property-names-ecmascript@^1.0.4: version "1.0.4" resolved "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz" @@ -9253,21 +9514,30 @@ universalify@^2.0.0: integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== unstorage@^1.0.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/unstorage/-/unstorage-1.8.0.tgz#fa90a5a82c35183257acc3f0461fd982f42dfc9a" - integrity sha512-Wl6a0fYIIPx8yWIHAVNzsNRcIpagVnBV05UXeIFCNqPZ5tu0w0MPE+eTjpRe/yxCD60K7qX55K5Px/PeKvNntw== + version "1.9.0" + resolved "https://registry.yarnpkg.com/unstorage/-/unstorage-1.9.0.tgz#0c1977f4e769a48344339ac97ec3f2feea94d43d" + integrity sha512-VpD8ZEYc/le8DZCrny3bnqKE4ZjioQxBRnWE+j5sGNvziPjeDlaS1NaFFHzl/kkXaO3r7UaF8MGQrs14+1B4pQ== dependencies: anymatch "^3.1.3" chokidar "^3.5.3" - destr "^2.0.0" + destr "^2.0.1" h3 "^1.7.1" ioredis "^5.3.2" - listhen "^1.0.4" + listhen "^1.2.2" lru-cache "^10.0.0" mri "^1.2.0" node-fetch-native "^1.2.0" ofetch "^1.1.1" - ufo "^1.1.2" + ufo "^1.2.0" + +untun@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/untun/-/untun-0.1.2.tgz#fa42a62ae24c1c5c6f3209692a2b0e1f573f1353" + integrity sha512-wLAMWvxfqyTiBODA1lg3IXHQtjggYLeTK7RnSfqtOXixWJ3bAa2kK/HHmOOg19upteqO3muLvN6O/icbyQY33Q== + dependencies: + citty "^0.1.3" + consola "^3.2.3" + pathe "^1.1.1" update-browserslist-db@^1.0.11: version "1.0.11" @@ -9277,6 +9547,11 @@ update-browserslist-db@^1.0.11: escalade "^3.1.1" picocolors "^1.0.0" +uqr@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/uqr/-/uqr-0.1.2.tgz#5c6cd5dcff9581f9bb35b982cb89e2c483a41d7d" + integrity sha512-MJu7ypHq6QasgF5YRTjqscSzQp/W11zoUk6kvmlH+fmWEs63Y0Eib13hYFwAzagRJcVY8WVnlV+eBDUGMJ5IbA== + uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" @@ -9284,6 +9559,11 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" +urlpattern-polyfill@8.0.2: + version "8.0.2" + resolved "https://registry.yarnpkg.com/urlpattern-polyfill/-/urlpattern-polyfill-8.0.2.tgz#99f096e35eff8bf4b5a2aa7d58a1523d6ebc7ce5" + integrity sha512-Qp95D4TPJl1kC9SKigDcqgyM2VDVO4RiJc2d4qe5GrYm+zbIQCWWKAFaJNQ4BhdFeDGwBmAxqJBwWSJDb9T3BQ== + use-memo-one@^1.1.1: version "1.1.3" resolved "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.3.tgz" @@ -9305,9 +9585,9 @@ uuid@3.4.0, uuid@^3.3.2: integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== uuid@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.0.tgz#592f550650024a38ceb0c562f2f6aa435761efb5" - integrity sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg== + version "9.0.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30" + integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA== v8-compile-cache-lib@^3.0.1: version "3.0.1" @@ -9384,7 +9664,7 @@ which-boxed-primitive@^1.0.2: is-string "^1.0.5" is-symbol "^1.0.3" -which-typed-array@^1.1.10, which-typed-array@^1.1.11, which-typed-array@^1.1.9: +which-typed-array@^1.1.11, which-typed-array@^1.1.9: version "1.1.11" resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.11.tgz#99d691f23c72aab6768680805a271b69761ed61a" integrity sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew== @@ -9527,8 +9807,8 @@ zod@3.21.4: integrity sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw== zustand@^4.3.8: - version "4.3.9" - resolved "https://registry.yarnpkg.com/zustand/-/zustand-4.3.9.tgz#a7d4332bbd75dfd25c6848180b3df1407217f2ad" - integrity sha512-Tat5r8jOMG1Vcsj8uldMyqYKC5IZvQif8zetmLHs9WoZlntTHmIoNM8TpLRY31ExncuUvUOXehd0kvahkuHjDw== + version "4.4.1" + resolved "https://registry.yarnpkg.com/zustand/-/zustand-4.4.1.tgz#0cd3a3e4756f21811bd956418fdc686877e8b3b0" + integrity sha512-QCPfstAS4EBiTQzlaGP1gmorkh/UL1Leaj2tdj+zZCZ/9bm0WS7sI2wnfD5lpOszFqWJ1DcPnGoY8RDL61uokw== dependencies: use-sync-external-store "1.2.0" From 55487ca72528aad931facd68f09e6525af00351b Mon Sep 17 00:00:00 2001 From: Francis Cao Date: Thu, 21 Sep 2023 13:51:16 -0700 Subject: [PATCH 108/113] Fix search on settings table from dissappearing --- src/components/common/SettingsTable.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/common/SettingsTable.js b/src/components/common/SettingsTable.js index a74581cae..701dbe13b 100644 --- a/src/components/common/SettingsTable.js +++ b/src/components/common/SettingsTable.js @@ -36,7 +36,7 @@ export function SettingsTable({ return ( <> - {showSearch && !!value.length && ( + {showSearch && (value.length > 0 || filterValue) && ( Date: Thu, 21 Sep 2023 16:30:15 -0700 Subject: [PATCH 109/113] Update redis package. --- package.json | 2 +- .../pages/settings/websites/TrackingCode.js | 6 ++-- src/lib/cache.ts | 28 +++++++++---------- src/lib/middleware.ts | 2 +- src/pages/api/auth/login.ts | 5 ++-- src/pages/api/auth/logout.ts | 2 +- src/pages/api/auth/sso.ts | 2 +- yarn.lock | 8 +++--- 8 files changed, 26 insertions(+), 29 deletions(-) diff --git a/package.json b/package.json index 8350a060f..6617b4557 100644 --- a/package.json +++ b/package.json @@ -65,7 +65,7 @@ "@prisma/client": "5.3.1", "@tanstack/react-query": "^4.33.0", "@umami/prisma-client": "^0.2.0", - "@umami/redis-client": "^0.5.0", + "@umami/redis-client": "^0.15.0", "chalk": "^4.1.1", "chart.js": "^4.2.1", "chartjs-adapter-date-fns": "^3.0.0", diff --git a/src/components/pages/settings/websites/TrackingCode.js b/src/components/pages/settings/websites/TrackingCode.js index a666476d9..03dd6a1d8 100644 --- a/src/components/pages/settings/websites/TrackingCode.js +++ b/src/components/pages/settings/websites/TrackingCode.js @@ -3,7 +3,7 @@ import useMessages from 'components/hooks/useMessages'; import useConfig from 'components/hooks/useConfig'; import { useRouter } from 'next/router'; -export function TrackingCode({ websiteId, analyticsUrl }) { +export function TrackingCode({ websiteId, baseUrl }) { const { formatMessage, messages } = useMessages(); const { basePath } = useRouter(); const config = useConfig(); @@ -13,9 +13,7 @@ export function TrackingCode({ websiteId, analyticsUrl }) { const url = trackerScriptName?.startsWith('http') ? trackerScriptName - : `${ - analyticsUrl || process.env.analyticsUrl || location.origin - }${basePath}/${trackerScriptName}`; + : `${baseUrl || location.origin}${basePath}/${trackerScriptName}`; const code = ``; diff --git a/src/lib/cache.ts b/src/lib/cache.ts index c54eda2ee..a2e4ea5a9 100644 --- a/src/lib/cache.ts +++ b/src/lib/cache.ts @@ -2,60 +2,58 @@ import { User, Website } from '@prisma/client'; import redis from '@umami/redis-client'; import { getSession, getUserById, getWebsiteById } from '../queries'; -const { fetchObject, storeObject, deleteObject, expire } = redis; - async function fetchWebsite(id): Promise { - return fetchObject(`website:${id}`, () => getWebsiteById(id), 86400); + return redis.fetchObject(`website:${id}`, () => getWebsiteById(id), 86400); } async function storeWebsite(data) { const { id } = data; const key = `website:${id}`; - const obj = await storeObject(key, data); - await expire(key, 86400); + const obj = await redis.storeObject(key, data); + await redis.expire(key, 86400); return obj; } async function deleteWebsite(id) { - return deleteObject(`website:${id}`); + return redis.deleteObject(`website:${id}`); } async function fetchUser(id): Promise { - return fetchObject(`user:${id}`, () => getUserById(id, { includePassword: true }), 86400); + return redis.fetchObject(`user:${id}`, () => getUserById(id, { includePassword: true }), 86400); } async function storeUser(data) { const { id } = data; const key = `user:${id}`; - const obj = await storeObject(key, data); - await expire(key, 86400); + const obj = await redis.storeObject(key, data); + await redis.expire(key, 86400); return obj; } async function deleteUser(id) { - return deleteObject(`user:${id}`); + return redis.deleteObject(`user:${id}`); } async function fetchSession(id) { - return fetchObject(`session:${id}`, () => getSession(id), 86400); + return redis.fetchObject(`session:${id}`, () => getSession(id), 86400); } async function storeSession(data) { const { id } = data; const key = `session:${id}`; - const obj = await storeObject(key, data); - await expire(key, 86400); + const obj = await redis.storeObject(key, data); + await redis.expire(key, 86400); return obj; } async function deleteSession(id) { - return deleteObject(`session:${id}`); + return redis.deleteObject(`session:${id}`); } async function fetchUserBlock(userId: string) { @@ -80,5 +78,5 @@ export default { deleteSession, fetchUserBlock, incrementUserBlock, - enabled: redis.enabled, + enabled: !!redis, }; diff --git a/src/lib/middleware.ts b/src/lib/middleware.ts index 8259677dc..4be958b6b 100644 --- a/src/lib/middleware.ts +++ b/src/lib/middleware.ts @@ -55,7 +55,7 @@ export const useAuth = createMiddleware(async (req, res, next) => { if (isUuid(userId)) { user = await getUserById(userId); - } else if (redis.enabled && authKey) { + } else if (redis && authKey) { user = await redis.get(authKey); } diff --git a/src/pages/api/auth/login.ts b/src/pages/api/auth/login.ts index 47521084b..74661e33e 100644 --- a/src/pages/api/auth/login.ts +++ b/src/pages/api/auth/login.ts @@ -52,17 +52,18 @@ export default async ( const user = await getUserByUsername(username, { includePassword: true }); if (user && checkPassword(password, user.password)) { - if (redis.enabled) { + if (redis) { const token = await setAuthKey(user); return ok(res, { token, user }); } const token = createSecureToken({ userId: user.id }, secret()); + const { id, username, role, createdAt } = user; return ok(res, { token, - user: { id: user.id, username: user.username, role: user.role, createdAt: user.createdAt }, + user: { id, username, role, createdAt }, }); } diff --git a/src/pages/api/auth/logout.ts b/src/pages/api/auth/logout.ts index cbccce8d7..e6222e491 100644 --- a/src/pages/api/auth/logout.ts +++ b/src/pages/api/auth/logout.ts @@ -8,7 +8,7 @@ export default async (req: NextApiRequest, res: NextApiResponse) => { await useAuth(req, res); if (req.method === 'POST') { - if (redis.enabled) { + if (redis) { await redis.del(getAuthToken(req)); } diff --git a/src/pages/api/auth/sso.ts b/src/pages/api/auth/sso.ts index 66cbd8e27..a7992666e 100644 --- a/src/pages/api/auth/sso.ts +++ b/src/pages/api/auth/sso.ts @@ -8,7 +8,7 @@ import { setAuthKey } from 'lib/auth'; export default async (req: NextApiRequestAuth, res: NextApiResponse) => { await useAuth(req, res); - if (redis.enabled && req.auth.user) { + if (redis && req.auth.user) { const token = await setAuthKey(req.auth.user, 86400); return ok(res, { user: req.auth.user, token }); diff --git a/yarn.lock b/yarn.lock index 8687c4326..ecb1a7ebe 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2766,10 +2766,10 @@ dependencies: debug "^4.3.4" -"@umami/redis-client@^0.5.0": - version "0.5.0" - resolved "https://registry.npmjs.org/@umami/redis-client/-/redis-client-0.5.0.tgz" - integrity sha512-x7wx/pMjyg3AAYzgjGOw031bNhyZ81h6tRMAl60RQQI9xlJaJEA1r0TEUrWfFi21gHAvdBLJGYCsvHzpix4LKQ== +"@umami/redis-client@^0.15.0": + version "0.15.0" + resolved "https://registry.yarnpkg.com/@umami/redis-client/-/redis-client-0.15.0.tgz#55e9c4ede28fdd3b6a169378d391a5d2cc039e51" + integrity sha512-+Ei6i4qx9Md4o92Mlzvh9rTgkfllgmSwFu1687DEqFnNrHd+KNVxgNNDiyyCwzfC0t/DAaq7PoOFw4NjJYo9wQ== dependencies: debug "^4.3.4" redis "^4.5.1" From a3bba63b09fff35128e43752a27a483f48ef6a48 Mon Sep 17 00:00:00 2001 From: Brian Cao Date: Thu, 21 Sep 2023 16:45:46 -0700 Subject: [PATCH 110/113] update ignore. --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 32e3ef0b8..050397c90 100644 --- a/.gitignore +++ b/.gitignore @@ -33,7 +33,8 @@ yarn-debug.log* yarn-error.log* # local env files -*.env +.env +.env.* *.dev.yml From a3a24e76c94ac4028265cce1289484dc126265ab Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Thu, 21 Sep 2023 17:30:40 -0700 Subject: [PATCH 111/113] Pass analyticsUrl prop. --- src/components/pages/settings/websites/ShareUrl.js | 7 ++----- src/components/pages/settings/websites/TrackingCode.js | 4 ++-- .../pages/settings/websites/WebsiteSettings.js | 9 ++++++++- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/components/pages/settings/websites/ShareUrl.js b/src/components/pages/settings/websites/ShareUrl.js index a7b7fc2f2..f4569ca38 100644 --- a/src/components/pages/settings/websites/ShareUrl.js +++ b/src/components/pages/settings/websites/ShareUrl.js @@ -16,7 +16,7 @@ import useMessages from 'components/hooks/useMessages'; const generateId = () => getRandomChars(16); -export function ShareUrl({ websiteId, data, onSave }) { +export function ShareUrl({ websiteId, data, analyticsUrl, onSave }) { const { formatMessage, labels, messages } = useMessages(); const { name, shareId } = data; const [id, setId] = useState(shareId); @@ -27,10 +27,7 @@ export function ShareUrl({ websiteId, data, onSave }) { ); const ref = useRef(null); const url = useMemo( - () => - `${process.env.analyticsUrl || location.origin}${basePath}/share/${id}/${encodeURIComponent( - name, - )}`, + () => `${analyticsUrl || location.origin}${basePath}/share/${id}/${encodeURIComponent(name)}`, [id, name, basePath], ); diff --git a/src/components/pages/settings/websites/TrackingCode.js b/src/components/pages/settings/websites/TrackingCode.js index 03dd6a1d8..298cd17aa 100644 --- a/src/components/pages/settings/websites/TrackingCode.js +++ b/src/components/pages/settings/websites/TrackingCode.js @@ -3,7 +3,7 @@ import useMessages from 'components/hooks/useMessages'; import useConfig from 'components/hooks/useConfig'; import { useRouter } from 'next/router'; -export function TrackingCode({ websiteId, baseUrl }) { +export function TrackingCode({ websiteId, analyticsUrl }) { const { formatMessage, messages } = useMessages(); const { basePath } = useRouter(); const config = useConfig(); @@ -13,7 +13,7 @@ export function TrackingCode({ websiteId, baseUrl }) { const url = trackerScriptName?.startsWith('http') ? trackerScriptName - : `${baseUrl || location.origin}${basePath}/${trackerScriptName}`; + : `${analyticsUrl || location.origin}${basePath}/${trackerScriptName}`; const code = ``; diff --git a/src/components/pages/settings/websites/WebsiteSettings.js b/src/components/pages/settings/websites/WebsiteSettings.js index 3cd4185c9..63e898148 100644 --- a/src/components/pages/settings/websites/WebsiteSettings.js +++ b/src/components/pages/settings/websites/WebsiteSettings.js @@ -69,7 +69,14 @@ export function WebsiteSettings({ websiteId, openExternal = false, analyticsUrl )} {tab === 'tracking' && } - {tab === 'share' && } + {tab === 'share' && ( + + )} {tab === 'data' && } ); From 424f3e5323240e13e3705e3783452f8dc9580ccc Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Thu, 21 Sep 2023 18:37:40 -0700 Subject: [PATCH 112/113] Fixed login redirect. --- package.components.json | 2 +- src/components/hooks/useRequireLogin.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package.components.json b/package.components.json index feb3fc2e6..41e72579f 100644 --- a/package.components.json +++ b/package.components.json @@ -1,6 +1,6 @@ { "name": "@umami/components", - "version": "0.11.0", + "version": "0.1.0", "description": "Umami React components.", "author": "Mike Cao ", "license": "MIT", diff --git a/src/components/hooks/useRequireLogin.ts b/src/components/hooks/useRequireLogin.ts index 950bb60ac..d2f540d45 100644 --- a/src/components/hooks/useRequireLogin.ts +++ b/src/components/hooks/useRequireLogin.ts @@ -4,7 +4,7 @@ import useApi from 'components/hooks/useApi'; import useUser from 'components/hooks/useUser'; export function useRequireLogin(handler: (data?: object) => void) { - const router = useRouter(); + const { basePath } = useRouter(); const { get } = useApi(); const { user, setUser } = useUser(); @@ -15,7 +15,7 @@ export function useRequireLogin(handler: (data?: object) => void) { setUser(typeof handler === 'function' ? handler(data) : (data as any)?.user); } catch { - await router.push('/login'); + location.href = `${basePath}/login`; } } From 2ccb8d0a3cdfc5c47e78498e803874fbafe01e78 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Fri, 22 Sep 2023 17:24:15 -0700 Subject: [PATCH 113/113] Bump version v2.7.0. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6617b4557..79960eb23 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "umami", - "version": "2.6.2", + "version": "2.7.0", "description": "A simple, fast, privacy-focused alternative to Google Analytics.", "author": "Mike Cao ", "license": "MIT",