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

Closes: #19336 - Replace JS interface table toggles with server-side URL filters (#22263)

bctiemann 10 часов назад
Родитель
Сommit
648d56010d

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

@@ -789,8 +789,6 @@ class DeviceInterfaceTable(InterfaceTable):
             'data-virtual': lambda record: "true" if record.is_virtual else "false",
             'data-mark-connected': lambda record: "true" if record.mark_connected else "false",
             'data-cable-status': lambda record: record.cable.status if record.cable else "",
-            'data-type': lambda record: record.type,
-            'data-connected': lambda record: "connected" if record.mark_connected or record.cable else "disconnected"
         }
 
 

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
netbox/project-static/dist/netbox.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
netbox/project-static/dist/netbox.js.map


+ 0 - 2
netbox/project-static/src/netbox.ts

@@ -8,7 +8,6 @@ import { initMessages } from './messages';
 import { initClipboard } from './clipboard';
 import { initDateSelector } from './dateSelector';
 import { initTableConfig } from './tableConfig';
-import { initInterfaceTable } from './tables';
 import { initSideNav } from './sidenav';
 import { initDashboard } from './dashboard';
 import { initRackElevation } from './racks';
@@ -28,7 +27,6 @@ function initDocument(): void {
     initButtons,
     initClipboard,
     initTableConfig,
-    initInterfaceTable,
     initSideNav,
     initDashboard,
     initRackElevation,

+ 0 - 1
netbox/project-static/src/tables/index.ts

@@ -1 +0,0 @@
-export * from './interfaceTable';

+ 0 - 251
netbox/project-static/src/tables/interfaceTable.ts

@@ -1,251 +0,0 @@
-import { getElements, replaceAll, findFirstAdjacent } from '../util';
-
-type ShowHide = 'show' | 'hide';
-
-function isShowHide(value: unknown): value is ShowHide {
-  return typeof value === 'string' && ['show', 'hide'].includes(value);
-}
-
-/**
- * When this error is thrown, it's an indication that we don't need to manage this table, because
- * it doesn't contain the required elements.
- */
-class TableStateError extends Error {
-  table: HTMLTableElement;
-  constructor(message: string, table: HTMLTableElement) {
-    super(message);
-    this.table = table;
-  }
-}
-
-/**
- * Manage the display text of a button element as well as the visibility of its corresponding rows.
- */
-class ButtonState {
-  /**
-   * Underlying Button DOM Element
-   */
-  public button: HTMLButtonElement;
-
-  /**
-   * Table rows provided in constructor
-   */
-  private rows: NodeListOf<HTMLTableRowElement>;
-
-  constructor(button: HTMLButtonElement, rows: NodeListOf<HTMLTableRowElement>) {
-    this.button = button;
-    this.rows = rows;
-  }
-
-  /**
-   * Remove visibility of button state rows.
-   */
-  private hideRows(): void {
-    for (const row of this.rows) {
-      row.classList.add('d-none');
-    }
-  }
-
-  /**
-   * Update the DOM element's `data-state` attribute.
-   */
-  public set buttonState(state: Nullable<ShowHide>) {
-    if (isShowHide(state)) {
-      this.button.setAttribute('data-state', state);
-    }
-  }
-
-  /**
-   * Get the DOM element's `data-state` attribute.
-   */
-  public get buttonState(): Nullable<ShowHide> {
-    const state = this.button.getAttribute('data-state');
-    if (isShowHide(state)) {
-      return state;
-    }
-    return null;
-  }
-
-  /**
-   * Update the DOM element's display text to reflect the action opposite the current state. For
-   * example, if the current state is to hide enabled interfaces, the DOM text should say
-   * "Show Enabled Interfaces".
-   */
-  private toggleButton(): void {
-    if (this.buttonState === 'show') {
-      this.button.innerText = replaceAll(this.button.innerText, 'Show', 'Hide');
-    } else if (this.buttonState === 'hide') {
-      this.button.innerText = replaceAll(this.button.innerHTML, 'Hide', 'Show');
-    }
-  }
-
-  /**
-   * Toggle the DOM element's `data-state` attribute.
-   */
-  private toggleState(): void {
-    if (this.buttonState === 'show') {
-      this.buttonState = 'hide';
-    } else if (this.buttonState === 'hide') {
-      this.buttonState = 'show';
-    }
-  }
-
-  /**
-   * Toggle all controlled elements.
-   */
-  private toggle(): void {
-    this.toggleState();
-    this.toggleButton();
-  }
-
-  /**
-   * When the button is clicked, toggle all controlled elements and hide rows based on
-   * buttonstate.
-   */
-  public handleClick(event: Event): void {
-    const button = event.currentTarget as HTMLButtonElement;
-    if (button.isEqualNode(this.button)) {
-      this.toggle();
-    }
-    if (this.buttonState === 'hide') {
-      this.hideRows();
-    }
-  }
-}
-
-/**
- * Manage the state of a table and its elements.
- */
-class TableState {
-  /**
-   * Underlying DOM Table Element.
-   */
-
-  private table: HTMLTableElement;
-  /**
-   * Instance of ButtonState for the 'show/hide enabled rows' button.
-   */
-  // @ts-expect-error null handling is performed in the constructor
-  private enabledButton: ButtonState;
-
-  /**
-   * Instance of ButtonState for the 'show/hide disabled rows' button.
-   */
-  // @ts-expect-error null handling is performed in the constructor
-  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;
-
-  /**
-   * Instance of ButtonState for the 'show/hide virtual rows' button.
-   */
-  // @ts-expect-error null handling is performed in the constructor
-  private disconnectedButton: ButtonState;
-
-  /**
-   * All table rows in table
-   */
-  private rows: NodeListOf<HTMLTableRowElement>;
-
-  constructor(table: HTMLTableElement) {
-    this.table = table;
-    this.rows = this.table.querySelectorAll('tr');
-    try {
-      const toggleEnabledButton = findFirstAdjacent<HTMLButtonElement>(
-        this.table,
-        'button.toggle-enabled',
-      );
-      const toggleDisabledButton = findFirstAdjacent<HTMLButtonElement>(
-        this.table,
-        'button.toggle-disabled',
-      );
-      const toggleVirtualButton = findFirstAdjacent<HTMLButtonElement>(
-        this.table,
-        'button.toggle-virtual',
-      );
-      const toggleDisconnectedButton = findFirstAdjacent<HTMLButtonElement>(
-        this.table,
-        'button.toggle-disconnected',
-      );
-
-      if (toggleEnabledButton === null) {
-        throw new TableStateError("Table is missing a 'toggle-enabled' button.", table);
-      }
-
-      if (toggleDisabledButton === null) {
-        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);
-      }
-
-      if (toggleDisconnectedButton === null) {
-        throw new TableStateError("Table is missing a 'toggle-disconnected' button.", table);
-      }
-
-      // Attach event listeners to the buttons elements.
-      toggleEnabledButton.addEventListener('click', event => this.handleClick(event, this));
-      toggleDisabledButton.addEventListener('click', event => this.handleClick(event, this));
-      toggleVirtualButton.addEventListener('click', event => this.handleClick(event, this));
-      toggleDisconnectedButton.addEventListener('click', event => this.handleClick(event, this));
-
-      // Instantiate ButtonState for each button for state management.
-      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"]'),
-      );
-      this.disconnectedButton = new ButtonState(
-        toggleDisconnectedButton,
-        table.querySelectorAll<HTMLTableRowElement>('tr[data-connected="disconnected"]'),
-      );
-    } catch (err) {
-      if (err instanceof TableStateError) {
-        // This class is useless for tables that don't have toggle buttons.
-        console.debug('Table does not contain enable/disable toggle buttons');
-        return;
-      } else {
-        throw err;
-      }
-    }
-  }
-
-  /**
-   * 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 instance Instance of TableState (`this` cannot be used since that's context-specific).
-   */
-  public handleClick(event: Event, instance: TableState): void {
-    for (const row of this.rows) {
-      row.classList.remove('d-none');
-    }
-
-    instance.enabledButton.handleClick(event);
-    instance.disabledButton.handleClick(event);
-    instance.virtualButton.handleClick(event);
-    instance.disconnectedButton.handleClick(event);
-  }
-}
-
-/**
- * Initialize table states.
- */
-export function initInterfaceTable(): void {
-  for (const element of getElements<HTMLTableElement>('table')) {
-    new TableState(element);
-  }
-}

