From a460fd8e401a619991c23b4039d4e7734ea6cf09 Mon Sep 17 00:00:00 2001 From: Christian Heubaum Date: Fri, 17 Apr 2026 12:24:07 +0000 Subject: [PATCH 01/26] Multi-Chapter-Support: Aktivierungscode, Gitea-Sync, Auto-Update --- index.html | 690 +++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 612 insertions(+), 78 deletions(-) diff --git a/index.html b/index.html index d14cd12..2d9a1bd 100644 --- a/index.html +++ b/index.html @@ -43,7 +43,8 @@ background: linear-gradient(160deg, #0f1f45 0%, #1a2744 40%, #0d1b35 100%); flex-direction: column; align-items: center; - justify-content: center; + justify-content: flex-start; + padding-top: clamp(90px, 12vh, 160px); position: relative; overflow: hidden; } @@ -84,14 +85,15 @@ #fullscreen-btn:hover { background: rgba(255,255,255,0.18); color: white; } .display-header { position: absolute; - top: 32px; left: 40px; + top: clamp(14px, 2vh, 32px); left: 40px; display: flex; align-items: center; - gap: 14px; + gap: clamp(10px, 1.5vh, 18px); + z-index: 10; } .bni-badge { - height: 52px; + height: clamp(44px, 6vh, 80px); width: auto; display: block; object-fit: contain; @@ -99,22 +101,23 @@ .chapter-name { color: rgba(255,255,255,0.7); - font-size: 1.1rem; + font-size: clamp(1rem, 1.8vh, 2rem); font-weight: 300; letter-spacing: 1px; } .progress-indicator { position: absolute; - top: 36px; right: 40px; + top: clamp(28px, 4vh, 50px); right: 40px; color: rgba(255,255,255,0.5); - font-size: 0.95rem; + font-size: clamp(0.85rem, 1.5vh, 1.8rem); letter-spacing: 1px; + z-index: 10; } .round-badge { position: absolute; - top: 70px; right: 40px; + top: 96px; right: 40px; background: var(--red); color: white; font-size: 0.8rem; @@ -131,16 +134,18 @@ display: flex; flex-direction: row; align-items: center; - gap: 56px; + gap: clamp(40px, 5vw, 100px); background: rgba(255,255,255,0.07); backdrop-filter: blur(24px); border: 1px solid rgba(255,255,255,0.12); - border-radius: 28px; - padding: 52px 60px; - max-width: 1000px; - width: 92%; + border-radius: clamp(20px, 3vh, 36px); + padding: clamp(32px, 5vh, 80px) clamp(40px, 5vw, 100px); + max-width: none; + width: 96vw; + flex: 1; position: relative; z-index: 1; + margin-bottom: clamp(16px, 2.5vh, 40px); } .photo-section { @@ -152,8 +157,8 @@ } .member-photo-wrap { - width: 220px; - height: 220px; + width: 100%; + height: 100%; border-radius: 50%; border: 4px solid var(--red); overflow: hidden; @@ -171,36 +176,42 @@ } .initials-avatar { - font-size: 4rem; + font-size: clamp(4rem, 12vh, 12rem); font-weight: 700; color: white; } - .qr-wrap { + .qr-corner { + position: absolute; + top: clamp(102px, 14vh, 180px); + right: clamp(24px, 3vw, 60px); + z-index: 3; background: white; - padding: 10px; - border-radius: 12px; + padding: clamp(8px, 1vh, 14px); + border-radius: 14px; + box-shadow: 0 4px 24px rgba(0,0,0,0.35); } .qr-label { - color: rgba(255,255,255,0.4); - font-size: 0.7rem; + color: #1a2744; + font-size: clamp(0.6rem, 1vh, 0.9rem); text-align: center; - margin-top: 6px; + margin-top: 5px; text-transform: uppercase; letter-spacing: 1px; + font-weight: 600; } .info-section { flex: 1; display: flex; flex-direction: column; - gap: 14px; + gap: clamp(14px, 2.5vh, 36px); } .substitute-label { color: rgba(255,255,255,0.5); - font-size: 0.85rem; + font-size: clamp(0.75rem, 1.5vh, 1.5rem); text-transform: uppercase; letter-spacing: 2px; border-left: 3px solid var(--red); @@ -208,14 +219,14 @@ } .display-name { - font-size: clamp(2rem, 4vw, 3.2rem); + font-size: clamp(3rem, max(5vw, 7vh), 10rem); font-weight: 800; color: white; line-height: 1.1; } .display-company { - font-size: clamp(1.1rem, 2vw, 1.6rem); + font-size: clamp(1.6rem, max(2.8vw, 4vh), 6rem); color: rgba(255,255,255,0.75); font-weight: 400; } @@ -225,8 +236,8 @@ background: rgba(204,0,0,0.25); border: 1px solid rgba(204,0,0,0.5); color: #ff8080; - font-size: 1rem; - padding: 8px 18px; + font-size: clamp(1rem, 2.2vh, 2.4rem); + padding: clamp(6px, 1vh, 14px) clamp(12px, 1.8vw, 28px); border-radius: 30px; align-self: flex-start; } @@ -236,8 +247,8 @@ background: rgba(234,179,8,0.2); border: 1px solid rgba(234,179,8,0.4); color: #fcd34d; - font-size: 0.85rem; - padding: 4px 14px; + font-size: clamp(0.8rem, 1.6vh, 1.6rem); + padding: clamp(4px, 0.8vh, 10px) clamp(10px, 1.5vw, 20px); border-radius: 20px; align-self: flex-start; margin-top: 4px; @@ -255,13 +266,13 @@ } .presenter-avatar { - width: 44px; height: 44px; + width: clamp(36px, 4.5vh, 64px); height: clamp(36px, 4.5vh, 64px); border-radius: 50%; overflow: hidden; flex-shrink: 0; border: 2px solid rgba(255,255,255,0.2); display: flex; align-items: center; justify-content: center; - font-size: 0.9rem; font-weight: 700; color: white; + font-size: clamp(0.8rem, 1.4vh, 1.4rem); font-weight: 700; color: white; } .presenter-avatar img { @@ -269,7 +280,7 @@ } .presenter-label { - font-size: 0.7rem; + font-size: clamp(0.65rem, 1.2vh, 1.2rem); text-transform: uppercase; letter-spacing: 1.5px; color: rgba(255,255,255,0.4); @@ -277,13 +288,13 @@ } .presenter-name { - font-size: 0.95rem; + font-size: clamp(0.9rem, 1.8vh, 1.8rem); font-weight: 600; color: rgba(255,255,255,0.85); } .presenter-company { - font-size: 0.8rem; + font-size: clamp(0.75rem, 1.4vh, 1.4rem); color: rgba(255,255,255,0.5); } @@ -296,53 +307,60 @@ /* Next Bar */ .next-bar { position: absolute; - bottom: 0; left: 0; right: 0; - background: rgba(0,0,0,0.55); + top: 0; left: 0; right: 0; + background: rgba(0,0,0,0.6); backdrop-filter: blur(12px); - border-top: 1px solid rgba(255,255,255,0.08); - padding: 18px 40px; + border-bottom: 1px solid rgba(255,255,255,0.1); + padding: clamp(12px, 1.8vh, 24px) 40px; display: flex; align-items: center; - gap: 20px; + gap: clamp(16px, 2.5vh, 36px); + z-index: 5; } - .next-bar-label { - color: rgba(255,255,255,0.4); - font-size: 0.8rem; - text-transform: uppercase; - letter-spacing: 2px; - white-space: nowrap; + #next-bar { + padding-left: 320px; } + + .next-bar-divider { width: 1px; - height: 30px; + height: clamp(40px, 7vh, 96px); background: rgba(255,255,255,0.15); } .next-photo-small { - width: 44px; height: 44px; + width: clamp(56px, 8.5vh, 120px); height: clamp(56px, 8.5vh, 120px); border-radius: 50%; object-fit: cover; - border: 2px solid rgba(255,255,255,0.2); + border: 2px solid rgba(255,255,255,0.3); background: rgba(255,255,255,0.1); } .next-info .next-name-text { color: white; - font-size: 1.15rem; - font-weight: 600; + font-size: clamp(1.5rem, 3.8vh, 4.2rem); + font-weight: 700; } .next-info .next-company-text { + color: rgba(255,255,255,0.6); + font-size: clamp(1rem, 2.5vh, 2.8rem); + } + + .next-bar-label { color: rgba(255,255,255,0.5); - font-size: 0.9rem; + font-size: clamp(0.8rem, 1.8vh, 2rem); + text-transform: uppercase; + letter-spacing: 2px; + white-space: nowrap; } .next-bar-end-text { - color: rgba(255,255,255,0.3); + color: rgba(255,255,255,0.4); font-style: italic; - font-size: 1rem; + font-size: clamp(1.2rem, 2.5vh, 2.8rem); } /* ============================================================ @@ -709,13 +727,13 @@ ============================================================ */ .photo-timer-wrap { position: relative; - width: 220px; height: 220px; + width: min(42vh, 45vmin); height: min(42vh, 45vmin); flex-shrink: 0; } .timer-ring-svg { position: absolute; top: -14px; left: -14px; - width: 248px; height: 248px; + width: calc(min(42vh, 45vmin) + 28px); height: calc(min(42vh, 45vmin) + 28px); transform: rotate(-90deg); pointer-events: none; display: none; @@ -738,7 +756,7 @@ @keyframes timerBlink { to { opacity: 0.15; } } #display-timer-text { - font-size: 2.6rem; font-weight: 700; + font-size: clamp(2rem, 4vh, 5rem); font-weight: 700; color: rgba(255,255,255,0.95); font-variant-numeric: tabular-nums; letter-spacing: 3px; @@ -986,6 +1004,59 @@ } .btn-save:hover { background: var(--red-dark); } + /* Profile Extras Section in Modal */ + .extras-section-divider { + border: none; + border-top: 1px solid var(--border); + margin: 16px 0 12px; + } + .extras-section-title { + font-size: 0.72rem; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 1.5px; + color: var(--muted); + margin-bottom: 12px; + } + .offline-photo-row { + display: flex; + align-items: center; + gap: 12px; + padding: 10px 12px; + background: var(--bg); + border-radius: 8px; + border: 1px solid var(--border); + margin-bottom: 8px; + } + .offline-photo-thumb { + width: 52px; height: 52px; + border-radius: 50%; + object-fit: cover; + border: 2px solid var(--border); + flex-shrink: 0; + } + .offline-photo-actions { + display: flex; + gap: 8px; + flex-wrap: wrap; + align-items: center; + } + .btn-file-label { + display: inline-flex; + align-items: center; + gap: 4px; + padding: 5px 12px; + font-size: 0.82rem; + font-weight: 600; + cursor: pointer; + border-radius: 6px; + border: 1px solid var(--border); + background: white; + color: var(--muted); + transition: all 0.15s; + } + .btn-file-label:hover { background: white; color: var(--text); } + /* Import/Export */ .import-export-panel { padding: 16px; @@ -1049,12 +1120,16 @@
- BNI Sonne Ulm -
Vorstellungsrunde
+ +
Vorstellungsrunde
⚙ Steuerung
+
2. Runde – Besucher
@@ -1074,7 +1149,7 @@
- BNI Sonne Ulm + BNI
@@ -1091,10 +1166,6 @@
-
@@ -1121,7 +1192,7 @@
—
- +
@@ -1142,8 +1213,8 @@
- BNI Sonne Ulm -
Vorstellungsrunde steuern
+ +
Vorstellungsrunde steuern
@@ -1188,6 +1259,7 @@
Besucher
Mitglieder
Vertretungen
+
Admin
@@ -1232,6 +1304,10 @@
+
+ +
+
Mitglied als vertreten markieren:
@@ -1289,13 +1365,32 @@ - + +
+
Dauerhaft gespeichert (bleibt nach BNI-Sync erhalten)
+ + + + + +
+ +
+ + + +
+
+ + +
+
Profildaten (Kurzlinks + Offline-Fotos)
+

+ Kurzlinks und lokale Fotos werden getrennt gespeichert und bleiben nach jedem BNI-Sync erhalten. + Diese Datei im Projektordner ablegen und nach einem Browser-Reset wieder importieren. +

+
+ + + +
@@ -1505,7 +1615,7 @@
Schritt 2 – Daten exportieren
  1. BNI-Mitgliederliste öffnen: - bni-ulm.com → Chapter Sonne + bni-ulm.com → Chapter Sonne
  2. Warten bis alle Mitglieder geladen sind
  3. Bookmarklet "BNI Mitglieder exportieren" klicken
  4. @@ -1533,10 +1643,32 @@
+ + +
+ +
+
BNI Vorstellungsrunde
+
Bitte gib deinen Lizenzcode ein, um dein Chapter freizuschalten.
+ +
+ +
+
+ From c244148050a7dc0aedffdb7761e28402a87bea83 Mon Sep 17 00:00:00 2001 From: Christian Heubaum Date: Fri, 17 Apr 2026 12:24:20 +0000 Subject: [PATCH 02/26] =?UTF-8?q?version.json=20hinzugef=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- version.json | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 version.json diff --git a/version.json b/version.json new file mode 100644 index 0000000..fd0e770 --- /dev/null +++ b/version.json @@ -0,0 +1,4 @@ +{ + "version": "1.1.0", + "notes": "Multi-Chapter-Support mit Lizenzcode" +} From 74ffbf7c760f735f5dda080a829b0dd75c287ab7 Mon Sep 17 00:00:00 2001 From: Christian Heubaum Date: Fri, 17 Apr 2026 12:25:15 +0000 Subject: [PATCH 03/26] Chapter Sonne: config.json --- chapters/sonne-7x4m9k/config.json | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 chapters/sonne-7x4m9k/config.json diff --git a/chapters/sonne-7x4m9k/config.json b/chapters/sonne-7x4m9k/config.json new file mode 100644 index 0000000..165be64 --- /dev/null +++ b/chapters/sonne-7x4m9k/config.json @@ -0,0 +1,6 @@ +{ + "chapterName": "BNI Chapter Sonne", + "syncUrl": "https://bni-ulm.com/sonne/de/memberlist?chapterName=6035®ionIds=43671&isChapterwebsite=true", + "websiteUrl": "https://bni-ulm.de/sonne", + "defaultTimer": 60 +} From 1f68d164aa49f59603217eebb1831c4b2ae68381 Mon Sep 17 00:00:00 2001 From: Christian Heubaum Date: Fri, 17 Apr 2026 12:25:15 +0000 Subject: [PATCH 04/26] Chapter Sonne: members.json --- chapters/sonne-7x4m9k/members.json | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 chapters/sonne-7x4m9k/members.json diff --git a/chapters/sonne-7x4m9k/members.json b/chapters/sonne-7x4m9k/members.json new file mode 100644 index 0000000..9a30c6f --- /dev/null +++ b/chapters/sonne-7x4m9k/members.json @@ -0,0 +1,4 @@ +{ + "lastUpdated": "2026-04-17", + "members": [] +} From 4a7b13a94d9ca5749b8180f1414608f27fce05d0 Mon Sep 17 00:00:00 2001 From: Christian Heubaum Date: Fri, 17 Apr 2026 12:28:27 +0000 Subject: [PATCH 05/26] Fix: Activation view vor Script-Block verschoben --- index.html | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/index.html b/index.html index 2d9a1bd..4ec45a3 100644 --- a/index.html +++ b/index.html @@ -1336,6 +1336,26 @@ + +
+ +
+
BNI Vorstellungsrunde
+
Bitte gib deinen Lizenzcode ein, um dein Chapter freizuschalten.
+ +
+ +
+
+ @@ -4204,25 +4224,6 @@ if (getView() === 'control') { } - -
- -
-
BNI Vorstellungsrunde
-
Bitte gib deinen Lizenzcode ein, um dein Chapter freizuschalten.
- -
- -
-
From df4b319b9eb79a12d9e3880f9a537b7873c67547 Mon Sep 17 00:00:00 2001 From: Christian Heubaum Date: Fri, 17 Apr 2026 12:39:24 +0000 Subject: [PATCH 06/26] Fix CORS: API-Endpunkt statt Raw-URL --- index.html | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/index.html b/index.html index 4ec45a3..ef414a9 100644 --- a/index.html +++ b/index.html @@ -1667,7 +1667,8 @@ // CONSTANTS & CHAPTER CONFIG // ============================================================ const APP_VERSION = '1.1.0'; -const GITEA_RAW = 'http://72.60.134.73:3000/cheubaum/BNI-Sonne/raw/branch/main'; +const GITEA_RAW = 'http://72.60.134.73:3000/api/v1/repos/cheubaum/BNI-Sonne/raw'; +function giteaUrl(path) { return `${GITEA_RAW}/${path}?ref=main`; } const CHAPTER_CONFIG_KEY = 'bni-active-chapter'; function loadChapterConfig() { @@ -4029,7 +4030,7 @@ async function activateChapter() { status.textContent = 'Überprüfe Lizenzcode…'; status.style.color = 'rgba(255,255,255,0.6)'; try { - const res = await fetch(`${GITEA_RAW}/chapters/${code}/config.json`, { cache: 'no-store' }); + const res = await fetch(giteaUrl(`chapters/${code}/config.json`), { cache: 'no-store' }); if (!res.ok) { status.textContent = 'Ungültiger oder abgelaufener Lizenzcode.'; status.style.color = '#f87171'; @@ -4070,7 +4071,7 @@ function applyChapterUI(config) { if (ctrlName) ctrlName.textContent = `${name} – Steuerung`; if (config.logoUrl && activeChapter) { const src = config.logoUrl.startsWith('http') ? config.logoUrl - : `${GITEA_RAW}/chapters/${activeChapter.code}/${config.logoUrl}`; + : giteaUrl(`chapters/${activeChapter.code}/${config.logoUrl}`); ['display-logo','display-logo-empty','ctrl-logo'].forEach(id => { const img = document.getElementById(id); if (img) img.src = src; @@ -4086,7 +4087,7 @@ function applyChapterUI(config) { async function checkLicenseAndUpdates() { if (!activeChapter) return; try { - const res = await fetch(`${GITEA_RAW}/chapters/${activeChapter.code}/config.json`, { cache: 'no-store' }); + const res = await fetch(giteaUrl(`chapters/${activeChapter.code}/config.json`), { cache: 'no-store' }); if (!res.ok) { clearChapterData(); state = defaultState(); @@ -4109,7 +4110,7 @@ async function checkLicenseAndUpdates() { async function checkForUpdates() { try { - const res = await fetch(`${GITEA_RAW}/version.json`, { cache: 'no-store' }); + const res = await fetch(giteaUrl('version.json'), { cache: 'no-store' }); if (!res.ok) return; const data = await res.json(); if (data.version && data.version > APP_VERSION) showUpdateBanner(data.version, data.notes); @@ -4130,7 +4131,7 @@ function showUpdateBanner(version, notes) { async function downloadUpdate(version) { try { - const licRes = await fetch(`${GITEA_RAW}/chapters/${activeChapter.code}/config.json`, { cache: 'no-store' }); + const licRes = await fetch(giteaUrl(`chapters/${activeChapter.code}/config.json`), { cache: 'no-store' }); if (!licRes.ok) { clearChapterData(); state = defaultState(); @@ -4140,7 +4141,7 @@ async function downloadUpdate(version) { } } catch(e) { alert('Keine Serververbindung möglich.'); return; } try { - const res = await fetch(`${GITEA_RAW}/index.html`, { cache: 'no-store' }); + const res = await fetch(giteaUrl('index.html'), { cache: 'no-store' }); const html = await res.text(); const blob = new Blob([html], { type: 'text/html' }); const a = document.createElement('a'); @@ -4154,7 +4155,7 @@ async function downloadUpdate(version) { async function fetchChapterMembersFromGitea() { if (!activeChapter) return; try { - const res = await fetch(`${GITEA_RAW}/chapters/${activeChapter.code}/members.json`, { cache: 'no-store' }); + const res = await fetch(giteaUrl(`chapters/${activeChapter.code}/members.json`), { cache: 'no-store' }); if (!res.ok) return; const data = await res.json(); if (!data.members || !data.members.length) return; From 46a26dbc4fc1d00054741ab241312873616e1aec Mon Sep 17 00:00:00 2001 From: Christian Heubaum Date: Fri, 17 Apr 2026 12:45:53 +0000 Subject: [PATCH 07/26] Admin: Mitglieder mit Fotos auf Gitea hochladen --- index.html | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 89 insertions(+), 7 deletions(-) diff --git a/index.html b/index.html index ef414a9..92296a0 100644 --- a/index.html +++ b/index.html @@ -1668,6 +1668,7 @@ // ============================================================ const APP_VERSION = '1.1.0'; const GITEA_RAW = 'http://72.60.134.73:3000/api/v1/repos/cheubaum/BNI-Sonne/raw'; +const GITEA_API = 'http://72.60.134.73:3000/api/v1/repos/cheubaum/BNI-Sonne'; function giteaUrl(path) { return `${GITEA_RAW}/${path}?ref=main`; } const CHAPTER_CONFIG_KEY = 'bni-active-chapter'; @@ -4159,11 +4160,19 @@ async function fetchChapterMembersFromGitea() { if (!res.ok) return; const data = await res.json(); if (!data.members || !data.members.length) return; + const extras = loadExtras(); const mergedMap = new Map(state.members.map(m => [m.id, m])); data.members.forEach(m => { const ex = mergedMap.get(m.id); mergedMap.set(m.id, ex ? Object.assign({}, ex, m) : m); + // Embed photoData into extras so existing photo display picks it up + if (m.photoData) { + const key = extrasKey(m.name); + if (!extras[key]) extras[key] = {}; + extras[key].offlinePhotoB64 = m.photoData; + } }); + saveExtras(extras); state.members = Array.from(mergedMap.values()); const knownIds = new Set(state.meetingOrder); state.members.forEach(m => { if (!knownIds.has(m.id)) state.meetingOrder.push(m.id); }); @@ -4175,6 +4184,65 @@ async function fetchChapterMembersFromGitea() { } catch(e) { /* ignore */ } } +function buildMembersJson() { + const extras = loadExtras(); + const members = state.members.map(m => { + const ex = extras[extrasKey(m.name)] || {}; + const entry = { id: m.id, name: m.name, company: m.company, specialty: m.specialty, photoUrl: m.photoUrl || '', profileUrl: m.profileUrl || '' }; + if (ex.offlinePhotoB64) entry.photoData = ex.offlinePhotoB64; + return entry; + }); + return { lastUpdated: new Date().toISOString().slice(0, 10), members }; +} + +function saveAdminToken() { + const val = (document.getElementById('admin-token-input').value || '').trim(); + if (val) localStorage.setItem('bni-gitea-admin-token', val); + else localStorage.removeItem('bni-gitea-admin-token'); + renderAdminPanel(); +} + +async function uploadMembersToGitea() { + const token = localStorage.getItem('bni-gitea-admin-token'); + if (!token) { alert('Bitte zuerst den Admin-Token speichern.'); return; } + const statusEl = document.getElementById('upload-status'); + statusEl.textContent = 'Lädt hoch…'; + statusEl.style.color = 'var(--muted)'; + + const data = buildMembersJson(); + const jsonStr = JSON.stringify(data, null, 2); + const content = btoa(unescape(encodeURIComponent(jsonStr))); + const path = `chapters/${activeChapter.code}/members.json`; + + try { + // Get current SHA + let sha = null; + const shaRes = await fetch(`${GITEA_API}/contents/${path}`, { headers: { 'Authorization': `token ${token}` } }); + if (shaRes.ok) sha = (await shaRes.json()).sha; + + const body = { message: `Mitglieder aktualisiert ${new Date().toLocaleDateString('de')}`, content }; + if (sha) body.sha = sha; + + const res = await fetch(`${GITEA_API}/contents/${path}`, { + method: sha ? 'PUT' : 'POST', + headers: { 'Authorization': `token ${token}`, 'Content-Type': 'application/json' }, + body: JSON.stringify(body) + }); + if (res.ok) { + activeChapter.lastMemberUpload = new Date().toISOString(); + saveChapterConfig(activeChapter); + statusEl.textContent = `✓ ${data.members.length} Mitglieder hochgeladen`; + statusEl.style.color = 'var(--success)'; + } else { + statusEl.textContent = 'Fehler beim Upload. Token prüfen.'; + statusEl.style.color = '#dc2626'; + } + } catch(e) { + statusEl.textContent = 'Verbindungsfehler.'; + statusEl.style.color = '#dc2626'; + } +} + function renderAdminPanel() { const panel = document.getElementById('admin-panel'); if (!panel) return; @@ -4182,7 +4250,8 @@ function renderAdminPanel() { const code = activeChapter && activeChapter.code; const lastChecked = activeChapter && activeChapter.lastChecked ? new Date(activeChapter.lastChecked).toLocaleString('de') : '—'; const lastSync = activeChapter && activeChapter.lastMemberSync ? new Date(activeChapter.lastMemberSync).toLocaleString('de') : '—'; - const maskedCode = code ? code.slice(0, -3).replace(/./g, '·') + code.slice(-3) : '—'; + const lastUpload = activeChapter && activeChapter.lastMemberUpload ? new Date(activeChapter.lastMemberUpload).toLocaleString('de') : '—'; + const hasToken = !!localStorage.getItem('bni-gitea-admin-token'); panel.innerHTML = `
Chapter-Administration
@@ -4190,13 +4259,26 @@ function renderAdminPanel() {
Aktives Chapter
${cfg.chapterName || '—'}
-
Version: ${APP_VERSION}
-
Letzte Lizenzprüfung: ${lastChecked}
+
Version: ${APP_VERSION} · Lizenzprüfung: ${lastChecked}
- -
Letzte Synchronisation: ${lastSync}
- -
+ +
Mitglieder laden
+ +
Letzter Download: ${lastSync}
+ +
Mitglieder hochladen (Admin)
+
+ + +
+ +
+
Letzter Upload: ${lastUpload}
+ + ` : `
Kein Chapter aktiviert.
`}
From 7a5dd462642d62a1ea7173323185c799cf9043b6 Mon Sep 17 00:00:00 2001 From: Christian Heubaum Date: Sat, 18 Apr 2026 14:08:57 +0000 Subject: [PATCH 08/26] Fix: Admin-Tab Breite --- index.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/index.html b/index.html index 92296a0..c9ac6eb 100644 --- a/index.html +++ b/index.html @@ -807,12 +807,12 @@ .panel-right-tab { flex: 1; - padding: 12px 8px; + padding: 10px 4px; text-align: center; - font-size: 0.78rem; + font-size: 0.7rem; font-weight: 600; text-transform: uppercase; - letter-spacing: 1px; + letter-spacing: 0.4px; color: var(--muted); cursor: pointer; border-bottom: 2px solid transparent; From de9d3b14c415f292673e0fa443bf9e225d6674e9 Mon Sep 17 00:00:00 2001 From: Christian Heubaum Date: Sat, 18 Apr 2026 14:16:03 +0000 Subject: [PATCH 09/26] =?UTF-8?q?Chapter=20Galaxis=20hinzugef=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- chapters/galaxis-go26for37/config.json | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 chapters/galaxis-go26for37/config.json diff --git a/chapters/galaxis-go26for37/config.json b/chapters/galaxis-go26for37/config.json new file mode 100644 index 0000000..7291a75 --- /dev/null +++ b/chapters/galaxis-go26for37/config.json @@ -0,0 +1,6 @@ +{ + "chapterName": "BNI Chapter Galaxis", + "syncUrl": "https://bni-ulm.com/galaxis/de/memberlist?chapterName=6041®ionIds=43671$isChapterwebsite", + "websiteUrl": "https://bni-ulm.de/galaxis", + "defaultTimer": 60 +} From da3d480e1c4238df7a0f87aaad5c2dbf7344e9ca Mon Sep 17 00:00:00 2001 From: Christian Heubaum Date: Sat, 18 Apr 2026 14:16:03 +0000 Subject: [PATCH 10/26] Chapter Galaxis: members.json --- chapters/galaxis-go26for37/members.json | 1 + 1 file changed, 1 insertion(+) create mode 100644 chapters/galaxis-go26for37/members.json diff --git a/chapters/galaxis-go26for37/members.json b/chapters/galaxis-go26for37/members.json new file mode 100644 index 0000000..ccaab29 --- /dev/null +++ b/chapters/galaxis-go26for37/members.json @@ -0,0 +1 @@ +{"lastUpdated":"2026-04-18","members":[]} \ No newline at end of file From 09769faf0e9cd3a1b68896694f5a64dde2ca204b Mon Sep 17 00:00:00 2001 From: Christian Heubaum Date: Sat, 18 Apr 2026 14:19:12 +0000 Subject: [PATCH 11/26] Chapter Galaxis: Logo --- chapters/galaxis-go26for37/logo.png | Bin 0 -> 6922 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 chapters/galaxis-go26for37/logo.png diff --git a/chapters/galaxis-go26for37/logo.png b/chapters/galaxis-go26for37/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..bd952cb9685515d975ca4c1ee19947782d2d3226 GIT binary patch literal 6922 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 Date: Sat, 18 Apr 2026 14:19:23 +0000 Subject: [PATCH 12/26] =?UTF-8?q?Galaxis=20config:=20logoUrl=20erg=C3=A4nz?= =?UTF-8?q?t?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- chapters/galaxis-go26for37/config.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/chapters/galaxis-go26for37/config.json b/chapters/galaxis-go26for37/config.json index 7291a75..81cc773 100644 --- a/chapters/galaxis-go26for37/config.json +++ b/chapters/galaxis-go26for37/config.json @@ -1,6 +1,7 @@ { "chapterName": "BNI Chapter Galaxis", - "syncUrl": "https://bni-ulm.com/galaxis/de/memberlist?chapterName=6041®ionIds=43671$isChapterwebsite", + "logoUrl": "logo.png", + "syncUrl": "https://bni-ulm.com/galaxis/de/memberlist?chapterName=6041®ionIds=43671&isChapterwebsite=true", "websiteUrl": "https://bni-ulm.de/galaxis", "defaultTimer": 60 -} +} \ No newline at end of file From a92f8466ca1580203872eb849bb00da43f2bc90b Mon Sep 17 00:00:00 2001 From: Christian Heubaum Date: Sat, 18 Apr 2026 14:56:24 +0000 Subject: [PATCH 13/26] Update index.html: Stammvertreter-Feature + vereinfachter Admin-Tab --- index.html | 216 ++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 197 insertions(+), 19 deletions(-) diff --git a/index.html b/index.html index c9ac6eb..c588cfc 100644 --- a/index.html +++ b/index.html @@ -1330,6 +1330,13 @@
Aktive Vertretungen
+
+
+
Stammvertreter-Vorrat
+ +
+
+
@@ -1452,6 +1459,38 @@ + + + + + +