Improved the upgrade callout and API keys page layout
This commit is contained in:
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
+57
-50
@@ -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>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user