chore: remove plugin reorder functionality

This commit is contained in:
Junyan Qin
2025-08-21 10:47:53 +08:00
parent 53ade384eb
commit 9e9bc88473
2 changed files with 205 additions and 199 deletions
+7 -7
View File
@@ -3,7 +3,7 @@ import PluginInstalledComponent, {
PluginInstalledComponentRef, PluginInstalledComponentRef,
} from '@/app/home/plugins/plugin-installed/PluginInstalledComponent'; } from '@/app/home/plugins/plugin-installed/PluginInstalledComponent';
import MarketPage from '@/app/home/plugins/plugin-market/PluginMarketComponent'; import MarketPage from '@/app/home/plugins/plugin-market/PluginMarketComponent';
import PluginSortDialog from '@/app/home/plugins/plugin-sort/PluginSortDialog'; // import PluginSortDialog from '@/app/home/plugins/plugin-sort/PluginSortDialog';
import styles from './plugins.module.css'; import styles from './plugins.module.css';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
@@ -44,7 +44,7 @@ enum PluginInstallStatus {
export default function PluginConfigPage() { export default function PluginConfigPage() {
const { t } = useTranslation(); const { t } = useTranslation();
const [modalOpen, setModalOpen] = useState(false); const [modalOpen, setModalOpen] = useState(false);
const [sortModalOpen, setSortModalOpen] = useState(false); // const [sortModalOpen, setSortModalOpen] = useState(false);
const [activeTab, setActiveTab] = useState('installed'); const [activeTab, setActiveTab] = useState('installed');
const [installSource, setInstallSource] = useState<string>('local'); const [installSource, setInstallSource] = useState<string>('local');
const [installInfo, setInstallInfo] = useState<Record<string, any>>({}); // eslint-disable-line @typescript-eslint/no-explicit-any const [installInfo, setInstallInfo] = useState<Record<string, any>>({}); // eslint-disable-line @typescript-eslint/no-explicit-any
@@ -219,15 +219,15 @@ export default function PluginConfigPage() {
</TabsList> </TabsList>
<div className="flex flex-row justify-end items-center"> <div className="flex flex-row justify-end items-center">
<Button {/* <Button
variant="outline" variant="outline"
className="px-6 py-4 cursor-pointer mr-2" className="px-6 py-4 cursor-pointer mr-2"
onClick={() => { onClick={() => {
setSortModalOpen(true); // setSortModalOpen(true);
}} }}
> >
{t('plugins.arrange')} {t('plugins.arrange')}
</Button> </Button> */}
<DropdownMenu> <DropdownMenu>
<DropdownMenuTrigger asChild> <DropdownMenuTrigger asChild>
<Button variant="default" className="px-6 py-4 cursor-pointer"> <Button variant="default" className="px-6 py-4 cursor-pointer">
@@ -347,13 +347,13 @@ export default function PluginConfigPage() {
</div> </div>
)} )}
<PluginSortDialog {/* <PluginSortDialog
open={sortModalOpen} open={sortModalOpen}
onOpenChange={setSortModalOpen} onOpenChange={setSortModalOpen}
onSortComplete={() => { onSortComplete={() => {
pluginInstalledRef.current?.refreshPluginList(); pluginInstalledRef.current?.refreshPluginList();
}} }}
/> /> */}
</div> </div>
); );
} }
@@ -1,209 +1,215 @@
'use client'; // 'use client';
import * as React from 'react'; // import * as React from 'react';
import { useState, useEffect } from 'react'; // import { useState, useEffect } from 'react';
import { PluginCardVO } from '@/app/home/plugins/plugin-installed/PluginCardVO'; // import { PluginCardVO } from '@/app/home/plugins/plugin-installed/PluginCardVO';
import { httpClient } from '@/app/infra/http/HttpClient'; // import { httpClient } from '@/app/infra/http/HttpClient';
import { PluginReorderElement } from '@/app/infra/entities/api'; // import { PluginReorderElement } from '@/app/infra/entities/api';
import { toast } from 'sonner'; // import { toast } from 'sonner';
import { // import {
Dialog, // Dialog,
DialogContent, // DialogContent,
DialogHeader, // DialogHeader,
DialogTitle, // DialogTitle,
DialogFooter, // DialogFooter,
} from '@/components/ui/dialog'; // } from '@/components/ui/dialog';
import { Button } from '@/components/ui/button'; // import { Button } from '@/components/ui/button';
import { // import {
DndContext, // DndContext,
closestCenter, // closestCenter,
KeyboardSensor, // KeyboardSensor,
PointerSensor, // PointerSensor,
useSensor, // useSensor,
useSensors, // useSensors,
DragEndEvent, // DragEndEvent,
} from '@dnd-kit/core'; // } from '@dnd-kit/core';
import { // import {
arrayMove, // arrayMove,
SortableContext, // SortableContext,
sortableKeyboardCoordinates, // sortableKeyboardCoordinates,
useSortable, // useSortable,
verticalListSortingStrategy, // verticalListSortingStrategy,
} from '@dnd-kit/sortable'; // } from '@dnd-kit/sortable';
import { CSS } from '@dnd-kit/utilities'; // import { CSS } from '@dnd-kit/utilities';
import { useTranslation } from 'react-i18next'; // import { useTranslation } from 'react-i18next';
import { extractI18nObject } from '@/i18n/I18nProvider'; // import { extractI18nObject } from '@/i18n/I18nProvider';
interface PluginSortDialogProps { // interface PluginSortDialogProps {
open: boolean; // open: boolean;
onOpenChange: (open: boolean) => void; // onOpenChange: (open: boolean) => void;
onSortComplete: () => void; // onSortComplete: () => void;
} // }
function SortablePluginItem({ plugin }: { plugin: PluginCardVO }) { // function SortablePluginItem({ plugin }: { plugin: PluginCardVO }) {
const { attributes, listeners, setNodeRef, transform, transition } = // const { attributes, listeners, setNodeRef, transform, transition } =
useSortable({ // useSortable({
id: `${plugin.author}-${plugin.name}`, // id: `${plugin.author}-${plugin.name}`,
}); // });
const style = { // const style = {
transform: CSS.Transform.toString(transform), // transform: CSS.Transform.toString(transform),
transition, // transition,
}; // };
return ( // return (
<div // <div
ref={setNodeRef} // ref={setNodeRef}
style={style} // style={style}
{...attributes} // {...attributes}
{...listeners} // {...listeners}
className="bg-white dark:bg-gray-800 p-4 rounded-md shadow-sm border mb-2 cursor-move" // className="bg-white dark:bg-gray-800 p-4 rounded-md shadow-sm border mb-2 cursor-move"
> // >
<div className="flex flex-col"> // <div className="flex flex-col">
<div className="text-sm text-gray-600 dark:text-gray-400"> // <div className="text-sm text-gray-600 dark:text-gray-400">
{plugin.author} // {plugin.author}
</div> // </div>
<div className="text-lg font-medium">{plugin.name}</div> // <div className="text-lg font-medium">{plugin.name}</div>
<div className="text-sm line-clamp-2 text-gray-500 dark:text-gray-400 mt-1"> // <div className="text-sm line-clamp-2 text-gray-500 dark:text-gray-400 mt-1">
{plugin.description} // {plugin.description}
</div> // </div>
</div> // </div>
</div> // </div>
); // );
} // }
export default function PluginSortDialog({ // export default function PluginSortDialog({
open, // open,
onOpenChange, // onOpenChange,
onSortComplete, // onSortComplete,
}: PluginSortDialogProps) { // }: PluginSortDialogProps) {
const { t } = useTranslation(); // const { t } = useTranslation();
const [sortedPlugins, setSortedPlugins] = useState<PluginCardVO[]>([]); // const [sortedPlugins, setSortedPlugins] = useState<PluginCardVO[]>([]);
const [isLoading, setIsLoading] = useState(false); // const [isLoading, setIsLoading] = useState(false);
function getPluginList() { // function getPluginList() {
httpClient.getPlugins().then((value) => { // httpClient.getPlugins().then((value) => {
setSortedPlugins( // setSortedPlugins(
value.plugins.map((plugin) => { // value.plugins.map((plugin) => {
return new PluginCardVO({ // return new PluginCardVO({
author: plugin.author, // author: plugin.manifest.manifest.metadata.author ?? '',
description: extractI18nObject(plugin.description), // description: extractI18nObject(
enabled: plugin.enabled, // plugin.manifest.manifest.metadata.description ?? {
name: plugin.name, // en_US: '',
version: plugin.version, // zh_Hans: '',
status: plugin.status, // },
tools: plugin.tools, // ),
event_handlers: plugin.event_handlers, // enabled: plugin.enabled,
repository: plugin.repository, // name: plugin.manifest.manifest.metadata.name,
priority: plugin.priority, // version: plugin.manifest.manifest.metadata.version ?? '',
}); // status: plugin.status,
}), // components: plugin.components,
); // install_source: plugin.install_source,
}); // install_info: plugin.install_info,
} // priority: plugin.priority,
// debug: plugin.debug,
// });
// }),
// );
// });
// }
useEffect(() => { // useEffect(() => {
if (open) { // if (open) {
getPluginList(); // getPluginList();
} // }
}, [open]); // }, [open]);
const sensors = useSensors( // const sensors = useSensors(
useSensor(PointerSensor), // useSensor(PointerSensor),
useSensor(KeyboardSensor, { // useSensor(KeyboardSensor, {
coordinateGetter: sortableKeyboardCoordinates, // coordinateGetter: sortableKeyboardCoordinates,
}), // }),
); // );
function handleDragEnd(event: DragEndEvent) { // function handleDragEnd(event: DragEndEvent) {
const { active, over } = event; // const { active, over } = event;
console.log('Drag end event:', { active, over }); // console.log('Drag end event:', { active, over });
if (over && active.id !== over.id) { // if (over && active.id !== over.id) {
setSortedPlugins((items) => { // setSortedPlugins((items) => {
const oldIndex = items.findIndex( // const oldIndex = items.findIndex(
(item) => `${item.author}-${item.name}` === active.id, // (item) => `${item.author}-${item.name}` === active.id,
); // );
const newIndex = items.findIndex( // const newIndex = items.findIndex(
(item) => `${item.author}-${item.name}` === over.id, // (item) => `${item.author}-${item.name}` === over.id,
); // );
const newItems = arrayMove(items, oldIndex, newIndex); // const newItems = arrayMove(items, oldIndex, newIndex);
return newItems; // return newItems;
}); // });
} // }
} // }
function handleSave() { // function handleSave() {
setIsLoading(true); // setIsLoading(true);
const reorderElements: PluginReorderElement[] = sortedPlugins.map( // const reorderElements: PluginReorderElement[] = sortedPlugins.map(
(plugin, index) => ({ // (plugin, index) => ({
author: plugin.author, // author: plugin.author,
name: plugin.name, // name: plugin.name,
priority: index, // priority: index,
}), // }),
); // );
httpClient // httpClient
.reorderPlugins(reorderElements) // .reorderPlugins(reorderElements)
.then(() => { // .then(() => {
toast.success(t('plugins.pluginSortSuccess')); // toast.success(t('plugins.pluginSortSuccess'));
onSortComplete(); // onSortComplete();
onOpenChange(false); // onOpenChange(false);
}) // })
.catch((err) => { // .catch((err) => {
toast.error(t('plugins.pluginSortError') + err.message); // toast.error(t('plugins.pluginSortError') + err.message);
}) // })
.finally(() => { // .finally(() => {
setIsLoading(false); // setIsLoading(false);
}); // });
} // }
return ( // return (
<Dialog open={open} onOpenChange={onOpenChange}> // <Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="w-[700px] max-h-[80vh] p-0 flex flex-col"> // <DialogContent className="w-[700px] max-h-[80vh] p-0 flex flex-col">
<DialogHeader className="px-6 pt-6 pb-0"> // <DialogHeader className="px-6 pt-6 pb-0">
<DialogTitle>{t('plugins.pluginSort')}</DialogTitle> // <DialogTitle>{t('plugins.pluginSort')}</DialogTitle>
</DialogHeader> // </DialogHeader>
<div className="flex-1 overflow-y-auto px-6 py-0"> // <div className="flex-1 overflow-y-auto px-6 py-0">
<p className="text-sm text-gray-500 mb-4"> // <p className="text-sm text-gray-500 mb-4">
{t('plugins.pluginSortDescription')} // {t('plugins.pluginSortDescription')}
</p> // </p>
<DndContext // <DndContext
sensors={sensors} // sensors={sensors}
collisionDetection={closestCenter} // collisionDetection={closestCenter}
onDragEnd={handleDragEnd} // onDragEnd={handleDragEnd}
> // >
<SortableContext // <SortableContext
items={sortedPlugins.map( // items={sortedPlugins.map(
(plugin) => `${plugin.author}-${plugin.name}`, // (plugin) => `${plugin.author}-${plugin.name}`,
)} // )}
strategy={verticalListSortingStrategy} // strategy={verticalListSortingStrategy}
> // >
{sortedPlugins.map((plugin) => ( // {sortedPlugins.map((plugin) => (
<SortablePluginItem // <SortablePluginItem
key={`${plugin.author}-${plugin.name}`} // key={`${plugin.author}-${plugin.name}`}
plugin={plugin} // plugin={plugin}
/> // />
))} // ))}
</SortableContext> // </SortableContext>
</DndContext> // </DndContext>
</div> // </div>
<DialogFooter className="px-6 py-4"> // <DialogFooter className="px-6 py-4">
<Button // <Button
variant="outline" // variant="outline"
onClick={() => onOpenChange(false)} // onClick={() => onOpenChange(false)}
disabled={isLoading} // disabled={isLoading}
> // >
{t('common.cancel')} // {t('common.cancel')}
</Button> // </Button>
<Button onClick={handleSave} disabled={isLoading}> // <Button onClick={handleSave} disabled={isLoading}>
{isLoading ? t('common.saving') : t('common.save')} // {isLoading ? t('common.saving') : t('common.save')}
</Button> // </Button>
</DialogFooter> // </DialogFooter>
</DialogContent> // </DialogContent>
</Dialog> // </Dialog>
); // );
} // }