13 lines
4.7 KiB
HTML
13 lines
4.7 KiB
HTML
|
|
{% extends "shared/frontend/base.html" %}
|
|||
|
|
{% block title %}Workflowdrift – BMC Hub{% endblock %}
|
|||
|
|
{% block content %}<div class="container py-3"><h2>Workflowdrift</h2><a href="/workflows">Tilbage til workflows</a><button id="ops-refresh" class="btn btn-sm btn-outline-secondary ms-3">Opdatér</button><div id="ops-message" role="status" class="my-2"></div><div id="ops-runtime" class="alert alert-info mt-3"></div><h5>Hændelseskø</h5><div id="ops-queues" class="mb-3"></div><h5>Fejlede hændelser</h5><div id="ops-failed"></div><h5 class="mt-4">Eksport og afstemning</h5><p>Ved en uafklaret eksport: find den eksisterende ordre i e-conomic og indtast ordrenummeret. Afstemning læser og kontrollerer ordren; den opretter ingen ny ordre.</p><div id="ops-exports"></div></div>{% endblock %}
|
|||
|
|
{% block extra_js %}<script>
|
|||
|
|
(()=>{'use strict';const $=name=>document.getElementById('ops-'+name),statusLabels={pending:'Afventer',processing:'Behandles',done:'Færdig',failed:'Fejlet',superseded:'Erstattet',sending:'Sendes',uncertain:'Uafklaret'};
|
|||
|
|
function el(tag,text,cls){const e=document.createElement(tag);if(text!==undefined)e.textContent=text;if(cls)e.className=cls;return e;}
|
|||
|
|
async function api(path,body){const r=await fetch('/api/v1/workflows'+path,{method:body?'POST':'GET',credentials:'same-origin',headers:{'Content-Type':'application/json'},body:body?JSON.stringify(body):undefined});const data=await r.json();if(!r.ok)throw Error(typeof data.detail==='string'?data.detail:JSON.stringify(data.detail));return data;}
|
|||
|
|
async function run(fn){try{await fn();}catch(e){$('message').className='alert alert-danger';$('message').textContent=e.message;}}
|
|||
|
|
async function load(){const runtime=await api('/runtime/status');$('runtime').className='alert '+(!runtime.enabled?'alert-secondary':runtime.mode==='shadow'?'alert-info':'alert-warning');$('runtime').textContent=!runtime.enabled?'Workflowmotoren er slukket. Ingen nye workflows behandles.':`Motoren kører i ${runtime.mode==='shadow'?'skyggetilstand – ingen afregning ændres':'aktiv tilstand'}. Aktive kunder: ${(runtime.customer_ids||[]).join(', ')||'ingen'}${runtime.internal_enabled?' · Intern tid aktiveret':''} · AI: ${runtime.ai_enabled?'til':'fra'}`;$('queues').replaceChildren();for(const q of runtime.queues||[])$('queues').append(el('div',`${statusLabels[q.status]||q.status}: ${q.count}${q.oldest?' · ældste '+q.oldest:''}`));$('failed').replaceChildren();if(!runtime.failed?.length)$('failed').append(el('p','Ingen fejlede hændelser.','text-muted'));for(const f of runtime.failed||[]){const card=el('section',undefined,'card p-3 my-2');card.append(el('strong',`${f.trigger} · ${f.entity_type} #${f.entity_id}`),el('p',f.error||'Ukendt fejl','text-danger'),el('span',`Forsøg: ${f.attempts} · ${f.created_at}`,'small text-muted'));const retry=el('button','Genforsøg','btn btn-sm btn-outline-primary mt-2');retry.disabled=!runtime.enabled;retry.onclick=()=>run(async()=>{retry.disabled=true;try{await api('/runtime/events/'+encodeURIComponent(f.id)+'/retry',{});$('message').className='alert alert-success';$('message').textContent='Et nyt genforsøg er lagt i kø. Den tidligere hændelse bevares.';await load();}finally{retry.disabled=!runtime.enabled;}});card.append(retry);$('failed').append(card);}await loadExports();}
|
|||
|
|
async function loadExports(){try{const rows=await api('/exports');$('exports').replaceChildren();if(!rows.length)$('exports').append(el('p','Ingen workfloweksporter registreret.','text-muted'));for(const row of rows){const card=el('section',undefined,'card p-3 my-2'),link=el('a','Åbn ordrekladde #'+row.draft_id);link.href='/ordre/'+Number(row.draft_id);card.append(link,el('p',`Status: ${statusLabels[row.status]||row.status} · Reference: ${row.reference}`));if(row.error)card.append(el('p',row.error,'text-danger'));if(['sending','uncertain'].includes(row.status)){const label=el('label','Eksisterende e-conomic-ordrenummer'),input=el('input',undefined,'form-control');input.type='number';input.min='1';label.append(input);card.append(label);const btn=el('button','Kontrollér og afstem eksisterende ordre','btn btn-outline-primary mt-2');btn.onclick=()=>run(async()=>{if(!Number.isInteger(Number(input.value))||Number(input.value)<=0)throw Error('Angiv et gyldigt ordrenummer');btn.disabled=true;try{await api('/exports/'+Number(row.draft_id)+'/reconcile',{economic_order_number:Number(input.value)});$('message').className='alert alert-success';$('message').textContent='Den eksisterende ordre er verificeret og knyttet til kladden.';await loadExports();}finally{btn.disabled=false;}});card.append(btn);}$('exports').append(card);}}catch(e){$('exports').replaceChildren(el('p',e.message,'text-muted'));}}
|
|||
|
|
$('refresh').onclick=()=>run(load);run(load);
|
|||
|
|
})();</script>{% endblock %}
|