- werkzeuge/bootstrap/: Bootstrap 5.3.8 (CSS, JS-Bundle) und Bootstrap Icons 1.13.1 (CSS, woff2/woff) byte-gleich aus den npm-Paketen, Integrität geprüft; README mit Version, Quelle, Integrität, Lizenz und Aktualisierung; Lizenzen (MIT) daneben; .gitattributes: binary, die README bleibt Text mit Diff. - werkzeuge/stil/ag_prozesse.css: eigene kleine Stilschicht (ag-*): Seite in voller Höhe, dunkle Navigationsleiste, hellgrauer Hintergrund, Karten mit farbigem Rand, Tabellenziffern, Druck. Vorbild VLN_SN/EA-Bilanz, nichts übernommen. - Vorschau: Kopfzeile als dunkle Navigationsleiste mit Icon-Knöpfen; JavaScript, IDs und Zeichenfläche (Wasserzeichen) unverändert. - scripts/vorschau.py bettet Bootstrap, Icons und Stil ein und setzt die Icon-Schrift als data:-URI ein (_schriften_einbetten); ein nicht einbettbarer Schriftverweis bricht laut ab. - Tests: drei neue in test_vorschau.py; der Aufbau von test_bibliothek_mit_script_ende_wird_abgelehnt kopiert jetzt ganz werkzeuge/ (Erwartung unverändert). - AGENTS.md: eingebettete Fremdbibliotheken sind bpmn-js und Bootstrap. - Tests: python -m pytest -q -> 256 bestanden, 1 übersprungen. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
106 lines
5.1 KiB
HTML
106 lines
5.1 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="de" class="ag-seite">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<title>BPMN-Vorschau</title>
|
||
<!-- Bootstrap, Bootstrap Icons und bpmn-js (bpmn.io), lokal eingebettet – siehe README.md und
|
||
werkzeuge/bootstrap/README.md. Nichts wird aus dem Netz geladen. -->
|
||
<link rel="stylesheet" href="../bootstrap/bootstrap.min.css">
|
||
<link rel="stylesheet" href="../bootstrap/icons/bootstrap-icons.min.css">
|
||
<link rel="stylesheet" href="../stil/ag_prozesse.css">
|
||
<link rel="stylesheet" href="bpmn-js/diagram-js.css">
|
||
<link rel="stylesheet" href="bpmn-js/bpmn-js.css">
|
||
<style>
|
||
#meldung { margin: 0; padding: .25rem 1rem; border-bottom: 1px solid var(--bs-border-color); background: var(--bs-body-bg); }
|
||
#meldung:empty { display: none; }
|
||
#meldung.fehler { color: var(--bs-danger); }
|
||
#meldung.warnung { color: var(--bs-warning-text-emphasis); }
|
||
/* Zeichenfläche: das bpmn.io-Wasserzeichen unten rechts muss laut Lizenz sichtbar und unverdeckt bleiben. */
|
||
#flaeche { position: absolute; inset: 0; }
|
||
#hinweis {
|
||
position: absolute; inset: 24px 24px 64px 24px; display: flex; align-items: center; justify-content: center;
|
||
text-align: center; color: var(--bs-secondary-color); border: 2px dashed var(--bs-border-color);
|
||
border-radius: .75rem; padding: 1rem; pointer-events: none;
|
||
}
|
||
main.ziehen #hinweis { border-color: var(--ag-akzent); color: var(--ag-akzent); }
|
||
main.geladen #hinweis { display: none; }
|
||
</style>
|
||
</head>
|
||
<body class="ag-app">
|
||
<nav class="navbar navbar-dark bg-dark navbar-expand px-3 py-1 ag-nav">
|
||
<span class="navbar-brand mb-0"><i class="bi bi-diagram-3 me-1"></i>BPMN-Vorschau</span>
|
||
<span id="dateiname" class="text-secondary small text-truncate me-auto"></span>
|
||
<div class="btn-group btn-group-sm">
|
||
<label class="btn btn-outline-light" for="datei" title="Datei öffnen"><i class="bi bi-folder2-open"></i><span class="d-none d-md-inline"> Datei öffnen …</span></label>
|
||
<button type="button" class="btn btn-outline-light" id="einpassen" disabled title="Einpassen"><i class="bi bi-arrows-angle-contract"></i><span class="d-none d-md-inline"> Einpassen</span></button>
|
||
<button type="button" class="btn btn-outline-light" id="groesser" disabled title="Vergrößern"><i class="bi bi-zoom-in"></i></button>
|
||
<button type="button" class="btn btn-outline-light" id="kleiner" disabled title="Verkleinern"><i class="bi bi-zoom-out"></i></button>
|
||
</div>
|
||
<input type="file" id="datei" accept=".bpmn,.xml" hidden>
|
||
</nav>
|
||
<p id="meldung" role="status"></p>
|
||
<main id="bereich" class="ag-inhalt">
|
||
<div id="flaeche"></div>
|
||
<div id="hinweis">.bpmn-Datei hierher ziehen oder über „Datei öffnen …“ wählen.<br>
|
||
Die Datei wird nur in diesem Browser angezeigt und nirgendwohin übertragen.</div>
|
||
</main>
|
||
<script src="bpmn-js/bpmn-navigated-viewer.production.min.js"></script>
|
||
<script>
|
||
// Wird von scripts/vorschau.py durch den Inhalt einer .bpmn und ihren Namen ersetzt.
|
||
const EINGEBETTET = null;
|
||
const DATEINAME = null;
|
||
|
||
const bereich = document.getElementById('bereich');
|
||
const meldung = document.getElementById('meldung');
|
||
const knoepfe = ['einpassen', 'groesser', 'kleiner'].map(id => document.getElementById(id));
|
||
const viewer = new BpmnJS({ container: '#flaeche' });
|
||
const canvas = () => viewer.get('canvas');
|
||
|
||
function melde(text, art) {
|
||
meldung.textContent = text || '';
|
||
meldung.className = art || '';
|
||
}
|
||
|
||
async function zeige(xml, name) {
|
||
melde('');
|
||
try {
|
||
const { warnings } = await viewer.importXML(xml);
|
||
canvas().zoom('fit-viewport', 'auto');
|
||
bereich.classList.add('geladen');
|
||
knoepfe.forEach(k => { k.disabled = false; });
|
||
document.getElementById('dateiname').textContent = name || '';
|
||
document.title = name ? `${name} – BPMN-Vorschau` : 'BPMN-Vorschau';
|
||
if (warnings.length) {
|
||
melde(`${warnings.length} Warnung(en) beim Einlesen: ` + warnings.map(w => w.message).join(' | '), 'warnung');
|
||
}
|
||
} catch (fehler) {
|
||
bereich.classList.remove('geladen');
|
||
knoepfe.forEach(k => { k.disabled = true; });
|
||
melde(`Die Datei ${name || ''} lässt sich nicht als BPMN lesen: ${fehler.message}`, 'fehler');
|
||
}
|
||
}
|
||
|
||
function lies(datei) {
|
||
if (!datei) return;
|
||
datei.text().then(xml => zeige(xml, datei.name));
|
||
}
|
||
|
||
document.getElementById('datei').addEventListener('change', e => lies(e.target.files[0]));
|
||
document.getElementById('einpassen').addEventListener('click', () => canvas().zoom('fit-viewport', 'auto'));
|
||
document.getElementById('groesser').addEventListener('click', () => canvas().zoom(canvas().zoom() * 1.25));
|
||
document.getElementById('kleiner').addEventListener('click', () => canvas().zoom(canvas().zoom() / 1.25));
|
||
|
||
['dragenter', 'dragover'].forEach(art => document.addEventListener(art, e => {
|
||
e.preventDefault(); bereich.classList.add('ziehen');
|
||
}));
|
||
['dragleave', 'drop'].forEach(art => document.addEventListener(art, e => {
|
||
e.preventDefault(); bereich.classList.remove('ziehen');
|
||
}));
|
||
document.addEventListener('drop', e => lies(e.dataTransfer.files[0]));
|
||
|
||
if (EINGEBETTET) zeige(EINGEBETTET, DATEINAME);
|
||
</script>
|
||
</body>
|
||
</html>
|