Skip to content

Commit 38c2fad

Browse files
committed
feat(db): add platform notification models and relations
Add PlatformNotification and PlatformNotificationInteraction Prisma models, including enums PlatformNotificationSurface and PlatformNotificationScope, indexes, timestamps, and fields for scoping (user, project, organization), lifecycle (startsAt, endsAt, archivedAt) and delivery behavior (CLI-specific fields, priority). Wire new relations into User, Organization, Project, OrgMember and Workspace models so notifications and interactions can be queried from those entities. Add SQL migration to create the new enums and adjust schema constraints and indexes required for the migration. The change enables admin-created, scoped platform notifications with per-user interaction tracking for both webapp and CLI surfaces. feat(notifications): Add a way to notify users on platform feat(notifications): Enforce notifications expired date, add CLI improvements CLI colors CLI show every n-th notification feat(webapp): Platform notifications ui/ux improvements feat(CLI): CLI notifications v1 feat(webapp): add dashboard platform notifications service & UI Introduce a new server-side service to read and record platform notifications targeted at the webapp. - Add payload schema (v1) using zod and typed PayloadV1. - Define PlatformNotificationWithPayload type and scope priority map. - Implement getActivePlatformNotifications to: - query active WEBAPP notifications with scope/org/project/user filters, - include user interactions and validate payloads, - filter dismissed items, compute unreadCount, and return sorted results. - Add helper functions: - findInteraction to match global/org interactions, - compareNotifications to sort by scope, priority, then recency. - Implement upsertInteraction to create or update platform notification interactions, handling GLOBAL-scoped interactions per organization. These changes centralize notification read/write logic, enforce payload validation, and provide deterministic ordering and unread counts for the webapp UI.
1 parent f86e492 commit 38c2fad

25 files changed

+2915
-89
lines changed

apps/webapp/app/components/navigation/HelpAndFeedbackPopover.tsx

