Community
    • Categories
    • Recent
    • Popular
    • Users
    • Search
    • Register
    • Login

    Switch Ports Sortierung

    Scheduled Pinned Locked Moved Betrieb
    13 Posts 2 Posters 524 Views 2 Watching
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • LFischerL Offline
      LFischer @StefanP74
      last edited by

      Hallo @StefanP74,

      das Thema "Sortierung" ist leider sehr schwierig, da es gefühlt keinen richtigen Weg gibt, der alle glücklich macht. Aktuell gibt es eine Reihe an Bedingungen für die Verkabelungsansicht:

      • Um intern verkabelte Anschlüsse beieinander zu halten, werden diese so gut es geht zusammen sortiert (Eingang und Ausgang auf gleicher höhe)
      • Intern nicht verkabelte Anschlüsse werden nach unten sortiert, damit die interne Verkabelung etwas ordentlicher wird
      • Anschlussnamen werden aufgesplittet und numerisch sowie alphabetisch sortiert (sodass "Port 9" vor "Port 10" kommt)

      Nachdem diese Regeln durchlaufen sind, bleibt es aber weiterhin so, dass wir von links nach rechts sortieren. In deinem Fall führt das leider zu einem unschönen Ergebnis, da die rechte Seite nicht weiter sortiert wird, um die vorherige Logik nicht zunichte zu machen.

      Ich glaube, die einzige "saubere" Lösung wäre, eine optionale Sortierung pro Seite (Ein- und Ausgänge) anzubieten. Das ist jedoch mit erheblichem Aufwand verbunden 😞 Ich weiß nicht, ob wir das in nächster Zeit angehen werden.

      Ich hoffe ich konnte zumindest etwas Licht ins Dunkle bringen

      Viele Grüße
      Leo

      StefanP74S 1 Reply Last reply Reply Quote 0
      • StefanP74S Offline
        StefanP74 @LFischer
        last edited by

        Hallo @LFischer,

        danke für die Info, ich verstehe es nur nicht ganz ... seitens der Programmierlogik.
        Meine Gedanken zu dem Thema, vielleicht sehe ich das auch zu locker. 😉

        Wenn ich einen Eingang mit einem Ausgang verbunden habe, dann ist nur die Sortierung der Eingänge (also links) nötig, da die beiden mit einander verbunden sind und der Ausgang entsprechend gereiht wird, anhand der Abhängigkeit zum Eingang.

        Hat ein Eingang mehrere Ausgänge, dann werden zusätzlich die Ausgänge mit Abhängigkeit zum jeweiligen Eingang, ebenso sortiert.

        Hat ein Eingang keine Abhängigkeit zu einem Ausgang, dann werden diese zB. unten, aber dennoch sortiert angezeigt, Eingang wie auch Ausgang.

        LG Stefan

        LFischerL 1 Reply Last reply Reply Quote 0
        • LFischerL Offline
          LFischer @StefanP74
          last edited by

          Hallo @StefanP74

          ich glaube genau dieser Fall wird aktuell nicht berücksichtigt 🤔

          Hat ein Eingang mehrere Ausgänge, dann werden zusätzlich die Ausgänge mit Abhängigkeit zum jeweiligen Eingang, ebenso sortiert.

          Ich werde mir das aber noch mal lokal nachbauen und anschauen. Vielleicht lässt es sich ja doch noch irgendwie einbauen ohne etwas anderes kaputt zu machen 😉

          Viele Grüße
          Leo

          StefanP74S 1 Reply Last reply Reply Quote 0
          • StefanP74S Offline
            StefanP74 @LFischer
            last edited by

            Hallo @LFischer,

            ich lege meine Hoffnung in deine Hände 😁
            Danke, wäre toll wenn das klappen würde.

            LG Stefan

            LFischerL 1 Reply Last reply Reply Quote 0
            • LFischerL Offline
              LFischer @StefanP74
              last edited by LFischer

              Hey @StefanP74

              ich glaube ich habe etwas gefunden - könntest du das vielleicht kurz bei dir ausprobieren und schauen ob es ggf. zu unerwünschten Seiteneffekten kommt? Ich habe das mit der Add-on Version 1.4 geprüft.

              Dazu bitte in die folgende Datei navigieren (ausgehend vom i-doit Verzeichnis) src/classes/modules/cabling/assets/js/cabling.js

              Hier auf Zeile 254 steht folgendes:

              // Then sort by "toIndex" to keep internally wired connectors near by each other.
              if (a.data.toIndex && b.data.toIndex) {
                  return a.data.toIndex - b.data.toIndex
              }
              

              Das bitte mal mit folgender kleinen Änderung anpassen:

              // Then sort by "toIndex" to keep internally wired connectors near by each other.
              if (a.data.toIndex && b.data.toIndex && a.data.toIndex !== b.data.toIndex) {
                  return a.data.toIndex - b.data.toIndex
              }
              

              Das Problem ist nämlich das die Ausgänge alle auf den gleichen Eingang zeigen - bedeutet hier das der a.data.toIndex und b.data.toIndex den identischen Wert beinhalten. Das Ergebnis der Sortierung ist in diesem Fall 0 was so viel heißt wie: "Bleib wo du bist".

              In diesem Fall soll aber die Sortierung nach Namen übernehmen. Aus diesem Grund ergänzen wir die Bedingung um a.data.toIndex ist ungleich b.data.toIndex.

              Wenn das soweit passt würde ich das im Code übernehmen sodass diese Anpassung in der nächsten Version landet 🙂

              Viele Grüße
              Leo

              StefanP74S 1 Reply Last reply Reply Quote 0
              • StefanP74S Offline
                StefanP74 @LFischer
                last edited by

                Hallo @LFischer,

                best support ever! 😄 👍
                Funktioniert hervorragend, sehr fein, danke.

                idoit_port_no_20240930_01.JPG

                Super, danke.
                Ich konnte bei den anderen Verbindungen (bis auf das noch bestehende Problem "chaotische Verkabelung", bei nachträglich angelegten Ports) nichts negatives feststellen.

                Problem chaotische Verkabelung:
                idoit_port_chaos_20240830_01.JPG
                Das ist wohl ein ganz anderes Thema.

                Danke jedenfalls für den super tollen raschen Fix.
                Wenn du heute Abend das Gefühl hast "hääää was war das denn?" ... das war ich, ich habe ein paar Bier auf dich getrunken 😁

                LG Stefan

                LFischerL 1 Reply Last reply Reply Quote 0
                • LFischerL Offline
                  LFischer @StefanP74
                  last edited by LFischer

                  Hey @StefanP74

                  freut mich das ich dir damit weiterhelfen konnte 😄 Bzgl. dem "Chaotische Verkabelung" Problem - ist das erst durch den Fix geschehen? Denn genau den zuständigen Code habe ich angepasst...

                  Wäre natürlich schön wenn der Fix nur Probleme löst anstatt auch neue zu schaffen 😞

                  Ich schaue mal ob ich auch dieses Problem nachvollziehen (und ggf. fixen) kann

                  VG Leo

                  edit

                  3479e8b6-ff8a-4e86-b34a-497faf203a50-image.png

                  Okay, ich kann es nachstellen... Mal sehen ob ich das auch noch hinbekomme 😄

                  edit 2

                  Ich glaube auch hier habe ich das Problem gefunden... Es ist aber etwa schwieriger zu lösen 😕 Es ist nämlich so dass die toIndex Werte vom Backend vorbereitet werden... Die Sortierung passiert dann aber im Frontend und ändert die Indexe, sodass diese dann nicht mehr korrekt sind.
                  Mal sehen wie ich das löse 😄

                  StefanP74S 1 Reply Last reply Reply Quote 0
                  • StefanP74S Offline
                    StefanP74 @LFischer
                    last edited by StefanP74

                    @LFischer

                    nein, das ist nicht neu dazugekommen.

                    Edit: Wäre genial wenn du das lösen könntest. 🖖

                    LG Stefan

                    LFischerL 1 Reply Last reply Reply Quote 0
                    • LFischerL Offline
                      LFischer @StefanP74
                      last edited by LFischer

                      Hey @StefanP74

                      ich war ein wenig fleißig und habe etwas erarbeitet 😉 Dieses mal betrifft es aber ein paar mehr Zeilen - ich glaube es ist einfacher die komplette Datei zu tauschen. Leider ist es im Forum nicht möglich die ganze Datei hochzuladen...

                      /**
                       * i-doit cabling visualization javascript base class.
                       *
                       * @author  Leonard Fischer <lfischer@i-doit.com>
                       */
                      window.Cabling = Class.create({
                          $element:      null,
                          data:          null,
                          cache:         null,
                          svg:           null,
                          vis:           null,
                          zoom:          null,
                          options:       {},
                          indexMapping:  [],
                          rootContainer: {
                              height:   0,
                              matching: []
                          },
                      
                          getOptions: function () {
                              return this.options;
                          },
                      
                          getOption: function (option) {
                              return this.options[option];
                          },
                      
                          setOption: function (option, value) {
                              this.options[option] = value;
                      
                              return this;
                          },
                      
                          getSelectedElements: function () {
                              // This method should be used to get all selected cable paths.
                              // this.svg.selectAll('.selected');
                          },
                      
                          initialize: function ($el, data, options) {
                              var that = this;
                      
                              that.$element = $el;
                              that.data = data || [];
                              that.options = {
                                  authEdit:               false, // Defines if the cabling view will allow any editing.
                                  minZoomLevel:           0.1,   // Defines the minimal zoom level.
                                  maxZoomLevel:           1.5,   // Defines the maximal zoom level.
                                  objectTypeData:         {},    // JSON with all necessary object type data (name, color, ...).
                                  connectorTypeData:      {},    // JSON with all necessary connector type data (name, color, ...).
                                  objectTypeFilter:       [],    // Array pf object types, that shall not be displayed.
                                  onAfterProcess:         null,  // 'Complete' event for when the rendering has finished.
                                  onObjSelect:            null,  // Click event for a object node.
                                  onObjUnselect:          null,  // Event for when a object gets unselected.
                                  onCableSelect:          null,  // Click event for a cable.
                                  onConnectorSelect:      null,  // Click event for a connector.
                                  onConnectorUnselect:    null,  // Event for when a connector gets unselected.
                                  onObjAcceptDrag:        null,  // Event for when a object gets unselected.
                                  onObjAbortDrag:         null,  // Event for when a object gets unselected.
                                  width:                  null,  // This can be used to change the viewpoints width. The SVG element will always remain 100%x100%.
                                  height:                 null,  // This can be used to change the viewpoints height. The SVG element will always remain 100%x100%.
                                  undefinedConnectorType: {
                                      color: '#fff',
                                      title: '-'
                                  },                             // Default 'connector type' object.
                                  undefinedObjectType:    {
                                      color: '#fff',
                                      title: '-'
                                  },                             // Default 'object type' object.
                                  nodeWidth:              150,   // Define the node width.
                                  nodeHeight:             20,    // Define the node heigt.
                                  nodeMarginX:            25,    // Define the horizontal margin between nodes.
                                  nodeMarginY:            25,    // Define the vertical margin between nodes.
                                  displayWiring:          false, // Define if the internal wiring shall be displayed (object boxes will get transparent).
                                  showCableLabels:        false, // Define if cables shall be displayed.
                                  clickableConnectors:    false  // Define if connectors shall be clickable.
                              };
                      
                              that.rootContainer = {
                                  height:   0,
                                  matching: []
                              };
                      
                              // Setting the default width and height.
                              that.options.width = that.$element.getWidth();
                              that.options.height = that.$element.getHeight() + 16;
                      
                              Object.extend(that.options, options || {});
                      
                              that.svg = d3.select($el).append('svg')
                                           .attr('width', that.options.width)
                                           .attr('height', that.options.height);
                      
                              that
                                  .svg.append('rect')
                                  .attr('width', that.options.width)
                                  .attr('height', that.options.height)
                                  .style('fill', 'none')
                                  .style('pointer-events', 'all');
                      
                              // Here we set the <g> after the <rect>, this is necessary for dragging and zooming but still clicking elements inside <g>.
                              that.vis = this.svg.append("g");
                      
                              that.zoom = d3.zoom()
                                  .scaleExtent([
                                      that.options.minZoomLevel,
                                      that.options.maxZoomLevel
                                  ])
                                  .on('zoom', function () {
                                      that.vis.attr('transform', d3.event.transform);
                                  });
                      
                              that.svg
                                  .call(that.zoom)
                                  .call(that.zoom.transform, d3.zoomIdentity.translate(that.options.width / 2, that.options.height / 2));
                      
                              this.appendStyle();
                      
                              return this;
                          },
                      
                          appendStyle: function () {
                              // This method is necessary to include the SVG styles - this will be used in the SVG export.
                              var defs   = this.svg.select('defs'),
                                  isIE11 = !!window.MSInputMethodContext && !!document.documentMode;
                      
                              if (defs.node() === null) {
                                  defs = this.svg.append('defs');
                      
                                  defs.append('style').attr('type', 'text/css').text(
                                      ".cabling-object { \
                                          fill: none;\
                                          stroke: #444;\
                                          stroke-width: 1px;\
                                      }\
                                      text {\
                                          font-family: \"Helvetica Neue\", \"Lucida Grande\", \"Tahoma\", Arial, serif;\
                                          font-size: 11px;\
                                          paint-order: stroke;\
                                          stroke: transparent;\
                                          stroke-width: 0;\
                                          fill: #000;\
                                      }\
                                      text.connector-left-title,\
                                      text.connector-right-title {\
                                          stroke-width: 5px;\
                                          stroke: transparent;\
                                      }\
                                      text.connector-left-title.stroked,\
                                      text.connector-right-title.stroked {\
                                          " + (isIE11 ? "stroke-width: 0;" : "stroke-width: 5px;") + "\
                                          stroke: #fff;\
                                      }\
                                      text.title,\
                                      .linkname text,\
                                      .linkname.clicked rect,\
                                      .clicked rect.title {\
                                          fill: #fff;\
                                      }\
                                      text.title {\
                                          font-weight: bold;\
                                      }\
                                      .linkname rect,\
                                      .linkname.clicked text {\
                                          fill: #000;\
                                      }\
                                      rect.title,\
                                      .clicked text.title {\
                                          fill: #222;\
                                      }\
                                      circle.connector {\
                                          stroke: rgba(0, 0, 0, 0.75);\
                                          stroke-width: 1;\
                                      }\
                                      circle.connector-inner {\
                                          fill: rgba(0, 0, 0, 0.75);\
                                          stroke: none;\
                                      }\
                                      path {\
                                          fill: none;\
                                          stroke: #555;\
                                          stroke-width: 2;\
                                      }"
                                  );
                              }
                          },
                      
                          textFormat: function (text, width) {
                              var result = text;
                      
                              if (width <= 0) {
                                  return '';
                              }
                      
                              d3.select(this).text(result);
                      
                              while (this.getComputedTextLength() > width) {
                                  result = result.substring(0, (result.length - 2));
                                  d3.select(this).text(result);
                              }
                      
                              if (result !== text && width > 2) {
                                  result += '..';
                              }
                      
                              return result;
                          },
                      
                          clearCanvas: function () {
                              this.vis.selectAll('*').remove();
                      
                              this.rootContainer = {
                                  height:   0,
                                  matching: []
                              };
                          },
                      
                          responsive: function () {
                              this.options.width = this.$element.getWidth();
                              this.options.height = this.$element.getHeight() + 16;
                      
                              return this;
                          },
                      
                          preProcess: function () {
                              return this;
                          },
                      
                          process: function () {
                              this.indexMapping = [];
                      
                              return this.preProcess().processSide('left').processSide('right').postProcess();
                          },
                      
                          processSide: function (dir) {
                              var that    = this,
                                  invertX = (dir === 'right'),
                                  cache = this.data[dir];
                      
                              // @see CABLING-49 Implement proper calculation for 'separation'.
                              var tree = d3.tree()
                                  .separation((a, b) => Math.max(1, (a.children || []).length, (b.children || []).length))
                                  .nodeSize([
                                      (that.options.nodeHeight + that.options.nodeMarginY),
                                      (that.options.nodeWidth + that.options.nodeMarginX)
                                  ]);
                      
                              var root = d3.stratify()(cache)
                                  .sort(function (a, b) {
                                      // First sort by 'connected-index' to keep internally wired connectors near by each other.
                                      if (dir === 'right' && a.data.siblingId && b.data.siblingId && a.data.siblingId !== b.data.siblingId) {
                                          // @see CABLING-58 Use the newly created indexMapping to find the proper index.
                                          return this.indexMapping.findIndex((d) => d == a.data.siblingId) - this.indexMapping.findIndex((d) => d == b.data.siblingId);
                                      }
                      
                                      // @see  CABLING-36  Any "unconnected" connector will be moved down, so that no wires cross each other.
                                      if (a.data.siblingId && !b.data.siblingId) {
                                          return -1;
                                      }
                      
                                      if (!a.data.siblingId && b.data.siblingId) {
                                          return 1;
                                      }
                      
                                      // @see CABLING-19 Following code will try to sort the connectors in a more natural way!
                      
                                      // First we split by "non-word" characters (like dots, slashes etc.).
                                      var aParts = a.data.title.split(/\W/),
                                          bParts = b.data.title.split(/\W/),
                                          minParts = Math.min(aParts.length, bParts.length), comparison, i;
                      
                                      for (i = 0; i < minParts; i++) {
                                          if (isNumeric(aParts[i]) && isNumeric(bParts[i])) {
                                              comparison = aParts[i] - bParts[i];
                                          } else {
                                              comparison = aParts[i].localeCompare(bParts[i]);
                                          }
                      
                                          if (comparison !== 0) {
                                              return comparison;
                                          }
                                      }
                      
                                      // If nothing worked out, use the default:
                                      return a.data.title.localeCompare(b.data.title);
                                  }.bind(this));
                      
                              if (dir === 'left') {
                                  this.indexMapping = root.children.map((d) => d.data.id);
                              }
                      
                              var connectorTranslate = function (d) {
                                  if (that.options.clickableConnectors) {
                                      if (d.parent === null || d.parent && d.parent.id === 'root') {
                                          return 'translate(' + (invertX ? 5 : -5) + ',0)';
                                      }
                      
                                      if (d.data.inner) {
                                          return 'translate(' + (invertX ? -5 : that.options.nodeWidth+5) + ',0)';
                                      } else {
                                          return 'translate(' + (invertX ? that.options.nodeWidth+5 : -(that.options.nodeWidth+5)) + ',0)';
                                      }
                                  } else {
                                      if (d.parent === null || d.parent && d.parent.id === 'root') {
                                          return 'translate(0,0)';
                                      }
                      
                                      if (d.data.inner) {
                                          return 'translate(' + (invertX ? 0 : that.options.nodeWidth) + ',0)';
                                      } else {
                                          return 'translate(' + (invertX ? that.options.nodeWidth : -that.options.nodeWidth) + ',0)';
                                      }
                                  }
                              };
                      
                              var linkData = tree(root).links();
                      
                              var cable = that.vis
                                  .selectAll(".cable.cable-" + dir)
                                  .data(linkData);
                      
                              cable
                                  .enter().append("path")
                                  .style("opacity", 0)
                                  .attr("class", "cable cable-" + dir);
                      
                              // After the link data is assigned, we reduce the data to only hold cable information.
                              linkData = linkData.filter(function (d) {
                                  return d.source.id !== 'root' && d.source.data.outer;
                              });
                      
                              // @see  CABLING-35  Show internal cabling
                              that.vis
                                  .selectAll('.internal-link.internal-link-' + dir)
                                  .data((root.children || []).filter((d) => d.data.wiredToItself))
                                  .enter()
                                  .append("path")
                                  .style("opacity", 0)
                                  .attr('class', 'internal-link internal-link-' + dir)
                                  .attr('d', function (d) {
                                      const connection = (root.children || []).find(function (conn) { return conn.id == d.data.connectorId});
                      
                                      if (!connection) {
                                          return '';
                                      }
                      
                                      d.y -= 20;
                                      var xBetween = d.y + 30;
                                      const yBetween = ((d.x + connection.x) / 2);
                      
                                      // Mirror the coordinates for the left side.
                                      if (dir === 'left') {
                                          d.y *= -1;
                                          xBetween *= -1;
                                      }
                      
                      
                                      return 'M' + d.y + ',' + d.x +
                                             ' C' + xBetween + ',' + d.x + ' ' + xBetween + ',' + yBetween + ' ' + xBetween + ',' + yBetween;
                                  })
                                  .interrupt()
                                  .transition().duration(500)
                                  .transition().duration(250)
                                  .style("opacity", 1);
                      
                              var cableLabel = that.vis
                                  .selectAll(".linkname.linkname-" + dir)
                                  .data(linkData)
                                  .enter()
                                  .append("g")
                                  .style("opacity", 0)
                                  .attr("class", "linkname linkname-" + dir)
                                  .attr('data-id', function (d) {
                                      return d.source.data.cableId;
                                  });
                      
                              that.vis
                                  .selectAll(".cable.cable-" + dir)
                                  .classed('cable-root', function (d) {
                                      return (d.source.id === 'root');
                                  })
                                  .interrupt().transition().duration(500)
                                  .attr("d", function (d) {
                                      var fromX  = (d.source.y + (that.options.showCableLabels ? 50 : 125)),
                                          fromX2 = (fromX+20),
                                          fromX3 = (fromX+40),
                                          fromY  = d.source.x,
                                          toX    = (d.target.y + (that.options.showCableLabels ? 50 : 125)),
                                          toY    = d.target.x;
                      
                                      if (d.target.data.doubling) {
                                          toX += 20;
                                      }
                      
                                      if (!invertX) {
                                          fromX *= -1;
                                          fromX2 *= -1;
                                          fromX3 *= -1;
                                          toX *= -1;
                                      }
                      
                                      return "M" + fromX + "," + fromY +
                                             "C" + fromX2 + "," + fromY + " " + fromX2 + "," + toY + " " + fromX3 + "," + toY +
                                             "L" + toX + "," + toY;
                                  })
                                  .transition().duration(250)
                                  .style("opacity", 1)
                                  .style('stroke-dasharray', function (d) {
                                      if (d.target.data.doubling) {
                                          return '2,2';
                                      }
                      
                                      return null;
                                  });
                      
                              cable
                                  .exit()
                                  .interrupt().transition().duration(500)
                                  .style("opacity", 0)
                                  .remove();
                      
                              cableLabel
                                  .append('rect')
                                  .attr('class', 'mouse-pointer')
                                  .attr('height', 14)
                                  .attr('width', 125)
                                  .attr('data-id', function (d) {
                                      return d.source.cableId
                                  })
                                  .on('click', that.selectCableObject.bind(this));
                      
                              cableLabel
                                  .append('text')
                                  .attr('class', 'mouse-pointer')
                                  .attr('dy', 10)
                                  .attr('x', 62.5)
                                  .style('text-anchor', 'middle')
                                  .text(function (d) {
                                      return d.source.data.cableTitle;
                                  })
                                  .on('click', that.selectCableObject.bind(this));
                      
                              that.vis
                                  .selectAll(".linkname.linkname-" + dir)
                                  .classed('hide', !that.options.showCableLabels)
                                  .interrupt().transition().duration(550)
                                  .style('opacity', (that.options.showCableLabels ? 1 : 0))
                                  .attr('transform', function (d) {
                                      var translateX = d.source.y,
                                          translateY = d.source.x;
                      
                                      if (invertX) {
                                          translateX = translateX + 85;
                                      } else {
                                          translateX = translateX + that.options.nodeWidth + 65;
                                      }
                      
                                      if (d.source.parent.id === 'root') {
                                          translateX = translateX - 65;
                                      }
                      
                                      return 'translate(' + (invertX ? '' : '-') + translateX + ',' + translateY + ')';
                                  });
                      
                              var node = that.vis
                                  .selectAll(".node.node-" + dir)
                                  .data(root.descendants());
                      
                              var nodeEnter = node
                                  .enter().append("g")
                                  .style("opacity", 0)
                                  .attr("class", "node node-" + dir)
                                  .classed('root', function (d) {
                                      return d.parent === null;
                                  })
                                  .attr('data-id', function (d) {
                                      return d.id;
                                  });
                      
                              // This will append newly created and already existing nodes.
                              this.vis
                                  .selectAll('.node.node-' + dir)
                                  .transition().duration(500)
                                  .style("opacity", 1)
                                  .attr("transform", function (d) {
                                      var translateX = d.y,
                                          translateY = d.x;
                      
                                      if (d.parent === null) {
                                          return "translate(" + (invertX ? 0 : -that.options.nodeWidth) + "," + translateY + ")";
                                      }
                      
                                      if (d.parent && d.parent.id === 'root') {
                                          return "translate(" + (invertX ? that.options.nodeWidth : -that.options.nodeWidth) + "," + translateY + ")";
                                      }
                      
                                      if (d.data.inner) {
                                          if (!invertX) {
                                              translateX = -(translateX + that.options.nodeWidth);
                                          }
                                      } else {
                                          if (!invertX) {
                                              translateX = -(translateX + that.options.nodeWidth) + (that.options.nodeWidth + that.options.nodeMarginX);
                                          } else {
                                              translateX -= that.options.nodeMarginX;
                                          }
                                      }
                      
                                      return "translate(" + translateX + "," + translateY + ")";
                                  });
                      
                              node.exit()
                                  .interrupt().transition().duration(500)
                                  .style("opacity", 0)
                                  .remove();
                      
                              var container = nodeEnter
                                  .filter(function (d) {
                                      // Only draw boxes for the "root" element and "left" connectors.
                                      return d.parent === null || d.data.inner;
                                  })
                                  .each(function (d) {
                                      // Prepare some data for each node.
                                      d.childNum = (d.children ? d.children.length : 1);
                      
                                      d.minX = d.y;
                                      d.maxX = d.y + (that.options.nodeWidth * 2);
                      
                                      if (d.children) {
                                          d.minY = d.children.first().x;
                                          d.maxY = d.children.last().x + that.options.nodeHeight;
                                      } else {
                                          d.minY = d.x;
                                          d.maxY = d.x + that.options.nodeHeight;
                                      }
                      
                                      d.width = d.maxX - d.minX;
                                      d.height = d.maxY - d.minY;
                                      d.translateX = 0;
                                      d.translateY = -(d.height / 2);
                      
                                      if (d.parent === null) {
                                          if (that.rootContainer.height < d.height) {
                                              that.rootContainer.height = d.height;
                                              that.rootContainer.translateX = d.translateX;
                                              that.rootContainer.translateY = d.translateY;
                                          }
                      
                                          d.width = that.options.nodeWidth;
                                      }
                                  });
                      
                              container
                                  .append('rect')
                                  .attr('class', 'title mouse-pointer')
                                  .attr('width', function (d) {
                                      return d.width;
                                  })
                                  .attr('height', function (d) {
                                      return 20;
                                  })
                                  .attr('data-object-id', function (d) {
                                      return d.data.objectId;
                                  })
                                  .attr('transform', function (d) {
                                      var translateX = d.translateX,
                                          translateY = d.translateY;
                      
                                      if (d.parent && d.parent !== 'root') {
                                          if (!invertX) {
                                              translateX = -that.options.nodeWidth;
                                          }
                                      }
                      
                                      return 'translate(' + translateX + ',' + (translateY - 20) + ')';
                                  })
                                  .on('click', that.selectObject.bind(this));
                      
                              container
                                  .append('rect')
                                  .attr('class', 'body')
                                  .attr('width', function (d) {
                                      return d.width;
                                  })
                                  .attr('height', function (d) {
                                      return d.height;
                                  })
                                  .attr('data-conn', function (d) {
                                      return d.data.title;
                                  })
                                  .attr('transform', function (d) {
                                      var translateX = d.translateX,
                                          translateY = d.translateY;
                      
                                      if (d.parent && d.parent !== 'root') {
                                          if (!invertX) {
                                              translateX = -that.options.nodeWidth;
                                          }
                                      }
                      
                                      return 'translate(' + translateX + ',' + translateY + ')';
                                  })
                                  .attr('fill', function (d) {
                                      if (!that.options.objectTypeData.hasOwnProperty(d.data.objectTypeId)) {
                                          return that.options.undefinedObjectType.color;
                                      }
                      
                                      return that.options.objectTypeData[d.data.objectTypeId].color || that.options.undefinedObjectType.color
                                  });
                      
                              nodeEnter
                                  .filter(function (d) {
                                      return d.parent !== null;
                                  })
                                  .append('circle')
                                  .attr('data-connector-id', function (d) {
                                      return d.data.id;
                                  })
                                  .attr('class', 'connector connector-' + dir)
                                  .attr('transform', connectorTranslate)
                                  .on('click', that.selectConnector.bind(this));
                      
                              nodeEnter
                                  .filter(function (d) {
                                      return d.parent !== null;
                                  })
                                  .append('circle')
                                  .attr('data-connector-id', function (d) {
                                      return d.data.id;
                                  })
                                  .style('opacity', 0)
                                  .attr('class', 'connector-inner hide connector-inner-' + dir)
                                  .attr('r', 4)
                                  .attr('transform', connectorTranslate)
                                  .on('click', that.selectConnector.bind(this));
                      
                              that.vis
                                  .selectAll('circle.connector.connector-' + dir)
                                  .classed('mouse-pointer', that.options.clickableConnectors)
                                  .interrupt().transition().duration(500)
                                  .attr('r', (that.options.clickableConnectors ? 10: 5))
                                  .attr('fill', function (d) {
                                      var connectorType = that.options.connectorTypeData[d.data.connectorType];
                      
                                      return connectorType ? connectorType.color : that.options.undefinedConnectorType.color;
                                  })
                                  .attr('transform', connectorTranslate)
                                  .style('stroke-width', (that.options.clickableConnectors ? 3 : 1));
                      
                              that.vis
                                  .selectAll('circle.connector-inner.connector-inner-' + dir)
                                  .classed('mouse-pointer', that.options.clickableConnectors)
                                  .interrupt().transition().duration(500)
                                  .attr('transform', connectorTranslate)
                                  .style('opacity', (that.options.clickableConnectors ? 1 : 0));
                      
                              container
                                  .filter(function (d) {
                                      return (d.parent !== null || invertX);
                                  })
                                  .append('text')
                                  .attr('class', 'title mouse-pointer')
                                  .attr("dy", function (d) {
                                      if (d.id === 'root') {
                                          return -((that.rootContainer.height / 2) + 7);
                                      }
                      
                                      return -((d.height / 2) + 7);
                                  })
                                  .attr("x", function (d) {
                                      if (d.parent === null) {
                                          return 0
                                      }
                      
                                      return invertX ? that.options.nodeWidth : 0;
                                  })
                                  .style("text-anchor", 'middle')
                                  .text(function (d) {
                                      return d.data.objectTitle;
                                  })
                                  .on('click', that.selectObject.bind(this));
                      
                              nodeEnter
                                  .append("text")
                                  .attr('class', 'connector-' + dir + '-title')
                                  .attr("dy", 3)
                                  .attr("x", function (d) {
                                      if (d.parent !== null && d.parent.id === 'root') {
                                          return invertX ? -25 : 25;
                                      }
                      
                                      if (d.data.outer) {
                                          return invertX ? that.options.nodeWidth-10 : -(that.options.nodeWidth-10);
                                      }
                      
                                      return invertX ? 10 : (that.options.nodeWidth-10);
                                  })
                                  .style("text-anchor", function (d) {
                                      if (d.parent !== null && d.parent.id === 'root' || d.data.outer) {
                                          return invertX ? 'end' : 'start';
                                      }
                      
                                      return invertX ? "start" : "end";
                                  })
                                  .text(function (d) {
                                      return that.textFormat.call(this, d.data.title, (that.options.nodeWidth - 15));
                                  });
                      
                              // @see CABLING-56 Show the full title when hovering connector.
                              nodeEnter.append('title').text(d => d.data.title);
                      
                              // After all calculations have been done, we set the root height.
                              this.vis.selectAll('g.root rect.title')
                                  .attr('transform', function (d) {
                                      return 'translate(' + that.rootContainer.translateX + ',' + (that.rootContainer.translateY - 20) + ')';
                                  });
                      
                              this.vis.selectAll('g.root rect.body')
                                  .attr('height', function () {
                                      return that.rootContainer.height;
                                  })
                                  .attr('transform', function (d) {
                                      return 'translate(' + that.rootContainer.translateX + ',' + that.rootContainer.translateY + ')';
                                  });
                      
                              this.vis.selectAll('rect.body')
                                  .transition().duration(250)
                                  .style('opacity', (this.options.displayWiring ? 0.5 : 1));
                      
                              this.vis
                                  .selectAll(".cable.cable-root.cable-" + dir)
                                  .each(function (d) {
                                      d.fromX = (invertX ? '' : '-') + 100;
                                      d.fromY = d.target.x;
                                      d.toX = (invertX ? '' : '-') + (d.target.y + (that.options.showCableLabels ? 50 : 125));
                                      d.toY = d.target.x;
                      
                                      // If a connector is internally wired, we draw the line to the middle (to visually "connect" them).
                                      if (d.target.data.wired) {
                                          d.fromX = 0; // -25;
                                      }
                      
                                      // If a root connector is not connected, only show a small "stump".
                                      if (!d.target.children) {
                                          d.toX = parseInt((invertX ? '' : '-') + 200);
                                      }
                                  })
                                  .attr('data-index', (d, i) => i)
                                  .interrupt().transition().delay(500).duration(250)
                                  .style('opacity', 1)
                                  .attr('d', function (d) {
                                      // @see  CABLING-35  Cut the 'self wired' connectors more short
                                      if (d.target.data.wiredToItself || false) {
                                          if (dir === 'right') {
                                              d.toX -= 45;
                                          } else {
                                              d.toX += 45;
                                          }
                                      }
                      
                                      if (invertX && d.target.data.wired) {
                                          const index = this.indexMapping.findIndex((i) => i == d.target.data.siblingId);
                                          const $selection = this.vis.select('[data-index="' + index + '"]');
                      
                                          if (index >= 0 && $selection.size()) {
                                              d.fromY = $selection.data()[0].fromY;
                      
                                              return "M" + d.fromX + "," + d.fromY +
                                                     "C" + (d.fromX+20) + "," + d.fromY + " " + (d.fromX+20) + "," + d.toY + " " + (d.fromX+40) + "," + d.toY +
                                                     "L" + d.toX + "," + d.toY;
                                          }
                                      }
                      
                                      return "M" + d.fromX + "," + d.fromY +
                                             "L" + d.toX + "," + d.toY;
                                  }.bind(this));
                      
                              this.vis.selectAll('.connector-' + dir + '-title')
                                  .classed('stroked', this.options.displayWiring);
                      
                              return this;
                          },
                      
                          postProcess: function () {
                              if (Object.isFunction(this.options.onAfterProcess)) {
                                  this.options.onAfterProcess.call(this);
                              }
                      
                              return this;
                          },
                      
                          setData: function (data) {
                              this.data = data;
                      
                              return this;
                          },
                      
                          selectObject: function (d) {
                              var $object = this.vis.selectAll('[data-id="' + d.id + '"]');
                      
                              if (!$object.classed('clicked')) {
                                  this.vis.selectAll('.clicked').classed('clicked', false);
                      
                                  $object.classed('clicked', true);
                      
                                  if (Object.isFunction(this.options.onObjSelect)) {
                                      this.options.onObjSelect.call(this, d);
                                  }
                              }
                      
                              return this;
                          },
                      
                          selectCableObject: function (d) {
                              var $object = this.vis.selectAll('[data-id="' + d.source.data.cableId + '"]');
                      
                              if (!$object.classed('clicked')) {
                                  this.vis.selectAll('.clicked').classed('clicked', false);
                      
                                  $object.classed('clicked', true);
                      
                                  if (Object.isFunction(this.options.onCableSelect)) {
                                      this.options.onCableSelect.call(this, d);
                                  }
                              }
                      
                              return this;
                          },
                      
                          selectConnector: function (d) {
                              var $connector = this.vis.select('circle.connector-inner[data-connector-id="' + d.data.id + '"]');
                      
                              if (! this.options.clickableConnectors) {
                                  return;
                              }
                      
                              $connector.classed('hide', !$connector.classed('hide'));
                      
                              if (Object.isFunction(this.options.onConnectorSelect)) {
                                  this.options.onConnectorSelect.call(this, d);
                              }
                      
                              return this;
                          },
                      
                          unselectConnectors: function (d) {
                              var data = this.vis.selectAll('.connector-inner:not(.hide)').classed('hide', true).data();
                      
                              if (Object.isFunction(this.options.onConnectorUnselect)) {
                                  this.options.onConnectorUnselect.call(this, data);
                              }
                      
                              return this;
                          },
                      
                          unselectObject: function (data) {
                              if (Object.isFunction(this.options.onObjUnselect)) {
                                  this.options.onObjUnselect.call(this, data);
                              }
                      
                              return this;
                          },
                      
                          center: function () {
                              var translateX = (this.options.width / 2),
                                  translateY = (this.options.height / 2);
                      
                              this.vis.attr('transform', "translate(" + translateX + "," + translateY + ")");
                      
                              this.svg.select('rect').call(this.zoom.transform, d3.zoomIdentity.translate(translateX, translateY));
                      
                              return this;
                          }
                      });
                      

                      Die Datei müsste mit diesem neuen Inhalt überschrieben werden 😄

                      Das dürfte weiterhelfen!

                      4b3a1091-f515-4bae-bfc1-f35baeca93b8-image.png

                      VG Leo

                      StefanP74S 1 Reply Last reply Reply Quote 1
                      • StefanP74S Offline
                        StefanP74 @LFischer
                        last edited by

                        Servus @LFischer,

                        fantastico! 👌

                        Vielen Dank, das ist perfekt.
                        Was für ein mächtiger Einsatz. 👍

                        LG Stefan

                        1 Reply Last reply Reply Quote 0
                        • LFischerL Offline
                          LFischer
                          last edited by

                          Kurzes Update: Gelöst in Add-on Version 1.5

                          Die hier beschriebenen Probleme wurden in der Zwischenzeit in Version 1.5 des Add-ons gelöst. Dieses wurde am 26.Februar veröffentlicht 🙂

                          Viele Grüße
                          Leo

                          1 Reply Last reply Reply Quote 0
                          • StefanP74S Offline
                            StefanP74
                            last edited by

                            ... und das erfreute mich ganz besonders 😊 👏

                            1 Reply Last reply Reply Quote 0
                            • First post
                              Last post