From ea51cec57eeb2406a9c20b4dd0ddf84a59e49b73 Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Sun, 20 Jul 2025 17:23:30 +0800 Subject: [PATCH] feat: add pipeline sorting functionality with three sort options (#1582) * feat: add pipeline sorting functionality with three sort options Co-Authored-By: Junyan Qin , u79E6u9A8Fu8A00 in Chinese, you can call me my english name Rock Chin. * perf: ui --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Junyan Qin , u79E6u9A8Fu8A00 in Chinese, you can call me my english name Rock Chin. --- .../controller/groups/pipelines/pipelines.py | 4 +- pkg/api/http/service/pipeline.py | 18 ++++++-- web/src/app/home/pipelines/page.tsx | 44 ++++++++++++++++++- web/src/app/infra/http/HttpClient.ts | 11 ++++- web/src/i18n/locales/en-US.ts | 4 ++ web/src/i18n/locales/ja-JP.ts | 4 ++ web/src/i18n/locales/zh-Hans.ts | 4 ++ 7 files changed, 81 insertions(+), 8 deletions(-) diff --git a/pkg/api/http/controller/groups/pipelines/pipelines.py b/pkg/api/http/controller/groups/pipelines/pipelines.py index 96ca239a..d056afb4 100644 --- a/pkg/api/http/controller/groups/pipelines/pipelines.py +++ b/pkg/api/http/controller/groups/pipelines/pipelines.py @@ -11,7 +11,9 @@ class PipelinesRouterGroup(group.RouterGroup): @self.route('', methods=['GET', 'POST']) async def _() -> str: if quart.request.method == 'GET': - return self.success(data={'pipelines': await self.ap.pipeline_service.get_pipelines()}) + sort_by = quart.request.args.get('sort_by', 'created_at') + sort_order = quart.request.args.get('sort_order', 'DESC') + return self.success(data={'pipelines': await self.ap.pipeline_service.get_pipelines(sort_by, sort_order)}) elif quart.request.method == 'POST': json_data = await quart.request.json diff --git a/pkg/api/http/service/pipeline.py b/pkg/api/http/service/pipeline.py index f0f6c083..96504d61 100644 --- a/pkg/api/http/service/pipeline.py +++ b/pkg/api/http/service/pipeline.py @@ -38,9 +38,21 @@ class PipelineService: self.ap.pipeline_config_meta_output.data, ] - async def get_pipelines(self) -> list[dict]: - result = await self.ap.persistence_mgr.execute_async(sqlalchemy.select(persistence_pipeline.LegacyPipeline)) - + async def get_pipelines(self, sort_by: str = 'created_at', sort_order: str = 'DESC') -> list[dict]: + query = sqlalchemy.select(persistence_pipeline.LegacyPipeline) + + if sort_by == 'created_at': + if sort_order == 'DESC': + query = query.order_by(persistence_pipeline.LegacyPipeline.created_at.desc()) + else: + query = query.order_by(persistence_pipeline.LegacyPipeline.created_at.asc()) + elif sort_by == 'updated_at': + if sort_order == 'DESC': + query = query.order_by(persistence_pipeline.LegacyPipeline.updated_at.desc()) + else: + query = query.order_by(persistence_pipeline.LegacyPipeline.updated_at.asc()) + + result = await self.ap.persistence_mgr.execute_async(query) pipelines = result.all() return [ self.ap.persistence_mgr.serialize_model(persistence_pipeline.LegacyPipeline, pipeline) diff --git a/web/src/app/home/pipelines/page.tsx b/web/src/app/home/pipelines/page.tsx index 40875f6e..ecead827 100644 --- a/web/src/app/home/pipelines/page.tsx +++ b/web/src/app/home/pipelines/page.tsx @@ -9,6 +9,13 @@ import styles from './pipelineConfig.module.css'; import { toast } from 'sonner'; import { useTranslation } from 'react-i18next'; import PipelineDialog from './PipelineDetailDialog'; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from '@/components/ui/select'; export default function PluginConfigPage() { const { t } = useTranslation(); @@ -26,14 +33,19 @@ export default function PluginConfigPage() { }); const [selectedPipelineIsDefault, setSelectedPipelineIsDefault] = useState(false); + const [sortByValue, setSortByValue] = useState('created_at'); + const [sortOrderValue, setSortOrderValue] = useState('DESC'); useEffect(() => { getPipelines(); }, []); - function getPipelines() { + function getPipelines( + sortBy: string = sortByValue, + sortOrder: string = sortOrderValue, + ) { httpClient - .getPipelines() + .getPipelines(sortBy, sortOrder) .then((value) => { const currentTime = new Date(); const pipelineList = value.pipelines.map((pipeline) => { @@ -106,6 +118,13 @@ export default function PluginConfigPage() { setDialogOpen(true); }; + function handleSortChange(value: string) { + const [newSortBy, newSortOrder] = value.split(',').map((s) => s.trim()); + setSortByValue(newSortBy); + setSortOrderValue(newSortOrder); + getPipelines(newSortBy, newSortOrder); + } + return (
+
+ +
{ - return this.get('/api/v1/pipelines'); + public getPipelines( + sortBy?: string, + sortOrder?: string, + ): Promise { + const params = new URLSearchParams(); + if (sortBy) params.append('sort_by', sortBy); + if (sortOrder) params.append('sort_order', sortOrder); + const queryString = params.toString(); + return this.get(`/api/v1/pipelines${queryString ? `?${queryString}` : ''}`); } public getPipeline(uuid: string): Promise { diff --git a/web/src/i18n/locales/en-US.ts b/web/src/i18n/locales/en-US.ts index e194c58b..3e9089fc 100644 --- a/web/src/i18n/locales/en-US.ts +++ b/web/src/i18n/locales/en-US.ts @@ -194,6 +194,10 @@ const enUS = { today: 'Today', updateTime: 'Updated ', defaultBadge: 'Default', + sortBy: 'Sort by', + newestCreated: 'Newest Created', + recentlyEdited: 'Recently Edited', + earliestEdited: 'Earliest Edited', basicInfo: 'Basic', aiCapabilities: 'AI', triggerConditions: 'Trigger', diff --git a/web/src/i18n/locales/ja-JP.ts b/web/src/i18n/locales/ja-JP.ts index a5ea9c04..67df7d24 100644 --- a/web/src/i18n/locales/ja-JP.ts +++ b/web/src/i18n/locales/ja-JP.ts @@ -195,6 +195,10 @@ const jaJP = { today: '今日', updateTime: '更新日時', defaultBadge: 'デフォルト', + sortBy: '並び順', + newestCreated: '最新作成', + recentlyEdited: '最近編集', + earliestEdited: '最古編集', basicInfo: '基本情報', aiCapabilities: 'AI機能', triggerConditions: 'トリガー条件', diff --git a/web/src/i18n/locales/zh-Hans.ts b/web/src/i18n/locales/zh-Hans.ts index 621bb16c..49c09015 100644 --- a/web/src/i18n/locales/zh-Hans.ts +++ b/web/src/i18n/locales/zh-Hans.ts @@ -189,6 +189,10 @@ const zhHans = { today: '今天', updateTime: '更新于', defaultBadge: '默认', + sortBy: '排序方式', + newestCreated: '最新创建', + recentlyEdited: '最近编辑', + earliestEdited: '最早编辑', basicInfo: '基础信息', aiCapabilities: 'AI 能力', triggerConditions: '触发条件',