Lines changed: 37 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
import { cn } from "~/utils/cn";
1212
import { DiscordIcon, SlackIcon } from "@trigger.dev/companyicons";
1313
import { Fragment, useState } from "react";
14+
import { useRecentChangelogs } from "~/routes/resources.platform-changelogs";
1415
import { motion } from "framer-motion";
1516
import { useCurrentPlan } from "~/routes/_app.orgs.$organizationSlug/route";
1617
import { useShortcutKeys } from "~/hooks/useShortcutKeys";
@@ -38,6 +39,7 @@ export function HelpAndFeedback({
3839
}) {
3940
const [isHelpMenuOpen, setHelpMenuOpen] = useState(false);
4041
const currentPlan = useCurrentPlan();
42+
const { changelogs } = useRecentChangelogs();
4143

4244
useShortcutKeys({
4345
shortcut: disableShortcut ? undefined : { key: "h", enabledOnInputElements: false },
@@ -140,96 +142,7 @@ export function HelpAndFeedback({
140142
data-action="suggest-a-feature"
141143
target="_blank"
142144
/>
143-
<SideMenuItem
144-
name="Changelog"
145-
icon={StarIcon}
146-
trailingIcon={ArrowUpRightIcon}
147-
trailingIconClassName="text-text-dimmed"
148-
inactiveIconColor="text-sun-500"
149-
activeIconColor="text-sun-500"
150-
to="https://trigger.dev/changelog"
151-
data-action="changelog"
152-
target="_blank"
153-
/>
154145
<Shortcuts />
155-
</div>
156-
<div className="flex flex-col gap-1 p-1">
157-
<Paragraph className="pb-1 pl-1.5 pt-1.5 text-xs">Need help?</Paragraph>
158-
{currentPlan?.v3Subscription?.plan?.limits.support === "slack" && (
159-
<div>
160-
<Dialog>
161-
<DialogTrigger asChild>
162-
<Button
163-
variant="small-menu-item"
164-
LeadingIcon={SlackIcon}
165-
data-action="join-our-slack"
166-
fullWidth
167-
textAlignLeft
168-
>
169-
<div className="flex w-full items-center justify-between">
170-
<span className="text-text-bright">Join our Slack…</span>
171-
<Badge variant="extra-small" className="uppercase">
172-
Pro
173-
</Badge>
174-
</div>
175-
</Button>
176-
</DialogTrigger>
177-
<DialogContent>
178-
<DialogHeader>Join our Slack</DialogHeader>
179-
<div className="mt-2 flex flex-col gap-4">
180-
<div className="flex items-center gap-4">
181-
<Icon icon={SlackIcon} className="h-10 w-10 min-w-[2.5rem]" />
182-
<Paragraph variant="base/bright">
183-
As a subscriber, you have access to a dedicated Slack channel for 1-to-1
184-
support with the Trigger.dev team.
185-
</Paragraph>
186-
</div>
187-
<hr className="border-charcoal-800" />
188-
<div>
189-
<StepNumber stepNumber="1" title="Email us" />
190-
<StepContentContainer>
191-
<Paragraph>
192-
Send us an email to this address from your Trigger.dev account email
193-
address:
194-
<ClipboardField
195-
variant="secondary/medium"
196-
value="priority-support@trigger.dev"
197-
className="my-2"
198-
/>
199-
</Paragraph>
200-
</StepContentContainer>
201-
<StepNumber stepNumber="2" title="Look out for an invite from Slack" />
202-
<StepContentContainer>
203-
<Paragraph>
204-
As soon as we can, we'll setup a Slack Connect channel and say hello!
205-
</Paragraph>
206-
</StepContentContainer>
207-
</div>
208-
</div>
209-
</DialogContent>
210-
</Dialog>
211-
</div>
212-
)}
213-
<SideMenuItem
214-
name="Ask in our Discord"
215-
icon={DiscordIcon}
216-
trailingIcon={ArrowUpRightIcon}
217-
trailingIconClassName="text-text-dimmed"
218-
to="https://trigger.dev/discord"
219-
data-action="join our discord"
220-
target="_blank"
221-
/>
222-
<SideMenuItem
223-
name="Book a 15 min call"
224-
icon={CalendarDaysIcon}
225-
trailingIcon={ArrowUpRightIcon}
226-
trailingIconClassName="text-text-dimmed"
227-
inactiveIconColor="text-rose-500"
228-
activeIconColor="text-rose-500"
229-
to="https://cal.com/team/triggerdotdev/founders-call"
230-
data-action="book-a-call"
231-
target="_blank"
232-
/>
233146
<Feedback
234147
button={
235148
<Button
@@ -246,9 +159,44 @@ export function HelpAndFeedback({
246159
}
247160
/>
248161
</div>
162+
<div className="flex flex-col gap-1 p-1">
163+
<Paragraph className="pb-1 pl-1.5 pt-1.5 text-xs">What's new</Paragraph>
164+
{changelogs.map((entry) => (
165+
<SideMenuItem
166+
key={entry.id}
167+
name={entry.title}
168+
icon={GrayDotIcon}
169+
trailingIcon={ArrowUpRightIcon}
170+
trailingIconClassName="text-text-dimmed"
171+
inactiveIconColor="text-text-dimmed"
172+
activeIconColor="text-text-dimmed"
173+
to={entry.actionUrl ?? "https://trigger.dev/changelog"}
174+
target="_blank"
175+
/>
176+
))}
177+
<SideMenuItem
178+
name="Full changelog"
179+
icon={StarIcon}
180+
trailingIcon={ArrowUpRightIcon}
181+
trailingIconClassName="text-text-dimmed"
182+
inactiveIconColor="text-text-dimmed"
183+
activeIconColor="text-text-dimmed"
184+
to="https://trigger.dev/changelog"
185+
data-action="full-changelog"
186+
target="_blank"
187+
/>
188+
</div>
249189
</Fragment>
250190
</PopoverContent>
251191
</Popover>
252192
</motion.div>
253193
);
254194
}
195+
196+
function GrayDotIcon({ className }: { className?: string }) {
197+
return (
198+
<span className={cn("flex items-center justify-center", className)}>
199+
<span className="block h-1.5 w-1.5 rounded-full bg-text-dimmed" />
200+
</span>
201+
);
202+
}

0 commit comments

Comments
 (0)