249 lines
9.0 KiB
TypeScript
249 lines
9.0 KiB
TypeScript
import { ArrowLeftIcon, LinkIcon } from "@heroicons/react/24/solid";
|
|
import { BellIcon } from "~/assets/icons/BellIcon";
|
|
import { CreditCardIcon } from "~/assets/icons/CreditCardIcon";
|
|
import { PadlockIcon } from "~/assets/icons/PadlockIcon";
|
|
import { UsageIcon } from "~/assets/icons/UsageIcon";
|
|
import { RolesIcon } from "~/assets/icons/RolesIcon";
|
|
import { SlackIcon } from "~/assets/icons/SlackIcon";
|
|
import { SlidersIcon } from "~/assets/icons/SlidersIcon";
|
|
import { UserGroupIcon } from "~/assets/icons/UserGroupIcon";
|
|
import { VercelLogo } from "~/components/integrations/VercelLogo";
|
|
import { useFeatureFlags } from "~/hooks/useFeatureFlags";
|
|
import { useFeatures } from "~/hooks/useFeatures";
|
|
import { type MatchedOrganization } from "~/hooks/useOrganizations";
|
|
import { cn } from "~/utils/cn";
|
|
import {
|
|
organizationRolesPath,
|
|
organizationSettingsPath,
|
|
organizationSlackIntegrationPath,
|
|
organizationSsoPath,
|
|
organizationTeamPath,
|
|
organizationVercelIntegrationPath,
|
|
rootPath,
|
|
v3BillingLimitsPath,
|
|
v3BillingPath,
|
|
v3PrivateConnectionsPath,
|
|
v3UsagePath,
|
|
} from "~/utils/pathBuilder";
|
|
import { LinkButton } from "../primitives/Buttons";
|
|
import { HelpAndFeedback } from "./HelpAndFeedbackPopover";
|
|
import { SideMenuHeader } from "./SideMenuHeader";
|
|
import { SideMenuItem } from "./SideMenuItem";
|
|
import { useShowSelfServe } from "~/hooks/useShowSelfServe";
|
|
import { useCurrentPlan } from "~/routes/_app.orgs.$organizationSlug/route";
|
|
import { Paragraph } from "../primitives/Paragraph";
|
|
import { Badge } from "../primitives/Badge";
|
|
import { useHasAdminAccess } from "~/hooks/useUser";
|
|
import { AskAI } from "../AskAI";
|
|
|
|
export type BuildInfo = {
|
|
appVersion: string | undefined;
|
|
packageVersion: string;
|
|
buildTimestampSeconds: string | undefined;
|
|
gitSha: string | undefined;
|
|
gitRefName: string | undefined;
|
|
};
|
|
|
|
export function OrganizationSettingsSideMenu({
|
|
organization,
|
|
buildInfo,
|
|
isUsingPlugin,
|
|
isSsoUsingPlugin,
|
|
}: {
|
|
organization: MatchedOrganization;
|
|
buildInfo: BuildInfo;
|
|
isUsingPlugin: boolean;
|
|
isSsoUsingPlugin: boolean;
|
|
}) {
|
|
const { isManagedCloud } = useFeatures();
|
|
const featureFlags = useFeatureFlags();
|
|
const currentPlan = useCurrentPlan();
|
|
const showSelfServe = useShowSelfServe();
|
|
const isAdmin = useHasAdminAccess();
|
|
const showBuildInfo = isAdmin || !isManagedCloud;
|
|
|
|
return (
|
|
<div
|
|
className={cn(
|
|
"grid h-full grid-rows-[2.5rem_auto_2.5rem] overflow-hidden border-r border-grid-bright bg-background-bright transition"
|
|
)}
|
|
>
|
|
<div className={cn("flex items-center justify-between p-1 transition")}>
|
|
<LinkButton
|
|
variant="minimal/medium"
|
|
LeadingIcon={ArrowLeftIcon}
|
|
to={rootPath()}
|
|
fullWidth
|
|
textAlignLeft
|
|
>
|
|
<span className="text-text-bright">Back to app</span>
|
|
</LinkButton>
|
|
</div>
|
|
<div className="mb-6 flex grow flex-col gap-4 overflow-y-auto px-1 pt-2 scrollbar-thin scrollbar-track-transparent scrollbar-thumb-surface-control">
|
|
<div className="flex flex-col">
|
|
<div className="mb-1">
|
|
<SideMenuHeader title="Organization" />
|
|
</div>
|
|
{isManagedCloud && (
|
|
<>
|
|
<SideMenuItem
|
|
name="Usage"
|
|
icon={UsageIcon}
|
|
activeIconColor="text-text-bright"
|
|
inactiveIconColor="text-text-dimmed"
|
|
to={v3UsagePath(organization)}
|
|
data-action="usage"
|
|
/>
|
|
<SideMenuItem
|
|
name="Billing"
|
|
icon={CreditCardIcon}
|
|
activeIconColor="text-text-bright"
|
|
inactiveIconColor="text-text-dimmed"
|
|
to={v3BillingPath(organization)}
|
|
data-action="billing"
|
|
badge={
|
|
currentPlan?.v3Subscription?.isPaying ? (
|
|
<Badge variant="extra-small">{currentPlan?.v3Subscription?.plan?.title}</Badge>
|
|
) : undefined
|
|
}
|
|
/>
|
|
{showSelfServe ? (
|
|
<SideMenuItem
|
|
name="Billing limits"
|
|
icon={BellIcon}
|
|
activeIconColor="text-text-bright"
|
|
inactiveIconColor="text-text-dimmed"
|
|
to={v3BillingLimitsPath(organization)}
|
|
data-action="billing-limits"
|
|
/>
|
|
) : null}
|
|
</>
|
|
)}
|
|
<SideMenuItem
|
|
name="Team"
|
|
icon={UserGroupIcon}
|
|
activeIconColor="text-text-bright"
|
|
inactiveIconColor="text-text-dimmed"
|
|
to={organizationTeamPath(organization)}
|
|
data-action="team"
|
|
/>
|
|
{featureFlags.hasPrivateConnections && (
|
|
<SideMenuItem
|
|
name="Private Connections"
|
|
icon={LinkIcon}
|
|
activeIconColor="text-text-bright"
|
|
inactiveIconColor="text-text-dimmed"
|
|
to={v3PrivateConnectionsPath(organization)}
|
|
data-action="private-connections"
|
|
/>
|
|
)}
|
|
{isUsingPlugin && (
|
|
<SideMenuItem
|
|
name="Roles"
|
|
icon={RolesIcon}
|
|
activeIconColor="text-text-bright"
|
|
inactiveIconColor="text-text-dimmed"
|
|
to={organizationRolesPath(organization)}
|
|
data-action="roles"
|
|
/>
|
|
)}
|
|
{isSsoUsingPlugin && (
|
|
<SideMenuItem
|
|
name="SSO & Directory Sync"
|
|
icon={PadlockIcon}
|
|
activeIconColor="text-text-bright"
|
|
inactiveIconColor="text-text-dimmed"
|
|
to={organizationSsoPath(organization)}
|
|
data-action="sso"
|
|
badge={
|
|
currentPlan?.v3Subscription?.plan?.code === "enterprise" ? undefined : (
|
|
<Badge variant="extra-small">Enterprise</Badge>
|
|
)
|
|
}
|
|
/>
|
|
)}
|
|
<SideMenuItem
|
|
name="Settings"
|
|
icon={SlidersIcon}
|
|
activeIconColor="text-text-bright"
|
|
inactiveIconColor="text-text-dimmed"
|
|
to={organizationSettingsPath(organization)}
|
|
data-action="settings"
|
|
/>
|
|
</div>
|
|
<div className="flex flex-col">
|
|
<div className="mb-1">
|
|
<SideMenuHeader title="Integrations" />
|
|
</div>
|
|
<SideMenuItem
|
|
name="Vercel"
|
|
icon={VercelLogo}
|
|
activeIconColor="text-text-bright"
|
|
inactiveIconColor="text-text-dimmed"
|
|
iconClassName="size-4 ml-[0.15rem]"
|
|
to={organizationVercelIntegrationPath(organization)}
|
|
data-action="integrations"
|
|
/>
|
|
<SideMenuItem
|
|
name="Slack"
|
|
icon={SlackIcon}
|
|
activeIconColor="text-text-bright"
|
|
inactiveIconColor="text-text-dimmed"
|
|
iconClassName="size-4 ml-0.5"
|
|
to={organizationSlackIntegrationPath(organization)}
|
|
data-action="integrations"
|
|
/>
|
|
</div>
|
|
<div className="flex flex-col gap-1">
|
|
<SideMenuHeader title="App version" />
|
|
<Paragraph variant="extra-small" className="px-2 text-text-dimmed">
|
|
{buildInfo.appVersion || `v${buildInfo.packageVersion}`}
|
|
</Paragraph>
|
|
</div>
|
|
{showBuildInfo && buildInfo.buildTimestampSeconds && (
|
|
<div className="flex flex-col gap-1">
|
|
<SideMenuHeader title="Build timestamp" />
|
|
<Paragraph variant="extra-small" className="px-2 text-text-dimmed">
|
|
{new Date(Number(buildInfo.buildTimestampSeconds) * 1000).toISOString()}
|
|
</Paragraph>
|
|
</div>
|
|
)}
|
|
{showBuildInfo && buildInfo.gitRefName && (
|
|
<div className="flex flex-col gap-1">
|
|
<SideMenuHeader title="Git ref" />
|
|
<Paragraph variant="extra-small" className="px-2 text-text-dimmed">
|
|
<a
|
|
href={`https://github.com/triggerdotdev/trigger.dev/tree/${buildInfo.gitRefName}`}
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
className="transition hover:text-text-bright"
|
|
>
|
|
{buildInfo.gitRefName}
|
|
</a>
|
|
</Paragraph>
|
|
</div>
|
|
)}
|
|
{showBuildInfo && buildInfo.gitSha && (
|
|
<div className="flex flex-col gap-1">
|
|
<SideMenuHeader title="Git sha" />
|
|
<Paragraph variant="extra-small" className="px-2 text-text-dimmed">
|
|
<a
|
|
href={`https://github.com/triggerdotdev/trigger.dev/commit/${buildInfo.gitSha}`}
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
className="transition hover:text-text-bright"
|
|
>
|
|
{buildInfo.gitSha.slice(0, 9)}
|
|
</a>
|
|
</Paragraph>
|
|
</div>
|
|
)}
|
|
</div>
|
|
<div className="flex w-full items-center justify-between border-t border-grid-bright p-1">
|
|
<HelpAndFeedback organizationId={organization.id} />
|
|
<AskAI />
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|