v1.0.169: prompts CRUD via VM API — /api/prompts, no more prompt.cfm dependency

This commit is contained in:
2026-06-24 10:27:59 +04:00
parent dd558e00e7
commit abba9c4f1d
4 changed files with 150 additions and 25 deletions
+21 -24
View File
@@ -583,12 +583,12 @@ function closePromptModal(e) {
}
function loadPrompt(role) {
fetch('/prompt.cfm?action=get_active&role=' + role)
fetch(VM_API + '/api/prompts?role=' + role)
.then(function(r) { return r.json(); })
.then(function(d) {
if (d.OK) {
promptEditor.value = d.BODY || '';
activePromptId[role] = d.ID || '';
if (d.ok) {
promptEditor.value = d.body || '';
activePromptId[role] = d.id || '';
loadHistory(role);
}
})
@@ -596,52 +596,50 @@ function loadPrompt(role) {
}
function loadHistory(role) {
fetch('/prompt.cfm?action=list&role=' + role)
fetch(VM_API + '/api/prompts/list?role=' + role)
.then(function(r) { return r.json(); })
.then(function(d) {
if (!d.OK || !d.VERSIONS || !d.VERSIONS.length) {
if (!d.ok || !d.versions || !d.versions.length) {
promptHistory.innerHTML = '<div style="color:var(--muted);">нет версий</div>';
return;
}
promptHistory.innerHTML = d.VERSIONS.map(function(v) {
var isActive = v.IS_ACTIVE ? '✓ ' : '';
var style = v.IS_ACTIVE ? 'font-weight:600;' : '';
promptHistory.innerHTML = d.versions.map(function(v) {
var isActive = v.is_active ? '✓ ' : '';
var style = v.is_active ? 'font-weight:600;' : '';
return '<div style="display:flex;align-items:center;padding:4px 0;border-bottom:1px solid var(--brand-gray);font-size:11px;' + style + '">'
+ '<span style="flex:1;">' + isActive + escHtml(v.NAME) + ' <span style="color:var(--muted);">' + fmtDate(v.CREATED_AT) + '</span></span>'
+ (!v.IS_ACTIVE ? '<button class="arrow-btn" onclick="activatePrompt(\'' + v.ID + '\')" title="Активировать" style="font-size:14px;">←</button>' : '')
+ (!v.IS_ACTIVE ? '<button class="arrow-btn" onclick="deletePrompt(\'' + v.ID + '\')" title="Удалить" style="font-size:14px;">✕</button>' : '')
+ '<span style="flex:1;">' + isActive + escHtml(v.name) + ' <span style="color:var(--muted);">' + fmtDate(v.created_at) + '</span></span>'
+ (!v.is_active ? '<button class="arrow-btn" onclick="activatePrompt(\'' + v.id + '\')" title="Активировать" style="font-size:14px;">←</button>' : '')
+ (!v.is_active ? '<button class="arrow-btn" onclick="deletePrompt(\'' + v.id + '\')" title="Удалить" style="font-size:14px;">✕</button>' : '')
+ '</div>';
}).join('');
})
.catch(function(e) { console.error('loadHistory:', e); });
}
// escHtml/fmtDate — вынесены в app_utils.js
function activatePrompt(id) {
fetch('/prompt.cfm?action=activate', {
fetch(VM_API + '/api/prompts/activate', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({id: id})
})
.then(function(r) { return r.json(); })
.then(function(d) {
if (d.OK) { loadPrompt(promptRole); promptStatus.textContent = '✓ активирован'; }
else { promptStatus.textContent = '✕ ' + (d.ERROR || 'ошибка'); }
if (d.ok) { loadPrompt(promptRole); promptStatus.textContent = '✓ активирован'; }
else { promptStatus.textContent = '✕ ' + (d.error || 'ошибка'); }
});
}
function deletePrompt(id) {
if (!confirm('Удалить эту версию промпта?')) return;
fetch('/prompt.cfm?action=delete', {
fetch(VM_API + '/api/prompts/delete', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({id: id})
})
.then(function(r) { return r.json(); })
.then(function(d) {
if (d.OK) { loadHistory(promptRole); promptStatus.textContent = '✓ удалено'; }
else { promptStatus.textContent = '✕ ' + (d.ERROR || 'ошибка'); }
if (d.ok) { loadHistory(promptRole); promptStatus.textContent = '✓ удалено'; }
else { promptStatus.textContent = '✕ ' + (d.error || 'ошибка'); }
});
}
@@ -649,23 +647,22 @@ document.getElementById('promptSave').addEventListener('click', function() {
var body = promptEditor.value.trim();
if (!body) { promptStatus.textContent = '✕ тело промпта пустое'; return; }
var name = promptName.value.trim() || ('v' + new Date().toISOString().replace(/[:.]/g,'-').substring(0,16));
fetch('/prompt.cfm?action=save', {
fetch(VM_API + '/api/prompts/save', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
role: promptRole, name: name, body: body,
parent_id: activePromptId[promptRole] || '',
notes: promptNotes.value.trim(), is_active: true
})
})
.then(function(r) { return r.json(); })
.then(function(d) {
if (d.OK) {
if (d.ok) {
promptStatus.textContent = '✓ сохранено (новая версия)';
promptName.value = ''; promptNotes.value = '';
loadPrompt(promptRole);
} else {
promptStatus.textContent = '✕ ' + (d.ERROR || 'ошибка');
promptStatus.textContent = '✕ ' + (d.error || 'ошибка');
}
});
});