feat: bot setting

This commit is contained in:
Tristan Yang
2022-12-21 08:05:14 +08:00
parent e984031535
commit 7546af66a5
10 changed files with 56 additions and 36 deletions
+16 -9
View File
@@ -4,8 +4,10 @@ import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useGetBotAPIKeysQuery } from '../../../app/services/user';
import IconDelete from '../../../assets/icons/delete.svg';
import IconAdd from '../../../assets/icons/add.svg';
import CreateAPIKeyModal from './CreateAPIKeyModal';
import DeleteAPIKeyModal from './DeleteAPIKeyModal';
import clsx from 'clsx';
type Props = {
uid: number
@@ -34,22 +36,20 @@ const BotAPIKeys = ({ uid }: Props) => {
setDeleteApiKey(param);
};
if (!data) return null;
const colWidths = ["w-20", "w-[166px]", "w-36", "w-15", "w-10"];
return (
<div className='flex flex-col gap-2 items-start'>
<button onClick={toggleCreateModal.bind(null, uid)} type='button' className="rounded-full bg-green-50 text-green-600 text-xs py-0.5 px-2">
New API Key
</button>
{data.length > 0 ? <div className='border-t border-solid border-b border-gray-200 py-2'>
<div className='border-t border-solid border-b border-gray-100 py-2 w-full'>
<table className="min-w-full table-auto font-mono">
<thead >
<tr >
{[t("col_key_name"), t('col_key_value'), t('col_key_create_time'), t('col_key_last_used'), ""].map(title => <th key={title} scope="col" className="text-xs text-gray-900 px-1 text-left pb-2">
{[t("col_key_name"), t('col_key_value'), t('col_key_create_time'), t('col_key_last_used'), ""].map((title, idx) => <th key={title} scope="col" className={clsx(`text-xs text-gray-900 px-1 text-left pb-2`, colWidths[idx])}>
{title}
</th>)}
</tr>
</thead>
<tbody>
{data.map(ak => {
{data.length > 0 ? data.map(ak => {
const { id, name, key, created_at, last_used } = ak;
return <tr key={id} className="group" >
<td className={tdClass}>
@@ -62,7 +62,6 @@ const BotAPIKeys = ({ uid }: Props) => {
{dayjs(created_at).format("YYYY-MM-DD HH:mm:ss")}
</td>
<td className={tdClass}>
{last_used ? dayjs(last_used).format("YYYY-MM-DD HH:mm:ss") : "Unused"}
</td>
<td className={`${tdClass} invisible group-hover:visible`}>
@@ -71,9 +70,17 @@ const BotAPIKeys = ({ uid }: Props) => {
</button>
</td>
</tr>;
})}
}) : <tr>
<td colSpan={5} className='w-full text-center text-xs text-gray-400 pt-4'>
No API Key Yet
</td>
</tr>}
</tbody>
</table></div> : null}
</table>
<button onClick={toggleCreateModal.bind(null, uid)} className="text-green-600 text-xs py-0.5 flex items-center gap-1 m-auto my-2 bg-green-50 rounded-full px-2 ">
<IconAdd className="!w-4 !h-4 fill-green-600" /> Add API Key
</button>
</div>
{currentUid && <CreateAPIKeyModal uid={currentUid} closeModal={toggleCreateModal.bind(null, undefined)} />}
{deleteApiKey && <DeleteAPIKeyModal uid={deleteApiKey.uid} kid={deleteApiKey.kid} closeModal={toggleDeleteModal.bind(null, undefined)} />}
</div>
@@ -14,7 +14,7 @@ type Props = {
}
const CreateAPIKeyModal = ({ closeModal, uid }: Props) => {
const { copy } = useCopy();
const [createBotAPIKey, { error, isSuccess, isLoading, data }] = useCreateBotAPIKeyMutation();
const [createBotAPIKey, { error, isSuccess, isLoading, data = "" }] = useCreateBotAPIKeyMutation();
const formRef = useRef(null);
const { t } = useTranslation("setting", { keyPrefix: "bot" });
const { t: ct } = useTranslation();
@@ -25,7 +25,6 @@ const CreateAPIKeyModal = ({ closeModal, uid }: Props) => {
if (!formEle.checkValidity()) {
formEle.reportValidity();
return;
}
createBotAPIKey({
uid,
+2 -2
View File
@@ -73,7 +73,7 @@ const CreateModal = ({ closeModal }: Props) => {
<Button className="cancel" onClick={closeModal}>
{ct("action.cancel")}
</Button>
<Button onClick={handleCreateBot}>{isLoading ? "Updating" : ct("action.done")}</Button>
<Button onClick={handleCreateBot}>{isLoading ? "Creating" : ct("action.done")}</Button>
</>
}
>
@@ -83,7 +83,7 @@ const CreateModal = ({ closeModal }: Props) => {
<Input name={"name"} required placeholder='Please input bot name'></Input>
</div>
<div className="flex flex-col gap-1 w-full">
<label htmlFor={"webhook_url"} className="text-sm text-[#6b7280]">Webhook URL</label>
<label htmlFor={"webhook_url"} className="text-sm text-[#6b7280]">Webhook URL (Optional)</label>
<Input name={"webhook_url"} type="url" placeholder='Please input webhook url'></Input>
</div>
</form>
+12 -4
View File
@@ -58,22 +58,30 @@ const WebhookEdit = ({ uid }: Props) => {
};
const handleCancelEdit = () => {
setEditable(false);
const form = formRef.current;
if (form) {
const input = form.querySelector("input");
input!.value = data?.webhook_url || "";
}
};
return (
<div>
{(url || editable || updateSuccess) ?
<div className="flex gap-2">
<form action="/" ref={formRef} >
<form action="/" ref={formRef} onSubmit={(evt) => {
evt.preventDefault();
handleEdit();
}}>
<input readOnly={!editable} required autoFocus type="url" name='webhook' defaultValue={url} className={clsx("text-sm text-gray-500 px-2 py-1", editable ? "border border-solid border-gray-200 bg-gray-50" : "bg-transparent")} />
</form>
<button type='button' disabled={isUpdating} onClick={handleEdit}>
{isUpdating ? <Orbit size={16} /> : editable ?
<IconSave />
<IconSave className="stroke-gray-500 !w-5 !h-5" />
: <IconEdit />}
: <IconEdit className="fill-gray-500 !w-5 !h-5" />}
</button>
{editable && !isUpdating && <button type='button' disabled={isUpdating} onClick={handleCancelEdit}>
<IconCancel className="!w-6 !h-6" />
<IconCancel className="!w-5 !h-5 fill-gray-500" />
</button>}
</div>
:
+11 -8
View File
@@ -22,7 +22,7 @@ const Tip = ({ title, desc }: TipProps) => {
<p className="text-gray-500">{desc}</p>
</div>;
};
const tdClass = "px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900 align-top";
const tdClass = "p-6 whitespace-nowrap text-sm font-medium text-gray-900 align-top";
type WebhookParams = { webhook?: string, uid: number };
type DeleteParams = { name: string, uid: number };
export default function BotConfig() {
@@ -75,16 +75,19 @@ export default function BotConfig() {
{bots.map(bot => {
const { uid, name, avatar } = bot;
return <tr key={uid} className="bg-white border-b transition duration-300 ease-in-out hover:bg-gray-100">
<td className="px-4 py-2 flex flex-col gap-1 items-start">
<td className="px-4 py-2">
<AvatarUploader uid={uid} url={avatar} uploadImage={updateAvatar} name={name} className="!w-14 !h-14" />
<span className='text-xs text-gray-500'>
</td>
<td className={`${tdClass}`}>
<div>
{name}
</div>
<div className='text-xs text-gray-500'>
#{uid}
</span>
</div>
</td>
<td className={tdClass}>
{name}
</td>
<td className={tdClass}>
<td className={`${tdClass} py-2`}>
<BotAPIKeys uid={uid} />
</td>
<td className={tdClass}>