+ 28 - 5
netbox/templates/dcim/device/inc/interface_table_controls.html

@@ -3,12 +3,35 @@
 
 {% block extra_table_controls %}
   <button class="btn dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">
-    <i class="mdi mdi-eye"></i>
+    <i class="mdi mdi-eye" aria-hidden="true"></i>
   </button>
   <ul class="dropdown-menu">
-    <button type="button" class="dropdown-item toggle-enabled" data-state="show">{% trans "Hide Enabled" %}</button>
-    <button type="button" class="dropdown-item toggle-disabled" data-state="show">{% trans "Hide Disabled" %}</button>
-    <button type="button" class="dropdown-item toggle-virtual" data-state="show">{% trans "Hide Virtual" %}</button>
-    <button type="button" class="dropdown-item toggle-disconnected" data-state="show">{% trans "Hide Disconnected" %}</button>
+    {# enabled filter: True = show only enabled (hide disabled), False = show only disabled (hide enabled) #}
+    <li>
+      <a class="dropdown-item{% if request.GET.enabled == 'True' %} active{% endif %}"
+         href="{{ request.path }}{% if request.GET.enabled == 'True' %}{% querystring enabled=None %}{% else %}{% querystring enabled='True' %}{% endif %}">
+        {% if request.GET.enabled == 'True' %}<i class="mdi mdi-check" aria-hidden="true"></i> {% endif %}{% trans "Hide Disabled" %}
+      </a>
+    </li>
+    <li>
+      <a class="dropdown-item{% if request.GET.enabled == 'False' %} active{% endif %}"
+         href="{{ request.path }}{% if request.GET.enabled == 'False' %}{% querystring enabled=None %}{% else %}{% querystring enabled='False' %}{% endif %}">
+        {% if request.GET.enabled == 'False' %}<i class="mdi mdi-check" aria-hidden="true"></i> {% endif %}{% trans "Hide Enabled" %}
+      </a>
+    </li>
+    {# kind filter: physical = show only physical (hide virtual/wireless) #}
+    <li>
+      <a class="dropdown-item{% if request.GET.kind == 'physical' %} active{% endif %}"
+         href="{{ request.path }}{% if request.GET.kind == 'physical' %}{% querystring kind=None %}{% else %}{% querystring kind='physical' %}{% endif %}">
+        {% if request.GET.kind == 'physical' %}<i class="mdi mdi-check" aria-hidden="true"></i> {% endif %}{% trans "Hide Virtual" %}
+      </a>
+    </li>
+    {# connected filter: True = show only connected (hide disconnected) #}
+    <li>
+      <a class="dropdown-item{% if request.GET.connected == 'True' %} active{% endif %}"
+         href="{{ request.path }}{% if request.GET.connected == 'True' %}{% querystring connected=None %}{% else %}{% querystring connected='True' %}{% endif %}">
+        {% if request.GET.connected == 'True' %}<i class="mdi mdi-check" aria-hidden="true"></i> {% endif %}{% trans "Hide Disconnected" %}
+      </a>
+    </li>
   </ul>
 {% endblock extra_table_controls %}

Некоторые файлы не были показаны из-за большого количества измененных файлов