diff --git a/superx/edit/kern/etl_manager.jsp b/superx/edit/kern/superx_komponentenverwaltung.jsp similarity index 67% rename from superx/edit/kern/etl_manager.jsp rename to superx/edit/kern/superx_komponentenverwaltung.jsp index 923fb56..a59b099 100644 --- a/superx/edit/kern/etl_manager.jsp +++ b/superx/edit/kern/superx_komponentenverwaltung.jsp @@ -549,7 +549,7 @@ try { -SuperX ETL Manager +SuperX Komponentenverwaltung
-

SuperX ETL Manager

Aufgeräumte Modulübersicht für den täglichen Betrieb. Technische Details, Jobauswahl und JSON-Rohdaten sind über den Detailbereich erreichbar.

+

SuperX Komponentenverwaltung

Aufgeräumte Modulübersicht für den täglichen Betrieb. Technische Details, Jobauswahl und JSON-Rohdaten sind über den Detailbereich erreichbar.

+
';return h;} -function showDetails(m){if(!m){return;}var abbr=key(m),arr=jobs(m),vi=versionInfo(m),cp=completePlan(m),ul=unloadPlan(m),uo=updateOnlyPlan(m),ug=upgradePlan(m),h='';el.detailsTitle.textContent='Details: '+(m.name||abbr);h+='

Modul

Name
'+esc(m.name||'-')+'
Kürzel
'+code(abbr||'-')+'
Systeminfo-ID
'+esc(m.systeminfoId||'-')+'
Installiert
'+(m.installed===true?'ja':'nein')+'
Installierte Version
'+versionValue(vi.installed)+'
Verfügbare Version
'+versionValue(vi.target)+'
Datenquelle
'+esc(displayDataSource(m))+'
DB verbunden
'+(m.databaseConnected===true?'ja':(m.databaseConnected===false?'nein':'unbekannt'))+'
Letztes Update
'+fmtDate(m.lastUpdate)+'
';h+=renderPlan('Unload',ul);h+=renderPlan('Update',uo);h+=renderPlan('Unload & Update',cp);h+='

Upgrade

Bezeichnung
Modulaktualisierung
verfügbar
'+(ug.available?badge('ja','ok'):badge('nein','warn'))+'
Upgradebedarf
'+(m.needsUpgrade===true?badge('laut /etl/list ja','warn'):badge('laut /etl/list nein','neutral'))+'
Start
'+code(ug.endpoint)+'
technischer Job
'+(ug.job&&ug.job.id?code(ug.job.id):'nicht gefunden / nicht benötigt')+'
Erklärung
'+esc(ug.reason)+'
';h+='

Technische Jobs laut REST-Schnittstelle

';if(jobErr(m)){h+='
Jobliste konnte nicht geladen werden: '+esc(jobErr(m))+'
';}else if(arr.length===0){h+='
Für dieses Modul wurden keine technischen Jobs zurückgeliefert.
';}else{h+='';for(var i=0;i';}h+='
Job-IDNameTyp
'+code(arr[i].id||'-')+''+esc(arr[i].name||'-')+''+esc(arr[i].type||'-')+'
';}h+='
JSON dieses Moduls anzeigen
'+esc(JSON.stringify(m,null,2))+'
Komplette JSON-Liste aus /etl/list anzeigen
'+esc(JSON.stringify(modules,null,2))+'
JSON der technischen Jobs dieses Moduls anzeigen
'+esc(JSON.stringify(arr,null,2))+'
';el.detailsBody.innerHTML=h;el.detailsPanel.classList.remove('hidden');el.detailsPanel.scrollIntoView({behavior:'smooth',block:'start'});} -function loadModules(){hideMsg();el.moduleTbody.innerHTML='Module werden geladen...';el.moduleCount.textContent='';return fetchJson(API_BASE+'/list').then(function(data){if(!Array.isArray(data)){throw new Error('Unerwartete Antwort von /etl/list');}modules=data;jobsByComponent={};jobErrorsByComponent={};renderModules();renderVersionDiagnostics();return loadAllJobs().then(function(){renderModules();renderVersionDiagnostics();msg('Module und Jobinformationen wurden geladen.','ok');});}).catch(function(e){modules=[];jobsByComponent={};jobErrorsByComponent={};el.moduleTbody.innerHTML='Module konnten nicht geladen werden.';msg(e.message||String(e),'error');});} +function showDetails(m){if(!m){return;}var abbr=key(m),arr=jobs(m),vi=versionInfo(m),cp=completePlan(m),ul=unloadPlan(m),uo=updateOnlyPlan(m),ug=upgradePlan(m),h='';el.detailsTitle.textContent='Details: '+(m.name||abbr);h+='

