mirror of
https://github.com/umami-software/umami.git
synced 2026-02-07 14:17:13 +01:00
More work on reports. Added Funnel page.
This commit is contained in:
parent
5159dd470f
commit
3847e32f39
59 changed files with 1815 additions and 2370 deletions
|
|
@ -1,9 +1,8 @@
|
|||
import { z } from 'zod';
|
||||
import { parseRequest } from '@/lib/request';
|
||||
import { deleteReport, getReport, updateReport } from '@/queries';
|
||||
import { canDeleteReport, canUpdateReport, canViewReport } from '@/lib/auth';
|
||||
import { unauthorized, json, notFound, ok } from '@/lib/response';
|
||||
import { reportTypeParam } from '@/lib/schema';
|
||||
import { reportSchema } from '@/lib/schema';
|
||||
|
||||
export async function GET(request: Request, { params }: { params: Promise<{ reportId: string }> }) {
|
||||
const { auth, error } = await parseRequest(request);
|
||||
|
|
@ -20,8 +19,6 @@ export async function GET(request: Request, { params }: { params: Promise<{ repo
|
|||
return unauthorized();
|
||||
}
|
||||
|
||||
report.parameters = JSON.parse(report.parameters);
|
||||
|
||||
return json(report);
|
||||
}
|
||||
|
||||
|
|
@ -29,15 +26,7 @@ export async function POST(
|
|||
request: Request,
|
||||
{ params }: { params: Promise<{ reportId: string }> },
|
||||
) {
|
||||
const schema = z.object({
|
||||
websiteId: z.string().uuid(),
|
||||
type: reportTypeParam,
|
||||
name: z.string().max(200),
|
||||
description: z.string().max(500),
|
||||
parameters: z.object({}).passthrough(),
|
||||
});
|
||||
|
||||
const { auth, body, error } = await parseRequest(request, schema);
|
||||
const { auth, body, error } = await parseRequest(request, reportSchema);
|
||||
|
||||
if (error) {
|
||||
return error();
|
||||
|
|
@ -62,8 +51,8 @@ export async function POST(
|
|||
type,
|
||||
name,
|
||||
description,
|
||||
parameters: JSON.stringify(parameters),
|
||||
} as any);
|
||||
parameters,
|
||||
});
|
||||
|
||||
return json(result);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,25 +1,11 @@
|
|||
import { z } from 'zod';
|
||||
import { canViewWebsite } from '@/lib/auth';
|
||||
import { unauthorized, json } from '@/lib/response';
|
||||
import { parseRequest } from '@/lib/request';
|
||||
import { getFunnel } from '@/queries';
|
||||
import { reportParms } from '@/lib/schema';
|
||||
import { reportResultSchema } from '@/lib/schema';
|
||||
|
||||
export async function POST(request: Request) {
|
||||
const schema = z.object({
|
||||
...reportParms,
|
||||
window: z.coerce.number().positive(),
|
||||
steps: z
|
||||
.array(
|
||||
z.object({
|
||||
type: z.string(),
|
||||
value: z.string(),
|
||||
}),
|
||||
)
|
||||
.min(2),
|
||||
});
|
||||
|
||||
const { auth, body, error } = await parseRequest(request, schema);
|
||||
const { auth, body, error } = await parseRequest(request, reportResultSchema);
|
||||
|
||||
if (error) {
|
||||
return error();
|
||||
|
|
@ -27,9 +13,8 @@ export async function POST(request: Request) {
|
|||
|
||||
const {
|
||||
websiteId,
|
||||
steps,
|
||||
window,
|
||||
dateRange: { startDate, endDate },
|
||||
parameters: { steps, window },
|
||||
} = body;
|
||||
|
||||
if (!(await canViewWebsite(auth, websiteId))) {
|
||||
|
|
|
|||
34
src/app/api/reports/goal/route.ts
Normal file
34
src/app/api/reports/goal/route.ts
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
import { canViewWebsite } from '@/lib/auth';
|
||||
import { unauthorized, json } from '@/lib/response';
|
||||
import { parseRequest } from '@/lib/request';
|
||||
import { getGoal } from '@/queries/sql/reports/getGoal';
|
||||
import { reportResultSchema } from '@/lib/schema';
|
||||
|
||||
export async function POST(request: Request) {
|
||||
const { auth, body, error } = await parseRequest(request, reportResultSchema);
|
||||
|
||||
if (error) {
|
||||
return error();
|
||||
}
|
||||
|
||||
const {
|
||||
websiteId,
|
||||
dateRange: { startDate, endDate },
|
||||
parameters: { type, value, property, operator },
|
||||
} = body;
|
||||
|
||||
if (!(await canViewWebsite(auth, websiteId))) {
|
||||
return unauthorized();
|
||||
}
|
||||
|
||||
const data = await getGoal(websiteId, {
|
||||
type,
|
||||
value,
|
||||
property,
|
||||
operator,
|
||||
startDate: new Date(startDate),
|
||||
endDate: new Date(endDate),
|
||||
});
|
||||
|
||||
return json(data);
|
||||
}
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
import { z } from 'zod';
|
||||
import { canViewWebsite } from '@/lib/auth';
|
||||
import { unauthorized, json } from '@/lib/response';
|
||||
import { parseRequest } from '@/lib/request';
|
||||
import { getGoal } from '@/queries/sql/reports/getGoal';
|
||||
import { filterParams, reportParms } from '@/lib/schema';
|
||||
|
||||
export async function POST(request: Request) {
|
||||
const schema = z
|
||||
.object({
|
||||
...reportParms,
|
||||
...filterParams,
|
||||
type: z.enum(['page', 'event']),
|
||||
value: z.string(),
|
||||
operator: z
|
||||
.string()
|
||||
.regex(/count|sum|average/)
|
||||
.optional(),
|
||||
property: z.string().optional(),
|
||||
})
|
||||
.refine(data => {
|
||||
if (data['type'] === 'event' && data['property']) {
|
||||
return data['operator'] && data['property'];
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
const { auth, body, error } = await parseRequest(request, schema);
|
||||
|
||||
if (error) {
|
||||
return error();
|
||||
}
|
||||
|
||||
const {
|
||||
websiteId,
|
||||
type,
|
||||
value,
|
||||
property,
|
||||
operator,
|
||||
dateRange: { startDate, endDate },
|
||||
} = body;
|
||||
|
||||
if (!(await canViewWebsite(auth, websiteId))) {
|
||||
return unauthorized();
|
||||
}
|
||||
|
||||
const data = await getGoal(websiteId, {
|
||||
type,
|
||||
value,
|
||||
property,
|
||||
operator,
|
||||
startDate: new Date(startDate),
|
||||
endDate: new Date(endDate),
|
||||
});
|
||||
|
||||
return json(data);
|
||||
}
|
||||
|
|
@ -1,15 +1,15 @@
|
|||
import { z } from 'zod';
|
||||
import { uuid } from '@/lib/crypto';
|
||||
import { pagingParams, reportTypeParam } from '@/lib/schema';
|
||||
import { pagingParams, reportSchema } from '@/lib/schema';
|
||||
import { parseRequest } from '@/lib/request';
|
||||
import { canViewTeam, canViewWebsite, canUpdateWebsite } from '@/lib/auth';
|
||||
import { canViewWebsite, canUpdateWebsite } from '@/lib/auth';
|
||||
import { unauthorized, json } from '@/lib/response';
|
||||
import { getReports, createReport } from '@/queries';
|
||||
|
||||
export async function GET(request: Request) {
|
||||
const schema = z.object({
|
||||
websiteId: z.string().uuid().optional(),
|
||||
teamId: z.string().uuid().optional(),
|
||||
type: z.string().optional(),
|
||||
...pagingParams,
|
||||
});
|
||||
|
||||
|
|
@ -19,53 +19,24 @@ export async function GET(request: Request) {
|
|||
return error();
|
||||
}
|
||||
|
||||
const { page, search, pageSize, websiteId, teamId } = query;
|
||||
const userId = auth.user.id;
|
||||
const { page, search, pageSize, websiteId, type } = query;
|
||||
const filters = {
|
||||
page,
|
||||
pageSize,
|
||||
search,
|
||||
};
|
||||
|
||||
if (
|
||||
(websiteId && !(await canViewWebsite(auth, websiteId))) ||
|
||||
(teamId && !(await canViewTeam(auth, teamId)))
|
||||
) {
|
||||
if (websiteId && !(await canViewWebsite(auth, websiteId))) {
|
||||
return unauthorized();
|
||||
}
|
||||
|
||||
const data = await getReports(
|
||||
{
|
||||
where: {
|
||||
OR: [
|
||||
...(websiteId ? [{ websiteId }] : []),
|
||||
...(teamId
|
||||
? [
|
||||
{
|
||||
website: {
|
||||
deletedAt: null,
|
||||
teamId,
|
||||
},
|
||||
},
|
||||
]
|
||||
: []),
|
||||
...(userId && !websiteId && !teamId
|
||||
? [
|
||||
{
|
||||
website: {
|
||||
deletedAt: null,
|
||||
userId,
|
||||
},
|
||||
},
|
||||
]
|
||||
: []),
|
||||
],
|
||||
},
|
||||
include: {
|
||||
websiteId,
|
||||
type,
|
||||
website: {
|
||||
select: {
|
||||
domain: true,
|
||||
},
|
||||
deletedAt: null,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -76,15 +47,7 @@ export async function GET(request: Request) {
|
|||
}
|
||||
|
||||
export async function POST(request: Request) {
|
||||
const schema = z.object({
|
||||
websiteId: z.string().uuid(),
|
||||
name: z.string().max(200),
|
||||
type: reportTypeParam,
|
||||
description: z.string().max(500),
|
||||
parameters: z.object({}).passthrough(),
|
||||
});
|
||||
|
||||
const { auth, body, error } = await parseRequest(request, schema);
|
||||
const { auth, body, error } = await parseRequest(request, reportSchema);
|
||||
|
||||
if (error) {
|
||||
return error();
|
||||
|
|
@ -102,9 +65,9 @@ export async function POST(request: Request) {
|
|||
websiteId,
|
||||
type,
|
||||
name,
|
||||
description,
|
||||
parameters: JSON.stringify(parameters),
|
||||
} as any);
|
||||
description: description || '',
|
||||
parameters,
|
||||
});
|
||||
|
||||
return json(result);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,94 +0,0 @@
|
|||
import { z } from 'zod';
|
||||
import { canViewWebsite } from '@/lib/auth';
|
||||
import { unauthorized, json, ok } from '@/lib/response';
|
||||
import { parseRequest } from '@/lib/request';
|
||||
import { getReports, createReport, updateReport } from '@/queries';
|
||||
import { uuid } from '@/lib/crypto';
|
||||
|
||||
export async function GET(
|
||||
request: Request,
|
||||
{ params }: { params: Promise<{ websiteId: string }> },
|
||||
) {
|
||||
const { auth, query, error } = await parseRequest(request);
|
||||
|
||||
if (error) {
|
||||
return error();
|
||||
}
|
||||
|
||||
const { websiteId } = await params;
|
||||
const { page, search, pageSize } = query;
|
||||
const filters = {
|
||||
page,
|
||||
pageSize,
|
||||
search,
|
||||
};
|
||||
|
||||
if (!(await canViewWebsite(auth, websiteId))) {
|
||||
return unauthorized();
|
||||
}
|
||||
|
||||
const data = await getReports(
|
||||
{
|
||||
where: {
|
||||
websiteId,
|
||||
type: 'goals',
|
||||
},
|
||||
},
|
||||
filters,
|
||||
).then(result => {
|
||||
result.data = result.data.map(report => {
|
||||
report.parameters = JSON.parse(report.parameters);
|
||||
|
||||
return report;
|
||||
});
|
||||
|
||||
return result;
|
||||
});
|
||||
|
||||
return json(data);
|
||||
}
|
||||
|
||||
export async function POST(
|
||||
request: Request,
|
||||
{ params }: { params: Promise<{ websiteId: string }> },
|
||||
) {
|
||||
const schema = z.object({
|
||||
id: z.string().uuid().optional(),
|
||||
name: z.string(),
|
||||
type: z.enum(['page', 'event']),
|
||||
value: z.string(),
|
||||
});
|
||||
|
||||
const { auth, body, error } = await parseRequest(request, schema);
|
||||
|
||||
if (error) {
|
||||
return error();
|
||||
}
|
||||
|
||||
const { websiteId } = await params;
|
||||
|
||||
if (!(await canViewWebsite(auth, websiteId))) {
|
||||
return unauthorized();
|
||||
}
|
||||
|
||||
const { id, name, type, value } = body;
|
||||
|
||||
if (id) {
|
||||
await updateReport(id, {
|
||||
name,
|
||||
parameters: JSON.stringify({ name, type, value }),
|
||||
});
|
||||
} else {
|
||||
await createReport({
|
||||
id: uuid(),
|
||||
userId: auth.user.id,
|
||||
websiteId,
|
||||
type: 'goals',
|
||||
name,
|
||||
description: '',
|
||||
parameters: JSON.stringify({ name, type, value }),
|
||||
});
|
||||
}
|
||||
|
||||
return ok();
|
||||
}
|
||||
|
|
@ -1,15 +1,17 @@
|
|||
import { z } from 'zod';
|
||||
import { canViewWebsite } from '@/lib/auth';
|
||||
import { getWebsiteReports } from '@/queries';
|
||||
import { pagingParams } from '@/lib/schema';
|
||||
import { getReports } from '@/queries';
|
||||
import { filterParams, pagingParams } from '@/lib/schema';
|
||||
import { parseRequest } from '@/lib/request';
|
||||
import { unauthorized, json } from '@/lib/response';
|
||||
|
||||
export async function GET(
|
||||
request: Request,
|
||||
{ params }: { params: Promise<{ websiteId: string }> },
|
||||
filters: { type: string },
|
||||
) {
|
||||
const schema = z.object({
|
||||
...filterParams,
|
||||
...pagingParams,
|
||||
});
|
||||
|
||||
|
|
@ -26,11 +28,19 @@ export async function GET(
|
|||
return unauthorized();
|
||||
}
|
||||
|
||||
const data = await getWebsiteReports(websiteId, {
|
||||
page: +page,
|
||||
pageSize: +pageSize,
|
||||
search,
|
||||
});
|
||||
const data = await getReports(
|
||||
{
|
||||
where: {
|
||||
websiteId,
|
||||
type: filters.type,
|
||||
},
|
||||
},
|
||||
{
|
||||
page,
|
||||
pageSize,
|
||||
search,
|
||||
},
|
||||
);
|
||||
|
||||
return json(data);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue