mirror of
https://github.com/fosrl/pangolin.git
synced 2025-08-29 06:08:15 +02:00
Add translation keys in admin/api-keys
This commit is contained in:
parent
d994a8100d
commit
8242a66b97
6 changed files with 67 additions and 56 deletions
|
@ -32,6 +32,7 @@ import { Input } from "@app/components/ui/input";
|
||||||
import { DataTablePagination } from "@app/components/DataTablePagination";
|
import { DataTablePagination } from "@app/components/DataTablePagination";
|
||||||
import { Plus, Search } from "lucide-react";
|
import { Plus, Search } from "lucide-react";
|
||||||
import { DataTable } from "@app/components/ui/data-table";
|
import { DataTable } from "@app/components/ui/data-table";
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
|
||||||
interface DataTableProps<TData, TValue> {
|
interface DataTableProps<TData, TValue> {
|
||||||
columns: ColumnDef<TData, TValue>[];
|
columns: ColumnDef<TData, TValue>[];
|
||||||
|
@ -44,15 +45,17 @@ export function ApiKeysDataTable<TData, TValue>({
|
||||||
columns,
|
columns,
|
||||||
data
|
data
|
||||||
}: DataTableProps<TData, TValue>) {
|
}: DataTableProps<TData, TValue>) {
|
||||||
|
|
||||||
|
const t = useTranslations();
|
||||||
return (
|
return (
|
||||||
<DataTable
|
<DataTable
|
||||||
columns={columns}
|
columns={columns}
|
||||||
data={data}
|
data={data}
|
||||||
title="API Keys"
|
title={t('apiKeys')}
|
||||||
searchPlaceholder="Search API keys..."
|
searchPlaceholder={t('searchApiKeys')}
|
||||||
searchColumn="name"
|
searchColumn="name"
|
||||||
onAdd={addApiKey}
|
onAdd={addApiKey}
|
||||||
addButtonText="Generate API Key"
|
addButtonText={t('apiKeysAdd')}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ import { createApiClient } from "@app/lib/api";
|
||||||
import { useEnvContext } from "@app/hooks/useEnvContext";
|
import { useEnvContext } from "@app/hooks/useEnvContext";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import { ApiKeysDataTable } from "./ApiKeysDataTable";
|
import { ApiKeysDataTable } from "./ApiKeysDataTable";
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
|
||||||
export type ApiKeyRow = {
|
export type ApiKeyRow = {
|
||||||
id: string;
|
id: string;
|
||||||
|
@ -45,14 +46,16 @@ export default function ApiKeysTable({ apiKeys }: ApiKeyTableProps) {
|
||||||
|
|
||||||
const api = createApiClient(useEnvContext());
|
const api = createApiClient(useEnvContext());
|
||||||
|
|
||||||
|
const t = useTranslations();
|
||||||
|
|
||||||
const deleteSite = (apiKeyId: string) => {
|
const deleteSite = (apiKeyId: string) => {
|
||||||
api.delete(`/api-key/${apiKeyId}`)
|
api.delete(`/api-key/${apiKeyId}`)
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
console.error("Error deleting API key", e);
|
console.error(t('apiKeysErrorDelete'), e);
|
||||||
toast({
|
toast({
|
||||||
variant: "destructive",
|
variant: "destructive",
|
||||||
title: "Error deleting API key",
|
title: t('apiKeysErrorDelete'),
|
||||||
description: formatAxiosError(e, "Error deleting API key")
|
description: formatAxiosError(e, t('apiKeysErrorDeleteMessage'))
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
@ -86,7 +89,7 @@ export default function ApiKeysTable({ apiKeys }: ApiKeyTableProps) {
|
||||||
setSelected(apiKeyROw);
|
setSelected(apiKeyROw);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span>View settings</span>
|
<span>{t('viewSettings')}</span>
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
<DropdownMenuItem
|
<DropdownMenuItem
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
@ -94,7 +97,7 @@ export default function ApiKeysTable({ apiKeys }: ApiKeyTableProps) {
|
||||||
setIsDeleteModalOpen(true);
|
setIsDeleteModalOpen(true);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span className="text-red-500">Delete</span>
|
<span className="text-red-500">{t('delete')}</span>
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
|
@ -111,7 +114,7 @@ export default function ApiKeysTable({ apiKeys }: ApiKeyTableProps) {
|
||||||
column.toggleSorting(column.getIsSorted() === "asc")
|
column.toggleSorting(column.getIsSorted() === "asc")
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
Name
|
{t('name')}
|
||||||
<ArrowUpDown className="ml-2 h-4 w-4" />
|
<ArrowUpDown className="ml-2 h-4 w-4" />
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
|
@ -141,7 +144,7 @@ export default function ApiKeysTable({ apiKeys }: ApiKeyTableProps) {
|
||||||
<div className="flex items-center justify-end">
|
<div className="flex items-center justify-end">
|
||||||
<Link href={`/admin/api-keys/${r.id}`}>
|
<Link href={`/admin/api-keys/${r.id}`}>
|
||||||
<Button variant={"outlinePrimary"} className="ml-2">
|
<Button variant={"outlinePrimary"} className="ml-2">
|
||||||
Edit
|
{t('edit')}
|
||||||
<ArrowRight className="ml-2 w-4 h-4" />
|
<ArrowRight className="ml-2 w-4 h-4" />
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
|
@ -163,27 +166,24 @@ export default function ApiKeysTable({ apiKeys }: ApiKeyTableProps) {
|
||||||
dialog={
|
dialog={
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<p>
|
<p>
|
||||||
Are you sure you want to remove the API key{" "}
|
{t('apiKeysQuestionRemove', {selectedApiKey: selected?.name || selected?.id})}
|
||||||
<b>{selected?.name || selected?.id}</b>?
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<b>
|
<b>
|
||||||
Once removed, the API key will no longer be
|
{t('apiKeysMessageRemove')}
|
||||||
able to be used.
|
|
||||||
</b>
|
</b>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
To confirm, please type the name of the API key
|
{t('apiKeysMessageConfirm')}
|
||||||
below.
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
buttonText="Confirm Delete API Key"
|
buttonText={t('apiKeysDeleteConfirm')}
|
||||||
onConfirm={async () => deleteSite(selected!.id)}
|
onConfirm={async () => deleteSite(selected!.id)}
|
||||||
string={selected.name}
|
string={selected.name}
|
||||||
title="Delete API Key"
|
title={t('apiKeysDelete')}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ import {
|
||||||
import { GetApiKeyResponse } from "@server/routers/apiKeys";
|
import { GetApiKeyResponse } from "@server/routers/apiKeys";
|
||||||
import ApiKeyProvider from "@app/providers/ApiKeyProvider";
|
import ApiKeyProvider from "@app/providers/ApiKeyProvider";
|
||||||
import { HorizontalTabs } from "@app/components/HorizontalTabs";
|
import { HorizontalTabs } from "@app/components/HorizontalTabs";
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
|
||||||
interface SettingsLayoutProps {
|
interface SettingsLayoutProps {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
|
@ -29,6 +30,8 @@ interface SettingsLayoutProps {
|
||||||
export default async function SettingsLayout(props: SettingsLayoutProps) {
|
export default async function SettingsLayout(props: SettingsLayoutProps) {
|
||||||
const params = await props.params;
|
const params = await props.params;
|
||||||
|
|
||||||
|
const t = useTranslations();
|
||||||
|
|
||||||
const { children } = props;
|
const { children } = props;
|
||||||
|
|
||||||
let apiKey = null;
|
let apiKey = null;
|
||||||
|
@ -45,14 +48,14 @@ export default async function SettingsLayout(props: SettingsLayoutProps) {
|
||||||
|
|
||||||
const navItems = [
|
const navItems = [
|
||||||
{
|
{
|
||||||
title: "Permissions",
|
title: t('apiKeysPermissionsTitle'),
|
||||||
href: "/admin/api-keys/{apiKeyId}/permissions"
|
href: "/admin/api-keys/{apiKeyId}/permissions"
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<SettingsSectionTitle title={`${apiKey?.name} Settings`} />
|
<SettingsSectionTitle title={t('apiKeysSettings', {apiKeyName: apiKey?.name})} />
|
||||||
|
|
||||||
<ApiKeyProvider apiKey={apiKey}>
|
<ApiKeyProvider apiKey={apiKey}>
|
||||||
<HorizontalTabs items={navItems}>{children}</HorizontalTabs>
|
<HorizontalTabs items={navItems}>{children}</HorizontalTabs>
|
||||||
|
|
|
@ -23,12 +23,15 @@ import { ListApiKeyActionsResponse } from "@server/routers/apiKeys";
|
||||||
import { AxiosResponse } from "axios";
|
import { AxiosResponse } from "axios";
|
||||||
import { useParams } from "next/navigation";
|
import { useParams } from "next/navigation";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
|
||||||
export default function Page() {
|
export default function Page() {
|
||||||
const { env } = useEnvContext();
|
const { env } = useEnvContext();
|
||||||
const api = createApiClient({ env });
|
const api = createApiClient({ env });
|
||||||
const { apiKeyId } = useParams();
|
const { apiKeyId } = useParams();
|
||||||
|
|
||||||
|
const t = useTranslations();
|
||||||
|
|
||||||
const [loadingPage, setLoadingPage] = useState<boolean>(true);
|
const [loadingPage, setLoadingPage] = useState<boolean>(true);
|
||||||
const [selectedPermissions, setSelectedPermissions] = useState<
|
const [selectedPermissions, setSelectedPermissions] = useState<
|
||||||
Record<string, boolean>
|
Record<string, boolean>
|
||||||
|
@ -47,10 +50,10 @@ export default function Page() {
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
toast({
|
toast({
|
||||||
variant: "destructive",
|
variant: "destructive",
|
||||||
title: "Error loading API key actions",
|
title: t('apiKeysPermissionsErrorLoadingActions'),
|
||||||
description: formatAxiosError(
|
description: formatAxiosError(
|
||||||
e,
|
e,
|
||||||
"Error loading API key actions"
|
t('apiKeysPermissionsErrorLoadingActions')
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -81,18 +84,18 @@ export default function Page() {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
console.error("Error setting permissions", e);
|
console.error(t('apiKeysPermissionsErrorUpdate'), e);
|
||||||
toast({
|
toast({
|
||||||
variant: "destructive",
|
variant: "destructive",
|
||||||
title: "Error setting permissions",
|
title: t('apiKeysPermissionsErrorUpdate'),
|
||||||
description: formatAxiosError(e)
|
description: formatAxiosError(e)
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
if (actionsRes && actionsRes.status === 200) {
|
if (actionsRes && actionsRes.status === 200) {
|
||||||
toast({
|
toast({
|
||||||
title: "Permissions updated",
|
title: t('apiKeysPermissionsUpdated'),
|
||||||
description: "The permissions have been updated."
|
description: t('apiKeysPermissionsUpdatedDescription')
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,10 +109,10 @@ export default function Page() {
|
||||||
<SettingsSection>
|
<SettingsSection>
|
||||||
<SettingsSectionHeader>
|
<SettingsSectionHeader>
|
||||||
<SettingsSectionTitle>
|
<SettingsSectionTitle>
|
||||||
Permissions
|
{t('apiKeysPermissionsTitle')}
|
||||||
</SettingsSectionTitle>
|
</SettingsSectionTitle>
|
||||||
<SettingsSectionDescription>
|
<SettingsSectionDescription>
|
||||||
Determine what this API key can do
|
{t('apiKeysPermissionsGeneralSettingsDescription')}
|
||||||
</SettingsSectionDescription>
|
</SettingsSectionDescription>
|
||||||
</SettingsSectionHeader>
|
</SettingsSectionHeader>
|
||||||
<SettingsSectionBody>
|
<SettingsSectionBody>
|
||||||
|
@ -127,7 +130,7 @@ export default function Page() {
|
||||||
loading={loadingSavePermissions}
|
loading={loadingSavePermissions}
|
||||||
disabled={loadingSavePermissions}
|
disabled={loadingSavePermissions}
|
||||||
>
|
>
|
||||||
Save Permissions
|
{t('apiKeysPermissionsSave')}
|
||||||
</Button>
|
</Button>
|
||||||
</SettingsSectionFooter>
|
</SettingsSectionFooter>
|
||||||
</SettingsSectionBody>
|
</SettingsSectionBody>
|
||||||
|
|
|
@ -59,15 +59,18 @@ import CopyToClipboard from "@app/components/CopyToClipboard";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import CopyTextBox from "@app/components/CopyTextBox";
|
import CopyTextBox from "@app/components/CopyTextBox";
|
||||||
import PermissionsSelectBox from "@app/components/PermissionsSelectBox";
|
import PermissionsSelectBox from "@app/components/PermissionsSelectBox";
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
|
||||||
|
const t = useTranslations();
|
||||||
|
|
||||||
const createFormSchema = z.object({
|
const createFormSchema = z.object({
|
||||||
name: z
|
name: z
|
||||||
.string()
|
.string()
|
||||||
.min(2, {
|
.min(2, {
|
||||||
message: "Name must be at least 2 characters."
|
message: t('apiKeysNameMin')
|
||||||
})
|
})
|
||||||
.max(255, {
|
.max(255, {
|
||||||
message: "Name must not be longer than 255 characters."
|
message: t('apiKeysNameMax')
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -82,7 +85,7 @@ const copiedFormSchema = z
|
||||||
return data.copied;
|
return data.copied;
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
message: "You must confirm that you have copied the API key.",
|
message: t('apiKeysConfirmCopy2'),
|
||||||
path: ["copied"]
|
path: ["copied"]
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -127,7 +130,7 @@ export default function Page() {
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
toast({
|
toast({
|
||||||
variant: "destructive",
|
variant: "destructive",
|
||||||
title: "Error creating API key",
|
title: t('apiKeysErrorCreate'),
|
||||||
description: formatAxiosError(e)
|
description: formatAxiosError(e)
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -148,10 +151,10 @@ export default function Page() {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
console.error("Error setting permissions", e);
|
console.error(t('apiKeysErrorSetPermission'), e);
|
||||||
toast({
|
toast({
|
||||||
variant: "destructive",
|
variant: "destructive",
|
||||||
title: "Error setting permissions",
|
title: t('apiKeysErrorSetPermission'),
|
||||||
description: formatAxiosError(e)
|
description: formatAxiosError(e)
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -184,8 +187,8 @@ export default function Page() {
|
||||||
<>
|
<>
|
||||||
<div className="flex justify-between">
|
<div className="flex justify-between">
|
||||||
<HeaderTitle
|
<HeaderTitle
|
||||||
title="Generate API Key"
|
title={t('apiKeysCreate')}
|
||||||
description="Generate a new root access API key"
|
description={t('apiKeysCreateDescription')}
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
|
@ -205,7 +208,7 @@ export default function Page() {
|
||||||
<SettingsSection>
|
<SettingsSection>
|
||||||
<SettingsSectionHeader>
|
<SettingsSectionHeader>
|
||||||
<SettingsSectionTitle>
|
<SettingsSectionTitle>
|
||||||
API Key Information
|
{t('apiKeysTitle')}
|
||||||
</SettingsSectionTitle>
|
</SettingsSectionTitle>
|
||||||
</SettingsSectionHeader>
|
</SettingsSectionHeader>
|
||||||
<SettingsSectionBody>
|
<SettingsSectionBody>
|
||||||
|
@ -221,7 +224,7 @@ export default function Page() {
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>
|
<FormLabel>
|
||||||
Name
|
{t('name')}
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
|
@ -242,10 +245,10 @@ export default function Page() {
|
||||||
<SettingsSection>
|
<SettingsSection>
|
||||||
<SettingsSectionHeader>
|
<SettingsSectionHeader>
|
||||||
<SettingsSectionTitle>
|
<SettingsSectionTitle>
|
||||||
Permissions
|
{t('apiKeysGeneralSettings')}
|
||||||
</SettingsSectionTitle>
|
</SettingsSectionTitle>
|
||||||
<SettingsSectionDescription>
|
<SettingsSectionDescription>
|
||||||
Determine what this API key can do
|
{t('apiKeysGeneralSettingsDescription')}
|
||||||
</SettingsSectionDescription>
|
</SettingsSectionDescription>
|
||||||
</SettingsSectionHeader>
|
</SettingsSectionHeader>
|
||||||
<SettingsSectionBody>
|
<SettingsSectionBody>
|
||||||
|
@ -265,14 +268,14 @@ export default function Page() {
|
||||||
<SettingsSection>
|
<SettingsSection>
|
||||||
<SettingsSectionHeader>
|
<SettingsSectionHeader>
|
||||||
<SettingsSectionTitle>
|
<SettingsSectionTitle>
|
||||||
Your API Key
|
{t('apiKeysList')}
|
||||||
</SettingsSectionTitle>
|
</SettingsSectionTitle>
|
||||||
</SettingsSectionHeader>
|
</SettingsSectionHeader>
|
||||||
<SettingsSectionBody>
|
<SettingsSectionBody>
|
||||||
<InfoSections cols={2}>
|
<InfoSections cols={2}>
|
||||||
<InfoSection>
|
<InfoSection>
|
||||||
<InfoSectionTitle>
|
<InfoSectionTitle>
|
||||||
Name
|
{t('name')}
|
||||||
</InfoSectionTitle>
|
</InfoSectionTitle>
|
||||||
<InfoSectionContent>
|
<InfoSectionContent>
|
||||||
<CopyToClipboard
|
<CopyToClipboard
|
||||||
|
@ -282,7 +285,7 @@ export default function Page() {
|
||||||
</InfoSection>
|
</InfoSection>
|
||||||
<InfoSection>
|
<InfoSection>
|
||||||
<InfoSectionTitle>
|
<InfoSectionTitle>
|
||||||
Created
|
{t('created')}
|
||||||
</InfoSectionTitle>
|
</InfoSectionTitle>
|
||||||
<InfoSectionContent>
|
<InfoSectionContent>
|
||||||
{moment(
|
{moment(
|
||||||
|
@ -295,17 +298,15 @@ export default function Page() {
|
||||||
<Alert variant="neutral">
|
<Alert variant="neutral">
|
||||||
<InfoIcon className="h-4 w-4" />
|
<InfoIcon className="h-4 w-4" />
|
||||||
<AlertTitle className="font-semibold">
|
<AlertTitle className="font-semibold">
|
||||||
Save Your API Key
|
{t('apiKeysSave')}
|
||||||
</AlertTitle>
|
</AlertTitle>
|
||||||
<AlertDescription>
|
<AlertDescription>
|
||||||
You will only be able to see this
|
{t('apiKeysSaveDescription')}
|
||||||
once. Make sure to copy it to a
|
|
||||||
secure place.
|
|
||||||
</AlertDescription>
|
</AlertDescription>
|
||||||
</Alert>
|
</Alert>
|
||||||
|
|
||||||
<h4 className="font-semibold">
|
<h4 className="font-semibold">
|
||||||
Your API key is:
|
{t('apiKeysInfo')}
|
||||||
</h4>
|
</h4>
|
||||||
|
|
||||||
<CopyTextBox
|
<CopyTextBox
|
||||||
|
@ -343,8 +344,7 @@ export default function Page() {
|
||||||
htmlFor="terms"
|
htmlFor="terms"
|
||||||
className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
|
className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
|
||||||
>
|
>
|
||||||
I have copied
|
{t('apiKeysConfirmCopy')}
|
||||||
the API key
|
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
|
@ -368,7 +368,7 @@ export default function Page() {
|
||||||
router.push(`/admin/api-keys`);
|
router.push(`/admin/api-keys`);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Cancel
|
{t('cancel')}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
{!apiKey && (
|
{!apiKey && (
|
||||||
|
@ -380,7 +380,7 @@ export default function Page() {
|
||||||
form.handleSubmit(onSubmit)();
|
form.handleSubmit(onSubmit)();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Generate
|
{t('generate')}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
@ -391,7 +391,7 @@ export default function Page() {
|
||||||
copiedForm.handleSubmit(onCopiedSubmit)();
|
copiedForm.handleSubmit(onCopiedSubmit)();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Done
|
{t('done')}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -9,6 +9,7 @@ import { AxiosResponse } from "axios";
|
||||||
import SettingsSectionTitle from "@app/components/SettingsSectionTitle";
|
import SettingsSectionTitle from "@app/components/SettingsSectionTitle";
|
||||||
import { ListRootApiKeysResponse } from "@server/routers/apiKeys";
|
import { ListRootApiKeysResponse } from "@server/routers/apiKeys";
|
||||||
import ApiKeysTable, { ApiKeyRow } from "./ApiKeysTable";
|
import ApiKeysTable, { ApiKeyRow } from "./ApiKeysTable";
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
|
||||||
type ApiKeyPageProps = {};
|
type ApiKeyPageProps = {};
|
||||||
|
|
||||||
|
@ -16,6 +17,7 @@ export const dynamic = "force-dynamic";
|
||||||
|
|
||||||
export default async function ApiKeysPage(props: ApiKeyPageProps) {
|
export default async function ApiKeysPage(props: ApiKeyPageProps) {
|
||||||
let apiKeys: ListRootApiKeysResponse["apiKeys"] = [];
|
let apiKeys: ListRootApiKeysResponse["apiKeys"] = [];
|
||||||
|
const t = useTranslations();
|
||||||
try {
|
try {
|
||||||
const res = await internal.get<AxiosResponse<ListRootApiKeysResponse>>(
|
const res = await internal.get<AxiosResponse<ListRootApiKeysResponse>>(
|
||||||
`/api-keys`,
|
`/api-keys`,
|
||||||
|
@ -36,8 +38,8 @@ export default async function ApiKeysPage(props: ApiKeyPageProps) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<SettingsSectionTitle
|
<SettingsSectionTitle
|
||||||
title="Manage API Keys"
|
title={t('apiKeysManage')}
|
||||||
description="API keys are used to authenticate with the integration API"
|
description={t('apiKeysDescription')}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<ApiKeysTable apiKeys={rows} />
|
<ApiKeysTable apiKeys={rows} />
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue