mirror of
https://github.com/umami-software/umami.git
synced 2025-12-06 01:18:00 +01:00
Merge branch 'dev' into feat/thumbnail-team-memory
This commit is contained in:
commit
f5d6d0ebaf
577 changed files with 2413 additions and 3645 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
|
||||
|
||||
# Script dependencies
|
||||
RUN pnpm 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/
|
||||
RUN pnpm --allow-build='@prisma/engines' add npm-run-all dotenv chalk semver prisma@6.18.0 @prisma/adapter-pg@6.18.0
|
||||
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/public ./public
|
||||
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 = {
|
||||
matcher: '/:path*',
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import 'dotenv/config';
|
||||
import pkg from './package.json' assert { type: 'json' };
|
||||
import pkg from './package.json' with { type: 'json' };
|
||||
|
||||
const TRACKER_SCRIPT = '/script.js';
|
||||
|
||||
|
|
|
|||
34
package.json
34
package.json
|
|
@ -42,24 +42,18 @@
|
|||
"download-country-names": "node scripts/download-country-names.js",
|
||||
"download-language-names": "node scripts/download-language-names.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",
|
||||
"postbuild": "node scripts/postbuild.js",
|
||||
"test": "jest",
|
||||
"cypress-open": "cypress open cypress run",
|
||||
"cypress-run": "cypress run cypress run"
|
||||
"cypress-run": "cypress run cypress run",
|
||||
"lint": "biome lint .",
|
||||
"format": "biome format --write .",
|
||||
"check": "biome check --write"
|
||||
},
|
||||
"lint-staged": {
|
||||
"**/*.{js,jsx,ts,tsx}": [
|
||||
"prettier --write",
|
||||
"eslint"
|
||||
],
|
||||
"**/*.css": [
|
||||
"stylelint --fix",
|
||||
"prettier --write"
|
||||
],
|
||||
"**/*.json": [
|
||||
"prettier --write"
|
||||
"**/*.{js,jsx,ts,tsx,json,css}": [
|
||||
"biome check --write --no-errors-on-unmatched --files-ignore-unknown=true"
|
||||
]
|
||||
},
|
||||
"cacheDirectories": [
|
||||
|
|
@ -78,7 +72,7 @@
|
|||
"@react-spring/web": "^10.0.3",
|
||||
"@svgr/cli": "^8.1.0",
|
||||
"@tanstack/react-query": "^5.90.5",
|
||||
"@umami/react-zen": "^0.207.0",
|
||||
"@umami/react-zen": "^0.210.0",
|
||||
"@umami/redis-client": "^0.29.0",
|
||||
"bcryptjs": "^3.0.2",
|
||||
"chalk": "^5.6.2",
|
||||
|
|
@ -95,7 +89,6 @@
|
|||
"detect-browser": "^5.2.0",
|
||||
"dotenv": "^17.2.3",
|
||||
"esbuild": "^0.25.11",
|
||||
"eslint-plugin-promise": "^6.1.1",
|
||||
"fs-extra": "^11.3.2",
|
||||
"immer": "^10.2.0",
|
||||
"ipaddr.js": "^2.0.1",
|
||||
|
|
@ -132,6 +125,7 @@
|
|||
"zustand": "^5.0.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "^2.3.6",
|
||||
"@formatjs/cli": "^4.2.29",
|
||||
"@netlify/plugin-nextjs": "^5.14.4",
|
||||
"@rollup/plugin-alias": "^5.0.0",
|
||||
|
|
@ -146,20 +140,9 @@
|
|||
"@types/react": "^19.2.2",
|
||||
"@types/react-dom": "^19.2.2",
|
||||
"@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",
|
||||
"cross-env": "^10.1.0",
|
||||
"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.3",
|
||||
"extract-react-intl-messages": "^4.1.1",
|
||||
"husky": "^9.1.7",
|
||||
"jest": "^29.7.0",
|
||||
|
|
@ -168,7 +151,6 @@
|
|||
"postcss-flexbugs-fixes": "^5.0.2",
|
||||
"postcss-import": "^15.1.0",
|
||||
"postcss-preset-env": "7.8.3",
|
||||
"prettier": "^3.6.2",
|
||||
"prompts": "2.4.2",
|
||||
"rollup": "^4.52.5",
|
||||
"rollup-plugin-copy": "^3.4.0",
|
||||
|
|
|
|||
2885
pnpm-lock.yaml
generated
2885
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'),
|
||||
},
|
||||
});
|
||||
|
|
@ -1,19 +1,19 @@
|
|||
{
|
||||
"name": "",
|
||||
"short_name": "",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/android-chrome-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/android-chrome-512x512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png"
|
||||
}
|
||||
],
|
||||
"theme_color": "#ffffff",
|
||||
"background_color": "#ffffff",
|
||||
"display": "standalone"
|
||||
"name": "",
|
||||
"short_name": "",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/android-chrome-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/android-chrome-512x512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png"
|
||||
}
|
||||
],
|
||||
"theme_color": "#ffffff",
|
||||
"background_color": "#ffffff",
|
||||
"display": "standalone"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ import 'dotenv/config';
|
|||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import https from 'https';
|
||||
import zlib from 'zlib';
|
||||
import tar from 'tar';
|
||||
import zlib from 'zlib';
|
||||
|
||||
if (process.env.VERCEL && !process.env.BUILD_GEO) {
|
||||
console.log('Vercel environment detected. Skipping geo setup.');
|
||||
|
|
@ -50,7 +50,9 @@ const downloadDirect = (url, originalUrl) =>
|
|||
https.get(url, res => {
|
||||
// Follow redirects
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -78,27 +80,29 @@ if (isDirectMmdb) {
|
|||
process.exit(1);
|
||||
});
|
||||
} else {
|
||||
downloadCompressed(url).then(
|
||||
res =>
|
||||
new Promise((resolve, reject) => {
|
||||
res.on('entry', entry => {
|
||||
if (entry.path.endsWith('.mmdb')) {
|
||||
const filename = path.join(dest, path.basename(entry.path));
|
||||
entry.pipe(fs.createWriteStream(filename));
|
||||
downloadCompressed(url)
|
||||
.then(
|
||||
res =>
|
||||
new Promise((resolve, reject) => {
|
||||
res.on('entry', entry => {
|
||||
if (entry.path.endsWith('.mmdb')) {
|
||||
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 => {
|
||||
reject(e);
|
||||
});
|
||||
res.on('finish', () => {
|
||||
resolve();
|
||||
});
|
||||
}),
|
||||
).catch(e => {
|
||||
console.error('Failed to download geo database:', e);
|
||||
process.exit(1);
|
||||
});
|
||||
res.on('error', e => {
|
||||
reject(e);
|
||||
});
|
||||
res.on('finish', () => {
|
||||
resolve();
|
||||
});
|
||||
}),
|
||||
)
|
||||
.catch(e => {
|
||||
console.error('Failed to download geo database:', e);
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
/* eslint-disable no-console */
|
||||
import 'dotenv/config';
|
||||
import { execSync } from 'node:child_process';
|
||||
import { PrismaPg } from '@prisma/adapter-pg';
|
||||
import chalk from 'chalk';
|
||||
import semver from 'semver';
|
||||
import { PrismaClient } from '../generated/prisma/client.js';
|
||||
import { PrismaPg } from '@prisma/adapter-pg';
|
||||
|
||||
const MIN_VERSION = '9.4.0';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
/* eslint-disable no-console */
|
||||
import fs from 'fs-extra';
|
||||
|
||||
import path from 'node:path';
|
||||
import https from 'https';
|
||||
import chalk from 'chalk';
|
||||
import fs from 'fs-extra';
|
||||
import https from 'https';
|
||||
|
||||
const src = path.resolve(process.cwd(), 'src/lang');
|
||||
const dest = path.resolve(process.cwd(), 'public/intl/country');
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
/* eslint-disable no-console */
|
||||
import fs from 'fs-extra';
|
||||
|
||||
import path from 'node:path';
|
||||
import https from 'https';
|
||||
import chalk from 'chalk';
|
||||
import fs from 'fs-extra';
|
||||
import https from 'https';
|
||||
|
||||
const src = path.resolve(process.cwd(), 'src/lang');
|
||||
const dest = path.resolve(process.cwd(), 'public/intl/language');
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import path from 'node:path';
|
||||
import fs from 'fs-extra';
|
||||
import del from 'del';
|
||||
import fs from 'fs-extra';
|
||||
import { createRequire } from 'module';
|
||||
|
||||
const require = createRequire(import.meta.url);
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/* eslint-disable no-console */
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import prettier from 'prettier';
|
||||
import { createRequire } from 'module';
|
||||
import prettier from 'prettier';
|
||||
|
||||
const require = createRequire(import.meta.url);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
export const dynamic = 'force-dynamic';
|
||||
|
||||
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 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');
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
export const dynamic = 'force-dynamic';
|
||||
|
||||
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 { 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 }> }) {
|
||||
const { slug } = await params;
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
'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 { 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 { 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 { removeItem, setItem } from '@/lib/storage';
|
||||
import { UpdateNotice } from './UpdateNotice';
|
||||
|
||||
export function App({ children }) {
|
||||
const { user, isLoading, error } = useLoginQuery();
|
||||
|
|
@ -27,7 +27,9 @@ export function App({ children }) {
|
|||
}
|
||||
|
||||
if (error) {
|
||||
window.location.href = `${process.env.basePath || ''}/login`;
|
||||
window.location.href = config.cloudMode
|
||||
? `${process.env.cloudUrl}/login`
|
||||
: `${process.env.basePath || ''}/login`;
|
||||
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 { useMessages, useNavigation } from '@/components/hooks';
|
||||
import { Globe, Grid2x2, LinkIcon } from '@/components/icons';
|
||||
import { MobileMenuButton } from '@/components/input/MobileMenuButton';
|
||||
import { NavButton } from '@/components/input/NavButton';
|
||||
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 { SettingsNav } from './settings/SettingsNav';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,20 +1,20 @@
|
|||
import { Key } from 'react';
|
||||
import Link from 'next/link';
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarSection,
|
||||
SidebarItem,
|
||||
SidebarHeader,
|
||||
Row,
|
||||
SidebarProps,
|
||||
Sidebar,
|
||||
SidebarHeader,
|
||||
SidebarItem,
|
||||
type SidebarProps,
|
||||
SidebarSection,
|
||||
ThemeButton,
|
||||
} from '@umami/react-zen';
|
||||
import { Globe, LinkIcon, Grid2x2, PanelLeft } from '@/components/icons';
|
||||
import { Logo } from '@/components/svg';
|
||||
import { useMessages, useNavigation, useGlobalState } from '@/components/hooks';
|
||||
import Link from 'next/link';
|
||||
import type { Key } from 'react';
|
||||
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 { PanelButton } from '@/components/input/PanelButton';
|
||||
import { LanguageButton } from '@/components/input/LanguageButton';
|
||||
import { Logo } from '@/components/svg';
|
||||
|
||||
export function SideNav(props: SidebarProps) {
|
||||
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 { ProfileButton } from '@/components/input/ProfileButton';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import { useEffect, useCallback, useState } from 'react';
|
||||
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 { AlertBanner, Button, Column, Row } from '@umami/react-zen';
|
||||
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 }) {
|
||||
const { formatMessage, labels, messages } = useMessages();
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
'use client';
|
||||
import { Column, Grid } from '@umami/react-zen';
|
||||
import type { ReactNode } from 'react';
|
||||
import { PageBody } from '@/components/common/PageBody';
|
||||
import { useLoginQuery } from '@/components/hooks';
|
||||
import { Column, Grid } from '@umami/react-zen';
|
||||
import { ReactNode } from 'react';
|
||||
import { AdminNav } from './AdminNav';
|
||||
|
||||
export function AdminLayout({ children }: { children: ReactNode }) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Metadata } from 'next';
|
||||
import type { Metadata } from 'next';
|
||||
import { AdminLayout } from './AdminLayout';
|
||||
|
||||
export default function ({ children }) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import type { ReactNode } from 'react';
|
||||
import { DataGrid } from '@/components/common/DataGrid';
|
||||
import { useTeamsQuery } from '@/components/hooks';
|
||||
import { AdminTeamsTable } from './AdminTeamsTable';
|
||||
import { ReactNode } from 'react';
|
||||
|
||||
export function AdminTeamsDataTable({
|
||||
showActions,
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
'use client';
|
||||
import { AdminTeamsDataTable } from './AdminTeamsDataTable';
|
||||
import { Column } from '@umami/react-zen';
|
||||
import { useMessages } from '@/components/hooks';
|
||||
import { PageHeader } from '@/components/common/PageHeader';
|
||||
import { Panel } from '@/components/common/Panel';
|
||||
import { useMessages } from '@/components/hooks';
|
||||
import { AdminTeamsDataTable } from './AdminTeamsDataTable';
|
||||
|
||||
export function AdminTeamsPage() {
|
||||
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 { useMessages } from '@/components/hooks';
|
||||
import { Edit, Trash } from '@/components/icons';
|
||||
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 Link from 'next/link';
|
||||
import { useState } from 'react';
|
||||
|
||||
export function AdminTeamsTable({
|
||||
data = [],
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import type { Metadata } from 'next';
|
||||
import { AdminTeamPage } from './AdminTeamPage';
|
||||
import { Metadata } from 'next';
|
||||
|
||||
export default async function ({ params }: { params: Promise<{ teamId: string }> }) {
|
||||
const { teamId } = await params;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Metadata } from 'next';
|
||||
import type { Metadata } from 'next';
|
||||
import { AdminTeamsPage } from './AdminTeamsPage';
|
||||
|
||||
export default function () {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { Button, Icon, Text, Modal, DialogTrigger, Dialog, useToast } from '@umami/react-zen';
|
||||
import { UserAddForm } from './UserAddForm';
|
||||
import { Button, Dialog, DialogTrigger, Icon, Modal, Text, useToast } from '@umami/react-zen';
|
||||
import { useMessages, useModified } from '@/components/hooks';
|
||||
import { Plus } from '@/components/icons';
|
||||
import { UserAddForm } from './UserAddForm';
|
||||
|
||||
export function UserAddButton({ onSave }: { onSave?: () => void }) {
|
||||
const { formatMessage, labels, messages } = useMessages();
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
import {
|
||||
Select,
|
||||
ListItem,
|
||||
Form,
|
||||
FormField,
|
||||
FormButtons,
|
||||
FormSubmitButton,
|
||||
TextField,
|
||||
PasswordField,
|
||||
Button,
|
||||
Form,
|
||||
FormButtons,
|
||||
FormField,
|
||||
FormSubmitButton,
|
||||
ListItem,
|
||||
PasswordField,
|
||||
Select,
|
||||
TextField,
|
||||
} from '@umami/react-zen';
|
||||
import { useMessages, useUpdateQuery } from '@/components/hooks';
|
||||
import { ROLES } from '@/lib/constants';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { Button, Icon, Modal, DialogTrigger, Dialog, Text } from '@umami/react-zen';
|
||||
import { useMessages, useLoginQuery } from '@/components/hooks';
|
||||
import { Button, Dialog, DialogTrigger, Icon, Modal, Text } from '@umami/react-zen';
|
||||
import { useLoginQuery, useMessages } from '@/components/hooks';
|
||||
import { Trash } from '@/components/icons';
|
||||
import { UserDeleteForm } from './UserDeleteForm';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import type { ReactNode } from 'react';
|
||||
import { DataGrid } from '@/components/common/DataGrid';
|
||||
import { useUsersQuery } from '@/components/hooks';
|
||||
import { UsersTable } from './UsersTable';
|
||||
import { ReactNode } from 'react';
|
||||
|
||||
export function UsersDataTable({ showActions }: { showActions?: boolean; children?: ReactNode }) {
|
||||
const queryResult = useUsersQuery();
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
'use client';
|
||||
import { UsersDataTable } from './UsersDataTable';
|
||||
import { Column } from '@umami/react-zen';
|
||||
import { useMessages } from '@/components/hooks';
|
||||
import { UserAddButton } from './UserAddButton';
|
||||
import { PageHeader } from '@/components/common/PageHeader';
|
||||
import { Panel } from '@/components/common/Panel';
|
||||
import { useMessages } from '@/components/hooks';
|
||||
import { UserAddButton } from './UserAddButton';
|
||||
import { UsersDataTable } from './UsersDataTable';
|
||||
|
||||
export function UsersPage() {
|
||||
const { formatMessage, labels } = useMessages();
|
||||
|
|
|
|||
|
|
@ -1,13 +1,12 @@
|
|||
import { useState } from 'react';
|
||||
import { Row, Text, Icon, DataTable, DataColumn, MenuItem, Modal } from '@umami/react-zen';
|
||||
import { DataColumn, DataTable, Icon, MenuItem, Modal, Row, Text } from '@umami/react-zen';
|
||||
import Link from 'next/link';
|
||||
import { ROLES } from '@/lib/constants';
|
||||
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 { useState } from 'react';
|
||||
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({
|
||||
data = [],
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
import {
|
||||
Select,
|
||||
ListItem,
|
||||
Form,
|
||||
FormField,
|
||||
FormButtons,
|
||||
TextField,
|
||||
FormField,
|
||||
FormSubmitButton,
|
||||
ListItem,
|
||||
PasswordField,
|
||||
Select,
|
||||
TextField,
|
||||
} from '@umami/react-zen';
|
||||
import { useLoginQuery, useMessages, useUpdateQuery, useUser } from '@/components/hooks';
|
||||
import { ROLES } from '@/lib/constants';
|
||||
|
|
@ -30,7 +30,7 @@ export function UserEditForm({ userId, onSave }: { userId: string; onSave?: () =
|
|||
};
|
||||
|
||||
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)}>
|
||||
<TextField data-test="input-username" />
|
||||
</FormField>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { User } from '@/components/icons';
|
||||
import { PageHeader } from '@/components/common/PageHeader';
|
||||
import { useUser } from '@/components/hooks';
|
||||
import { User } from '@/components/icons';
|
||||
|
||||
export function UserHeader() {
|
||||
const user = useUser();
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
'use client';
|
||||
import { Column } from '@umami/react-zen';
|
||||
import { UserSettings } from './UserSettings';
|
||||
import { UserProvider } from './UserProvider';
|
||||
import { UserHeader } from '@/app/(main)/admin/users/[userId]/UserHeader';
|
||||
import { Panel } from '@/components/common/Panel';
|
||||
import { UserProvider } from './UserProvider';
|
||||
import { UserSettings } from './UserSettings';
|
||||
|
||||
export function UserPage({ userId }: { userId: string }) {
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { createContext, ReactNode } from 'react';
|
||||
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 type { User } from '@/generated/prisma/client';
|
||||
|
||||
export const UserContext = createContext<User>(null);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { Column, Tabs, Tab, TabList, TabPanel } from '@umami/react-zen';
|
||||
import { UserEditForm } from './UserEditForm';
|
||||
import { Column, Tab, TabList, TabPanel, Tabs } from '@umami/react-zen';
|
||||
import { useMessages } from '@/components/hooks';
|
||||
import { UserEditForm } from './UserEditForm';
|
||||
import { UserWebsites } from './UserWebsites';
|
||||
|
||||
export function UserSettings({ userId }: { userId: string }) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { WebsitesTable } from '@/app/(main)/websites/WebsitesTable';
|
||||
import { DataGrid } from '@/components/common/DataGrid';
|
||||
import { useUserWebsitesQuery } from '@/components/hooks';
|
||||
import { WebsitesTable } from '@/app/(main)/websites/WebsitesTable';
|
||||
|
||||
export function UserWebsites({ userId }) {
|
||||
const queryResult = useUserWebsitesQuery({ userId });
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import type { Metadata } from 'next';
|
||||
import { UserPage } from './UserPage';
|
||||
import { Metadata } from 'next';
|
||||
|
||||
export default async function ({ params }: { params: Promise<{ userId: string }> }) {
|
||||
const { userId } = await params;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Metadata } from 'next';
|
||||
import type { Metadata } from 'next';
|
||||
import { UsersPage } from './UsersPage';
|
||||
|
||||
export default function () {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
'use client';
|
||||
import { AdminWebsitesDataTable } from './AdminWebsitesDataTable';
|
||||
import { Column } from '@umami/react-zen';
|
||||
import { useMessages } from '@/components/hooks';
|
||||
import { PageHeader } from '@/components/common/PageHeader';
|
||||
import { Panel } from '@/components/common/Panel';
|
||||
import { useMessages } from '@/components/hooks';
|
||||
import { AdminWebsitesDataTable } from './AdminWebsitesDataTable';
|
||||
|
||||
export function AdminWebsitesPage() {
|
||||
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 { Row, Text, Icon, DataTable, DataColumn, MenuItem, Modal, Dialog } from '@umami/react-zen';
|
||||
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 { useState } from 'react';
|
||||
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[] }) {
|
||||
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';
|
||||
|
||||
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';
|
||||
|
||||
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 { Button, Icon, Modal, Dialog, DialogTrigger, Text, useToast } from '@umami/react-zen';
|
||||
import { Plus } from '@/components/icons';
|
||||
import { BoardAddForm } from './BoardAddForm';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { Form, FormField, FormSubmitButton, Row, TextField, Button } from '@umami/react-zen';
|
||||
import { useUpdateQuery, useMessages } from '@/components/hooks';
|
||||
import { Button, Form, FormField, FormSubmitButton, Row, TextField } from '@umami/react-zen';
|
||||
import { useMessages, useUpdateQuery } from '@/components/hooks';
|
||||
import { DOMAIN_REGEX } from '@/lib/constants';
|
||||
|
||||
export function BoardAddForm({
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
'use client';
|
||||
import { Column } from '@umami/react-zen';
|
||||
import { PageHeader } from '@/components/common/PageHeader';
|
||||
import { PageBody } from '@/components/common/PageBody';
|
||||
import { PageHeader } from '@/components/common/PageHeader';
|
||||
import { BoardAddButton } from './BoardAddButton';
|
||||
|
||||
export function BoardsPage() {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Metadata } from 'next';
|
||||
import type { Metadata } from 'next';
|
||||
import { Board } from './Board';
|
||||
|
||||
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';
|
||||
|
||||
export default function () {
|
||||
|
|
|
|||
|
|
@ -1,25 +1,25 @@
|
|||
'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 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 { useWebsiteQuery } from '@/components/hooks';
|
||||
import { PageBody } from '@/components/common/PageBody';
|
||||
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 }) {
|
||||
const { data } = useWebsiteQuery(websiteId);
|
||||
|
||||
function handleRunScript() {
|
||||
window['umami'].track(props => ({
|
||||
window.umami.track(props => ({
|
||||
...props,
|
||||
url: '/page-view',
|
||||
referrer: 'https://www.google.com',
|
||||
}));
|
||||
window['umami'].track('track-event-no-data');
|
||||
window['umami'].track('track-event-with-data', {
|
||||
window.umami.track('track-event-no-data');
|
||||
window.umami.track('track-event-with-data', {
|
||||
test: 'test-data',
|
||||
boolean: true,
|
||||
booleanError: 'true',
|
||||
|
|
@ -40,32 +40,32 @@ export function TestConsolePage({ websiteId }: { websiteId: string }) {
|
|||
}
|
||||
|
||||
function handleRunRevenue() {
|
||||
window['umami'].track(props => ({
|
||||
window.umami.track(props => ({
|
||||
...props,
|
||||
url: '/checkout-cart',
|
||||
referrer: 'https://www.google.com',
|
||||
}));
|
||||
window['umami'].track('checkout-cart', {
|
||||
window.umami.track('checkout-cart', {
|
||||
revenue: parseFloat((Math.random() * 1000).toFixed(2)),
|
||||
currency: 'USD',
|
||||
});
|
||||
window['umami'].track('affiliate-link', {
|
||||
window.umami.track('affiliate-link', {
|
||||
revenue: parseFloat((Math.random() * 1000).toFixed(2)),
|
||||
currency: 'USD',
|
||||
});
|
||||
window['umami'].track('promotion-link', {
|
||||
window.umami.track('promotion-link', {
|
||||
revenue: parseFloat((Math.random() * 1000).toFixed(2)),
|
||||
currency: 'USD',
|
||||
});
|
||||
window['umami'].track('checkout-cart', {
|
||||
window.umami.track('checkout-cart', {
|
||||
revenue: parseFloat((Math.random() * 1000).toFixed(2)),
|
||||
currency: 'EUR',
|
||||
});
|
||||
window['umami'].track('promotion-link', {
|
||||
window.umami.track('promotion-link', {
|
||||
revenue: parseFloat((Math.random() * 1000).toFixed(2)),
|
||||
currency: 'EUR',
|
||||
});
|
||||
window['umami'].track('affiliate-link', {
|
||||
window.umami.track('affiliate-link', {
|
||||
item1: {
|
||||
productIdentity: 'ABC424',
|
||||
revenue: parseFloat((Math.random() * 10000).toFixed(2)),
|
||||
|
|
@ -80,7 +80,7 @@ export function TestConsolePage({ websiteId }: { websiteId: string }) {
|
|||
}
|
||||
|
||||
function handleRunIdentify() {
|
||||
window['umami'].identify({
|
||||
window.umami.identify({
|
||||
userId: 123,
|
||||
name: 'brian',
|
||||
number: Math.random() * 100,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Metadata } from 'next';
|
||||
import type { Metadata } from 'next';
|
||||
import { TestConsolePage } from './TestConsolePage';
|
||||
|
||||
async function getEnabled() {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
'use client';
|
||||
import { Column } from '@umami/react-zen';
|
||||
import { PageBody } from '@/components/common/PageBody';
|
||||
import { PageHeader } from '@/components/common/PageHeader';
|
||||
import { useMessages } from '@/components/hooks';
|
||||
import { PageBody } from '@/components/common/PageBody';
|
||||
|
||||
export function DashboardPage() {
|
||||
const { formatMessage, labels } = useMessages();
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Metadata } from 'next';
|
||||
import type { Metadata } from 'next';
|
||||
import { DashboardPage } from './DashboardPage';
|
||||
|
||||
export default async function () {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import type { Metadata } from 'next';
|
||||
import { Suspense } from 'react';
|
||||
import { Metadata } from 'next';
|
||||
import { App } from './App';
|
||||
|
||||
export default function ({ children }) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { useMessages } from '@/components/hooks';
|
||||
import { Plus } from '@/components/icons';
|
||||
import { LinkEditForm } from './LinkEditForm';
|
||||
import { DialogButton } from '@/components/input/DialogButton';
|
||||
import { LinkEditForm } from './LinkEditForm';
|
||||
|
||||
export function LinkAddButton({ teamId }: { teamId?: string }) {
|
||||
const { formatMessage, labels } = useMessages();
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { Trash } from '@/components/icons';
|
||||
import { ConfirmationForm } from '@/components/common/ConfirmationForm';
|
||||
import { messages } from '@/components/messages';
|
||||
import { useDeleteQuery, useMessages } from '@/components/hooks';
|
||||
import { Trash } from '@/components/icons';
|
||||
import { DialogButton } from '@/components/input/DialogButton';
|
||||
import { messages } from '@/components/messages';
|
||||
|
||||
export function LinkDeleteButton({
|
||||
linkId,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { Edit } from '@/components/icons';
|
||||
import { LinkEditForm } from './LinkEditForm';
|
||||
import { useMessages } from '@/components/hooks';
|
||||
import { Edit } from '@/components/icons';
|
||||
import { DialogButton } from '@/components/input/DialogButton';
|
||||
import { LinkEditForm } from './LinkEditForm';
|
||||
|
||||
export function LinkEditButton({ linkId }: { linkId: string }) {
|
||||
const { formatMessage, labels } = useMessages();
|
||||
|
|
|
|||
|
|
@ -1,22 +1,21 @@
|
|||
import { useState, useEffect } from 'react';
|
||||
import {
|
||||
Button,
|
||||
Column,
|
||||
Form,
|
||||
FormField,
|
||||
FormSubmitButton,
|
||||
Icon,
|
||||
Label,
|
||||
Loading,
|
||||
Row,
|
||||
TextField,
|
||||
Button,
|
||||
Label,
|
||||
Column,
|
||||
Icon,
|
||||
Loading,
|
||||
} from '@umami/react-zen';
|
||||
import { useConfig, useLinkQuery } from '@/components/hooks';
|
||||
import { useMessages } from '@/components/hooks';
|
||||
import { RefreshCw } from '@/components/icons';
|
||||
import { getRandomChars } from '@/lib/generate';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useConfig, useLinkQuery, useMessages } from '@/components/hooks';
|
||||
import { useUpdateQuery } from '@/components/hooks/queries/useUpdateQuery';
|
||||
import { RefreshCw } from '@/components/icons';
|
||||
import { LINKS_URL } from '@/lib/constants';
|
||||
import { getRandomChars } from '@/lib/generate';
|
||||
import { isValidUrl } from '@/lib/url';
|
||||
|
||||
const generateId = () => getRandomChars(9);
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
'use client';
|
||||
import { createContext, ReactNode } from 'react';
|
||||
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 type { Link } from '@/generated/prisma/client';
|
||||
|
||||
export const LinkContext = createContext<Link>(null);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { DataGrid } from '@/components/common/DataGrid';
|
||||
import { useLinksQuery, useNavigation } from '@/components/hooks';
|
||||
import { LinksTable } from './LinksTable';
|
||||
import { DataGrid } from '@/components/common/DataGrid';
|
||||
|
||||
export function LinksDataTable() {
|
||||
const { teamId } = useNavigation();
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
'use client';
|
||||
import { PageBody } from '@/components/common/PageBody';
|
||||
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 { PageBody } from '@/components/common/PageBody';
|
||||
import { PageHeader } from '@/components/common/PageHeader';
|
||||
import { Panel } from '@/components/common/Panel';
|
||||
import { useMessages, useNavigation } from '@/components/hooks';
|
||||
import { LinkAddButton } from './LinkAddButton';
|
||||
|
||||
export function LinksPage() {
|
||||
const { formatMessage, labels } = useMessages();
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import { DataColumn, DataTable, type DataTableProps, Row } from '@umami/react-zen';
|
||||
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 { ExternalLink } from '@/components/common/ExternalLink';
|
||||
import { LinkEditButton } from './LinkEditButton';
|
||||
import { useMessages, useNavigation, useSlug } from '@/components/hooks';
|
||||
import { LinkDeleteButton } from './LinkDeleteButton';
|
||||
import { LinkEditButton } from './LinkEditButton';
|
||||
|
||||
export function LinksTable(props: DataTableProps) {
|
||||
const { formatMessage, labels } = useMessages();
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import { Column, Row } from '@umami/react-zen';
|
||||
import { WebsiteFilterButton } from '@/components/input/WebsiteFilterButton';
|
||||
import { WebsiteDateFilter } from '@/components/input/WebsiteDateFilter';
|
||||
import { ExportButton } from '@/components/input/ExportButton';
|
||||
import { FilterBar } from '@/components/input/FilterBar';
|
||||
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({
|
||||
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 { ExternalLink, Link } from '@/components/icons';
|
||||
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() {
|
||||
const { formatMessage, labels } = useMessages();
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import { LoadingPanel } from '@/components/common/LoadingPanel';
|
||||
import { useDateRange, useMessages } from '@/components/hooks';
|
||||
import { useWebsiteStatsQuery } from '@/components/hooks/queries/useWebsiteStatsQuery';
|
||||
import { MetricCard } from '@/components/metrics/MetricCard';
|
||||
import { MetricsBar } from '@/components/metrics/MetricsBar';
|
||||
import { formatLongNumber } from '@/lib/format';
|
||||
import { useWebsiteStatsQuery } from '@/components/hooks/queries/useWebsiteStatsQuery';
|
||||
import { LoadingPanel } from '@/components/common/LoadingPanel';
|
||||
|
||||
export function LinkMetricsBar({
|
||||
linkId,
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
'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 { 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 { 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'];
|
||||
|
||||
|
|
|
|||
|
|
@ -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 { Panel } from '@/components/common/Panel';
|
||||
import { WorldMap } from '@/components/metrics/WorldMap';
|
||||
import { MetricsTable } from '@/components/metrics/MetricsTable';
|
||||
import { useMessages } from '@/components/hooks';
|
||||
import { MetricsTable } from '@/components/metrics/MetricsTable';
|
||||
import { WorldMap } from '@/components/metrics/WorldMap';
|
||||
|
||||
export function LinkPanels({ linkId }: { linkId: string }) {
|
||||
const { formatMessage, labels } = useMessages();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import type { Metadata } from 'next';
|
||||
import { LinkPage } from './LinkPage';
|
||||
import { Metadata } from 'next';
|
||||
|
||||
export default async function ({ params }: { params: Promise<{ linkId: string }> }) {
|
||||
const { linkId } = await params;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import type { Metadata } from 'next';
|
||||
import { LinksPage } from './LinksPage';
|
||||
import { Metadata } from 'next';
|
||||
|
||||
export default function () {
|
||||
return <LinksPage />;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { useMessages } from '@/components/hooks';
|
||||
import { Plus } from '@/components/icons';
|
||||
import { PixelEditForm } from './PixelEditForm';
|
||||
import { DialogButton } from '@/components/input/DialogButton';
|
||||
import { PixelEditForm } from './PixelEditForm';
|
||||
|
||||
export function PixelAddButton({ teamId }: { teamId?: string }) {
|
||||
const { formatMessage, labels } = useMessages();
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { Trash } from '@/components/icons';
|
||||
import { ConfirmationForm } from '@/components/common/ConfirmationForm';
|
||||
import { messages } from '@/components/messages';
|
||||
import { useDeleteQuery, useMessages, useModified } from '@/components/hooks';
|
||||
import { Trash } from '@/components/icons';
|
||||
import { DialogButton } from '@/components/input/DialogButton';
|
||||
import { messages } from '@/components/messages';
|
||||
|
||||
export function PixelDeleteButton({
|
||||
pixelId,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { Edit } from '@/components/icons';
|
||||
import { PixelEditForm } from './PixelEditForm';
|
||||
import { useMessages } from '@/components/hooks';
|
||||
import { Edit } from '@/components/icons';
|
||||
import { DialogButton } from '@/components/input/DialogButton';
|
||||
import { PixelEditForm } from './PixelEditForm';
|
||||
|
||||
export function PixelEditButton({ pixelId }: { pixelId: string }) {
|
||||
const { formatMessage, labels } = useMessages();
|
||||
|
|
|
|||
|
|
@ -1,22 +1,21 @@
|
|||
import {
|
||||
Button,
|
||||
Column,
|
||||
Form,
|
||||
FormField,
|
||||
FormSubmitButton,
|
||||
Icon,
|
||||
Label,
|
||||
Loading,
|
||||
Row,
|
||||
TextField,
|
||||
Button,
|
||||
Label,
|
||||
Column,
|
||||
Icon,
|
||||
Loading,
|
||||
} 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 { 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 { getRandomChars } from '@/lib/generate';
|
||||
|
||||
const generateId = () => getRandomChars(9);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
'use client';
|
||||
import { createContext, ReactNode } from 'react';
|
||||
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 type { Pixel } from '@/generated/prisma/client';
|
||||
|
||||
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 { useNavigation, usePixelsQuery } from '@/components/hooks';
|
||||
import { PixelsTable } from './PixelsTable';
|
||||
|
||||
export function PixelsDataTable() {
|
||||
const { teamId } = useNavigation();
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
'use client';
|
||||
import { PageBody } from '@/components/common/PageBody';
|
||||
import { Column } from '@umami/react-zen';
|
||||
import { PageBody } from '@/components/common/PageBody';
|
||||
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 { useMessages, useNavigation } from '@/components/hooks';
|
||||
import { PixelAddButton } from './PixelAddButton';
|
||||
import { PixelsDataTable } from './PixelsDataTable';
|
||||
|
||||
export function PixelsPage() {
|
||||
const { formatMessage, labels } = useMessages();
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import { DataColumn, DataTable, type DataTableProps, Row } from '@umami/react-zen';
|
||||
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 { PixelEditButton } from './PixelEditButton';
|
||||
import { PixelDeleteButton } from './PixelDeleteButton';
|
||||
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) {
|
||||
const { formatMessage, labels } = useMessages();
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import { Column, Row } from '@umami/react-zen';
|
||||
import { WebsiteFilterButton } from '@/components/input/WebsiteFilterButton';
|
||||
import { WebsiteDateFilter } from '@/components/input/WebsiteDateFilter';
|
||||
import { ExportButton } from '@/components/input/ExportButton';
|
||||
import { FilterBar } from '@/components/input/FilterBar';
|
||||
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({
|
||||
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 { ExternalLink, Grid2x2 } from '@/components/icons';
|
||||
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() {
|
||||
const { formatMessage, labels } = useMessages();
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import { LoadingPanel } from '@/components/common/LoadingPanel';
|
||||
import { useDateRange, useMessages } from '@/components/hooks';
|
||||
import { useWebsiteStatsQuery } from '@/components/hooks/queries/useWebsiteStatsQuery';
|
||||
import { MetricCard } from '@/components/metrics/MetricCard';
|
||||
import { MetricsBar } from '@/components/metrics/MetricsBar';
|
||||
import { formatLongNumber } from '@/lib/format';
|
||||
import { useWebsiteStatsQuery } from '@/components/hooks/queries/useWebsiteStatsQuery';
|
||||
import { LoadingPanel } from '@/components/common/LoadingPanel';
|
||||
|
||||
export function PixelMetricsBar({
|
||||
pixelId,
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
'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 { 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 { 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'];
|
||||
|
||||
|
|
|
|||
|
|
@ -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 { Panel } from '@/components/common/Panel';
|
||||
import { WorldMap } from '@/components/metrics/WorldMap';
|
||||
import { MetricsTable } from '@/components/metrics/MetricsTable';
|
||||
import { useMessages } from '@/components/hooks';
|
||||
import { MetricsTable } from '@/components/metrics/MetricsTable';
|
||||
import { WorldMap } from '@/components/metrics/WorldMap';
|
||||
|
||||
export function PixelPanels({ pixelId }: { pixelId: string }) {
|
||||
const { formatMessage, labels } = useMessages();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import type { Metadata } from 'next';
|
||||
import { PixelPage } from './PixelPage';
|
||||
import { Metadata } from 'next';
|
||||
|
||||
export default async function ({ params }: { params: { pixelId: string } }) {
|
||||
const { pixelId } = await params;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import type { Metadata } from 'next';
|
||||
import { PixelsPage } from './PixelsPage';
|
||||
import { Metadata } from 'next';
|
||||
|
||||
export default function () {
|
||||
return <PixelsPage />;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
'use client';
|
||||
import { PageBody } from '@/components/common/PageBody';
|
||||
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';
|
||||
|
||||
export function SettingsLayout({ children }: { children: ReactNode }) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Metadata } from 'next';
|
||||
import type { Metadata } from 'next';
|
||||
import { SettingsLayout } from './SettingsLayout';
|
||||
|
||||
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 { useState } from 'react';
|
||||
import { useMessages } from '@/components/hooks';
|
||||
import { DateFilter } from '@/components/input/DateFilter';
|
||||
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() {
|
||||
const { formatMessage, labels } = useMessages();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { Button, ListItem, Row, Select } from '@umami/react-zen';
|
||||
import { useState } from 'react';
|
||||
import { Button, Select, ListItem, Row } from '@umami/react-zen';
|
||||
import { useLocale, useMessages } from '@/components/hooks';
|
||||
import { DEFAULT_LOCALE } from '@/lib/constants';
|
||||
import { languages } from '@/lib/lang';
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import { Column, Label } from '@umami/react-zen';
|
||||
import { useLoginQuery, useMessages } from '@/components/hooks';
|
||||
import { TimezoneSetting } from './TimezoneSetting';
|
||||
import { DateRangeSetting } from './DateRangeSetting';
|
||||
import { LanguageSetting } from './LanguageSetting';
|
||||
import { ThemeSetting } from './ThemeSetting';
|
||||
import { TimezoneSetting } from './TimezoneSetting';
|
||||
|
||||
export function PreferenceSettings() {
|
||||
const { user } = useLoginQuery();
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
'use client';
|
||||
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 { PageHeader } from '@/components/common/PageHeader';
|
||||
import { Panel } from '@/components/common/Panel';
|
||||
import { useMessages } from '@/components/hooks';
|
||||
import { PreferenceSettings } from './PreferenceSettings';
|
||||
|
||||
export function PreferencesPage() {
|
||||
const { formatMessage, labels } = useMessages();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { Row, Button, Icon, useTheme } from '@umami/react-zen';
|
||||
import { Sun, Moon } from '@/components/icons';
|
||||
import { Button, Icon, Row, useTheme } from '@umami/react-zen';
|
||||
import { Moon, Sun } from '@/components/icons';
|
||||
|
||||
export function ThemeSetting() {
|
||||
const { theme, setTheme } = useTheme();
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { Button, ListItem, Row, Select } from '@umami/react-zen';
|
||||
import { useState } from 'react';
|
||||
import { Row, Select, ListItem, Button } from '@umami/react-zen';
|
||||
import { useTimezone, useMessages } from '@/components/hooks';
|
||||
import { useMessages, useTimezone } from '@/components/hooks';
|
||||
import { getTimezone } from '@/lib/date';
|
||||
|
||||
const timezones = Intl.supportedValuesOf('timeZone');
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Metadata } from 'next';
|
||||
import type { Metadata } from 'next';
|
||||
import { PreferencesPage } from './PreferencesPage';
|
||||
|
||||
export default function () {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { Button, Icon, Text, useToast, DialogTrigger, Dialog, Modal } from '@umami/react-zen';
|
||||
import { PasswordEditForm } from './PasswordEditForm';
|
||||
import { LockKeyhole } from '@/components/icons';
|
||||
import { Button, Dialog, DialogTrigger, Icon, Modal, Text, useToast } from '@umami/react-zen';
|
||||
import { useMessages } from '@/components/hooks';
|
||||
import { LockKeyhole } from '@/components/icons';
|
||||
import { PasswordEditForm } from './PasswordEditForm';
|
||||
|
||||
export function PasswordChangeButton() {
|
||||
const { formatMessage, labels, messages } = useMessages();
|
||||
|
|
|
|||
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