Modul

Name
'+esc(m.name||'-')+'
Kürzel
'+code(abbr||'-')+'
Systeminfo-ID
'+esc(m.systeminfoId||'-')+'
Installiert
'+(m.installed===true?'ja':'nein')+'
Installierte Version
'+versionValue(vi.installed)+'
Verfügbare Version
'+versionValue(vi.target)+'
Datenquelle
'+esc(displayDataSource(m))+'
DB verbunden
'+(m.databaseConnected===true?'ja':(m.databaseConnected===false?'nein':'unbekannt'))+'
Letztes Update
'+fmtDate(m.lastUpdate)+'
';h+=renderPlan('Unload',ul);h+=renderPlan('Update',uo);h+=renderPlan('Unload & Update',cp);var iuLabel=ug.actionLabel||'Upgrade';h+='

'+esc(iuLabel)+'

Bezeichnung
'+(m.installed===true?'Modulaktualisierung':'Modulinstallation')+'
verfügbar
'+(ug.available?badge('ja','ok'):badge('nein','warn'))+'
Upgradebedarf
'+(m.installed===true?(m.needsUpgrade===true?badge('laut /etl/list ja','warn'):badge('laut /etl/list nein','neutral')):'nicht installiert')+'
Start
'+code(ug.endpoint)+'
technischer Job
'+(ug.job&&ug.job.id?code(ug.job.id):'nicht gefunden / nicht benötigt')+'
Erklärung
'+esc(ug.reason)+'
';h+='

Technische Jobs laut REST-Schnittstelle

