mirror of
https://github.com/umami-software/umami.git
synced 2025-12-06 01:18:00 +01:00
Compare commits
7 commits
41d2a24f9d
...
33cb195fd0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
33cb195fd0 | ||
|
|
64767b1896 | ||
|
|
be1b787789 | ||
|
|
dae7327ed3 | ||
|
|
a06490af74 | ||
|
|
65f657dd23 | ||
|
|
6b584338e3 |
12 changed files with 1174 additions and 1244 deletions
18
Dockerfile
18
Dockerfile
|
|
@ -1,5 +1,7 @@
|
|||
ARG NODE_IMAGE_VERSION="22-alpine"
|
||||
|
||||
# Install dependencies only when needed
|
||||
FROM node:22-alpine AS deps
|
||||
FROM node:${NODE_IMAGE_VERSION} AS deps
|
||||
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
|
||||
RUN apk add --no-cache libc6-compat
|
||||
WORKDIR /app
|
||||
|
|
@ -8,7 +10,7 @@ RUN npm install -g pnpm
|
|||
RUN pnpm install --frozen-lockfile
|
||||
|
||||
# Rebuild the source code only when needed
|
||||
FROM node:22-alpine AS builder
|
||||
FROM node:${NODE_IMAGE_VERSION} AS builder
|
||||
WORKDIR /app
|
||||
COPY --from=deps /app/node_modules ./node_modules
|
||||
COPY . .
|
||||
|
|
@ -25,9 +27,10 @@ ENV NEXT_TELEMETRY_DISABLED=1
|
|||
RUN npm run build-docker
|
||||
|
||||
# Production image, copy all the files and run next
|
||||
FROM node:22-alpine AS runner
|
||||
FROM node:${NODE_IMAGE_VERSION} AS runner
|
||||
WORKDIR /app
|
||||
|
||||
ARG PRISMA_VERSION="6.19.0"
|
||||
ARG NODE_OPTIONS
|
||||
|
||||
ENV NODE_ENV=production
|
||||
|
|
@ -36,13 +39,14 @@ ENV NODE_OPTIONS=$NODE_OPTIONS
|
|||
|
||||
RUN addgroup --system --gid 1001 nodejs
|
||||
RUN adduser --system --uid 1001 nextjs
|
||||
RUN npm install -g pnpm
|
||||
|
||||
RUN set -x \
|
||||
&& apk add --no-cache curl
|
||||
&& apk add --no-cache curl \
|
||||
&& npm install -g pnpm
|
||||
|
||||
# Script dependencies
|
||||
RUN pnpm --allow-build='@prisma/engines' 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@${PRISMA_VERSION} \
|
||||
@prisma/adapter-pg@${PRISMA_VERSION}
|
||||
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/public ./public
|
||||
COPY --from=builder /app/prisma ./prisma
|
||||
|
|
|
|||
24
package.json
24
package.json
|
|
@ -72,7 +72,7 @@
|
|||
"@prisma/extension-read-replicas": "^0.4.1",
|
||||
"@react-spring/web": "^10.0.3",
|
||||
"@svgr/cli": "^8.1.0",
|
||||
"@tanstack/react-query": "^5.90.5",
|
||||
"@tanstack/react-query": "^5.90.11",
|
||||
"@umami/react-zen": "^0.211.0",
|
||||
"@umami/redis-client": "^0.29.0",
|
||||
"bcryptjs": "^3.0.2",
|
||||
|
|
@ -92,7 +92,7 @@
|
|||
"esbuild": "^0.25.11",
|
||||
"fs-extra": "^11.3.2",
|
||||
"immer": "^10.2.0",
|
||||
"ipaddr.js": "^2.0.1",
|
||||
"ipaddr.js": "^2.3.0",
|
||||
"is-ci": "^3.0.1",
|
||||
"is-docker": "^3.0.0",
|
||||
"is-localhost-ip": "^2.0.0",
|
||||
|
|
@ -102,15 +102,15 @@
|
|||
"kafkajs": "^2.1.0",
|
||||
"lucide-react": "^0.543.0",
|
||||
"maxmind": "^5.0.0",
|
||||
"next": "15.5.3",
|
||||
"next": "^15.5.7",
|
||||
"node-fetch": "^3.2.8",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"papaparse": "^5.5.3",
|
||||
"pg": "^8.16.3",
|
||||
"prisma": "^6.18.0",
|
||||
"pure-rand": "^7.0.1",
|
||||
"react": "^19.2.0",
|
||||
"react-dom": "^19.2.0",
|
||||
"react": "^19.2.1",
|
||||
"react-dom": "^19.2.1",
|
||||
"react-error-boundary": "^4.0.4",
|
||||
"react-intl": "^7.1.14",
|
||||
"react-simple-maps": "^2.3.0",
|
||||
|
|
@ -122,13 +122,13 @@
|
|||
"thenby": "^1.3.4",
|
||||
"ua-parser-js": "^2.0.6",
|
||||
"uuid": "^11.1.0",
|
||||
"zod": "^4.1.12",
|
||||
"zustand": "^5.0.8"
|
||||
"zod": "^4.1.13",
|
||||
"zustand": "^5.0.9"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "^2.3.6",
|
||||
"@biomejs/biome": "^2.3.8",
|
||||
"@formatjs/cli": "^4.2.29",
|
||||
"@netlify/plugin-nextjs": "^5.14.4",
|
||||
"@netlify/plugin-nextjs": "^5.15.1",
|
||||
"@rollup/plugin-alias": "^5.0.0",
|
||||
"@rollup/plugin-commonjs": "^25.0.4",
|
||||
"@rollup/plugin-json": "^6.0.0",
|
||||
|
|
@ -138,7 +138,7 @@
|
|||
"@rollup/plugin-typescript": "^12.3.0",
|
||||
"@types/jest": "^30.0.0",
|
||||
"@types/node": "^24.9.2",
|
||||
"@types/react": "^19.2.2",
|
||||
"@types/react": "^19.2.7",
|
||||
"@types/react-dom": "^19.2.2",
|
||||
"@types/react-window": "^1.8.8",
|
||||
"babel-plugin-react-compiler": "19.1.0-rc.2",
|
||||
|
|
@ -156,7 +156,7 @@
|
|||
"rollup": "^4.52.5",
|
||||
"rollup-plugin-copy": "^3.4.0",
|
||||
"rollup-plugin-delete": "^3.0.1",
|
||||
"rollup-plugin-dts": "^6.2.3",
|
||||
"rollup-plugin-dts": "^6.3.0",
|
||||
"rollup-plugin-node-externals": "^8.1.1",
|
||||
"rollup-plugin-peer-deps-external": "^2.2.4",
|
||||
"rollup-plugin-postcss": "^4.0.2",
|
||||
|
|
@ -165,7 +165,7 @@
|
|||
"stylelint-config-prettier": "^9.0.3",
|
||||
"stylelint-config-recommended": "^14.0.0",
|
||||
"tar": "^6.1.2",
|
||||
"ts-jest": "^29.4.5",
|
||||
"ts-jest": "^29.4.6",
|
||||
"ts-node": "^10.9.1",
|
||||
"tsup": "^8.5.0",
|
||||
"tsx": "^4.19.0",
|
||||
|
|
|
|||
2220
pnpm-lock.yaml
generated
2220
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load diff
|
|
@ -1,33 +0,0 @@
|
|||
-- 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");
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
-- 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,7 +27,6 @@ model User {
|
|||
pixels Pixel[] @relation("user")
|
||||
teams TeamUser[]
|
||||
reports Report[]
|
||||
boards Board[] @relation("user")
|
||||
|
||||
@@map("user")
|
||||
}
|
||||
|
|
@ -100,23 +99,23 @@ model WebsiteEvent {
|
|||
sessionId String @map("session_id") @db.Uuid
|
||||
visitId String @map("visit_id") @db.Uuid
|
||||
createdAt DateTime? @default(now()) @map("created_at") @db.Timestamptz(6)
|
||||
urlPath String @map("url_path") @db.VarChar(1024)
|
||||
urlQuery String? @map("url_query") @db.VarChar(1024)
|
||||
utmSource String? @map("utm_source") @db.VarChar(512)
|
||||
utmMedium String? @map("utm_medium") @db.VarChar(512)
|
||||
utmCampaign String? @map("utm_campaign") @db.VarChar(512)
|
||||
utmContent String? @map("utm_content") @db.VarChar(512)
|
||||
utmTerm String? @map("utm_term") @db.VarChar(512)
|
||||
referrerPath String? @map("referrer_path") @db.VarChar(1024)
|
||||
referrerQuery String? @map("referrer_query") @db.VarChar(1024)
|
||||
urlPath String @map("url_path") @db.VarChar(500)
|
||||
urlQuery String? @map("url_query") @db.VarChar(500)
|
||||
utmSource String? @map("utm_source") @db.VarChar(255)
|
||||
utmMedium String? @map("utm_medium") @db.VarChar(255)
|
||||
utmCampaign String? @map("utm_campaign") @db.VarChar(255)
|
||||
utmContent String? @map("utm_content") @db.VarChar(255)
|
||||
utmTerm String? @map("utm_term") @db.VarChar(255)
|
||||
referrerPath String? @map("referrer_path") @db.VarChar(500)
|
||||
referrerQuery String? @map("referrer_query") @db.VarChar(500)
|
||||
referrerDomain String? @map("referrer_domain") @db.VarChar(500)
|
||||
pageTitle String? @map("page_title") @db.VarChar(500)
|
||||
gclid String? @db.VarChar(1024)
|
||||
fbclid String? @db.VarChar(1024)
|
||||
msclkid String? @db.VarChar(1024)
|
||||
ttclid String? @db.VarChar(1024)
|
||||
lifatid String? @map("li_fat_id") @db.VarChar(1024)
|
||||
twclid String? @db.VarChar(1024)
|
||||
gclid String? @db.VarChar(255)
|
||||
fbclid String? @db.VarChar(255)
|
||||
msclkid String? @db.VarChar(255)
|
||||
ttclid String? @db.VarChar(255)
|
||||
lifatid String? @map("li_fat_id") @db.VarChar(255)
|
||||
twclid String? @db.VarChar(255)
|
||||
eventType Int @default(1) @map("event_type") @db.Integer
|
||||
eventName String? @map("event_name") @db.VarChar(50)
|
||||
tag String? @db.VarChar(50)
|
||||
|
|
@ -200,7 +199,6 @@ model Team {
|
|||
members TeamUser[]
|
||||
links Link[]
|
||||
pixels Pixel[]
|
||||
boards Board[]
|
||||
|
||||
@@index([accessCode])
|
||||
@@map("team")
|
||||
|
|
@ -318,25 +316,3 @@ model Pixel {
|
|||
@@index([createdAt])
|
||||
@@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,4 +1,4 @@
|
|||
import { Icon, Text } from '@umami/react-zen';
|
||||
import { IconLabel } from '@umami/react-zen';
|
||||
import { LinkButton } from '@/components/common/LinkButton';
|
||||
import { PageHeader } from '@/components/common/PageHeader';
|
||||
import { useLink, useMessages, useSlug } from '@/components/hooks';
|
||||
|
|
@ -10,12 +10,9 @@ export function LinkHeader() {
|
|||
const link = useLink();
|
||||
|
||||
return (
|
||||
<PageHeader title={link.name} description={link.url} icon={<Link />} marginBottom="3">
|
||||
<LinkButton href={getSlugUrl(link.slug)} target="_blank" prefetch={false}>
|
||||
<Icon>
|
||||
<ExternalLink />
|
||||
</Icon>
|
||||
<Text>{formatMessage(labels.view)}</Text>
|
||||
<PageHeader title={link.name} description={link.url} icon={<Link />}>
|
||||
<LinkButton href={getSlugUrl(link.slug)} target="_blank" prefetch={false} asAnchor>
|
||||
<IconLabel icon={<ExternalLink />} label={formatMessage(labels.view)} />
|
||||
</LinkButton>
|
||||
</PageHeader>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Icon, Text } from '@umami/react-zen';
|
||||
import { IconLabel } from '@umami/react-zen';
|
||||
import { LinkButton } from '@/components/common/LinkButton';
|
||||
import { PageHeader } from '@/components/common/PageHeader';
|
||||
import { useMessages, usePixel, useSlug } from '@/components/hooks';
|
||||
|
|
@ -10,12 +10,9 @@ export function PixelHeader() {
|
|||
const pixel = usePixel();
|
||||
|
||||
return (
|
||||
<PageHeader title={pixel.name} icon={<Grid2x2 />} marginBottom="3">
|
||||
<LinkButton href={getSlugUrl(pixel.slug)} target="_blank" prefetch={false}>
|
||||
<Icon>
|
||||
<ExternalLink />
|
||||
</Icon>
|
||||
<Text>{formatMessage(labels.view)}</Text>
|
||||
<PageHeader title={pixel.name} icon={<Grid2x2 />}>
|
||||
<LinkButton href={getSlugUrl(pixel.slug)} target="_blank" prefetch={false} asAnchor>
|
||||
<IconLabel icon={<ExternalLink />} label={formatMessage(labels.view)} />
|
||||
</LinkButton>
|
||||
</PageHeader>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ export function WebsiteHeader({ showActions }: { showActions?: boolean }) {
|
|||
<PageHeader
|
||||
title={website.name}
|
||||
icon={<Favicon domain={website.domain} />}
|
||||
marginBottom="3"
|
||||
titleHref={renderUrl(`/websites/${website.id}`, false)}
|
||||
>
|
||||
<Row alignItems="center" gap="6" wrap="wrap">
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ export interface LinkButtonProps extends ButtonProps {
|
|||
scroll?: boolean;
|
||||
variant?: any;
|
||||
prefetch?: boolean;
|
||||
asAnchor?: boolean;
|
||||
children?: ReactNode;
|
||||
}
|
||||
|
||||
|
|
@ -19,15 +20,22 @@ export function LinkButton({
|
|||
target,
|
||||
prefetch,
|
||||
children,
|
||||
asAnchor,
|
||||
...props
|
||||
}: LinkButtonProps) {
|
||||
const { dir } = useLocale();
|
||||
|
||||
return (
|
||||
<Button {...props} variant={variant} asChild>
|
||||
<Link href={href} dir={dir} scroll={scroll} target={target} prefetch={prefetch}>
|
||||
{children}
|
||||
</Link>
|
||||
{asAnchor ? (
|
||||
<a href={href} target={target}>
|
||||
{children}
|
||||
</a>
|
||||
) : (
|
||||
<Link href={href} dir={dir} scroll={scroll} target={target} prefetch={prefetch}>
|
||||
{children}
|
||||
</Link>
|
||||
)}
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,7 +50,9 @@ export function PageHeader({
|
|||
</Text>
|
||||
)}
|
||||
</Column>
|
||||
<Row justifyContent="flex-end">{children}</Row>
|
||||
<Row justifyContent="flex-end" alignItems="center">
|
||||
{children}
|
||||
</Row>
|
||||
</Grid>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { Button, Icon, ListItem, Row, Select, Text } from '@umami/react-zen';
|
||||
import { isAfter } from 'date-fns';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import { useMemo } from 'react';
|
||||
import { useDateRange, useDateRangeQuery, useMessages, useNavigation } from '@/components/hooks';
|
||||
import { ChevronRight } from '@/components/icons';
|
||||
import { getDateRangeValue } from '@/lib/date';
|
||||
|
|
@ -45,13 +45,9 @@ export function WebsiteDateFilter({
|
|||
}
|
||||
};
|
||||
|
||||
const handleIncrement = useCallback(
|
||||
(increment: number) => {
|
||||
router.push(updateParams({ offset: +offset + increment }));
|
||||
},
|
||||
[offset],
|
||||
);
|
||||
|
||||
const handleIncrement = increment => {
|
||||
router.push(updateParams({ offset: Number(offset) + increment }));
|
||||
};
|
||||
const handleSelect = (compare: any) => {
|
||||
router.push(updateParams({ compare }));
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue