mirror of
https://github.com/umami-software/umami.git
synced 2025-12-06 01:18:00 +01:00
Merge branch 'dev' into seed-sample-data
This commit is contained in:
commit
b08413ebea
580 changed files with 2593 additions and 3703 deletions
|
|
@ -1 +0,0 @@
|
||||||
/src/generated/
|
|
||||||
|
|
@ -1,51 +0,0 @@
|
||||||
{
|
|
||||||
"env": {
|
|
||||||
"browser": true,
|
|
||||||
"es2020": true,
|
|
||||||
"node": true,
|
|
||||||
"jquery": true,
|
|
||||||
"jest": true
|
|
||||||
},
|
|
||||||
"parser": "@typescript-eslint/parser",
|
|
||||||
"parserOptions": {
|
|
||||||
"ecmaFeatures": {
|
|
||||||
"jsx": true
|
|
||||||
},
|
|
||||||
"ecmaVersion": 11,
|
|
||||||
"sourceType": "module"
|
|
||||||
},
|
|
||||||
"extends": [
|
|
||||||
"plugin:@typescript-eslint/eslint-recommended",
|
|
||||||
"plugin:@typescript-eslint/recommended",
|
|
||||||
"eslint:recommended",
|
|
||||||
"plugin:prettier/recommended",
|
|
||||||
"plugin:import/errors",
|
|
||||||
"plugin:import/typescript",
|
|
||||||
"plugin:css-modules/recommended",
|
|
||||||
"plugin:cypress/recommended",
|
|
||||||
"prettier",
|
|
||||||
"next"
|
|
||||||
],
|
|
||||||
"plugins": ["@typescript-eslint", "prettier", "promise", "css-modules", "cypress"],
|
|
||||||
"rules": {
|
|
||||||
"no-console": "error",
|
|
||||||
"react/display-name": "off",
|
|
||||||
"react-hooks/exhaustive-deps": "off",
|
|
||||||
"react/react-in-jsx-scope": "off",
|
|
||||||
"react/prop-types": "off",
|
|
||||||
"import/no-anonymous-default-export": "off",
|
|
||||||
"import/no-named-as-default": "off",
|
|
||||||
"css-modules/no-unused-class": "off",
|
|
||||||
"@next/next/no-img-element": "off",
|
|
||||||
"@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-unused-vars": ["error", { "ignoreRestSiblings": true }],
|
|
||||||
"@typescript-eslint/no-namespace": ["error", { "allowDeclarations": true }],
|
|
||||||
"@typescript-eslint/triple-slash-reference": "off"
|
|
||||||
},
|
|
||||||
"globals": {
|
|
||||||
"React": "writable"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
/public/script.js
|
|
||||||
/src/generated/
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
{
|
|
||||||
"arrowParens": "avoid",
|
|
||||||
"endOfLine": "lf",
|
|
||||||
"printWidth": 100,
|
|
||||||
"singleQuote": true,
|
|
||||||
"trailingComma": "all"
|
|
||||||
}
|
|
||||||
|
|
@ -42,10 +42,7 @@ RUN set -x \
|
||||||
&& apk add --no-cache curl
|
&& apk add --no-cache curl
|
||||||
|
|
||||||
# Script dependencies
|
# Script dependencies
|
||||||
RUN pnpm add npm-run-all dotenv chalk semver prisma@6.18.0 @prisma/adapter-pg@6.18.0
|
RUN pnpm --allow-build='@prisma/engines' add npm-run-all dotenv chalk semver prisma@6.18.0 @prisma/adapter-pg@6.18.0
|
||||||
|
|
||||||
# Permissions for prisma
|
|
||||||
RUN chown -R nextjs:nodejs node_modules/.pnpm/
|
|
||||||
|
|
||||||
COPY --from=builder --chown=nextjs:nodejs /app/public ./public
|
COPY --from=builder --chown=nextjs:nodejs /app/public ./public
|
||||||
COPY --from=builder /app/prisma ./prisma
|
COPY --from=builder /app/prisma ./prisma
|
||||||
|
|
|
||||||
57
biome.json
Normal file
57
biome.json
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://biomejs.dev/schemas/2.3.6/schema.json",
|
||||||
|
"vcs": {
|
||||||
|
"enabled": true,
|
||||||
|
"clientKind": "git",
|
||||||
|
"useIgnoreFile": true
|
||||||
|
},
|
||||||
|
"files": {
|
||||||
|
"includes": ["**", "!!**/dist"]
|
||||||
|
},
|
||||||
|
"formatter": {
|
||||||
|
"enabled": true,
|
||||||
|
"lineWidth": 100,
|
||||||
|
"indentStyle": "space",
|
||||||
|
"indentWidth": 2,
|
||||||
|
"lineEnding": "lf"
|
||||||
|
},
|
||||||
|
"linter": {
|
||||||
|
"enabled": true,
|
||||||
|
"rules": {
|
||||||
|
"recommended": true,
|
||||||
|
"a11y": "off",
|
||||||
|
"correctness": {
|
||||||
|
"useExhaustiveDependencies": "off"
|
||||||
|
},
|
||||||
|
"style": {
|
||||||
|
"noDescendingSpecificity": "off"
|
||||||
|
},
|
||||||
|
"complexity": {
|
||||||
|
"noImportantStyles": "off"
|
||||||
|
},
|
||||||
|
"suspicious": {
|
||||||
|
"noArrayIndexKey": "off",
|
||||||
|
"noExplicitAny": "off",
|
||||||
|
"noImplicitAnyLet": "off"
|
||||||
|
},
|
||||||
|
"performance": {
|
||||||
|
"noImgElement": "off"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"javascript": {
|
||||||
|
"formatter": {
|
||||||
|
"quoteStyle": "single",
|
||||||
|
"trailingCommas": "all",
|
||||||
|
"arrowParentheses": "asNeeded"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"assist": {
|
||||||
|
"enabled": true,
|
||||||
|
"actions": {
|
||||||
|
"source": {
|
||||||
|
"organizeImports": "on"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { NextRequest, NextResponse } from 'next/server';
|
import { type NextRequest, NextResponse } from 'next/server';
|
||||||
|
|
||||||
export const config = {
|
export const config = {
|
||||||
matcher: '/:path*',
|
matcher: '/:path*',
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import 'dotenv/config';
|
import 'dotenv/config';
|
||||||
import pkg from './package.json' assert { type: 'json' };
|
import pkg from './package.json' with { type: 'json' };
|
||||||
|
|
||||||
const TRACKER_SCRIPT = '/script.js';
|
const TRACKER_SCRIPT = '/script.js';
|
||||||
|
|
||||||
|
|
|
||||||
32
package.json
32
package.json
|
|
@ -42,25 +42,19 @@
|
||||||
"download-country-names": "node scripts/download-country-names.js",
|
"download-country-names": "node scripts/download-country-names.js",
|
||||||
"download-language-names": "node scripts/download-language-names.js",
|
"download-language-names": "node scripts/download-language-names.js",
|
||||||
"change-password": "node scripts/change-password.js",
|
"change-password": "node scripts/change-password.js",
|
||||||
"lint": "next lint --quiet",
|
|
||||||
"prepare": "node -e \"if (process.env.NODE_ENV !== 'production'){process.exit(1)} \" || husky install",
|
"prepare": "node -e \"if (process.env.NODE_ENV !== 'production'){process.exit(1)} \" || husky install",
|
||||||
"postbuild": "node scripts/postbuild.js",
|
"postbuild": "node scripts/postbuild.js",
|
||||||
"test": "jest",
|
"test": "jest",
|
||||||
"cypress-open": "cypress open cypress run",
|
"cypress-open": "cypress open cypress run",
|
||||||
"cypress-run": "cypress run cypress run",
|
"cypress-run": "cypress run cypress run",
|
||||||
"seed-data": "tsx scripts/seed-data.ts"
|
"seed-data": "tsx scripts/seed-data.ts"
|
||||||
|
"lint": "biome lint .",
|
||||||
|
"format": "biome format --write .",
|
||||||
|
"check": "biome check --write"
|
||||||
},
|
},
|
||||||
"lint-staged": {
|
"lint-staged": {
|
||||||
"**/*.{js,jsx,ts,tsx}": [
|
"**/*.{js,jsx,ts,tsx,json,css}": [
|
||||||
"prettier --write",
|
"biome check --write --no-errors-on-unmatched --files-ignore-unknown=true"
|
||||||
"eslint"
|
|
||||||
],
|
|
||||||
"**/*.css": [
|
|
||||||
"stylelint --fix",
|
|
||||||
"prettier --write"
|
|
||||||
],
|
|
||||||
"**/*.json": [
|
|
||||||
"prettier --write"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"cacheDirectories": [
|
"cacheDirectories": [
|
||||||
|
|
@ -79,7 +73,7 @@
|
||||||
"@react-spring/web": "^10.0.3",
|
"@react-spring/web": "^10.0.3",
|
||||||
"@svgr/cli": "^8.1.0",
|
"@svgr/cli": "^8.1.0",
|
||||||
"@tanstack/react-query": "^5.90.5",
|
"@tanstack/react-query": "^5.90.5",
|
||||||
"@umami/react-zen": "^0.207.0",
|
"@umami/react-zen": "^0.210.0",
|
||||||
"@umami/redis-client": "^0.29.0",
|
"@umami/redis-client": "^0.29.0",
|
||||||
"bcryptjs": "^3.0.2",
|
"bcryptjs": "^3.0.2",
|
||||||
"chalk": "^5.6.2",
|
"chalk": "^5.6.2",
|
||||||
|
|
@ -96,7 +90,6 @@
|
||||||
"detect-browser": "^5.2.0",
|
"detect-browser": "^5.2.0",
|
||||||
"dotenv": "^17.2.3",
|
"dotenv": "^17.2.3",
|
||||||
"esbuild": "^0.25.11",
|
"esbuild": "^0.25.11",
|
||||||
"eslint-plugin-promise": "^6.1.1",
|
|
||||||
"fs-extra": "^11.3.2",
|
"fs-extra": "^11.3.2",
|
||||||
"immer": "^10.2.0",
|
"immer": "^10.2.0",
|
||||||
"ipaddr.js": "^2.0.1",
|
"ipaddr.js": "^2.0.1",
|
||||||
|
|
@ -133,6 +126,7 @@
|
||||||
"zustand": "^5.0.8"
|
"zustand": "^5.0.8"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@biomejs/biome": "^2.3.6",
|
||||||
"@formatjs/cli": "^4.2.29",
|
"@formatjs/cli": "^4.2.29",
|
||||||
"@netlify/plugin-nextjs": "^5.14.4",
|
"@netlify/plugin-nextjs": "^5.14.4",
|
||||||
"@rollup/plugin-alias": "^5.0.0",
|
"@rollup/plugin-alias": "^5.0.0",
|
||||||
|
|
@ -147,20 +141,9 @@
|
||||||
"@types/react": "^19.2.2",
|
"@types/react": "^19.2.2",
|
||||||
"@types/react-dom": "^19.2.2",
|
"@types/react-dom": "^19.2.2",
|
||||||
"@types/react-window": "^1.8.8",
|
"@types/react-window": "^1.8.8",
|
||||||
"@typescript-eslint/eslint-plugin": "^8.46.2",
|
|
||||||
"@typescript-eslint/parser": "^8.46.2",
|
|
||||||
"babel-plugin-react-compiler": "19.1.0-rc.2",
|
"babel-plugin-react-compiler": "19.1.0-rc.2",
|
||||||
"cross-env": "^10.1.0",
|
"cross-env": "^10.1.0",
|
||||||
"cypress": "^13.6.6",
|
"cypress": "^13.6.6",
|
||||||
"eslint": "^8.33.0",
|
|
||||||
"eslint-config-next": "^14.2.33",
|
|
||||||
"eslint-config-prettier": "^10.1.8",
|
|
||||||
"eslint-import-resolver-alias": "^1.1.2",
|
|
||||||
"eslint-plugin-css-modules": "^2.12.0",
|
|
||||||
"eslint-plugin-cypress": "^2.15.1",
|
|
||||||
"eslint-plugin-import": "^2.32.0",
|
|
||||||
"eslint-plugin-jest": "^27.9.0",
|
|
||||||
"eslint-plugin-prettier": "^5.5.4",
|
|
||||||
"extract-react-intl-messages": "^4.1.1",
|
"extract-react-intl-messages": "^4.1.1",
|
||||||
"husky": "^9.1.7",
|
"husky": "^9.1.7",
|
||||||
"jest": "^29.7.0",
|
"jest": "^29.7.0",
|
||||||
|
|
@ -169,7 +152,6 @@
|
||||||
"postcss-flexbugs-fixes": "^5.0.2",
|
"postcss-flexbugs-fixes": "^5.0.2",
|
||||||
"postcss-import": "^15.1.0",
|
"postcss-import": "^15.1.0",
|
||||||
"postcss-preset-env": "7.8.3",
|
"postcss-preset-env": "7.8.3",
|
||||||
"prettier": "^3.6.2",
|
|
||||||
"prompts": "2.4.2",
|
"prompts": "2.4.2",
|
||||||
"rollup": "^4.52.5",
|
"rollup": "^4.52.5",
|
||||||
"rollup-plugin-copy": "^3.4.0",
|
"rollup-plugin-copy": "^3.4.0",
|
||||||
|
|
|
||||||
2883
pnpm-lock.yaml
generated
2883
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load diff
8
prisma.config.ts
Normal file
8
prisma.config.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
import 'dotenv/config';
|
||||||
|
import { defineConfig, env } from 'prisma/config';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
datasource: {
|
||||||
|
url: env('DATABASE_URL'),
|
||||||
|
},
|
||||||
|
});
|
||||||
33
prisma/migrations/15_boards/migration.sql
Normal file
33
prisma/migrations/15_boards/migration.sql
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "board" (
|
||||||
|
"board_id" UUID NOT NULL,
|
||||||
|
"type" VARCHAR(50) NOT NULL,
|
||||||
|
"name" VARCHAR(200) NOT NULL,
|
||||||
|
"description" VARCHAR(500) NOT NULL,
|
||||||
|
"parameters" JSONB NOT NULL,
|
||||||
|
"slug" VARCHAR(100) NOT NULL,
|
||||||
|
"user_id" UUID,
|
||||||
|
"team_id" UUID,
|
||||||
|
"created_at" TIMESTAMPTZ(6) DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"updated_at" TIMESTAMPTZ(6),
|
||||||
|
|
||||||
|
CONSTRAINT "board_pkey" PRIMARY KEY ("board_id")
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "board_board_id_key" ON "board"("board_id");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "board_slug_key" ON "board"("slug");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE INDEX "board_slug_idx" ON "board"("slug");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE INDEX "board_user_id_idx" ON "board"("user_id");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE INDEX "board_team_id_idx" ON "board"("team_id");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE INDEX "board_created_at_idx" ON "board"("created_at");
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "website_event" ALTER COLUMN "url_path" SET DATA TYPE VARCHAR(1024),
|
||||||
|
ALTER COLUMN "url_query" SET DATA TYPE VARCHAR(1024),
|
||||||
|
ALTER COLUMN "referrer_path" SET DATA TYPE VARCHAR(1024),
|
||||||
|
ALTER COLUMN "referrer_query" SET DATA TYPE VARCHAR(1024),
|
||||||
|
ALTER COLUMN "fbclid" SET DATA TYPE VARCHAR(1024),
|
||||||
|
ALTER COLUMN "gclid" SET DATA TYPE VARCHAR(1024),
|
||||||
|
ALTER COLUMN "li_fat_id" SET DATA TYPE VARCHAR(1024),
|
||||||
|
ALTER COLUMN "msclkid" SET DATA TYPE VARCHAR(1024),
|
||||||
|
ALTER COLUMN "ttclid" SET DATA TYPE VARCHAR(1024),
|
||||||
|
ALTER COLUMN "twclid" SET DATA TYPE VARCHAR(1024),
|
||||||
|
ALTER COLUMN "utm_campaign" SET DATA TYPE VARCHAR(512),
|
||||||
|
ALTER COLUMN "utm_content" SET DATA TYPE VARCHAR(512),
|
||||||
|
ALTER COLUMN "utm_medium" SET DATA TYPE VARCHAR(512),
|
||||||
|
ALTER COLUMN "utm_source" SET DATA TYPE VARCHAR(512),
|
||||||
|
ALTER COLUMN "utm_term" SET DATA TYPE VARCHAR(512);
|
||||||
|
|
@ -27,6 +27,7 @@ model User {
|
||||||
pixels Pixel[] @relation("user")
|
pixels Pixel[] @relation("user")
|
||||||
teams TeamUser[]
|
teams TeamUser[]
|
||||||
reports Report[]
|
reports Report[]
|
||||||
|
boards Board[] @relation("user")
|
||||||
|
|
||||||
@@map("user")
|
@@map("user")
|
||||||
}
|
}
|
||||||
|
|
@ -99,23 +100,23 @@ model WebsiteEvent {
|
||||||
sessionId String @map("session_id") @db.Uuid
|
sessionId String @map("session_id") @db.Uuid
|
||||||
visitId String @map("visit_id") @db.Uuid
|
visitId String @map("visit_id") @db.Uuid
|
||||||
createdAt DateTime? @default(now()) @map("created_at") @db.Timestamptz(6)
|
createdAt DateTime? @default(now()) @map("created_at") @db.Timestamptz(6)
|
||||||
urlPath String @map("url_path") @db.VarChar(500)
|
urlPath String @map("url_path") @db.VarChar(1024)
|
||||||
urlQuery String? @map("url_query") @db.VarChar(500)
|
urlQuery String? @map("url_query") @db.VarChar(1024)
|
||||||
utmSource String? @map("utm_source") @db.VarChar(255)
|
utmSource String? @map("utm_source") @db.VarChar(512)
|
||||||
utmMedium String? @map("utm_medium") @db.VarChar(255)
|
utmMedium String? @map("utm_medium") @db.VarChar(512)
|
||||||
utmCampaign String? @map("utm_campaign") @db.VarChar(255)
|
utmCampaign String? @map("utm_campaign") @db.VarChar(512)
|
||||||
utmContent String? @map("utm_content") @db.VarChar(255)
|
utmContent String? @map("utm_content") @db.VarChar(512)
|
||||||
utmTerm String? @map("utm_term") @db.VarChar(255)
|
utmTerm String? @map("utm_term") @db.VarChar(512)
|
||||||
referrerPath String? @map("referrer_path") @db.VarChar(500)
|
referrerPath String? @map("referrer_path") @db.VarChar(1024)
|
||||||
referrerQuery String? @map("referrer_query") @db.VarChar(500)
|
referrerQuery String? @map("referrer_query") @db.VarChar(1024)
|
||||||
referrerDomain String? @map("referrer_domain") @db.VarChar(500)
|
referrerDomain String? @map("referrer_domain") @db.VarChar(500)
|
||||||
pageTitle String? @map("page_title") @db.VarChar(500)
|
pageTitle String? @map("page_title") @db.VarChar(500)
|
||||||
gclid String? @db.VarChar(255)
|
gclid String? @db.VarChar(1024)
|
||||||
fbclid String? @db.VarChar(255)
|
fbclid String? @db.VarChar(1024)
|
||||||
msclkid String? @db.VarChar(255)
|
msclkid String? @db.VarChar(1024)
|
||||||
ttclid String? @db.VarChar(255)
|
ttclid String? @db.VarChar(1024)
|
||||||
lifatid String? @map("li_fat_id") @db.VarChar(255)
|
lifatid String? @map("li_fat_id") @db.VarChar(1024)
|
||||||
twclid String? @db.VarChar(255)
|
twclid String? @db.VarChar(1024)
|
||||||
eventType Int @default(1) @map("event_type") @db.Integer
|
eventType Int @default(1) @map("event_type") @db.Integer
|
||||||
eventName String? @map("event_name") @db.VarChar(50)
|
eventName String? @map("event_name") @db.VarChar(50)
|
||||||
tag String? @db.VarChar(50)
|
tag String? @db.VarChar(50)
|
||||||
|
|
@ -199,6 +200,7 @@ model Team {
|
||||||
members TeamUser[]
|
members TeamUser[]
|
||||||
links Link[]
|
links Link[]
|
||||||
pixels Pixel[]
|
pixels Pixel[]
|
||||||
|
boards Board[]
|
||||||
|
|
||||||
@@index([accessCode])
|
@@index([accessCode])
|
||||||
@@map("team")
|
@@map("team")
|
||||||
|
|
@ -316,3 +318,25 @@ model Pixel {
|
||||||
@@index([createdAt])
|
@@index([createdAt])
|
||||||
@@map("pixel")
|
@@map("pixel")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
model Board {
|
||||||
|
id String @id() @unique() @map("board_id") @db.Uuid
|
||||||
|
type String @db.VarChar(50)
|
||||||
|
name String @db.VarChar(200)
|
||||||
|
description String @db.VarChar(500)
|
||||||
|
parameters Json
|
||||||
|
slug String @unique() @db.VarChar(100)
|
||||||
|
userId String? @map("user_id") @db.Uuid
|
||||||
|
teamId String? @map("team_id") @db.Uuid
|
||||||
|
createdAt DateTime? @default(now()) @map("created_at") @db.Timestamptz(6)
|
||||||
|
updatedAt DateTime? @updatedAt @map("updated_at") @db.Timestamptz(6)
|
||||||
|
|
||||||
|
user User? @relation("user", fields: [userId], references: [id])
|
||||||
|
team Team? @relation(fields: [teamId], references: [id])
|
||||||
|
|
||||||
|
@@index([slug])
|
||||||
|
@@index([userId])
|
||||||
|
@@index([teamId])
|
||||||
|
@@index([createdAt])
|
||||||
|
@@map("board")
|
||||||
|
}
|
||||||
|
|
@ -1,19 +1,19 @@
|
||||||
{
|
{
|
||||||
"name": "",
|
"name": "",
|
||||||
"short_name": "",
|
"short_name": "",
|
||||||
"icons": [
|
"icons": [
|
||||||
{
|
{
|
||||||
"src": "/android-chrome-192x192.png",
|
"src": "/android-chrome-192x192.png",
|
||||||
"sizes": "192x192",
|
"sizes": "192x192",
|
||||||
"type": "image/png"
|
"type": "image/png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "/android-chrome-512x512.png",
|
"src": "/android-chrome-512x512.png",
|
||||||
"sizes": "512x512",
|
"sizes": "512x512",
|
||||||
"type": "image/png"
|
"type": "image/png"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"theme_color": "#ffffff",
|
"theme_color": "#ffffff",
|
||||||
"background_color": "#ffffff",
|
"background_color": "#ffffff",
|
||||||
"display": "standalone"
|
"display": "standalone"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@ import 'dotenv/config';
|
||||||
import fs from 'node:fs';
|
import fs from 'node:fs';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import https from 'https';
|
import https from 'https';
|
||||||
import zlib from 'zlib';
|
|
||||||
import tar from 'tar';
|
import tar from 'tar';
|
||||||
|
import zlib from 'zlib';
|
||||||
|
|
||||||
if (process.env.VERCEL && !process.env.BUILD_GEO) {
|
if (process.env.VERCEL && !process.env.BUILD_GEO) {
|
||||||
console.log('Vercel environment detected. Skipping geo setup.');
|
console.log('Vercel environment detected. Skipping geo setup.');
|
||||||
|
|
@ -50,21 +50,23 @@ const downloadDirect = (url, originalUrl) =>
|
||||||
https.get(url, res => {
|
https.get(url, res => {
|
||||||
// Follow redirects
|
// Follow redirects
|
||||||
if (res.statusCode === 301 || res.statusCode === 302) {
|
if (res.statusCode === 301 || res.statusCode === 302) {
|
||||||
downloadDirect(res.headers.location, originalUrl || url).then(resolve).catch(reject);
|
downloadDirect(res.headers.location, originalUrl || url)
|
||||||
|
.then(resolve)
|
||||||
|
.catch(reject);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const filename = path.join(dest, path.basename(originalUrl || url));
|
const filename = path.join(dest, path.basename(originalUrl || url));
|
||||||
const fileStream = fs.createWriteStream(filename);
|
const fileStream = fs.createWriteStream(filename);
|
||||||
|
|
||||||
res.pipe(fileStream);
|
res.pipe(fileStream);
|
||||||
|
|
||||||
fileStream.on('finish', () => {
|
fileStream.on('finish', () => {
|
||||||
fileStream.close();
|
fileStream.close();
|
||||||
console.log('Saved geo database:', filename);
|
console.log('Saved geo database:', filename);
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
|
|
||||||
fileStream.on('error', e => {
|
fileStream.on('error', e => {
|
||||||
reject(e);
|
reject(e);
|
||||||
});
|
});
|
||||||
|
|
@ -78,27 +80,29 @@ if (isDirectMmdb) {
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
downloadCompressed(url).then(
|
downloadCompressed(url)
|
||||||
res =>
|
.then(
|
||||||
new Promise((resolve, reject) => {
|
res =>
|
||||||
res.on('entry', entry => {
|
new Promise((resolve, reject) => {
|
||||||
if (entry.path.endsWith('.mmdb')) {
|
res.on('entry', entry => {
|
||||||
const filename = path.join(dest, path.basename(entry.path));
|
if (entry.path.endsWith('.mmdb')) {
|
||||||
entry.pipe(fs.createWriteStream(filename));
|
const filename = path.join(dest, path.basename(entry.path));
|
||||||
|
entry.pipe(fs.createWriteStream(filename));
|
||||||
|
|
||||||
console.log('Saved geo database:', filename);
|
console.log('Saved geo database:', filename);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
res.on('error', e => {
|
res.on('error', e => {
|
||||||
reject(e);
|
reject(e);
|
||||||
});
|
});
|
||||||
res.on('finish', () => {
|
res.on('finish', () => {
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
).catch(e => {
|
)
|
||||||
console.error('Failed to download geo database:', e);
|
.catch(e => {
|
||||||
process.exit(1);
|
console.error('Failed to download geo database:', e);
|
||||||
});
|
process.exit(1);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
/* eslint-disable no-console */
|
/* eslint-disable no-console */
|
||||||
import 'dotenv/config';
|
import 'dotenv/config';
|
||||||
import { execSync } from 'node:child_process';
|
import { execSync } from 'node:child_process';
|
||||||
|
import { PrismaPg } from '@prisma/adapter-pg';
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
import semver from 'semver';
|
import semver from 'semver';
|
||||||
import { PrismaClient } from '../generated/prisma/client.js';
|
import { PrismaClient } from '../generated/prisma/client.js';
|
||||||
import { PrismaPg } from '@prisma/adapter-pg';
|
|
||||||
|
|
||||||
const MIN_VERSION = '9.4.0';
|
const MIN_VERSION = '9.4.0';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
/* eslint-disable no-console */
|
/* eslint-disable no-console */
|
||||||
import fs from 'fs-extra';
|
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import https from 'https';
|
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
|
import fs from 'fs-extra';
|
||||||
|
import https from 'https';
|
||||||
|
|
||||||
const src = path.resolve(process.cwd(), 'src/lang');
|
const src = path.resolve(process.cwd(), 'src/lang');
|
||||||
const dest = path.resolve(process.cwd(), 'public/intl/country');
|
const dest = path.resolve(process.cwd(), 'public/intl/country');
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
/* eslint-disable no-console */
|
/* eslint-disable no-console */
|
||||||
import fs from 'fs-extra';
|
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import https from 'https';
|
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
|
import fs from 'fs-extra';
|
||||||
|
import https from 'https';
|
||||||
|
|
||||||
const src = path.resolve(process.cwd(), 'src/lang');
|
const src = path.resolve(process.cwd(), 'src/lang');
|
||||||
const dest = path.resolve(process.cwd(), 'public/intl/language');
|
const dest = path.resolve(process.cwd(), 'public/intl/language');
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import fs from 'fs-extra';
|
|
||||||
import del from 'del';
|
import del from 'del';
|
||||||
|
import fs from 'fs-extra';
|
||||||
import { createRequire } from 'module';
|
import { createRequire } from 'module';
|
||||||
|
|
||||||
const require = createRequire(import.meta.url);
|
const require = createRequire(import.meta.url);
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
/* eslint-disable no-console */
|
/* eslint-disable no-console */
|
||||||
import fs from 'node:fs';
|
import fs from 'node:fs';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import prettier from 'prettier';
|
|
||||||
import { createRequire } from 'module';
|
import { createRequire } from 'module';
|
||||||
|
import prettier from 'prettier';
|
||||||
|
|
||||||
const require = createRequire(import.meta.url);
|
const require = createRequire(import.meta.url);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
export const dynamic = 'force-dynamic';
|
export const dynamic = 'force-dynamic';
|
||||||
|
|
||||||
import { NextResponse } from 'next/server';
|
import { NextResponse } from 'next/server';
|
||||||
import { notFound } from '@/lib/response';
|
|
||||||
import redis from '@/lib/redis';
|
|
||||||
import { findPixel } from '@/queries/prisma';
|
|
||||||
import { Pixel } from '@/generated/prisma/client';
|
|
||||||
import { POST } from '@/app/api/send/route';
|
import { POST } from '@/app/api/send/route';
|
||||||
|
import type { Pixel } from '@/generated/prisma/client';
|
||||||
|
import redis from '@/lib/redis';
|
||||||
|
import { notFound } from '@/lib/response';
|
||||||
|
import { findPixel } from '@/queries/prisma';
|
||||||
|
|
||||||
const image = Buffer.from('R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw', 'base64');
|
const image = Buffer.from('R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw', 'base64');
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
export const dynamic = 'force-dynamic';
|
export const dynamic = 'force-dynamic';
|
||||||
|
|
||||||
import { NextResponse } from 'next/server';
|
import { NextResponse } from 'next/server';
|
||||||
|
import { POST } from '@/app/api/send/route';
|
||||||
|
import type { Link } from '@/generated/prisma/client';
|
||||||
|
import redis from '@/lib/redis';
|
||||||
import { notFound } from '@/lib/response';
|
import { notFound } from '@/lib/response';
|
||||||
import { findLink } from '@/queries/prisma';
|
import { findLink } from '@/queries/prisma';
|
||||||
import { POST } from '@/app/api/send/route';
|
|
||||||
import { Link } from '@/generated/prisma/client';
|
|
||||||
import redis from '@/lib/redis';
|
|
||||||
|
|
||||||
export async function GET(request: Request, { params }: { params: Promise<{ slug: string }> }) {
|
export async function GET(request: Request, { params }: { params: Promise<{ slug: string }> }) {
|
||||||
const { slug } = await params;
|
const { slug } = await params;
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
'use client';
|
'use client';
|
||||||
import { Grid, Loading, Column, Row } from '@umami/react-zen';
|
import { Column, Grid, Loading, Row } from '@umami/react-zen';
|
||||||
import Script from 'next/script';
|
import Script from 'next/script';
|
||||||
import { UpdateNotice } from './UpdateNotice';
|
|
||||||
import { SideNav } from '@/app/(main)/SideNav';
|
|
||||||
import { useLoginQuery, useConfig, useNavigation } from '@/components/hooks';
|
|
||||||
import { MobileNav } from '@/app/(main)/MobileNav';
|
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { removeItem, setItem } from '@/lib/storage';
|
import { MobileNav } from '@/app/(main)/MobileNav';
|
||||||
|
import { SideNav } from '@/app/(main)/SideNav';
|
||||||
|
import { useConfig, useLoginQuery, useNavigation } from '@/components/hooks';
|
||||||
import { LAST_TEAM_CONFIG } from '@/lib/constants';
|
import { LAST_TEAM_CONFIG } from '@/lib/constants';
|
||||||
|
import { removeItem, setItem } from '@/lib/storage';
|
||||||
|
import { UpdateNotice } from './UpdateNotice';
|
||||||
|
|
||||||
export function App({ children }) {
|
export function App({ children }) {
|
||||||
const { user, isLoading, error } = useLoginQuery();
|
const { user, isLoading, error } = useLoginQuery();
|
||||||
|
|
@ -27,7 +27,9 @@ export function App({ children }) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
window.location.href = `${process.env.basePath || ''}/login`;
|
window.location.href = config.cloudMode
|
||||||
|
? `${process.env.cloudUrl}/login`
|
||||||
|
: `${process.env.basePath || ''}/login`;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
|
import { Grid, IconLabel, NavMenu, NavMenuItem, Row, Text } from '@umami/react-zen';
|
||||||
|
import Link from 'next/link';
|
||||||
import { WebsiteNav } from '@/app/(main)/websites/[websiteId]/WebsiteNav';
|
import { WebsiteNav } from '@/app/(main)/websites/[websiteId]/WebsiteNav';
|
||||||
import { useMessages, useNavigation } from '@/components/hooks';
|
import { useMessages, useNavigation } from '@/components/hooks';
|
||||||
import { Globe, Grid2x2, LinkIcon } from '@/components/icons';
|
import { Globe, Grid2x2, LinkIcon } from '@/components/icons';
|
||||||
import { MobileMenuButton } from '@/components/input/MobileMenuButton';
|
import { MobileMenuButton } from '@/components/input/MobileMenuButton';
|
||||||
import { NavButton } from '@/components/input/NavButton';
|
import { NavButton } from '@/components/input/NavButton';
|
||||||
import { Logo } from '@/components/svg';
|
import { Logo } from '@/components/svg';
|
||||||
import { Grid, IconLabel, NavMenu, NavMenuItem, Row, Text } from '@umami/react-zen';
|
|
||||||
import Link from 'next/link';
|
|
||||||
import { AdminNav } from './admin/AdminNav';
|
import { AdminNav } from './admin/AdminNav';
|
||||||
import { SettingsNav } from './settings/SettingsNav';
|
import { SettingsNav } from './settings/SettingsNav';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,20 @@
|
||||||
import { Key } from 'react';
|
|
||||||
import Link from 'next/link';
|
|
||||||
import {
|
import {
|
||||||
Sidebar,
|
|
||||||
SidebarSection,
|
|
||||||
SidebarItem,
|
|
||||||
SidebarHeader,
|
|
||||||
Row,
|
Row,
|
||||||
SidebarProps,
|
Sidebar,
|
||||||
|
SidebarHeader,
|
||||||
|
SidebarItem,
|
||||||
|
type SidebarProps,
|
||||||
|
SidebarSection,
|
||||||
ThemeButton,
|
ThemeButton,
|
||||||
} from '@umami/react-zen';
|
} from '@umami/react-zen';
|
||||||
import { Globe, LinkIcon, Grid2x2, PanelLeft } from '@/components/icons';
|
import Link from 'next/link';
|
||||||
import { Logo } from '@/components/svg';
|
import type { Key } from 'react';
|
||||||
import { useMessages, useNavigation, useGlobalState } from '@/components/hooks';
|
import { useGlobalState, useMessages, useNavigation } from '@/components/hooks';
|
||||||
|
import { Globe, Grid2x2, LinkIcon, PanelLeft } from '@/components/icons';
|
||||||
|
import { LanguageButton } from '@/components/input/LanguageButton';
|
||||||
import { NavButton } from '@/components/input/NavButton';
|
import { NavButton } from '@/components/input/NavButton';
|
||||||
import { PanelButton } from '@/components/input/PanelButton';
|
import { PanelButton } from '@/components/input/PanelButton';
|
||||||
import { LanguageButton } from '@/components/input/LanguageButton';
|
import { Logo } from '@/components/svg';
|
||||||
|
|
||||||
export function SideNav(props: SidebarProps) {
|
export function SideNav(props: SidebarProps) {
|
||||||
const { formatMessage, labels } = useMessages();
|
const { formatMessage, labels } = useMessages();
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { ThemeButton, Row } from '@umami/react-zen';
|
import { Row, ThemeButton } from '@umami/react-zen';
|
||||||
import { LanguageButton } from '@/components/input/LanguageButton';
|
import { LanguageButton } from '@/components/input/LanguageButton';
|
||||||
import { ProfileButton } from '@/components/input/ProfileButton';
|
import { ProfileButton } from '@/components/input/ProfileButton';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
import { useEffect, useCallback, useState } from 'react';
|
import { AlertBanner, Button, Column, Row } from '@umami/react-zen';
|
||||||
import { Button, AlertBanner, Column, Row } from '@umami/react-zen';
|
|
||||||
import { setItem } from '@/lib/storage';
|
|
||||||
import { useVersion, checkVersion } from '@/store/version';
|
|
||||||
import { REPO_URL, VERSION_CHECK } from '@/lib/constants';
|
|
||||||
import { useMessages } from '@/components/hooks';
|
|
||||||
import { usePathname } from 'next/navigation';
|
import { usePathname } from 'next/navigation';
|
||||||
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
|
import { useMessages } from '@/components/hooks';
|
||||||
|
import { REPO_URL, VERSION_CHECK } from '@/lib/constants';
|
||||||
|
import { setItem } from '@/lib/storage';
|
||||||
|
import { checkVersion, useVersion } from '@/store/version';
|
||||||
|
|
||||||
export function UpdateNotice({ user, config }) {
|
export function UpdateNotice({ user, config }) {
|
||||||
const { formatMessage, labels, messages } = useMessages();
|
const { formatMessage, labels, messages } = useMessages();
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
'use client';
|
'use client';
|
||||||
|
import { Column, Grid } from '@umami/react-zen';
|
||||||
|
import type { ReactNode } from 'react';
|
||||||
import { PageBody } from '@/components/common/PageBody';
|
import { PageBody } from '@/components/common/PageBody';
|
||||||
import { useLoginQuery } from '@/components/hooks';
|
import { useLoginQuery } from '@/components/hooks';
|
||||||
import { Column, Grid } from '@umami/react-zen';
|
|
||||||
import { ReactNode } from 'react';
|
|
||||||
import { AdminNav } from './AdminNav';
|
import { AdminNav } from './AdminNav';
|
||||||
|
|
||||||
export function AdminLayout({ children }: { children: ReactNode }) {
|
export function AdminLayout({ children }: { children: ReactNode }) {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { Metadata } from 'next';
|
import type { Metadata } from 'next';
|
||||||
import { AdminLayout } from './AdminLayout';
|
import { AdminLayout } from './AdminLayout';
|
||||||
|
|
||||||
export default function ({ children }) {
|
export default function ({ children }) {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
|
import type { ReactNode } from 'react';
|
||||||
import { DataGrid } from '@/components/common/DataGrid';
|
import { DataGrid } from '@/components/common/DataGrid';
|
||||||
import { useTeamsQuery } from '@/components/hooks';
|
import { useTeamsQuery } from '@/components/hooks';
|
||||||
import { AdminTeamsTable } from './AdminTeamsTable';
|
import { AdminTeamsTable } from './AdminTeamsTable';
|
||||||
import { ReactNode } from 'react';
|
|
||||||
|
|
||||||
export function AdminTeamsDataTable({
|
export function AdminTeamsDataTable({
|
||||||
showActions,
|
showActions,
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
'use client';
|
'use client';
|
||||||
import { AdminTeamsDataTable } from './AdminTeamsDataTable';
|
|
||||||
import { Column } from '@umami/react-zen';
|
import { Column } from '@umami/react-zen';
|
||||||
import { useMessages } from '@/components/hooks';
|
|
||||||
import { PageHeader } from '@/components/common/PageHeader';
|
import { PageHeader } from '@/components/common/PageHeader';
|
||||||
import { Panel } from '@/components/common/Panel';
|
import { Panel } from '@/components/common/Panel';
|
||||||
|
import { useMessages } from '@/components/hooks';
|
||||||
|
import { AdminTeamsDataTable } from './AdminTeamsDataTable';
|
||||||
|
|
||||||
export function AdminTeamsPage() {
|
export function AdminTeamsPage() {
|
||||||
const { formatMessage, labels } = useMessages();
|
const { formatMessage, labels } = useMessages();
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
|
import { DataColumn, DataTable, Dialog, Icon, MenuItem, Modal, Row, Text } from '@umami/react-zen';
|
||||||
|
import Link from 'next/link';
|
||||||
|
import { useState } from 'react';
|
||||||
import { DateDistance } from '@/components/common/DateDistance';
|
import { DateDistance } from '@/components/common/DateDistance';
|
||||||
import { useMessages } from '@/components/hooks';
|
import { useMessages } from '@/components/hooks';
|
||||||
import { Edit, Trash } from '@/components/icons';
|
import { Edit, Trash } from '@/components/icons';
|
||||||
import { MenuButton } from '@/components/input/MenuButton';
|
import { MenuButton } from '@/components/input/MenuButton';
|
||||||
import { DataColumn, DataTable, Dialog, Icon, MenuItem, Modal, Row, Text } from '@umami/react-zen';
|
|
||||||
import { TeamDeleteForm } from '../../teams/[teamId]/TeamDeleteForm';
|
import { TeamDeleteForm } from '../../teams/[teamId]/TeamDeleteForm';
|
||||||
import Link from 'next/link';
|
|
||||||
import { useState } from 'react';
|
|
||||||
|
|
||||||
export function AdminTeamsTable({
|
export function AdminTeamsTable({
|
||||||
data = [],
|
data = [],
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
|
import type { Metadata } from 'next';
|
||||||
import { AdminTeamPage } from './AdminTeamPage';
|
import { AdminTeamPage } from './AdminTeamPage';
|
||||||
import { Metadata } from 'next';
|
|
||||||
|
|
||||||
export default async function ({ params }: { params: Promise<{ teamId: string }> }) {
|
export default async function ({ params }: { params: Promise<{ teamId: string }> }) {
|
||||||
const { teamId } = await params;
|
const { teamId } = await params;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { Metadata } from 'next';
|
import type { Metadata } from 'next';
|
||||||
import { AdminTeamsPage } from './AdminTeamsPage';
|
import { AdminTeamsPage } from './AdminTeamsPage';
|
||||||
|
|
||||||
export default function () {
|
export default function () {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { Button, Icon, Text, Modal, DialogTrigger, Dialog, useToast } from '@umami/react-zen';
|
import { Button, Dialog, DialogTrigger, Icon, Modal, Text, useToast } from '@umami/react-zen';
|
||||||
import { UserAddForm } from './UserAddForm';
|
|
||||||
import { useMessages, useModified } from '@/components/hooks';
|
import { useMessages, useModified } from '@/components/hooks';
|
||||||
import { Plus } from '@/components/icons';
|
import { Plus } from '@/components/icons';
|
||||||
|
import { UserAddForm } from './UserAddForm';
|
||||||
|
|
||||||
export function UserAddButton({ onSave }: { onSave?: () => void }) {
|
export function UserAddButton({ onSave }: { onSave?: () => void }) {
|
||||||
const { formatMessage, labels, messages } = useMessages();
|
const { formatMessage, labels, messages } = useMessages();
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
import {
|
import {
|
||||||
Select,
|
|
||||||
ListItem,
|
|
||||||
Form,
|
|
||||||
FormField,
|
|
||||||
FormButtons,
|
|
||||||
FormSubmitButton,
|
|
||||||
TextField,
|
|
||||||
PasswordField,
|
|
||||||
Button,
|
Button,
|
||||||
|
Form,
|
||||||
|
FormButtons,
|
||||||
|
FormField,
|
||||||
|
FormSubmitButton,
|
||||||
|
ListItem,
|
||||||
|
PasswordField,
|
||||||
|
Select,
|
||||||
|
TextField,
|
||||||
} from '@umami/react-zen';
|
} from '@umami/react-zen';
|
||||||
import { useMessages, useUpdateQuery } from '@/components/hooks';
|
import { useMessages, useUpdateQuery } from '@/components/hooks';
|
||||||
import { ROLES } from '@/lib/constants';
|
import { ROLES } from '@/lib/constants';
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { Button, Icon, Modal, DialogTrigger, Dialog, Text } from '@umami/react-zen';
|
import { Button, Dialog, DialogTrigger, Icon, Modal, Text } from '@umami/react-zen';
|
||||||
import { useMessages, useLoginQuery } from '@/components/hooks';
|
import { useLoginQuery, useMessages } from '@/components/hooks';
|
||||||
import { Trash } from '@/components/icons';
|
import { Trash } from '@/components/icons';
|
||||||
import { UserDeleteForm } from './UserDeleteForm';
|
import { UserDeleteForm } from './UserDeleteForm';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
|
import type { ReactNode } from 'react';
|
||||||
import { DataGrid } from '@/components/common/DataGrid';
|
import { DataGrid } from '@/components/common/DataGrid';
|
||||||
import { useUsersQuery } from '@/components/hooks';
|
import { useUsersQuery } from '@/components/hooks';
|
||||||
import { UsersTable } from './UsersTable';
|
import { UsersTable } from './UsersTable';
|
||||||
import { ReactNode } from 'react';
|
|
||||||
|
|
||||||
export function UsersDataTable({ showActions }: { showActions?: boolean; children?: ReactNode }) {
|
export function UsersDataTable({ showActions }: { showActions?: boolean; children?: ReactNode }) {
|
||||||
const queryResult = useUsersQuery();
|
const queryResult = useUsersQuery();
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
'use client';
|
'use client';
|
||||||
import { UsersDataTable } from './UsersDataTable';
|
|
||||||
import { Column } from '@umami/react-zen';
|
import { Column } from '@umami/react-zen';
|
||||||
import { useMessages } from '@/components/hooks';
|
|
||||||
import { UserAddButton } from './UserAddButton';
|
|
||||||
import { PageHeader } from '@/components/common/PageHeader';
|
import { PageHeader } from '@/components/common/PageHeader';
|
||||||
import { Panel } from '@/components/common/Panel';
|
import { Panel } from '@/components/common/Panel';
|
||||||
|
import { useMessages } from '@/components/hooks';
|
||||||
|
import { UserAddButton } from './UserAddButton';
|
||||||
|
import { UsersDataTable } from './UsersDataTable';
|
||||||
|
|
||||||
export function UsersPage() {
|
export function UsersPage() {
|
||||||
const { formatMessage, labels } = useMessages();
|
const { formatMessage, labels } = useMessages();
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,12 @@
|
||||||
import { useState } from 'react';
|
import { DataColumn, DataTable, Icon, MenuItem, Modal, Row, Text } from '@umami/react-zen';
|
||||||
import { Row, Text, Icon, DataTable, DataColumn, MenuItem, Modal } from '@umami/react-zen';
|
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import { ROLES } from '@/lib/constants';
|
import { useState } from 'react';
|
||||||
import { Trash } from '@/components/icons';
|
|
||||||
import { useMessages } from '@/components/hooks';
|
|
||||||
import { Edit } from '@/components/icons';
|
|
||||||
import { MenuButton } from '@/components/input/MenuButton';
|
|
||||||
import { UserDeleteForm } from './UserDeleteForm';
|
|
||||||
import { DateDistance } from '@/components/common/DateDistance';
|
import { DateDistance } from '@/components/common/DateDistance';
|
||||||
|
import { useMessages } from '@/components/hooks';
|
||||||
|
import { Edit, Trash } from '@/components/icons';
|
||||||
|
import { MenuButton } from '@/components/input/MenuButton';
|
||||||
|
import { ROLES } from '@/lib/constants';
|
||||||
|
import { UserDeleteForm } from './UserDeleteForm';
|
||||||
|
|
||||||
export function UsersTable({
|
export function UsersTable({
|
||||||
data = [],
|
data = [],
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
import {
|
import {
|
||||||
Select,
|
|
||||||
ListItem,
|
|
||||||
Form,
|
Form,
|
||||||
FormField,
|
|
||||||
FormButtons,
|
FormButtons,
|
||||||
TextField,
|
FormField,
|
||||||
FormSubmitButton,
|
FormSubmitButton,
|
||||||
|
ListItem,
|
||||||
PasswordField,
|
PasswordField,
|
||||||
|
Select,
|
||||||
|
TextField,
|
||||||
} from '@umami/react-zen';
|
} from '@umami/react-zen';
|
||||||
import { useLoginQuery, useMessages, useUpdateQuery, useUser } from '@/components/hooks';
|
import { useLoginQuery, useMessages, useUpdateQuery, useUser } from '@/components/hooks';
|
||||||
import { ROLES } from '@/lib/constants';
|
import { ROLES } from '@/lib/constants';
|
||||||
|
|
@ -30,7 +30,7 @@ export function UserEditForm({ userId, onSave }: { userId: string; onSave?: () =
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form onSubmit={handleSubmit} error={getMessage(error?.['code'])} values={user}>
|
<Form onSubmit={handleSubmit} error={getMessage(error?.code)} values={user}>
|
||||||
<FormField name="username" label={formatMessage(labels.username)}>
|
<FormField name="username" label={formatMessage(labels.username)}>
|
||||||
<TextField data-test="input-username" />
|
<TextField data-test="input-username" />
|
||||||
</FormField>
|
</FormField>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { User } from '@/components/icons';
|
|
||||||
import { PageHeader } from '@/components/common/PageHeader';
|
import { PageHeader } from '@/components/common/PageHeader';
|
||||||
import { useUser } from '@/components/hooks';
|
import { useUser } from '@/components/hooks';
|
||||||
|
import { User } from '@/components/icons';
|
||||||
|
|
||||||
export function UserHeader() {
|
export function UserHeader() {
|
||||||
const user = useUser();
|
const user = useUser();
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
'use client';
|
'use client';
|
||||||
import { Column } from '@umami/react-zen';
|
import { Column } from '@umami/react-zen';
|
||||||
import { UserSettings } from './UserSettings';
|
|
||||||
import { UserProvider } from './UserProvider';
|
|
||||||
import { UserHeader } from '@/app/(main)/admin/users/[userId]/UserHeader';
|
import { UserHeader } from '@/app/(main)/admin/users/[userId]/UserHeader';
|
||||||
import { Panel } from '@/components/common/Panel';
|
import { Panel } from '@/components/common/Panel';
|
||||||
|
import { UserProvider } from './UserProvider';
|
||||||
|
import { UserSettings } from './UserSettings';
|
||||||
|
|
||||||
export function UserPage({ userId }: { userId: string }) {
|
export function UserPage({ userId }: { userId: string }) {
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { createContext, ReactNode } from 'react';
|
|
||||||
import { Loading } from '@umami/react-zen';
|
import { Loading } from '@umami/react-zen';
|
||||||
import { User } from '@/generated/prisma/client';
|
import { createContext, type ReactNode } from 'react';
|
||||||
import { useUserQuery } from '@/components/hooks/queries/useUserQuery';
|
import { useUserQuery } from '@/components/hooks/queries/useUserQuery';
|
||||||
|
import type { User } from '@/generated/prisma/client';
|
||||||
|
|
||||||
export const UserContext = createContext<User>(null);
|
export const UserContext = createContext<User>(null);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { Column, Tabs, Tab, TabList, TabPanel } from '@umami/react-zen';
|
import { Column, Tab, TabList, TabPanel, Tabs } from '@umami/react-zen';
|
||||||
import { UserEditForm } from './UserEditForm';
|
|
||||||
import { useMessages } from '@/components/hooks';
|
import { useMessages } from '@/components/hooks';
|
||||||
|
import { UserEditForm } from './UserEditForm';
|
||||||
import { UserWebsites } from './UserWebsites';
|
import { UserWebsites } from './UserWebsites';
|
||||||
|
|
||||||
export function UserSettings({ userId }: { userId: string }) {
|
export function UserSettings({ userId }: { userId: string }) {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
|
import { WebsitesTable } from '@/app/(main)/websites/WebsitesTable';
|
||||||
import { DataGrid } from '@/components/common/DataGrid';
|
import { DataGrid } from '@/components/common/DataGrid';
|
||||||
import { useUserWebsitesQuery } from '@/components/hooks';
|
import { useUserWebsitesQuery } from '@/components/hooks';
|
||||||
import { WebsitesTable } from '@/app/(main)/websites/WebsitesTable';
|
|
||||||
|
|
||||||
export function UserWebsites({ userId }) {
|
export function UserWebsites({ userId }) {
|
||||||
const queryResult = useUserWebsitesQuery({ userId });
|
const queryResult = useUserWebsitesQuery({ userId });
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
|
import type { Metadata } from 'next';
|
||||||
import { UserPage } from './UserPage';
|
import { UserPage } from './UserPage';
|
||||||
import { Metadata } from 'next';
|
|
||||||
|
|
||||||
export default async function ({ params }: { params: Promise<{ userId: string }> }) {
|
export default async function ({ params }: { params: Promise<{ userId: string }> }) {
|
||||||
const { userId } = await params;
|
const { userId } = await params;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { Metadata } from 'next';
|
import type { Metadata } from 'next';
|
||||||
import { UsersPage } from './UsersPage';
|
import { UsersPage } from './UsersPage';
|
||||||
|
|
||||||
export default function () {
|
export default function () {
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
'use client';
|
'use client';
|
||||||
import { AdminWebsitesDataTable } from './AdminWebsitesDataTable';
|
|
||||||
import { Column } from '@umami/react-zen';
|
import { Column } from '@umami/react-zen';
|
||||||
import { useMessages } from '@/components/hooks';
|
|
||||||
import { PageHeader } from '@/components/common/PageHeader';
|
import { PageHeader } from '@/components/common/PageHeader';
|
||||||
import { Panel } from '@/components/common/Panel';
|
import { Panel } from '@/components/common/Panel';
|
||||||
|
import { useMessages } from '@/components/hooks';
|
||||||
|
import { AdminWebsitesDataTable } from './AdminWebsitesDataTable';
|
||||||
|
|
||||||
export function AdminWebsitesPage() {
|
export function AdminWebsitesPage() {
|
||||||
const { formatMessage, labels } = useMessages();
|
const { formatMessage, labels } = useMessages();
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,11 @@
|
||||||
import { useState } from 'react';
|
import { DataColumn, DataTable, Dialog, Icon, MenuItem, Modal, Row, Text } from '@umami/react-zen';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import { Row, Text, Icon, DataTable, DataColumn, MenuItem, Modal, Dialog } from '@umami/react-zen';
|
import { useState } from 'react';
|
||||||
import { Trash, Users } from '@/components/icons';
|
|
||||||
import { useMessages } from '@/components/hooks';
|
|
||||||
import { Edit } from '@/components/icons';
|
|
||||||
import { MenuButton } from '@/components/input/MenuButton';
|
|
||||||
import { DateDistance } from '@/components/common/DateDistance';
|
|
||||||
import { WebsiteDeleteForm } from '@/app/(main)/websites/[websiteId]/settings/WebsiteDeleteForm';
|
import { WebsiteDeleteForm } from '@/app/(main)/websites/[websiteId]/settings/WebsiteDeleteForm';
|
||||||
|
import { DateDistance } from '@/components/common/DateDistance';
|
||||||
|
import { useMessages } from '@/components/hooks';
|
||||||
|
import { Edit, Trash, Users } from '@/components/icons';
|
||||||
|
import { MenuButton } from '@/components/input/MenuButton';
|
||||||
|
|
||||||
export function AdminWebsitesTable({ data = [] }: { data: any[] }) {
|
export function AdminWebsitesTable({ data = [] }: { data: any[] }) {
|
||||||
const { formatMessage, labels } = useMessages();
|
const { formatMessage, labels } = useMessages();
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { Metadata } from 'next';
|
import type { Metadata } from 'next';
|
||||||
import { WebsiteSettingsPage } from '@/app/(main)/settings/websites/[websiteId]/WebsiteSettingsPage';
|
import { WebsiteSettingsPage } from '@/app/(main)/settings/websites/[websiteId]/WebsiteSettingsPage';
|
||||||
|
|
||||||
export default async function ({ params }: { params: Promise<{ websiteId: string }> }) {
|
export default async function ({ params }: { params: Promise<{ websiteId: string }> }) {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { Metadata } from 'next';
|
import type { Metadata } from 'next';
|
||||||
import { AdminWebsitesPage } from './AdminWebsitesPage';
|
import { AdminWebsitesPage } from './AdminWebsitesPage';
|
||||||
|
|
||||||
export default function () {
|
export default function () {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
|
import { Button, Dialog, DialogTrigger, Icon, Modal, Text, useToast } from '@umami/react-zen';
|
||||||
import { useMessages, useModified, useNavigation } from '@/components/hooks';
|
import { useMessages, useModified, useNavigation } from '@/components/hooks';
|
||||||
import { Button, Icon, Modal, Dialog, DialogTrigger, Text, useToast } from '@umami/react-zen';
|
|
||||||
import { Plus } from '@/components/icons';
|
import { Plus } from '@/components/icons';
|
||||||
import { BoardAddForm } from './BoardAddForm';
|
import { BoardAddForm } from './BoardAddForm';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { Form, FormField, FormSubmitButton, Row, TextField, Button } from '@umami/react-zen';
|
import { Button, Form, FormField, FormSubmitButton, Row, TextField } from '@umami/react-zen';
|
||||||
import { useUpdateQuery, useMessages } from '@/components/hooks';
|
import { useMessages, useUpdateQuery } from '@/components/hooks';
|
||||||
import { DOMAIN_REGEX } from '@/lib/constants';
|
import { DOMAIN_REGEX } from '@/lib/constants';
|
||||||
|
|
||||||
export function BoardAddForm({
|
export function BoardAddForm({
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
'use client';
|
'use client';
|
||||||
import { Column } from '@umami/react-zen';
|
import { Column } from '@umami/react-zen';
|
||||||
import { PageHeader } from '@/components/common/PageHeader';
|
|
||||||
import { PageBody } from '@/components/common/PageBody';
|
import { PageBody } from '@/components/common/PageBody';
|
||||||
|
import { PageHeader } from '@/components/common/PageHeader';
|
||||||
import { BoardAddButton } from './BoardAddButton';
|
import { BoardAddButton } from './BoardAddButton';
|
||||||
|
|
||||||
export function BoardsPage() {
|
export function BoardsPage() {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { Metadata } from 'next';
|
import type { Metadata } from 'next';
|
||||||
import { Board } from './Board';
|
import { Board } from './Board';
|
||||||
|
|
||||||
export default async function ({ params }: { params: Promise<{ boardId: string }> }) {
|
export default async function ({ params }: { params: Promise<{ boardId: string }> }) {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { Metadata } from 'next';
|
import type { Metadata } from 'next';
|
||||||
import { BoardsPage } from './BoardsPage';
|
import { BoardsPage } from './BoardsPage';
|
||||||
|
|
||||||
export default function () {
|
export default function () {
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,25 @@
|
||||||
'use client';
|
'use client';
|
||||||
import { Button, Grid, Column, Heading } from '@umami/react-zen';
|
import { Button, Column, Grid, Heading } from '@umami/react-zen';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import Script from 'next/script';
|
import Script from 'next/script';
|
||||||
import { Panel } from '@/components/common/Panel';
|
|
||||||
import { PageBody } from '@/components/common/PageBody';
|
|
||||||
import { EventsChart } from '@/components/metrics/EventsChart';
|
|
||||||
import { WebsiteChart } from '@/app/(main)/websites/[websiteId]/WebsiteChart';
|
import { WebsiteChart } from '@/app/(main)/websites/[websiteId]/WebsiteChart';
|
||||||
import { useWebsiteQuery } from '@/components/hooks';
|
import { PageBody } from '@/components/common/PageBody';
|
||||||
import { PageHeader } from '@/components/common/PageHeader';
|
import { PageHeader } from '@/components/common/PageHeader';
|
||||||
|
import { Panel } from '@/components/common/Panel';
|
||||||
|
import { useWebsiteQuery } from '@/components/hooks';
|
||||||
|
import { EventsChart } from '@/components/metrics/EventsChart';
|
||||||
|
|
||||||
export function TestConsolePage({ websiteId }: { websiteId: string }) {
|
export function TestConsolePage({ websiteId }: { websiteId: string }) {
|
||||||
const { data } = useWebsiteQuery(websiteId);
|
const { data } = useWebsiteQuery(websiteId);
|
||||||
|
|
||||||
function handleRunScript() {
|
function handleRunScript() {
|
||||||
window['umami'].track(props => ({
|
window.umami.track(props => ({
|
||||||
...props,
|
...props,
|
||||||
url: '/page-view',
|
url: '/page-view',
|
||||||
referrer: 'https://www.google.com',
|
referrer: 'https://www.google.com',
|
||||||
}));
|
}));
|
||||||
window['umami'].track('track-event-no-data');
|
window.umami.track('track-event-no-data');
|
||||||
window['umami'].track('track-event-with-data', {
|
window.umami.track('track-event-with-data', {
|
||||||
test: 'test-data',
|
test: 'test-data',
|
||||||
boolean: true,
|
boolean: true,
|
||||||
booleanError: 'true',
|
booleanError: 'true',
|
||||||
|
|
@ -40,32 +40,32 @@ export function TestConsolePage({ websiteId }: { websiteId: string }) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleRunRevenue() {
|
function handleRunRevenue() {
|
||||||
window['umami'].track(props => ({
|
window.umami.track(props => ({
|
||||||
...props,
|
...props,
|
||||||
url: '/checkout-cart',
|
url: '/checkout-cart',
|
||||||
referrer: 'https://www.google.com',
|
referrer: 'https://www.google.com',
|
||||||
}));
|
}));
|
||||||
window['umami'].track('checkout-cart', {
|
window.umami.track('checkout-cart', {
|
||||||
revenue: parseFloat((Math.random() * 1000).toFixed(2)),
|
revenue: parseFloat((Math.random() * 1000).toFixed(2)),
|
||||||
currency: 'USD',
|
currency: 'USD',
|
||||||
});
|
});
|
||||||
window['umami'].track('affiliate-link', {
|
window.umami.track('affiliate-link', {
|
||||||
revenue: parseFloat((Math.random() * 1000).toFixed(2)),
|
revenue: parseFloat((Math.random() * 1000).toFixed(2)),
|
||||||
currency: 'USD',
|
currency: 'USD',
|
||||||
});
|
});
|
||||||
window['umami'].track('promotion-link', {
|
window.umami.track('promotion-link', {
|
||||||
revenue: parseFloat((Math.random() * 1000).toFixed(2)),
|
revenue: parseFloat((Math.random() * 1000).toFixed(2)),
|
||||||
currency: 'USD',
|
currency: 'USD',
|
||||||
});
|
});
|
||||||
window['umami'].track('checkout-cart', {
|
window.umami.track('checkout-cart', {
|
||||||
revenue: parseFloat((Math.random() * 1000).toFixed(2)),
|
revenue: parseFloat((Math.random() * 1000).toFixed(2)),
|
||||||
currency: 'EUR',
|
currency: 'EUR',
|
||||||
});
|
});
|
||||||
window['umami'].track('promotion-link', {
|
window.umami.track('promotion-link', {
|
||||||
revenue: parseFloat((Math.random() * 1000).toFixed(2)),
|
revenue: parseFloat((Math.random() * 1000).toFixed(2)),
|
||||||
currency: 'EUR',
|
currency: 'EUR',
|
||||||
});
|
});
|
||||||
window['umami'].track('affiliate-link', {
|
window.umami.track('affiliate-link', {
|
||||||
item1: {
|
item1: {
|
||||||
productIdentity: 'ABC424',
|
productIdentity: 'ABC424',
|
||||||
revenue: parseFloat((Math.random() * 10000).toFixed(2)),
|
revenue: parseFloat((Math.random() * 10000).toFixed(2)),
|
||||||
|
|
@ -80,7 +80,7 @@ export function TestConsolePage({ websiteId }: { websiteId: string }) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleRunIdentify() {
|
function handleRunIdentify() {
|
||||||
window['umami'].identify({
|
window.umami.identify({
|
||||||
userId: 123,
|
userId: 123,
|
||||||
name: 'brian',
|
name: 'brian',
|
||||||
number: Math.random() * 100,
|
number: Math.random() * 100,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { Metadata } from 'next';
|
import type { Metadata } from 'next';
|
||||||
import { TestConsolePage } from './TestConsolePage';
|
import { TestConsolePage } from './TestConsolePage';
|
||||||
|
|
||||||
async function getEnabled() {
|
async function getEnabled() {
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
'use client';
|
'use client';
|
||||||
import { Column } from '@umami/react-zen';
|
import { Column } from '@umami/react-zen';
|
||||||
|
import { PageBody } from '@/components/common/PageBody';
|
||||||
import { PageHeader } from '@/components/common/PageHeader';
|
import { PageHeader } from '@/components/common/PageHeader';
|
||||||
import { useMessages } from '@/components/hooks';
|
import { useMessages } from '@/components/hooks';
|
||||||
import { PageBody } from '@/components/common/PageBody';
|
|
||||||
|
|
||||||
export function DashboardPage() {
|
export function DashboardPage() {
|
||||||
const { formatMessage, labels } = useMessages();
|
const { formatMessage, labels } = useMessages();
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { Metadata } from 'next';
|
import type { Metadata } from 'next';
|
||||||
import { DashboardPage } from './DashboardPage';
|
import { DashboardPage } from './DashboardPage';
|
||||||
|
|
||||||
export default async function () {
|
export default async function () {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
|
import type { Metadata } from 'next';
|
||||||
import { Suspense } from 'react';
|
import { Suspense } from 'react';
|
||||||
import { Metadata } from 'next';
|
|
||||||
import { App } from './App';
|
import { App } from './App';
|
||||||
|
|
||||||
export default function ({ children }) {
|
export default function ({ children }) {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { useMessages } from '@/components/hooks';
|
import { useMessages } from '@/components/hooks';
|
||||||
import { Plus } from '@/components/icons';
|
import { Plus } from '@/components/icons';
|
||||||
import { LinkEditForm } from './LinkEditForm';
|
|
||||||
import { DialogButton } from '@/components/input/DialogButton';
|
import { DialogButton } from '@/components/input/DialogButton';
|
||||||
|
import { LinkEditForm } from './LinkEditForm';
|
||||||
|
|
||||||
export function LinkAddButton({ teamId }: { teamId?: string }) {
|
export function LinkAddButton({ teamId }: { teamId?: string }) {
|
||||||
const { formatMessage, labels } = useMessages();
|
const { formatMessage, labels } = useMessages();
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { Trash } from '@/components/icons';
|
|
||||||
import { ConfirmationForm } from '@/components/common/ConfirmationForm';
|
import { ConfirmationForm } from '@/components/common/ConfirmationForm';
|
||||||
import { messages } from '@/components/messages';
|
|
||||||
import { useDeleteQuery, useMessages } from '@/components/hooks';
|
import { useDeleteQuery, useMessages } from '@/components/hooks';
|
||||||
|
import { Trash } from '@/components/icons';
|
||||||
import { DialogButton } from '@/components/input/DialogButton';
|
import { DialogButton } from '@/components/input/DialogButton';
|
||||||
|
import { messages } from '@/components/messages';
|
||||||
|
|
||||||
export function LinkDeleteButton({
|
export function LinkDeleteButton({
|
||||||
linkId,
|
linkId,
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { Edit } from '@/components/icons';
|
|
||||||
import { LinkEditForm } from './LinkEditForm';
|
|
||||||
import { useMessages } from '@/components/hooks';
|
import { useMessages } from '@/components/hooks';
|
||||||
|
import { Edit } from '@/components/icons';
|
||||||
import { DialogButton } from '@/components/input/DialogButton';
|
import { DialogButton } from '@/components/input/DialogButton';
|
||||||
|
import { LinkEditForm } from './LinkEditForm';
|
||||||
|
|
||||||
export function LinkEditButton({ linkId }: { linkId: string }) {
|
export function LinkEditButton({ linkId }: { linkId: string }) {
|
||||||
const { formatMessage, labels } = useMessages();
|
const { formatMessage, labels } = useMessages();
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,21 @@
|
||||||
import { useState, useEffect } from 'react';
|
|
||||||
import {
|
import {
|
||||||
|
Button,
|
||||||
|
Column,
|
||||||
Form,
|
Form,
|
||||||
FormField,
|
FormField,
|
||||||
FormSubmitButton,
|
FormSubmitButton,
|
||||||
|
Icon,
|
||||||
|
Label,
|
||||||
|
Loading,
|
||||||
Row,
|
Row,
|
||||||
TextField,
|
TextField,
|
||||||
Button,
|
|
||||||
Label,
|
|
||||||
Column,
|
|
||||||
Icon,
|
|
||||||
Loading,
|
|
||||||
} from '@umami/react-zen';
|
} from '@umami/react-zen';
|
||||||
import { useConfig, useLinkQuery } from '@/components/hooks';
|
import { useEffect, useState } from 'react';
|
||||||
import { useMessages } from '@/components/hooks';
|
import { useConfig, useLinkQuery, useMessages } from '@/components/hooks';
|
||||||
import { RefreshCw } from '@/components/icons';
|
|
||||||
import { getRandomChars } from '@/lib/generate';
|
|
||||||
import { useUpdateQuery } from '@/components/hooks/queries/useUpdateQuery';
|
import { useUpdateQuery } from '@/components/hooks/queries/useUpdateQuery';
|
||||||
|
import { RefreshCw } from '@/components/icons';
|
||||||
import { LINKS_URL } from '@/lib/constants';
|
import { LINKS_URL } from '@/lib/constants';
|
||||||
|
import { getRandomChars } from '@/lib/generate';
|
||||||
import { isValidUrl } from '@/lib/url';
|
import { isValidUrl } from '@/lib/url';
|
||||||
|
|
||||||
const generateId = () => getRandomChars(9);
|
const generateId = () => getRandomChars(9);
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
'use client';
|
'use client';
|
||||||
import { createContext, ReactNode } from 'react';
|
|
||||||
import { Loading } from '@umami/react-zen';
|
import { Loading } from '@umami/react-zen';
|
||||||
import { Link } from '@/generated/prisma/client';
|
import { createContext, type ReactNode } from 'react';
|
||||||
import { useLinkQuery } from '@/components/hooks/queries/useLinkQuery';
|
import { useLinkQuery } from '@/components/hooks/queries/useLinkQuery';
|
||||||
|
import type { Link } from '@/generated/prisma/client';
|
||||||
|
|
||||||
export const LinkContext = createContext<Link>(null);
|
export const LinkContext = createContext<Link>(null);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
|
import { DataGrid } from '@/components/common/DataGrid';
|
||||||
import { useLinksQuery, useNavigation } from '@/components/hooks';
|
import { useLinksQuery, useNavigation } from '@/components/hooks';
|
||||||
import { LinksTable } from './LinksTable';
|
import { LinksTable } from './LinksTable';
|
||||||
import { DataGrid } from '@/components/common/DataGrid';
|
|
||||||
|
|
||||||
export function LinksDataTable() {
|
export function LinksDataTable() {
|
||||||
const { teamId } = useNavigation();
|
const { teamId } = useNavigation();
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
'use client';
|
'use client';
|
||||||
import { PageBody } from '@/components/common/PageBody';
|
|
||||||
import { Column } from '@umami/react-zen';
|
import { Column } from '@umami/react-zen';
|
||||||
import { PageHeader } from '@/components/common/PageHeader';
|
|
||||||
import { LinkAddButton } from './LinkAddButton';
|
|
||||||
import { useMessages, useNavigation } from '@/components/hooks';
|
|
||||||
import { LinksDataTable } from '@/app/(main)/links/LinksDataTable';
|
import { LinksDataTable } from '@/app/(main)/links/LinksDataTable';
|
||||||
|
import { PageBody } from '@/components/common/PageBody';
|
||||||
|
import { PageHeader } from '@/components/common/PageHeader';
|
||||||
import { Panel } from '@/components/common/Panel';
|
import { Panel } from '@/components/common/Panel';
|
||||||
|
import { useMessages, useNavigation } from '@/components/hooks';
|
||||||
|
import { LinkAddButton } from './LinkAddButton';
|
||||||
|
|
||||||
export function LinksPage() {
|
export function LinksPage() {
|
||||||
const { formatMessage, labels } = useMessages();
|
const { formatMessage, labels } = useMessages();
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
|
import { DataColumn, DataTable, type DataTableProps, Row } from '@umami/react-zen';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import { DataTable, DataColumn, Row, DataTableProps } from '@umami/react-zen';
|
|
||||||
import { useMessages, useNavigation, useSlug } from '@/components/hooks';
|
|
||||||
import { DateDistance } from '@/components/common/DateDistance';
|
import { DateDistance } from '@/components/common/DateDistance';
|
||||||
import { ExternalLink } from '@/components/common/ExternalLink';
|
import { ExternalLink } from '@/components/common/ExternalLink';
|
||||||
import { LinkEditButton } from './LinkEditButton';
|
import { useMessages, useNavigation, useSlug } from '@/components/hooks';
|
||||||
import { LinkDeleteButton } from './LinkDeleteButton';
|
import { LinkDeleteButton } from './LinkDeleteButton';
|
||||||
|
import { LinkEditButton } from './LinkEditButton';
|
||||||
|
|
||||||
export function LinksTable(props: DataTableProps) {
|
export function LinksTable(props: DataTableProps) {
|
||||||
const { formatMessage, labels } = useMessages();
|
const { formatMessage, labels } = useMessages();
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import { Column, Row } from '@umami/react-zen';
|
import { Column, Row } from '@umami/react-zen';
|
||||||
import { WebsiteFilterButton } from '@/components/input/WebsiteFilterButton';
|
import { ExportButton } from '@/components/input/ExportButton';
|
||||||
import { WebsiteDateFilter } from '@/components/input/WebsiteDateFilter';
|
|
||||||
import { FilterBar } from '@/components/input/FilterBar';
|
import { FilterBar } from '@/components/input/FilterBar';
|
||||||
import { MonthFilter } from '@/components/input/MonthFilter';
|
import { MonthFilter } from '@/components/input/MonthFilter';
|
||||||
import { ExportButton } from '@/components/input/ExportButton';
|
import { WebsiteDateFilter } from '@/components/input/WebsiteDateFilter';
|
||||||
|
import { WebsiteFilterButton } from '@/components/input/WebsiteFilterButton';
|
||||||
|
|
||||||
export function LinkControls({
|
export function LinkControls({
|
||||||
linkId: websiteId,
|
linkId: websiteId,
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { useLink, useMessages, useSlug } from '@/components/hooks';
|
|
||||||
import { PageHeader } from '@/components/common/PageHeader';
|
|
||||||
import { Icon, Text } from '@umami/react-zen';
|
import { Icon, Text } from '@umami/react-zen';
|
||||||
import { ExternalLink, Link } from '@/components/icons';
|
|
||||||
import { LinkButton } from '@/components/common/LinkButton';
|
import { LinkButton } from '@/components/common/LinkButton';
|
||||||
|
import { PageHeader } from '@/components/common/PageHeader';
|
||||||
|
import { useLink, useMessages, useSlug } from '@/components/hooks';
|
||||||
|
import { ExternalLink, Link } from '@/components/icons';
|
||||||
|
|
||||||
export function LinkHeader() {
|
export function LinkHeader() {
|
||||||
const { formatMessage, labels } = useMessages();
|
const { formatMessage, labels } = useMessages();
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
|
import { LoadingPanel } from '@/components/common/LoadingPanel';
|
||||||
import { useDateRange, useMessages } from '@/components/hooks';
|
import { useDateRange, useMessages } from '@/components/hooks';
|
||||||
|
import { useWebsiteStatsQuery } from '@/components/hooks/queries/useWebsiteStatsQuery';
|
||||||
import { MetricCard } from '@/components/metrics/MetricCard';
|
import { MetricCard } from '@/components/metrics/MetricCard';
|
||||||
import { MetricsBar } from '@/components/metrics/MetricsBar';
|
import { MetricsBar } from '@/components/metrics/MetricsBar';
|
||||||
import { formatLongNumber } from '@/lib/format';
|
import { formatLongNumber } from '@/lib/format';
|
||||||
import { useWebsiteStatsQuery } from '@/components/hooks/queries/useWebsiteStatsQuery';
|
|
||||||
import { LoadingPanel } from '@/components/common/LoadingPanel';
|
|
||||||
|
|
||||||
export function LinkMetricsBar({
|
export function LinkMetricsBar({
|
||||||
linkId,
|
linkId,
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
'use client';
|
'use client';
|
||||||
import { PageBody } from '@/components/common/PageBody';
|
|
||||||
import { LinkProvider } from '@/app/(main)/links/LinkProvider';
|
|
||||||
import { LinkHeader } from '@/app/(main)/links/[linkId]/LinkHeader';
|
|
||||||
import { Panel } from '@/components/common/Panel';
|
|
||||||
import { WebsiteChart } from '@/app/(main)/websites/[websiteId]/WebsiteChart';
|
|
||||||
import { LinkMetricsBar } from '@/app/(main)/links/[linkId]/LinkMetricsBar';
|
|
||||||
import { LinkControls } from '@/app/(main)/links/[linkId]/LinkControls';
|
|
||||||
import { LinkPanels } from '@/app/(main)/links/[linkId]/LinkPanels';
|
|
||||||
import { Column, Grid } from '@umami/react-zen';
|
import { Column, Grid } from '@umami/react-zen';
|
||||||
|
import { LinkControls } from '@/app/(main)/links/[linkId]/LinkControls';
|
||||||
|
import { LinkHeader } from '@/app/(main)/links/[linkId]/LinkHeader';
|
||||||
|
import { LinkMetricsBar } from '@/app/(main)/links/[linkId]/LinkMetricsBar';
|
||||||
|
import { LinkPanels } from '@/app/(main)/links/[linkId]/LinkPanels';
|
||||||
|
import { LinkProvider } from '@/app/(main)/links/LinkProvider';
|
||||||
import { ExpandedViewModal } from '@/app/(main)/websites/[websiteId]/ExpandedViewModal';
|
import { ExpandedViewModal } from '@/app/(main)/websites/[websiteId]/ExpandedViewModal';
|
||||||
|
import { WebsiteChart } from '@/app/(main)/websites/[websiteId]/WebsiteChart';
|
||||||
|
import { PageBody } from '@/components/common/PageBody';
|
||||||
|
import { Panel } from '@/components/common/Panel';
|
||||||
|
|
||||||
const excludedIds = ['path', 'entry', 'exit', 'title', 'language', 'screen', 'event'];
|
const excludedIds = ['path', 'entry', 'exit', 'title', 'language', 'screen', 'event'];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import { Grid, Tabs, Tab, TabList, TabPanel, Heading } from '@umami/react-zen';
|
import { Grid, Heading, Tab, TabList, TabPanel, Tabs } from '@umami/react-zen';
|
||||||
import { GridRow } from '@/components/common/GridRow';
|
import { GridRow } from '@/components/common/GridRow';
|
||||||
import { Panel } from '@/components/common/Panel';
|
import { Panel } from '@/components/common/Panel';
|
||||||
import { WorldMap } from '@/components/metrics/WorldMap';
|
|
||||||
import { MetricsTable } from '@/components/metrics/MetricsTable';
|
|
||||||
import { useMessages } from '@/components/hooks';
|
import { useMessages } from '@/components/hooks';
|
||||||
|
import { MetricsTable } from '@/components/metrics/MetricsTable';
|
||||||
|
import { WorldMap } from '@/components/metrics/WorldMap';
|
||||||
|
|
||||||
export function LinkPanels({ linkId }: { linkId: string }) {
|
export function LinkPanels({ linkId }: { linkId: string }) {
|
||||||
const { formatMessage, labels } = useMessages();
|
const { formatMessage, labels } = useMessages();
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
|
import type { Metadata } from 'next';
|
||||||
import { LinkPage } from './LinkPage';
|
import { LinkPage } from './LinkPage';
|
||||||
import { Metadata } from 'next';
|
|
||||||
|
|
||||||
export default async function ({ params }: { params: Promise<{ linkId: string }> }) {
|
export default async function ({ params }: { params: Promise<{ linkId: string }> }) {
|
||||||
const { linkId } = await params;
|
const { linkId } = await params;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
|
import type { Metadata } from 'next';
|
||||||
import { LinksPage } from './LinksPage';
|
import { LinksPage } from './LinksPage';
|
||||||
import { Metadata } from 'next';
|
|
||||||
|
|
||||||
export default function () {
|
export default function () {
|
||||||
return <LinksPage />;
|
return <LinksPage />;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { useMessages } from '@/components/hooks';
|
import { useMessages } from '@/components/hooks';
|
||||||
import { Plus } from '@/components/icons';
|
import { Plus } from '@/components/icons';
|
||||||
import { PixelEditForm } from './PixelEditForm';
|
|
||||||
import { DialogButton } from '@/components/input/DialogButton';
|
import { DialogButton } from '@/components/input/DialogButton';
|
||||||
|
import { PixelEditForm } from './PixelEditForm';
|
||||||
|
|
||||||
export function PixelAddButton({ teamId }: { teamId?: string }) {
|
export function PixelAddButton({ teamId }: { teamId?: string }) {
|
||||||
const { formatMessage, labels } = useMessages();
|
const { formatMessage, labels } = useMessages();
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { Trash } from '@/components/icons';
|
|
||||||
import { ConfirmationForm } from '@/components/common/ConfirmationForm';
|
import { ConfirmationForm } from '@/components/common/ConfirmationForm';
|
||||||
import { messages } from '@/components/messages';
|
|
||||||
import { useDeleteQuery, useMessages, useModified } from '@/components/hooks';
|
import { useDeleteQuery, useMessages, useModified } from '@/components/hooks';
|
||||||
|
import { Trash } from '@/components/icons';
|
||||||
import { DialogButton } from '@/components/input/DialogButton';
|
import { DialogButton } from '@/components/input/DialogButton';
|
||||||
|
import { messages } from '@/components/messages';
|
||||||
|
|
||||||
export function PixelDeleteButton({
|
export function PixelDeleteButton({
|
||||||
pixelId,
|
pixelId,
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { Edit } from '@/components/icons';
|
|
||||||
import { PixelEditForm } from './PixelEditForm';
|
|
||||||
import { useMessages } from '@/components/hooks';
|
import { useMessages } from '@/components/hooks';
|
||||||
|
import { Edit } from '@/components/icons';
|
||||||
import { DialogButton } from '@/components/input/DialogButton';
|
import { DialogButton } from '@/components/input/DialogButton';
|
||||||
|
import { PixelEditForm } from './PixelEditForm';
|
||||||
|
|
||||||
export function PixelEditButton({ pixelId }: { pixelId: string }) {
|
export function PixelEditButton({ pixelId }: { pixelId: string }) {
|
||||||
const { formatMessage, labels } = useMessages();
|
const { formatMessage, labels } = useMessages();
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,21 @@
|
||||||
import {
|
import {
|
||||||
|
Button,
|
||||||
|
Column,
|
||||||
Form,
|
Form,
|
||||||
FormField,
|
FormField,
|
||||||
FormSubmitButton,
|
FormSubmitButton,
|
||||||
|
Icon,
|
||||||
|
Label,
|
||||||
|
Loading,
|
||||||
Row,
|
Row,
|
||||||
TextField,
|
TextField,
|
||||||
Button,
|
|
||||||
Label,
|
|
||||||
Column,
|
|
||||||
Icon,
|
|
||||||
Loading,
|
|
||||||
} from '@umami/react-zen';
|
} from '@umami/react-zen';
|
||||||
import { useConfig, usePixelQuery } from '@/components/hooks';
|
|
||||||
import { useMessages } from '@/components/hooks';
|
|
||||||
import { RefreshCw } from '@/components/icons';
|
|
||||||
import { getRandomChars } from '@/lib/generate';
|
|
||||||
import { useUpdateQuery } from '@/components/hooks/queries/useUpdateQuery';
|
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
|
import { useConfig, useMessages, usePixelQuery } from '@/components/hooks';
|
||||||
|
import { useUpdateQuery } from '@/components/hooks/queries/useUpdateQuery';
|
||||||
|
import { RefreshCw } from '@/components/icons';
|
||||||
import { PIXELS_URL } from '@/lib/constants';
|
import { PIXELS_URL } from '@/lib/constants';
|
||||||
|
import { getRandomChars } from '@/lib/generate';
|
||||||
|
|
||||||
const generateId = () => getRandomChars(9);
|
const generateId = () => getRandomChars(9);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
'use client';
|
'use client';
|
||||||
import { createContext, ReactNode } from 'react';
|
|
||||||
import { Loading } from '@umami/react-zen';
|
import { Loading } from '@umami/react-zen';
|
||||||
import { Pixel } from '@/generated/prisma/client';
|
import { createContext, type ReactNode } from 'react';
|
||||||
import { usePixelQuery } from '@/components/hooks/queries/usePixelQuery';
|
import { usePixelQuery } from '@/components/hooks/queries/usePixelQuery';
|
||||||
|
import type { Pixel } from '@/generated/prisma/client';
|
||||||
|
|
||||||
export const PixelContext = createContext<Pixel>(null);
|
export const PixelContext = createContext<Pixel>(null);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { usePixelsQuery, useNavigation } from '@/components/hooks';
|
|
||||||
import { PixelsTable } from './PixelsTable';
|
|
||||||
import { DataGrid } from '@/components/common/DataGrid';
|
import { DataGrid } from '@/components/common/DataGrid';
|
||||||
|
import { useNavigation, usePixelsQuery } from '@/components/hooks';
|
||||||
|
import { PixelsTable } from './PixelsTable';
|
||||||
|
|
||||||
export function PixelsDataTable() {
|
export function PixelsDataTable() {
|
||||||
const { teamId } = useNavigation();
|
const { teamId } = useNavigation();
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
'use client';
|
'use client';
|
||||||
import { PageBody } from '@/components/common/PageBody';
|
|
||||||
import { Column } from '@umami/react-zen';
|
import { Column } from '@umami/react-zen';
|
||||||
|
import { PageBody } from '@/components/common/PageBody';
|
||||||
import { PageHeader } from '@/components/common/PageHeader';
|
import { PageHeader } from '@/components/common/PageHeader';
|
||||||
import { PixelAddButton } from './PixelAddButton';
|
|
||||||
import { useMessages, useNavigation } from '@/components/hooks';
|
|
||||||
import { PixelsDataTable } from './PixelsDataTable';
|
|
||||||
import { Panel } from '@/components/common/Panel';
|
import { Panel } from '@/components/common/Panel';
|
||||||
|
import { useMessages, useNavigation } from '@/components/hooks';
|
||||||
|
import { PixelAddButton } from './PixelAddButton';
|
||||||
|
import { PixelsDataTable } from './PixelsDataTable';
|
||||||
|
|
||||||
export function PixelsPage() {
|
export function PixelsPage() {
|
||||||
const { formatMessage, labels } = useMessages();
|
const { formatMessage, labels } = useMessages();
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
|
import { DataColumn, DataTable, type DataTableProps, Row } from '@umami/react-zen';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import { DataTable, DataColumn, Row, DataTableProps } from '@umami/react-zen';
|
|
||||||
import { useMessages, useNavigation, useSlug } from '@/components/hooks';
|
|
||||||
import { DateDistance } from '@/components/common/DateDistance';
|
import { DateDistance } from '@/components/common/DateDistance';
|
||||||
import { PixelEditButton } from './PixelEditButton';
|
|
||||||
import { PixelDeleteButton } from './PixelDeleteButton';
|
|
||||||
import { ExternalLink } from '@/components/common/ExternalLink';
|
import { ExternalLink } from '@/components/common/ExternalLink';
|
||||||
|
import { useMessages, useNavigation, useSlug } from '@/components/hooks';
|
||||||
|
import { PixelDeleteButton } from './PixelDeleteButton';
|
||||||
|
import { PixelEditButton } from './PixelEditButton';
|
||||||
|
|
||||||
export function PixelsTable(props: DataTableProps) {
|
export function PixelsTable(props: DataTableProps) {
|
||||||
const { formatMessage, labels } = useMessages();
|
const { formatMessage, labels } = useMessages();
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import { Column, Row } from '@umami/react-zen';
|
import { Column, Row } from '@umami/react-zen';
|
||||||
import { WebsiteFilterButton } from '@/components/input/WebsiteFilterButton';
|
import { ExportButton } from '@/components/input/ExportButton';
|
||||||
import { WebsiteDateFilter } from '@/components/input/WebsiteDateFilter';
|
|
||||||
import { FilterBar } from '@/components/input/FilterBar';
|
import { FilterBar } from '@/components/input/FilterBar';
|
||||||
import { MonthFilter } from '@/components/input/MonthFilter';
|
import { MonthFilter } from '@/components/input/MonthFilter';
|
||||||
import { ExportButton } from '@/components/input/ExportButton';
|
import { WebsiteDateFilter } from '@/components/input/WebsiteDateFilter';
|
||||||
|
import { WebsiteFilterButton } from '@/components/input/WebsiteFilterButton';
|
||||||
|
|
||||||
export function PixelControls({
|
export function PixelControls({
|
||||||
pixelId: websiteId,
|
pixelId: websiteId,
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { usePixel, useMessages, useSlug } from '@/components/hooks';
|
|
||||||
import { PageHeader } from '@/components/common/PageHeader';
|
|
||||||
import { Icon, Text } from '@umami/react-zen';
|
import { Icon, Text } from '@umami/react-zen';
|
||||||
import { ExternalLink, Grid2x2 } from '@/components/icons';
|
|
||||||
import { LinkButton } from '@/components/common/LinkButton';
|
import { LinkButton } from '@/components/common/LinkButton';
|
||||||
|
import { PageHeader } from '@/components/common/PageHeader';
|
||||||
|
import { useMessages, usePixel, useSlug } from '@/components/hooks';
|
||||||
|
import { ExternalLink, Grid2x2 } from '@/components/icons';
|
||||||
|
|
||||||
export function PixelHeader() {
|
export function PixelHeader() {
|
||||||
const { formatMessage, labels } = useMessages();
|
const { formatMessage, labels } = useMessages();
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
|
import { LoadingPanel } from '@/components/common/LoadingPanel';
|
||||||
import { useDateRange, useMessages } from '@/components/hooks';
|
import { useDateRange, useMessages } from '@/components/hooks';
|
||||||
|
import { useWebsiteStatsQuery } from '@/components/hooks/queries/useWebsiteStatsQuery';
|
||||||
import { MetricCard } from '@/components/metrics/MetricCard';
|
import { MetricCard } from '@/components/metrics/MetricCard';
|
||||||
import { MetricsBar } from '@/components/metrics/MetricsBar';
|
import { MetricsBar } from '@/components/metrics/MetricsBar';
|
||||||
import { formatLongNumber } from '@/lib/format';
|
import { formatLongNumber } from '@/lib/format';
|
||||||
import { useWebsiteStatsQuery } from '@/components/hooks/queries/useWebsiteStatsQuery';
|
|
||||||
import { LoadingPanel } from '@/components/common/LoadingPanel';
|
|
||||||
|
|
||||||
export function PixelMetricsBar({
|
export function PixelMetricsBar({
|
||||||
pixelId,
|
pixelId,
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
'use client';
|
'use client';
|
||||||
import { PageBody } from '@/components/common/PageBody';
|
|
||||||
import { PixelProvider } from '@/app/(main)/pixels/PixelProvider';
|
|
||||||
import { PixelHeader } from '@/app/(main)/pixels/[pixelId]/PixelHeader';
|
|
||||||
import { Panel } from '@/components/common/Panel';
|
|
||||||
import { WebsiteChart } from '@/app/(main)/websites/[websiteId]/WebsiteChart';
|
|
||||||
import { PixelMetricsBar } from '@/app/(main)/pixels/[pixelId]/PixelMetricsBar';
|
|
||||||
import { PixelControls } from '@/app/(main)/pixels/[pixelId]/PixelControls';
|
|
||||||
import { PixelPanels } from '@/app/(main)/pixels/[pixelId]/PixelPanels';
|
|
||||||
import { Column, Grid } from '@umami/react-zen';
|
import { Column, Grid } from '@umami/react-zen';
|
||||||
|
import { PixelControls } from '@/app/(main)/pixels/[pixelId]/PixelControls';
|
||||||
|
import { PixelHeader } from '@/app/(main)/pixels/[pixelId]/PixelHeader';
|
||||||
|
import { PixelMetricsBar } from '@/app/(main)/pixels/[pixelId]/PixelMetricsBar';
|
||||||
|
import { PixelPanels } from '@/app/(main)/pixels/[pixelId]/PixelPanels';
|
||||||
|
import { PixelProvider } from '@/app/(main)/pixels/PixelProvider';
|
||||||
import { ExpandedViewModal } from '@/app/(main)/websites/[websiteId]/ExpandedViewModal';
|
import { ExpandedViewModal } from '@/app/(main)/websites/[websiteId]/ExpandedViewModal';
|
||||||
|
import { WebsiteChart } from '@/app/(main)/websites/[websiteId]/WebsiteChart';
|
||||||
|
import { PageBody } from '@/components/common/PageBody';
|
||||||
|
import { Panel } from '@/components/common/Panel';
|
||||||
|
|
||||||
const excludedIds = ['path', 'entry', 'exit', 'title', 'language', 'screen', 'event'];
|
const excludedIds = ['path', 'entry', 'exit', 'title', 'language', 'screen', 'event'];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import { Grid, Tabs, Tab, TabList, TabPanel, Heading } from '@umami/react-zen';
|
import { Grid, Heading, Tab, TabList, TabPanel, Tabs } from '@umami/react-zen';
|
||||||
import { GridRow } from '@/components/common/GridRow';
|
import { GridRow } from '@/components/common/GridRow';
|
||||||
import { Panel } from '@/components/common/Panel';
|
import { Panel } from '@/components/common/Panel';
|
||||||
import { WorldMap } from '@/components/metrics/WorldMap';
|
|
||||||
import { MetricsTable } from '@/components/metrics/MetricsTable';
|
|
||||||
import { useMessages } from '@/components/hooks';
|
import { useMessages } from '@/components/hooks';
|
||||||
|
import { MetricsTable } from '@/components/metrics/MetricsTable';
|
||||||
|
import { WorldMap } from '@/components/metrics/WorldMap';
|
||||||
|
|
||||||
export function PixelPanels({ pixelId }: { pixelId: string }) {
|
export function PixelPanels({ pixelId }: { pixelId: string }) {
|
||||||
const { formatMessage, labels } = useMessages();
|
const { formatMessage, labels } = useMessages();
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
|
import type { Metadata } from 'next';
|
||||||
import { PixelPage } from './PixelPage';
|
import { PixelPage } from './PixelPage';
|
||||||
import { Metadata } from 'next';
|
|
||||||
|
|
||||||
export default async function ({ params }: { params: { pixelId: string } }) {
|
export default async function ({ params }: { params: { pixelId: string } }) {
|
||||||
const { pixelId } = await params;
|
const { pixelId } = await params;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
|
import type { Metadata } from 'next';
|
||||||
import { PixelsPage } from './PixelsPage';
|
import { PixelsPage } from './PixelsPage';
|
||||||
import { Metadata } from 'next';
|
|
||||||
|
|
||||||
export default function () {
|
export default function () {
|
||||||
return <PixelsPage />;
|
return <PixelsPage />;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
'use client';
|
'use client';
|
||||||
import { PageBody } from '@/components/common/PageBody';
|
|
||||||
import { Column, Grid } from '@umami/react-zen';
|
import { Column, Grid } from '@umami/react-zen';
|
||||||
import { ReactNode } from 'react';
|
import type { ReactNode } from 'react';
|
||||||
|
import { PageBody } from '@/components/common/PageBody';
|
||||||
import { SettingsNav } from './SettingsNav';
|
import { SettingsNav } from './SettingsNav';
|
||||||
|
|
||||||
export function SettingsLayout({ children }: { children: ReactNode }) {
|
export function SettingsLayout({ children }: { children: ReactNode }) {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { Metadata } from 'next';
|
import type { Metadata } from 'next';
|
||||||
import { SettingsLayout } from './SettingsLayout';
|
import { SettingsLayout } from './SettingsLayout';
|
||||||
|
|
||||||
export default function ({ children }) {
|
export default function ({ children }) {
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import { useState } from 'react';
|
|
||||||
import { DateFilter } from '@/components/input/DateFilter';
|
|
||||||
import { Button, Row } from '@umami/react-zen';
|
import { Button, Row } from '@umami/react-zen';
|
||||||
|
import { useState } from 'react';
|
||||||
import { useMessages } from '@/components/hooks';
|
import { useMessages } from '@/components/hooks';
|
||||||
|
import { DateFilter } from '@/components/input/DateFilter';
|
||||||
import { DATE_RANGE_CONFIG, DEFAULT_DATE_RANGE_VALUE } from '@/lib/constants';
|
import { DATE_RANGE_CONFIG, DEFAULT_DATE_RANGE_VALUE } from '@/lib/constants';
|
||||||
import { setItem, getItem } from '@/lib/storage';
|
import { getItem, setItem } from '@/lib/storage';
|
||||||
|
|
||||||
export function DateRangeSetting() {
|
export function DateRangeSetting() {
|
||||||
const { formatMessage, labels } = useMessages();
|
const { formatMessage, labels } = useMessages();
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
|
import { Button, ListItem, Row, Select } from '@umami/react-zen';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { Button, Select, ListItem, Row } from '@umami/react-zen';
|
|
||||||
import { useLocale, useMessages } from '@/components/hooks';
|
import { useLocale, useMessages } from '@/components/hooks';
|
||||||
import { DEFAULT_LOCALE } from '@/lib/constants';
|
import { DEFAULT_LOCALE } from '@/lib/constants';
|
||||||
import { languages } from '@/lib/lang';
|
import { languages } from '@/lib/lang';
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import { Column, Label } from '@umami/react-zen';
|
import { Column, Label } from '@umami/react-zen';
|
||||||
import { useLoginQuery, useMessages } from '@/components/hooks';
|
import { useLoginQuery, useMessages } from '@/components/hooks';
|
||||||
import { TimezoneSetting } from './TimezoneSetting';
|
|
||||||
import { DateRangeSetting } from './DateRangeSetting';
|
import { DateRangeSetting } from './DateRangeSetting';
|
||||||
import { LanguageSetting } from './LanguageSetting';
|
import { LanguageSetting } from './LanguageSetting';
|
||||||
import { ThemeSetting } from './ThemeSetting';
|
import { ThemeSetting } from './ThemeSetting';
|
||||||
|
import { TimezoneSetting } from './TimezoneSetting';
|
||||||
|
|
||||||
export function PreferenceSettings() {
|
export function PreferenceSettings() {
|
||||||
const { user } = useLoginQuery();
|
const { user } = useLoginQuery();
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
'use client';
|
'use client';
|
||||||
import { Column } from '@umami/react-zen';
|
import { Column } from '@umami/react-zen';
|
||||||
import { useMessages } from '@/components/hooks';
|
|
||||||
import { Panel } from '@/components/common/Panel';
|
|
||||||
import { PreferenceSettings } from './PreferenceSettings';
|
|
||||||
import { PageHeader } from '@/components/common/PageHeader';
|
|
||||||
import { PageBody } from '@/components/common/PageBody';
|
import { PageBody } from '@/components/common/PageBody';
|
||||||
|
import { PageHeader } from '@/components/common/PageHeader';
|
||||||
|
import { Panel } from '@/components/common/Panel';
|
||||||
|
import { useMessages } from '@/components/hooks';
|
||||||
|
import { PreferenceSettings } from './PreferenceSettings';
|
||||||
|
|
||||||
export function PreferencesPage() {
|
export function PreferencesPage() {
|
||||||
const { formatMessage, labels } = useMessages();
|
const { formatMessage, labels } = useMessages();
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { Row, Button, Icon, useTheme } from '@umami/react-zen';
|
import { Button, Icon, Row, useTheme } from '@umami/react-zen';
|
||||||
import { Sun, Moon } from '@/components/icons';
|
import { Moon, Sun } from '@/components/icons';
|
||||||
|
|
||||||
export function ThemeSetting() {
|
export function ThemeSetting() {
|
||||||
const { theme, setTheme } = useTheme();
|
const { theme, setTheme } = useTheme();
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue