aron bergur jóhannsson 3 лет назад
Родитель
Сommit
eed6990b39

+ 1 - 0
netbox/dcim/tables/devices.py

@@ -588,6 +588,7 @@ class DeviceInterfaceTable(InterfaceTable):
             'class': get_interface_row_class,
             'class': get_interface_row_class,
             'data-name': lambda record: record.name,
             'data-name': lambda record: record.name,
             'data-enabled': get_interface_state_attribute,
             'data-enabled': get_interface_state_attribute,
+            'data-type': lambda record: record.type,
         }
         }
 
 
 
 

+ 55 - 67
netbox/project-static/src/tables/interfaceTable.ts

@@ -1,6 +1,5 @@
 import { getElements, replaceAll, findFirstAdjacent } from '../util';
 import { getElements, replaceAll, findFirstAdjacent } from '../util';
 
 
-type InterfaceState = 'enabled' | 'disabled';
 type ShowHide = 'show' | 'hide';
 type ShowHide = 'show' | 'hide';
 
 
 function isShowHide(value: unknown): value is ShowHide {
 function isShowHide(value: unknown): value is ShowHide {
@@ -27,54 +26,23 @@ class ButtonState {
    * Underlying Button DOM Element
    * Underlying Button DOM Element
    */
    */
   public button: HTMLButtonElement;
   public button: HTMLButtonElement;
-  /**
-   * Table rows with `data-enabled` set to `"enabled"`
-   */
-  private enabledRows: NodeListOf<HTMLTableRowElement>;
-  /**
-   * Table rows with `data-enabled` set to `"disabled"`
-   */
-  private disabledRows: NodeListOf<HTMLTableRowElement>;
-
-  constructor(button: HTMLButtonElement, table: HTMLTableElement) {
-    this.button = button;
-    this.enabledRows = table.querySelectorAll<HTMLTableRowElement>('tr[data-enabled="enabled"]');
-    this.disabledRows = table.querySelectorAll<HTMLTableRowElement>('tr[data-enabled="disabled"]');
-  }
 
 
   /**
   /**
-   * This button's controlled type. For example, a button with the class `toggle-disabled` has
-   * directive 'disabled' because it controls the visibility of rows with
-   * `data-enabled="disabled"`. Likewise, `toggle-enabled` controls rows with
-   * `data-enabled="enabled"`.
+   * Table rows provided in constructor
    */
    */
-  private get directive(): InterfaceState {
-    if (this.button.classList.contains('toggle-disabled')) {
-      return 'disabled';
-    } else if (this.button.classList.contains('toggle-enabled')) {
-      return 'enabled';
-    }
-    // If this class has been instantiated but doesn't contain these classes, it's probably because
-    // the classes are missing in the HTML template.
-    console.warn(this.button);
-    throw new Error('Toggle button does not contain expected class');
-  }
+  private rows: NodeListOf<HTMLTableRowElement>;
 
 
-  /**
-   * Toggle visibility of rows with `data-enabled="enabled"`.
-   */
-  private toggleEnabledRows(): void {
-    for (const row of this.enabledRows) {
-      row.classList.toggle('d-none');
-    }
+  constructor(button: HTMLButtonElement, rows: NodeListOf<HTMLTableRowElement>) {
+    this.button = button;
+    this.rows = rows;
   }
   }
 
 
   /**
   /**
-   * Toggle visibility of rows with `data-enabled="disabled"`.
+   * Remove visibility of button state rows.
    */
    */
-  private toggleDisabledRows(): void {
-    for (const row of this.disabledRows) {
-      row.classList.toggle('d-none');
+  private hideRows(): void {
+    for (const row of this.rows) {
+      row.classList.add('d-none');
     }
     }
   }
   }
 
 
@@ -111,17 +79,6 @@ class ButtonState {
     }
     }
   }
   }
 
 
-  /**
-   * Toggle visibility for the rows this element controls.
-   */
-  private toggleRows(): void {
-    if (this.directive === 'enabled') {
-      this.toggleEnabledRows();
-    } else if (this.directive === 'disabled') {
-      this.toggleDisabledRows();
-    }
-  }
-
   /**
   /**
    * Toggle the DOM element's `data-state` attribute.
    * Toggle the DOM element's `data-state` attribute.
    */
    */
@@ -139,17 +96,20 @@ class ButtonState {
   private toggle(): void {
   private toggle(): void {
     this.toggleState();
     this.toggleState();
     this.toggleButton();
     this.toggleButton();
-    this.toggleRows();
   }
   }
 
 
   /**
   /**
-   * When the button is clicked, toggle all controlled elements.
+   * When the button is clicked, toggle all controlled elements and hide rows based on
+   * buttonstate.
    */
    */
   public handleClick(event: Event): void {
   public handleClick(event: Event): void {
     const button = event.currentTarget as HTMLButtonElement;
     const button = event.currentTarget as HTMLButtonElement;
     if (button.isEqualNode(this.button)) {
     if (button.isEqualNode(this.button)) {
       this.toggle();
       this.toggle();
     }
     }
+    if (this.buttonState === 'hide') {
+      this.hideRows();
+    }
   }
   }
 }
 }
 
 
