diff --git a/apps/server/src/public/status.ts b/apps/server/src/public/status.ts index aecc19c3..4896f9cb 100644 --- a/apps/server/src/public/status.ts +++ b/apps/server/src/public/status.ts @@ -1,7 +1,7 @@ import { Hono } from "hono"; import { endTime, setMetric, startTime } from "hono/timing"; -import { and, db, eq, gte, inArray, isNull, lte } from "@openstatus/db"; +import { and, db, eq, gte, inArray, isNull, lte, ne } from "@openstatus/db"; import { incidentTable, maintenance, @@ -9,7 +9,6 @@ import { monitorsToPages, monitorsToStatusReport, page, - pagesToStatusReports, statusReport, } from "@openstatus/db/src/schema"; import { Status, Tracker } from "@openstatus/tracker"; @@ -53,15 +52,12 @@ status.get("/:slug", async (c) => { } = await getStatusPageData(currentPage.id); endTime(c, "database"); - console.log(maintenanceData); - - const statusReports = [ - ...pageStatusReportData, - ...monitorStatusReportData, - ].map((item) => { + const statusReports = [...monitorStatusReportData].map((item) => { return item.status_report; }); + statusReports.push(...pageStatusReportData); + const tracker = new Tracker({ incidents: ongoingIncidents, statusReports, @@ -110,18 +106,6 @@ async function getStatusPageData(pageId: number) { .where(inArray(monitorsToStatusReport.monitorId, monitorIds)) .all(); - const pageStatusReportDataQuery = db - .select() - .from(pagesToStatusReports) - .innerJoin( - statusReport, - and( - eq(pagesToStatusReports.statusReportId, statusReport.id), - eq(pagesToStatusReports.pageId, pageId), - ), - ) - .all(); - const ongoingIncidentsQuery = db .select() .from(incidentTable) @@ -144,14 +128,21 @@ async function getStatusPageData(pageId: number) { ), ); + const pageStatusReportDataQuery = db + .select() + .from(statusReport) + .where( + and(eq(statusReport.pageId, pageId), ne(statusReport.status, "resolved")), + ); + const [ - monitorStatusReportData, pageStatusReportData, + monitorStatusReportData, ongoingIncidents, maintenanceData, ] = await Promise.all([ - monitorStatusReportQuery, pageStatusReportDataQuery, + monitorStatusReportQuery, ongoingIncidentsQuery, ongoingMaintenancesQuery, ]); diff --git a/apps/server/src/v1/statusReportUpdates/post.ts b/apps/server/src/v1/statusReportUpdates/post.ts index a40abadd..22878f1b 100644 --- a/apps/server/src/v1/statusReportUpdates/post.ts +++ b/apps/server/src/v1/statusReportUpdates/post.ts @@ -4,7 +4,6 @@ import { and, db, eq, isNotNull } from "@openstatus/db"; import { page, pageSubscriber, - pagesToStatusReports, statusReport, statusReportUpdate, } from "@openstatus/db/src/schema"; @@ -81,31 +80,24 @@ export function registerPostStatusReportUpdate( // send email - if (workspacePlan.title !== "Hobby") { - const allPages = await db + if (workspacePlan.limits.notifications && _statusReport.pageId) { + const subscribers = await db .select() - .from(pagesToStatusReports) - .where(eq(pagesToStatusReports.statusReportId, _statusReport.id)) - .all(); - - for (const currentPage of allPages) { - const subscribers = await db - .select() - .from(pageSubscriber) - .where( - and( - eq(pageSubscriber.pageId, currentPage.pageId), - isNotNull(pageSubscriber.acceptedAt) - ) + .from(pageSubscriber) + .where( + and( + eq(pageSubscriber.pageId, _statusReport.pageId), + isNotNull(pageSubscriber.acceptedAt) ) - .all(); + ) + .all(); - const pageInfo = await db - .select() - .from(page) - .where(eq(page.id, currentPage.pageId)) - .get(); - if (!pageInfo) continue; + const pageInfo = await db + .select() + .from(page) + .where(eq(page.id, _statusReport.pageId)) + .get(); + if (pageInfo) { const subscribersEmails = subscribers.map( (subscriber) => subscriber.email ); diff --git a/apps/server/src/v1/statusReports/get.ts b/apps/server/src/v1/statusReports/get.ts index aef3f4a4..86c0349e 100644 --- a/apps/server/src/v1/statusReports/get.ts +++ b/apps/server/src/v1/statusReports/get.ts @@ -38,7 +38,6 @@ export function regsiterGetStatusReport(api: typeof statusReportsApi) { with: { statusReportUpdates: true, monitorsToStatusReports: true, - pagesToStatusReports: true, }, where: and( eq(statusReport.workspaceId, Number(workspaceId)), @@ -50,11 +49,7 @@ export function regsiterGetStatusReport(api: typeof statusReportsApi) { throw new HTTPException(404, { message: "Not Found" }); } - const { - statusReportUpdates, - monitorsToStatusReports, - pagesToStatusReports, - } = _statusUpdate; + const { statusReportUpdates, monitorsToStatusReports } = _statusUpdate; // most recent report information const { message, date } = @@ -67,9 +62,7 @@ export function regsiterGetStatusReport(api: typeof statusReportsApi) { monitorIds: monitorsToStatusReports.length ? monitorsToStatusReports.map((monitor) => monitor.monitorId) : null, - pageIds: pagesToStatusReports.length - ? pagesToStatusReports.map((page) => page.pageId) - : null, + statusReportUpdateIds: statusReportUpdates.map((update) => update.id), }); diff --git a/apps/server/src/v1/statusReports/get_all.ts b/apps/server/src/v1/statusReports/get_all.ts index 33dc2eac..95180e20 100644 --- a/apps/server/src/v1/statusReports/get_all.ts +++ b/apps/server/src/v1/statusReports/get_all.ts @@ -35,7 +35,6 @@ export function registerGetAllStatusReports(api: typeof statusReportsApi) { with: { statusReportUpdates: true, monitorsToStatusReports: true, - pagesToStatusReports: true, }, where: eq(statusReport.workspaceId, Number(workspaceId)), }); @@ -48,7 +47,6 @@ export function registerGetAllStatusReports(api: typeof statusReportsApi) { _statusReports.map((r) => ({ ...r, statusReportUpdateIds: r.statusReportUpdates.map((u) => u.id), - pageIds: r.pagesToStatusReports.map((p) => p.pageId), monitorIds: r.monitorsToStatusReports.map((m) => m.monitorId), })) ); diff --git a/apps/server/src/v1/statusReports/post.ts b/apps/server/src/v1/statusReports/post.ts index c945a324..07eca637 100644 --- a/apps/server/src/v1/statusReports/post.ts +++ b/apps/server/src/v1/statusReports/post.ts @@ -6,7 +6,6 @@ import { monitorsToStatusReport, page, pageSubscriber, - pagesToStatusReports, statusReport, statusReportUpdate, } from "@openstatus/db/src/schema"; @@ -62,7 +61,7 @@ export function registerPostStatusReport(api: typeof statusReportsApi) { const workspaceId = c.get("workspaceId"); const workspacePlan = c.get("workspacePlan"); - const { pageIds, monitorIds, date, ...rest } = input; + const { monitorIds, date, ...rest } = input; if (monitorIds?.length) { const _monitors = await db @@ -82,21 +81,22 @@ export function registerPostStatusReport(api: typeof statusReportsApi) { } } - if (pageIds?.length) { + + if(rest.pageId){ const _pages = await db - .select() - .from(page) - .where( - and( - eq(page.workspaceId, Number(workspaceId)), - inArray(page.id, pageIds) - ) + .select() + .from(page) + .where( + and( + eq(page.workspaceId, Number(workspaceId)), + eq(page.id, rest.pageId) ) - .all(); + ) + .all(); - if (_pages.length !== pageIds.length) { - throw new HTTPException(400, { message: "Page not found" }); - } + if (_pages.length !== 1) { + throw new HTTPException(400, { message: "Page not found" }); + } } const _newStatusReport = await db @@ -118,20 +118,6 @@ export function registerPostStatusReport(api: typeof statusReportsApi) { .returning() .get(); - if (pageIds?.length) { - await db - .insert(pagesToStatusReports) - .values( - pageIds.map((id) => { - return { - pageId: id, - statusReportId: _newStatusReport.id, - }; - }) - ) - .returning(); - } - if (monitorIds?.length) { await db .insert(monitorsToStatusReport) @@ -146,31 +132,23 @@ export function registerPostStatusReport(api: typeof statusReportsApi) { .returning(); } - if (workspacePlan.title !== "Hobby") { - const allPages = await db + if (workspacePlan.limits.notifications && _newStatusReport.pageId) { + const subscribers = await db .select() - .from(pagesToStatusReports) + .from(pageSubscriber) .where( - eq(pagesToStatusReports.statusReportId, Number(_newStatusReport.id)) + and( + eq(pageSubscriber.pageId, _newStatusReport.pageId), + isNotNull(pageSubscriber.acceptedAt) + ) ) .all(); - for (const currentPage of allPages) { - const subscribers = await db - .select() - .from(pageSubscriber) - .where( - and( - eq(pageSubscriber.pageId, currentPage.pageId), - isNotNull(pageSubscriber.acceptedAt) - ) - ) - .all(); - const pageInfo = await db - .select() - .from(page) - .where(eq(page.id, currentPage.pageId)) - .get(); - if (!pageInfo) continue; + const pageInfo = await db + .select() + .from(page) + .where(eq(page.id, _newStatusReport.pageId)) + .get(); + if (pageInfo) { const subscribersEmails = subscribers.map( (subscriber) => subscriber.email ); @@ -187,7 +165,6 @@ export function registerPostStatusReport(api: typeof statusReportsApi) { const data = StatusReportSchema.parse({ ..._newStatusReport, monitorIds, - pageIds, statusReportUpdateIds: [_newStatusReportUpdate.id], }); diff --git a/apps/server/src/v1/statusReports/schema.ts b/apps/server/src/v1/statusReports/schema.ts index ebf9225e..46aff08f 100644 --- a/apps/server/src/v1/statusReports/schema.ts +++ b/apps/server/src/v1/statusReports/schema.ts @@ -1,6 +1,6 @@ import { z } from "@hono/zod-openapi"; -import { statusReportStatusSchema } from "@openstatus/db/src/schema"; +import { page, statusReportStatusSchema } from "@openstatus/db/src/schema"; export const ParamsSchema = z.object({ id: z @@ -49,15 +49,11 @@ export const StatusReportSchema = z.object({ description: "id of monitors this report needs to refer", }) .nullable(), - pageIds: z - .array(z.number()) - .optional() - .nullable() - .default([]) - .openapi({ - description: "id of status pages this report needs to refer", - }) - .nullable(), + + pageId: z.number().optional().nullable().openapi({ + description: "The id of the page this status report belongs to", + + }), }); export type StatusReportSchema = z.infer; diff --git a/apps/server/src/v1/statusReports/statusReports.test.ts b/apps/server/src/v1/statusReports/statusReports.test.ts index 69142324..5e2c5aed 100644 --- a/apps/server/src/v1/statusReports/statusReports.test.ts +++ b/apps/server/src/v1/statusReports/statusReports.test.ts @@ -15,7 +15,7 @@ test("GET one status report", async () => { status: "monitoring", statusReportUpdateIds: expect.arrayContaining([1, 3]), // depending on the order of the updates monitorIds: null, - pageIds: [1], + pageId: 1, }); }); @@ -34,7 +34,7 @@ test("Get all status report", async () => { status: "monitoring", statusReportUpdateIds: expect.arrayContaining([1, 3]), // depending on the order of the updates monitorIds: [], - pageIds: [1], + pageId: 1, }, { id: 2, @@ -42,7 +42,7 @@ test("Get all status report", async () => { status: "investigating", statusReportUpdateIds: expect.arrayContaining([2]), // depending on the order of the updates monitorIds: [1, 2], - pageIds: [1], + pageId: 1, }, ], }); @@ -60,7 +60,7 @@ test("Create one status report including passing optional fields", async () => { title: "New Status Report", message: "Message", monitorIds: [1], - pageIds: [1], + pageId: 1, }), }); const json = await res.json(); @@ -73,7 +73,7 @@ test("Create one status report including passing optional fields", async () => { status: "investigating", statusReportUpdateIds: [expect.any(Number)], monitorIds: [1], - pageIds: [1], + pageId: 1, }); }); @@ -118,7 +118,7 @@ test("Create status report with non existing monitor ids should return 400", asy title: "New Status Report", message: "Message", monitorIds: [100], - pageIds: [1], + pageId: 1, }), }); @@ -137,7 +137,7 @@ test("Create status report with non existing page ids should return 400", async title: "New Status Report", message: "Message", monitorIds: [1], - pageIds: [100], + pageId: 100, }), }); diff --git a/apps/server/src/v1/statusReports/update/post.ts b/apps/server/src/v1/statusReports/update/post.ts index e03ef4e0..31e51cd4 100644 --- a/apps/server/src/v1/statusReports/update/post.ts +++ b/apps/server/src/v1/statusReports/update/post.ts @@ -3,7 +3,6 @@ import { and, db, eq, isNotNull } from "@openstatus/db"; import { page, pageSubscriber, - pagesToStatusReports, statusReport, statusReportUpdate, } from "@openstatus/db/src/schema"; @@ -77,29 +76,23 @@ export function registerStatusReportUpdateRoutes(api: typeof statusReportsApi) { .returning() .get(); - if (workspacePlan.title !== "Hobby") { - const allPages = await db + if (workspacePlan.limits.notifications && _statusReport.pageId) { + const subscribers = await db .select() - .from(pagesToStatusReports) - .where(eq(pagesToStatusReports.statusReportId, Number(id))) - .all(); - for (const currentPage of allPages) { - const subscribers = await db - .select() - .from(pageSubscriber) - .where( - and( - eq(pageSubscriber.pageId, currentPage.pageId), - isNotNull(pageSubscriber.acceptedAt) - ) + .from(pageSubscriber) + .where( + and( + eq(pageSubscriber.pageId, _statusReport.pageId), + isNotNull(pageSubscriber.acceptedAt) ) - .all(); - const pageInfo = await db - .select() - .from(page) - .where(eq(page.id, currentPage.pageId)) - .get(); - if (!pageInfo) continue; + ) + .all(); + const pageInfo = await db + .select() + .from(page) + .where(eq(page.id, _statusReport.pageId)) + .get(); + if (pageInfo) { const subscribersEmails = subscribers.map( (subscriber) => subscriber.email ); @@ -113,7 +106,7 @@ export function registerStatusReportUpdateRoutes(api: typeof statusReportsApi) { } } - const data = StatusReportUpdateSchema.parse(_statusReportUpdate); + const data = StatusReportSchema.parse(_statusReportUpdate); return c.json(data, 200); }); diff --git a/apps/web/src/app/(content)/features/mock.ts b/apps/web/src/app/(content)/features/mock.ts index 9d6c5363..4514c3de 100644 --- a/apps/web/src/app/(content)/features/mock.ts +++ b/apps/web/src/app/(content)/features/mock.ts @@ -1033,6 +1033,7 @@ export const statusReportData = { status: "resolved" as const, title: "Downtime", workspaceId: 1, + pageId: 0, createdAt: new Date("2024-07-09T21:22:43.000Z"), updatedAt: new Date("2024-07-09T21:23:17.000Z"), statusReportUpdates: [ diff --git a/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-reports/(overview)/loading.tsx b/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/[id]/reports/(overview)/loading.tsx similarity index 100% rename from apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-reports/(overview)/loading.tsx rename to apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/[id]/reports/(overview)/loading.tsx diff --git a/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-reports/(overview)/page.tsx b/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/[id]/reports/(overview)/page.tsx similarity index 56% rename from apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-reports/(overview)/page.tsx rename to apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/[id]/reports/(overview)/page.tsx index b4672d56..4a3e502b 100644 --- a/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-reports/(overview)/page.tsx +++ b/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/[id]/reports/(overview)/page.tsx @@ -8,8 +8,14 @@ import { columns } from "@/components/data-table/status-report/columns"; import { DataTable } from "@/components/data-table/status-report/data-table"; import { api } from "@/trpc/server"; -export default async function MonitorPage() { - const reports = await api.statusReport.getStatusReportByWorkspace.query(); +export default async function MonitorPage({ + params, +}: { + params: { id: string }; +}) { + const reports = await api.statusReport.getStatusReportByPageId.query({ + id: Number.parseInt(params.id), + }); if (reports?.length === 0) return ( @@ -19,11 +25,18 @@ export default async function MonitorPage() { description="Create your first status report" action={ } /> ); - return ; + return ( +
+ + +
+ ); } diff --git a/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-reports/[id]/_components/status-update-button.tsx b/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/[id]/reports/[reportId]/_components/status-update-button.tsx similarity index 100% rename from apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-reports/[id]/_components/status-update-button.tsx rename to apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/[id]/reports/[reportId]/_components/status-update-button.tsx diff --git a/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-reports/[id]/edit/loading.tsx b/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/[id]/reports/[reportId]/edit/loading.tsx similarity index 100% rename from apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-reports/[id]/edit/loading.tsx rename to apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/[id]/reports/[reportId]/edit/loading.tsx diff --git a/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-reports/[id]/edit/page.tsx b/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/[id]/reports/[reportId]/edit/page.tsx similarity index 73% rename from apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-reports/[id]/edit/page.tsx rename to apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/[id]/reports/[reportId]/edit/page.tsx index fcede334..2f088e16 100644 --- a/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-reports/[id]/edit/page.tsx +++ b/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/[id]/reports/[reportId]/edit/page.tsx @@ -4,20 +4,18 @@ import { api } from "@/trpc/server"; export default async function EditPage({ params, }: { - params: { workspaceSlug: string; id: string }; + params: { workspaceSlug: string; id: string; reportId: string }; }) { const statusUpdate = await api.statusReport.getStatusReportById.query({ - id: Number.parseInt(params.id), + id: Number.parseInt(params.reportId), + pageId: Number.parseInt(params.id), }); const monitors = await api.monitor.getMonitorsByWorkspace.query(); - const pages = await api.page.getPagesByWorkspace.query(); - return ( monitorId, + ({ monitorId }) => monitorId ), - pages: statusUpdate?.pagesToStatusReports.map(({ pageId }) => pageId), message: "", } } + pageId={Number.parseInt(params.id)} defaultSection="connect" /> ); diff --git a/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/[id]/reports/[reportId]/overview/_components/header.tsx b/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/[id]/reports/[reportId]/overview/_components/header.tsx new file mode 100644 index 00000000..cdd0eb10 --- /dev/null +++ b/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/[id]/reports/[reportId]/overview/_components/header.tsx @@ -0,0 +1,80 @@ +"use client"; + +import { StatusReportUpdateForm } from "@/components/forms/status-report-update/form"; +import { StatusBadge } from "@/components/status-update/status-badge"; +import { formatDate } from "@/lib/utils"; +import type { + Monitor, + StatusReport, + StatusReportUpdate, +} from "@openstatus/db/src/schema"; +import { + Badge, + Button, + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle, + DialogTrigger, + Separator, +} from "@openstatus/ui"; +import { useState } from "react"; + +export function Header({ + report, + monitors, +}: { + report: StatusReport & { statusReportUpdates: StatusReportUpdate[] }; + monitors?: Pick[]; +}) { + const [open, setOpen] = useState(false); + + const firstUpdate = report.statusReportUpdates?.[0]; + const lastUpdate = + report.statusReportUpdates?.[report.statusReportUpdates?.length - 1]; + + return ( +
+
+
+

{report.title}

+
+ + {firstUpdate?.date + ? formatDate(firstUpdate?.date) + : "Missing date"} + + • + + • + {monitors?.map(({ name, id }) => ( + + {name} + + ))} +
+
+ + + + + + + + Edit Status Report + + Update your status report with new information. + + + setOpen(false)} + /> + + +
+ +
+ ); +} diff --git a/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/[id]/reports/[reportId]/overview/loading.tsx b/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/[id]/reports/[reportId]/overview/loading.tsx new file mode 100644 index 00000000..3c787dcc --- /dev/null +++ b/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/[id]/reports/[reportId]/overview/loading.tsx @@ -0,0 +1,26 @@ +import { Separator, Skeleton } from "@openstatus/ui"; + +export default function Loading() { + return ( +
+
+
+
+ +
+ + • + + • + +
+
+ +
+ +
+ + +
+ ); +} diff --git a/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-reports/[id]/overview/page.tsx b/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/[id]/reports/[reportId]/overview/page.tsx similarity index 64% rename from apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-reports/[id]/overview/page.tsx rename to apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/[id]/reports/[reportId]/overview/page.tsx index 2596443d..cbd7d29a 100644 --- a/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-reports/[id]/overview/page.tsx +++ b/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/[id]/reports/[reportId]/overview/page.tsx @@ -2,20 +2,21 @@ import Link from "next/link"; import { notFound } from "next/navigation"; import * as React from "react"; -import { Button, Separator } from "@openstatus/ui"; +import { Button } from "@openstatus/ui"; import { EmptyState } from "@/components/dashboard/empty-state"; import { Events } from "@/components/status-update/events"; -import { Summary } from "@/components/status-update/summary"; import { api } from "@/trpc/server"; +import { Header } from "./_components/header"; export default async function OverviewPage({ params, }: { - params: { workspaceSlug: string; id: string }; + params: { workspaceSlug: string; id: string; reportId: string }; }) { const report = await api.statusReport.getStatusReportById.query({ - id: Number.parseInt(params.id), + id: Number.parseInt(params.reportId), + pageId: Number.parseInt(params.id), }); if (!report) return notFound(); @@ -24,8 +25,7 @@ export default async function OverviewPage({ return ( <> - - +
{report.statusReportUpdates.length > 0 ? ( ) : ( @@ -33,12 +33,6 @@ export default async function OverviewPage({ icon="megaphone" title="No status report updates" description="Create your first update" - action={ - - } /> )} diff --git a/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/[id]/reports/[reportId]/page.tsx b/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/[id]/reports/[reportId]/page.tsx new file mode 100644 index 00000000..16a25f2e --- /dev/null +++ b/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/[id]/reports/[reportId]/page.tsx @@ -0,0 +1,9 @@ +import { redirect } from "next/navigation"; + +export default function Page({ + params, +}: { + params: { workspaceSlug: string; reportId: string }; +}) { + return redirect(`./${params.reportId}/overview`); +} diff --git a/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-reports/new/loading.tsx b/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/[id]/reports/new/loading.tsx similarity index 100% rename from apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-reports/new/loading.tsx rename to apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/[id]/reports/new/loading.tsx diff --git a/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-reports/new/page.tsx b/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/[id]/reports/new/page.tsx similarity index 68% rename from apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-reports/new/page.tsx rename to apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/[id]/reports/new/page.tsx index 94d2b4e9..11371a08 100644 --- a/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-reports/new/page.tsx +++ b/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/[id]/reports/new/page.tsx @@ -1,17 +1,19 @@ import { StatusReportForm } from "@/components/forms/status-report/form"; import { api } from "@/trpc/server"; -export default async function NewPage() { +export default async function NewPage({ + params, +}: { + params: { id: string; reportId: string }; +}) { const monitors = await api.monitor.getMonitorsByWorkspace.query(); - const pages = await api.page.getPagesByWorkspace.query(); - return ( ); } diff --git a/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-reports/(overview)/layout.tsx b/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-reports/(overview)/layout.tsx deleted file mode 100644 index db1b2cce..00000000 --- a/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-reports/(overview)/layout.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import Link from "next/link"; -import type { ReactNode } from "react"; - -import { Button } from "@openstatus/ui"; - -import { Header } from "@/components/dashboard/header"; -import AppPageLayout from "@/components/layout/app-page-layout"; - -export default async function Layout({ children }: { children: ReactNode }) { - return ( - -
- Create - - } - /> - {children} - - ); -} diff --git a/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-reports/[id]/layout.tsx b/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-reports/[id]/layout.tsx deleted file mode 100644 index ddb33d7c..00000000 --- a/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-reports/[id]/layout.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { notFound } from "next/navigation"; - -import { Header } from "@/components/dashboard/header"; -import AppPageWithSidebarLayout from "@/components/layout/app-page-with-sidebar-layout"; -import { api } from "@/trpc/server"; -import { StatusUpdateButton } from "./_components/status-update-button"; - -export default async function Layout({ - children, - params, -}: { - children: React.ReactNode; - params: { workspaceSlug: string; id: string }; -}) { - const id = params.id; - - const statusReport = await api.statusReport.getStatusReportById.query({ - id: Number(id), - }); - - if (!statusReport) { - return notFound(); - } - - return ( - -
} - /> - {children} - - ); -} diff --git a/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-reports/[id]/overview/loading.tsx b/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-reports/[id]/overview/loading.tsx deleted file mode 100644 index 69460271..00000000 --- a/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-reports/[id]/overview/loading.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import { Separator, Skeleton } from "@openstatus/ui"; - -export default function Loading() { - return ( -
-
- - - - - -
- - -
-
- - - -
- ); -} diff --git a/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-reports/[id]/page.tsx b/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-reports/[id]/page.tsx deleted file mode 100644 index 2265f50d..00000000 --- a/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-reports/[id]/page.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { redirect } from "next/navigation"; - -export default function Page({ - params, -}: { - params: { workspaceSlug: string; id: string }; -}) { - return redirect(`./${params.id}/overview`); -} diff --git a/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-reports/edit/loading.tsx b/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-reports/edit/loading.tsx deleted file mode 100644 index 41fdbbaa..00000000 --- a/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-reports/edit/loading.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import { Skeleton } from "@openstatus/ui"; - -import { Header } from "@/components/dashboard/header"; -import { SkeletonForm } from "@/components/forms/skeleton-form"; - -export default function Loading() { - return ( -
-
- - - -
-
- -
-
- ); -} diff --git a/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-reports/edit/page.tsx b/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-reports/edit/page.tsx deleted file mode 100644 index 2462739d..00000000 --- a/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-reports/edit/page.tsx +++ /dev/null @@ -1,71 +0,0 @@ -import { notFound } from "next/navigation"; -import * as z from "zod"; - -import { Header } from "@/components/dashboard/header"; -import { StatusReportForm } from "@/components/forms/status-report-form"; -import AppPageLayout from "@/components/layout/app-page-layout"; -import { api } from "@/trpc/server"; - -/** - * allowed URL search params - */ -const searchParamsSchema = z.object({ - id: z.coerce.number().optional(), -}); - -export default async function EditPage({ - // biome-ignore lint/correctness/noUnusedVariables: - params, - searchParams, -}: { - params: { workspaceSlug: string }; - searchParams: { [key: string]: string | string[] | undefined }; -}) { - const search = searchParamsSchema.safeParse(searchParams); - - if (!search.success) { - return notFound(); - } - - const { id } = search.data; - - const statusUpdate = id - ? await api.statusReport.getStatusReportById.query({ - id, - }) - : undefined; - - const monitors = await api.monitor.getMonitorsByWorkspace.query(); - - const pages = await api.page.getPagesByWorkspace.query(); - - return ( - -
- monitorId, - ), - pages: statusUpdate?.pagesToStatusReports.map( - ({ pageId }) => pageId, - ), - message: "", - } - : undefined - } - /> - - ); -} diff --git a/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-reports/new/layout.tsx b/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-reports/new/layout.tsx deleted file mode 100644 index 1555095d..00000000 --- a/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-reports/new/layout.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { Header } from "@/components/dashboard/header"; -import AppPageLayout from "@/components/layout/app-page-layout"; - -export default async function Layout({ - children, -}: { - children: React.ReactNode; -}) { - return ( - -
- {children} - - ); -} diff --git a/apps/web/src/components/data-table/status-report/columns.tsx b/apps/web/src/components/data-table/status-report/columns.tsx index 925992fe..a751400b 100644 --- a/apps/web/src/components/data-table/status-report/columns.tsx +++ b/apps/web/src/components/data-table/status-report/columns.tsx @@ -21,10 +21,7 @@ export const columns: ColumnDef< cell: ({ row }) => { const id = row.original.id; return ( - + {row.getValue("title")} ); diff --git a/apps/web/src/components/data-table/status-report/data-table-row-actions.tsx b/apps/web/src/components/data-table/status-report/data-table-row-actions.tsx index 13040699..944272c5 100644 --- a/apps/web/src/components/data-table/status-report/data-table-row-actions.tsx +++ b/apps/web/src/components/data-table/status-report/data-table-row-actions.tsx @@ -69,10 +69,10 @@ export function DataTableRowActions({ - + Edit - + View diff --git a/apps/web/src/components/forms/status-report-form.tsx b/apps/web/src/components/forms/status-report-form.tsx index 6830cbef..9d690a87 100644 --- a/apps/web/src/components/forms/status-report-form.tsx +++ b/apps/web/src/components/forms/status-report-form.tsx @@ -51,15 +51,15 @@ import { api } from "@/trpc/client"; interface Props { defaultValues?: InsertStatusReport; monitors?: Monitor[]; - pages?: Page[]; nextUrl?: string; + pageId: number; } export function StatusReportForm({ defaultValues, monitors, - pages, nextUrl, + pageId, }: Props) { const form = useForm({ resolver: zodResolver(insertStatusReportSchema), @@ -69,7 +69,6 @@ export function StatusReportForm({ title: defaultValues.title, status: defaultValues.status, monitors: defaultValues.monitors, - pages: defaultValues.pages, // include update on creation message: defaultValues.message, date: defaultValues.date, @@ -86,15 +85,19 @@ export function StatusReportForm({ startTransition(async () => { try { if (defaultValues) { - await api.statusReport.updateStatusReport.mutate({ ...props }); + await api.statusReport.updateStatusReport.mutate({ + pageId, + ...props, + }); } else { const { message, date, status, ...rest } = props; const statusReport = await api.statusReport.createStatusReport.mutate( { status, message, + pageId, ...rest, - }, + } ); // include update on creation if (statusReport?.id) { @@ -224,8 +227,8 @@ export function StatusReportForm({ ]) : field.onChange( field.value?.filter( - (value) => value !== item.id, - ), + (value) => value !== item.id + ) ); }} /> @@ -240,7 +243,7 @@ export function StatusReportForm({ "rounded-full p-1", item.active ? "bg-green-500" - : "bg-red-500", + : "bg-red-500" )} /> @@ -258,66 +261,6 @@ export function StatusReportForm({ )} /> - ( - -
- Pages - - Select the pages that you want to refer the incident to. - -
-
- {pages?.map((item) => ( - { - return ( - - - { - return checked - ? field.onChange([ - ...(field.value || []), - item.id, - ]) - : field.onChange( - field.value?.filter( - (value) => value !== item.id, - ), - ); - }} - /> - -
-
- - {item.title} - -
-

- {item.description} -

-
-
- ); - }} - /> - ))} -
- -
- )} - /> {/* include update on creation */} diff --git a/apps/web/src/components/forms/status-report/form.tsx b/apps/web/src/components/forms/status-report/form.tsx index 7f5ee12f..589cf2da 100644 --- a/apps/web/src/components/forms/status-report/form.tsx +++ b/apps/web/src/components/forms/status-report/form.tsx @@ -30,16 +30,16 @@ interface Props { defaultSection?: string; defaultValues?: InsertStatusReport; monitors?: Monitor[]; - pages?: Page[]; nextUrl?: string; + pageId: number; } export function StatusReportForm({ defaultSection, defaultValues, monitors, - pages, nextUrl, + pageId, }: Props) { const form = useForm({ resolver: zodResolver(insertStatusReportSchema), @@ -49,7 +49,6 @@ export function StatusReportForm({ title: defaultValues.title, status: defaultValues.status, monitors: defaultValues.monitors, - pages: defaultValues.pages, // include update on creation message: defaultValues.message, date: defaultValues.date, @@ -67,15 +66,19 @@ export function StatusReportForm({ startTransition(async () => { try { if (defaultValues) { - await api.statusReport.updateStatusReport.mutate({ ...props }); + await api.statusReport.updateStatusReport.mutate({ + pageId, + ...props, + }); } else { const { message, date, status, ...rest } = props; const statusReport = await api.statusReport.createStatusReport.mutate( { status, message, + pageId, ...rest, - }, + } ); // include update on creation if (statusReport?.id) { @@ -133,7 +136,7 @@ export function StatusReportForm({ ) : null} - + ; - pages?: Page[]; monitors?: Monitor[]; } -export function SectionConnect({ form, pages, monitors }: Props) { +export function SectionConnect({ form, monitors }: Props) { return (
- ( - -
- Pages - - Select the pages that you want to refer the incident to. - -
-
- {pages?.map((item) => ( - { - return ( - - - { - return checked - ? field.onChange([ - ...(field.value || []), - item.id, - ]) - : field.onChange( - field.value?.filter( - (value) => value !== item.id, - ), - ); - }} - > - {item.title} - - - - ); - }} - /> - ))} -
- {!pages || pages.length === 0 ? ( - Missing status pages. - ) : null} - -
- )} - /> value !== item.id, - ), + (value) => value !== item.id + ) ); }} > diff --git a/apps/web/src/config/pages.ts b/apps/web/src/config/pages.ts index f0630f3c..8487a7c6 100644 --- a/apps/web/src/config/pages.ts +++ b/apps/web/src/config/pages.ts @@ -88,6 +88,13 @@ export const statusPagesPagesConfig: Page[] = [ icon: "cog", segment: "edit", }, + { + title: "Status Reports", + description: "Inform your users about recent reports", + href: "/status-pages/[id]/reports", + icon: "megaphone", + segment: "reports", + }, { title: "Domain", description: "Where you can see the domain settings.", @@ -175,14 +182,6 @@ export const pagesConfig = [ segment: "status-pages", children: statusPagesPagesConfig, }, - { - title: "Status Reports", - description: "War room where you handle the incidents.", - href: "/status-reports", - icon: "megaphone", - segment: "status-reports", - children: statusReportsPagesConfig, - }, { title: "Notifications", description: "Where you can see all the notifications.", diff --git a/packages/api/src/router/page.ts b/packages/api/src/router/page.ts index b7bd99e4..d6ee75dc 100644 --- a/packages/api/src/router/page.ts +++ b/packages/api/src/router/page.ts @@ -1,7 +1,17 @@ import { TRPCError } from "@trpc/server"; import { z } from "zod"; -import { and, eq, gte, inArray, isNull, lte, or, sql } from "@openstatus/db"; +import { + and, + eq, + gte, + inArray, + isNotNull, + isNull, + lte, + or, + sql, +} from "@openstatus/db"; import { incidentTable, insertPageSchema, @@ -10,7 +20,6 @@ import { monitorsToPages, monitorsToStatusReport, page, - pagesToStatusReports, selectPageSchemaWithMonitorsRelation, selectPublicPageSchemaWithRelation, statusReport, @@ -269,34 +278,21 @@ export const pageRouter = createTRPCRouter({ .all() : []; - const statusReportsToPagesResult = await opts.ctx.db - .select() - .from(pagesToStatusReports) - .where(eq(pagesToStatusReports.pageId, result.id)) - .all(); - const monitorStatusReportIds = monitorsToStatusReportResult.map( ({ statusReportId }) => statusReportId, ); - const pageStatusReportIds = statusReportsToPagesResult.map( - ({ statusReportId }) => statusReportId, - ); - - const statusReportIds = Array.from( - new Set([...monitorStatusReportIds, ...pageStatusReportIds]), - ); + const statusReportIds = Array.from(new Set([...monitorStatusReportIds])); const statusReports = statusReportIds.length > 0 ? await opts.ctx.db.query.statusReport.findMany({ - where: or(inArray(statusReport.id, statusReportIds)), + where: eq(statusReport.pageId, result.id), with: { statusReportUpdates: { orderBy: (reports, { desc }) => desc(reports.date), }, monitorsToStatusReports: { with: { monitor: true } }, - pagesToStatusReports: true, }, }) : []; diff --git a/packages/api/src/router/statusReport.ts b/packages/api/src/router/statusReport.ts index e2e391d3..5b324574 100644 --- a/packages/api/src/router/statusReport.ts +++ b/packages/api/src/router/statusReport.ts @@ -7,7 +7,6 @@ import { monitorsToStatusReport, page, pageSubscriber, - pagesToStatusReports, selectMonitorSchema, selectPublicStatusReportSchemaWithRelation, selectStatusReportSchema, @@ -25,8 +24,7 @@ export const statusReportRouter = createTRPCRouter({ createStatusReport: protectedProcedure .input(insertStatusReportSchema) .mutation(async (opts) => { - const { id, monitors, pages, date, message, ...statusReportInput } = - opts.input; + const { id, monitors, date, message, ...statusReportInput } = opts.input; const newStatusReport = await opts.ctx.db .insert(statusReport) @@ -50,19 +48,6 @@ export const statusReportRouter = createTRPCRouter({ .get(); } - if (pages.length > 0) { - await opts.ctx.db - .insert(pagesToStatusReports) - .values( - pages.map((page) => ({ - pageId: page, - statusReportId: newStatusReport.id, - })), - ) - .returning() - .get(); - } - return newStatusReport; }), @@ -70,7 +55,7 @@ export const statusReportRouter = createTRPCRouter({ .input(insertStatusReportUpdateSchema) .mutation(async (opts) => { // update parent status report with latest status - await opts.ctx.db + const _statusReport = await opts.ctx.db .update(statusReport) .set({ status: opts.input.status, updatedAt: new Date() }) .where( @@ -97,34 +82,23 @@ export const statusReportRouter = createTRPCRouter({ .from(workspace) .where(eq(workspace.id, opts.ctx.workspace.id)) .get(); - if (currentWorkspace?.plan !== "pro") { - const allPages = await opts.ctx.db + if (currentWorkspace?.plan !== "pro" && _statusReport.pageId) { + const subscribers = await opts.ctx.db .select() - .from(pagesToStatusReports) + .from(pageSubscriber) .where( - eq( - pagesToStatusReports.statusReportId, - updatedValue.statusReportId, + and( + eq(pageSubscriber.pageId, _statusReport.pageId), + isNotNull(pageSubscriber.acceptedAt), ), ) .all(); - for (const currentPage of allPages) { - const subscribers = await opts.ctx.db - .select() - .from(pageSubscriber) - .where( - and( - eq(pageSubscriber.pageId, currentPage.pageId), - isNotNull(pageSubscriber.acceptedAt), - ), - ) - .all(); - const pageInfo = await opts.ctx.db - .select() - .from(page) - .where(eq(page.id, currentPage.pageId)) - .get(); - if (!pageInfo) continue; + const pageInfo = await opts.ctx.db + .select() + .from(page) + .where(eq(page.id, _statusReport.pageId)) + .get(); + if (pageInfo) { const subscribersEmails = subscribers.map( (subscriber) => subscriber.email, ); @@ -143,7 +117,7 @@ export const statusReportRouter = createTRPCRouter({ updateStatusReport: protectedProcedure .input(insertStatusReportSchema) .mutation(async (opts) => { - const { monitors, pages, ...statusReportInput } = opts.input; + const { monitors, ...statusReportInput } = opts.input; if (!statusReportInput.id) return; @@ -201,42 +175,6 @@ export const statusReportRouter = createTRPCRouter({ .run(); } - const currentPagesToStatusReports = await opts.ctx.db - .select() - .from(pagesToStatusReports) - .where(eq(pagesToStatusReports.statusReportId, currentStatusReport.id)) - .all(); - - const addedPages = pages?.filter( - (x) => - !currentPagesToStatusReports.map(({ pageId }) => pageId)?.includes(x), - ); - - if (addedPages.length) { - const values = addedPages.map((pageId) => ({ - pageId, - statusReportId: currentStatusReport.id, - })); - - await opts.ctx.db.insert(pagesToStatusReports).values(values).run(); - } - - const removedPages = currentPagesToStatusReports - .map(({ pageId }) => pageId) - .filter((x) => !pages?.includes(x)); - - if (removedPages.length) { - await opts.ctx.db - .delete(pagesToStatusReports) - .where( - and( - eq(pagesToStatusReports.statusReportId, currentStatusReport.id), - inArray(pagesToStatusReports.pageId, removedPages), - ), - ) - .run(); - } - return currentStatusReport; }), @@ -296,7 +234,7 @@ export const statusReportRouter = createTRPCRouter({ }), getStatusReportById: protectedProcedure - .input(z.object({ id: z.number() })) + .input(z.object({ id: z.number(), pageId: z.number().optional() })) .query(async (opts) => { const selectPublicStatusReportSchemaWithRelation = selectStatusReportSchema.extend({ @@ -310,9 +248,6 @@ export const statusReportRouter = createTRPCRouter({ }), ) .default([]), - pagesToStatusReports: z - .array(z.object({ statusReportId: z.number(), pageId: z.number() })) - .default([]), statusReportUpdates: z.array(selectStatusReportUpdateSchema), date: z.date().default(new Date()), }); @@ -321,10 +256,13 @@ export const statusReportRouter = createTRPCRouter({ where: and( eq(statusReport.id, opts.input.id), eq(statusReport.workspaceId, opts.ctx.workspace.id), + // only allow to fetch status report if it belongs to the page + opts.input.pageId + ? eq(statusReport.pageId, opts.input.pageId) + : undefined, ), with: { monitorsToStatusReports: { with: { monitor: true } }, - pagesToStatusReports: true, statusReportUpdates: { orderBy: (statusReportUpdate, { desc }) => [ desc(statusReportUpdate.createdAt), @@ -377,6 +315,42 @@ export const statusReportRouter = createTRPCRouter({ return z.array(selectStatusSchemaWithRelation).parse(result); }), + getStatusReportByPageId: protectedProcedure + .input(z.object({ id: z.number() })) + .query(async (opts) => { + // FIXME: can we get rid of that? + const selectStatusSchemaWithRelation = selectStatusReportSchema.extend({ + status: statusReportStatusSchema.default("investigating"), // TODO: remove! + monitorsToStatusReports: z + .array( + z.object({ + statusReportId: z.number(), + monitorId: z.number(), + monitor: selectMonitorSchema, + }), + ) + .default([]), + statusReportUpdates: z.array(selectStatusReportUpdateSchema), + }); + + const result = await opts.ctx.db.query.statusReport.findMany({ + where: and( + eq(statusReport.workspaceId, opts.ctx.workspace.id), + eq(statusReport.pageId, opts.input.id), + ), + with: { + monitorsToStatusReports: { with: { monitor: true } }, + statusReportUpdates: { + orderBy: (statusReportUpdate, { desc }) => [ + desc(statusReportUpdate.createdAt), + ], + }, + }, + orderBy: (statusReport, { desc }) => [desc(statusReport.updatedAt)], + }); + return z.array(selectStatusSchemaWithRelation).parse(result); + }), + getPublicStatusReportById: publicProcedure .input(z.object({ slug: z.string().toLowerCase(), id: z.number() })) .query(async (opts) => { @@ -389,6 +363,7 @@ export const statusReportRouter = createTRPCRouter({ const _statusReport = await opts.ctx.db.query.statusReport.findFirst({ where: and( eq(statusReport.id, opts.input.id), + eq(statusReport.pageId, result.id), eq(statusReport.workspaceId, result.workspaceId), ), with: { diff --git a/packages/api/src/router/workspace.ts b/packages/api/src/router/workspace.ts index 3e4e44c3..bbbdcff5 100644 --- a/packages/api/src/router/workspace.ts +++ b/packages/api/src/router/workspace.ts @@ -3,7 +3,7 @@ import { generateSlug } from "random-word-slugs"; import * as randomWordSlugs from "random-word-slugs"; import { z } from "zod"; -import { and, eq, sql } from "@openstatus/db"; +import { and, eq, isNotNull, sql } from "@openstatus/db"; import { application, monitor, @@ -206,7 +206,12 @@ export const workspaceRouter = createTRPCRouter({ const monitors = await tx .select({ count: sql`count(*)` }) .from(monitor) - .where(eq(monitor.workspaceId, opts.ctx.workspace.id)); + .where( + and( + eq(monitor.workspaceId, opts.ctx.workspace.id), + isNotNull(monitor.deletedAt), + ), + ); const pages = await tx .select({ count: sql`count(*)` }) .from(page) diff --git a/packages/db/drizzle/0034_serious_shard.sql b/packages/db/drizzle/0034_serious_shard.sql new file mode 100644 index 00000000..0c7d209c --- /dev/null +++ b/packages/db/drizzle/0034_serious_shard.sql @@ -0,0 +1,3 @@ +ALTER TABLE `status_report` ADD `page_id` integer REFERENCES page(id);--> statement-breakpoint + +UPDATE `status_report` SET `page_id` = `t`.`page_id` from (select `page_id`, `status_report_id` from `status_reports_to_pages`) `t` where `t`.`status_report_id` = `id` ; \ No newline at end of file diff --git a/packages/db/drizzle/meta/0034_snapshot.json b/packages/db/drizzle/meta/0034_snapshot.json new file mode 100644 index 00000000..9428f24c --- /dev/null +++ b/packages/db/drizzle/meta/0034_snapshot.json @@ -0,0 +1,2186 @@ +{ + "version": "6", + "dialect": "sqlite", + "id": "145f2782-3cb0-4066-9842-881a17636999", + "prevId": "447f81c0-1837-4e85-bb0e-9ecce75e95d9", + "tables": { + "status_report_to_monitors": { + "name": "status_report_to_monitors", + "columns": { + "monitor_id": { + "name": "monitor_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "status_report_id": { + "name": "status_report_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(strftime('%s', 'now'))" + } + }, + "indexes": {}, + "foreignKeys": { + "status_report_to_monitors_monitor_id_monitor_id_fk": { + "name": "status_report_to_monitors_monitor_id_monitor_id_fk", + "tableFrom": "status_report_to_monitors", + "tableTo": "monitor", + "columnsFrom": [ + "monitor_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "status_report_to_monitors_status_report_id_status_report_id_fk": { + "name": "status_report_to_monitors_status_report_id_status_report_id_fk", + "tableFrom": "status_report_to_monitors", + "tableTo": "status_report", + "columnsFrom": [ + "status_report_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "status_report_to_monitors_monitor_id_status_report_id_pk": { + "columns": [ + "monitor_id", + "status_report_id" + ], + "name": "status_report_to_monitors_monitor_id_status_report_id_pk" + } + }, + "uniqueConstraints": {} + }, + "status_report": { + "name": "status_report", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "title": { + "name": "title", + "type": "text(256)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "workspace_id": { + "name": "workspace_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "page_id": { + "name": "page_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(strftime('%s', 'now'))" + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(strftime('%s', 'now'))" + } + }, + "indexes": {}, + "foreignKeys": { + "status_report_workspace_id_workspace_id_fk": { + "name": "status_report_workspace_id_workspace_id_fk", + "tableFrom": "status_report", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "status_report_page_id_page_id_fk": { + "name": "status_report_page_id_page_id_fk", + "tableFrom": "status_report", + "tableTo": "page", + "columnsFrom": [ + "page_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "status_report_update": { + "name": "status_report_update", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "text(4)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "date": { + "name": "date", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "message": { + "name": "message", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "status_report_id": { + "name": "status_report_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(strftime('%s', 'now'))" + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(strftime('%s', 'now'))" + } + }, + "indexes": {}, + "foreignKeys": { + "status_report_update_status_report_id_status_report_id_fk": { + "name": "status_report_update_status_report_id_status_report_id_fk", + "tableFrom": "status_report_update", + "tableTo": "status_report", + "columnsFrom": [ + "status_report_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "integration": { + "name": "integration", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text(256)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "workspace_id": { + "name": "workspace_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "credential": { + "name": "credential", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "external_id": { + "name": "external_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(strftime('%s', 'now'))" + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(strftime('%s', 'now'))" + }, + "data": { + "name": "data", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": { + "integration_workspace_id_workspace_id_fk": { + "name": "integration_workspace_id_workspace_id_fk", + "tableFrom": "integration", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "page": { + "name": "page", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "workspace_id": { + "name": "workspace_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "icon": { + "name": "icon", + "type": "text(256)", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "''" + }, + "slug": { + "name": "slug", + "type": "text(256)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "custom_domain": { + "name": "custom_domain", + "type": "text(256)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "published": { + "name": "published", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": false + }, + "password": { + "name": "password", + "type": "text(256)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "password_protected": { + "name": "password_protected", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(strftime('%s', 'now'))" + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(strftime('%s', 'now'))" + } + }, + "indexes": { + "page_slug_unique": { + "name": "page_slug_unique", + "columns": [ + "slug" + ], + "isUnique": true + } + }, + "foreignKeys": { + "page_workspace_id_workspace_id_fk": { + "name": "page_workspace_id_workspace_id_fk", + "tableFrom": "page", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "monitor": { + "name": "monitor", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "job_type": { + "name": "job_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'other'" + }, + "periodicity": { + "name": "periodicity", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'other'" + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'active'" + }, + "active": { + "name": "active", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": false + }, + "regions": { + "name": "regions", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "''" + }, + "url": { + "name": "url", + "type": "text(2048)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text(256)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "''" + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "''" + }, + "headers": { + "name": "headers", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "''" + }, + "body": { + "name": "body", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "''" + }, + "method": { + "name": "method", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "'GET'" + }, + "workspace_id": { + "name": "workspace_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "timeout": { + "name": "timeout", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 45000 + }, + "degraded_after": { + "name": "degraded_after", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "assertions": { + "name": "assertions", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "public": { + "name": "public", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(strftime('%s', 'now'))" + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(strftime('%s', 'now'))" + }, + "deleted_at": { + "name": "deleted_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": { + "monitor_workspace_id_workspace_id_fk": { + "name": "monitor_workspace_id_workspace_id_fk", + "tableFrom": "monitor", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "monitors_to_pages": { + "name": "monitors_to_pages", + "columns": { + "monitor_id": { + "name": "monitor_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "page_id": { + "name": "page_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(strftime('%s', 'now'))" + }, + "order": { + "name": "order", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + } + }, + "indexes": {}, + "foreignKeys": { + "monitors_to_pages_monitor_id_monitor_id_fk": { + "name": "monitors_to_pages_monitor_id_monitor_id_fk", + "tableFrom": "monitors_to_pages", + "tableTo": "monitor", + "columnsFrom": [ + "monitor_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "monitors_to_pages_page_id_page_id_fk": { + "name": "monitors_to_pages_page_id_page_id_fk", + "tableFrom": "monitors_to_pages", + "tableTo": "page", + "columnsFrom": [ + "page_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "monitors_to_pages_monitor_id_page_id_pk": { + "columns": [ + "monitor_id", + "page_id" + ], + "name": "monitors_to_pages_monitor_id_page_id_pk" + } + }, + "uniqueConstraints": {} + }, + "account": { + "name": "account", + "columns": { + "user_id": { + "name": "user_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "provider": { + "name": "provider", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "provider_account_id": { + "name": "provider_account_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "expires_at": { + "name": "expires_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "token_type": { + "name": "token_type", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "scope": { + "name": "scope", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "id_token": { + "name": "id_token", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "session_state": { + "name": "session_state", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": { + "account_user_id_user_id_fk": { + "name": "account_user_id_user_id_fk", + "tableFrom": "account", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "account_provider_provider_account_id_pk": { + "columns": [ + "provider", + "provider_account_id" + ], + "name": "account_provider_provider_account_id_pk" + } + }, + "uniqueConstraints": {} + }, + "session": { + "name": "session", + "columns": { + "session_token": { + "name": "session_token", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "expires": { + "name": "expires", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": { + "session_user_id_user_id_fk": { + "name": "session_user_id_user_id_fk", + "tableFrom": "session", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "user": { + "name": "user", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "tenant_id": { + "name": "tenant_id", + "type": "text(256)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "first_name": { + "name": "first_name", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "''" + }, + "last_name": { + "name": "last_name", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "''" + }, + "photo_url": { + "name": "photo_url", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "''" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "''" + }, + "emailVerified": { + "name": "emailVerified", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(strftime('%s', 'now'))" + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(strftime('%s', 'now'))" + } + }, + "indexes": { + "user_tenant_id_unique": { + "name": "user_tenant_id_unique", + "columns": [ + "tenant_id" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "users_to_workspaces": { + "name": "users_to_workspaces", + "columns": { + "user_id": { + "name": "user_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "workspace_id": { + "name": "workspace_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'member'" + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(strftime('%s', 'now'))" + } + }, + "indexes": {}, + "foreignKeys": { + "users_to_workspaces_user_id_user_id_fk": { + "name": "users_to_workspaces_user_id_user_id_fk", + "tableFrom": "users_to_workspaces", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "users_to_workspaces_workspace_id_workspace_id_fk": { + "name": "users_to_workspaces_workspace_id_workspace_id_fk", + "tableFrom": "users_to_workspaces", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "users_to_workspaces_user_id_workspace_id_pk": { + "columns": [ + "user_id", + "workspace_id" + ], + "name": "users_to_workspaces_user_id_workspace_id_pk" + } + }, + "uniqueConstraints": {} + }, + "verification_token": { + "name": "verification_token", + "columns": { + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "expires": { + "name": "expires", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": { + "verification_token_identifier_token_pk": { + "columns": [ + "identifier", + "token" + ], + "name": "verification_token_identifier_token_pk" + } + }, + "uniqueConstraints": {} + }, + "page_subscriber": { + "name": "page_subscriber", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "page_id": { + "name": "page_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "accepted_at": { + "name": "accepted_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "expires_at": { + "name": "expires_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(strftime('%s', 'now'))" + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(strftime('%s', 'now'))" + } + }, + "indexes": {}, + "foreignKeys": { + "page_subscriber_page_id_page_id_fk": { + "name": "page_subscriber_page_id_page_id_fk", + "tableFrom": "page_subscriber", + "tableTo": "page", + "columnsFrom": [ + "page_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "workspace": { + "name": "workspace", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "stripe_id": { + "name": "stripe_id", + "type": "text(256)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "subscription_id": { + "name": "subscription_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "plan": { + "name": "plan", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "ends_at": { + "name": "ends_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "paid_until": { + "name": "paid_until", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(strftime('%s', 'now'))" + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(strftime('%s', 'now'))" + }, + "dsn": { + "name": "dsn", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "workspace_slug_unique": { + "name": "workspace_slug_unique", + "columns": [ + "slug" + ], + "isUnique": true + }, + "workspace_stripe_id_unique": { + "name": "workspace_stripe_id_unique", + "columns": [ + "stripe_id" + ], + "isUnique": true + }, + "workspace_id_dsn_unique": { + "name": "workspace_id_dsn_unique", + "columns": [ + "id", + "dsn" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "notification": { + "name": "notification", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "provider": { + "name": "provider", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "data": { + "name": "data", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "'{}'" + }, + "workspace_id": { + "name": "workspace_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(strftime('%s', 'now'))" + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(strftime('%s', 'now'))" + } + }, + "indexes": {}, + "foreignKeys": { + "notification_workspace_id_workspace_id_fk": { + "name": "notification_workspace_id_workspace_id_fk", + "tableFrom": "notification", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "notifications_to_monitors": { + "name": "notifications_to_monitors", + "columns": { + "monitor_id": { + "name": "monitor_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "notification_id": { + "name": "notification_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(strftime('%s', 'now'))" + } + }, + "indexes": {}, + "foreignKeys": { + "notifications_to_monitors_monitor_id_monitor_id_fk": { + "name": "notifications_to_monitors_monitor_id_monitor_id_fk", + "tableFrom": "notifications_to_monitors", + "tableTo": "monitor", + "columnsFrom": [ + "monitor_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "notifications_to_monitors_notification_id_notification_id_fk": { + "name": "notifications_to_monitors_notification_id_notification_id_fk", + "tableFrom": "notifications_to_monitors", + "tableTo": "notification", + "columnsFrom": [ + "notification_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "notifications_to_monitors_monitor_id_notification_id_pk": { + "columns": [ + "monitor_id", + "notification_id" + ], + "name": "notifications_to_monitors_monitor_id_notification_id_pk" + } + }, + "uniqueConstraints": {} + }, + "monitor_status": { + "name": "monitor_status", + "columns": { + "monitor_id": { + "name": "monitor_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "region": { + "name": "region", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "''" + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'active'" + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(strftime('%s', 'now'))" + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(strftime('%s', 'now'))" + } + }, + "indexes": { + "monitor_status_idx": { + "name": "monitor_status_idx", + "columns": [ + "monitor_id", + "region" + ], + "isUnique": false + } + }, + "foreignKeys": { + "monitor_status_monitor_id_monitor_id_fk": { + "name": "monitor_status_monitor_id_monitor_id_fk", + "tableFrom": "monitor_status", + "tableTo": "monitor", + "columnsFrom": [ + "monitor_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "monitor_status_monitor_id_region_pk": { + "columns": [ + "monitor_id", + "region" + ], + "name": "monitor_status_monitor_id_region_pk" + } + }, + "uniqueConstraints": {} + }, + "invitation": { + "name": "invitation", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'member'" + }, + "workspace_id": { + "name": "workspace_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "expires_at": { + "name": "expires_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(strftime('%s', 'now'))" + }, + "accepted_at": { + "name": "accepted_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "incident": { + "name": "incident", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "''" + }, + "summary": { + "name": "summary", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "''" + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'triage'" + }, + "monitor_id": { + "name": "monitor_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "workspace_id": { + "name": "workspace_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "started_at": { + "name": "started_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(strftime('%s', 'now'))" + }, + "acknowledged_at": { + "name": "acknowledged_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "acknowledged_by": { + "name": "acknowledged_by", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "resolved_at": { + "name": "resolved_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "resolved_by": { + "name": "resolved_by", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "incident_screenshot_url": { + "name": "incident_screenshot_url", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "recovery_screenshot_url": { + "name": "recovery_screenshot_url", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "auto_resolved": { + "name": "auto_resolved", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(strftime('%s', 'now'))" + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(strftime('%s', 'now'))" + } + }, + "indexes": { + "incident_monitor_id_started_at_unique": { + "name": "incident_monitor_id_started_at_unique", + "columns": [ + "monitor_id", + "started_at" + ], + "isUnique": true + } + }, + "foreignKeys": { + "incident_monitor_id_monitor_id_fk": { + "name": "incident_monitor_id_monitor_id_fk", + "tableFrom": "incident", + "tableTo": "monitor", + "columnsFrom": [ + "monitor_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set default", + "onUpdate": "no action" + }, + "incident_workspace_id_workspace_id_fk": { + "name": "incident_workspace_id_workspace_id_fk", + "tableFrom": "incident", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "incident_acknowledged_by_user_id_fk": { + "name": "incident_acknowledged_by_user_id_fk", + "tableFrom": "incident", + "tableTo": "user", + "columnsFrom": [ + "acknowledged_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "incident_resolved_by_user_id_fk": { + "name": "incident_resolved_by_user_id_fk", + "tableFrom": "incident", + "tableTo": "user", + "columnsFrom": [ + "resolved_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "monitor_tag": { + "name": "monitor_tag", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "workspace_id": { + "name": "workspace_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "color": { + "name": "color", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(strftime('%s', 'now'))" + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(strftime('%s', 'now'))" + } + }, + "indexes": {}, + "foreignKeys": { + "monitor_tag_workspace_id_workspace_id_fk": { + "name": "monitor_tag_workspace_id_workspace_id_fk", + "tableFrom": "monitor_tag", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "monitor_tag_to_monitor": { + "name": "monitor_tag_to_monitor", + "columns": { + "monitor_id": { + "name": "monitor_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "monitor_tag_id": { + "name": "monitor_tag_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(strftime('%s', 'now'))" + } + }, + "indexes": {}, + "foreignKeys": { + "monitor_tag_to_monitor_monitor_id_monitor_id_fk": { + "name": "monitor_tag_to_monitor_monitor_id_monitor_id_fk", + "tableFrom": "monitor_tag_to_monitor", + "tableTo": "monitor", + "columnsFrom": [ + "monitor_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "monitor_tag_to_monitor_monitor_tag_id_monitor_tag_id_fk": { + "name": "monitor_tag_to_monitor_monitor_tag_id_monitor_tag_id_fk", + "tableFrom": "monitor_tag_to_monitor", + "tableTo": "monitor_tag", + "columnsFrom": [ + "monitor_tag_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "monitor_tag_to_monitor_monitor_id_monitor_tag_id_pk": { + "columns": [ + "monitor_id", + "monitor_tag_id" + ], + "name": "monitor_tag_to_monitor_monitor_id_monitor_tag_id_pk" + } + }, + "uniqueConstraints": {} + }, + "application": { + "name": "application", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "dsn": { + "name": "dsn", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "workspace_id": { + "name": "workspace_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(strftime('%s', 'now'))" + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(strftime('%s', 'now'))" + } + }, + "indexes": { + "application_dsn_unique": { + "name": "application_dsn_unique", + "columns": [ + "dsn" + ], + "isUnique": true + } + }, + "foreignKeys": { + "application_workspace_id_workspace_id_fk": { + "name": "application_workspace_id_workspace_id_fk", + "tableFrom": "application", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "maintenance": { + "name": "maintenance", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "title": { + "name": "title", + "type": "text(256)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "message": { + "name": "message", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "from": { + "name": "from", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "to": { + "name": "to", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "workspace_id": { + "name": "workspace_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "page_id": { + "name": "page_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(strftime('%s', 'now'))" + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(strftime('%s', 'now'))" + } + }, + "indexes": {}, + "foreignKeys": { + "maintenance_workspace_id_workspace_id_fk": { + "name": "maintenance_workspace_id_workspace_id_fk", + "tableFrom": "maintenance", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "maintenance_page_id_page_id_fk": { + "name": "maintenance_page_id_page_id_fk", + "tableFrom": "maintenance", + "tableTo": "page", + "columnsFrom": [ + "page_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "maintenance_to_monitor": { + "name": "maintenance_to_monitor", + "columns": { + "monitor_id": { + "name": "monitor_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "maintenance_id": { + "name": "maintenance_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(strftime('%s', 'now'))" + } + }, + "indexes": {}, + "foreignKeys": { + "maintenance_to_monitor_monitor_id_monitor_id_fk": { + "name": "maintenance_to_monitor_monitor_id_monitor_id_fk", + "tableFrom": "maintenance_to_monitor", + "tableTo": "monitor", + "columnsFrom": [ + "monitor_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "maintenance_to_monitor_maintenance_id_maintenance_id_fk": { + "name": "maintenance_to_monitor_maintenance_id_maintenance_id_fk", + "tableFrom": "maintenance_to_monitor", + "tableTo": "maintenance", + "columnsFrom": [ + "maintenance_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "maintenance_to_monitor_monitor_id_maintenance_id_pk": { + "columns": [ + "maintenance_id", + "monitor_id" + ], + "name": "maintenance_to_monitor_monitor_id_maintenance_id_pk" + } + }, + "uniqueConstraints": {} + }, + "check": { + "name": "check", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "regions": { + "name": "regions", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "''" + }, + "url": { + "name": "url", + "type": "text(4096)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "headers": { + "name": "headers", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "''" + }, + "body": { + "name": "body", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "''" + }, + "method": { + "name": "method", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "'GET'" + }, + "count_requests": { + "name": "count_requests", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 1 + }, + "workspace_id": { + "name": "workspace_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "(strftime('%s', 'now'))" + } + }, + "indexes": {}, + "foreignKeys": { + "check_workspace_id_workspace_id_fk": { + "name": "check_workspace_id_workspace_id_fk", + "tableFrom": "check", + "tableTo": "workspace", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + } + }, + "enums": {}, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + } +} \ No newline at end of file diff --git a/packages/db/drizzle/meta/_journal.json b/packages/db/drizzle/meta/_journal.json index a4ccd2c3..932f409f 100644 --- a/packages/db/drizzle/meta/_journal.json +++ b/packages/db/drizzle/meta/_journal.json @@ -239,6 +239,13 @@ "when": 1719740057514, "tag": "0033_solid_colossus", "breakpoints": true + }, + { + "idx": 34, + "version": "6", + "when": 1720727898360, + "tag": "0034_serious_shard", + "breakpoints": true } ] } \ No newline at end of file diff --git a/packages/db/src/schema/pages/page.ts b/packages/db/src/schema/pages/page.ts index ebe2e9cc..af95bbe0 100644 --- a/packages/db/src/schema/pages/page.ts +++ b/packages/db/src/schema/pages/page.ts @@ -3,7 +3,6 @@ import { integer, sqliteTable, text } from "drizzle-orm/sqlite-core"; import { maintenance } from "../maintenances"; import { monitorsToPages } from "../monitors"; -import { pagesToStatusReports } from "../status_reports"; import { workspace } from "../workspaces"; export const page = sqliteTable("page", { @@ -23,20 +22,19 @@ export const page = sqliteTable("page", { // Password protecting the status page - no specific restriction on password password: text("password", { length: 256 }), passwordProtected: integer("password_protected", { mode: "boolean" }).default( - false, + false ), createdAt: integer("created_at", { mode: "timestamp" }).default( - sql`(strftime('%s', 'now'))`, + sql`(strftime('%s', 'now'))` ), updatedAt: integer("updated_at", { mode: "timestamp" }).default( - sql`(strftime('%s', 'now'))`, + sql`(strftime('%s', 'now'))` ), }); export const pageRelations = relations(page, ({ many, one }) => ({ monitorsToPages: many(monitorsToPages), - pagesToStatusReports: many(pagesToStatusReports), maintenancesToPages: many(maintenance), workspace: one(workspace, { fields: [page.workspaceId], diff --git a/packages/db/src/schema/status_reports/status_reports.ts b/packages/db/src/schema/status_reports/status_reports.ts index 921d11ca..3b75877b 100644 --- a/packages/db/src/schema/status_reports/status_reports.ts +++ b/packages/db/src/schema/status_reports/status_reports.ts @@ -24,11 +24,13 @@ export const statusReport = sqliteTable("status_report", { workspaceId: integer("workspace_id").references(() => workspace.id), + pageId: integer("page_id").references(() => page.id), + createdAt: integer("created_at", { mode: "timestamp" }).default( - sql`(strftime('%s', 'now'))`, + sql`(strftime('%s', 'now'))` ), updatedAt: integer("updated_at", { mode: "timestamp" }).default( - sql`(strftime('%s', 'now'))`, + sql`(strftime('%s', 'now'))` ), }); @@ -43,10 +45,10 @@ export const statusReportUpdate = sqliteTable("status_report_update", { .references(() => statusReport.id, { onDelete: "cascade" }) .notNull(), createdAt: integer("created_at", { mode: "timestamp" }).default( - sql`(strftime('%s', 'now'))`, + sql`(strftime('%s', 'now'))` ), updatedAt: integer("updated_at", { mode: "timestamp" }).default( - sql`(strftime('%s', 'now'))`, + sql`(strftime('%s', 'now'))` ), }); @@ -54,13 +56,16 @@ export const StatusReportRelations = relations( statusReport, ({ one, many }) => ({ monitorsToStatusReports: many(monitorsToStatusReport), - pagesToStatusReports: many(pagesToStatusReports), + page: one(page, { + fields: [statusReport.pageId], + references: [page.id], + }), statusReportUpdates: many(statusReportUpdate), workspace: one(workspace, { fields: [statusReport.workspaceId], references: [workspace.id], }), - }), + }) ); export const statusReportUpdateRelations = relations( @@ -70,7 +75,7 @@ export const statusReportUpdateRelations = relations( fields: [statusReportUpdate.statusReportId], references: [statusReport.id], }), - }), + }) ); export const monitorsToStatusReport = sqliteTable( @@ -83,12 +88,12 @@ export const monitorsToStatusReport = sqliteTable( .notNull() .references(() => statusReport.id, { onDelete: "cascade" }), createdAt: integer("created_at", { mode: "timestamp" }).default( - sql`(strftime('%s', 'now'))`, + sql`(strftime('%s', 'now'))` ), }, (t) => ({ pk: primaryKey(t.monitorId, t.statusReportId), - }), + }) ); export const monitorsToStatusReportRelations = relations( @@ -102,37 +107,38 @@ export const monitorsToStatusReportRelations = relations( fields: [monitorsToStatusReport.statusReportId], references: [statusReport.id], }), - }), + }) ); -export const pagesToStatusReports = sqliteTable( - "status_reports_to_pages", - { - pageId: integer("page_id") - .notNull() - .references(() => page.id, { onDelete: "cascade" }), - statusReportId: integer("status_report_id") - .notNull() - .references(() => statusReport.id, { onDelete: "cascade" }), - createdAt: integer("created_at", { mode: "timestamp" }).default( - sql`(strftime('%s', 'now'))`, - ), - }, - (t) => ({ - pk: primaryKey(t.pageId, t.statusReportId), - }), -); +// FIXME: We might have to drop foreign key constraints for the following tables +// export const pagesToStatusReports = sqliteTable( +// "status_reports_to_pages", +// { +// pageId: integer("page_id") +// .notNull() +// .references(() => page.id, { onDelete: "cascade" }), +// statusReportId: integer("status_report_id") +// .notNull() +// .references(() => statusReport.id, { onDelete: "cascade" }), +// createdAt: integer("created_at", { mode: "timestamp" }).default( +// sql`(strftime('%s', 'now'))` +// ), +// }, +// (t) => ({ +// pk: primaryKey(t.pageId, t.statusReportId), +// }) +// ); -export const pagesToStatusReportsRelations = relations( - pagesToStatusReports, - ({ one }) => ({ - page: one(page, { - fields: [pagesToStatusReports.pageId], - references: [page.id], - }), - statusReport: one(statusReport, { - fields: [pagesToStatusReports.statusReportId], - references: [statusReport.id], - }), - }), -); +// export const pagesToStatusReportsRelations = relations( +// pagesToStatusReports, +// ({ one }) => ({ +// page: one(page, { +// fields: [pagesToStatusReports.pageId], +// references: [page.id], +// }), +// statusReport: one(statusReport, { +// fields: [pagesToStatusReports.statusReportId], +// references: [statusReport.id], +// }), +// }) +// ); diff --git a/packages/db/src/schema/status_reports/validation.ts b/packages/db/src/schema/status_reports/validation.ts index f07ba54a..6dd34c0c 100644 --- a/packages/db/src/schema/status_reports/validation.ts +++ b/packages/db/src/schema/status_reports/validation.ts @@ -13,7 +13,7 @@ export const insertStatusReportUpdateSchema = createInsertSchema( statusReportUpdate, { status: statusReportStatusSchema, - }, + } ); export const insertStatusReportSchema = createInsertSchema(statusReport, { @@ -25,7 +25,6 @@ export const insertStatusReportSchema = createInsertSchema(statusReport, { * relationship to monitors and pages */ monitors: z.number().array().optional().default([]), - pages: z.number().array().optional().default([]), }) .extend({ /** @@ -42,7 +41,7 @@ export const selectStatusReportUpdateSchema = createSelectSchema( statusReportUpdate, { status: statusReportStatusSchema, - }, + } ); export type InsertStatusReport = z.infer; diff --git a/packages/db/src/seed.mts b/packages/db/src/seed.mts index 9f1acf67..92143912 100644 --- a/packages/db/src/seed.mts +++ b/packages/db/src/seed.mts @@ -11,7 +11,6 @@ import { notification, notificationsToMonitors, page, - pagesToStatusReports, statusReport, statusReportUpdate, user, @@ -143,6 +142,7 @@ async function main() { .values({ id: 1, workspaceId: 1, + pageId:1, title: "Test Status Report", status: "investigating", updatedAt: new Date(), @@ -165,6 +165,7 @@ async function main() { .values({ id: 2, workspaceId: 1, + pageId:1, title: "Test Status Report", status: "investigating", updatedAt: new Date(), @@ -193,17 +194,6 @@ async function main() { }, ]); - await db.insert(pagesToStatusReports).values([ - { - pageId: 1, - statusReportId: 2, - }, - { - pageId: 1, - statusReportId: 1, - }, - ]); - await db .insert(incidentTable) .values({ diff --git a/utils/api-bruno/checker.bru b/utils/api-bruno/checker.bru index e61d9138..4f4346b7 100644 --- a/utils/api-bruno/checker.bru +++ b/utils/api-bruno/checker.bru @@ -24,7 +24,7 @@ body:json { "url":"https://openstat.us/404", "status": "active", "cronTimestamp":1699088595307 - "pageIds":["1"] + "pageId":1 } } @@ -36,6 +36,6 @@ body:text { "url":"https://openstat.us/404", "status": "active", "cronTimestamp":1699088595307, - "pageIds":["1"] + "pageId":1 } }