mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-07-24 21:36:06 +00:00
feat: add pipeline sorting functionality with three sort options (#1582)
* feat: add pipeline sorting functionality with three sort options Co-Authored-By: Junyan Qin <Chin>, u79E6u9A8Fu8A00 in Chinese, you can call me my english name Rock Chin. <rockchinq@gmail.com> * perf: ui --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Junyan Qin <Chin>, u79E6u9A8Fu8A00 in Chinese, you can call me my english name Rock Chin. <rockchinq@gmail.com>
This commit is contained in:
committed by
GitHub
parent
28ce986a8c
commit
ea51cec57e
@@ -11,7 +11,9 @@ class PipelinesRouterGroup(group.RouterGroup):
|
|||||||
@self.route('', methods=['GET', 'POST'])
|
@self.route('', methods=['GET', 'POST'])
|
||||||
async def _() -> str:
|
async def _() -> str:
|
||||||
if quart.request.method == 'GET':
|
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':
|
elif quart.request.method == 'POST':
|
||||||
json_data = await quart.request.json
|
json_data = await quart.request.json
|
||||||
|
|
||||||
|
|||||||
@@ -38,9 +38,21 @@ class PipelineService:
|
|||||||
self.ap.pipeline_config_meta_output.data,
|
self.ap.pipeline_config_meta_output.data,
|
||||||
]
|
]
|
||||||
|
|
||||||
async def get_pipelines(self) -> list[dict]:
|
async def get_pipelines(self, sort_by: str = 'created_at', sort_order: str = 'DESC') -> list[dict]:
|
||||||
result = await self.ap.persistence_mgr.execute_async(sqlalchemy.select(persistence_pipeline.LegacyPipeline))
|
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()
|
pipelines = result.all()
|
||||||
return [
|
return [
|
||||||
self.ap.persistence_mgr.serialize_model(persistence_pipeline.LegacyPipeline, pipeline)
|
self.ap.persistence_mgr.serialize_model(persistence_pipeline.LegacyPipeline, pipeline)
|
||||||
|
|||||||
@@ -9,6 +9,13 @@ import styles from './pipelineConfig.module.css';
|
|||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import PipelineDialog from './PipelineDetailDialog';
|
import PipelineDialog from './PipelineDetailDialog';
|
||||||
|
import {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectItem,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue,
|
||||||
|
} from '@/components/ui/select';
|
||||||
|
|
||||||
export default function PluginConfigPage() {
|
export default function PluginConfigPage() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -26,14 +33,19 @@ export default function PluginConfigPage() {
|
|||||||
});
|
});
|
||||||
const [selectedPipelineIsDefault, setSelectedPipelineIsDefault] =
|
const [selectedPipelineIsDefault, setSelectedPipelineIsDefault] =
|
||||||
useState(false);
|
useState(false);
|
||||||
|
const [sortByValue, setSortByValue] = useState<string>('created_at');
|
||||||
|
const [sortOrderValue, setSortOrderValue] = useState<string>('DESC');
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getPipelines();
|
getPipelines();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
function getPipelines() {
|
function getPipelines(
|
||||||
|
sortBy: string = sortByValue,
|
||||||
|
sortOrder: string = sortOrderValue,
|
||||||
|
) {
|
||||||
httpClient
|
httpClient
|
||||||
.getPipelines()
|
.getPipelines(sortBy, sortOrder)
|
||||||
.then((value) => {
|
.then((value) => {
|
||||||
const currentTime = new Date();
|
const currentTime = new Date();
|
||||||
const pipelineList = value.pipelines.map((pipeline) => {
|
const pipelineList = value.pipelines.map((pipeline) => {
|
||||||
@@ -106,6 +118,13 @@ export default function PluginConfigPage() {
|
|||||||
setDialogOpen(true);
|
setDialogOpen(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function handleSortChange(value: string) {
|
||||||
|
const [newSortBy, newSortOrder] = value.split(',').map((s) => s.trim());
|
||||||
|
setSortByValue(newSortBy);
|
||||||
|
setSortOrderValue(newSortOrder);
|
||||||
|
getPipelines(newSortBy, newSortOrder);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.configPageContainer}>
|
<div className={styles.configPageContainer}>
|
||||||
<PipelineDialog
|
<PipelineDialog
|
||||||
@@ -134,6 +153,27 @@ export default function PluginConfigPage() {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<div className="flex flex-row justify-between items-center mb-4 px-[0.8rem]">
|
||||||
|
<Select
|
||||||
|
value={`${sortByValue},${sortOrderValue}`}
|
||||||
|
onValueChange={handleSortChange}
|
||||||
|
>
|
||||||
|
<SelectTrigger className="w-[180px] cursor-pointer bg-white dark:bg-gray-800">
|
||||||
|
<SelectValue placeholder={t('pipelines.sortBy')} />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value="created_at,DESC">
|
||||||
|
{t('pipelines.newestCreated')}
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="updated_at,DESC">
|
||||||
|
{t('pipelines.recentlyEdited')}
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="updated_at,ASC">
|
||||||
|
{t('pipelines.earliestEdited')}
|
||||||
|
</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
<div className={styles.pipelineListContainer}>
|
<div className={styles.pipelineListContainer}>
|
||||||
<CreateCardComponent
|
<CreateCardComponent
|
||||||
width={'100%'}
|
width={'100%'}
|
||||||
|
|||||||
@@ -323,8 +323,15 @@ class HttpClient {
|
|||||||
return this.get('/api/v1/pipelines/_/metadata');
|
return this.get('/api/v1/pipelines/_/metadata');
|
||||||
}
|
}
|
||||||
|
|
||||||
public getPipelines(): Promise<ApiRespPipelines> {
|
public getPipelines(
|
||||||
return this.get('/api/v1/pipelines');
|
sortBy?: string,
|
||||||
|
sortOrder?: string,
|
||||||
|
): Promise<ApiRespPipelines> {
|
||||||
|
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<GetPipelineResponseData> {
|
public getPipeline(uuid: string): Promise<GetPipelineResponseData> {
|
||||||
|
|||||||
@@ -194,6 +194,10 @@ const enUS = {
|
|||||||
today: 'Today',
|
today: 'Today',
|
||||||
updateTime: 'Updated ',
|
updateTime: 'Updated ',
|
||||||
defaultBadge: 'Default',
|
defaultBadge: 'Default',
|
||||||
|
sortBy: 'Sort by',
|
||||||
|
newestCreated: 'Newest Created',
|
||||||
|
recentlyEdited: 'Recently Edited',
|
||||||
|
earliestEdited: 'Earliest Edited',
|
||||||
basicInfo: 'Basic',
|
basicInfo: 'Basic',
|
||||||
aiCapabilities: 'AI',
|
aiCapabilities: 'AI',
|
||||||
triggerConditions: 'Trigger',
|
triggerConditions: 'Trigger',
|
||||||
|
|||||||
@@ -195,6 +195,10 @@ const jaJP = {
|
|||||||
today: '今日',
|
today: '今日',
|
||||||
updateTime: '更新日時',
|
updateTime: '更新日時',
|
||||||
defaultBadge: 'デフォルト',
|
defaultBadge: 'デフォルト',
|
||||||
|
sortBy: '並び順',
|
||||||
|
newestCreated: '最新作成',
|
||||||
|
recentlyEdited: '最近編集',
|
||||||
|
earliestEdited: '最古編集',
|
||||||
basicInfo: '基本情報',
|
basicInfo: '基本情報',
|
||||||
aiCapabilities: 'AI機能',
|
aiCapabilities: 'AI機能',
|
||||||
triggerConditions: 'トリガー条件',
|
triggerConditions: 'トリガー条件',
|
||||||
|
|||||||
@@ -189,6 +189,10 @@ const zhHans = {
|
|||||||
today: '今天',
|
today: '今天',
|
||||||
updateTime: '更新于',
|
updateTime: '更新于',
|
||||||
defaultBadge: '默认',
|
defaultBadge: '默认',
|
||||||
|
sortBy: '排序方式',
|
||||||
|
newestCreated: '最新创建',
|
||||||
|
recentlyEdited: '最近编辑',
|
||||||
|
earliestEdited: '最早编辑',
|
||||||
basicInfo: '基础信息',
|
basicInfo: '基础信息',
|
||||||
aiCapabilities: 'AI 能力',
|
aiCapabilities: 'AI 能力',
|
||||||
triggerConditions: '触发条件',
|
triggerConditions: '触发条件',
|
||||||
|
|||||||
Reference in New Issue
Block a user