feat: export preset.

This commit is contained in:
Wentao Lyu 2023-04-03 12:54:15 +08:00
parent ced65f8c98
commit 15ada95249
4 changed files with 98 additions and 20 deletions

View file

@ -39,6 +39,7 @@
"clsx": "^1.2.1", "clsx": "^1.2.1",
"copy-to-clipboard": "^3.3.3", "copy-to-clipboard": "^3.3.3",
"crypto-browserify": "^3.12.0", "crypto-browserify": "^3.12.0",
"export-from-json": "^1.7.2",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"lucide-react": "^0.113.0", "lucide-react": "^0.113.0",
"react": "^18.2.0", "react": "^18.2.0",

View file

@ -1,8 +1,9 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { useSetRecoilState, useRecoilValue } from 'recoil'; import { useSetRecoilState, useRecoilValue } from 'recoil';
import axios from 'axios'; import axios from 'axios';
import exportFromJSON from 'export-from-json';
import DialogTemplate from '../ui/DialogTemplate'; import DialogTemplate from '../ui/DialogTemplate';
import { Dialog } from '../ui/Dialog.tsx'; import { Dialog, DialogClose, DialogButton } from '../ui/Dialog.tsx';
import { Input } from '../ui/Input.tsx'; import { Input } from '../ui/Input.tsx';
import { Label } from '../ui/Label.tsx'; import { Label } from '../ui/Label.tsx';
import Dropdown from '../ui/Dropdown'; import Dropdown from '../ui/Dropdown';
@ -55,17 +56,47 @@ const EditPresetDialog = ({ open, onOpenChange, preset: _preset }) => {
const defaultTextProps = const defaultTextProps =
'rounded-md border border-gray-200 focus:border-slate-400 focus:bg-gray-50 bg-transparent text-sm shadow-[0_0_10px_rgba(0,0,0,0.05)] outline-none placeholder:text-gray-400 focus:outline-none focus:ring-gray-400 focus:ring-opacity-20 focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 dark:border-gray-500 dark:bg-gray-700 focus:dark:bg-gray-600 dark:text-gray-50 dark:shadow-[0_0_15px_rgba(0,0,0,0.10)] dark:focus:border-gray-400 dark:focus:outline-none dark:focus:ring-0 dark:focus:ring-gray-400 dark:focus:ring-offset-0'; 'rounded-md border border-gray-200 focus:border-slate-400 focus:bg-gray-50 bg-transparent text-sm shadow-[0_0_10px_rgba(0,0,0,0.05)] outline-none placeholder:text-gray-400 focus:outline-none focus:ring-gray-400 focus:ring-opacity-20 focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 dark:border-gray-500 dark:bg-gray-700 focus:dark:bg-gray-600 dark:text-gray-50 dark:shadow-[0_0_15px_rgba(0,0,0,0.10)] dark:focus:border-gray-400 dark:focus:outline-none dark:focus:ring-0 dark:focus:ring-gray-400 dark:focus:ring-offset-0';
// in order not to use wrong data from other endpoint
const clearPreset = () => {
if (preset?.endpoint === 'openAI')
return {
title: preset?.title,
endpoint: preset?.endpoint,
model: preset?.model,
chatGptLabel: preset?.chatGptLabel,
promptPrefix: preset?.promptPrefix,
temperature: preset?.temperature,
top_p: preset?.top_p,
presence_penalty: preset?.presence_penalty,
frequency_penalty: preset?.frequency_penalty
};
else
return {
title: preset?.title,
endpoint: preset?.endpoint
};
// TODO: else
};
const submitPreset = () => { const submitPreset = () => {
axios({ axios({
method: 'post', method: 'post',
url: '/api/presets', url: '/api/presets',
data: preset, data: clearPreset(),
withCredentials: true withCredentials: true
}).then(res => { }).then(res => {
setPresets(res?.data); setPresets(res?.data);
}); });
}; };
const exportPreset = () => {
exportFromJSON({
data: clearPreset(),
fileName: `${preset?.title}.json`,
exportType: exportFromJSON.types.json
});
};
useEffect(() => { useEffect(() => {
setPreset(_preset); setPreset(_preset);
}, [open]); }, [open]);
@ -123,11 +154,26 @@ const EditPresetDialog = ({ open, onOpenChange, preset: _preset }) => {
<div className="w-full p-0">{renderSettings()}</div> <div className="w-full p-0">{renderSettings()}</div>
</div> </div>
} }
selection={{ buttons={
selectHandler: submitPreset, <>
selectClasses: 'bg-green-600 hover:bg-green-700 dark:hover:bg-green-800 text-white', <DialogClose
selectText: 'Save' onClick={submitPreset}
}} className="dark:hover:gray-400 border-gray-700 bg-green-600 text-white hover:bg-green-700 dark:hover:bg-green-800"
>
Save
</DialogClose>
</>
}
leftButtons={
<>
<DialogButton
onClick={exportPreset}
className="dark:hover:gray-400 bg-red border-gray-700"
>
Export
</DialogButton>
</>
}
/> />
</Dialog> </Dialog>
); );

