mirror of
https://github.com/YspCoder/clawgo.git
synced 2026-05-06 04:47:28 +08:00
Unify webui dialogs and loading flow
This commit is contained in:
@@ -148,14 +148,47 @@ const Config: React.FC = () => {
|
||||
async function saveConfig() {
|
||||
try {
|
||||
const payload = showRaw ? JSON.parse(cfgRaw) : cfg;
|
||||
const r = await fetch(`/webui/api/config${q}`, {
|
||||
method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload),
|
||||
});
|
||||
alert(await r.text());
|
||||
const submit = async (confirmRisky: boolean) => {
|
||||
const body = confirmRisky ? { ...payload, confirm_risky: true } : payload;
|
||||
return ui.withLoading(async () => {
|
||||
const r = await fetch(`/webui/api/config${q}`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(body),
|
||||
});
|
||||
const text = await r.text();
|
||||
let data: any = null;
|
||||
try {
|
||||
data = text ? JSON.parse(text) : null;
|
||||
} catch {
|
||||
data = null;
|
||||
}
|
||||
return { ok: r.ok, text, data };
|
||||
}, t('saving'));
|
||||
};
|
||||
|
||||
let result = await submit(false);
|
||||
if (!result.ok && result.data?.requires_confirm) {
|
||||
const changedFields = Array.isArray(result.data?.changed_fields) ? result.data.changed_fields.join(', ') : '';
|
||||
const ok = await ui.confirmDialog({
|
||||
title: t('configRiskyChangeConfirmTitle'),
|
||||
message: t('configRiskyChangeConfirmMessage', { fields: changedFields || '-' }),
|
||||
danger: true,
|
||||
confirmText: t('saveChanges'),
|
||||
});
|
||||
if (!ok) return;
|
||||
result = await submit(true);
|
||||
}
|
||||
|
||||
if (!result.ok) {
|
||||
throw new Error(result.data?.error || result.text || 'save failed');
|
||||
}
|
||||
|
||||
await ui.notify({ title: t('saved'), message: t('configSaved') });
|
||||
setBaseline(JSON.parse(JSON.stringify(payload)));
|
||||
setShowDiff(false);
|
||||
} catch (e) {
|
||||
alert(`${t('saveConfigFailed')}: ${e}`);
|
||||
await ui.notify({ title: t('requestFailed'), message: `${t('saveConfigFailed')}: ${e}` });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -93,14 +93,19 @@ const Cron: React.FC = () => {
|
||||
if (!ok) return;
|
||||
}
|
||||
try {
|
||||
await fetch(`/webui/api/cron${q}`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ action, id }),
|
||||
});
|
||||
await ui.withLoading(async () => {
|
||||
const r = await fetch(`/webui/api/cron${q}`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ action, id }),
|
||||
});
|
||||
if (!r.ok) {
|
||||
throw new Error(await r.text());
|
||||
}
|
||||
}, t('loading'));
|
||||
await refreshCron();
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
await ui.notify({ title: t('actionFailed'), message: String(e) });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,12 +157,13 @@ const Cron: React.FC = () => {
|
||||
if (r.ok) {
|
||||
setIsCronModalOpen(false);
|
||||
await refreshCron();
|
||||
await ui.notify({ title: t('saved'), message: t('cronSaved') });
|
||||
} else {
|
||||
const err = await r.text();
|
||||
alert(`${t('actionFailed')}: ${err}`);
|
||||
await ui.notify({ title: t('actionFailed'), message: err });
|
||||
}
|
||||
} catch (e) {
|
||||
alert(`${t('actionFailed')}: ${e}`);
|
||||
await ui.notify({ title: t('actionFailed'), message: String(e) });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,10 @@ const Memory: React.FC = () => {
|
||||
|
||||
async function loadFiles() {
|
||||
const r = await fetch(`/webui/api/memory${q}`);
|
||||
if (!r.ok) {
|
||||
await ui.notify({ title: t('requestFailed'), message: await r.text() });
|
||||
return;
|
||||
}
|
||||
const j = await r.json();
|
||||
setFiles(Array.isArray(j.files) ? j.files : []);
|
||||
}
|
||||
@@ -21,6 +25,10 @@ const Memory: React.FC = () => {
|
||||
|
||||
async function openFile(path: string) {
|
||||
const r = await fetch(`/webui/api/memory${qp('path', path)}`);
|
||||
if (!r.ok) {
|
||||
await ui.notify({ title: t('requestFailed'), message: await r.text() });
|
||||
return;
|
||||
}
|
||||
const j = await r.json();
|
||||
setActive(path);
|
||||
setContent(j.content || '');
|
||||
@@ -28,12 +36,22 @@ const Memory: React.FC = () => {
|
||||
|
||||
async function saveFile() {
|
||||
if (!active) return;
|
||||
await fetch(`/webui/api/memory${q}`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ path: active, content }),
|
||||
});
|
||||
await loadFiles();
|
||||
try {
|
||||
await ui.withLoading(async () => {
|
||||
const r = await fetch(`/webui/api/memory${q}`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ path: active, content }),
|
||||
});
|
||||
if (!r.ok) {
|
||||
throw new Error(await r.text());
|
||||
}
|
||||
await loadFiles();
|
||||
}, t('saving'));
|
||||
await ui.notify({ title: t('saved'), message: t('memoryFileSaved') });
|
||||
} catch (e) {
|
||||
await ui.notify({ title: t('requestFailed'), message: String(e) });
|
||||
}
|
||||
}
|
||||
|
||||
async function removeFile(path: string) {
|
||||
@@ -44,24 +62,48 @@ const Memory: React.FC = () => {
|
||||
confirmText: t('delete'),
|
||||
});
|
||||
if (!ok) return;
|
||||
await fetch(`/webui/api/memory${qp('path', path)}`, { method: 'DELETE' });
|
||||
if (active === path) {
|
||||
setActive('');
|
||||
setContent('');
|
||||
try {
|
||||
await ui.withLoading(async () => {
|
||||
const r = await fetch(`/webui/api/memory${qp('path', path)}`, { method: 'DELETE' });
|
||||
if (!r.ok) {
|
||||
throw new Error(await r.text());
|
||||
}
|
||||
if (active === path) {
|
||||
setActive('');
|
||||
setContent('');
|
||||
}
|
||||
await loadFiles();
|
||||
}, t('deleting'));
|
||||
} catch (e) {
|
||||
await ui.notify({ title: t('requestFailed'), message: String(e) });
|
||||
}
|
||||
await loadFiles();
|
||||
}
|
||||
|
||||
async function createFile() {
|
||||
const name = prompt(t('memoryFileNamePrompt'), `note-${Date.now()}.md`);
|
||||
if (!name) return;
|
||||
await fetch(`/webui/api/memory${q}`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ path: name, content: '' }),
|
||||
const name = await ui.promptDialog({
|
||||
title: t('memoryCreateTitle'),
|
||||
message: t('memoryFileNamePrompt'),
|
||||
confirmText: t('create'),
|
||||
initialValue: `note-${Date.now()}.md`,
|
||||
inputPlaceholder: 'note.md',
|
||||
});
|
||||
await loadFiles();
|
||||
await openFile(name);
|
||||
if (!name) return;
|
||||
try {
|
||||
await ui.withLoading(async () => {
|
||||
const r = await fetch(`/webui/api/memory${q}`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ path: name, content: '' }),
|
||||
});
|
||||
if (!r.ok) {
|
||||
throw new Error(await r.text());
|
||||
}
|
||||
await loadFiles();
|
||||
await openFile(name);
|
||||
}, t('creating'));
|
||||
} catch (e) {
|
||||
await ui.notify({ title: t('requestFailed'), message: String(e) });
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
Reference in New Issue
Block a user