PageSourceSearch

https://factchecker.cloud/src/components/Settings/ChatHistoryCleanup.tsx

js factchecker.cloud collected 2026-10-02 01:21:54 UTC 16,148 bytes, 225 lines download raw bytes

1import { createHotContext as __vite__createHotContext } from "/@vite/client";import.meta.hot = __vite__createHotContext("/src/components/Settings/ChatHistoryCleanup.tsx");const useState = __vite__cjsImport0_react["useState"];const _jsxDEV = __vite__cjsImport6_react_jsxDevRuntime["jsxDEV"];import __vite__cjsImport0_react from "/node_modules/.vite/deps/react.js?v=ae253003";
2import { App as AntdApp, Button, Card, Checkbox, Input, Modal, Radio, Space, Typography } from "/node_modules/.vite/deps/antd.js?v=ae253003";
3import { DeleteOutlined } from "/node_modules/.vite/deps/@ant-design_icons.js?v=ae253003";
4import { bulkDeleteMySessions } from "/src/api/chat.ts";
5import { useChatStore } from "/src/store/chatStore.ts";
6import { extractErrorMessage } from "/src/utils/errorUtils.ts";
7var _jsxFileName = "/home/bang/datatek_rag/frontend/src/components/Settings/ChatHistoryCleanup.tsx";
8import __vite__cjsImport6_react_jsxDevRuntime from "/node_modules/.vite/deps/react_jsx-dev-runtime.js?v=ae253003";
9var _s = $RefreshSig$();
10const CONFIRM_WORD = "삭제";
11/**
12* 내 대화 기록 일괄 삭제 — 실수로 누르기 쉬운 사이드바가 아니라 설정 화면에 둔다.
13* 범위를 고르고 확인 문구를 직접 입력해야 실행되며, 고정한 대화는 기본적으로 남긴다.
14*/
15export default function ChatHistoryCleanup() {
16	_s();
17	const { message: messageApi } = AntdApp.useApp();
18	const loadSessions = useChatStore((s) => s.loadSessions);
19	const clearCurrentSession = useChatStore((s) => s.clearCurrentSession);
20	const [open, setOpen] = useState(false);
21	const [range, setRange] = useState("90");
22	const [includePinned, setIncludePinned] = useState(false);
23	const [typed, setTyped] = useState("");
24	const [running, setRunning] = useState(false);
25	const close = () => {
26		if (running) return;
27		setOpen(false);
28		setTyped("");
29	};
30	const run = async () => {
31		if (typed.trim() !== CONFIRM_WORD || running) return;
32		setRunning(true);
33		try {
34			const res = await bulkDeleteMySessions({
35				older_than_days: range === "all" ? null : Number(range),
36				include_pinned: includePinned,
37				confirm: typed.trim()
38			});
39			messageApi.success(res.deleted > 0 ? `대화 ${res.deleted}개를 삭제했습니다` : "조건에 맞는 대화가 없습니다");
40			clearCurrentSession();
41			void loadSessions();
42			setOpen(false);
43			setTyped("");
44		} catch (error) {
45			messageApi.error(extractErrorMessage(error, "대화 삭제에 실패했습니다"));
46		} finally {
47			setRunning(false);
48		}
49	};
50	return /* @__PURE__ */ _jsxDEV(Card, {
51		title: "대화 기록 정리",
52		style: { marginTop: 24 },
53		children: [
54			/* @__PURE__ */ _jsxDEV(Typography.Paragraph, {
55				type: "secondary",
56				children: "오래된 대화를 한꺼번에 지웁니다. 삭제한 대화와 메시지는 되돌릴 수 없습니다."
57			}, void 0, false, {
58				fileName: _jsxFileName,
59				lineNumber: 53,
60				columnNumber: 7
61			}, this),
62			/* @__PURE__ */ _jsxDEV(Button, {
63				danger: true,
64				icon: /* @__PURE__ */ _jsxDEV(DeleteOutlined, {}, void 0, false, {
65					fileName: _jsxFileName,
66					lineNumber: 56,
67					columnNumber: 28
68				}, this),
69				onClick: () => setOpen(true),
70				children: "대화 기록 삭제…"
71			}, void 0, false, {
72				fileName: _jsxFileName,
73				lineNumber: 56,
74				columnNumber: 7
75			}, this),
76			/* @__PURE__ */ _jsxDEV(Modal, {
77				open,
78				title: "대화 기록 삭제",
79				okText: "삭제 실행",
80				cancelText: "취소",
81				onOk: () => void run(),
82				onCancel: close,
83				okButtonProps: {
84					danger: true,
85					disabled: typed.trim() !== CONFIRM_WORD,
86					loading: running
87				},
88				cancelButtonProps: { disabled: running },
89				mask: { closable: false },
90				destroyOnHidden: true,
91				children: /* @__PURE__ */ _jsxDEV(Space, {
92					orientation: "vertical",
93					size: 12,
94					style: { width: "100%" },
95					children: [
96						/* @__PURE__ */ _jsxDEV(Radio.Group, {
97							value: range,
98							onChange: (e) => setRange(e.target.value),
99							"aria-label": "삭제 범위",
100							children: /* @__PURE__ */ _jsxDEV(Space, {
101								orientation: "vertical",
102								children: [
103									/* @__PURE__ */ _jsxDEV(Radio, {
104										value: "90",
105										children: "90일 넘게 쓰지 않은 대화"
106									}, void 0, false, {
107										fileName: _jsxFileName,
108										lineNumber: 74,
109										columnNumber: 15
110									}, this),
111									/* @__PURE__ */ _jsxDEV(Radio, {
112										value: "30",
113										children: "30일 넘게 쓰지 않은 대화"
114									}, void 0, false, {
115										fileName: _jsxFileName,
116										lineNumber: 75,
117										columnNumber: 15
118									}, this),
119									/* @__PURE__ */ _jsxDEV(Radio, {
120										value: "all",
121										children: "모든 대화"
122									}, void 0, false, {
123										fileName: _jsxFileName,
124										lineNumber: 76,
125										columnNumber: 15
126									}, this)
127								]
128							}, void 0, true, {
129								fileName: _jsxFileName,
130								lineNumber: 73,
131								columnNumber: 13
132							}, this)
133						}, void 0, false, {
134							fileName: _jsxFileName,
135							lineNumber: 72,
136							columnNumber: 11
137						}, this),
138						/* @__PURE__ */ _jsxDEV(Checkbox, {
139							checked: includePinned,
140							onChange: (e) => setIncludePinned(e.target.checked),
141							children: "고정한 대화도 삭제"
142						}, void 0, false, {
143							fileName: _jsxFileName,
144							lineNumber: 79,
145							columnNumber: 11
146						}, this),
147						/* @__PURE__ */ _jsxDEV(Typography.Text, { children: [
148							"계속하려면 아래에 ",
149							/* @__PURE__ */ _jsxDEV(Typography.Text, {
150								strong: true,
151								children: CONFIRM_WORD
152							}, void 0, false, {
153								fileName: _jsxFileName,
154								lineNumber: 83,
155								columnNumber: 23
156							}, this),
157							" 를 입력하세요."
158						] }, void 0, true, {
159							fileName: _jsxFileName,
160							lineNumber: 82,
161							columnNumber: 11
162						}, this),
163						/* @__PURE__ */ _jsxDEV(Input, {
164							"aria-label": "확인 문구",
165							value: typed,
166							onChange: (e) => setTyped(e.target.value),
167							placeholder: CONFIRM_WORD,
168							onPressEnter: () => void run()
169						}, void 0, false, {
170							fileName: _jsxFileName,
171							lineNumber: 85,
172							columnNumber: 11
173						}, this)
174					]
175				}, void 0, true, {
176					fileName: _jsxFileName,
177					lineNumber: 71,
178					columnNumber: 9
179				}, this)
180			}, void 0, false, {
181				fileName: _jsxFileName,
182				lineNumber: 59,
183				columnNumber: 7
184			}, this)
185		]
186	}, void 0, true, {
187		fileName: _jsxFileName,
188		lineNumber: 52,
189		columnNumber: 5
190	}, this);
191}
192_s(ChatHistoryCleanup, "mF4OL2I5bM5xQsErOAv4jh7+3/k=", false, function() {
193	return [
194		AntdApp.useApp,
195		useChatStore,
196		useChatStore
197	];
198});
199_c = ChatHistoryCleanup;
200var _c;
201$RefreshReg$(_c, "ChatHistoryCleanup");
202import * as RefreshRuntime from "/@react-refresh";
203const inWebWorker = typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope;
204import * as __vite_react_currentExports from "/src/components/Settings/ChatHistoryCleanup.tsx";
205if (import.meta.hot && !inWebWorker) {
206  if (!window.$RefreshReg$) {
207    throw new Error(
208      "@vitejs/plugin-react can't detect preamble. Something is wrong."
209    );
210  }
211
212  const currentExports = __vite_react_currentExports;
213  queueMicrotask(() => {
214    RefreshRuntime.registerExportsForReactRefresh("/home/bang/datatek_rag/frontend/src/components/Settings/ChatHistoryCleanup.tsx", currentExports);
215    import.meta.hot.accept((nextExports) => {
216      if (!nextExports) return;
217      const invalidateMessage = RefreshRuntime.validateRefreshBoundaryAndEnqueueUpdate("/home/bang/datatek_rag/frontend/src/components/Settings/ChatHistoryCleanup.tsx", currentExports, nextExports);
218      if (invalidateMessage) import.meta.hot.invalidate(invalidateMessage);
219    });
220  });
221}
222function $RefreshReg$(type, id) { return RefreshRuntime.register(type, "/home/bang/datatek_rag/frontend/src/components/Settings/ChatHistoryCleanup.tsx" + ' ' + id); }
223function $RefreshSig$() { return RefreshRuntime.createSignatureFunctionForTransform(); }
224
225//# sourceMappingURL=data:application/json;base64,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QUFpQjtPQUNMLHdCQUFDLFdBQVcsTUFBWjtRQUFpQjtrQkFBUTtPQUE4Qjs7Ozs7T0FBQztNQUNuRDs7Ozs7TUFDakIsd0JBQUMsT0FBRDtPQUNFLGNBQVc7T0FDWCxPQUFPO09BQ1AsV0FBVyxNQUFNLFNBQVMsRUFBRSxPQUFPLEtBQUs7T0FDeEMsYUFBYTtPQUNiLG9CQUFvQixLQUFLLElBQUk7TUFDOUI7Ozs7O0tBQ0k7Ozs7OztHQUNGOzs7OztFQUNIOzs7Ozs7QUFFViIsIm5hbWVzIjpbXSwic291cmNlcyI6WyJDaGF0SGlzdG9yeUNsZWFudXAudHN4Il0sInZlcnNpb24iOjMsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IHVzZVN0YXRlIH0gZnJvbSAncmVhY3QnO1xuaW1wb3J0IHsgQXBwIGFzIEFudGRBcHAsIEJ1dHRvbiwgQ2FyZCwgQ2hlY2tib3gsIElucHV0LCBNb2RhbCwgUmFkaW8sIFNwYWNlLCBUeXBvZ3JhcGh5IH0gZnJvbSAnYW50ZCc7XG5pbXBvcnQgeyBEZWxldGVPdXRsaW5lZCB9IGZyb20gJ0BhbnQtZGVzaWduL2ljb25zJztcbmltcG9ydCB7IGJ1bGtEZWxldGVNeVNlc3Npb25zIH0gZnJvbSAnLi4vLi4vYXBpL2NoYXQnO1xuaW1wb3J0IHsgdXNlQ2hhdFN0b3JlIH0gZnJvbSAnLi4vLi4vc3RvcmUvY2hhdFN0b3JlJztcbmltcG9ydCB7IGV4dHJhY3RFcnJvck1lc3NhZ2UgfSBmcm9tICcuLi8uLi91dGlscy9lcnJvclV0aWxzJztcblxuY29uc3QgQ09ORklSTV9XT1JEID0gJ+yCreygnCc7XG5cbi8qKlxuICog64K0IOuMgO2ZlCDquLDroZ0g7J286rSEIOyCreygnCDigJQg7Iuk7IiY66GcIOuIhOultOq4sCDsiazsmrQg7IKs7J2065Oc67CU6rCAIOyVhOuLiOudvCDshKTsoJUg7ZmU66m07JeQIOuRlOuLpC5cbiAqIOuylOychOulvCDqs6DrpbTqs6Ag7ZmV7J24IOusuOq1rOulvCDsp4HsoJEg7J6F66Cl7ZW07JW8IOyLpO2WieuQmOupsCwg6rOg7KCV7ZWcIOuMgO2ZlOuKlCDquLDrs7jsoIHsnLzroZwg64Ko6ri064ukLlxuICovXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbiBDaGF0SGlzdG9yeUNsZWFudXAoKSB7XG4gIGNvbnN0IHsgbWVzc2FnZTogbWVzc2FnZUFwaSB9ID0gQW50ZEFwcC51c2VBcHAoKTtcbiAgY29uc3QgbG9hZFNlc3Npb25zID0gdXNlQ2hhdFN0b3JlKChzKSA9PiBzLmxvYWRTZXNzaW9ucyk7XG4gIGNvbnN0IGNsZWFyQ3VycmVudFNlc3Npb24gPSB1c2VDaGF0U3RvcmUoKHMpID0+IHMuY2xlYXJDdXJyZW50U2Vzc2lvbik7XG4gIGNvbnN0IFtvcGVuLCBzZXRPcGVuXSA9IHVzZVN0YXRlKGZhbHNlKTtcbiAgY29uc3QgW3JhbmdlLCBzZXRSYW5nZV0gPSB1c2VTdGF0ZTwnOTAnIHwgJzMwJyB8ICdhbGwnPignOTAnKTtcbiAgY29uc3QgW2luY2x1ZGVQaW5uZWQsIHNldEluY2x1ZGVQaW5uZWRdID0gdXNlU3RhdGUoZmFsc2UpO1xuICBjb25zdCBbdHlwZWQsIHNldFR5cGVkXSA9IHVzZVN0YXRlKCcnKTtcbiAgY29uc3QgW3J1bm5pbmcsIHNldFJ1bm5pbmddID0gdXNlU3RhdGUoZmFsc2UpO1xuXG4gIGNvbnN0IGNsb3NlID0gKCkgPT4ge1xuICAgIGlmIChydW5uaW5nKSByZXR1cm47XG4gICAgc2V0T3BlbihmYWxzZSk7XG4gICAgc2V0VHlwZWQoJycpO1xuICB9O1xuXG4gIGNvbnN0IHJ1biA9IGFzeW5jICgpID0+IHtcbiAgICBpZiAodHlwZWQudHJpbSgpICE9PSBDT05GSVJNX1dPUkQgfHwgcnVubmluZykgcmV0dXJuO1xuICAgIHNldFJ1bm5pbmcodHJ1ZSk7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IGJ1bGtEZWxldGVNeVNlc3Npb25zKHtcbiAgICAgICAgb2xkZXJfdGhhbl9kYXlzOiByYW5nZSA9PT0gJ2FsbCcgPyBudWxsIDogTnVtYmVyKHJhbmdlKSxcbiAgICAgICAgaW5jbHVkZV9waW5uZWQ6IGluY2x1ZGVQaW5uZWQsXG4gICAgICAgIGNvbmZpcm06IHR5cGVkLnRyaW0oKSxcbiAgICAgIH0pO1xuICAgICAgbWVzc2FnZUFwaS5zdWNjZXNzKHJlcy5kZWxldGVkID4gMCA/IGDrjIDtmZQgJHtyZXMuZGVsZXRlZH3qsJzrpbwg7IKt7KCc7ZaI7Iq164uI64ukYCA6ICfsobDqsbTsl5Ag66ee64qU
225IOuMgO2ZlOqwgCDsl4bsirXri4jri6QnKTtcbiAgICAgIGNsZWFyQ3VycmVudFNlc3Npb24oKTtcbiAgICAgIHZvaWQgbG9hZFNlc3Npb25zKCk7XG4gICAgICBzZXRPcGVuKGZhbHNlKTtcbiAgICAgIHNldFR5cGVkKCcnKTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgbWVzc2FnZUFwaS5lcnJvcihleHRyYWN0RXJyb3JNZXNzYWdlKGVycm9yLCAn64yA7ZmUIOyCreygnOyXkCDsi6TtjKjtlojsirXri4jri6QnKSk7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHNldFJ1bm5pbmcoZmFsc2UpO1xuICAgIH1cbiAgfTtcblxuICByZXR1cm4gKFxuICAgIDxDYXJkIHRpdGxlPVwi64yA7ZmUIOq4sOuhnSDsoJXrpqxcIiBzdHlsZT17eyBtYXJnaW5Ub3A6IDI0IH19PlxuICAgICAgPFR5cG9ncmFwaHkuUGFyYWdyYXBoIHR5cGU9XCJzZWNvbmRhcnlcIj5cbiAgICAgICAg7Jik656Y65CcIOuMgO2ZlOulvCDtlZzqurzrsojsl5Ag7KeA7JuB64uI64ukLiDsgq3soJztlZwg64yA7ZmU7JmAIOuplOyLnOyngOuKlCDrkJjrj4zrprQg7IiYIOyXhuyKteuLiOuLpC5cbiAgICAgIDwvVHlwb2dyYXBoeS5QYXJhZ3JhcGg+XG4gICAgICA8QnV0dG9uIGRhbmdlciBpY29uPXs8RGVsZXRlT3V0bGluZWQgLz59IG9uQ2xpY2s9eygpID0+IHNldE9wZW4odHJ1ZSl9PlxuICAgICAgICDrjIDtmZQg6riw66GdIOyCreygnOKAplxuICAgICAgPC9CdXR0b24+XG4gICAgICA8TW9kYWxcbiAgICAgICAgb3Blbj17b3Blbn1cbiAgICAgICAgdGl0bGU9XCLrjIDtmZQg6riw66GdIOyCreygnFwiXG4gICAgICAgIG9rVGV4dD1cIuyCreygnCDsi6TtlolcIlxuICAgICAgICBjYW5jZWxUZXh0PVwi7Leo7IaMXCJcbiAgICAgICAgb25Paz17KCkgPT4gdm9pZCBydW4oKX1cbiAgICAgICAgb25DYW5jZWw9e2Nsb3NlfVxuICAgICAgICBva0J1dHRvblByb3BzPXt7IGRhbmdlcjogdHJ1ZSwgZGlzYWJsZWQ6IHR5cGVkLnRyaW0oKSAhPT0gQ09ORklSTV9XT1JELCBsb2FkaW5nOiBydW5uaW5nIH19XG4gICAgICAgIGNhbmNlbEJ1dHRvblByb3BzPXt7IGRpc2FibGVkOiBydW5uaW5nIH19XG4gICAgICAgIG1hc2s9e3sgY2xvc2FibGU6IGZhbHNlIH19XG4gICAgICAgIGRlc3Ryb3lPbkhpZGRlblxuICAgICAgPlxuICAgICAgICA8U3BhY2Ugb3JpZW50YXRpb249XCJ2ZXJ0aWNhbFwiIHNpemU9ezEyfSBzdHlsZT17eyB3aWR0aDogJzEwMCUnIH19PlxuICAgICAgICAgIDxSYWRpby5Hcm91cCB2YWx1ZT17cmFuZ2V9IG9uQ2hhbmdlPXsoZSkgPT4gc2V0UmFuZ2UoZS50YXJnZXQudmFsdWUpfSBhcmlhLWxhYmVsPVwi7IKt7KCcIOuylOychFwiPlxuICAgICAgICAgICAgPFNwYWNlIG9yaWVudGF0aW9uPVwidmVydGljYWxcIj5cbiAgICAgICAgICAgICAgPFJhZGlvIHZhbHVlPVwiOTBcIj45MOydvCDrhJjqsowg7JOw7KeAIOyViuydgCDrjIDtmZQ8L1JhZGlvPlxuICAgICAgICAgICAgICA8UmFkaW8gdmFsdWU9XCIzMFwiPjMw7J28IOuEmOqyjCDsk7Dsp4Ag7JWK7J2AIOuMgO2ZlDwvUmFkaW8+XG4gICAgICAgICAgICAgIDxSYWRpbyB2YWx1ZT1cImFsbFwiPuuqqOuToCDrjIDtmZQ8L1JhZGlvPlxuICAgICAgICAgICAgPC9TcGFjZT5cbiAgICAgICAgICA8L1JhZGlvLkdyb3VwPlxuICAgICAgICAgIDxDaGVja2JveCBjaGVja2VkPXtpbmNsdWRlUGlubmVkfSBvbkNoYW5nZT17KGUpID0+IHNldEluY2x1ZGVQaW5uZWQoZS50YXJnZXQuY2hlY2tlZCl9PlxuICAgICAgICAgICAg6rOg7KCV7ZWcIOuMgO2ZlOuPhCDsgq3soJxcbiAgICAgICAgICA8L0NoZWNrYm94PlxuICAgICAgICAgIDxUeXBvZ3JhcGh5LlRleHQ+XG4gICAgICAgICAgICDqs4Tsho3tlZjroKTrqbQg7JWE656Y7JeQIDxUeXBvZ3JhcGh5LlRleHQgc3Ryb25nPntDT05GSVJNX1dPUkR9PC9UeXBvZ3JhcGh5LlRleHQ+IOulvCDsnoXroKXtlZjshLjsmpQuXG4gICAgICAgICAgPC9UeXBvZ3JhcGh5LlRleHQ+XG4gICAgICAgICAgPElucHV0XG4gICAgICAgICAgICBhcmlhLWxhYmVsPVwi7ZmV7J24IOusuOq1rFwiXG4gICAgICAgICAgICB2YWx1ZT17dHlwZWR9XG4gICAgICAgICAgICBvbkNoYW5nZT17KGUpID0+IHNldFR5cGVkKGUudGFyZ2V0LnZhbHVlKX1cbiAgICAgICAgICAgIHBsYWNlaG9sZGVyPXtDT05GSVJNX1dPUkR9XG4gICAgICAgICAgICBvblByZXNzRW50ZXI9eygpID0+IHZvaWQgcnVuKCl9XG4gICAgICAgICAgLz5cbiAgICAgICAgPC9TcGFjZT5cbiAgICAgIDwvTW9kYWw+XG4gICAgPC9DYXJkPlxuICApO1xufVxuIl19

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.