bmc_hub/app/workflows/frontend/operations.html

13 lines
4.7 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{% 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 %}