feat(schematic): Echte Junction-Verbindungen (Abzweigungen)
- Neue DB-Felder: junction_connection_id, junction_x, junction_y - Klick auf Leitung im Zeichenmodus erstellt echte Abzweigung - Orthogonale Pfadberechnung (nur rechtwinklig) - Separater Dialog für Abzweigungen mit übernommenen Werten - Migration für v9.2.0 hinzugefügt Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
276abe3f06
commit
1221f49c5b
5 changed files with 274 additions and 39 deletions
|
|
@ -161,6 +161,10 @@ switch ($action) {
|
||||||
$connection->position_y = GETPOSTINT('position_y');
|
$connection->position_y = GETPOSTINT('position_y');
|
||||||
$connection->path_data = GETPOST('path_data', 'nohtml');
|
$connection->path_data = GETPOST('path_data', 'nohtml');
|
||||||
$connection->bundled_terminals = GETPOST('bundled_terminals', 'alphanohtml');
|
$connection->bundled_terminals = GETPOST('bundled_terminals', 'alphanohtml');
|
||||||
|
// Junction fields for branching from existing connections
|
||||||
|
$connection->junction_connection_id = GETPOSTINT('junction_connection_id') ?: null;
|
||||||
|
$connection->junction_x = GETPOST('junction_x', 'alpha') ? floatval(GETPOST('junction_x', 'alpha')) : null;
|
||||||
|
$connection->junction_y = GETPOST('junction_y', 'alpha') ? floatval(GETPOST('junction_y', 'alpha')) : null;
|
||||||
|
|
||||||
$result = $connection->create($user);
|
$result = $connection->create($user);
|
||||||
if ($result > 0) {
|
if ($result > 0) {
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,12 @@ class EquipmentConnection extends CommonObject
|
||||||
public $fk_carrier;
|
public $fk_carrier;
|
||||||
public $position_y = 0;
|
public $position_y = 0;
|
||||||
public $path_data; // SVG path for manually drawn connections
|
public $path_data; // SVG path for manually drawn connections
|
||||||
|
|
||||||
|
// Junction fields - branching from existing connections
|
||||||
|
public $junction_connection_id; // ID of connection to branch from
|
||||||
|
public $junction_x; // X coordinate of junction point
|
||||||
|
public $junction_y; // Y coordinate of junction point
|
||||||
|
|
||||||
public $note_private;
|
public $note_private;
|
||||||
public $status = 1;
|
public $status = 1;
|
||||||
|
|
||||||
|
|
@ -91,6 +97,7 @@ class EquipmentConnection extends CommonObject
|
||||||
$sql .= " connection_type, color, output_label,";
|
$sql .= " connection_type, color, output_label,";
|
||||||
$sql .= " medium_type, medium_spec, medium_length,";
|
$sql .= " medium_type, medium_spec, medium_length,";
|
||||||
$sql .= " is_rail, rail_start_te, rail_end_te, rail_phases, excluded_te, fk_carrier, position_y, path_data,";
|
$sql .= " is_rail, rail_start_te, rail_end_te, rail_phases, excluded_te, fk_carrier, position_y, path_data,";
|
||||||
|
$sql .= " junction_connection_id, junction_x, junction_y,";
|
||||||
$sql .= " note_private, status, date_creation, fk_user_creat";
|
$sql .= " note_private, status, date_creation, fk_user_creat";
|
||||||
$sql .= ") VALUES (";
|
$sql .= ") VALUES (";
|
||||||
$sql .= ((int) $conf->entity);
|
$sql .= ((int) $conf->entity);
|
||||||
|
|
@ -115,6 +122,9 @@ class EquipmentConnection extends CommonObject
|
||||||
$sql .= ", ".($this->fk_carrier > 0 ? ((int) $this->fk_carrier) : "NULL");
|
$sql .= ", ".($this->fk_carrier > 0 ? ((int) $this->fk_carrier) : "NULL");
|
||||||
$sql .= ", ".((int) $this->position_y);
|
$sql .= ", ".((int) $this->position_y);
|
||||||
$sql .= ", ".($this->path_data ? "'".$this->db->escape($this->path_data)."'" : "NULL");
|
$sql .= ", ".($this->path_data ? "'".$this->db->escape($this->path_data)."'" : "NULL");
|
||||||
|
$sql .= ", ".($this->junction_connection_id > 0 ? ((int) $this->junction_connection_id) : "NULL");
|
||||||
|
$sql .= ", ".($this->junction_x !== null ? floatval($this->junction_x) : "NULL");
|
||||||
|
$sql .= ", ".($this->junction_y !== null ? floatval($this->junction_y) : "NULL");
|
||||||
$sql .= ", ".($this->note_private ? "'".$this->db->escape($this->note_private)."'" : "NULL");
|
$sql .= ", ".($this->note_private ? "'".$this->db->escape($this->note_private)."'" : "NULL");
|
||||||
$sql .= ", ".((int) $this->status);
|
$sql .= ", ".((int) $this->status);
|
||||||
$sql .= ", '".$this->db->idate($now)."'";
|
$sql .= ", '".$this->db->idate($now)."'";
|
||||||
|
|
@ -184,6 +194,9 @@ class EquipmentConnection extends CommonObject
|
||||||
$this->fk_carrier = $obj->fk_carrier;
|
$this->fk_carrier = $obj->fk_carrier;
|
||||||
$this->position_y = $obj->position_y;
|
$this->position_y = $obj->position_y;
|
||||||
$this->path_data = isset($obj->path_data) ? $obj->path_data : null;
|
$this->path_data = isset($obj->path_data) ? $obj->path_data : null;
|
||||||
|
$this->junction_connection_id = isset($obj->junction_connection_id) ? $obj->junction_connection_id : null;
|
||||||
|
$this->junction_x = isset($obj->junction_x) ? $obj->junction_x : null;
|
||||||
|
$this->junction_y = isset($obj->junction_y) ? $obj->junction_y : null;
|
||||||
$this->note_private = $obj->note_private;
|
$this->note_private = $obj->note_private;
|
||||||
$this->status = $obj->status;
|
$this->status = $obj->status;
|
||||||
$this->date_creation = $this->db->jdate($obj->date_creation);
|
$this->date_creation = $this->db->jdate($obj->date_creation);
|
||||||
|
|
@ -337,6 +350,9 @@ class EquipmentConnection extends CommonObject
|
||||||
$conn->fk_carrier = $obj->fk_carrier;
|
$conn->fk_carrier = $obj->fk_carrier;
|
||||||
$conn->position_y = $obj->position_y;
|
$conn->position_y = $obj->position_y;
|
||||||
$conn->path_data = isset($obj->path_data) ? $obj->path_data : null;
|
$conn->path_data = isset($obj->path_data) ? $obj->path_data : null;
|
||||||
|
$conn->junction_connection_id = isset($obj->junction_connection_id) ? $obj->junction_connection_id : null;
|
||||||
|
$conn->junction_x = isset($obj->junction_x) ? $obj->junction_x : null;
|
||||||
|
$conn->junction_y = isset($obj->junction_y) ? $obj->junction_y : null;
|
||||||
$conn->status = $obj->status;
|
$conn->status = $obj->status;
|
||||||
|
|
||||||
$conn->source_label = $obj->source_label;
|
$conn->source_label = $obj->source_label;
|
||||||
|
|
|
||||||
|
|
@ -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'
|
$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'
|
// Possible values for version are: 'development', 'experimental', 'dolibarr', 'dolibarr_deprecated', 'experimental_deprecated' or a version string like 'x.y.z'
|
||||||
$this->version = '9.1';
|
$this->version = '9.2';
|
||||||
// Url to the file with your last numberversion of this module
|
// Url to the file with your last numberversion of this module
|
||||||
//$this->url_last_version = 'http://www.example.com/versionmodule.txt';
|
//$this->url_last_version = 'http://www.example.com/versionmodule.txt';
|
||||||
|
|
||||||
|
|
@ -659,6 +659,9 @@ class modKundenKarte extends DolibarrModules
|
||||||
|
|
||||||
// v8.6.0: has_product Flag für Typen
|
// v8.6.0: has_product Flag für Typen
|
||||||
$this->migrate_v860_has_product();
|
$this->migrate_v860_has_product();
|
||||||
|
|
||||||
|
// v9.2.0: Junction-Verbindungen (Abzweigungen auf Leitungen)
|
||||||
|
$this->migrate_v920_junction_connections();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -1048,6 +1051,29 @@ class modKundenKarte extends DolibarrModules
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Migration v9.2.0: Junction-Verbindungen
|
||||||
|
* Ermöglicht Abzweigungen von bestehenden Leitungen
|
||||||
|
*/
|
||||||
|
private function migrate_v920_junction_connections()
|
||||||
|
{
|
||||||
|
$table = MAIN_DB_PREFIX."kundenkarte_equipment_connection";
|
||||||
|
|
||||||
|
// junction_connection_id - die Verbindung von der abgezweigt wird
|
||||||
|
$resql = $this->db->query("SHOW COLUMNS FROM ".$table." LIKE 'junction_connection_id'");
|
||||||
|
if (!$resql || $this->db->num_rows($resql) == 0) {
|
||||||
|
$this->db->query("ALTER TABLE ".$table." ADD COLUMN junction_connection_id int(11) DEFAULT NULL AFTER fk_target");
|
||||||
|
$this->db->query("ALTER TABLE ".$table." ADD INDEX idx_junction_conn (junction_connection_id)");
|
||||||
|
}
|
||||||
|
|
||||||
|
// junction_x, junction_y - Koordinaten des Abzweigpunkts
|
||||||
|
$resql = $this->db->query("SHOW COLUMNS FROM ".$table." LIKE 'junction_x'");
|
||||||
|
if (!$resql || $this->db->num_rows($resql) == 0) {
|
||||||
|
$this->db->query("ALTER TABLE ".$table." ADD COLUMN junction_x decimal(10,2) DEFAULT NULL AFTER junction_connection_id");
|
||||||
|
$this->db->query("ALTER TABLE ".$table." ADD COLUMN junction_y decimal(10,2) DEFAULT NULL AFTER junction_x");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function called when module is disabled.
|
* Function called when module is disabled.
|
||||||
* Remove from database constants, boxes and permissions from Dolibarr database.
|
* Remove from database constants, boxes and permissions from Dolibarr database.
|
||||||
|
|
|
||||||
|
|
@ -7776,43 +7776,63 @@
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
||||||
// If we're in wire draw mode with a source terminal selected,
|
// If we're in wire draw mode with a source terminal selected,
|
||||||
// create connection from that terminal to the clicked wire's target
|
// create TRUE junction connection to the clicked wire
|
||||||
if (self.wireDrawMode && self.wireDrawSourceEq && connId) {
|
if (self.wireDrawMode && self.wireDrawSourceEq && connId) {
|
||||||
var conn = self.connections.find(function(c) { return c.id == connId; });
|
var conn = self.connections.find(function(c) { return c.id == connId; });
|
||||||
if (conn && conn.fk_target) {
|
if (conn) {
|
||||||
// Create connection from selected terminal to wire's target equipment
|
// Calculate junction point on the wire (snapped to grid)
|
||||||
var sourceEqId = self.wireDrawSourceEq;
|
var svg = self.svgElement;
|
||||||
var sourceTermId = self.wireDrawSourceTerm;
|
var pt = svg.createSVGPoint();
|
||||||
var targetEqId = conn.fk_target;
|
pt.x = e.clientX;
|
||||||
var targetTermId = conn.target_terminal_id || 'input';
|
pt.y = e.clientY;
|
||||||
|
var svgPt = pt.matrixTransform(svg.getScreenCTM().inverse());
|
||||||
|
|
||||||
// Build path: source terminal → existing points → target terminal
|
// Snap to grid
|
||||||
var pathPoints = self.wireDrawPoints.slice(); // Copy existing points
|
var gridSize = self.GRID_SIZE;
|
||||||
|
var junctionX = Math.round(svgPt.x / gridSize) * gridSize;
|
||||||
|
var junctionY = Math.round(svgPt.y / gridSize) * gridSize;
|
||||||
|
|
||||||
// Add target terminal position
|
// Build orthogonal path from source terminal to junction point
|
||||||
var targetEq = self.equipment.find(function(eq) { return eq.id == targetEqId; });
|
var pathPoints = self.wireDrawPoints.slice();
|
||||||
if (targetEq) {
|
if (pathPoints.length === 0) {
|
||||||
var terminals = self.getTerminals(targetEq);
|
// Get source terminal position
|
||||||
var targetPos = self.getTerminalPosition(targetEq, targetTermId, terminals);
|
var srcEq = self.equipment.find(function(eq) { return eq.id == self.wireDrawSourceEq; });
|
||||||
if (targetPos) {
|
if (srcEq) {
|
||||||
pathPoints.push({x: targetPos.x, y: targetPos.y});
|
var srcTerminals = self.getTerminals(srcEq);
|
||||||
|
var srcPos = self.getTerminalPosition(srcEq, self.wireDrawSourceTerm, srcTerminals);
|
||||||
|
if (srcPos) {
|
||||||
|
pathPoints.push({x: srcPos.x, y: srcPos.y});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add orthogonal bend point if needed (go vertical first, then horizontal)
|
||||||
|
if (pathPoints.length > 0) {
|
||||||
|
var lastPt = pathPoints[pathPoints.length - 1];
|
||||||
|
// Add intermediate point for orthogonal routing
|
||||||
|
if (lastPt.x !== junctionX && lastPt.y !== junctionY) {
|
||||||
|
pathPoints.push({x: lastPt.x, y: junctionY});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pathPoints.push({x: junctionX, y: junctionY});
|
||||||
|
|
||||||
// Build path string
|
// Build path string
|
||||||
var pathData = '';
|
var pathData = '';
|
||||||
for (var i = 0; i < pathPoints.length; i++) {
|
for (var i = 0; i < pathPoints.length; i++) {
|
||||||
pathData += (i === 0 ? 'M' : 'L') + ' ' + pathPoints[i].x + ' ' + pathPoints[i].y + ' ';
|
pathData += (i === 0 ? 'M' : 'L') + ' ' + pathPoints[i].x + ' ' + pathPoints[i].y + ' ';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store connection values to inherit
|
// Store junction info and show dialog
|
||||||
self._inheritFromConnection = conn;
|
self._inheritFromConnection = conn;
|
||||||
self._pendingPathData = pathData.trim() || null;
|
self._pendingPathData = pathData.trim();
|
||||||
|
self._pendingJunction = {
|
||||||
|
connection_id: conn.id,
|
||||||
|
x: junctionX,
|
||||||
|
y: junctionY
|
||||||
|
};
|
||||||
|
|
||||||
// Clear source terminal but keep draw mode active
|
|
||||||
self.cleanupWireDrawState(true);
|
self.cleanupWireDrawState(true);
|
||||||
|
self.showJunctionDialog(self.wireDrawSourceEq, self.wireDrawSourceTerm, conn);
|
||||||
self.showConnectionLabelDialog(sourceEqId, sourceTermId, targetEqId, targetTermId);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -7842,34 +7862,49 @@
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
||||||
// If in wire draw mode with source terminal, connect to output's source
|
// If in wire draw mode, create junction to this output
|
||||||
if (self.wireDrawMode && self.wireDrawSourceEq && connId) {
|
if (self.wireDrawMode && self.wireDrawSourceEq && connId) {
|
||||||
var conn = self.connections.find(function(c) { return c.id == connId; });
|
var conn = self.connections.find(function(c) { return c.id == connId; });
|
||||||
if (conn && conn.fk_source) {
|
if (conn) {
|
||||||
var sourceEqId = self.wireDrawSourceEq;
|
// Calculate junction point
|
||||||
var sourceTermId = self.wireDrawSourceTerm;
|
var svg = self.svgElement;
|
||||||
var targetEqId = conn.fk_source;
|
var pt = svg.createSVGPoint();
|
||||||
var targetTermId = conn.source_terminal_id || 'output';
|
pt.x = e.clientX;
|
||||||
|
pt.y = e.clientY;
|
||||||
|
var svgPt = pt.matrixTransform(svg.getScreenCTM().inverse());
|
||||||
|
|
||||||
// Build path with existing points
|
var gridSize = self.GRID_SIZE;
|
||||||
|
var junctionX = Math.round(svgPt.x / gridSize) * gridSize;
|
||||||
|
var junctionY = Math.round(svgPt.y / gridSize) * gridSize;
|
||||||
|
|
||||||
|
// Build orthogonal path
|
||||||
var pathPoints = self.wireDrawPoints.slice();
|
var pathPoints = self.wireDrawPoints.slice();
|
||||||
var targetEq = self.equipment.find(function(eq) { return eq.id == targetEqId; });
|
if (pathPoints.length === 0) {
|
||||||
if (targetEq) {
|
var srcEq = self.equipment.find(function(eq) { return eq.id == self.wireDrawSourceEq; });
|
||||||
var terminals = self.getTerminals(targetEq);
|
if (srcEq) {
|
||||||
var targetPos = self.getTerminalPosition(targetEq, targetTermId, terminals);
|
var srcTerminals = self.getTerminals(srcEq);
|
||||||
if (targetPos) {
|
var srcPos = self.getTerminalPosition(srcEq, self.wireDrawSourceTerm, srcTerminals);
|
||||||
pathPoints.push({x: targetPos.x, y: targetPos.y});
|
if (srcPos) pathPoints.push({x: srcPos.x, y: srcPos.y});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (pathPoints.length > 0) {
|
||||||
|
var lastPt = pathPoints[pathPoints.length - 1];
|
||||||
|
if (lastPt.x !== junctionX && lastPt.y !== junctionY) {
|
||||||
|
pathPoints.push({x: lastPt.x, y: junctionY});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pathPoints.push({x: junctionX, y: junctionY});
|
||||||
|
|
||||||
var pathData = '';
|
var pathData = '';
|
||||||
for (var i = 0; i < pathPoints.length; i++) {
|
for (var i = 0; i < pathPoints.length; i++) {
|
||||||
pathData += (i === 0 ? 'M' : 'L') + ' ' + pathPoints[i].x + ' ' + pathPoints[i].y + ' ';
|
pathData += (i === 0 ? 'M' : 'L') + ' ' + pathPoints[i].x + ' ' + pathPoints[i].y + ' ';
|
||||||
}
|
}
|
||||||
|
|
||||||
self._inheritFromConnection = conn;
|
self._inheritFromConnection = conn;
|
||||||
self._pendingPathData = pathData.trim() || null;
|
self._pendingPathData = pathData.trim();
|
||||||
|
self._pendingJunction = { connection_id: conn.id, x: junctionX, y: junctionY };
|
||||||
self.cleanupWireDrawState(true);
|
self.cleanupWireDrawState(true);
|
||||||
self.showConnectionLabelDialog(sourceEqId, sourceTermId, targetEqId, targetTermId);
|
self.showJunctionDialog(self.wireDrawSourceEq, self.wireDrawSourceTerm, conn);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -10746,6 +10781,160 @@
|
||||||
setTimeout(function() { $('#conn-label').focus(); }, 100);
|
setTimeout(function() { $('#conn-label').focus(); }, 100);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Dialog for junction connections (terminal to wire)
|
||||||
|
showJunctionDialog: function(sourceEqId, sourceTermId, targetConn) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
var sourceEq = this.equipment.find(function(e) { return e.id == sourceEqId; });
|
||||||
|
|
||||||
|
// Inherit values from target connection
|
||||||
|
var defaultType = targetConn.connection_type || 'L1N';
|
||||||
|
var defaultColor = targetConn.color || this.COLORS.connection;
|
||||||
|
var defaultMedium = targetConn.medium_type || '';
|
||||||
|
var defaultLength = targetConn.medium_length || '';
|
||||||
|
|
||||||
|
var html = '<div id="schematic-conn-dialog" class="kundenkarte-modal visible">';
|
||||||
|
html += '<div class="kundenkarte-modal-content" style="max-width:450px;">';
|
||||||
|
html += '<div class="kundenkarte-modal-header"><h3>Abzweigung erstellen</h3>';
|
||||||
|
html += '<span class="kundenkarte-modal-close">×</span></div>';
|
||||||
|
html += '<div class="kundenkarte-modal-body">';
|
||||||
|
|
||||||
|
html += '<div style="margin-bottom:15px;padding:10px;background:#2a2a2a;border-radius:4px;">';
|
||||||
|
html += '<strong style="color:#3498db;">' + this.escapeHtml((sourceEq ? sourceEq.label || sourceEq.type_label_short : 'Gerät')) + '</strong>';
|
||||||
|
html += ' <i class="fa fa-arrow-right" style="color:#888;margin:0 10px;"></i> ';
|
||||||
|
html += '<strong style="color:#f39c12;"><i class="fa fa-code-fork"></i> Abzweigung</strong>';
|
||||||
|
html += '</div>';
|
||||||
|
|
||||||
|
html += '<div class="form-group" style="margin-bottom:12px;">';
|
||||||
|
html += '<label style="display:block;margin-bottom:5px;color:#aaa;">Bezeichnung / Stromkreis</label>';
|
||||||
|
html += '<input type="text" id="conn-label" class="flat" style="width:100%;padding:8px;" placeholder="z.B. Küche Steckdosen">';
|
||||||
|
html += '</div>';
|
||||||
|
|
||||||
|
html += '<div class="form-group" style="margin-bottom:12px;">';
|
||||||
|
html += '<label style="display:block;margin-bottom:5px;color:#aaa;">Typ</label>';
|
||||||
|
html += '<div style="display:flex;gap:8px;flex-wrap:wrap;">';
|
||||||
|
|
||||||
|
var typePresets = ['L1', 'L2', 'L3', 'N', 'PE', 'L1N', '3P'];
|
||||||
|
typePresets.forEach(function(t) {
|
||||||
|
var color = self.PHASE_COLORS[t] || self.COLORS.connection;
|
||||||
|
var isSelected = (t === defaultType);
|
||||||
|
var outlineStyle = isSelected ? 'outline:2px solid #fff;' : '';
|
||||||
|
html += '<button type="button" class="conn-type-btn" data-type="' + t + '" data-color="' + color + '" ';
|
||||||
|
html += 'style="padding:5px 12px;background:' + color + ';color:#fff;border:none;border-radius:3px;cursor:pointer;font-size:12px;' + outlineStyle + '">';
|
||||||
|
html += t + '</button>';
|
||||||
|
});
|
||||||
|
|
||||||
|
html += '</div>';
|
||||||
|
html += '<input type="hidden" id="conn-type" value="' + self.escapeHtml(defaultType) + '">';
|
||||||
|
html += '<input type="hidden" id="conn-color" value="' + self.escapeHtml(defaultColor) + '">';
|
||||||
|
html += '</div>';
|
||||||
|
|
||||||
|
html += '<div class="form-group">';
|
||||||
|
html += '<label style="display:block;margin-bottom:5px;color:#aaa;">Kabel (optional)</label>';
|
||||||
|
html += '<div style="display:flex;gap:8px;">';
|
||||||
|
html += '<input type="text" id="conn-medium" class="flat" style="flex:1;padding:8px;" placeholder="z.B. NYM-J 3x1.5" value="' + self.escapeHtml(defaultMedium) + '">';
|
||||||
|
html += '<input type="text" id="conn-length" class="flat" style="width:80px;padding:8px;" placeholder="Länge" value="' + self.escapeHtml(defaultLength) + '">';
|
||||||
|
html += '</div>';
|
||||||
|
html += '</div>';
|
||||||
|
|
||||||
|
html += '</div>';
|
||||||
|
html += '<div class="kundenkarte-modal-footer">';
|
||||||
|
html += '<button type="button" class="button" id="conn-save"><i class="fa fa-check"></i> Erstellen</button> ';
|
||||||
|
html += '<button type="button" class="button" id="conn-cancel">Abbrechen</button>';
|
||||||
|
html += '</div></div></div>';
|
||||||
|
|
||||||
|
$('body').append(html);
|
||||||
|
|
||||||
|
// Type preset buttons
|
||||||
|
$('.conn-type-btn').on('click', function() {
|
||||||
|
$('.conn-type-btn').css('outline', 'none');
|
||||||
|
$(this).css('outline', '2px solid #fff');
|
||||||
|
$('#conn-type').val($(this).data('type'));
|
||||||
|
$('#conn-color').val($(this).data('color'));
|
||||||
|
});
|
||||||
|
|
||||||
|
// Save junction
|
||||||
|
$('#conn-save').on('click', function() {
|
||||||
|
var label = $('#conn-label').val();
|
||||||
|
var connType = $('#conn-type').val();
|
||||||
|
var color = $('#conn-color').val();
|
||||||
|
var medium = $('#conn-medium').val();
|
||||||
|
var length = $('#conn-length').val();
|
||||||
|
|
||||||
|
var pathData = self._pendingPathData || null;
|
||||||
|
var junction = self._pendingJunction || null;
|
||||||
|
self._pendingPathData = null;
|
||||||
|
self._pendingJunction = null;
|
||||||
|
|
||||||
|
self.createJunctionConnection(sourceEqId, sourceTermId, {
|
||||||
|
label: label,
|
||||||
|
type: connType,
|
||||||
|
color: color,
|
||||||
|
medium: medium,
|
||||||
|
length: length,
|
||||||
|
pathData: pathData,
|
||||||
|
junction: junction
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#schematic-conn-dialog').remove();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Cancel
|
||||||
|
$('#conn-cancel, .kundenkarte-modal-close').on('click', function() {
|
||||||
|
$('#schematic-conn-dialog').remove();
|
||||||
|
self._pendingPathData = null;
|
||||||
|
self._pendingJunction = null;
|
||||||
|
});
|
||||||
|
|
||||||
|
setTimeout(function() { $('#conn-label').focus(); }, 100);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Create junction connection (branches from existing wire)
|
||||||
|
createJunctionConnection: function(sourceEqId, sourceTermId, options) {
|
||||||
|
var self = this;
|
||||||
|
options = options || {};
|
||||||
|
|
||||||
|
var data = {
|
||||||
|
action: 'create',
|
||||||
|
fk_source: sourceEqId,
|
||||||
|
source_terminal_id: sourceTermId,
|
||||||
|
fk_target: '', // No target equipment for junction
|
||||||
|
target_terminal_id: '',
|
||||||
|
connection_type: options.type || 'L1N',
|
||||||
|
color: options.color || self.COLORS.connection,
|
||||||
|
output_label: options.label || '',
|
||||||
|
medium_type: options.medium || '',
|
||||||
|
medium_length: options.length || '',
|
||||||
|
path_data: options.pathData || '',
|
||||||
|
token: $('input[name="token"]').val()
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add junction info
|
||||||
|
if (options.junction) {
|
||||||
|
data.junction_connection_id = options.junction.connection_id;
|
||||||
|
data.junction_x = options.junction.x;
|
||||||
|
data.junction_y = options.junction.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: baseUrl + '/custom/kundenkarte/ajax/equipment_connection.php',
|
||||||
|
method: 'POST',
|
||||||
|
data: data,
|
||||||
|
dataType: 'json',
|
||||||
|
success: function(response) {
|
||||||
|
if (response.success) {
|
||||||
|
self.showMessage('Abzweigung erstellt!', 'success');
|
||||||
|
self.loadConnections();
|
||||||
|
} else {
|
||||||
|
self.showMessage('Fehler: ' + response.error, 'error');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function() {
|
||||||
|
self.showMessage('Verbindungsfehler', 'error');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
updateConnectionPreview: function(e) {
|
updateConnectionPreview: function(e) {
|
||||||
if (!this.selectedTerminal) return;
|
if (!this.selectedTerminal) return;
|
||||||
|
|
||||||
|
|
|
||||||
4
sw.js
4
sw.js
|
|
@ -3,8 +3,8 @@
|
||||||
* Offline-First für Schaltschrank-Dokumentation
|
* Offline-First für Schaltschrank-Dokumentation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const CACHE_NAME = 'kundenkarte-pwa-v9.2';
|
const CACHE_NAME = 'kundenkarte-pwa-v9.3';
|
||||||
const OFFLINE_CACHE = 'kundenkarte-offline-v9.2';
|
const OFFLINE_CACHE = 'kundenkarte-offline-v9.3';
|
||||||
|
|
||||||
// Statische Assets die immer gecached werden (ohne Query-String)
|
// Statische Assets die immer gecached werden (ohne Query-String)
|
||||||
const STATIC_ASSETS = [
|
const STATIC_ASSETS = [
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue