1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

#7084: Fix issue where hidden VLAN form fields were incorrectly included in the form submission

This commit is contained in:
thatmattlove
2021-09-01 11:41:35 -07:00
parent 6f94198934
commit a2eb0d80d2
5 changed files with 76 additions and 19 deletions

View File

@ -14,6 +14,7 @@
* [#7082](https://github.com/netbox-community/netbox/issues/7082) - Avoid exception when referencing invalid content type in table * [#7082](https://github.com/netbox-community/netbox/issues/7082) - Avoid exception when referencing invalid content type in table
* [#7083](https://github.com/netbox-community/netbox/issues/7083) - Correct labeling for VM memory attribute * [#7083](https://github.com/netbox-community/netbox/issues/7083) - Correct labeling for VM memory attribute
* [#7084](https://github.com/netbox-community/netbox/issues/7084) - Fix KeyError exception when editing access VLAN on an interface * [#7084](https://github.com/netbox-community/netbox/issues/7084) - Fix KeyError exception when editing access VLAN on an interface
* [#7084](https://github.com/netbox-community/netbox/issues/7084) - Fix issue where hidden VLAN form fields were incorrectly included in the form submission
* [#7089](https://github.com/netbox-community/netbox/issues/7089) - Fix ContentTypeFilterSet not filtering on q filter * [#7089](https://github.com/netbox-community/netbox/issues/7089) - Fix ContentTypeFilterSet not filtering on q filter
* [#7090](https://github.com/netbox-community/netbox/issues/7090) - Fix Cable Bulk Edit Form - allow decimal input on Length field * [#7090](https://github.com/netbox-community/netbox/issues/7090) - Fix Cable Bulk Edit Form - allow decimal input on Length field
* [#7091](https://github.com/netbox-community/netbox/issues/7091) - Ensure API requests from the UI are aware of `BASE_PATH` * [#7091](https://github.com/netbox-community/netbox/issues/7091) - Ensure API requests from the UI are aware of `BASE_PATH`

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,4 +1,4 @@
import { all, getElement, resetSelect, toggleVisibility } from '../util'; import { all, getElement, resetSelect, toggleVisibility as _toggleVisibility } from '../util';
/** /**
* Get a select element's containing `.row` element. * Get a select element's containing `.row` element.
@ -14,6 +14,38 @@ function fieldContainer(element: Nullable<HTMLSelectElement>): Nullable<HTMLElem
return null; return null;
} }
/**
* Toggle visibility of the select element's container and disable the select element itself.
*
* @param element Select element.
* @param action 'show' or 'hide'
*/
function toggleVisibility<E extends Nullable<HTMLSelectElement>>(
element: E,
action: 'show' | 'hide',
): void {
// Find the select element's containing element.
const parent = fieldContainer(element);
if (element !== null && parent !== null) {
// Toggle container visibility to visually remove it from the form.
_toggleVisibility(parent, action);
// Create a new event so that the APISelect instance properly handles the enable/disable
// action.
const event = new Event(`netbox.select.disabled.${element.name}`);
switch (action) {
case 'hide':
// Disable the native select element and dispatch the event APISelect is listening for.
element.disabled = true;
element.dispatchEvent(event);
break;
case 'show':
// Enable the native select element and dispatch the event APISelect is listening for.
element.disabled = false;
element.dispatchEvent(event);
}
}
}
/** /**
* Toggle element visibility when the mode field does not have a value. * Toggle element visibility when the mode field does not have a value.
*/ */
@ -29,7 +61,7 @@ function handleModeNone(): void {
resetSelect(untaggedVlan); resetSelect(untaggedVlan);
resetSelect(taggedVlans); resetSelect(taggedVlans);
for (const element of elements) { for (const element of elements) {
toggleVisibility(fieldContainer(element), 'hide'); toggleVisibility(element, 'hide');
} }
} }
} }
@ -46,9 +78,9 @@ function handleModeAccess(): void {
if (all(elements)) { if (all(elements)) {
const [taggedVlans, untaggedVlan, vlanGroup] = elements; const [taggedVlans, untaggedVlan, vlanGroup] = elements;
resetSelect(taggedVlans); resetSelect(taggedVlans);
toggleVisibility(fieldContainer(vlanGroup), 'show'); toggleVisibility(vlanGroup, 'show');
toggleVisibility(fieldContainer(untaggedVlan), 'show'); toggleVisibility(untaggedVlan, 'show');
toggleVisibility(fieldContainer(taggedVlans), 'hide'); toggleVisibility(taggedVlans, 'hide');
} }
} }
@ -63,9 +95,9 @@ function handleModeTagged(): void {
]; ];
if (all(elements)) { if (all(elements)) {
const [taggedVlans, untaggedVlan, vlanGroup] = elements; const [taggedVlans, untaggedVlan, vlanGroup] = elements;
toggleVisibility(fieldContainer(taggedVlans), 'show'); toggleVisibility(taggedVlans, 'show');
toggleVisibility(fieldContainer(vlanGroup), 'show'); toggleVisibility(vlanGroup, 'show');
toggleVisibility(fieldContainer(untaggedVlan), 'show'); toggleVisibility(untaggedVlan, 'show');
} }
} }
@ -81,9 +113,9 @@ function handleModeTaggedAll(): void {
if (all(elements)) { if (all(elements)) {
const [taggedVlans, untaggedVlan, vlanGroup] = elements; const [taggedVlans, untaggedVlan, vlanGroup] = elements;
resetSelect(taggedVlans); resetSelect(taggedVlans);
toggleVisibility(fieldContainer(vlanGroup), 'show'); toggleVisibility(vlanGroup, 'show');
toggleVisibility(fieldContainer(untaggedVlan), 'show'); toggleVisibility(untaggedVlan, 'show');
toggleVisibility(fieldContainer(taggedVlans), 'hide'); toggleVisibility(taggedVlans, 'hide');
} }
} }

