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

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

thatmattlove 4 лет назад
Родитель
Сommit
a2eb0d80d2

+ 1 - 0
docs/release-notes/version-3.0.md

@@ -14,6 +14,7 @@
 * [#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
 * [#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
 * [#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`

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


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


+ 43 - 11
netbox/project-static/src/forms/vlanTags.ts

@@ -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.
@@ -14,6 +14,38 @@ function fieldContainer(element: Nullable<HTMLSelectElement>): Nullable<HTMLElem
   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.
  */
@@ -29,7 +61,7 @@ function handleModeNone(): void {
     resetSelect(untaggedVlan);
     resetSelect(taggedVlans);
     for (const element of elements) {
-      toggleVisibility(fieldContainer(element), 'hide');
+      toggleVisibility(element, 'hide');
     }
   }
 }
@@ -46,9 +78,9 @@ function handleModeAccess(): void {
   if (all(elements)) {
     const [taggedVlans, untaggedVlan, vlanGroup] = elements;
     resetSelect(taggedVlans);
-    toggleVisibility(fieldContainer(vlanGroup), 'show');
-    toggleVisibility(fieldContainer(untaggedVlan), 'show');
-    toggleVisibility(fieldContainer(taggedVlans), 'hide');
+    toggleVisibility(vlanGroup, 'show');
+    toggleVisibility(untaggedVlan, 'show');
+    toggleVisibility(taggedVlans, 'hide');
   }
 }
 
@@ -63,9 +95,9 @@ function handleModeTagged(): void {
   ];
   if (all(elements)) {
     const [taggedVlans, untaggedVlan, vlanGroup] = elements;
-    toggleVisibility(fieldContainer(taggedVlans), 'show');
-    toggleVisibility(fieldContainer(vlanGroup), 'show');
-    toggleVisibility(fieldContainer(untaggedVlan), 'show');
+    toggleVisibility(taggedVlans, 'show');
+    toggleVisibility(vlanGroup, 'show');
+    toggleVisibility(untaggedVlan, 'show');
   }
 }
 
@@ -81,9 +113,9 @@ function handleModeTaggedAll(): void {
   if (all(elements)) {
     const [taggedVlans, untaggedVlan, vlanGroup] = elements;
     resetSelect(taggedVlans);
-    toggleVisibility(fieldContainer(vlanGroup), 'show');
-    toggleVisibility(fieldContainer(untaggedVlan), 'show');
-    toggleVisibility(fieldContainer(taggedVlans), 'hide');
+    toggleVisibility(vlanGroup, 'show');
+    toggleVisibility(untaggedVlan, 'show');
+    toggleVisibility(taggedVlans, 'hide');
   }
 }
 

+ 24 - 0
netbox/project-static/src/select/api/apiSelect.ts

@@ -320,6 +320,7 @@ export class APISelect {
         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.enable();
   }
 
   /**
@@ -357,6 +359,11 @@ export class APISelect {
       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
     // element to update its API query.
     // const dependencies = new Set([...this.filterParams.keys(), ...this.pathValues.keys()]);
@@ -578,6 +585,23 @@ export class APISelect {
     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.
    *

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