Skip to content

Commit 912ade7

Browse files
authored
Merge branch 'main' into docs/on-cancel-limitation
2 parents 6bf2880 + 6409fea commit 912ade7

File tree

81 files changed

+7625
-1485
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

81 files changed

+7625
-1485
lines changed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { VercelLogo } from "./VercelLogo";
2+
import { LinkButton } from "~/components/primitives/Buttons";
3+
import { SimpleTooltip } from "~/components/primitives/Tooltip";
4+
5+
export function VercelLink({ vercelDeploymentUrl }: { vercelDeploymentUrl: string }) {
6+
return (
7+
<SimpleTooltip
8+
button={
9+
<LinkButton
10+
variant="minimal/small"
11+
LeadingIcon={<VercelLogo className="size-3.5" />}
12+
iconSpacing="gap-x-1"
13+
to={vercelDeploymentUrl}
14+
className="pl-1"
15+
>
16+
Vercel
17+
</LinkButton>
18+
}
19+
content="View on Vercel"
20+
/>
21+
);
22+
}

apps/webapp/app/components/integrations/VercelOnboardingModal.tsx

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ import {
4444
} from "~/v3/vercel/vercelProjectIntegrationSchema";
4545
import { type VercelCustomEnvironment } from "~/models/vercelIntegration.server";
4646
import { type VercelOnboardingData } from "~/presenters/v3/VercelSettingsPresenter.server";
47-
import { vercelAppInstallPath, v3ProjectSettingsPath, githubAppInstallPath, vercelResourcePath } from "~/utils/pathBuilder";
47+
import { vercelAppInstallPath, v3ProjectSettingsIntegrationsPath, githubAppInstallPath, vercelResourcePath } from "~/utils/pathBuilder";
4848
import type { loader } from "~/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.vercel";
4949
import { useEffect, useState, useCallback, useRef } from "react";
5050
import { usePostHogTracking } from "~/hooks/usePostHog";
@@ -102,6 +102,7 @@ export function VercelOnboardingModal({
102102
hasOrgIntegration,
103103
nextUrl,
104104
onDataReload,
105+
vercelManageAccessUrl,
105106
}: {
106107
isOpen: boolean;
107108
onClose: () => void;
@@ -114,6 +115,7 @@ export function VercelOnboardingModal({
114115
hasOrgIntegration: boolean;
115116
nextUrl?: string;
116117
onDataReload?: (vercelStagingEnvironment?: string) => void;
118+
vercelManageAccessUrl?: string;
117119
}) {
118120
const { capture, startSessionRecording } = usePostHogTracking();
119121
const navigation = useNavigation();
@@ -122,7 +124,8 @@ export function VercelOnboardingModal({
122124
const completeOnboardingFetcher = useFetcher();
123125
const { Form: CompleteOnboardingForm } = completeOnboardingFetcher;
124126
const [searchParams] = useSearchParams();
125-
const fromMarketplaceContext = searchParams.get("origin") === "marketplace";
127+
const origin = searchParams.get("origin");
128+
const fromMarketplaceContext = origin === "marketplace";
126129

127130
const availableProjects = onboardingData?.availableProjects || [];
128131
const hasProjectSelected = onboardingData?.hasProjectSelected ?? false;
@@ -543,8 +546,15 @@ export function VercelOnboardingModal({
543546

544547
if (!isGitHubConnectedForOnboarding) {
545548
setState("github-connection");
549+
capture("vercel onboarding github step viewed", {
550+
origin: fromMarketplaceContext ? "marketplace" : "dashboard",
551+
step: "github-connection",
552+
organization_slug: organizationSlug,
553+
project_slug: projectSlug,
554+
github_app_installed: gitHubAppInstallations.length > 0,
555+
});
546556
}
547-
}, [vercelStagingEnvironment, pullEnvVarsBeforeBuild, atomicBuilds, discoverEnvVars, syncEnvVarsMapping, nextUrl, fromMarketplaceContext, isGitHubConnectedForOnboarding, completeOnboardingFetcher, actionUrl, trackOnboarding]);
557+
}, [vercelStagingEnvironment, pullEnvVarsBeforeBuild, atomicBuilds, discoverEnvVars, syncEnvVarsMapping, nextUrl, fromMarketplaceContext, isGitHubConnectedForOnboarding, completeOnboardingFetcher, actionUrl, trackOnboarding, capture, organizationSlug, projectSlug, gitHubAppInstallations.length]);
548558

549559
const handleFinishOnboarding = useCallback((e: React.FormEvent<HTMLFormElement>) => {
550560
e.preventDefault();
@@ -639,7 +649,7 @@ export function VercelOnboardingModal({
639649
onClose();
640650
}
641651
}}>
642-
<DialogContent className="max-w-lg">
652+
<DialogContent className="max-w-lg" onInteractOutside={(e) => e.preventDefault()}>
643653
<DialogHeader>
644654
<div className="flex items-center gap-2">
645655
<VercelLogo className="size-5" />
@@ -727,14 +737,25 @@ export function VercelOnboardingModal({
727737

728738
<FormButtons
729739
confirmButton={
730-
<Button
731-
variant="primary/medium"
732-
onClick={handleProjectSelection}
733-
disabled={!selectedVercelProject || fetcher.state !== "idle"}
734-
LeadingIcon={fetcher.state !== "idle" ? SpinnerWhite : undefined}
735-
>
736-
{fetcher.state !== "idle" ? "Connecting..." : "Connect Project"}
737-
</Button>
740+
<div className="flex items-center gap-2">
741+
{vercelManageAccessUrl && !origin && (
742+
<LinkButton
743+
to={vercelManageAccessUrl}
744+
variant="tertiary/medium"
745+
target="_self"
746+
>
747+
Manage access
748+
</LinkButton>
749+
)}
750+
<Button
751+
variant="primary/medium"
752+
onClick={handleProjectSelection}
753+
disabled={!selectedVercelProject || fetcher.state !== "idle"}
754+
LeadingIcon={fetcher.state !== "idle" ? SpinnerWhite : undefined}
755+
>
756+
{fetcher.state !== "idle" ? "Connecting..." : "Connect Project"}
757+
</Button>
758+
</div>
738759
}
739760
cancelButton={
740761
<Button
@@ -813,6 +834,7 @@ export function VercelOnboardingModal({
813834
<Header3>Pull Environment Variables</Header3>
814835
<Paragraph className="text-sm">
815836
Select which environment variables to pull from Vercel now. This is a one-time pull.
837+
Later on environment variables can be pulled before each build.
816838
</Paragraph>
817839

818840
<div className="flex gap-4 text-sm">
@@ -1057,7 +1079,7 @@ export function VercelOnboardingModal({
10571079
</Callout>
10581080

10591081
{(() => {
1060-
const baseSettingsPath = v3ProjectSettingsPath(
1082+
const baseSettingsPath = v3ProjectSettingsIntegrationsPath(
10611083
{ slug: organizationSlug },
10621084
{ slug: projectSlug },
10631085
{ slug: environmentSlug }
@@ -1081,6 +1103,7 @@ export function VercelOnboardingModal({
10811103
)}
10821104
variant="secondary/medium"
10831105
LeadingIcon={OctoKitty}
1106+
onClick={() => trackOnboarding("vercel onboarding github app install clicked")}
10841107
>
10851108
Install GitHub app
10861109
</LinkButton>
@@ -1110,6 +1133,7 @@ export function VercelOnboardingModal({
11101133
<Button
11111134
variant="primary/medium"
11121135
onClick={() => {
1136+
trackOnboarding("vercel onboarding github completed");
11131137
setState("completed");
11141138
const validUrl = safeRedirectUrl(nextUrl);
11151139
if (validUrl) {
@@ -1123,6 +1147,7 @@ export function VercelOnboardingModal({
11231147
<Button
11241148
variant="tertiary/medium"
11251149
onClick={() => {
1150+
trackOnboarding("vercel onboarding github skipped");
11261151
setState("completed");
11271152
if (fromMarketplaceContext && nextUrl) {
11281153
const validUrl = safeRedirectUrl(nextUrl);
@@ -1141,6 +1166,7 @@ export function VercelOnboardingModal({
11411166
<Button
11421167
variant="tertiary/medium"
11431168
onClick={() => {
1169+
trackOnboarding("vercel onboarding github skipped");
11441170
setState("completed");
11451171
}}
11461172
>

apps/webapp/app/components/logs/LogDetailView.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ function DetailsTab({
186186
<CopyableText value={log.runId} copyValue={log.runId} asChild />
187187
<LinkButton
188188
to={runPath}
189-
variant="tertiary/small"
189+
variant="secondary/small"
190190
shortcut={{ key: "v" }}
191191
className="mt-2"
192192
>

apps/webapp/app/components/logs/LogsTable.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import {
2626
TableRow,
2727
type TableVariant,
2828
} from "../primitives/Table";
29+
import { RunsIcon } from "~/assets/icons/RunsIcon";
2930

3031
type LogsTableProps = {
3132
logs: LogEntry[];
@@ -124,6 +125,7 @@ export function LogsTable({
124125
<TableHeaderCell
125126
className="min-w-24 whitespace-nowrap"
126127
tooltip={<LogLevelTooltipInfo />}
128+
disableTooltipHoverableContent
127129
>
128130
Level
129131
</TableHeaderCell>
@@ -165,7 +167,7 @@ export function LogsTable({
165167
>
166168
<DateTimeAccurate date={log.triggeredTimestamp} hour12={false} />
167169
</TableCell>
168-
<TableCell className="min-w-24">
170+
<TableCell className="min-w-24" onClick={handleRowClick} hasAction>
169171
<TruncatedCopyableValue value={log.runId} />
170172
</TableCell>
171173
<TableCell className="min-w-32" onClick={handleRowClick} hasAction>
@@ -185,9 +187,11 @@ export function LogsTable({
185187
<LinkButton
186188
to={runPath}
187189
variant="minimal/small"
188-
TrailingIcon={ArrowTopRightOnSquareIcon}
190+
TrailingIcon={RunsIcon}
191+
trailingIconClassName="text-text-bright"
192+
className="h-[1.375rem] pl-1.5 pr-2"
189193
>
190-
View run
194+
<span className="text-[0.6875rem] text-text-bright">View run</span>
191195
</LinkButton>
192196
}
193197
/>

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

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,17 @@ import {
33
ChartBarIcon,
44
Cog8ToothIcon,
55
CreditCardIcon,
6-
PuzzlePieceIcon,
76
UserGroupIcon,
87
} from "@heroicons/react/20/solid";
98
import { ArrowLeftIcon } from "@heroicons/react/24/solid";
9+
import { SlackIcon } from "@trigger.dev/companyicons";
10+
import { VercelLogo } from "~/components/integrations/VercelLogo";
1011
import { useFeatures } from "~/hooks/useFeatures";
1112
import { type MatchedOrganization } from "~/hooks/useOrganizations";
1213
import { cn } from "~/utils/cn";
1314
import {
1415
organizationSettingsPath,
16+
organizationSlackIntegrationPath,
1517
organizationTeamPath,
1618
organizationVercelIntegrationPath,
1719
rootPath,
@@ -115,13 +117,25 @@ export function OrganizationSettingsSideMenu({
115117
to={organizationSettingsPath(organization)}
116118
data-action="settings"
117119
/>
120+
</div>
121+
<div className="flex flex-col">
122+
<div className="mb-1">
123+
<SideMenuHeader title="Integrations" />
124+
</div>
118125
<SideMenuItem
119-
name="Integrations"
120-
icon={PuzzlePieceIcon}
121-
activeIconColor="text-blue-500"
126+
name="Vercel"
127+
icon={VercelLogo}
128+
activeIconColor="text-white"
122129
to={organizationVercelIntegrationPath(organization)}
123130
data-action="integrations"
124131
/>
132+
<SideMenuItem
133+
name="Slack"
134+
icon={SlackIcon}
135+
activeIconColor="text-white"
136+
to={organizationSlackIntegrationPath(organization)}
137+
data-action="integrations"
138+
/>
125139
</div>
126140
<div className="flex flex-col gap-1">
127141
<SideMenuHeader title="App version" />

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

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
Cog8ToothIcon,
1212
CogIcon,
1313
ExclamationTriangleIcon,
14+
PuzzlePieceIcon,
1415
FolderIcon,
1516
FolderOpenIcon,
1617
GlobeAmericasIcon,
@@ -74,7 +75,8 @@ import {
7475
v3LogsPath,
7576
v3ProjectAlertsPath,
7677
v3ProjectPath,
77-
v3ProjectSettingsPath,
78+
v3ProjectSettingsGeneralPath,
79+
v3ProjectSettingsIntegrationsPath,
7880
v3QueuesPath,
7981
v3RunsPath,
8082
v3SchedulesPath,
@@ -127,7 +129,7 @@ type SideMenuUser = Pick<
127129
};
128130
export type SideMenuProject = Pick<
129131
MatchedProject,
130-
"id" | "name" | "slug" | "version" | "environments" | "engine"
132+
"id" | "name" | "slug" | "version" | "environments" | "engine" | "createdAt"
131133
>;
132134
export type SideMenuEnvironment = MatchedEnvironment;
133135

@@ -589,13 +591,34 @@ export function SideMenu({
589591
data-action="limits"
590592
isCollapsed={isCollapsed}
591593
/>
594+
</SideMenuSection>
595+
596+
<SideMenuSection
597+
title="Project settings"
598+
isSideMenuCollapsed={isCollapsed}
599+
itemSpacingClassName="space-y-0"
600+
initialCollapsed={getSectionCollapsed(
601+
user.dashboardPreferences.sideMenu,
602+
"project-settings"
603+
)}
604+
onCollapseToggle={handleSectionToggle("project-settings")}
605+
>
592606
<SideMenuItem
593-
name="Project settings"
607+
name="General"
594608
icon={Cog8ToothIcon}
595609
activeIconColor="text-text-bright"
596610
inactiveIconColor="text-text-dimmed"
597-
to={v3ProjectSettingsPath(organization, project, environment)}
598-
data-action="project-settings"
611+
to={v3ProjectSettingsGeneralPath(organization, project, environment)}
612+
data-action="project-settings-general"
613+
isCollapsed={isCollapsed}
614+
/>
615+
<SideMenuItem
616+
name="Integrations"
617+
icon={PuzzlePieceIcon}
618+
activeIconColor="text-text-bright"
619+
inactiveIconColor="text-text-dimmed"
620+
to={v3ProjectSettingsIntegrationsPath(organization, project, environment)}
621+
data-action="project-settings-integrations"
599622
isCollapsed={isCollapsed}
600623
/>
601624
</SideMenuSection>
@@ -611,6 +634,7 @@ export function SideMenu({
611634
<V3DeprecationPanel
612635
isCollapsed={isCollapsed}
613636
isV3={isV3Project}
637+
projectCreatedAt={project.createdAt}
614638
hasIncident={incidentStatus.hasIncident}
615639
isManagedCloud={incidentStatus.isManagedCloud}
616640
/>
@@ -641,15 +665,21 @@ export function SideMenu({
641665
function V3DeprecationPanel({
642666
isCollapsed,
643667
isV3,
668+
projectCreatedAt,
644669
hasIncident,
645670
isManagedCloud,
646671
}: {
647672
isCollapsed: boolean;
648673
isV3: boolean;
674+
projectCreatedAt: Date;
649675
hasIncident: boolean;
650676
isManagedCloud: boolean;
651677
}) {
652-
if (!isManagedCloud || !isV3 || hasIncident) {
678+
// Only show for projects created before v4 was released
679+
const V4_RELEASE_DATE = new Date("2025-09-01");
680+
const isLikelyV3 = isV3 && new Date(projectCreatedAt) < V4_RELEASE_DATE;
681+
682+
if (!isManagedCloud || !isLikelyV3 || hasIncident) {
653683
return null;
654684
}
655685

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { z } from "zod";
22

33
// Valid section IDs that can have their collapsed state toggled
4-
export const SideMenuSectionIdSchema = z.enum(["manage", "metrics"]);
4+
export const SideMenuSectionIdSchema = z.enum(["manage", "metrics", "project-settings"]);
55

66
// Inferred type from the schema
77
export type SideMenuSectionId = z.infer<typeof SideMenuSectionIdSchema>;

apps/webapp/app/components/primitives/Table.tsx

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,10 +176,22 @@ type TableCellBasicProps = {
176176
type TableHeaderCellProps = TableCellBasicProps & {
177177
hiddenLabel?: boolean;
178178
tooltip?: ReactNode;
179+
disableTooltipHoverableContent?: boolean;
179180
};
180181

181182
export const TableHeaderCell = forwardRef<HTMLTableCellElement, TableHeaderCellProps>(
182-
({ className, alignment = "left", children, colSpan, hiddenLabel = false, tooltip }, ref) => {
183+
(
184+
{
185+
className,
186+
alignment = "left",
187+
children,
188+
colSpan,
189+
hiddenLabel = false,
190+
tooltip,
191+
disableTooltipHoverableContent = false,
192+
},
193+
ref
194+
) => {
183195
const { variant } = useContext(TableContext);
184196
let alignmentClassName = "text-left";
185197
switch (alignment) {
@@ -222,6 +234,7 @@ export const TableHeaderCell = forwardRef<HTMLTableCellElement, TableHeaderCellP
222234
content={tooltip}
223235
contentClassName="normal-case tracking-normal"
224236
enabled={isHovered}
237+
disableHoverableContent={disableTooltipHoverableContent}
225238
/>
226239
</div>
227240
) : (

0 commit comments

Comments
 (0)