Compare commits

..

No commits in common. "d51f0641a687c8f37e15ee706da47b4264a5e362" and "94321192b813591c122b4b281bb3ba65d63cf631" have entirely different histories.

13 changed files with 167 additions and 493 deletions

View file

@ -66,13 +66,13 @@
"@dicebear/core": "^9.2.3", "@dicebear/core": "^9.2.3",
"@fontsource/inter": "^5.2.8", "@fontsource/inter": "^5.2.8",
"@hello-pangea/dnd": "^17.0.0", "@hello-pangea/dnd": "^17.0.0",
"@prisma/adapter-pg": "^7.0.0", "@prisma/adapter-pg": "^6.18.0",
"@prisma/client": "^7.0.0", "@prisma/client": "^6.18.0",
"@prisma/extension-read-replicas": "^0.4.1", "@prisma/extension-read-replicas": "^0.4.1",
"@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.210.0", "@umami/react-zen": "^0.208.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",
@ -107,7 +107,7 @@
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"papaparse": "^5.5.3", "papaparse": "^5.5.3",
"pg": "^8.16.3", "pg": "^8.16.3",
"prisma": "^7.0.0", "prisma": "^6.18.0",
"pure-rand": "^7.0.1", "pure-rand": "^7.0.1",
"react": "^19.2.0", "react": "^19.2.0",
"react-dom": "^19.2.0", "react-dom": "^19.2.0",

492
pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff

View file

@ -1,8 +0,0 @@
import 'dotenv/config';
import { defineConfig, env } from 'prisma/config';
export default defineConfig({
datasource: {
url: env('DATABASE_URL'),
},
});

View file

@ -6,6 +6,7 @@ generator client {
datasource db { datasource db {
provider = "postgresql" provider = "postgresql"
url = env("DATABASE_URL")
} }
model User { model User {

View file

@ -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"
} }

View file

@ -50,23 +50,21 @@ 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) downloadDirect(res.headers.location, originalUrl || url).then(resolve).catch(reject);
.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);
}); });
@ -80,29 +78,27 @@ if (isDirectMmdb) {
process.exit(1); process.exit(1);
}); });
} else { } else {
downloadCompressed(url) downloadCompressed(url).then(
.then( res =>
res => new Promise((resolve, reject) => {
new Promise((resolve, reject) => { res.on('entry', entry => {
res.on('entry', entry => { if (entry.path.endsWith('.mmdb')) {
if (entry.path.endsWith('.mmdb')) { const filename = path.join(dest, path.basename(entry.path));
const filename = path.join(dest, path.basename(entry.path)); entry.pipe(fs.createWriteStream(filename));
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 => {
.catch(e => { console.error('Failed to download geo database:', e);
console.error('Failed to download geo database:', e); process.exit(1);
process.exit(1); });
});
} }

View file

@ -1,13 +1,13 @@
'use client'; 'use client';
import { Column, Grid, Loading, Row } from '@umami/react-zen'; import { Grid, Loading, Column, Row } from '@umami/react-zen';
import Script from 'next/script'; import Script from 'next/script';
import { useEffect } from 'react';
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'; 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 { LAST_TEAM_CONFIG } from '@/lib/constants';
export function App({ children }) { export function App({ children }) {
const { user, isLoading, error } = useLoginQuery(); const { user, isLoading, error } = useLoginQuery();
@ -27,9 +27,7 @@ export function App({ children }) {
} }
if (error) { if (error) {
window.location.href = config.cloudMode window.location.href = `${process.env.basePath || ''}/login`;
? `${process.env.cloudUrl}/login`
: `${process.env.basePath || ''}/login`;
return null; return null;
} }

View file

@ -208,7 +208,7 @@
.start:before, .start:before,
.end:before { .end:before {
content: ""; content: '';
position: absolute; position: absolute;
border-radius: 100%; border-radius: 100%;
border: 3px solid var(--journey-line-color); border: 3px solid var(--journey-line-color);

View file

@ -137,6 +137,11 @@ export function MetricLabel({ type, data }: MetricLabelProps) {
return formatValue(label, 'language'); return formatValue(label, 'language');
default: default:
return <FilterLink type={type} value={label} />; return (
<FilterLink
type={type}
value={label}
/>
);
} }
} }

View file

@ -14,21 +14,23 @@ describe('renderNumberLabels', () => {
expect(renderNumberLabels(input)).toBe(expected); expect(renderNumberLabels(input)).toBe(expected);
}); });
test.each([ test.each([['12500', '12.5k']])(
['12500', '12.5k'], "formats numbers ≥ 10K as 'X.Xk' (%s → %s)",
])("formats numbers ≥ 10K as 'X.Xk' (%s → %s)", (input, expected) => { (input, expected) => {
expect(renderNumberLabels(input)).toBe(expected); expect(renderNumberLabels(input)).toBe(expected);
}); },
);
test.each([['1500', '1.50k']])("formats numbers ≥ 1K as 'X.XXk' (%s → %s)", (input, expected) => { test.each([['1500', '1.50k']])("formats numbers ≥ 1K as 'X.XXk' (%s → %s)", (input, expected) => {
expect(renderNumberLabels(input)).toBe(expected); expect(renderNumberLabels(input)).toBe(expected);
}); });
test.each([ test.each([['999', '999']])(
['999', '999'], 'calls formatNumber for values < 1000 (%s → %s)',
])('calls formatNumber for values < 1000 (%s → %s)', (input, expected) => { (input, expected) => {
expect(renderNumberLabels(input)).toBe(expected); expect(renderNumberLabels(input)).toBe(expected);
}); },
);
test.each([ test.each([
['0', '0'], ['0', '0'],

View file

@ -1,10 +1,10 @@
import debug from 'debug';
import { PrismaPg } from '@prisma/adapter-pg'; import { PrismaPg } from '@prisma/adapter-pg';
import { readReplicas } from '@prisma/extension-read-replicas'; import { readReplicas } from '@prisma/extension-read-replicas';
import debug from 'debug';
import { PrismaClient } from '@/generated/prisma/client'; import { PrismaClient } from '@/generated/prisma/client';
import { DEFAULT_PAGE_SIZE, FILTER_COLUMNS, OPERATORS, SESSION_COLUMNS } from './constants'; import { SESSION_COLUMNS, OPERATORS, DEFAULT_PAGE_SIZE, FILTER_COLUMNS } from './constants';
import { QueryOptions, QueryFilters, Operator } from './types';
import { filtersObjectToArray } from './params'; import { filtersObjectToArray } from './params';
import type { Operator, QueryFilters, QueryOptions } from './types';
const log = debug('umami:prisma'); const log = debug('umami:prisma');

View file

@ -1,6 +1,6 @@
import type { Prisma } from '@/generated/prisma/client'; import { Prisma } from '@/generated/prisma/client';
import prisma from '@/lib/prisma'; import prisma from '@/lib/prisma';
import type { QueryFilters } from '@/lib/types'; import { QueryFilters } from '@/lib/types';
export async function findPixel(criteria: Prisma.PixelFindUniqueArgs) { export async function findPixel(criteria: Prisma.PixelFindUniqueArgs) {
return prisma.client.pixel.findUnique(criteria); return prisma.client.pixel.findUnique(criteria);

View file

@ -8,7 +8,7 @@ body {
min-height: 100vh; min-height: 100vh;
} }
html[style*="padding-right"] { html[style*='padding-right'] {
padding-right: 0 !important; padding-right: 0 !important;
} }