|
261 | 261 | color: var(--muted); font-size: 0.95em; |
262 | 262 | } |
263 | 263 |
|
| 264 | + /* ── Export Modal ── */ |
| 265 | + .modal-overlay { |
| 266 | + position: fixed; inset: 0; background: var(--overlay); |
| 267 | + z-index: 200; display: none; justify-content: center; align-items: center; |
| 268 | + } |
| 269 | + .modal-overlay.open { display: flex; } |
| 270 | + .modal { |
| 271 | + background: var(--surface); border-radius: 10px; |
| 272 | + padding: 20px; max-width: 720px; width: 90%; max-height: 85vh; |
| 273 | + display: flex; flex-direction: column; |
| 274 | + border: 1px solid var(--input-border); |
| 275 | + box-shadow: 0 12px 40px rgba(0,0,0,0.4); |
| 276 | + } |
| 277 | + .modal-header { |
| 278 | + display: flex; justify-content: space-between; align-items: center; |
| 279 | + margin-bottom: 8px; |
| 280 | + } |
| 281 | + .modal-header h2 { font-size: 1.1em; color: var(--accent); margin: 0; } |
| 282 | + .modal-close { |
| 283 | + background: none; border: none; color: var(--muted); |
| 284 | + font-size: 1.4em; cursor: pointer; line-height: 1; |
| 285 | + } |
| 286 | + .modal-close:hover { color: var(--text); } |
| 287 | + .modal-hint { font-size: 0.85em; color: var(--muted); margin-bottom: 12px; } |
| 288 | + .modal-body { |
| 289 | + flex: 1; overflow-y: auto; margin-bottom: 12px; |
| 290 | + } |
| 291 | + .modal-body textarea { |
| 292 | + width: 100%; min-height: 300px; background: var(--bg); |
| 293 | + color: var(--text); border: 1px solid var(--input-border); |
| 294 | + border-radius: 6px; padding: 12px; font-size: 0.82em; |
| 295 | + font-family: 'Consolas', 'Monaco', monospace; resize: vertical; |
| 296 | + } |
| 297 | + .modal-footer { display: flex; gap: 10px; justify-content: flex-end; } |
| 298 | + .modal-footer .btn { |
| 299 | + display: inline-block; padding: 8px 20px; border: none; |
| 300 | + border-radius: 4px; cursor: pointer; font-size: 0.9em; |
| 301 | + font-family: inherit; font-weight: bold; |
| 302 | + } |
| 303 | + .btn-accent { background: var(--accent); color: #000; } |
| 304 | + .btn-accent:hover { filter: brightness(1.15); } |
| 305 | + .btn-muted { |
| 306 | + background: var(--card); color: var(--text); |
| 307 | + border: 1px solid var(--input-border); |
| 308 | + } |
| 309 | + .btn-muted:hover { background: var(--accent); color: #000; } |
| 310 | + |
264 | 311 | /* ── Responsive ── */ |
265 | 312 | @media (max-width: 900px) { .charts-grid { grid-template-columns: 1fr; } } |
266 | 313 | @media (max-width: 600px) { |
|
302 | 349 | <a class="sidebar-link" href="/settings"> |
303 | 350 | <span class="icon">⚙</span> {{ t.settings }} |
304 | 351 | </a> |
| 352 | + <a class="sidebar-link" id="export-link" onclick="exportForLLM()"> |
| 353 | + <span class="icon">📄</span> {{ t.export_llm }} |
| 354 | + </a> |
305 | 355 | <div class="sidebar-divider"></div> |
306 | 356 | <details class="sidebar-ref"> |
307 | 357 | <summary>{{ t.reference_values }}</summary> |
@@ -504,6 +554,24 @@ <h2 class="section-title">{{ t.upstream }} ({{ us|length }} {{ t.channels }})</h |
504 | 554 | </div> |
505 | 555 | </div><!-- /main-content --> |
506 | 556 |
|
| 557 | +<!-- Export Modal --> |
| 558 | +<div class="modal-overlay" id="export-modal"> |
| 559 | + <div class="modal"> |
| 560 | + <div class="modal-header"> |
| 561 | + <h2>{{ t.export_title }}</h2> |
| 562 | + <button class="modal-close" onclick="closeExportModal()">×</button> |
| 563 | + </div> |
| 564 | + <p class="modal-hint">{{ t.export_hint }}</p> |
| 565 | + <div class="modal-body"> |
| 566 | + <textarea id="export-text" readonly></textarea> |
| 567 | + </div> |
| 568 | + <div class="modal-footer"> |
| 569 | + <button class="btn btn-muted" onclick="closeExportModal()">{{ t.close }}</button> |
| 570 | + <button class="btn btn-accent" id="export-copy-btn" onclick="copyExport()">{{ t.copy_clipboard }}</button> |
| 571 | + </div> |
| 572 | + </div> |
| 573 | +</div> |
| 574 | + |
507 | 575 | <script src="https://cdn.jsdelivr.net/npm/chart.js@4/dist/chart.umd.min.js"></script> |
508 | 576 | <script> |
509 | 577 | (function() { |
@@ -829,6 +897,44 @@ <h2 class="section-title">{{ t.upstream }} ({{ us|length }} {{ t.channels }})</h |
829 | 897 | /* ── Init ── */ |
830 | 898 | updateDateLabel(); |
831 | 899 | })(); |
| 900 | + |
| 901 | +/* ── Export for LLM ── */ |
| 902 | +function exportForLLM() { |
| 903 | + var T = {{ t|tojson }}; |
| 904 | + var modal = document.getElementById('export-modal'); |
| 905 | + var textarea = document.getElementById('export-text'); |
| 906 | + var sidebar = document.getElementById('sidebar'); |
| 907 | + var overlay = document.getElementById('sidebar-overlay'); |
| 908 | + sidebar.classList.remove('open'); |
| 909 | + overlay.classList.remove('open'); |
| 910 | + textarea.value = T.export_no_data; |
| 911 | + modal.classList.add('open'); |
| 912 | + fetch('/api/export') |
| 913 | + .then(function(r) { return r.json(); }) |
| 914 | + .then(function(data) { |
| 915 | + if (data.text) { |
| 916 | + textarea.value = data.text; |
| 917 | + } else if (data.error) { |
| 918 | + textarea.value = data.error; |
| 919 | + } |
| 920 | + }) |
| 921 | + .catch(function() { |
| 922 | + textarea.value = 'Error loading export data.'; |
| 923 | + }); |
| 924 | +} |
| 925 | +function closeExportModal() { |
| 926 | + document.getElementById('export-modal').classList.remove('open'); |
| 927 | +} |
| 928 | +function copyExport() { |
| 929 | + var T = {{ t|tojson }}; |
| 930 | + var textarea = document.getElementById('export-text'); |
| 931 | + var btn = document.getElementById('export-copy-btn'); |
| 932 | + textarea.select(); |
| 933 | + navigator.clipboard.writeText(textarea.value).then(function() { |
| 934 | + btn.textContent = T.copied; |
| 935 | + setTimeout(function() { btn.textContent = T.copy_clipboard; }, 2000); |
| 936 | + }); |
| 937 | +} |
832 | 938 | </script> |
833 | 939 |
|
834 | 940 | </body> |
|
0 commit comments