mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
Closes #11011: Hide virtual interfaces
This commit is contained in:
committed by
Jeremy Stretch
parent
a554164d1d
commit
eed6990b39
@ -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,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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) {
|
/**
|
||||||
|
* Table rows provided in constructor
|
||||||
|
*/
|
||||||
|
private rows: NodeListOf<HTMLTableRowElement>;
|
||||||
|
|
||||||
|
constructor(button: HTMLButtonElement, rows: NodeListOf<HTMLTableRowElement>) {
|
||||||
this.button = button;
|
this.button = button;
|
||||||
this.enabledRows = table.querySelectorAll<HTMLTableRowElement>('tr[data-enabled="enabled"]');
|
this.rows = rows;
|
||||||
this.disabledRows = table.querySelectorAll<HTMLTableRowElement>('tr[data-enabled="disabled"]');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This button's controlled type. For example, a button with the class `toggle-disabled` has
|
* Remove visibility of button state rows.
|
||||||
* directive 'disabled' because it controls the visibility of rows with
|
|
||||||
* `data-enabled="disabled"`. Likewise, `toggle-enabled` controls rows with
|
|
||||||
* `data-enabled="enabled"`.
|
|
||||||
*/
|
*/
|
||||||
private get directive(): InterfaceState {
|
private hideRows(): void {
|
||||||
if (this.button.classList.contains('toggle-disabled')) {
|
for (const row of this.rows) {
|
||||||
return 'disabled';
|
row.classList.add('d-none');
|
||||||
} 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');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Toggle visibility of rows with `data-enabled="enabled"`.
|
|
||||||
*/
|
|
||||||
private toggleEnabledRows(): void {
|
|
||||||
for (const row of this.enabledRows) {
|
|
||||||
row.classList.toggle('d-none');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Toggle visibility of rows with `data-enabled="disabled"`.
|
|
||||||
*/
|
|
||||||
private toggleDisabledRows(): void {
|
|
||||||
for (const row of this.disabledRows) {
|
|
||||||
row.classList.toggle('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.enabledButton = new ButtonState(
|
||||||
this.disabledButton = new ButtonState(toggleDisabledButton, this.table);
|
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
|
* When toggle buttons are clicked, reapply visability all rows and
|
||||||
* this instance's state.
|
* 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;
|
for (const row of this.rows) {
|
||||||
const enabled = button.isEqualNode(instance.enabledButton.button);
|
row.classList.remove('d-none');
|
||||||
const disabled = button.isEqualNode(instance.disabledButton.button);
|
|
||||||
|
|
||||||
if (enabled) {
|
|
||||||
instance.enabledButton.handleClick(event);
|
|
||||||
} else if (disabled) {
|
|
||||||
instance.disabledButton.handleClick(event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
instance.enabledButton.handleClick(event);
|
||||||
|
instance.disabledButton.handleClick(event);
|
||||||
|
instance.virtualButton.handleClick(event);
|
||||||
instance.toggleCaption();
|
instance.toggleCaption();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 %}
|
||||||
|
Reference in New Issue
Block a user