mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-06-02 03:55:55 +00:00
feat: Add unsaved changes tracking to PipelineFormComponent
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useEffect, useRef, useState, useMemo } from 'react';
|
||||
import { httpClient } from '@/app/infra/http/HttpClient';
|
||||
import { GetPipelineResponseData, Pipeline } from '@/app/infra/entities/api';
|
||||
import {
|
||||
@@ -118,6 +118,14 @@ export default function PipelineFormComponent({
|
||||
},
|
||||
});
|
||||
|
||||
// Track unsaved changes by comparing current form values against a saved snapshot
|
||||
const savedSnapshotRef = useRef<string>('');
|
||||
const watchedValues = form.watch();
|
||||
const hasUnsavedChanges = useMemo(() => {
|
||||
if (!isEditMode || !savedSnapshotRef.current) return false;
|
||||
return JSON.stringify(watchedValues) !== savedSnapshotRef.current;
|
||||
}, [isEditMode, watchedValues]);
|
||||
|
||||
useEffect(() => {
|
||||
// get config schema from metadata
|
||||
httpClient.getGeneralPipelineMetadata().then((resp) => {
|
||||
@@ -139,7 +147,7 @@ export default function PipelineFormComponent({
|
||||
.getPipeline(pipelineId || '')
|
||||
.then((resp: GetPipelineResponseData) => {
|
||||
setIsDefaultPipeline(resp.pipeline.is_default ?? false);
|
||||
form.reset({
|
||||
const loadedValues = {
|
||||
basic: {
|
||||
name: resp.pipeline.name,
|
||||
description: resp.pipeline.description,
|
||||
@@ -149,7 +157,9 @@ export default function PipelineFormComponent({
|
||||
trigger: resp.pipeline.config.trigger,
|
||||
safety: resp.pipeline.config.safety,
|
||||
output: resp.pipeline.config.output,
|
||||
});
|
||||
};
|
||||
form.reset(loadedValues);
|
||||
savedSnapshotRef.current = JSON.stringify(loadedValues);
|
||||
});
|
||||
}
|
||||
}, []);
|
||||
@@ -216,6 +226,7 @@ export default function PipelineFormComponent({
|
||||
httpClient
|
||||
.updatePipeline(pipelineId || '', pipeline)
|
||||
.then(() => {
|
||||
savedSnapshotRef.current = JSON.stringify(form.getValues());
|
||||
onFinish();
|
||||
toast.success(t('pipelines.saveSuccess'));
|
||||
})
|
||||
@@ -509,7 +520,14 @@ export default function PipelineFormComponent({
|
||||
</form>
|
||||
{/* 按钮栏移到 Tabs 外部,始终固定底部 */}
|
||||
{showButtons && (
|
||||
<div className="flex justify-end gap-2 pt-4 border-t mb-0 bg-white dark:bg-black sticky bottom-0 z-10">
|
||||
<div className="flex justify-end items-center gap-2 pt-4 border-t mb-0 bg-white dark:bg-black sticky bottom-0 z-10">
|
||||
{isEditMode && hasUnsavedChanges && (
|
||||
<div className="text-amber-600 dark:text-amber-400 text-sm flex items-center gap-1.5 mr-auto">
|
||||
<span className="inline-block w-1.5 h-1.5 rounded-full bg-amber-500" />
|
||||
{t('pipelines.unsavedChanges')}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{isEditMode && !isDefaultPipeline && (
|
||||
<Button
|
||||
type="button"
|
||||
|
||||
@@ -589,6 +589,7 @@ const enUS = {
|
||||
copyConfirmTitle: 'Confirm Copy',
|
||||
copyConfirmation:
|
||||
'Are you sure you want to copy this pipeline? This will create a new pipeline with all configurations.',
|
||||
unsavedChanges: 'You have unsaved changes',
|
||||
extensions: {
|
||||
title: 'Extensions',
|
||||
loadError: 'Failed to load plugins',
|
||||
|
||||
@@ -591,6 +591,7 @@ const jaJP = {
|
||||
copyConfirmTitle: 'コピーの確認',
|
||||
copyConfirmation:
|
||||
'このパイプラインをコピーしますか?すべての設定を含む新しいパイプラインが作成されます。',
|
||||
unsavedChanges: '未保存の変更があります',
|
||||
extensions: {
|
||||
title: 'プラグイン統合',
|
||||
loadError: 'プラグインリストの読み込みに失敗しました',
|
||||
|
||||
@@ -565,6 +565,7 @@ const zhHans = {
|
||||
copyConfirmTitle: '确认复制',
|
||||
copyConfirmation:
|
||||
'确定要复制这个流水线吗?复制将创建一个包含完整配置的新流水线。',
|
||||
unsavedChanges: '有未保存的更改',
|
||||
extensions: {
|
||||
title: '扩展集成',
|
||||
loadError: '加载插件列表失败',
|
||||
|
||||
@@ -558,6 +558,7 @@ const zhHant = {
|
||||
copyConfirmTitle: '確認複製',
|
||||
copyConfirmation:
|
||||
'確定要複製這個流程線嗎?複製將創建一個包含完整配置的新流程線。',
|
||||
unsavedChanges: '有未儲存的變更',
|
||||
extensions: {
|
||||
title: '擴展集成',
|
||||
loadError: '載入插件清單失敗',
|
||||
|
||||
Reference in New Issue
Block a user