""" Admin DSMS Component - DSMS/IPFS WebUI, Archive Management """ def get_admin_dsms_css() -> str: """CSS für DSMS zurückgeben""" return """ /* DSMS Styles */ .dsms-subtab { padding: 6px 14px; border: none; background: transparent; color: var(--bp-text-muted); cursor: pointer; font-size: 13px; border-radius: 4px; transition: all 0.2s ease; } .dsms-subtab:hover { background: var(--bp-border-subtle); color: var(--bp-text); } .dsms-subtab.active { background: var(--bp-primary); color: white; } .dsms-content { display: none; } .dsms-content.active { display: block; } .dsms-status-card { background: var(--bp-surface-elevated); border: 1px solid var(--bp-border); border-radius: 8px; padding: 16px; } .dsms-status-card h4 { margin: 0 0 8px 0; font-size: 12px; color: var(--bp-text-muted); text-transform: uppercase; letter-spacing: 0.05em; } .dsms-status-card .value { font-size: 24px; font-weight: 600; color: var(--bp-text); } .dsms-status-card .value.online { color: var(--bp-accent); } .dsms-status-card .value.offline { color: var(--bp-danger); } .dsms-verify-success { background: var(--bp-accent-soft); border: 1px solid var(--bp-accent); border-radius: 8px; padding: 16px; color: var(--bp-accent); } .dsms-verify-error { background: rgba(239, 68, 68, 0.1); border: 1px solid var(--bp-danger); border-radius: 8px; padding: 16px; color: var(--bp-danger); } /* DSMS WebUI Styles */ .dsms-webui-nav { display: flex; align-items: center; gap: 10px; padding: 10px 12px; border: none; background: transparent; color: var(--bp-text-muted); font-size: 14px; border-radius: 6px; cursor: pointer; text-align: left; width: 100%; transition: all 0.2s; } .dsms-webui-nav:hover { background: var(--bp-surface-elevated); color: var(--bp-text); } .dsms-webui-nav.active { background: var(--bp-primary-soft); color: var(--bp-primary); font-weight: 500; } .dsms-webui-section { display: none; } .dsms-webui-section.active { display: block; } .dsms-webui-stat-card { background: var(--bp-surface-elevated); border: 1px solid var(--bp-border); border-radius: 8px; padding: 16px; } .dsms-webui-stat-label { font-size: 12px; color: var(--bp-text-muted); margin-bottom: 4px; } .dsms-webui-stat-value { font-size: 18px; font-weight: 600; color: var(--bp-text); } .dsms-webui-stat-sub { font-size: 11px; color: var(--bp-text-muted); margin-top: 4px; } .dsms-webui-upload-zone { border: 2px dashed var(--bp-border); border-radius: 12px; padding: 48px 24px; background: var(--bp-input-bg); transition: all 0.2s; } .dsms-webui-upload-zone.dragover { border-color: var(--bp-primary); background: var(--bp-primary-soft); } .dsms-webui-file-item { display: flex; align-items: center; justify-content: space-between; padding: 12px 16px; background: var(--bp-surface-elevated); border: 1px solid var(--bp-border); border-radius: 8px; margin-bottom: 8px; } .dsms-webui-file-item .cid { font-family: monospace; font-size: 12px; color: var(--bp-text-muted); word-break: break-all; } .main-layout { display: grid; grid-template-columns: 240px minmax(0, 1fr); height: 100%; min-height: 0; } .sidebar { border-right: 1px solid var(--bp-border-subtle); background: var(--bp-gradient-sidebar); padding: 14px 10px; display: flex; flex-direction: column; gap: 18px; min-width: 0; overflow: hidden; transition: background 0.3s ease, border-color 0.3s ease; } .sidebar-section-title { font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.08em; color: var(--bp-text); padding: 8px 6px 6px 6px; margin-top: 12px; } .sidebar-menu { display: flex; flex-direction: column; gap: 4px; } .sidebar-item { display: flex; align-items: center; justify-content: space-between; padding: 8px 10px; border-radius: 9px; cursor: pointer; font-size: 13px; color: var(--bp-text-muted); } .sidebar-item.active { background: var(--bp-surface-elevated); color: var(--bp-accent); border: 1px solid var(--bp-accent-soft); } [data-theme="light"] .sidebar-item.active { background: var(--bp-primary-soft); color: var(--bp-primary); border: 1px solid var(--bp-primary); } .sidebar-item-label { display: flex; align-items: center; gap: 7px; } .sidebar-item-badge { font-size: 10px; border-radius: 999px; padding: 2px 7px; border: 1px solid var(--bp-border-subtle); } .sidebar-footer { margin-top: auto; font-size: 11px; color: var(--bp-text-muted); padding: 0 6px; } .content { padding: 14px 16px 16px 16px; display: flex; flex-direction: column; gap: 14px; height: 100%; min-height: 0; overflow: hidden; } .panel { background: var(--bp-gradient-surface); border-radius: 16px; border: 1px solid var(--bp-border-subtle); padding: 12px 14px; display: flex; flex-direction: column; min-height: 0; height: 100%; flex: 1; overflow: hidden; transition: background 0.3s ease, border-color 0.3s ease; } [data-theme="light"] .panel { box-shadow: 0 2px 12px rgba(0,0,0,0.08); } .panel-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; } .panel-title { font-size: 18px; font-weight: 700; color: var(--bp-text); margin-bottom: 4px; } .panel-subtitle { font-size: 12px; color: var(--bp-text-muted); line-height: 1.5; } .panel-body { flex: 1; min-height: 0; display: flex; flex-direction: column; gap: 8px; overflow: auto; } .small-pill { font-size: 11px; font-weight: 600; padding: 4px 10px; border-radius: 999px; border: 1px solid var(--bp-border-subtle); color: var(--bp-text); background: var(--bp-surface-elevated); } .upload-inline { display: flex; flex-direction: column; gap: 8px; padding: 10px; background: var(--bp-surface-elevated); border-radius: 8px; border: 1px solid var(--bp-border-subtle); } [data-theme="light"] .upload-inline { background: var(--bp-surface); box-shadow: inset 0 1px 3px rgba(0,0,0,0.05); } .upload-inline input[type=file] { font-size: 11px; padding: 6px; background: var(--bp-input-bg); border: 1px solid var(--bp-border-subtle); border-radius: 6px; color: var(--bp-text); cursor: pointer; } .upload-inline input[type=file]::file-selector-button { background: var(--bp-accent-soft); border: 1px solid var(--bp-accent); border-radius: 4px; padding: 4px 10px; color: var(--bp-accent); font-size: 10px; font-weight: 600; cursor: pointer; margin-right: 8px; } [data-theme="light"] .upload-inline input[type=file]::file-selector-button { background: var(--bp-primary-soft); border-color: var(--bp-primary); color: var(--bp-primary); } .upload-inline input[type=file]::file-selector-button:hover { opacity: 0.8; } .file-list { list-style: none; margin: 0; padding: 0; max-height: 150px; overflow-y: auto; border-radius: 10px; border: 1px solid var(--bp-border-subtle); background: var(--bp-surface-elevated); } [data-theme="light"] .file-list { border-color: var(--bp-primary); background: var(--bp-surface); } .file-item { font-size: 12px; padding: 8px 10px; cursor: pointer; display: flex; align-items: center; justify-content: space-between; gap: 8px; transition: background 0.15s ease; } .file-item:nth-child(odd) { background: var(--bp-surface-elevated); } [data-theme="light"] .file-item:nth-child(odd) { background: rgba(108, 27, 27, 0.03); } .file-item:hover { background: var(--bp-accent-soft); } [data-theme="light"] .file-item:hover { background: var(--bp-primary-soft); } .file-item.active { background: var(--bp-accent-soft); } .file-item-name { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; flex: 1; min-width: 0; } .file-item-delete { font-size: 14px; color: #f97316; cursor: pointer; padding: 4px 6px; border-radius: 4px; transition: all 0.15s ease; flex-shrink: 0; } .file-item-delete:hover { color: #fb923c; background: rgba(249,115,22,0.15); } .file-empty { font-size: 12px; color: var(--bp-text-muted); } .inline-process { display: flex; justify-content: flex-end; margin-top: 12px; padding-top: 12px; border-top: 1px solid rgba(148,163,184,0.2); } .preview-container { flex: 1; border-radius: 12px; border: 1px solid var(--bp-border-subtle); background: var(--bp-gradient-sidebar); overflow: hidden; display: flex; align-items: stretch; justify-content: center; position: relative; min-height: 750px; transition: all 0.3s ease; } [data-theme="light"] .preview-container { background: var(--bp-bg); border: 2px solid var(--bp-primary); box-shadow: 0 4px 20px rgba(108, 27, 27, 0.1); } .preview-placeholder { font-size: 13px; color: var(--bp-text-muted); display: flex; align-items: center; justify-content: center; text-align: center; padding: 20px; } .compare-wrapper { display: grid; grid-template-columns: minmax(0, 1fr) 110px minmax(0, 1fr); gap: 8px; width: 100%; height: 100%; position: relative; } .compare-section { position: relative; border-radius: 10px; border: 1px solid var(--bp-border-subtle); background: var(--bp-gradient-sidebar); display: flex; flex-direction: column; overflow: hidden; min-height: 0; transition: all 0.3s ease; } [data-theme="light"] .compare-section { border: 2px solid var(--bp-primary); box-shadow: 0 4px 20px rgba(108, 27, 27, 0.1); } .compare-header { padding: 6px 10px; font-size: 12px; border-bottom: 1px solid var(--bp-border-subtle); display: flex; justify-content: space-between; align-items: center; gap: 6px; } [data-theme="light"] .compare-header { background: var(--bp-primary-soft); border-bottom: 1px solid var(--bp-primary); } .compare-header span { color: var(--bp-text-muted); } [data-theme="light"] .compare-header span { color: var(--bp-primary); font-weight: 600; } .compare-body { flex: 1; min-height: 0; position: relative; display: flex; align-items: center; justify-content: center; padding: 6px; } .compare-body-inner { position: relative; width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; } .preview-img { max-width: 100%; max-height: 100%; object-fit: contain; box-shadow: 0 18px 40px rgba(0,0,0,0.5); border-radius: 10px; } [data-theme="light"] .preview-img { box-shadow: 0 8px 24px rgba(108, 27, 27, 0.15); } .clean-frame { width: 100%; height: 100%; border: none; border-radius: 10px; background: white; } .preview-nav { position: absolute; inset: 0; display: flex; align-items: center; justify-content: space-between; pointer-events: none; padding: 0 4px; } .preview-nav button { pointer-events: auto; width: 28px; height: 28px; border-radius: 999px; border: 1px solid var(--bp-border-subtle); background: var(--bp-surface-elevated); color: var(--bp-text); cursor: pointer; font-size: 14px; display: flex; align-items: center; justify-content: center; transition: all 0.2s ease; } [data-theme="light"] .preview-nav button { border: 2px solid var(--bp-primary); background: var(--bp-surface); color: var(--bp-primary); font-weight: 700; } .preview-nav button:hover:not(:disabled) { border-color: var(--bp-primary); color: var(--bp-primary); } [data-theme="light"] .preview-nav button:hover:not(:disabled) { background: var(--bp-primary); color: white; } .preview-nav button:disabled { opacity: 0.35; cursor: default; } .preview-nav span { position: absolute; bottom: 6px; left: 50%; transform: translateX(-50%); font-size: 11px; padding: 2px 8px; border-radius: 999px; background: var(--bp-surface-elevated); border: 1px solid var(--bp-border-subtle); } [data-theme="light"] .preview-nav span { background: var(--bp-surface); border: 1px solid var(--bp-primary); color: var(--bp-primary); } .preview-thumbnails { display: flex; flex-direction: column; gap: 8px; padding: 8px 4px; overflow-y: auto; align-items: center; } .preview-thumb { min-width: 90px; width: 90px; height: 70px; border-radius: 8px; border: 2px solid rgba(148,163,184,0.25); background: rgba(15,23,42,0.5); cursor: pointer; overflow: hidden; display: flex; align-items: center; justify-content: center; position: relative; flex-shrink: 0; } .preview-thumb:hover { border-color: var(--bp-accent); } .preview-thumb.active { border-color: var(--bp-accent); border-width: 3px; } .preview-thumb img { width: 100%; height: 100%; object-fit: cover; } .preview-thumb-label { position: absolute; bottom: 0; left: 0; right: 0; font-size: 9px; padding: 2px; background: rgba(0,0,0,0.8); color: white; text-align: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .pager { grid-column: 1 / -1; display: flex; align-items: center; justify-content: center; gap: 8px; padding: 2px 0; font-size: 11px; } .pager button { width: 24px; height: 24px; border-radius: 999px; border: 1px solid var(--bp-border-subtle); background: var(--bp-surface-elevated); color: var(--bp-text); cursor: pointer; transition: all 0.2s ease; } .pager button:hover { border-color: var(--bp-primary); color: var(--bp-primary); } [data-theme="light"] .pager button { border: 2px solid var(--bp-primary); background: var(--bp-surface); color: var(--bp-primary); font-weight: 700; } [data-theme="light"] .pager button:hover { background: var(--bp-primary); color: white; } .status-bar { position: fixed; right: 18px; bottom: 18px; padding: 8px 12px; border-radius: 999px; background: var(--bp-surface-elevated); border: 1px solid var(--bp-border-subtle); display: flex; align-items: center; gap: 8px; font-size: 12px; min-width: 230px; transition: all 0.3s ease; } [data-theme="light"] .status-bar { background: var(--bp-surface); border: 2px solid var(--bp-primary); box-shadow: 0 4px 16px rgba(108, 27, 27, 0.15); } .status-dot { width: 10px; height: 10px; border-radius: 999px; background: var(--bp-text-muted); } .status-dot.busy { background: var(--bp-accent); } .status-dot.error { background: var(--bp-danger); } .status-text-main { font-size: 12px; } .status-text-sub { font-size: 11px; color: var(--bp-text-muted); } .footer { display: flex; align-items: center; justify-content: center; gap: 12px; font-size: 11px; color: var(--bp-text-muted); border-top: 1px solid var(--bp-border-subtle); background: var(--bp-surface-elevated); transition: background 0.3s ease; } .footer a { color: var(--bp-text-muted); text-decoration: none; } .footer a:hover { text-decoration: underline; } .btn { font-size: 13px; font-weight: 500; padding: 8px 16px; border-radius: 8px; border: 1px solid var(--bp-border-subtle); background: var(--bp-surface-elevated); color: var(--bp-text); cursor: pointer; transition: all 0.2s ease; } .btn:hover:not(:disabled) { border-color: var(--bp-primary); transform: translateY(-1px); } .btn-primary { border-color: var(--bp-accent); background: var(--bp-btn-primary-bg); color: white; } .btn-primary:hover:not(:disabled) { background: var(--bp-btn-primary-hover); box-shadow: 0 4px 12px rgba(34,197,94,0.3); } [data-theme="light"] .btn-primary:hover:not(:disabled) { box-shadow: 0 4px 12px rgba(108, 27, 27, 0.3); } .btn-ghost { background: transparent; } .btn-ghost:hover:not(:disabled) { background: var(--bp-surface-elevated); } [data-theme="light"] .btn-ghost { border-color: var(--bp-primary); color: var(--bp-primary); } [data-theme="light"] .btn-ghost:hover:not(:disabled) { background: var(--bp-primary-soft); } .btn-sm { padding: 6px 12px; font-size: 12px; } .btn:disabled { opacity: 0.5; cursor: not-allowed; } .panel-tools-header { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 6px; } .card-toggle-bar { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 8px; } .toggle-pill { font-size: 11px; padding: 4px 8px; border-radius: 999px; border: 1px solid var(--bp-border-subtle); background: var(--bp-surface-elevated); color: var(--bp-text-muted); cursor: pointer; transition: all 0.2s ease; } .toggle-pill.active { border-color: var(--bp-accent); color: var(--bp-accent); background: var(--bp-accent-soft); } [data-theme="light"] .toggle-pill.active { border-color: var(--bp-primary); color: var(--bp-primary); background: var(--bp-primary-soft); } .cards-grid { flex: 1; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); grid-auto-rows: 1fr; gap: 10px; min-height: 0; align-items: stretch; } .card { border-radius: 14px; border: 1px solid var(--bp-border-subtle); background: var(--bp-card-bg); padding: 10px; display: flex; flex-direction: column; cursor: pointer; min-height: 0; transition: all 0.3s ease; } [data-theme="light"] .card { border: 2px solid var(--bp-primary); box-shadow: 0 4px 20px rgba(108, 27, 27, 0.1); } [data-theme="light"] .card:hover { box-shadow: 0 6px 28px rgba(108, 27, 27, 0.2); transform: translateY(-2px); } .card-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 6px; } [data-theme="light"] .card-header { border-bottom: 1px solid var(--bp-border-subtle); padding-bottom: 8px; margin-bottom: 10px; } .card-title { font-size: 13px; font-weight: 500; } [data-theme="light"] .card-title { font-size: 15px; font-weight: 700; color: var(--bp-text); letter-spacing: -0.02em; } .card-badge { font-size: 10px; border-radius: 999px; padding: 2px 7px; border: 1px solid var(--bp-border-subtle); color: var(--bp-text-muted); } [data-theme="light"] .card-badge { background: linear-gradient(135deg, var(--bp-accent) 0%, #4CAF50 100%); color: white; border: none; font-weight: 600; padding: 4px 10px; } .card-body { flex: 1; display: flex; flex-direction: column; gap: 5px; font-size: 11px; color: var(--bp-text-muted); } [data-theme="light"] .card-body { font-size: 12px; line-height: 1.6; } .card-actions { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; } .card-hidden { display: none; } .card-full { grid-column: 1 / -1; min-height: 220px; } """ def get_admin_dsms_html() -> str: """HTML für DSMS WebUI Modal zurückgeben""" return """ """ def get_admin_dsms_js() -> str: """JavaScript für DSMS Functions zurückgeben""" return """ const DSMS_GATEWAY_URL = 'http://localhost:8082'; let dsmsArchives = []; function switchDsmsTab(tabName) { document.querySelectorAll('.dsms-subtab').forEach(t => t.classList.remove('active')); document.querySelectorAll('.dsms-content').forEach(c => c.classList.remove('active')); document.querySelector(`.dsms-subtab[data-dsms-tab="${tabName}"]`)?.classList.add('active'); document.getElementById(`dsms-${tabName}`)?.classList.add('active'); // Load data for specific tabs if (tabName === 'settings') { loadDsmsNodeInfo(); } } async function loadDsmsData() { await Promise.all([ loadDsmsStatus(), loadDsmsArchives(), loadDsmsDocumentSelect() ]); } async function loadDsmsStatus() { const container = document.getElementById('dsms-status-cards'); container.innerHTML = '
DSMS Gateway ist nicht verfügbar. Stellen Sie sicher, dass die Container laufen.
Keine archivierten Dokumente vorhanden.
Klicken Sie auf "+ Dokument archivieren" um ein Legal Document im DSMS zu speichern.
| CID | Dokument | Version | Archiviert am | Aktionen |
|---|---|---|---|---|
${doc.cid.substring(0, 12)}...
|
${doc.metadata?.document_id || doc.filename || '-'} | ${doc.metadata?.version || '-'} | ${doc.metadata?.created_at ? new Date(doc.metadata.created_at).toLocaleString('de-DE') : '-'} | ↗ |
${cid}${data.stored_checksum || '-'}Das Dokument existiert, aber die Prüfsumme stimmt nicht überein.
Gespeichert: ${data.stored_checksum}
Berechnet: ${data.calculated_checksum}
Kein Dokument mit diesem CID gefunden.
${data.error ? `${data.error}
` : ''}${e.message}
${info.node_id || '-'}${a}DSMS läuft als isolierter Node. Keine externen Peers verbunden.
| CID | ${cid} |
| Typ | ${data.metadata?.document_type || '--'} |
| Erstellt | ${data.metadata?.created_at ? new Date(data.metadata.created_at).toLocaleString('de-DE') : '--'} |
| Checksum | ${data.stored_checksum || '--'} |