Sfoglia il codice sorgente

Add SVG trace support for ProviderNetwork attachments

jeremystretch 4 anni fa
parent
commit
8b571912cf

+ 73 - 31
netbox/dcim/svg.py

@@ -349,7 +349,7 @@ class CableTraceSVG:
         :param url: Hyperlink URL
         :param labels: Iterable of text labels
         """
-        group = Group()
+        group = Group(class_='connector')
 
         # Draw cable (line)
         start = (OFFSET + self.center, self.cursor)
@@ -374,6 +374,29 @@ class CableTraceSVG:
 
         return group
 
+    def _draw_attachment(self):
+        """
+        Return an SVG group containing a line element and "Attachment" label.
+        """
+        group = Group(class_='connector')
+
+        # Draw attachment (line)
+        start = (OFFSET + self.center, self.cursor)
+        height = PADDING * 2 + LINE_HEIGHT + PADDING * 2
+        end = (start[0], start[1] + height)
+        line = Line(start=start, end=end, class_='attachment')
+        group.add(line)
+        self.cursor += PADDING * 2
+
+        # Add label
+        self.cursor += LINE_HEIGHT
+        text_coords = (self.center + PADDING * 2, self.cursor - LINE_HEIGHT / 2)
+        text = Text('Attachment', insert=text_coords)
+        group.add(text)
+        self.cursor += PADDING * 2
+
+        return group
+
     def render(self):
         """
         Return an SVG document representing a cable trace.
@@ -383,11 +406,11 @@ class CableTraceSVG:
         # Prep elements list
         parent_objects = []
         terminations = []
-        cables = []
+        connectors = []
 
         # Iterate through each (term, cable, term) segment in the path
         for i, segment in enumerate(traced_path):
-            near_end, cable, far_end = segment
+            near_end, connector, far_end = segment
 
             # Near end parent
             if i == 0:
@@ -412,38 +435,57 @@ class CableTraceSVG:
             )
             terminations.append(termination)
 
-            # Cable
-            cable = self._draw_cable(
-                color=cable.color or '000000',
-                url=cable.get_absolute_url(),
-                labels=[f'Cable {cable}', cable.get_status_display()]
-            )
-            cables.append(cable)
+            # Connector (either a Cable or attachment to a ProviderNetwork)
+            if connector is not None:
 
-            # Far end termination
-            termination = self._draw_box(
-                width=self.width * .8,
-                color=self._get_color(far_end),
-                url=far_end.get_absolute_url(),
-                labels=[str(far_end)],
-                radius=5
-            )
-            terminations.append(termination)
+                # Cable
+                cable = self._draw_cable(
+                    color=connector.color or '000000',
+                    url=connector.get_absolute_url(),
+                    labels=[f'Cable {connector}', connector.get_status_display()]
+                )
+                connectors.append(cable)
+
+                # Far end termination
+                termination = self._draw_box(
+                    width=self.width * .8,
+                    color=self._get_color(far_end),
+                    url=far_end.get_absolute_url(),
+                    labels=[str(far_end)],
+                    radius=5
+                )
+                terminations.append(termination)
 
-            # Far end parent
-            parent_object = self._draw_box(
-                width=self.width,
-                color=self._get_color(far_end.parent_object),
-                url=far_end.parent_object.get_absolute_url(),
-                labels=self._get_labels(far_end.parent_object),
-                y_indent=PADDING,
-                padding_multiplier=2
-            )
-            parent_objects.append(parent_object)
+                # Far end parent
+                parent_object = self._draw_box(
+                    width=self.width,
+                    color=self._get_color(far_end.parent_object),
+                    url=far_end.parent_object.get_absolute_url(),
+                    labels=self._get_labels(far_end.parent_object),
+                    y_indent=PADDING,
+                    padding_multiplier=2
+                )
+                parent_objects.append(parent_object)
+
+            else:
+
+                # Attachment
+                attachment = self._draw_attachment()
+                connectors.append(attachment)
+
+                # ProviderNetwork
+                parent_object = self._draw_box(
+                    width=self.width,
+                    color=self._get_color(far_end),
+                    url=far_end.get_absolute_url(),
+                    labels=self._get_labels(far_end),
+                    padding_multiplier=2
+                )
+                parent_objects.append(parent_object)
 
         # Determine drawing size
         self.drawing = svgwrite.Drawing(
-            size=(self.width, self.cursor)
+            size=(self.width, self.cursor + 2)
         )
 
         # Attach CSS stylesheet