View File

@ -320,6 +320,7 @@ export class APISelect {
this.slim.slim.multiSelected.container.setAttribute('disabled', ''); this.slim.slim.multiSelected.container.setAttribute('disabled', '');
} }
} }
this.slim.disable();
} }
/** /**
@ -335,6 +336,7 @@ export class APISelect {
this.slim.slim.multiSelected.container.removeAttribute('disabled'); this.slim.slim.multiSelected.container.removeAttribute('disabled');
} }
} }
this.slim.enable();
} }
/** /**
@ -357,6 +359,11 @@ export class APISelect {
this.fetchOptions(this.more, 'merge'), this.fetchOptions(this.more, 'merge'),
); );
// When the base select element is disabled or enabled, properly disable/enable this instance.
this.base.addEventListener(`netbox.select.disabled.${this.name}`, event =>
this.handleDisableEnable(event),
);
// Create a unique iterator of all possible form fields which, when changed, should cause this // Create a unique iterator of all possible form fields which, when changed, should cause this
// element to update its API query. // element to update its API query.
// const dependencies = new Set([...this.filterParams.keys(), ...this.pathValues.keys()]); // const dependencies = new Set([...this.filterParams.keys(), ...this.pathValues.keys()]);
@ -578,6 +585,23 @@ export class APISelect {
Promise.all([this.loadData()]); Promise.all([this.loadData()]);
} }
/**
* Event handler to be dispatched when the base select element is disabled or enabled. When that
* occurs, run the instance's `disable()` or `enable()` methods to synchronize UI state with
* desired action.
*
* @param event Dispatched event matching pattern `netbox.select.disabled.<name>`
*/
private handleDisableEnable(event: Event): void {
const target = event.target as HTMLSelectElement;
if (target.disabled === true) {
this.disable();
} else if (target.disabled === false) {
this.enable();
}
}
/** /**
* When the API returns an error, show it to the user and reset this element's available options. * When the API returns an error, show it to the user and reset this element's available options.
* *