747 lines
27 KiB
HTML
747 lines
27 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>Context Workflow Manager</title>
|
||
<style>
|
||
* {
|
||
margin: 0;
|
||
padding: 0;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
body {
|
||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
padding: 20px;
|
||
min-height: 100vh;
|
||
}
|
||
|
||
.container {
|
||
max-width: 1400px;
|
||
margin: 0 auto;
|
||
}
|
||
|
||
h1 {
|
||
text-align: center;
|
||
color: white;
|
||
margin-bottom: 30px;
|
||
font-size: 2.5em;
|
||
text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
|
||
}
|
||
|
||
.workflow-info {
|
||
background: white;
|
||
padding: 20px;
|
||
border-radius: 10px;
|
||
margin-bottom: 30px;
|
||
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
|
||
}
|
||
|
||
.workflow-info h3 {
|
||
color: #667eea;
|
||
margin-bottom: 15px;
|
||
}
|
||
|
||
.status-flow {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
flex-wrap: wrap;
|
||
gap: 10px;
|
||
}
|
||
|
||
.status-badge {
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
color: white;
|
||
padding: 8px 15px;
|
||
border-radius: 20px;
|
||
font-size: 0.9em;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(auto-fit, minmax(500px, 1fr));
|
||
gap: 20px;
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
.card {
|
||
background: white;
|
||
border-radius: 10px;
|
||
padding: 25px;
|
||
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
|
||
transition: transform 0.2s;
|
||
}
|
||
|
||
.card:hover {
|
||
transform: translateY(-5px);
|
||
box-shadow: 0 6px 12px rgba(0,0,0,0.15);
|
||
}
|
||
|
||
.card h3 {
|
||
color: #667eea;
|
||
margin-bottom: 15px;
|
||
padding-bottom: 10px;
|
||
border-bottom: 2px solid #f0f0f0;
|
||
}
|
||
|
||
.status-indicator {
|
||
display: inline-block;
|
||
padding: 5px 12px;
|
||
border-radius: 15px;
|
||
font-size: 0.85em;
|
||
font-weight: bold;
|
||
margin-left: 10px;
|
||
}
|
||
|
||
.status-0 { background: #ffd700; color: #000; }
|
||
.status-1 { background: #87ceeb; color: #000; }
|
||
.status-2 { background: #90ee90; color: #000; }
|
||
.status-3 { background: #ffa500; color: #fff; }
|
||
.status-4 { background: #9370db; color: #fff; }
|
||
.status-5 { background: #32cd32; color: #fff; }
|
||
|
||
.form-group {
|
||
margin-bottom: 15px;
|
||
}
|
||
|
||
label {
|
||
display: block;
|
||
margin-bottom: 5px;
|
||
color: #333;
|
||
font-weight: 600;
|
||
}
|
||
|
||
input, textarea, select {
|
||
width: 100%;
|
||
padding: 10px;
|
||
border: 2px solid #e0e0e0;
|
||
border-radius: 5px;
|
||
font-size: 14px;
|
||
transition: border-color 0.3s;
|
||
}
|
||
|
||
input:focus, textarea:focus {
|
||
outline: none;
|
||
border-color: #667eea;
|
||
}
|
||
|
||
textarea {
|
||
min-height: 80px;
|
||
resize: vertical;
|
||
font-family: inherit;
|
||
}
|
||
|
||
button {
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
color: white;
|
||
border: none;
|
||
padding: 12px 25px;
|
||
border-radius: 5px;
|
||
cursor: pointer;
|
||
font-size: 14px;
|
||
font-weight: bold;
|
||
transition: transform 0.2s, box-shadow 0.2s;
|
||
width: 100%;
|
||
margin-top: 10px;
|
||
}
|
||
|
||
button:hover {
|
||
transform: translateY(-2px);
|
||
box-shadow: 0 4px 8px rgba(0,0,0,0.2);
|
||
}
|
||
|
||
button:active {
|
||
transform: translateY(0);
|
||
}
|
||
|
||
.result {
|
||
margin-top: 15px;
|
||
padding: 15px;
|
||
border-radius: 5px;
|
||
background: #f8f9fa;
|
||
border-left: 4px solid #667eea;
|
||
display: none;
|
||
max-height: 400px;
|
||
overflow-y: auto;
|
||
}
|
||
|
||
.result.show {
|
||
display: block;
|
||
}
|
||
|
||
.result pre {
|
||
white-space: pre-wrap;
|
||
word-wrap: break-word;
|
||
margin: 0;
|
||
font-size: 12px;
|
||
}
|
||
|
||
.success {
|
||
border-left-color: #28a745;
|
||
background: #d4edda;
|
||
}
|
||
|
||
.error {
|
||
border-left-color: #dc3545;
|
||
background: #f8d7da;
|
||
}
|
||
|
||
.context-list {
|
||
margin-top: 15px;
|
||
}
|
||
|
||
.context-item {
|
||
background: #f8f9fa;
|
||
padding: 12px;
|
||
margin-bottom: 10px;
|
||
border-radius: 5px;
|
||
border-left: 4px solid #667eea;
|
||
cursor: pointer;
|
||
transition: background 0.2s;
|
||
}
|
||
|
||
.context-item:hover {
|
||
background: #e9ecef;
|
||
}
|
||
|
||
.context-item strong {
|
||
color: #667eea;
|
||
display: block;
|
||
margin-bottom: 5px;
|
||
}
|
||
|
||
.context-item small {
|
||
color: #666;
|
||
font-size: 0.85em;
|
||
}
|
||
|
||
.copy-btn {
|
||
background: #28a745;
|
||
padding: 5px 10px;
|
||
font-size: 12px;
|
||
display: inline-block;
|
||
width: auto;
|
||
margin: 5px 5px 0 0;
|
||
}
|
||
|
||
.selected-uuid {
|
||
background: #fff3cd;
|
||
border: 2px solid #ffc107;
|
||
padding: 10px;
|
||
border-radius: 5px;
|
||
margin-bottom: 15px;
|
||
display: none;
|
||
}
|
||
|
||
.selected-uuid.show {
|
||
display: block;
|
||
}
|
||
|
||
.quick-actions {
|
||
display: flex;
|
||
gap: 10px;
|
||
margin-top: 10px;
|
||
}
|
||
|
||
.quick-actions button {
|
||
flex: 1;
|
||
padding: 8px;
|
||
font-size: 12px;
|
||
}
|
||
|
||
.small-note {
|
||
font-size: 0.85em;
|
||
color: #666;
|
||
font-style: italic;
|
||
margin-top: 5px;
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="container">
|
||
<h1>🎯 Context Workflow Manager</h1>
|
||
|
||
<div class="workflow-info">
|
||
<h3>📊 Workflow Status Flow</h3>
|
||
<div class="status-flow">
|
||
<div class="status-badge">0: Draft</div>
|
||
<div class="status-badge">1: Enriched</div>
|
||
<div class="status-badge">2: Prompt Ready</div>
|
||
<div class="status-badge">3: Generating</div>
|
||
<div class="status-badge">4: Image Ready</div>
|
||
<div class="status-badge">5: Approved</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Status 0: Create Draft -->
|
||
<div class="grid">
|
||
<div class="card">
|
||
<h3>1️⃣ Create Context <span class="status-indicator status-0">Status: 0</span></h3>
|
||
<div class="form-group">
|
||
<label>Title *</label>
|
||
<input type="text" id="createTitle" placeholder="e.g., Family Members">
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Description *</label>
|
||
<textarea id="createDesc" placeholder="e.g., Learn vocabulary about family members"></textarea>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Grade * (Format: gradeX100 + unitX10 + lesson)</label>
|
||
<input type="number" id="createGrade" placeholder="e.g., 123 = Grade 1, Unit 2, Lesson 3">
|
||
<div class="small-note">Example: 123 = Grade 1, Unit 2, Lesson 3</div>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Type</label>
|
||
<input type="text" id="createType" value="vocabulary" placeholder="vocabulary, grammar, etc.">
|
||
</div>
|
||
<button onclick="createContext()">Create Context</button>
|
||
<div class="result" id="createResult"></div>
|
||
</div>
|
||
|
||
<div class="card">
|
||
<h3>📋 Get Contexts by Status <span class="status-indicator status-0">Status: 0</span></h3>
|
||
<button onclick="getContextsByStatus(0)">Get Status 0 (Draft)</button>
|
||
<div class="result" id="status0Result"></div>
|
||
<div class="context-list" id="status0List"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Status 1: Enrich -->
|
||
<div class="grid">
|
||
<div class="card">
|
||
<h3>2️⃣ Enrich Context <span class="status-indicator status-1">0 → 1</span></h3>
|
||
<div class="selected-uuid" id="enrichSelected"></div>
|
||
<div class="form-group">
|
||
<label>Context UUID *</label>
|
||
<input type="text" id="enrichUuid" placeholder="Paste UUID or click from list above">
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Knowledge *</label>
|
||
<textarea id="enrichKnowledge" placeholder="Additional knowledge and information about this context"></textarea>
|
||
</div>
|
||
<button onclick="enrichContext()">Enrich (Status 0 → 1)</button>
|
||
<div class="result" id="enrichResult"></div>
|
||
</div>
|
||
|
||
<div class="card">
|
||
<h3>📋 Get Contexts by Status <span class="status-indicator status-1">Status: 1</span></h3>
|
||
<button onclick="getContextsByStatus(1)">Get Status 1 (Enriched)</button>
|
||
<div class="result" id="status1Result"></div>
|
||
<div class="context-list" id="status1List"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Status 2: Prepare Prompt -->
|
||
<div class="grid">
|
||
<div class="card">
|
||
<h3>3️⃣ Prepare Prompt <span class="status-indicator status-2">1 → 2</span></h3>
|
||
<div class="selected-uuid" id="promptSelected"></div>
|
||
<div class="form-group">
|
||
<label>Context UUID *</label>
|
||
<input type="text" id="promptUuid" placeholder="Paste UUID or click from list above">
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Context Content *</label>
|
||
<textarea id="promptContext" placeholder="Main context content"></textarea>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Image Prompt * (JSON)</label>
|
||
<textarea id="imgPrompt" placeholder='{"prompt": "description", "style": "cartoon"}'></textarea>
|
||
<div class="small-note">Must be valid JSON object</div>
|
||
</div>
|
||
<button onclick="preparePrompt()">Prepare Prompt (Status 1 → 2)</button>
|
||
<div class="result" id="promptResult"></div>
|
||
</div>
|
||
|
||
<div class="card">
|
||
<h3>📋 Get Contexts by Status <span class="status-indicator status-2">Status: 2</span></h3>
|
||
<button onclick="getContextsByStatus(2)">Get Status 2 (Prompt Ready)</button>
|
||
|
||
<hr style="margin: 15px 0; border: 1px solid #e0e0e0;">
|
||
|
||
<button onclick="bulkUpdateStatus2To3()" style="background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%); margin-top: 10px;">
|
||
🚀 Quick Approve: All Status 2 → 3
|
||
</button>
|
||
<div class="result" id="bulkUpdateResultTop"></div>
|
||
|
||
<hr style="margin: 15px 0; border: 1px solid #e0e0e0;">
|
||
|
||
<div class="result" id="status2Result"></div>
|
||
<div class="context-list" id="status2List"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Status 3: Update Status -->
|
||
<div class="grid">
|
||
<div class="card">
|
||
<h3>4️⃣ Update Status <span class="status-indicator status-3">2 → 3 or 1</span></h3>
|
||
<div class="selected-uuid" id="updateStatusSelected"></div>
|
||
<div class="form-group">
|
||
<label>Context UUID *</label>
|
||
<input type="text" id="updateStatusUuid" placeholder="Paste UUID or click from list above">
|
||
</div>
|
||
<div class="form-group">
|
||
<label>New Status *</label>
|
||
<select id="updateStatusValue">
|
||
<option value="3">3 - Generating</option>
|
||
<option value="1">1 - Back to Enriched</option>
|
||
</select>
|
||
</div>
|
||
<button onclick="updateStatus()">Update Status</button>
|
||
<div class="result" id="updateStatusResult"></div>
|
||
|
||
<hr style="margin: 20px 0; border: 1px solid #e0e0e0;">
|
||
|
||
<h4 style="color: #667eea; margin-bottom: 10px;">🚀 Bulk Update</h4>
|
||
<button onclick="bulkUpdateStatus2To3()" style="background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);">
|
||
Update All Status 2 → 3
|
||
</button>
|
||
<div class="result" id="bulkUpdateResult"></div>
|
||
</div>
|
||
|
||
<div class="card">
|
||
<h3>📋 Get Contexts by Status <span class="status-indicator status-3">Status: 3</span></h3>
|
||
<button onclick="getContextsByStatus(3)">Get Status 3 (Generating)</button>
|
||
<div class="result" id="status3Result"></div>
|
||
<div class="context-list" id="status3List"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Status 4: Add Images -->
|
||
<div class="grid">
|
||
<div class="card">
|
||
<h3>5️⃣ Add Images <span class="status-indicator status-4">3 → 4</span></h3>
|
||
<div class="selected-uuid" id="imagesSelected"></div>
|
||
<div class="form-group">
|
||
<label>Context UUID *</label>
|
||
<input type="text" id="imagesUuid" placeholder="Paste UUID or click from list above">
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Image URL * (String)</label>
|
||
<input type="text" id="imageUrls" placeholder="https://example.com/image.jpg">
|
||
<div class="small-note">Enter a single image URL</div>
|
||
</div>
|
||
<button onclick="addImages()">Add Images (Status 3 → 4)</button>
|
||
<div class="result" id="imagesResult"></div>
|
||
</div>
|
||
|
||
<div class="card">
|
||
<h3>📋 Get Contexts by Status <span class="status-indicator status-4">Status: 4</span></h3>
|
||
<button onclick="getContextsByStatus(4)">Get Status 4 (Image Ready)</button>
|
||
<div class="result" id="status4Result"></div>
|
||
<div class="context-list" id="status4List"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Status 5: Approve -->
|
||
<div class="grid">
|
||
<div class="card">
|
||
<h3>6️⃣ Approve Context <span class="status-indicator status-5">4 → 5</span></h3>
|
||
<div class="selected-uuid" id="approveSelected"></div>
|
||
<div class="form-group">
|
||
<label>Context UUID *</label>
|
||
<input type="text" id="approveUuid" placeholder="Paste UUID or click from list above">
|
||
</div>
|
||
<button onclick="approveContext()">Approve (Status 4 → 5)</button>
|
||
<div class="result" id="approveResult"></div>
|
||
</div>
|
||
|
||
<div class="card">
|
||
<h3>📋 Get Contexts by Status <span class="status-indicator status-5">Status: 5</span></h3>
|
||
<button onclick="getContextsByStatus(5)">Get Status 5 (Approved)</button>
|
||
<div class="result" id="status5Result"></div>
|
||
<div class="context-list" id="status5List"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
const API_BASE = '/api/contexts';
|
||
|
||
function getHeaders() {
|
||
return {
|
||
'Content-Type': 'application/json'
|
||
};
|
||
}
|
||
|
||
function showResult(elementId, data, isSuccess = true) {
|
||
const element = document.getElementById(elementId);
|
||
element.className = `result show ${isSuccess ? 'success' : 'error'}`;
|
||
element.innerHTML = `<pre>${JSON.stringify(data, null, 2)}</pre>`;
|
||
}
|
||
|
||
function copyToClipboard(text, button) {
|
||
navigator.clipboard.writeText(text).then(() => {
|
||
const originalText = button.textContent;
|
||
button.textContent = '✓ Copied!';
|
||
setTimeout(() => {
|
||
button.textContent = originalText;
|
||
}, 2000);
|
||
});
|
||
}
|
||
|
||
function selectUuid(uuid, targetInputId, selectedDivId) {
|
||
document.getElementById(targetInputId).value = uuid;
|
||
const selectedDiv = document.getElementById(selectedDivId);
|
||
selectedDiv.innerHTML = `<strong>Selected UUID:</strong> ${uuid}`;
|
||
selectedDiv.className = 'selected-uuid show';
|
||
|
||
// Scroll to the input
|
||
document.getElementById(targetInputId).scrollIntoView({ behavior: 'smooth', block: 'center' });
|
||
}
|
||
|
||
async function createContext() {
|
||
const headers = getHeaders();
|
||
|
||
const title = document.getElementById('createTitle').value.trim();
|
||
const desc = document.getElementById('createDesc').value.trim();
|
||
const grade = document.getElementById('createGrade').value.trim();
|
||
const type = document.getElementById('createType').value.trim();
|
||
|
||
if (!title || !desc || !grade) {
|
||
showResult('createResult', { error: 'Title, desc, and grade are required' }, false);
|
||
return;
|
||
}
|
||
|
||
try {
|
||
const response = await fetch(API_BASE, {
|
||
method: 'POST',
|
||
headers: headers,
|
||
body: JSON.stringify({ title, desc, grade: parseInt(grade), type })
|
||
});
|
||
const data = await response.json();
|
||
showResult('createResult', data, response.ok);
|
||
if (response.ok) {
|
||
// Auto refresh status 0 list
|
||
getContextsByStatus(0);
|
||
}
|
||
} catch (error) {
|
||
showResult('createResult', { error: error.message }, false);
|
||
}
|
||
}
|
||
|
||
async function getContextsByStatus(status) {
|
||
const headers = getHeaders();
|
||
|
||
try {
|
||
const response = await fetch(`${API_BASE}/status/${status}`, {
|
||
headers: headers
|
||
});
|
||
const data = await response.json();
|
||
showResult(`status${status}Result`, data, response.ok);
|
||
|
||
if (response.ok && data.data && data.data.contexts) {
|
||
displayContextList(data.data.contexts, status);
|
||
}
|
||
} catch (error) {
|
||
showResult(`status${status}Result`, { error: error.message }, false);
|
||
}
|
||
}
|
||
|
||
function displayContextList(contexts, status) {
|
||
const listElement = document.getElementById(`status${status}List`);
|
||
if (contexts.length === 0) {
|
||
listElement.innerHTML = '<p style="color: #666; font-style: italic;">No contexts found</p>';
|
||
return;
|
||
}
|
||
|
||
listElement.innerHTML = contexts.map(ctx => `
|
||
<div class="context-item">
|
||
<strong>${ctx.title}</strong>
|
||
<small>UUID: ${ctx.uuid} | Grade: ${ctx.grade} | Type: ${ctx.type}</small>
|
||
<div class="quick-actions">
|
||
<button class="copy-btn" onclick="copyToClipboard('${ctx.uuid}', this)">📋 Copy UUID</button>
|
||
${getStatusActionButton(ctx, status)}
|
||
</div>
|
||
</div>
|
||
`).join('');
|
||
}
|
||
|
||
function getStatusActionButton(ctx, status) {
|
||
const uuid = ctx.uuid;
|
||
switch(status) {
|
||
case 0:
|
||
return `<button class="copy-btn" style="background: #17a2b8;" onclick="selectUuid('${uuid}', 'enrichUuid', 'enrichSelected')">→ Enrich</button>`;
|
||
case 1:
|
||
return `<button class="copy-btn" style="background: #17a2b8;" onclick="selectUuid('${uuid}', 'promptUuid', 'promptSelected')">→ Prepare Prompt</button>`;
|
||
case 2:
|
||
return `<button class="copy-btn" style="background: #17a2b8;" onclick="selectUuid('${uuid}', 'updateStatusUuid', 'updateStatusSelected')">→ Update Status</button>`;
|
||
case 3:
|
||
return `<button class="copy-btn" style="background: #17a2b8;" onclick="selectUuid('${uuid}', 'imagesUuid', 'imagesSelected')">→ Add Images</button>`;
|
||
case 4:
|
||
return `<button class="copy-btn" style="background: #17a2b8;" onclick="selectUuid('${uuid}', 'approveUuid', 'approveSelected')">→ Approve</button>`;
|
||
default:
|
||
return '';
|
||
}
|
||
}
|
||
|
||
async function enrichContext() {
|
||
const headers = getHeaders();
|
||
|
||
const uuid = document.getElementById('enrichUuid').value.trim();
|
||
const knowledge = document.getElementById('enrichKnowledge').value.trim();
|
||
|
||
if (!uuid || !knowledge) {
|
||
showResult('enrichResult', { error: 'UUID and knowledge are required' }, false);
|
||
return;
|
||
}
|
||
|
||
try {
|
||
const response = await fetch(`${API_BASE}/${uuid}/enrich`, {
|
||
method: 'POST',
|
||
headers: headers,
|
||
body: JSON.stringify({ knowledge })
|
||
});
|
||
const data = await response.json();
|
||
showResult('enrichResult', data, response.ok);
|
||
if (response.ok) {
|
||
getContextsByStatus(1);
|
||
}
|
||
} catch (error) {
|
||
showResult('enrichResult', { error: error.message }, false);
|
||
}
|
||
}
|
||
|
||
async function preparePrompt() {
|
||
const headers = getHeaders();
|
||
|
||
const uuid = document.getElementById('promptUuid').value.trim();
|
||
const context = document.getElementById('promptContext').value.trim();
|
||
const imgPromptStr = document.getElementById('imgPrompt').value.trim();
|
||
|
||
if (!uuid || !context || !imgPromptStr) {
|
||
showResult('promptResult', { error: 'UUID, context, and img_prompt are required' }, false);
|
||
return;
|
||
}
|
||
|
||
try {
|
||
const img_prompt = JSON.parse(imgPromptStr);
|
||
const response = await fetch(`${API_BASE}/${uuid}/prepare-prompt`, {
|
||
method: 'POST',
|
||
headers: headers,
|
||
body: JSON.stringify({ context, img_prompt })
|
||
});
|
||
const data = await response.json();
|
||
showResult('promptResult', data, response.ok);
|
||
if (response.ok) {
|
||
getContextsByStatus(2);
|
||
}
|
||
} catch (error) {
|
||
showResult('promptResult', { error: error.message }, false);
|
||
}
|
||
}
|
||
|
||
async function updateStatus() {
|
||
const headers = getHeaders();
|
||
|
||
const uuid = document.getElementById('updateStatusUuid').value.trim();
|
||
const status = document.getElementById('updateStatusValue').value;
|
||
|
||
if (!uuid) {
|
||
showResult('updateStatusResult', { error: 'UUID is required' }, false);
|
||
return;
|
||
}
|
||
|
||
try {
|
||
const response = await fetch(`${API_BASE}/${uuid}/update-status`, {
|
||
method: 'POST',
|
||
headers: headers,
|
||
body: JSON.stringify({ status: parseInt(status) })
|
||
});
|
||
const data = await response.json();
|
||
showResult('updateStatusResult', data, response.ok);
|
||
if (response.ok) {
|
||
getContextsByStatus(3);
|
||
}
|
||
} catch (error) {
|
||
showResult('updateStatusResult', { error: error.message }, false);
|
||
}
|
||
}
|
||
|
||
async function bulkUpdateStatus2To3() {
|
||
const headers = getHeaders();
|
||
|
||
if (!confirm('Are you sure you want to update ALL contexts from status 2 to status 3?')) {
|
||
return;
|
||
}
|
||
|
||
try {
|
||
const response = await fetch(`${API_BASE}/bulk/status-2-to-3`, {
|
||
method: 'POST',
|
||
headers: headers
|
||
});
|
||
const data = await response.json();
|
||
showResult('bulkUpdateResult', data, response.ok);
|
||
showResult('bulkUpdateResultTop', data, response.ok);
|
||
if (response.ok) {
|
||
getContextsByStatus(3);
|
||
getContextsByStatus(2);
|
||
}
|
||
} catch (error) {
|
||
showResult('bulkUpdateResult', { error: error.message }, false);
|
||
showResult('bulkUpdateResultTop', { error: error.message }, false);
|
||
}
|
||
}
|
||
|
||
async function addImages() {
|
||
const headers = getHeaders();
|
||
|
||
const uuid = document.getElementById('imagesUuid').value.trim();
|
||
const imageUrl = document.getElementById('imageUrls').value.trim();
|
||
|
||
if (!uuid || !imageUrl) {
|
||
showResult('imagesResult', { error: 'UUID and image URL are required' }, false);
|
||
return;
|
||
}
|
||
|
||
try {
|
||
const response = await fetch(`${API_BASE}/${uuid}/add-images`, {
|
||
method: 'POST',
|
||
headers: headers,
|
||
body: JSON.stringify({ image: imageUrl })
|
||
});
|
||
const data = await response.json();
|
||
showResult('imagesResult', data, response.ok);
|
||
if (response.ok) {
|
||
getContextsByStatus(4);
|
||
}
|
||
} catch (error) {
|
||
showResult('imagesResult', { error: error.message }, false);
|
||
}
|
||
}
|
||
|
||
async function approveContext() {
|
||
const headers = getHeaders();
|
||
|
||
const uuid = document.getElementById('approveUuid').value.trim();
|
||
|
||
if (!uuid) {
|
||
showResult('approveResult', { error: 'UUID is required' }, false);
|
||
return;
|
||
}
|
||
|
||
try {
|
||
const response = await fetch(`${API_BASE}/${uuid}/approve`, {
|
||
method: 'POST',
|
||
headers: headers
|
||
});
|
||
const data = await response.json();
|
||
showResult('approveResult', data, response.ok);
|
||
if (response.ok) {
|
||
getContextsByStatus(5);
|
||
}
|
||
} catch (error) {
|
||
showResult('approveResult', { error: error.message }, false);
|
||
}
|
||
}
|
||
|
||
// Page loaded
|
||
window.addEventListener('load', () => {
|
||
console.log('Context Workflow Manager loaded');
|
||
});
|
||
</script>
|
||
</body>
|
||
</html> |