mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-07-22 20:36:08 +00:00
Add pipeline copy button to duplicate existing configurations (#1767)
* Initial plan * Add copy button to pipeline configuration page Co-authored-by: RockChinQ <45992437+RockChinQ@users.noreply.github.com> * Add i18n support for copy suffix and address code review feedback Co-authored-by: RockChinQ <45992437+RockChinQ@users.noreply.github.com> * Show new pipeline name in copy toast and close dialog after copy Co-authored-by: RockChinQ <45992437+RockChinQ@users.noreply.github.com> * perf: tool list style in extension tab --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: RockChinQ <45992437+RockChinQ@users.noreply.github.com> Co-authored-by: Junyan Qin <rockchinq@gmail.com>
This commit is contained in:
@@ -286,8 +286,8 @@ export default function PipelineExtension({
|
|||||||
variant="outline"
|
variant="outline"
|
||||||
className="flex items-center gap-1 mt-1"
|
className="flex items-center gap-1 mt-1"
|
||||||
>
|
>
|
||||||
<Wrench className="h-3 w-3 text-white" />
|
<Wrench className="h-3 w-3 text-black dark:text-white" />
|
||||||
<span className="text-xs text-white">
|
<span className="text-xs text-black dark:text-white">
|
||||||
{t('pipelines.extensions.toolCount', {
|
{t('pipelines.extensions.toolCount', {
|
||||||
count: server.runtime_info.tool_count || 0,
|
count: server.runtime_info.tool_count || 0,
|
||||||
})}
|
})}
|
||||||
@@ -416,14 +416,17 @@ export default function PipelineExtension({
|
|||||||
</div>
|
</div>
|
||||||
{server.runtime_info &&
|
{server.runtime_info &&
|
||||||
server.runtime_info.status === 'connected' && (
|
server.runtime_info.status === 'connected' && (
|
||||||
<div className="flex items-center gap-1 mt-1">
|
<Badge
|
||||||
<Wrench className="h-3 w-3 text-muted-foreground" />
|
variant="outline"
|
||||||
<span className="text-xs text-muted-foreground">
|
className="flex items-center gap-1 mt-1"
|
||||||
|
>
|
||||||
|
<Wrench className="h-3 w-3 text-black dark:text-white" />
|
||||||
|
<span className="text-xs text-black dark:text-white">
|
||||||
{t('pipelines.extensions.toolCount', {
|
{t('pipelines.extensions.toolCount', {
|
||||||
count: server.runtime_info.tool_count || 0,
|
count: server.runtime_info.tool_count || 0,
|
||||||
})}
|
})}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</Badge>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{!server.enable && (
|
{!server.enable && (
|
||||||
|
|||||||
@@ -346,6 +346,32 @@ export default function PipelineFormComponent({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleCopy = () => {
|
||||||
|
if (pipelineId) {
|
||||||
|
let newPipelineName = '';
|
||||||
|
httpClient
|
||||||
|
.getPipeline(pipelineId)
|
||||||
|
.then((resp) => {
|
||||||
|
const originalPipeline = resp.pipeline;
|
||||||
|
newPipelineName = `${originalPipeline.name}${t('pipelines.copySuffix')}`;
|
||||||
|
const newPipeline: Pipeline = {
|
||||||
|
name: newPipelineName,
|
||||||
|
description: originalPipeline.description,
|
||||||
|
config: originalPipeline.config,
|
||||||
|
};
|
||||||
|
return httpClient.createPipeline(newPipeline);
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
onFinish();
|
||||||
|
toast.success(`${t('common.copySuccess')}: ${newPipelineName}`);
|
||||||
|
onCancel();
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
toast.error(t('pipelines.createError') + err.message);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="!max-w-[70vw] max-w-6xl h-full p-0 flex flex-col bg-white dark:bg-black">
|
<div className="!max-w-[70vw] max-w-6xl h-full p-0 flex flex-col bg-white dark:bg-black">
|
||||||
@@ -478,6 +504,18 @@ export default function PipelineFormComponent({
|
|||||||
{t('pipelines.defaultPipelineCannotDelete')}
|
{t('pipelines.defaultPipelineCannotDelete')}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{isEditMode && (
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
variant="default"
|
||||||
|
onClick={handleCopy}
|
||||||
|
className="bg-green-600 hover:bg-green-700 text-white"
|
||||||
|
>
|
||||||
|
{t('common.copy')}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
|
||||||
<Button type="submit" form="pipeline-form">
|
<Button type="submit" form="pipeline-form">
|
||||||
{isEditMode ? t('common.save') : t('common.submit')}
|
{isEditMode ? t('common.save') : t('common.submit')}
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ const enUS = {
|
|||||||
deleteSuccess: 'Deleted successfully',
|
deleteSuccess: 'Deleted successfully',
|
||||||
deleteError: 'Delete failed: ',
|
deleteError: 'Delete failed: ',
|
||||||
addRound: 'Add Round',
|
addRound: 'Add Round',
|
||||||
|
copy: 'Copy',
|
||||||
copySuccess: 'Copy Successfully',
|
copySuccess: 'Copy Successfully',
|
||||||
test: 'Test',
|
test: 'Test',
|
||||||
forgotPassword: 'Forgot Password?',
|
forgotPassword: 'Forgot Password?',
|
||||||
@@ -440,6 +441,7 @@ const enUS = {
|
|||||||
createError: 'Creation failed: ',
|
createError: 'Creation failed: ',
|
||||||
saveSuccess: 'Saved successfully',
|
saveSuccess: 'Saved successfully',
|
||||||
saveError: 'Save failed: ',
|
saveError: 'Save failed: ',
|
||||||
|
copySuffix: ' Copy',
|
||||||
deleteConfirmation:
|
deleteConfirmation:
|
||||||
'Are you sure you want to delete this pipeline? Bots bound to this pipeline will not work.',
|
'Are you sure you want to delete this pipeline? Bots bound to this pipeline will not work.',
|
||||||
defaultPipelineCannotDelete: 'Default pipeline cannot be deleted',
|
defaultPipelineCannotDelete: 'Default pipeline cannot be deleted',
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ const jaJP = {
|
|||||||
deleteSuccess: '削除に成功しました',
|
deleteSuccess: '削除に成功しました',
|
||||||
deleteError: '削除に失敗しました:',
|
deleteError: '削除に失敗しました:',
|
||||||
addRound: 'ラウンドを追加',
|
addRound: 'ラウンドを追加',
|
||||||
|
copy: 'コピー',
|
||||||
copySuccess: 'コピーに成功しました',
|
copySuccess: 'コピーに成功しました',
|
||||||
test: 'テスト',
|
test: 'テスト',
|
||||||
forgotPassword: 'パスワードを忘れた?',
|
forgotPassword: 'パスワードを忘れた?',
|
||||||
@@ -443,6 +444,7 @@ const jaJP = {
|
|||||||
createError: '作成に失敗しました:',
|
createError: '作成に失敗しました:',
|
||||||
saveSuccess: '保存に成功しました',
|
saveSuccess: '保存に成功しました',
|
||||||
saveError: '保存に失敗しました:',
|
saveError: '保存に失敗しました:',
|
||||||
|
copySuffix: ' Copy',
|
||||||
deleteConfirmation:
|
deleteConfirmation:
|
||||||
'本当にこのパイプラインを削除しますか?このパイプラインに紐付けられたボットは動作しなくなります。',
|
'本当にこのパイプラインを削除しますか?このパイプラインに紐付けられたボットは動作しなくなります。',
|
||||||
defaultPipelineCannotDelete: 'デフォルトパイプラインは削除できません',
|
defaultPipelineCannotDelete: 'デフォルトパイプラインは削除できません',
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ const zhHans = {
|
|||||||
deleteSuccess: '删除成功',
|
deleteSuccess: '删除成功',
|
||||||
deleteError: '删除失败:',
|
deleteError: '删除失败:',
|
||||||
addRound: '添加回合',
|
addRound: '添加回合',
|
||||||
|
copy: '复制',
|
||||||
copySuccess: '复制成功',
|
copySuccess: '复制成功',
|
||||||
test: '测试',
|
test: '测试',
|
||||||
forgotPassword: '忘记密码?',
|
forgotPassword: '忘记密码?',
|
||||||
@@ -423,6 +424,7 @@ const zhHans = {
|
|||||||
createError: '创建失败:',
|
createError: '创建失败:',
|
||||||
saveSuccess: '保存成功',
|
saveSuccess: '保存成功',
|
||||||
saveError: '保存失败:',
|
saveError: '保存失败:',
|
||||||
|
copySuffix: ' Copy',
|
||||||
deleteConfirmation:
|
deleteConfirmation:
|
||||||
'你确定要删除这个流水线吗?已绑定此流水线的机器人将无法使用。',
|
'你确定要删除这个流水线吗?已绑定此流水线的机器人将无法使用。',
|
||||||
defaultPipelineCannotDelete: '默认流水线不可删除',
|
defaultPipelineCannotDelete: '默认流水线不可删除',
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ const zhHant = {
|
|||||||
deleteSuccess: '刪除成功',
|
deleteSuccess: '刪除成功',
|
||||||
deleteError: '刪除失敗:',
|
deleteError: '刪除失敗:',
|
||||||
addRound: '新增回合',
|
addRound: '新增回合',
|
||||||
|
copy: '複製',
|
||||||
copySuccess: '複製成功',
|
copySuccess: '複製成功',
|
||||||
test: '測試',
|
test: '測試',
|
||||||
forgotPassword: '忘記密碼?',
|
forgotPassword: '忘記密碼?',
|
||||||
@@ -421,6 +422,7 @@ const zhHant = {
|
|||||||
createError: '建立失敗:',
|
createError: '建立失敗:',
|
||||||
saveSuccess: '儲存成功',
|
saveSuccess: '儲存成功',
|
||||||
saveError: '儲存失敗:',
|
saveError: '儲存失敗:',
|
||||||
|
copySuffix: ' Copy',
|
||||||
deleteConfirmation:
|
deleteConfirmation:
|
||||||
'您確定要刪除這個流程線嗎?已綁定此流程線的機器人將無法使用。',
|
'您確定要刪除這個流程線嗎?已綁定此流程線的機器人將無法使用。',
|
||||||
defaultPipelineCannotDelete: '預設流程線不可刪除',
|
defaultPipelineCannotDelete: '預設流程線不可刪除',
|
||||||
|
|||||||
Reference in New Issue
Block a user