Improved the upgrade callout and API keys page layout

This commit is contained in:
James Ritchie
2024-07-01 18:02:40 +01:00
parent 48ea74024b
commit 3124d7a909
2 changed files with 79 additions and 77 deletions
@@ -1,8 +1,8 @@
import { RocketLaunchIcon } from "@heroicons/react/20/solid";
import { Link } from "@remix-run/react";
import { LockOpenIcon } from "@heroicons/react/24/solid";
import { useOrganization } from "~/hooks/useOrganizations";
import { cn } from "~/utils/cn";
import { v3BillingPath } from "~/utils/pathBuilder";
import { LinkButton } from "./Buttons";
import { Header3 } from "./Headers";
import { Paragraph } from "./Paragraph";
type Props = {
@@ -17,31 +17,26 @@ export function UpgradeCallout({ title, children, to }: Props) {
to = to || v3BillingPath(organization);
return (
<Link
to={to}
className={cn(
`flex w-full items-start justify-between gap-2.5 rounded-md border px-3 py-3 shadow-md backdrop-blur-sm`,
"border-indigo-400/20 bg-indigo-800/10 text-indigo-400"
)}
<div
className="flex w-fit flex-col items-start justify-between gap-3 rounded-md border border-indigo-400/20
bg-indigo-800/10 p-4"
>
<div className={"flex w-full items-start gap-x-2"}>
<RocketLaunchIcon className="size-5" />
<div className="flex flex-col gap-2">
<Paragraph variant={"base"} className="text-indigo-200">
{title}
</Paragraph>
{typeof children === "string" ? (
<Paragraph variant={"small"} className="text-indigo-300">
{children}
</Paragraph>
) : (
children
)}
<div className={cn("rounded-sm bg-indigo-500/50 px-3 py-1.5 text-sm text-indigo-200")}>
Upgrade
</div>
</div>
<div className="flex w-full items-center justify-between gap-2">
<LockOpenIcon className="size-6 text-indigo-500" />
<LinkButton to={to} variant="secondary/small">
Upgrade
</LinkButton>
</div>
</Link>
<div className="flex flex-col gap-1">
<Header3 className="text-text-bright">{title}</Header3>
{typeof children === "string" ? (
<Paragraph variant={"small"} className="text-text-dimmed">
{children}
</Paragraph>
) : (
children
)}
</div>
</div>
);
}
@@ -1,4 +1,5 @@
import { BookOpenIcon } from "@heroicons/react/20/solid";
import { InformationCircleIcon } from "@heroicons/react/24/outline";
import { LoaderFunctionArgs } from "@remix-run/server-runtime";
import { typedjson, useTypedLoaderData } from "remix-typedjson";
import { AdminDebugTooltip } from "~/components/admin/debugTooltip";
@@ -23,11 +24,8 @@ import {
} from "~/components/primitives/Table";
import { TextLink } from "~/components/primitives/TextLink";
import { UpgradeCallout } from "~/components/primitives/UpgradeCallout";
import { useFeatures } from "~/hooks/useFeatures";
import { useOrganization } from "~/hooks/useOrganizations";
import { ApiKeysPresenter } from "~/presenters/v3/ApiKeysPresenter.server";
import { requireUserId } from "~/services/session.server";
import { cn } from "~/utils/cn";
import { ProjectParamSchema, docsPath } from "~/utils/pathBuilder";
export const loader = async ({ request, params }: LoaderFunctionArgs) => {
@@ -84,56 +82,65 @@ export default function Page() {
</PageAccessories>
</NavBar>
<PageBody>
<div className={cn("h-full")}>
<Header3 spacing>Secret keys</Header3>
<Paragraph variant="small" spacing>
Secret keys should be used on your server they give full API access and allow you to{" "}
<TextLink to={docsPath("v3/triggering")}>trigger tasks</TextLink> from your backend.
</Paragraph>
<div className="mt-4 flex flex-col gap-6">
<Table>
<TableHeader>
<TableRow>
<TableHeaderCell>Environment</TableHeaderCell>
<TableHeaderCell>Secret key</TableHeaderCell>
<TableHeaderCell>Key generated</TableHeaderCell>
<TableHeaderCell>Latest version</TableHeaderCell>
<TableHeaderCell>Env vars</TableHeaderCell>
<TableHeaderCell hiddenLabel>Actions</TableHeaderCell>
<div className="mt-1 flex flex-col gap-4">
<Table>
<TableHeader>
<TableRow>
<TableHeaderCell>Environment</TableHeaderCell>
<TableHeaderCell>Secret key</TableHeaderCell>
<TableHeaderCell>Key generated</TableHeaderCell>
<TableHeaderCell>Latest version</TableHeaderCell>
<TableHeaderCell>Env vars</TableHeaderCell>
<TableHeaderCell hiddenLabel>Actions</TableHeaderCell>
</TableRow>
</TableHeader>
<TableBody>
{environments.map((environment) => (
<TableRow key={environment.id}>
<TableCell>
<EnvironmentLabel environment={environment} />
</TableCell>
<TableCell>
<ClipboardField
className="w-full max-w-none"
secure={`tr_${environment.apiKey.split("_")[1]}_••••••••`}
value={environment.apiKey}
variant={"tertiary/small"}
/>
</TableCell>
<TableCell>
<DateTime date={environment.updatedAt} />
</TableCell>
<TableCell>{environment.latestVersion ?? ""}</TableCell>
<TableCell>{environment.environmentVariableCount}</TableCell>
<TableCellMenu isSticky>
<RegenerateApiKeyModal
id={environment.id}
title={environmentTitle(environment)}
/>
</TableCellMenu>
</TableRow>
</TableHeader>
<TableBody>
{environments.map((environment) => (
<TableRow key={environment.id}>
<TableCell>
<EnvironmentLabel environment={environment} />
</TableCell>
<TableCell>
<ClipboardField
className="w-full max-w-none"
secure={`tr_${environment.apiKey.split("_")[1]}_••••••••`}
value={environment.apiKey}
variant={"tertiary/small"}
/>
</TableCell>
<TableCell>
<DateTime date={environment.updatedAt} />
</TableCell>
<TableCell>{environment.latestVersion ?? ""}</TableCell>
<TableCell>{environment.environmentVariableCount}</TableCell>
<TableCellMenu isSticky>
<RegenerateApiKeyModal
id={environment.id}
title={environmentTitle(environment)}
/>
</TableCellMenu>
</TableRow>
))}
</TableBody>
</Table>
))}
</TableBody>
</Table>
<div className="flex items-start gap-3">
<div className="flex max-w-sm flex-col items-start justify-between gap-3 rounded-md border border-grid-bright p-4">
<div className="flex w-full items-center justify-between gap-2">
<InformationCircleIcon className="size-6 text-text-dimmed" />
</div>
<div className="flex flex-col gap-1">
<Header3 className="text-text-bright">Secret keys</Header3>
<Paragraph variant={"small"} className="text-text-dimmed">
Secret keys should be used on your server. They give full API access and allow you
to <TextLink to={docsPath("v3/triggering")}>trigger tasks</TextLink> from your
backend.
</Paragraph>
</div>
</div>
{!hasStaging && (
<UpgradeCallout title="Add a Staging environment">
<UpgradeCallout title="Unlock a Staging environment">
Upgrade your plan to add a Staging environment.
</UpgradeCallout>
)}