@@ -174,14 +134,25 @@ class TableState {
   // @ts-expect-error null handling is performed in the constructor
   // @ts-expect-error null handling is performed in the constructor
   private disabledButton: ButtonState;
   private disabledButton: ButtonState;
 
 
+  /**
+   * Instance of ButtonState for the 'show/hide virtual rows' button.
+   */
+  // @ts-expect-error null handling is performed in the constructor
+  private virtualButton: ButtonState;
+
   /**
   /**
    * Underlying DOM Table Caption Element.
    * Underlying DOM Table Caption Element.
    */
    */
   private caption: Nullable<HTMLTableCaptionElement> = null;
   private caption: Nullable<HTMLTableCaptionElement> = null;
 
 
+  /**
+   * All table rows in table
+   */
+  private rows: NodeListOf<HTMLTableRowElement>;
+
   constructor(table: HTMLTableElement) {
   constructor(table: HTMLTableElement) {
     this.table = table;
     this.table = table;
-
+    this.rows = this.table.querySelectorAll('tr');
     try {
     try {
       const toggleEnabledButton = findFirstAdjacent<HTMLButtonElement>(
       const toggleEnabledButton = findFirstAdjacent<HTMLButtonElement>(
         this.table,
         this.table,
@@ -191,6 +162,10 @@ class TableState {
         this.table,
         this.table,
         'button.toggle-disabled',
         'button.toggle-disabled',
       );
       );
+      const toggleVirtualButton = findFirstAdjacent<HTMLButtonElement>(
+        this.table,
+        'button.toggle-virtual',
+      );
 
 
       const caption = this.table.querySelector('caption');
       const caption = this.table.querySelector('caption');
       this.caption = caption;
       this.caption = caption;
@@ -203,13 +178,28 @@ class TableState {
         throw new TableStateError("Table is missing a 'toggle-disabled' button.", table);
         throw new TableStateError("Table is missing a 'toggle-disabled' button.", table);
       }
       }
 
 
+      if (toggleVirtualButton === null) {
+        throw new TableStateError("Table is missing a 'toggle-virtual' button.", table);
+      }
+
       // Attach event listeners to the buttons elements.
       // Attach event listeners to the buttons elements.
       toggleEnabledButton.addEventListener('click', event => this.handleClick(event, this));
       toggleEnabledButton.addEventListener('click', event => this.handleClick(event, this));
       toggleDisabledButton.addEventListener('click', event => this.handleClick(event, this));
       toggleDisabledButton.addEventListener('click', event => this.handleClick(event, this));
+      toggleVirtualButton.addEventListener('click', event => this.handleClick(event, this));
 
 
       // Instantiate ButtonState for each button for state management.
       // Instantiate ButtonState for each button for state management.
-      this.enabledButton = new ButtonState(toggleEnabledButton, this.table);
-      this.disabledButton = new ButtonState(toggleDisabledButton, this.table);
+      this.enabledButton = new ButtonState(
+        toggleEnabledButton,
+        table.querySelectorAll<HTMLTableRowElement>('tr[data-enabled="enabled"]'),
+      );
+      this.disabledButton = new ButtonState(
+        toggleDisabledButton,
+        table.querySelectorAll<HTMLTableRowElement>('tr[data-enabled="disabled"]'),
+      );
+      this.virtualButton = new ButtonState(
+        toggleVirtualButton,
+        table.querySelectorAll<HTMLTableRowElement>('tr[data-type="virtual"]'),
+      );
     } catch (err) {
     } catch (err) {
       if (err instanceof TableStateError) {
       if (err instanceof TableStateError) {
         // This class is useless for tables that don't have toggle buttons.
         // This class is useless for tables that don't have toggle buttons.
@@ -261,22 +251,20 @@ class TableState {
   }
   }
 
 
   /**
   /**
-   * When toggle buttons are clicked, pass the event to the relevant button's handler and update
-   * this instance's state.
+   * When toggle buttons are clicked, reapply visability all rows and
+   * pass the event to all button handlers
    *
    *
    * @param event onClick event for toggle buttons.
    * @param event onClick event for toggle buttons.
    * @param instance Instance of TableState (`this` cannot be used since that's context-specific).
    * @param instance Instance of TableState (`this` cannot be used since that's context-specific).
    */
    */
   public handleClick(event: Event, instance: TableState): void {
   public handleClick(event: Event, instance: TableState): void {
-    const button = event.currentTarget as HTMLButtonElement;
-    const enabled = button.isEqualNode(instance.enabledButton.button);
-    const disabled = button.isEqualNode(instance.disabledButton.button);
-
-    if (enabled) {
-      instance.enabledButton.handleClick(event);
-    } else if (disabled) {
-      instance.disabledButton.handleClick(event);
+    for (const row of this.rows) {
+      row.classList.remove('d-none');
     }
     }
+
+    instance.enabledButton.handleClick(event);
+    instance.disabledButton.handleClick(event);
+    instance.virtualButton.handleClick(event);
     instance.toggleCaption();
     instance.toggleCaption();
   }
   }
 }
 }

+ 1 - 0
netbox/templates/dcim/device/inc/interface_table_controls.html

@@ -7,5 +7,6 @@
   <ul class="dropdown-menu">
   <ul class="dropdown-menu">
     <button type="button" class="dropdown-item toggle-enabled" data-state="show">Hide Enabled</button>
     <button type="button" class="dropdown-item toggle-enabled" data-state="show">Hide Enabled</button>
     <button type="button" class="dropdown-item toggle-disabled" data-state="show">Hide Disabled</button>
     <button type="button" class="dropdown-item toggle-disabled" data-state="show">Hide Disabled</button>
+    <button type="button" class="dropdown-item toggle-virtual" data-state="show">Hide Virtual</button>
   </ul>
   </ul>
 {% endblock extra_table_controls %}
 {% endblock extra_table_controls %}