Просмотр исходного кода

Add SVG trace support for WirelessLinks

jeremystretch 4 лет назад
Родитель
Сommit
43f2d4a331

+ 66 - 15
netbox/dcim/svg.py

@@ -398,6 +398,39 @@ class CableTraceSVG:
 
         return group
 
+    def _draw_wirelesslink(self, url, labels):
+        """
+        Draw a line with labels representing a WirelessLink.
+
+        :param url: Hyperlink URL
+        :param labels: Iterable of text labels
+        """
+        group = Group(class_='connector')
+
+        # Draw the wireless link
+        start = (OFFSET + self.center, self.cursor)
+        height = PADDING * 2 + LINE_HEIGHT * len(labels) + PADDING * 2
+        end = (start[0], start[1] + height)
+        line = Line(start=start, end=end, class_='wireless-link')
+        group.add(line)
+
+        self.cursor += PADDING * 2
+
+        # Add link
+        link = Hyperlink(href=f'{self.base_url}{url}', target='_blank')
+
+        # Add text label(s)
+        for i, label in enumerate(labels):
+            self.cursor += LINE_HEIGHT
+            text_coords = (self.center + PADDING * 2, self.cursor - LINE_HEIGHT / 2)
+            text = Text(label, insert=text_coords, class_='bold' if not i else [])
+            link.add(text)
+
+        group.add(link)
+        self.cursor += PADDING * 2
+
+        return group
+
     def _draw_attachment(self):
         """
         Return an SVG group containing a line element and "Attachment" label.
@@ -418,6 +451,9 @@ class CableTraceSVG:
         """
         Return an SVG document representing a cable trace.
         """
+        from dcim.models import Cable
+        from wireless.models import WirelessLink
+
         traced_path = self.origin.trace()
 
         # Prep elements list
@@ -452,24 +488,39 @@ class CableTraceSVG:
             )
             terminations.append(termination)
 
-            # Connector (either a Cable or attachment to a ProviderNetwork)
+            # Connector (a Cable or WirelessLink)
             if connector is not None:
 
                 # Cable
-                cable_labels = [
-                    f'Cable {connector}',
-                    connector.get_status_display()
-                ]
-                if connector.type:
-                    cable_labels.append(connector.get_type_display())
-                if connector.length and connector.length_unit:
-                    cable_labels.append(f'{connector.length} {connector.get_length_unit_display()}')
-                cable = self._draw_cable(
-                    color=connector.color or '000000',
-                    url=connector.get_absolute_url(),
-                    labels=cable_labels
-                )
-                connectors.append(cable)
+                if type(connector) is Cable:
+                    connector_labels = [
+                        f'Cable {connector}',
+                        connector.get_status_display()
+                    ]
+                    if connector.type:
+                        connector_labels.append(connector.get_type_display())
+                    if connector.length and connector.length_unit:
+                        connector_labels.append(f'{connector.length} {connector.get_length_unit_display()}')
+                    cable = self._draw_cable(
+                        color=connector.color or '000000',
+                        url=connector.get_absolute_url(),
+                        labels=connector_labels
+                    )
+                    connectors.append(cable)
+
+                # WirelessLink
+                elif type(connector) is WirelessLink:
+                    connector_labels = [
+                        f'Wireless link {connector}',
+                        connector.get_status_display()
+                    ]
+                    if connector.ssid:
+                        connector_labels.append(connector.ssid)
+                    wirelesslink = self._draw_wirelesslink(
+                        url=connector.get_absolute_url(),
+                        labels=connector_labels
+                    )
+                    connectors.append(wirelesslink)
 
                 # Far end termination
                 termination = self._draw_box(

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

@@ -1 +1 @@
-:root{--nbx-trace-color: #000;--nbx-trace-node-bg: #e9ecef;--nbx-trace-termination-bg: #f8f9fa;--nbx-trace-cable-shadow: #343a40;--nbx-trace-attachment: #ced4da}:root[data-netbox-color-mode=dark]{--nbx-trace-color: #fff;--nbx-trace-node-bg: #212529;--nbx-trace-termination-bg: #343a40;--nbx-trace-cable-shadow: #e9ecef;--nbx-trace-attachment: #6c757d}*{font-family:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:.875rem}text{text-anchor:middle;dominant-baseline:middle}text:not([fill]){fill:var(--nbx-trace-color)}text.bold{font-weight:700}svg rect{fill:var(--nbx-trace-node-bg);stroke:#606060;stroke-width:1}svg rect .termination{fill:var(--nbx-trace-termination-bg)}svg .connector text{text-anchor:start}svg line{stroke-width:5px}svg line.cable-shadow{stroke:var(--nbx-trace-cable-shadow);stroke-width:7px}svg line.attachment{stroke:var(--nbx-trace-attachment);stroke-dasharray:5px,5px}
+:root{--nbx-trace-color: #000;--nbx-trace-node-bg: #e9ecef;--nbx-trace-termination-bg: #f8f9fa;--nbx-trace-cable-shadow: #343a40;--nbx-trace-attachment: #ced4da}:root[data-netbox-color-mode=dark]{--nbx-trace-color: #fff;--nbx-trace-node-bg: #212529;--nbx-trace-termination-bg: #343a40;--nbx-trace-cable-shadow: #e9ecef;--nbx-trace-attachment: #6c757d}*{font-family:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:.875rem}text{text-anchor:middle;dominant-baseline:middle}text:not([fill]){fill:var(--nbx-trace-color)}text.bold{font-weight:700}svg rect{fill:var(--nbx-trace-node-bg);stroke:#606060;stroke-width:1}svg rect .termination{fill:var(--nbx-trace-termination-bg)}svg .connector text{text-anchor:start}svg line{stroke-width:5px}svg line.cable-shadow{stroke:var(--nbx-trace-cable-shadow);stroke-width:7px}svg line.wireless-link{stroke:var(--nbx-trace-attachment);stroke-dasharray:4px 12px;stroke-linecap:round}svg line.attachment{stroke:var(--nbx-trace-attachment);stroke-dasharray:5px}

+ 6 - 1
netbox/project-static/styles/cable-trace.scss

@@ -59,8 +59,13 @@ svg {
     stroke: var(--nbx-trace-cable-shadow);
     stroke-width: 7px;
   }
+  line.wireless-link {
+    stroke: var(--nbx-trace-attachment);
+    stroke-dasharray: 4px 12px;
+    stroke-linecap: round;
+  }
   line.attachment {
     stroke: var(--nbx-trace-attachment);
-    stroke-dasharray: 5px, 5px;
+    stroke-dasharray: 5px;
   }
 }