@@ -451,7 +493,7 @@ class CableTraceSVG:
             self.drawing.defs.add(self.drawing.style(css_file.read()))
 
         # Add elements to the drawing in order of depth (Z axis)
-        for element in parent_objects + terminations + cables:
+        for element in connectors + parent_objects + terminations:
             self.drawing.add(element)
 
         return self.drawing

+ 7 - 4
netbox/project-static/_cable_trace.scss

@@ -14,12 +14,15 @@ svg {
     stroke-width: 1;
   }
 
-  /* Cables */
+  /* Connectors */
+  .connector text {
+    text-anchor: start;
+  }
   line {
     stroke-width: 3;
   }
-
-  text.cable {
-    text-anchor: start;
+  line.attachment {
+    stroke: #c0c0c0;
+    stroke-dasharray: 5px,5px;
   }
 }

+ 1 - 1
netbox/project-static/dist/cable_trace.css

@@ -1,2 +1,2 @@
-*{font-family:sans-serif;font-size:13px}text{text-anchor:middle;dominant-baseline:middle}svg rect{stroke:#303030;stroke-width:1}svg line{stroke-width:3}svg text.cable{text-anchor:start}
+*{font-family:sans-serif;font-size:13px}text{text-anchor:middle;dominant-baseline:middle}svg rect{stroke:#303030;stroke-width:1}svg .connector text{text-anchor:start}svg line{stroke-width:3}svg line.attachment{stroke:silver;stroke-dasharray:5px,5px}
 /*# sourceMappingURL=/static/cable_trace.css.map */

+ 1 - 1
netbox/project-static/dist/cable_trace.css.map

@@ -1 +1 @@
-{"version":3,"sources":["_cable_trace.scss"],"names":[],"mappings":"AAAA,EACI,sBAAA,CACA,eAEJ,KACI,kBAAA,CACA,yBAKF,SACE,cAAA,CACA,eAIF,SACE,eAGF,eACE","file":"cable_trace.css","sourceRoot":"..","sourcesContent":["* {\n    font-family: sans-serif;\n    font-size: 13px;\n}\ntext {\n    text-anchor: middle;\n    dominant-baseline: middle;\n}\n\nsvg {\n  /* Boxes */\n  rect {\n    stroke: #303030;\n    stroke-width: 1;\n  }\n\n  /* Cables */\n  line {\n    stroke-width: 3;\n  }\n\n  text.cable {\n    text-anchor: start;\n  }\n}\n"]}
+{"version":3,"sources":["_cable_trace.scss"],"names":[],"mappings":"AAAA,EACI,sBAAA,CACA,eAEJ,KACI,kBAAA,CACA,yBAKF,SACE,cAAA,CACA,eAIF,oBACE,kBAEF,SACE,eAEF,oBACE,aAAA,CACA","file":"cable_trace.css","sourceRoot":"..","sourcesContent":["* {\n    font-family: sans-serif;\n    font-size: 13px;\n}\ntext {\n    text-anchor: middle;\n    dominant-baseline: middle;\n}\n\nsvg {\n  /* Boxes */\n  rect {\n    stroke: #303030;\n    stroke-width: 1;\n  }\n\n  /* Connectors */\n  .connector text {\n    text-anchor: start;\n  }\n  line {\n    stroke-width: 3;\n  }\n  line.attachment {\n    stroke: #c0c0c0;\n    stroke-dasharray: 5px,5px;\n  }\n}\n"]}

File diff suppressed because it is too large
+ 0 - 0
netbox/project-static/dist/netbox-dark.css


File diff suppressed because it is too large
+ 0 - 0
netbox/project-static/dist/netbox-dark.css.map


File diff suppressed because it is too large
+ 0 - 0
netbox/project-static/dist/netbox-light.css


File diff suppressed because it is too large
+ 0 - 0
netbox/project-static/dist/netbox-light.css.map


Some files were not shown because too many files changed in this diff