diff --git a/core/modules/modKundenKarte.class.php b/core/modules/modKundenKarte.class.php index 46c75e8..0281472 100755 --- a/core/modules/modKundenKarte.class.php +++ b/core/modules/modKundenKarte.class.php @@ -76,7 +76,7 @@ class modKundenKarte extends DolibarrModules $this->editor_squarred_logo = ''; // Must be image filename into the module/img directory followed with @modulename. Example: 'myimage.png@kundenkarte' // Possible values for version are: 'development', 'experimental', 'dolibarr', 'dolibarr_deprecated', 'experimental_deprecated' or a version string like 'x.y.z' - $this->version = '7.5'; + $this->version = '8.3'; // Url to the file with your last numberversion of this module //$this->url_last_version = 'http://www.example.com/versionmodule.txt'; diff --git a/css/pwa.css b/css/pwa.css index 05d7669..5803b71 100644 --- a/css/pwa.css +++ b/css/pwa.css @@ -831,10 +831,10 @@ body { Zeile 3: Output-Terminals (Abgänge) */ .carrier-content { display: grid; - gap: 2px; + gap: 0; padding: 5px; - grid-template-rows: auto auto auto; - align-items: stretch; + /* 5 Zeilen: Labels oben, Terminals oben, Equipment, Terminals unten, Labels unten */ + grid-template-rows: auto auto auto auto auto; } /* Equipment Block (Zeile 2) - Sicherungsautomat-Optik */ @@ -869,7 +869,7 @@ body { } .equipment-block-value { - font-size: 11px; + font-size: 8px; font-weight: bold; color: #fff; line-height: 1.1; @@ -913,12 +913,18 @@ body { min-width: 0; } -.terminal-point.terminal-input { - align-self: end; +/* Zeile 2 (obere Terminals): direkt am Equipment (margin-bottom negativ) */ +.terminal-point.terminal-row-top { + margin-bottom: -2px; + position: relative; + z-index: 1; } -.terminal-point.terminal-output { - align-self: start; +/* Zeile 4 (untere Terminals): direkt am Equipment (margin-top negativ) */ +.terminal-point.terminal-row-bottom { + margin-top: -2px; + position: relative; + z-index: 1; } .terminal-point:active { @@ -1038,7 +1044,16 @@ body { .terminal-label-cell.bundled-label { display: flex; justify-content: center; - align-items: center; +} + +/* Oben: Am unteren Rand ausrichten (zum Equipment hin) */ +.terminal-label-cell.bundled-label.label-row-top { + align-items: flex-end; +} + +/* Unten: Am oberen Rand ausrichten (zum Equipment hin) */ +.terminal-label-cell.bundled-label.label-row-bottom { + align-items: flex-start; } /* Gebündeltes Label mit Pfeil */ diff --git a/js/pwa.js b/js/pwa.js index 8ed3682..a31eb66 100644 --- a/js/pwa.js +++ b/js/pwa.js @@ -856,25 +856,17 @@ const bundledTop = eqTopOutputs.find(o => o.bundled_terminals === 'all'); if (bundledTop && widthTe > 1) { - // Gebündeltes Label mit Pfeil: Über alle Spalten des Equipment spannen + // Gebündeltes Label (nur Text, OHNE Pfeil) in Zeile 1 const gridColStyle = posTe > 0 ? `grid-row:1; grid-column: ${posTe} / span ${widthTe}` : `grid-row:1; grid-column: span ${widthTe}`; const cableInfo = buildCableInfo(bundledTop); - const phaseColor = bundledTop.color || getPhaseColor(bundledTop.connection_type); - html += ``; - // Container für vertikale Anordnung: Label oben, Pfeil unten - html += ``; + html += ``; if (bundledTop.output_label) { html += `${escapeHtml(bundledTop.output_label)}`; if (cableInfo) html += `${escapeHtml(cableInfo)}`; html += ``; } - html += ``; - html += ``; - if (bundledTop.connection_type) html += `${escapeHtml(bundledTop.connection_type)}`; - html += ``; - html += ``; html += ``; } else { // Normale einzelne Labels pro Terminal - nur für tatsächliche Terminals @@ -925,24 +917,34 @@ const topOut = bundledTop || eqTopOutputs[t] || null; if (bundledTop && widthTe > 1) { - // Gebündelter Abgang: Pfeil ist bereits im Label (Zeile 1) - hier nur leere Zelle - html += ``; + // Gebündelter Abgang: Pfeil nur beim ersten Terminal, Rest leer + if (t === 0) { + const phaseColor = bundledTop.color || getPhaseColor(bundledTop.connection_type); + const bundledStyle = posTe > 0 + ? `grid-row:2; grid-column: ${posTe} / span ${topTerminalCount}` + : `grid-row:2; grid-column: span ${topTerminalCount}`; + html += ``; + html += ``; + html += `${escapeHtml(bundledTop.connection_type || '')}`; + html += ``; + } + // Restliche Terminals überspringen (grid-column: span hat sie schon) } else if (topOut && (!topOut.bundled_terminals || widthTe <= 1)) { // Normaler Top-Output ODER bundled bei 1 TE (Bundle macht bei 1 TE keinen Unterschied) const phaseColor = topOut.color || getPhaseColor(topOut.connection_type); - html += ``; + html += ``; html += ``; html += `${escapeHtml(topOut.connection_type || '')}`; html += ``; } else if (inp) { const phaseColor = inp.color || getPhaseColor(inp.connection_type); - html += ``; + html += ``; html += ``; html += `${escapeHtml(inp.connection_type || '')}`; html += ``; } else { // Leerer Terminal - neutral, Position "top" - html += ``; + html += ``; html += ``; html += ``; } @@ -951,7 +953,7 @@ for (let t = topTerminalCount; t < widthTe; t++) { const colPos = posTe > 0 ? posTe + t : 0; const style = `grid-row:2;${colPos > 0 ? ' grid-column:' + colPos : ''}`; - html += ``; + html += ``; } }); @@ -1034,24 +1036,34 @@ const inp = eqBottomInputs[t] || null; if (bundledBottom && widthTe > 1) { - // Gebündelter Abgang: Pfeil ist im Label (Zeile 5) - hier nur leere Zelle - html += ``; + // Gebündelter Abgang: Pfeil nur beim ersten Terminal, Rest leer + if (t === 0) { + const phaseColor = bundledBottom.color || getPhaseColor(bundledBottom.connection_type); + const bundledStyle = posTe > 0 + ? `grid-row:4; grid-column: ${posTe} / span ${bottomTerminalCount}` + : `grid-row:4; grid-column: span ${bottomTerminalCount}`; + html += ``; + html += ``; + html += `${escapeHtml(bundledBottom.connection_type || '')}`; + html += ``; + } + // Restliche Terminals überspringen (grid-column: span hat sie schon) } else if (out && (!out.bundled_terminals || widthTe <= 1)) { // Normaler Abgang ODER bundled bei 1 TE (Bundle macht bei 1 TE keinen Unterschied) const phaseColor = out.color || getPhaseColor(out.connection_type); - html += ``; + html += ``; html += ``; html += `${escapeHtml(out.connection_type || '')}`; html += ``; } else if (inp) { const phaseColor = inp.color || getPhaseColor(inp.connection_type); - html += ``; + html += ``; html += ``; html += `${escapeHtml(inp.connection_type || '')}`; html += ``; } else { // Leerer Terminal - neutral, Position "bottom" - html += ``; + html += ``; html += ``; html += ``; } @@ -1060,7 +1072,7 @@ for (let t = bottomTerminalCount; t < widthTe; t++) { const colPos = posTe > 0 ? posTe + t : 0; const style = `grid-row:4;${colPos > 0 ? ' grid-column:' + colPos : ''}`; - html += ``; + html += ``; } }); @@ -1078,26 +1090,18 @@ const bundledBottom = eqBottomOutputs.find(o => o.bundled_terminals === 'all'); if (bundledBottom && widthTe > 1) { - // Gebündeltes Label mit Pfeil: Über alle Spalten des Equipment spannen + // Gebündeltes Label (nur Text, OHNE Pfeil) in Zeile 5 const gridColStyle = posTe > 0 ? `grid-row:5; grid-column: ${posTe} / span ${widthTe}` : `grid-row:5; grid-column: span ${widthTe}`; const cableInfo = buildCableInfo(bundledBottom); - const phaseColor = bundledBottom.color || getPhaseColor(bundledBottom.connection_type); - html += ``; - // Container für vertikale Anordnung: Pfeil oben, Label unten - html += ``; - html += ``; - html += ``; - if (bundledBottom.connection_type) html += `${escapeHtml(bundledBottom.connection_type)}`; - html += ``; + html += ``; if (bundledBottom.output_label) { html += `${escapeHtml(bundledBottom.output_label)}`; if (cableInfo) html += `${escapeHtml(cableInfo)}`; html += ``; } html += ``; - html += ``; } else { // Normale einzelne Labels pro Terminal - nur für tatsächliche Terminals for (let t = 0; t < bottomTerminalCount; t++) { diff --git a/pwa.php b/pwa.php index b9b5c15..3686a93 100644 --- a/pwa.php +++ b/pwa.php @@ -44,7 +44,7 @@ $themeColor = getDolGlobalString('THEME_ELDY_TOPMENU_BACK1', '#3498db'); - + @@ -374,6 +374,6 @@ $themeColor = getDolGlobalString('THEME_ELDY_TOPMENU_BACK1', '#3498db'); window.DOLIBARR_URL = ''; window.MODULE_URL = '/custom/kundenkarte'; - + diff --git a/sw.js b/sw.js index e1dba82..3f00fdc 100644 --- a/sw.js +++ b/sw.js @@ -3,8 +3,8 @@ * Offline-First für Schaltschrank-Dokumentation */ -const CACHE_NAME = 'kundenkarte-pwa-v5.2'; -const OFFLINE_CACHE = 'kundenkarte-offline-v5.2'; +const CACHE_NAME = 'kundenkarte-pwa-v6.1'; +const OFFLINE_CACHE = 'kundenkarte-offline-v6.1'; // Statische Assets die immer gecached werden (ohne Query-String) const STATIC_ASSETS = [