From de559508dcad26f4f803485a19d136a2e18282b7 Mon Sep 17 00:00:00 2001
From: Maximilian Kaske <56969857+mxkaske@users.noreply.github.com>
Date: Thu, 2 Jan 2025 20:09:23 +0100
Subject: [PATCH] feat: add quicklinks for status reports (#1148)
---
.../_components/status-report-button.tsx | 53 +++++++++++++++++++
.../status-pages/(overview)/page.tsx | 3 ++
.../notification/data-table-row-actions.tsx | 2 +
.../data-table/status-page/columns.tsx | 41 +++++++++++++-
.../status-page/data-table-row-actions.tsx | 6 +++
packages/api/src/router/page.ts | 9 ++++
packages/db/src/schema/pages/page.ts | 2 +
packages/db/src/schema/shared.ts | 4 ++
.../src/schema/status_reports/validation.ts | 6 ++-
packages/emails/src/client.tsx | 2 +-
10 files changed, 124 insertions(+), 4 deletions(-)
create mode 100644 apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/(overview)/_components/status-report-button.tsx
diff --git a/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/(overview)/_components/status-report-button.tsx b/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/(overview)/_components/status-report-button.tsx
new file mode 100644
index 000000000..e1a6f0193
--- /dev/null
+++ b/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/(overview)/_components/status-report-button.tsx
@@ -0,0 +1,53 @@
+import { cn } from "@/lib/utils";
+import type { Page } from "@openstatus/db/src/schema";
+import {
+ Alert,
+ AlertDescription,
+ AlertTitle,
+} from "@openstatus/ui/src/components/alert";
+import { buttonVariants } from "@openstatus/ui/src/components/button";
+import {
+ DropdownMenu,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuLabel,
+ DropdownMenuSeparator,
+ DropdownMenuTrigger,
+} from "@openstatus/ui/src/components/dropdown-menu";
+import { ChevronDown, Megaphone } from "lucide-react";
+import Link from "next/link";
+
+export function StatusReportButton({ pages }: { pages: Page[] }) {
+ return (
+
+ Status Reports
+
+ Start a new report. If you want to update your users about a current
+ report, please hover the Last Report column and click on{" "}
+ Go to report.
+
+
+
+
+ New Status Report
+
+
+
+
+ Select Page
+
+ {pages.map((page) => (
+
+ {page.title}
+
+ ))}
+
+
+
+ );
+}
diff --git a/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/(overview)/page.tsx b/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/(overview)/page.tsx
index 8e7600928..b6101a8ba 100644
--- a/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/(overview)/page.tsx
+++ b/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/(overview)/page.tsx
@@ -8,6 +8,7 @@ import { Limit } from "@/components/dashboard/limit";
import { columns } from "@/components/data-table/status-page/columns";
import { DataTable } from "@/components/data-table/status-page/data-table";
import { api } from "@/trpc/server";
+import { StatusReportButton } from "./_components/status-report-button";
export default async function MonitorPage() {
const pages = await api.page.getPagesByWorkspace.query();
@@ -27,10 +28,12 @@ export default async function MonitorPage() {
);
}
const isLimitReached = await api.page.isPageLimitReached.query();
+
return (
<>
{isLimitReached ? : null}
+
>
);
}
diff --git a/apps/web/src/components/data-table/notification/data-table-row-actions.tsx b/apps/web/src/components/data-table/notification/data-table-row-actions.tsx
index 894e33045..c0547f221 100644
--- a/apps/web/src/components/data-table/notification/data-table-row-actions.tsx
+++ b/apps/web/src/components/data-table/notification/data-table-row-actions.tsx
@@ -21,6 +21,7 @@ import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
+ DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@openstatus/ui";
@@ -72,6 +73,7 @@ export function DataTableRowActions({
Edit
+
Delete
diff --git a/apps/web/src/components/data-table/status-page/columns.tsx b/apps/web/src/components/data-table/status-page/columns.tsx
index 62cd03083..d95b10c68 100644
--- a/apps/web/src/components/data-table/status-page/columns.tsx
+++ b/apps/web/src/components/data-table/status-page/columns.tsx
@@ -5,7 +5,12 @@ import Image from "next/image";
import Link from "next/link";
import * as z from "zod";
-import type { Maintenance, Page } from "@openstatus/db/src/schema";
+import type {
+ Maintenance,
+ Page,
+ StatusReport,
+ StatusReportUpdate,
+} from "@openstatus/db/src/schema";
import {
Tooltip,
TooltipContent,
@@ -13,6 +18,7 @@ import {
TooltipTrigger,
} from "@openstatus/ui";
+import { formatDate } from "@/lib/utils";
import { ArrowUpRight, Check } from "lucide-react";
import { DataTableBadges } from "../data-table-badges";
import { DataTableRowActions } from "./data-table-row-actions";
@@ -21,6 +27,9 @@ export const columns: ColumnDef<
Page & {
monitorsToPages: { monitor: { name: string } }[];
maintenancesToPages: Maintenance[]; // we get only the active maintenances!
+ statusReports: (StatusReport & {
+ statusReportUpdates: StatusReportUpdate[];
+ })[];
}
>[] = [
{
@@ -85,6 +94,36 @@ export const columns: ColumnDef<
);
},
},
+ {
+ accessorKey: "statusReports",
+ header: "Last Report",
+ cell: ({ row }) => {
+ const lastReport = row.original.statusReports?.[0];
+
+ if (!lastReport) {
+ return -;
+ }
+
+ const date =
+ lastReport.statusReportUpdates?.[0].date || lastReport.updatedAt;
+
+ return (
+
+
+ {formatDate(date)}
+
+
+
+ Go to report
+
+
+
+ );
+ },
+ },
{
accessorKey: "icon",
header: "Favicon",
diff --git a/apps/web/src/components/data-table/status-page/data-table-row-actions.tsx b/apps/web/src/components/data-table/status-page/data-table-row-actions.tsx
index 8706eb9ac..bec49a950 100644
--- a/apps/web/src/components/data-table/status-page/data-table-row-actions.tsx
+++ b/apps/web/src/components/data-table/status-page/data-table-row-actions.tsx
@@ -21,6 +21,7 @@ import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
+ DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@openstatus/ui";
@@ -80,6 +81,11 @@ export function DataTableRowActions({
>
Visit
+
+
+ Create Report
+
+
Delete
diff --git a/packages/api/src/router/page.ts b/packages/api/src/router/page.ts
index 6f792293f..a449e45d0 100644
--- a/packages/api/src/router/page.ts
+++ b/packages/api/src/router/page.ts
@@ -224,8 +224,17 @@ export const pageRouter = createTRPCRouter({
gte(maintenance.to, new Date()),
),
},
+ statusReports: {
+ orderBy: (reports, { desc }) => desc(reports.updatedAt),
+ with: {
+ statusReportUpdates: {
+ orderBy: (updates, { desc }) => desc(updates.date),
+ },
+ },
+ },
},
});
+ console.log(allPages.map((page) => page.statusReports));
return z.array(selectPageSchemaWithMonitorsRelation).parse(allPages);
}),
diff --git a/packages/db/src/schema/pages/page.ts b/packages/db/src/schema/pages/page.ts
index 402d1b962..c0e27c5bd 100644
--- a/packages/db/src/schema/pages/page.ts
+++ b/packages/db/src/schema/pages/page.ts
@@ -3,6 +3,7 @@ import { integer, sqliteTable, text } from "drizzle-orm/sqlite-core";
import { maintenance } from "../maintenances";
import { monitorsToPages } from "../monitors";
+import { statusReport } from "../status_reports";
import { workspace } from "../workspaces";
export const page = sqliteTable("page", {
@@ -43,6 +44,7 @@ export const page = sqliteTable("page", {
export const pageRelations = relations(page, ({ many, one }) => ({
monitorsToPages: many(monitorsToPages),
maintenancesToPages: many(maintenance),
+ statusReports: many(statusReport),
workspace: one(workspace, {
fields: [page.workspaceId],
references: [workspace.id],
diff --git a/packages/db/src/schema/shared.ts b/packages/db/src/schema/shared.ts
index 67b17df58..a930ced0c 100644
--- a/packages/db/src/schema/shared.ts
+++ b/packages/db/src/schema/shared.ts
@@ -59,6 +59,10 @@ export const selectPageSchemaWithMonitorsRelation = selectPageSchema.extend({
}),
),
maintenancesToPages: selectMaintenanceSchema.array().default([]),
+ statusReports: selectStatusReportSchema
+ .extend({ statusReportUpdates: selectStatusReportUpdateSchema.array() })
+ .array()
+ .default([]),
});
export const selectPublicPageSchemaWithRelation = selectPageSchema
diff --git a/packages/db/src/schema/status_reports/validation.ts b/packages/db/src/schema/status_reports/validation.ts
index 2f8c35680..048bcc5fb 100644
--- a/packages/db/src/schema/status_reports/validation.ts
+++ b/packages/db/src/schema/status_reports/validation.ts
@@ -14,13 +14,15 @@ export const insertStatusReportUpdateSchema = createInsertSchema(
{
status: statusReportStatusSchema,
},
-);
+).extend({
+ date: z.coerce.date().optional().default(new Date()),
+});
export const insertStatusReportSchema = createInsertSchema(statusReport, {
status: statusReportStatusSchema,
})
.extend({
- date: z.date().optional().default(new Date()),
+ date: z.coerce.date().optional().default(new Date()),
/**
* relationship to monitors and pages
*/
diff --git a/packages/emails/src/client.tsx b/packages/emails/src/client.tsx
index a1050e5c1..efd2fbdfb 100644
--- a/packages/emails/src/client.tsx
+++ b/packages/emails/src/client.tsx
@@ -14,8 +14,8 @@ export class EmailClient {
public async sendFollowUp(req: { to: string }) {
if (process.env.NODE_ENV === "development") return;
- const html = await render();
try {
+ const html = await render();
const result = await this.client.emails.send({
from: "Thibault Le Ouay Ducasse ",
subject: "How's it going with OpenStatus?",
--
2.54.0