View file

@ -1,5 +1,6 @@
import * as React from "react" import * as React from "react"
import * as DialogPrimitive from "@radix-ui/react-dialog" import * as DialogPrimitive from "@radix-ui/react-dialog"
import { Button } from '../ui/Button';
import { X } from "lucide-react" import { X } from "lucide-react"
import { cn } from "../../utils" import { cn } from "../../utils"
@ -81,7 +82,7 @@ const DialogFooter = ({
}: React.HTMLAttributes<HTMLDivElement>) => ( }: React.HTMLAttributes<HTMLDivElement>) => (
<div <div
className={cn( className={cn(
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", "flex flex-col-reverse sm:flex-row sm:justify-between sm:space-x-2",
className className
)} )}
{...props} {...props}
@ -132,6 +133,22 @@ const DialogClose = React.forwardRef<
)) ))
DialogClose.displayName = DialogPrimitive.Title.displayName DialogClose.displayName = DialogPrimitive.Title.displayName
const DialogButton = React.forwardRef<
React.ElementRef<typeof Button>,
React.ComponentPropsWithoutRef<typeof Button>
>(({ className, ...props }, ref) => (
<Button
ref={ref}
variant="outline"
className={cn(
"mt-2 inline-flex h-10 items-center justify-center rounded-md border border-slate-200 bg-transparent py-2 px-4 text-sm font-semibold text-slate-900 transition-colors hover:bg-slate-100 focus:outline-none focus:ring-2 focus:ring-slate-400 focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 dark:border-slate-700 dark:text-slate-100 dark:hover:bg-slate-700 dark:focus:ring-slate-400 dark:focus:ring-offset-slate-900 sm:mt-0",
className
)}
{...props}
/>
))
DialogButton.displayName = DialogPrimitive.Title.displayName
export { export {
Dialog, Dialog,
DialogTrigger, DialogTrigger,
@ -141,4 +158,5 @@ export {
DialogTitle, DialogTitle,
DialogDescription, DialogDescription,
DialogClose, DialogClose,
DialogButton,
} }

View file

@ -10,8 +10,16 @@ import {
} from './Dialog.tsx'; } from './Dialog.tsx';
import { cn } from '~/utils/'; import { cn } from '~/utils/';
export default function DialogTemplate({ title, description, main, buttons, selection, className }) { export default function DialogTemplate({
const { selectHandler, selectClasses, selectText } = selection; title,
description,
main,
buttons,
leftButtons,
selection,
className
}) {
const { selectHandler, selectClasses, selectText } = selection || {};
const defaultSelect = const defaultSelect =
'bg-gray-900 text-white transition-colors hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-gray-400 focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 dark:bg-gray-100 dark:text-gray-900 dark:hover:bg-gray-200 dark:focus:ring-gray-400 dark:focus:ring-offset-gray-900'; 'bg-gray-900 text-white transition-colors hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-gray-400 focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 dark:bg-gray-100 dark:text-gray-900 dark:hover:bg-gray-200 dark:focus:ring-gray-400 dark:focus:ring-offset-gray-900';
@ -43,16 +51,21 @@ export default function DialogTemplate({ title, description, main, buttons, sele
</div> */} </div> */}
{main ? main : null} {main ? main : null}
<DialogFooter> <DialogFooter>
<DialogClose className="dark:hover:gray-400 border-gray-700">Cancel</DialogClose> <div>{leftButtons ? leftButtons : null}</div>
{buttons ? buttons : null} <div>
<DialogClose <DialogClose className="dark:hover:gray-400 border-gray-700">Cancel</DialogClose>
onClick={selectHandler} {buttons ? buttons : null}
className={`${ {selection ? (
selectClasses || defaultSelect <DialogClose
} inline-flex h-10 items-center justify-center rounded-md border-none py-2 px-4 text-sm font-semibold`} onClick={selectHandler}
> className={`${
{selectText} selectClasses || defaultSelect
</DialogClose> } inline-flex h-10 items-center justify-center rounded-md border-none py-2 px-4 text-sm font-semibold`}
>
{selectText}
</DialogClose>
) : null}
</div>
</DialogFooter> </DialogFooter>
</DialogContent> </DialogContent>
); );