';if(jobErr(m)){h+='
Jobliste konnte nicht geladen werden: '+esc(jobErr(m))+'
';}else if(arr.length===0){h+='
Für dieses Modul wurden keine technischen Jobs zurückgeliefert.
';}else{h+='';for(var i=0;i';}h+='
Job-IDNameTyp
'+code(arr[i].id||'-')+''+esc(arr[i].name||'-')+''+esc(arr[i].type||'-')+'
';}h+='
JSON dieses Moduls anzeigen
'+esc(JSON.stringify(m,null,2))+'
Komplette JSON-Liste aus /etl/list anzeigen
'+esc(JSON.stringify(modules,null,2))+'
JSON der technischen Jobs dieses Moduls anzeigen
'+esc(JSON.stringify(arr,null,2))+'
';el.detailsBody.innerHTML=h;el.detailsPanel.classList.remove('hidden');el.detailsPanel.scrollIntoView({behavior:'smooth',block:'start'});} +function loadModules(){hideMsg();el.moduleTbody.innerHTML='Module werden geladen...';el.moduleCount.textContent='';var installedPromise=fetchJson(API_BASE+'/list');var installablesPromise=fetchJson(API_BASE+'/installables/list').catch(function(e){appendLog('Hinweis: /installables/list konnte nicht geladen werden: '+(e.message||String(e)));return [];});return Promise.all([installedPromise,installablesPromise]).then(function(results){var data=results[0],installables=results[1];if(!Array.isArray(data)){throw new Error('Unerwartete Antwort von /etl/list');}if(!Array.isArray(installables)){installables=[];}modules=mergeModuleLists(data,installables);jobsByComponent={};jobErrorsByComponent={};renderModules();renderVersionDiagnostics();return loadAllJobs().then(function(){renderModules();renderVersionDiagnostics();msg('Module und Jobinformationen wurden geladen.','ok');});}).catch(function(e){modules=[];jobsByComponent={};jobErrorsByComponent={};el.moduleTbody.innerHTML='Module konnten nicht geladen werden.';msg(e.message||String(e),'error');});} function loadAllJobs(){var ps=[];for(var i=0;i=0&&label.indexOf('/jobLog/')>=0){return 'Hinweis: Bei /jobLog/{id} war eine fehlende oder unvollständige Tabelle job_log eine bekannte Ursache. Prüfen Sie den Bereich „Datenbank / job_log“.';}if(t.indexOf('HTTP 500')>=0&&label.indexOf('/job/list/')>=0){return 'Hinweis: Bei /job/list/{modul} können fehlende Moduldateien, ein falscher aktiver Webapp-Kontext oder fehlende JVM-Optionen mögliche Ursachen sein.';}if(t.indexOf('HTTP 404')>=0){return 'Hinweis: 404 deutet häufig auf einen falschen Context-Pfad, falschen Port/Tunnel oder eine andere aktive Webapp hin.';}if(t.indexOf('Failed to fetch')>=0||t.indexOf('NetworkError')>=0){return 'Hinweis: Browser konnte den Endpunkt nicht erreichen. Tunnel, Port, Context-Pfad oder Anmeldung prüfen.';}return 'Hinweis: Fehlerdetails im Tomcat-Log prüfen. Beispiel-Kommandos stehen unten im Diagnosebereich.';} function diagRow(label,state,detail,hint){var type=state==='ok'?'ok':(state==='error'?'error':(state==='skip'?'info':'warn'));return '
'+code(label)+'
'+badge(state==='ok'?'ok':(state==='skip'?'übersprungen':(state==='error'?'Fehler':'Hinweis')),type)+'
'+esc(detail||'')+(hint?'
'+esc(hint)+'
':'')+'
';} -function runDiagnostics(){renderVersionDiagnostics();if(!el.diagnosticsRest){return;}el.diagnosticsRest.innerHTML='
REST-Schnittstellen werden geprüft...
';var checks=[];checks.push({label:'/etl/list',url:API_BASE+'/list'});checks.push({label:'/running',url:API_BASE+'/running'});for(var i=0;i=checks.length){el.diagnosticsRest.innerHTML=results.join('');return Promise.resolve();}var c=checks[idx];if(c.skip){results.push(diagRow(c.label,'skip',c.detail,''));el.diagnosticsRest.innerHTML=results.join('');return next(idx+1);}return fetchText(c.url).then(function(t){var detail='erreichbar';if(t&&t.length){detail+='; Antwortlänge '+t.length+' Zeichen';}results.push(diagRow(c.label,'ok',detail,''));el.diagnosticsRest.innerHTML=results.join('');}).catch(function(e){var text=e.message||String(e);results.push(diagRow(c.label,'error',text,restHint(c.label,text)));el.diagnosticsRest.innerHTML=results.join('');}).then(function(){return next(idx+1);});}return next(0);} +function runDiagnostics(){renderVersionDiagnostics();if(!el.diagnosticsRest){return;}el.diagnosticsRest.innerHTML='
REST-Schnittstellen werden geprüft...
';var checks=[];checks.push({label:'/etl/list',url:API_BASE+'/list'});checks.push({label:'/etl/installables/list',url:API_BASE+'/installables/list'});checks.push({label:'/running',url:API_BASE+'/running'});for(var i=0;i=checks.length){el.diagnosticsRest.innerHTML=results.join('');return Promise.resolve();}var c=checks[idx];if(c.skip){results.push(diagRow(c.label,'skip',c.detail,''));el.diagnosticsRest.innerHTML=results.join('');return next(idx+1);}return fetchText(c.url).then(function(t){var detail='erreichbar';if(t&&t.length){detail+='; Antwortlänge '+t.length+' Zeichen';}results.push(diagRow(c.label,'ok',detail,''));el.diagnosticsRest.innerHTML=results.join('');}).catch(function(e){var text=e.message||String(e);results.push(diagRow(c.label,'error',text,restHint(c.label,text)));el.diagnosticsRest.innerHTML=results.join('');}).then(function(){return next(idx+1);});}return next(0);} function copyFromElement(id){var node=document.getElementById(id);if(!node){return;}var text=node.value!==undefined?node.value:node.textContent;if(navigator.clipboard&&navigator.clipboard.writeText){navigator.clipboard.writeText(text).then(function(){msg('Text wurde in die Zwischenablage kopiert.','ok');}).catch(function(){node.focus();if(node.select){node.select();}msg('Text markieren und manuell kopieren.','warn');});}else{node.focus();if(node.select){node.select();}msg('Text markieren und manuell kopieren.','warn');}} -function startPlan(m,planFn,label){if(!m){return;}var p=planFn(m);if(!p.available){msg(label+' ist nicht verfügbar: '+p.reason,'error');return;}startJob(API_BASE+p.endpoint,label+' '+(m.name||key(m))+' ('+p.job.id+')');} -function startUpgrade(m){if(!m){return;}var p=upgradePlan(m);if(!p.available){msg('Upgrade ist nicht verfügbar: '+p.reason,'error');return;}var abbr=key(m);var text='Upgrade starten?\n\n'+(m.name||abbr)+'\n\nHinweis: '+(m.needsUpgrade===true?'Upgradebedarf erkannt.':'Aktuell wird kein Upgradebedarf gemeldet. Das Upgrade wird bewusst erneut ausgeführt.')+'\n\nInstallierte Version: '+(p.versionInfo.installed||'nicht geliefert')+'\nVerfügbare Version: '+(p.versionInfo.target||'nicht geliefert');if(!confirm(text)){return;}startJob(API_BASE+'/job/upgrade/'+encodeURIComponent(abbr),'Upgrade '+(m.name||abbr));} -function startJob(url,label){hideMsg();setLog('', 'Neuer Lauf wird gestartet.');appendLog('Starte: '+label);appendLog(url);fetchJson(url).then(function(result){var id=parseId(result);if(id===-1){msg('Der Server hat -1 zurückgeliefert. Es wurde kein neuer Job gestartet. Vermutlich läuft bereits ein anderer Job.','error');appendLog('Start nicht angenommen: -1');return checkRunning(true);}if(id===null){msg('Startantwort konnte nicht als JobExecutionId interpretiert werden.','error');appendLog('Startantwort: '+stringify(result));return;}currentExecutionId=id;currentJobLabel=label;logFailureByExecutionId[id]=false;setLog('Job gestartet. Log wird nach Abschluss automatisch geladen oder kann über „Log laden“ abgefragt werden.','JobExecutionId '+id);updateRun('gestartet');el.loadLogBtn.disabled=false;el.stopRunBtn.disabled=false;msg('Job gestartet. JobExecutionId: '+id,'ok');startPolling();}).catch(function(e){msg(e.message||String(e),'error');appendLog('Fehler beim Start: '+(e.message||String(e)));});}function parseId(r){if(typeof r==='number'){return r;}if(typeof r==='string'){var s=r.trim();if(/^-?\d+$/.test(s)){return parseInt(s,10);}try{return parseId(JSON.parse(s));}catch(e){return null;}}if(r&&typeof r==='object'){var keys=['jobExecutionId','id','executionId'];for(var i=0;i0&&runningId!==startId){appendLog('Hinweis: /running meldet laufende JobExecutionId '+runningId+' statt Startantwort '+startId+'. Verwende '+runningId+' für Status und Log.');currentExecutionId=runningId;}if(data&&typeof data==='object'){updateKnownIds(data);if(data.jobName){currentJobLabel=data.jobName;}else if(data.name){currentJobLabel=data.name;}}updateRun('gestartet');return Promise.resolve();}).catch(function(e){appendLog('Hinweis: /running konnte nach dem Start nicht zur ID-Prüfung gelesen werden: '+(e.message||String(e)));return Promise.resolve();});} +function parseId(r){if(typeof r==='number'){return r;}if(typeof r==='string'){var s=r.trim();if(/^-?\d+$/.test(s)){return parseInt(s,10);}try{return parseId(JSON.parse(s));}catch(e){return null;}}if(r&&typeof r==='object'){var keys=['jobExecutionId','id','executionId'];for(var i=0;i0)?id:null;} +function fieldId(o,keys){if(!o||typeof o!=='object'){return null;}for(var i=0;i=0){return 'Abgeschlossen';}if(u.indexOf('FAILED')>=0){return 'Fehlgeschlagen';}if(u.indexOf('STOPPED')>=0){return 'Gestoppt';}if(u.indexOf('ABANDONED')>=0){return 'Abgebrochen';}if(isUnknownStatus(raw)){return 'Läuft';}if(u.indexOf('RUNNING')>=0||u.indexOf('STARTED')>=0||u.indexOf('STARTING')>=0||u.indexOf('ANLAUF')>=0||u.indexOf('ANLAUEN')>=0){return 'Läuft';}return raw;} function doneStatus(s){s=String(s||'').toUpperCase();return s.indexOf('COMPLETED')>=0||s.indexOf('FAILED')>=0||s.indexOf('STOPPED')>=0||s.indexOf('ABANDONED')>=0;} -function renderStatus(data){var s=statusOf(data);el.runStatus.textContent=s||stringify(data).substring(0,300);el.runId.textContent=currentExecutionId||'-';el.runJob.textContent=currentJobLabel||'-';var p=progress(data);if(el.progressBar.tagName&&el.progressBar.tagName.toLowerCase()==='progress'){el.progressBar.value=p.percent;el.progressBar.textContent=p.percent+'%';}else{el.progressBar.style.width=p.percent+'%';}el.progressText.textContent=p.text;if(doneStatus(s)){el.stopRunBtn.disabled=true;}}function progress(d){var done=null,total=null;if(d&&typeof d==='object'){var dk=['executedStepsCount','completedStepsCount','executedSteps','stepsExecuted','writeCount'],tk=['totalStepsCount','countTotalSteps','totalSteps','stepCount'];for(var i=0;i0&&done!==null){var pc=Math.max(0,Math.min(100,Math.round(done*100/total)));return {percent:pc,text:done+' von '+total+' Schritten ('+pc+'%)'};}var s=statusOf(d).toUpperCase();if(s.indexOf('COMPLETED')>=0){return {percent:100,text:'abgeschlossen'};}if(s.indexOf('START')>=0||s.indexOf('RUNNING')>=0){return {percent:35,text:'läuft, Detailfortschritt nicht verfügbar'};}return {percent:0,text:'kein Fortschritt verfügbar'};} -function loadLog(userRequested){if(!currentExecutionId){return Promise.resolve();}var id=currentExecutionId;if(logFailureByExecutionId[id]&&userRequested!==true){return Promise.resolve();}el.logHint.textContent='Log wird geladen...';return fetchJson(API_BASE+'/jobLog/'+encodeURIComponent(id)).then(function(data){logFailureByExecutionId[id]=false;var t=extractLogText(data);if(t&&t.trim()){setLog(t, extractLogLabel(data,id));}else{setLog('(Der Log-Endpunkt hat keinen Logtext geliefert.)', extractLogLabel(data,id));}}).catch(function(e){var text=e.message||String(e);if(userRequested!==true&&!logFailureByExecutionId[id]){logFailureByExecutionId[id]=true;el.logHint.textContent='Log noch nicht verfügbar. Automatischer zweiter Versuch folgt.';return new Promise(function(resolve){setTimeout(resolve,3000);}).then(function(){logFailureByExecutionId[id]=false;return loadLog(true);});}logFailureByExecutionId[id]=true;var hint='Log für JobExecutionId '+id+' ist über /jobLog/'+id+' nicht verfügbar.';el.logHint.textContent='Log nicht verfügbar.';if(userRequested===true){appendLog(hint);appendLog(text);appendLog('Hinweis: Prüfen Sie über Diagnose die REST-Schnittstelle /jobLog/{id} und die Tabelle job_log.');}else{appendLog(hint+' Der Laufstatus wurde trotzdem abgefragt; vermutlich liefert der Server für diesen Log-Endpunkt HTTP 500.');}return Promise.resolve();});}function checkRunning(verbose){return fetchJson(API_BASE+'/running').then(function(data){var id=parseId(data);if(id&&id>0){if(verbose){appendLog('Antwort /running: '+stringify(data));}currentExecutionId=id;currentJobLabel=(data&&data.jobName)?data.jobName:'laufender Job';logFailureByExecutionId[id]=false;el.loadLogBtn.disabled=false;el.stopRunBtn.disabled=false;updateRun('laufender Job gefunden');startPolling();}else{if(verbose){appendLog('Kein laufender Job laut /running.');}if(!currentExecutionId){el.runStatus.textContent='Kein aktiver Lauf bekannt.';el.runId.textContent='-';el.runJob.textContent='-';if(el.progressBar.tagName&&el.progressBar.tagName.toLowerCase()==='progress'){el.progressBar.value=0;}else{el.progressBar.style.width='0%';}el.progressText.textContent='-';}}}).catch(function(e){appendLog('Running-Status konnte nicht gelesen werden: '+(e.message||String(e)));});}function stopRun(){if(!currentExecutionId){return;}if(!confirm('Aktuellen Job stoppen?\n\nJobExecutionId: '+currentExecutionId)){return;}fetchJson(API_BASE+'/stop/'+encodeURIComponent(currentExecutionId)).then(function(data){appendLog('Stop-Antwort: '+stringify(data));pollStatus();}).catch(function(e){msg('Job konnte nicht gestoppt werden: '+(e.message||String(e)),'error');});} +function renderStatus(data){var s=statusOf(data);el.runStatus.textContent=displayRunStatus(s)||stringify(data).substring(0,300);el.runId.textContent=currentExecutionId||'-';el.runJob.textContent=currentJobLabel||'-';var p=progress(data);if(el.progressBar.tagName&&el.progressBar.tagName.toLowerCase()==='progress'){el.progressBar.value=p.percent;el.progressBar.textContent=p.percent+'%';}else{el.progressBar.style.width=p.percent+'%';}el.progressText.textContent=p.text;if(doneStatus(s)){el.stopRunBtn.disabled=true;}}function progress(d){var done=null,total=null;if(d&&typeof d==='object'){var dk=['executedStepsCount','completedStepsCount','executedSteps','stepsExecuted','writeCount'],tk=['totalStepsCount','countTotalSteps','totalSteps','stepCount'];for(var i=0;i0&&done!==null){var pc=Math.max(0,Math.min(100,Math.round(done*100/total)));return {percent:pc,text:done+' von '+total+' Schritten ('+pc+'%)'};}var s=statusOf(d).toUpperCase();if(s.indexOf('COMPLETED')>=0){return {percent:100,text:'abgeschlossen'};}if(isUnknownStatus(s)||s.indexOf('START')>=0||s.indexOf('RUNNING')>=0){return {percent:35,text:'läuft, Detailfortschritt noch nicht verfügbar'};}return {percent:0,text:'kein Fortschritt verfügbar'};} +function loadLog(userRequested){if(!currentExecutionId&&!currentLogId){return Promise.resolve();}var candidates=logIdCandidates();if(candidates.length===0){return Promise.resolve();}var failureKey=candidates.join(',');if(logFailureByExecutionId[failureKey]&&userRequested!==true){return Promise.resolve();}el.logHint.textContent='Log wird geladen...';function tryCandidate(pos,errors){if(pos>=candidates.length){var text=errors.join('\n');logFailureByExecutionId[failureKey]=true;var hint='Log konnte für die bekannten IDs '+candidates.join(', ')+' nicht geladen werden.';el.logHint.textContent='Log nicht verfügbar.';if(userRequested===true){appendLog(hint);appendLog(text);appendLog('Hinweis: Der Log-Endpunkt verwendet je nach Backendstand eventuell eine andere ID als /jobExecutionStatus. Die Diagnose kann die aktuell bekannten REST-Antworten sichtbar machen.');}else{appendLog(hint+' Der Laufstatus wurde trotzdem abgefragt.');}return Promise.resolve();}var id=candidates[pos];return fetchJson(API_BASE+'/jobLog/'+encodeURIComponent(id)).then(function(data){currentLogId=id;logFailureByExecutionId[failureKey]=false;var t=extractLogText(data);if(t&&t.trim()){setLog(t, extractLogLabel(data,id));}else{setLog('(Der Log-Endpunkt hat keinen Logtext geliefert.)', extractLogLabel(data,id));}}).catch(function(e){errors.push('/jobLog/'+id+': '+(e.message||String(e)));return tryCandidate(pos+1,errors);});} +return tryCandidate(0,[]);} +function checkRunning(verbose){return fetchJson(API_BASE+'/running').then(function(data){var id=parseId(data);if(id&&id>0){if(verbose){appendLog('Antwort /running: '+stringify(data));}currentExecutionId=id;updateKnownIds(data);currentJobLabel=(data&&data.jobName)?data.jobName:((data&&data.name)?data.name:'laufender Job');logFailureByExecutionId[id]=false;el.loadLogBtn.disabled=false;el.stopRunBtn.disabled=false;updateRun('laufender Job gefunden');startPolling();}else{if(verbose){appendLog('Kein laufender Job laut /running.');}if(!currentExecutionId){currentLogId=null;lastStatusPayload=null;el.runStatus.textContent='Kein aktiver Lauf bekannt.';el.runId.textContent='-';el.runJob.textContent='-';if(el.progressBar.tagName&&el.progressBar.tagName.toLowerCase()==='progress'){el.progressBar.value=0;}else{el.progressBar.style.width='0%';}el.progressText.textContent='-';}}}).catch(function(e){appendLog('Running-Status konnte nicht gelesen werden: '+(e.message||String(e)));});}function stopRun(){if(!currentExecutionId){return;}var body='
'+confirmRow('Aktion','Lauf stoppen','action')+confirmRow('JobExecutionId',currentExecutionId,'code-value')+'
Der laufende Job wird zum Stoppen angefordert.
';askConfirm('Aktuellen Job stoppen?',body,'Job stoppen').then(function(ok){if(!ok){return;}fetchJson(API_BASE+'/stop/'+encodeURIComponent(currentExecutionId)).then(function(data){appendLog('Stop-Antwort: '+stringify(data));pollStatus();}).catch(function(e){msg('Job konnte nicht gestoppt werden: '+(e.message||String(e)),'error');});});} el.reloadBtn.onclick=loadModules;el.searchInput.oninput=renderModules;el.filterSelect.onchange=renderModules;el.diagnosticsBtn.onclick=function(){el.diagnosticsPanel.classList.remove('hidden');runDiagnostics();el.diagnosticsPanel.scrollIntoView({behavior:'smooth',block:'start'});};el.refreshDiagnosticsBtn.onclick=runDiagnostics;el.closeDiagnosticsBtn.onclick=function(){el.diagnosticsPanel.classList.add('hidden');};document.addEventListener('click',function(ev){var t=ev.target;if(t&&t.classList&&t.classList.contains('js-copy-text')){copyFromElement(t.getAttribute('data-copy-target'));}});el.closeDetailsBtn.onclick=function(){el.detailsPanel.classList.add('hidden');};el.refreshRunBtn.onclick=function(){if(currentExecutionId){pollStatus();}else{checkRunning(false);}};el.stopRunBtn.onclick=stopRun;el.loadLogBtn.onclick=function(){loadLog(true);};el.clearLogBtn.onclick=function(){setLog('','Log geleert.');}; loadModules().then(function(){checkRunning(false);}); })(); diff --git a/superx/xml/nd_templates.xsl b/superx/xml/nd_templates.xsl index 7871ade..acea033 100644 --- a/superx/xml/nd_templates.xsl +++ b/superx/xml/nd_templates.xsl @@ -473,7 +473,7 @@ $( "#content" ).load('/superx/xml/welcome_wiki.jsp',ajaxErrorHandler);