Skip to content

Commit 91508cb

Browse files
authored
♻️ Unify global dialog&modal, delete unused code
2 parents f1d6b17 + 83a25f9 commit 91508cb

File tree

8 files changed

+107
-499
lines changed

8 files changed

+107
-499
lines changed

frontend/app/[locale]/agents/components/AgentSetupOrchestrator.tsx

Lines changed: 14 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,7 @@ export default function AgentSetupOrchestrator({
116116
const [importWizardData, setImportWizardData] = useState<ImportAgentData | null>(null);
117117
// Use generation state passed from parent component, not local state
118118

119-
// Delete confirmation popup status
120-
const [isDeleteConfirmOpen, setIsDeleteConfirmOpen] = useState(false);
121-
const [agentToDelete, setAgentToDelete] = useState<Agent | null>(null);
119+
122120

123121
// Embedding auto-unselect notice modal
124122
const [isEmbeddingAutoUnsetOpen, setIsEmbeddingAutoUnsetOpen] =
@@ -1770,19 +1768,17 @@ export default function AgentSetupOrchestrator({
17701768
}, [pendingImportData, runAgentImport, t]);
17711769

17721770
// Handle confirmed deletion
1773-
const handleConfirmDelete = async (t: TFunction) => {
1774-
if (!agentToDelete) return;
1775-
1771+
const handleConfirmDelete = async (agent: Agent) => {
17761772
try {
1777-
const result = await deleteAgent(Number(agentToDelete.id));
1773+
const result = await deleteAgent(Number(agent.id));
17781774
if (result.success) {
17791775
message.success(
17801776
t("businessLogic.config.error.agentDeleteSuccess", {
1781-
name: agentToDelete.name,
1777+
name: agent.name,
17821778
})
17831779
);
17841780
// If currently editing the deleted agent, reset to initial clean state and avoid confirm modal on next switch
1785-
const deletedId = Number(agentToDelete.id);
1781+
const deletedId = Number(agent.id);
17861782
const currentEditingId =
17871783
(isEditingAgent && editingAgent ? Number(editingAgent.id) : null) ??
17881784
null;
@@ -1815,7 +1811,7 @@ export default function AgentSetupOrchestrator({
18151811
} else {
18161812
// If deleting another agent that is in enabledAgentIds, remove it and update baseline
18171813
// to avoid triggering false unsaved changes indicator
1818-
const deletedId = Number(agentToDelete.id);
1814+
const deletedId = Number(agent.id);
18191815
if (enabledAgentIds.includes(deletedId)) {
18201816
const updatedEnabledAgentIds = enabledAgentIds.filter(
18211817
(id) => id !== deletedId
@@ -1840,9 +1836,6 @@ export default function AgentSetupOrchestrator({
18401836
} catch (error) {
18411837
log.error(t("agentConfig.agents.deleteFailed"), error);
18421838
message.error(t("businessLogic.config.error.agentDeleteFailed"));
1843-
} finally {
1844-
setIsDeleteConfirmOpen(false);
1845-
setAgentToDelete(null);
18461839
}
18471840
};
18481841

@@ -2009,8 +2002,13 @@ export default function AgentSetupOrchestrator({
20092002

20102003
// Handle delete agent from list
20112004
const handleDeleteAgentFromList = (agent: Agent) => {
2012-
setAgentToDelete(agent);
2013-
setIsDeleteConfirmOpen(true);
2005+
confirm({
2006+
title: t("businessLogic.config.modal.deleteTitle"),
2007+
content: t("businessLogic.config.modal.deleteContent", {
2008+
name: agent.name,
2009+
}),
2010+
onOk: () => handleConfirmDelete(agent),
2011+
});
20142012
};
20152013

20162014
// Handle exit edit mode
@@ -2305,37 +2303,7 @@ export default function AgentSetupOrchestrator({
23052303
</Col>
23062304
</Row>
23072305

2308-
{/* Delete confirmation popup */}
2309-
<Modal
2310-
title={t("businessLogic.config.modal.deleteTitle")}
2311-
open={isDeleteConfirmOpen}
2312-
onCancel={() => setIsDeleteConfirmOpen(false)}
2313-
centered
2314-
footer={
2315-
<div className="flex justify-end gap-2">
2316-
<Button
2317-
type="primary"
2318-
danger
2319-
onClick={() => handleConfirmDelete(t)}
2320-
>
2321-
{t("common.confirm")}
2322-
</Button>
2323-
</div>
2324-
}
2325-
width={520}
2326-
>
2327-
<div className="py-2">
2328-
<div className="flex items-center">
2329-
<div className="ml-3 mt-2">
2330-
<div className="text-sm leading-6">
2331-
{t("businessLogic.config.modal.deleteContent", {
2332-
name: agentToDelete?.name,
2333-
})}
2334-
</div>
2335-
</div>
2336-
</div>
2337-
</div>
2338-
</Modal>
2306+
23392307
{/* Save confirmation modal for unsaved changes (debug/navigation hooks) */}
23402308
<SaveConfirmModal
23412309
open={isSaveConfirmOpen}

frontend/app/[locale]/chat/components/chatHeader.tsx

Lines changed: 31 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22

33
import { useState, useRef, useEffect } from "react";
44
import { useTranslation } from "react-i18next";
5-
import { Modal, Button } from "antd";
6-
import { WarningFilled } from "@ant-design/icons";
5+
import { Button } from "antd";
76

87
import { Input } from "@/components/ui/input";
98
import { loadMemoryConfig, setMemorySwitch } from "@/services/memoryService";
@@ -13,6 +12,7 @@ import { useRouter } from "next/navigation";
1312
import { useAuth } from "@/hooks/useAuth";
1413
import { USER_ROLES } from "@/const/modelConfig";
1514
import { saveView } from "@/lib/viewPersistence";
15+
import { useConfirmModal } from "@/hooks/useConfirmModal";
1616

1717
interface ChatHeaderProps {
1818
title: string;
@@ -24,18 +24,43 @@ export function ChatHeader({ title, onRename }: ChatHeaderProps) {
2424
const [isEditing, setIsEditing] = useState(false);
2525
const [editTitle, setEditTitle] = useState(title);
2626

27-
const [showConfigPrompt, setShowConfigPrompt] = useState(false);
28-
const [showAutoOffPrompt, setShowAutoOffPrompt] = useState(false);
27+
2928
const inputRef = useRef<HTMLInputElement>(null);
3029
const { t, i18n } = useTranslation("common");
3130
const { user, isSpeedMode } = useAuth();
31+
const { confirm } = useConfirmModal();
3232
const isAdmin = isSpeedMode || user?.role === USER_ROLES.ADMIN;
3333

3434
const goToModelSetup = () => {
3535
saveView("models");
3636
router.push(`/${i18n.language}`);
3737
};
3838

39+
const showAutoOffConfirm = () => {
40+
confirm({
41+
title: t("embedding.chatMemoryAutoDeselectModal.title"),
42+
content: (
43+
<div className="py-2">
44+
<div className="text-sm leading-6">
45+
{t("embedding.chatMemoryAutoDeselectModal.content")}
46+
</div>
47+
{!isAdmin && (
48+
<div className="mt-2 text-xs opacity-70">
49+
{t("embedding.chatMemoryAutoDeselectModal.tip")}
50+
</div>
51+
)}
52+
{isAdmin && (
53+
<div className="mt-4 flex justify-end">
54+
<Button type="primary" danger onClick={goToModelSetup}>
55+
{t("embedding.chatMemoryAutoDeselectModal.ok_config")}
56+
</Button>
57+
</div>
58+
)}
59+
</div>
60+
),
61+
});
62+
};
63+
3964
// Update editTitle when the title attribute changes
4065
useEffect(() => {
4166
setEditTitle(title);
@@ -73,7 +98,7 @@ export function ChatHeader({ title, onRename }: ChatHeaderProps) {
7398
"Failed to auto turn off memory switch when embedding is not configured"
7499
);
75100
}
76-
setShowAutoOffPrompt(true);
101+
showAutoOffConfirm();
77102
}
78103
})
79104
.catch((e) => {
@@ -145,83 +170,7 @@ export function ChatHeader({ title, onRename }: ChatHeaderProps) {
145170
</div>
146171
</div>
147172
</header>
148-
{/* Embedding not configured prompt */}
149-
<Modal
150-
title={t("embedding.chatMemoryWarningModal.title")}
151-
open={showConfigPrompt}
152-
onCancel={() => setShowConfigPrompt(false)}
153-
centered
154-
footer={
155-
<div className="flex justify-end mt-3 gap-4">
156-
{isAdmin && (
157-
<Button type="primary" onClick={goToModelSetup}>
158-
{t("embedding.chatMemoryWarningModal.ok_config")}
159-
</Button>
160-
)}
161-
<Button onClick={() => setShowConfigPrompt(false)}>
162-
{t("embedding.chatMemoryWarningModal.ok")}
163-
</Button>
164-
</div>
165-
}
166-
>
167-
<div className="py-2">
168-
<div className="flex items-center">
169-
<WarningFilled
170-
className="text-yellow-500 mt-1 mr-2"
171-
style={{ fontSize: "48px" }}
172-
/>
173-
<div className="ml-3 mt-2">
174-
<div className="text-sm leading-6">
175-
{t("embedding.chatMemoryWarningModal.content")}
176-
</div>
177-
{!isAdmin && (
178-
<div className="mt-2 text-xs opacity-70">
179-
{t("embedding.chatMemoryWarningModal.tip")}
180-
</div>
181-
)}
182-
</div>
183-
</div>
184-
</div>
185-
</Modal>
186-
187-
{/* Auto-off memory prompt when embedding missing */}
188-
<Modal
189-
title={t("embedding.chatMemoryAutoDeselectModal.title")}
190-
open={showAutoOffPrompt}
191-
onCancel={() => setShowAutoOffPrompt(false)}
192-
centered
193-
footer={
194-
<div className="flex justify-end mt-3 gap-4">
195-
{isAdmin && (
196-
<Button type="primary" onClick={goToModelSetup}>
197-
{t("embedding.chatMemoryAutoDeselectModal.ok_config")}
198-
</Button>
199-
)}
200-
<Button onClick={() => setShowAutoOffPrompt(false)}>
201-
{t("embedding.chatMemoryAutoDeselectModal.ok")}
202-
</Button>
203-
</div>
204-
}
205-
>
206-
<div className="py-2">
207-
<div className="flex items-center">
208-
<WarningFilled
209-
className="text-yellow-500 mt-1 mr-2"
210-
style={{ fontSize: "48px" }}
211-
/>
212-
<div className="ml-3 mt-2">
213-
<div className="text-sm leading-6">
214-
{t("embedding.chatMemoryAutoDeselectModal.content")}
215-
</div>
216-
{!isAdmin && (
217-
<div className="mt-2 text-xs opacity-70">
218-
{t("embedding.chatMemoryAutoDeselectModal.tip")}
219-
</div>
220-
)}
221-
</div>
222-
</div>
223-
</div>
224-
</Modal>
173+
225174
</>
226175
);
227176
}

frontend/app/[locale]/knowledges/KnowledgeBaseConfiguration.tsx

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ import type React from "react";
44
import { useState, useEffect, useRef, useLayoutEffect } from "react";
55
import { useTranslation } from "react-i18next";
66

7-
import { App, Modal, Row, Col } from "antd";
8-
import { InfoCircleFilled, WarningFilled } from "@ant-design/icons";
7+
import { App, Modal, Row, Col, theme } from "antd";
8+
import { ExclamationCircleFilled, WarningFilled, InfoCircleFilled } from "@ant-design/icons";
99
import {
1010
DOCUMENT_ACTION_TYPES,
1111
KNOWLEDGE_BASE_ACTION_TYPES,
@@ -116,6 +116,7 @@ function DataConfig({ isActive }: DataConfigProps) {
116116
const { message } = App.useApp();
117117
const { confirm } = useConfirmModal();
118118
const { modelConfig } = useConfig();
119+
const { token } = theme.useToken();
119120

120121
// Clear cache when component initializes
121122
useEffect(() => {
@@ -828,24 +829,29 @@ function DataConfig({ isActive }: DataConfigProps) {
828829
>
829830
<Modal
830831
open={showAutoDeselectModal}
831-
title={t("embedding.knowledgeBaseAutoDeselectModal.title")}
832+
title={null}
832833
onOk={() => setShowAutoDeselectModal(false)}
833834
onCancel={() => setShowAutoDeselectModal(false)}
834835
okText={t("common.confirm")}
835836
cancelButtonProps={{ style: { display: "none" } }}
836837
centered
838+
okButtonProps={{ type: "primary", danger: true }}
837839
getContainer={() => contentRef.current || document.body}
838840
>
839-
<div className="py-2">
840-
<div className="flex items-center px-4">
841-
<InfoCircleFilled
842-
className="text-blue-500 mt-1 mr-2"
843-
style={{ fontSize: "48px" }}
844-
/>
845-
<div className="ml-3 mt-2">
846-
<div className="text-sm leading-6">
847-
{t("embedding.knowledgeBaseAutoDeselectModal.content")}
848-
</div>
841+
<div className="flex items-start gap-4">
842+
<ExclamationCircleFilled
843+
style={{
844+
color: token.colorWarning,
845+
fontSize: '22px',
846+
marginTop: '2px'
847+
}}
848+
/>
849+
<div className="flex-1">
850+
<div className="text-base font-medium mb-3">
851+
{t("embedding.knowledgeBaseAutoDeselectModal.title")}
852+
</div>
853+
<div className="text-sm leading-6">
854+
{t("embedding.knowledgeBaseAutoDeselectModal.content")}
849855
</div>
850856
</div>
851857
</div>

0 commit comments

Comments
 (0)