* esm * wip * wip * wip * wip * wip * wip * subscription notice * wip * wip * wip * fix envs * fix: update docker build * fix * esm/types * delete dashboard :D * add patches to dockerfiles * update packages + catalogs + ts * wip * remove native libs * ts * improvements * fix redirects and fetching session * try fix favicon * fixes * fix * order and resize reportds within a dashboard * improvements * wip * added userjot to dashboard * fix * add op * wip * different cache key * improve date picker * fix table * event details loading * redo onboarding completely * fix login * fix * fix * extend session, billing and improve bars * fix * reduce price on 10M
169 lines
4.1 KiB
TypeScript
169 lines
4.1 KiB
TypeScript
import { PrismaError } from 'prisma-error-enum';
|
|
import { z } from 'zod';
|
|
|
|
import {
|
|
db,
|
|
getDashboardById,
|
|
getDashboardsByProjectId,
|
|
getId,
|
|
getProjectById,
|
|
} from '@openpanel/db';
|
|
import type { Prisma } from '@openpanel/db';
|
|
|
|
import { getProjectAccess } from '../access';
|
|
import { TRPCAccessError, TRPCNotFoundError } from '../errors';
|
|
import { createTRPCRouter, protectedProcedure } from '../trpc';
|
|
|
|
export const dashboardRouter = createTRPCRouter({
|
|
list: protectedProcedure
|
|
.input(
|
|
z.object({
|
|
projectId: z.string(),
|
|
}),
|
|
)
|
|
.query(({ input }) => {
|
|
return getDashboardsByProjectId(input.projectId);
|
|
}),
|
|
byId: protectedProcedure
|
|
.input(
|
|
z.object({
|
|
id: z.string(),
|
|
projectId: z.string(),
|
|
}),
|
|
)
|
|
.query(async ({ input, ctx }) => {
|
|
const access = await getProjectAccess({
|
|
projectId: input.projectId,
|
|
userId: ctx.session.userId,
|
|
});
|
|
|
|
if (!access) {
|
|
throw TRPCAccessError('You do not have access to this project');
|
|
}
|
|
|
|
const dashboard = await getDashboardById(input.id, input.projectId);
|
|
|
|
if (!dashboard) {
|
|
throw TRPCNotFoundError('Dashboard not found');
|
|
}
|
|
|
|
return dashboard;
|
|
}),
|
|
create: protectedProcedure
|
|
.input(
|
|
z.object({
|
|
name: z.string(),
|
|
projectId: z.string(),
|
|
}),
|
|
)
|
|
.mutation(async ({ input, ctx }) => {
|
|
const access = await getProjectAccess({
|
|
projectId: input.projectId,
|
|
userId: ctx.session.userId,
|
|
});
|
|
|
|
if (!access) {
|
|
throw TRPCAccessError('You do not have access to this project');
|
|
}
|
|
|
|
const project = await getProjectById(input.projectId);
|
|
|
|
if (!project) {
|
|
throw TRPCNotFoundError('Project not found');
|
|
}
|
|
|
|
return db.dashboard.create({
|
|
data: {
|
|
id: await getId('dashboard', input.name),
|
|
projectId: input.projectId,
|
|
organizationId: project.organizationId,
|
|
name: input.name,
|
|
},
|
|
});
|
|
}),
|
|
update: protectedProcedure
|
|
.input(
|
|
z.object({
|
|
id: z.string(),
|
|
name: z.string(),
|
|
}),
|
|
)
|
|
.mutation(async ({ input, ctx }) => {
|
|
const dashboard = await db.dashboard.findUniqueOrThrow({
|
|
where: {
|
|
id: input.id,
|
|
},
|
|
});
|
|
|
|
const access = await getProjectAccess({
|
|
projectId: dashboard.projectId,
|
|
userId: ctx.session.userId,
|
|
});
|
|
|
|
if (!access) {
|
|
throw TRPCAccessError('You do not have access to this dashboard');
|
|
}
|
|
|
|
return db.dashboard.update({
|
|
where: {
|
|
id: input.id,
|
|
},
|
|
data: {
|
|
name: input.name,
|
|
},
|
|
});
|
|
}),
|
|
delete: protectedProcedure
|
|
.input(
|
|
z.object({
|
|
id: z.string(),
|
|
forceDelete: z.boolean().optional(),
|
|
}),
|
|
)
|
|
.mutation(async ({ input, ctx }) => {
|
|
const dashboard = await db.dashboard.findUniqueOrThrow({
|
|
where: {
|
|
id: input.id,
|
|
},
|
|
});
|
|
|
|
const access = await getProjectAccess({
|
|
projectId: dashboard.projectId,
|
|
userId: ctx.session.userId,
|
|
});
|
|
|
|
if (!access) {
|
|
throw TRPCAccessError('You do not have access to this dashboard');
|
|
}
|
|
|
|
try {
|
|
if (input.forceDelete) {
|
|
await db.report.deleteMany({
|
|
where: {
|
|
dashboardId: input.id,
|
|
},
|
|
});
|
|
}
|
|
await db.dashboard.delete({
|
|
where: {
|
|
id: input.id,
|
|
},
|
|
});
|
|
} catch (e) {
|
|
// Below does not work...
|
|
// error instanceof Prisma.PrismaClientKnownRequestError
|
|
if (typeof e === 'object' && e && 'code' in e) {
|
|
const error = e as Prisma.PrismaClientKnownRequestError;
|
|
switch (error.code) {
|
|
case PrismaError.ForeignConstraintViolation:
|
|
throw new Error(
|
|
'Cannot delete dashboard with associated reports',
|
|
);
|
|
default:
|
|
throw new Error('Unknown error deleting dashboard');
|
|
}
|
|
}
|
|
}
|
|
}),
|
|
});
|