mirror of
https://github.com/Dvorinka/MyClubServer.git
synced 2026-06-04 18:52:56 +00:00
dev day #99
This commit is contained in:
+31
-19
@@ -20,7 +20,7 @@
|
||||
.btn.primary{background:var(--primary);border-color:var(--primary);color:#fff}
|
||||
.btn.ghost{background:transparent}
|
||||
main{padding:16px}
|
||||
.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(460px,1fr));gap:16px}
|
||||
.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(640px,1fr));gap:16px}
|
||||
.card{background:var(--panel);border:1px solid var(--border);border-radius:12px;overflow:hidden;display:flex;flex-direction:column}
|
||||
.card header{display:flex;align-items:center;gap:8px;justify-content:space-between;background:#0f131f;border-bottom:1px solid var(--border);padding:10px 12px;position:static}
|
||||
.title{display:flex;flex-direction:column;gap:4px}
|
||||
@@ -39,14 +39,15 @@
|
||||
</style>
|
||||
<script src="https://cdn.jsdelivr.net/npm/mermaid@10.9.1/dist/mermaid.min.js"></script>
|
||||
<script>
|
||||
mermaid.initialize({ startOnLoad:false, securityLevel:'loose', theme:'dark', flowchart:{ curve:'basis', useMaxWidth:true } });
|
||||
mermaid.initialize({ startOnLoad:false, securityLevel:'loose', theme:'dark', flowchart:{ curve:'linear', useMaxWidth:true } });
|
||||
|
||||
async function renderMermaidFile(mmdPath, container){
|
||||
try{
|
||||
container.innerHTML = '<div style="padding:16px;color:#9aa3b2">Loading '+mmdPath+'…</div>';
|
||||
const res = await fetch(mmdPath, { cache: 'no-store' });
|
||||
const res = await fetch(mmdPath + '?v=' + Date.now(), { cache: 'no-store' });
|
||||
if(!res.ok) throw new Error('Failed to load '+mmdPath+': '+res.status);
|
||||
const code = await res.text();
|
||||
const raw = await res.text();
|
||||
const code = raw.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
|
||||
const id = 'm-'+Math.random().toString(36).slice(2);
|
||||
const { svg } = await mermaid.render(id, code);
|
||||
container.innerHTML = svg;
|
||||
@@ -82,10 +83,13 @@
|
||||
if(!source.match(/^<svg[^>]+xmlns=/)) source = source.replace(/^<svg/, '<svg xmlns="http://www.w3.org/2000/svg"');
|
||||
source = '<?xml version="1.0" standalone="no"?>\n'+source;
|
||||
// Inject white background and readable styles for new tab view
|
||||
const firstGt = source.indexOf('>');
|
||||
if(firstGt > 0){
|
||||
const inject = '<rect width="100%" height="100%" fill="#ffffff"/><style>text{fill:#111827}.edgePath path,.flowchart-link{stroke:#334155}</style>';
|
||||
source = source.slice(0, firstGt+1) + inject + source.slice(firstGt+1);
|
||||
const svgStart = source.indexOf('<svg');
|
||||
if(svgStart !== -1){
|
||||
const svgTagEnd = source.indexOf('>', svgStart);
|
||||
if(svgTagEnd !== -1){
|
||||
const inject = '<rect width="100%" height="100%" fill="#ffffff"/><style>text{fill:#111827}.edgePath path,.flowchart-link{stroke:#334155}</style>';
|
||||
source = source.slice(0, svgTagEnd+1) + inject + source.slice(svgTagEnd+1);
|
||||
}
|
||||
}
|
||||
const blob = new Blob([source], { type:'image/svg+xml;charset=utf-8' });
|
||||
const url = URL.createObjectURL(blob);
|
||||
@@ -95,8 +99,7 @@
|
||||
|
||||
const ALL_DIAGRAMS = [
|
||||
// System & DB
|
||||
{ id:'system-clean', label:'System Overview (Clean)', file:'system-overall-clean.mmd', cat:'System', tags:['overview','recommended','big'] },
|
||||
{ id:'system', label:'System Overview (Classic)', file:'system-overall.mmd', cat:'System', tags:['overview','big'], defaultWires:'faint' },
|
||||
{ id:'system-clean', label:'System Overview', file:'system-overall-clean.mmd', cat:'System', tags:['overview','recommended','big'] },
|
||||
{ id:'db-er', label:'Database ER', file:'db-er.mmd', cat:'System', tags:['db'] },
|
||||
{ id:'db-models', label:'Database Models', file:'db-models.mmd', cat:'System', tags:['db'] },
|
||||
// Backend
|
||||
@@ -107,15 +110,13 @@
|
||||
{ id:'auth', label:'Auth Flow', file:'auth-flow.mmd', cat:'Backend', tags:['auth','flow'] },
|
||||
{ id:'err-flow', label:'Error Tracking Flow', file:'error-tracking-flow.mmd', cat:'Backend', tags:['errors','flow'] },
|
||||
// Frontend
|
||||
{ id:'fe-everything', label:'Frontend — Everything (Big)', file:'frontend-everything.mmd', cat:'Frontend', tags:['overview','big'], defaultWires:'faint' },
|
||||
{ id:'fe-overall', label:'Frontend — Overall', file:'frontend-overall.mmd', cat:'Frontend', tags:['architecture'] },
|
||||
{ id:'fe-everything', label:'Frontend — Everything (Big)', file:'frontend-everything.mmd', cat:'Frontend', tags:['overview','big','recommended'], defaultWires:'faint' },
|
||||
{ id:'fe-overall', label:'Frontend — Overall', file:'frontend-overall.mmd', cat:'Frontend', tags:['architecture','recommended'] },
|
||||
{ id:'fe-routes', label:'Frontend — Routes', file:'frontend-routes.mmd', cat:'Frontend', tags:['routes'] },
|
||||
{ id:'fe-home', label:'Frontend — Homepage', file:'frontend-homepage.mmd', cat:'Frontend', tags:['homepage'] },
|
||||
{ id:'fe-modules', label:'Frontend — Modules', file:'frontend-modules.mmd', cat:'Frontend', tags:['modules'] },
|
||||
{ id:'fe-arch', label:'Frontend — Provider Tree', file:'frontend-architecture.mmd', cat:'Frontend', tags:['providers'] },
|
||||
{ id:'fe-api', label:'Frontend — API Map', file:'frontend-api-map.mmd', cat:'Frontend', tags:['api'] },
|
||||
// Admin
|
||||
{ id:'admin-overall', label:'Admin — Overall', file:'admin-overall.mmd', cat:'Admin', tags:['admin','overview'], defaultWires:'faint' },
|
||||
{ id:'admin-overall', label:'Admin — Overall', file:'admin-overall.mmd', cat:'Admin', tags:['admin','overview','recommended'], defaultWires:'faint' },
|
||||
{ id:'scoreboard', label:'Scoreboard Flow', file:'scoreboard-flow.mmd', cat:'Admin', tags:['scoreboard','flow'] },
|
||||
{ id:'newsletter', label:'Newsletter Flow', file:'newsletter-flow.mmd', cat:'Admin', tags:['newsletter','flow'] },
|
||||
{ id:'comments', label:'Comments Flow', file:'comments-flow.mmd', cat:'Admin', tags:['comments','flow'] },
|
||||
@@ -145,7 +146,8 @@
|
||||
|
||||
const tb = document.createElement('div'); tb.className='toolbar';
|
||||
tb.innerHTML = `
|
||||
<label><input type="checkbox" class="fit" checked> Fit width</label>
|
||||
<label style="display:inline-flex;align-items:center;gap:8px"><input type="checkbox" class="fit" checked> Fit width</label>
|
||||
<label style="display:inline-flex;align-items:center;gap:6px">Zoom <input class="zoom" type="range" min="50" max="300" value="100" style="width:140px"></label>
|
||||
<a class="btn ghost src" href="${d.file}" target="_blank">Source</a>
|
||||
<span class="sp"></span>
|
||||
<button class="btn open">Open SVG in new tab</button>
|
||||
@@ -161,9 +163,17 @@
|
||||
const svg = container?.querySelector('svg');
|
||||
if(!svg) return;
|
||||
const fit = card.querySelector('.fit');
|
||||
if(fit && fit.checked){ svg.style.width='100%'; svg.style.height='auto'; } else { svg.style.width=''; svg.style.height=''; }
|
||||
svg.style.transformOrigin = '';
|
||||
svg.style.transform = '';
|
||||
const zoom = card.querySelector('.zoom');
|
||||
if(fit && fit.checked){
|
||||
svg.style.width='100%'; svg.style.height='auto';
|
||||
svg.style.transformOrigin = '';
|
||||
svg.style.transform = '';
|
||||
} else {
|
||||
svg.style.width=''; svg.style.height='';
|
||||
const z = Math.max(50, Math.min(300, parseInt(zoom?.value || '100', 10)));
|
||||
svg.style.transformOrigin = 'top left';
|
||||
svg.style.transform = 'scale('+(z/100)+')';
|
||||
}
|
||||
}
|
||||
|
||||
function wireCardControls(card, file){
|
||||
@@ -173,7 +183,9 @@
|
||||
const openBtn = card.querySelector('.open');
|
||||
const refresh = card.querySelector('.refresh');
|
||||
const download = card.querySelector('.download');
|
||||
const zoom = card.querySelector('.zoom');
|
||||
fit.addEventListener('change', () => applyFitZoomFor(card));
|
||||
zoom.addEventListener('input', () => applyFitZoomFor(card));
|
||||
openBtn.addEventListener('click', () => openSVGInNewTab(diag));
|
||||
refresh.addEventListener('click', async () => { diag.dataset.rendered=''; await renderMermaidFile(file, diag); diag.dataset.rendered='1'; applyFitZoomFor(card); });
|
||||
download.addEventListener('click', () => downloadSVGOf(diag, (file.replace('.mmd','')||'diagram')+'.svg'));
|
||||
|
||||
Reference in New Issue
Block a user