mirror of
https://github.com/umami-software/umami.git
synced 2026-02-04 04:37:11 +01:00
Compare commits
2 commits
6d480d9c36
...
889a404650
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
889a404650 | ||
|
|
b6013c3ee8 |
30 changed files with 97 additions and 39 deletions
41
prisma/migrations/15_add_share/migration.sql
Normal file
41
prisma/migrations/15_add_share/migration.sql
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "share" (
|
||||||
|
"share_id" UUID NOT NULL,
|
||||||
|
"entity_id" UUID NOT NULL,
|
||||||
|
"share_type" INTEGER NOT NULL,
|
||||||
|
"share_code" VARCHAR(50),
|
||||||
|
"parameters" JSONB NOT NULL,
|
||||||
|
"created_at" TIMESTAMPTZ(6) DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"updated_at" TIMESTAMPTZ(6),
|
||||||
|
|
||||||
|
CONSTRAINT "share_pkey" PRIMARY KEY ("share_id")
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "share_share_id_key" ON "share"("share_id");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "share_share_code_key" ON "share"("share_code");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE INDEX "share_entity_id_idx" ON "share"("entity_id");
|
||||||
|
|
||||||
|
-- MigrateData
|
||||||
|
INSERT INTO "share" (share_id, entity_id, share_type, share_code, parameters, created_at)
|
||||||
|
SELECT gen_random_uuid(),
|
||||||
|
website_id,
|
||||||
|
1,
|
||||||
|
share_id,
|
||||||
|
'{}'::jsonb,
|
||||||
|
now()
|
||||||
|
FROM "website"
|
||||||
|
WHERE share_id IS NOT NULL;
|
||||||
|
|
||||||
|
-- DropIndex
|
||||||
|
DROP INDEX "website_share_id_idx";
|
||||||
|
|
||||||
|
-- DropIndex
|
||||||
|
DROP INDEX "website_share_id_key";
|
||||||
|
|
||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "website" DROP COLUMN "share_id";
|
||||||
|
|
@ -67,7 +67,6 @@ model Website {
|
||||||
id String @id @unique @map("website_id") @db.Uuid
|
id String @id @unique @map("website_id") @db.Uuid
|
||||||
name String @db.VarChar(100)
|
name String @db.VarChar(100)
|
||||||
domain String? @db.VarChar(500)
|
domain String? @db.VarChar(500)
|
||||||
shareId String? @unique @map("share_id") @db.VarChar(50)
|
|
||||||
resetAt DateTime? @map("reset_at") @db.Timestamptz(6)
|
resetAt DateTime? @map("reset_at") @db.Timestamptz(6)
|
||||||
userId String? @map("user_id") @db.Uuid
|
userId String? @map("user_id") @db.Uuid
|
||||||
teamId String? @map("team_id") @db.Uuid
|
teamId String? @map("team_id") @db.Uuid
|
||||||
|
|
@ -88,7 +87,6 @@ model Website {
|
||||||
@@index([userId])
|
@@index([userId])
|
||||||
@@index([teamId])
|
@@index([teamId])
|
||||||
@@index([createdAt])
|
@@index([createdAt])
|
||||||
@@index([shareId])
|
|
||||||
@@index([createdBy])
|
@@index([createdBy])
|
||||||
@@map("website")
|
@@map("website")
|
||||||
}
|
}
|
||||||
|
|
@ -316,3 +314,16 @@ model Pixel {
|
||||||
@@index([createdAt])
|
@@index([createdAt])
|
||||||
@@map("pixel")
|
@@map("pixel")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
model Share {
|
||||||
|
id String @id() @unique() @map("share_id") @db.Uuid
|
||||||
|
entityId String @map("entity_id") @db.Uuid
|
||||||
|
shareType Int @map("share_type") @db.Integer
|
||||||
|
shareCode String? @unique @map("share_code") @db.VarChar(50)
|
||||||
|
parameters Json
|
||||||
|
createdAt DateTime? @default(now()) @map("created_at") @db.Timestamptz(6)
|
||||||
|
updatedAt DateTime? @updatedAt @map("updated_at") @db.Timestamptz(6)
|
||||||
|
|
||||||
|
@@index([entityId])
|
||||||
|
@@map("share")
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,8 @@ export async function POST(request: Request) {
|
||||||
return unauthorized();
|
return unauthorized();
|
||||||
}
|
}
|
||||||
|
|
||||||
const parameters = await setWebsiteDate(websiteId, auth.user.id, body.parameters);
|
const parameters = await setWebsiteDate(websiteId, body.parameters);
|
||||||
const filters = await getQueryFilters(body.filters, websiteId, auth.user?.id);
|
const filters = await getQueryFilters(body.filters, websiteId);
|
||||||
|
|
||||||
const data = await getAttribution(websiteId, parameters as AttributionParameters, filters);
|
const data = await getAttribution(websiteId, parameters as AttributionParameters, filters);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,8 @@ export async function POST(request: Request) {
|
||||||
return unauthorized();
|
return unauthorized();
|
||||||
}
|
}
|
||||||
|
|
||||||
const parameters = await setWebsiteDate(websiteId, auth.user.id, body.parameters);
|
const parameters = await setWebsiteDate(websiteId, body.parameters);
|
||||||
const filters = await getQueryFilters(body.filters, websiteId, auth.user?.id);
|
const filters = await getQueryFilters(body.filters, websiteId);
|
||||||
|
|
||||||
const data = await getBreakdown(websiteId, parameters as BreakdownParameters, filters);
|
const data = await getBreakdown(websiteId, parameters as BreakdownParameters, filters);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,8 @@ export async function POST(request: Request) {
|
||||||
return unauthorized();
|
return unauthorized();
|
||||||
}
|
}
|
||||||
|
|
||||||
const parameters = await setWebsiteDate(websiteId, auth.user.id, body.parameters);
|
const parameters = await setWebsiteDate(websiteId, body.parameters);
|
||||||
const filters = await getQueryFilters(body.filters, websiteId, auth.user?.id);
|
const filters = await getQueryFilters(body.filters, websiteId);
|
||||||
|
|
||||||
const data = await getFunnel(websiteId, parameters as FunnelParameters, filters);
|
const data = await getFunnel(websiteId, parameters as FunnelParameters, filters);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,8 @@ export async function POST(request: Request) {
|
||||||
return unauthorized();
|
return unauthorized();
|
||||||
}
|
}
|
||||||
|
|
||||||
const parameters = await setWebsiteDate(websiteId, auth.user.id, body.parameters);
|
const parameters = await setWebsiteDate(websiteId, body.parameters);
|
||||||
const filters = await getQueryFilters(body.filters, websiteId, auth.user?.id);
|
const filters = await getQueryFilters(body.filters, websiteId);
|
||||||
|
|
||||||
const data = await getGoal(websiteId, parameters as GoalParameters, filters);
|
const data = await getGoal(websiteId, parameters as GoalParameters, filters);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,8 @@ export async function POST(request: Request) {
|
||||||
return unauthorized();
|
return unauthorized();
|
||||||
}
|
}
|
||||||
|
|
||||||
const filters = await getQueryFilters(body.filters, websiteId, auth.user?.id);
|
const filters = await getQueryFilters(body.filters, websiteId);
|
||||||
const parameters = await setWebsiteDate(websiteId, auth.user.id, body.parameters);
|
const parameters = await setWebsiteDate(websiteId, body.parameters);
|
||||||
|
|
||||||
const data = await getRetention(websiteId, parameters as RetentionParameters, filters);
|
const data = await getRetention(websiteId, parameters as RetentionParameters, filters);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,8 @@ export async function POST(request: Request) {
|
||||||
return unauthorized();
|
return unauthorized();
|
||||||
}
|
}
|
||||||
|
|
||||||
const parameters = await setWebsiteDate(websiteId, auth.user.id, body.parameters);
|
const parameters = await setWebsiteDate(websiteId, body.parameters);
|
||||||
const filters = await getQueryFilters(body.filters, websiteId, auth.user?.id);
|
const filters = await getQueryFilters(body.filters, websiteId);
|
||||||
|
|
||||||
const data = await getRevenue(websiteId, parameters as RevenuParameters, filters);
|
const data = await getRevenue(websiteId, parameters as RevenuParameters, filters);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,8 @@ export async function POST(request: Request) {
|
||||||
return unauthorized();
|
return unauthorized();
|
||||||
}
|
}
|
||||||
|
|
||||||
const filters = await getQueryFilters(body.filters, websiteId, auth.user?.id);
|
const filters = await getQueryFilters(body.filters, websiteId);
|
||||||
const parameters = await setWebsiteDate(websiteId, auth.user.id, body.parameters);
|
const parameters = await setWebsiteDate(websiteId, body.parameters);
|
||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
utm_source: [],
|
utm_source: [],
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ export async function GET(
|
||||||
return unauthorized();
|
return unauthorized();
|
||||||
}
|
}
|
||||||
|
|
||||||
const filters = await getQueryFilters(query, websiteId, auth.user?.id);
|
const filters = await getQueryFilters(query, websiteId);
|
||||||
|
|
||||||
const data = await getEventDataEvents(websiteId, {
|
const data = await getEventDataEvents(websiteId, {
|
||||||
...filters,
|
...filters,
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ export async function GET(
|
||||||
return unauthorized();
|
return unauthorized();
|
||||||
}
|
}
|
||||||
|
|
||||||
const filters = await getQueryFilters(query, websiteId, auth.user?.id);
|
const filters = await getQueryFilters(query, websiteId);
|
||||||
|
|
||||||
const data = await getEventDataFields(websiteId, filters);
|
const data = await getEventDataFields(websiteId, filters);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ export async function GET(
|
||||||
return unauthorized();
|
return unauthorized();
|
||||||
}
|
}
|
||||||
|
|
||||||
const filters = await getQueryFilters(query, websiteId, auth.user?.id);
|
const filters = await getQueryFilters(query, websiteId);
|
||||||
|
|
||||||
const data = await getEventDataProperties(websiteId, filters);
|
const data = await getEventDataProperties(websiteId, filters);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ export async function GET(
|
||||||
return unauthorized();
|
return unauthorized();
|
||||||
}
|
}
|
||||||
|
|
||||||
const filters = await getQueryFilters(query, websiteId, auth.user?.id);
|
const filters = await getQueryFilters(query, websiteId);
|
||||||
|
|
||||||
const data = await getEventDataStats(websiteId, filters);
|
const data = await getEventDataStats(websiteId, filters);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ export async function GET(
|
||||||
}
|
}
|
||||||
|
|
||||||
const { propertyName } = query;
|
const { propertyName } = query;
|
||||||
const filters = await getQueryFilters(query, websiteId, auth.user?.id);
|
const filters = await getQueryFilters(query, websiteId);
|
||||||
|
|
||||||
const data = await getEventDataValues(websiteId, {
|
const data = await getEventDataValues(websiteId, {
|
||||||
...filters,
|
...filters,
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ export async function GET(
|
||||||
return unauthorized();
|
return unauthorized();
|
||||||
}
|
}
|
||||||
|
|
||||||
const filters = await getQueryFilters(query, websiteId, auth.user?.id);
|
const filters = await getQueryFilters(query, websiteId);
|
||||||
|
|
||||||
const data = await getWebsiteEvents(websiteId, filters);
|
const data = await getWebsiteEvents(websiteId, filters);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ export async function GET(
|
||||||
return unauthorized();
|
return unauthorized();
|
||||||
}
|
}
|
||||||
|
|
||||||
const filters = await getQueryFilters(query, websiteId, auth.user?.id);
|
const filters = await getQueryFilters(query, websiteId);
|
||||||
|
|
||||||
const data = await getEventStats(websiteId, filters);
|
const data = await getEventStats(websiteId, filters);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ export async function GET(
|
||||||
return unauthorized();
|
return unauthorized();
|
||||||
}
|
}
|
||||||
|
|
||||||
const filters = await getQueryFilters(query, websiteId, auth.user?.id);
|
const filters = await getQueryFilters(query, websiteId);
|
||||||
|
|
||||||
const [events, pages, referrers, browsers, os, devices, countries] = await Promise.all([
|
const [events, pages, referrers, browsers, os, devices, countries] = await Promise.all([
|
||||||
getEventMetrics(websiteId, { type: 'event' }, filters),
|
getEventMetrics(websiteId, { type: 'event' }, filters),
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ export async function GET(
|
||||||
}
|
}
|
||||||
|
|
||||||
const { type, limit, offset, search } = query;
|
const { type, limit, offset, search } = query;
|
||||||
const filters = await getQueryFilters(query, websiteId, auth.user?.id);
|
const filters = await getQueryFilters(query, websiteId);
|
||||||
|
|
||||||
if (search) {
|
if (search) {
|
||||||
filters[type] = `c.${search}`;
|
filters[type] = `c.${search}`;
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ export async function GET(
|
||||||
}
|
}
|
||||||
|
|
||||||
const { type, limit, offset, search } = query;
|
const { type, limit, offset, search } = query;
|
||||||
const filters = await getQueryFilters(query, websiteId, auth.user?.id);
|
const filters = await getQueryFilters(query, websiteId);
|
||||||
|
|
||||||
if (search) {
|
if (search) {
|
||||||
filters[type] = `c.${search}`;
|
filters[type] = `c.${search}`;
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ export async function GET(
|
||||||
return unauthorized();
|
return unauthorized();
|
||||||
}
|
}
|
||||||
|
|
||||||
const filters = await getQueryFilters(query, websiteId, auth.user?.id);
|
const filters = await getQueryFilters(query, websiteId);
|
||||||
|
|
||||||
const [pageviews, sessions] = await Promise.all([
|
const [pageviews, sessions] = await Promise.all([
|
||||||
getPageviewStats(websiteId, filters),
|
getPageviewStats(websiteId, filters),
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ export async function GET(
|
||||||
return unauthorized();
|
return unauthorized();
|
||||||
}
|
}
|
||||||
|
|
||||||
const filters = await getQueryFilters(query, websiteId, auth.user?.id);
|
const filters = await getQueryFilters(query, websiteId);
|
||||||
|
|
||||||
const data = await getSessionDataProperties(websiteId, filters);
|
const data = await getSessionDataProperties(websiteId, filters);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ export async function GET(
|
||||||
}
|
}
|
||||||
|
|
||||||
const { propertyName } = query;
|
const { propertyName } = query;
|
||||||
const filters = await getQueryFilters(query, websiteId, auth.user?.id);
|
const filters = await getQueryFilters(query, websiteId);
|
||||||
|
|
||||||
const data = await getSessionDataValues(websiteId, {
|
const data = await getSessionDataValues(websiteId, {
|
||||||
...filters,
|
...filters,
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ export async function GET(
|
||||||
return unauthorized();
|
return unauthorized();
|
||||||
}
|
}
|
||||||
|
|
||||||
const filters = await getQueryFilters(query, websiteId, auth.user?.id);
|
const filters = await getQueryFilters(query, websiteId);
|
||||||
|
|
||||||
const data = await getSessionActivity(websiteId, sessionId, filters);
|
const data = await getSessionActivity(websiteId, sessionId, filters);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ export async function GET(
|
||||||
return unauthorized();
|
return unauthorized();
|
||||||
}
|
}
|
||||||
|
|
||||||
const filters = await getQueryFilters(query, websiteId, auth.user?.id);
|
const filters = await getQueryFilters(query, websiteId);
|
||||||
|
|
||||||
const data = await getWebsiteSessions(websiteId, filters);
|
const data = await getWebsiteSessions(websiteId, filters);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ export async function GET(
|
||||||
return unauthorized();
|
return unauthorized();
|
||||||
}
|
}
|
||||||
|
|
||||||
const filters = await getQueryFilters(query, websiteId, auth.user?.id);
|
const filters = await getQueryFilters(query, websiteId);
|
||||||
|
|
||||||
const metrics = await getWebsiteSessionStats(websiteId, filters);
|
const metrics = await getWebsiteSessionStats(websiteId, filters);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ export async function GET(
|
||||||
return unauthorized();
|
return unauthorized();
|
||||||
}
|
}
|
||||||
|
|
||||||
const filters = await getQueryFilters(query, websiteId, auth.user?.id);
|
const filters = await getQueryFilters(query, websiteId);
|
||||||
|
|
||||||
const data = await getWeeklyTraffic(websiteId, filters);
|
const data = await getWeeklyTraffic(websiteId, filters);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ export async function GET(
|
||||||
return unauthorized();
|
return unauthorized();
|
||||||
}
|
}
|
||||||
|
|
||||||
const filters = await getQueryFilters(query, websiteId, auth.user?.id);
|
const filters = await getQueryFilters(query, websiteId);
|
||||||
|
|
||||||
const data = await getWebsiteStats(websiteId, filters);
|
const data = await getWebsiteStats(websiteId, filters);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ export async function GET(
|
||||||
value: segment.name,
|
value: segment.name,
|
||||||
}));
|
}));
|
||||||
} else {
|
} else {
|
||||||
const filters = await getQueryFilters(query, websiteId, auth.user?.id);
|
const filters = await getQueryFilters(query, websiteId);
|
||||||
values = await getValues(websiteId, FILTER_COLUMNS[type], filters);
|
values = await getValues(websiteId, FILTER_COLUMNS[type], filters);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -95,6 +95,13 @@ export const EVENT_TYPE = {
|
||||||
pixelEvent: 4,
|
pixelEvent: 4,
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
|
export const ENTITY_TYPE = {
|
||||||
|
website: 1,
|
||||||
|
link: 2,
|
||||||
|
pixel: 3,
|
||||||
|
board: 4,
|
||||||
|
} as const;
|
||||||
|
|
||||||
export const DATA_TYPE = {
|
export const DATA_TYPE = {
|
||||||
string: 1,
|
string: 1,
|
||||||
number: 2,
|
number: 2,
|
||||||
|
|
|
||||||
|
|
@ -81,12 +81,12 @@ export function getRequestFilters(query: Record<string, any>) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function setWebsiteDate(websiteId: string, userId: string, data: Record<string, any>) {
|
export async function setWebsiteDate(websiteId: string, data: Record<string, any>) {
|
||||||
const website = await fetchWebsite(websiteId);
|
const website = await fetchWebsite(websiteId);
|
||||||
const cloudMode = !!process.env.CLOUD_MODE;
|
const cloudMode = !!process.env.CLOUD_MODE;
|
||||||
|
|
||||||
if (cloudMode && website && !website.teamId) {
|
if (cloudMode && website && !website.teamId) {
|
||||||
const account = await fetchAccount(userId);
|
const account = await fetchAccount(website.userId);
|
||||||
|
|
||||||
if (!account?.hasSubscription) {
|
if (!account?.hasSubscription) {
|
||||||
data.startDate = maxDate(data.startDate, startOfMonth(subMonths(new Date(), 6)));
|
data.startDate = maxDate(data.startDate, startOfMonth(subMonths(new Date(), 6)));
|
||||||
|
|
@ -103,13 +103,12 @@ export async function setWebsiteDate(websiteId: string, userId: string, data: Re
|
||||||
export async function getQueryFilters(
|
export async function getQueryFilters(
|
||||||
params: Record<string, any>,
|
params: Record<string, any>,
|
||||||
websiteId?: string,
|
websiteId?: string,
|
||||||
userId?: string,
|
|
||||||
): Promise<QueryFilters> {
|
): Promise<QueryFilters> {
|
||||||
const dateRange = getRequestDateRange(params);
|
const dateRange = getRequestDateRange(params);
|
||||||
const filters = getRequestFilters(params);
|
const filters = getRequestFilters(params);
|
||||||
|
|
||||||
if (websiteId) {
|
if (websiteId) {
|
||||||
await setWebsiteDate(websiteId, userId, dateRange);
|
await setWebsiteDate(websiteId, dateRange);
|
||||||
|
|
||||||
if (params.segment) {
|
if (params.segment) {
|
||||||
const segmentParams = (await getWebsiteSegment(websiteId, params.segment))
|
const segmentParams = (await getWebsiteSegment(websiteId, params.segment))
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue