* Init support of i18n and English and mandarin * Update common.js (#1320) * add General Appearance and Chat setting zh translate (#1414) * add config zh translate (#1461) * patch some translation pages * Update locality fixes * update: complete login page Mandarin translation. (#1709) update: complete Mandarin translation. * complete translation * update github to run validator * bump to test workflow failure * bump to fix tests * update workflow * refactor lang selector support * add Spanish and French * add dictionaries --------- Co-authored-by: GetOffer.help <13744916+getofferhelp@users.noreply.github.com> Co-authored-by: AIR <129256286+KochabStar@users.noreply.github.com> Co-authored-by: Ezio T <ezio5600@gmail.com>
119 lines
4.0 KiB
JavaScript
119 lines
4.0 KiB
JavaScript
import { useEffect, useState } from "react";
|
|
import Sidebar from "@/components/SettingsSidebar";
|
|
import { isMobile } from "react-device-detect";
|
|
import * as Skeleton from "react-loading-skeleton";
|
|
import "react-loading-skeleton/dist/skeleton.css";
|
|
import { PlusCircle } from "@phosphor-icons/react";
|
|
import Admin from "@/models/admin";
|
|
import ApiKeyRow from "./ApiKeyRow";
|
|
import NewApiKeyModal from "./NewApiKeyModal";
|
|
import paths from "@/utils/paths";
|
|
import { userFromStorage } from "@/utils/request";
|
|
import System from "@/models/system";
|
|
import ModalWrapper from "@/components/ModalWrapper";
|
|
import { useModal } from "@/hooks/useModal";
|
|
import CTAButton from "@/components/lib/CTAButton";
|
|
import { useTranslation } from "react-i18next";
|
|
|
|
export default function AdminApiKeys() {
|
|
const { isOpen, openModal, closeModal } = useModal();
|
|
const { t } = useTranslation();
|
|
return (
|
|
<div className="w-screen h-screen overflow-hidden bg-sidebar flex">
|
|
<Sidebar />
|
|
<div
|
|
style={{ height: isMobile ? "100%" : "calc(100% - 32px)" }}
|
|
className="relative md:ml-[2px] md:mr-[16px] md:my-[16px] md:rounded-[16px] bg-main-gradient w-full h-full overflow-y-scroll"
|
|
>
|
|
<div className="flex flex-col w-full px-1 md:pl-6 md:pr-[50px] md:py-6 py-16">
|
|
<div className="w-full flex flex-col gap-y-1 pb-6 border-white border-b-2 border-opacity-10">
|
|
<div className="items-center flex gap-x-4">
|
|
<p className="text-lg leading-6 font-bold text-white">
|
|
{t("api.title")}
|
|
</p>
|
|
</div>
|
|
<p className="text-xs leading-[18px] font-base text-white text-opacity-60">
|
|
{t("api.description")}
|
|
</p>
|
|
<a
|
|
href={paths.apiDocs()}
|
|
target="_blank"
|
|
rel="noreferrer"
|
|
className="text-xs leading-[18px] font-base text-blue-300 hover:underline"
|
|
>
|
|
{t("api.link")} →
|
|
</a>
|
|
</div>
|
|
<div className="w-full justify-end flex">
|
|
<CTAButton onClick={openModal} className="mt-3 mr-0 -mb-14 z-10">
|
|
<PlusCircle className="h-4 w-4" weight="bold" />{" "}
|
|
{t("api.generate")}
|
|
</CTAButton>
|
|
</div>
|
|
<ApiKeysContainer />
|
|
</div>
|
|
<ModalWrapper isOpen={isOpen}>
|
|
<NewApiKeyModal closeModal={closeModal} />
|
|
</ModalWrapper>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function ApiKeysContainer() {
|
|
const [loading, setLoading] = useState(true);
|
|
const [apiKeys, setApiKeys] = useState([]);
|
|
const { t } = useTranslation();
|
|
|
|
useEffect(() => {
|
|
async function fetchExistingKeys() {
|
|
const user = userFromStorage();
|
|
const Model = !!user ? Admin : System;
|
|
const { apiKeys: foundKeys } = await Model.getApiKeys();
|
|
setApiKeys(foundKeys);
|
|
setLoading(false);
|
|
}
|
|
fetchExistingKeys();
|
|
}, []);
|
|
|
|
if (loading) {
|
|
return (
|
|
<Skeleton.default
|
|
height="80vh"
|
|
width="100%"
|
|
highlightColor="#3D4147"
|
|
baseColor="#2C2F35"
|
|
count={1}
|
|
className="w-full p-4 rounded-b-2xl rounded-tr-2xl rounded-tl-sm mt-6"
|
|
containerClassName="flex w-full"
|
|
/>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<table className="w-full text-sm text-left rounded-lg mt-6">
|
|
<thead className="text-white text-opacity-80 text-xs leading-[18px] font-bold uppercase border-white border-b border-opacity-60">
|
|
<tr>
|
|
<th scope="col" className="px-6 py-3 rounded-tl-lg">
|
|
{t("api.table.key")}
|
|
</th>
|
|
<th scope="col" className="px-6 py-3">
|
|
{t("api.table.by")}
|
|
</th>
|
|
<th scope="col" className="px-6 py-3">
|
|
{t("api.table.created")}
|
|
</th>
|
|
<th scope="col" className="px-6 py-3 rounded-tr-lg">
|
|
{" "}
|
|
</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{apiKeys.map((apiKey) => (
|
|
<ApiKeyRow key={apiKey.id} apiKey={apiKey} />
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
);
|
|
}
|