diff --git a/netbox/project-static/dist/netbox.js b/netbox/project-static/dist/netbox.js index f7eed047e..d0552b34f 100644 Binary files a/netbox/project-static/dist/netbox.js and b/netbox/project-static/dist/netbox.js differ diff --git a/netbox/project-static/dist/netbox.js.map b/netbox/project-static/dist/netbox.js.map index a2d489708..d6dcdbad5 100644 Binary files a/netbox/project-static/dist/netbox.js.map and b/netbox/project-static/dist/netbox.js.map differ diff --git a/netbox/project-static/src/forms.ts b/netbox/project-static/src/forms.ts index c87cc6e49..b1bbb17a2 100644 --- a/netbox/project-static/src/forms.ts +++ b/netbox/project-static/src/forms.ts @@ -1,5 +1,10 @@ import { getElements, scrollTo } from './util'; +type ShowHideMap = { + default: { hide: string[]; show: string[] }; + [k: string]: { hide: string[]; show: string[] }; +}; + /** * Get form data from a form element and transform it into a body usable by fetch. * @@ -156,8 +161,112 @@ function initMoveButtons() { } } +/** + * Mapping of scope names to arrays of object types whose fields should be hidden or shown when + * the scope type (key) is selected. + * + * For example, if `region` is the scope type, the fields with IDs listed in + * showHideMap.region.hide should be hidden, and the fields with IDs listed in + * showHideMap.region.show should be shown. + */ +const showHideMap: ShowHideMap = { + region: { + hide: ['id_sitegroup', 'id_site', 'id_location', 'id_rack', 'id_clustergroup', 'id_cluster'], + show: ['id_region'], + }, + 'site group': { + hide: ['id_region', 'id_site', 'id_location', 'id_rack', 'id_clustergroup', 'id_cluster'], + show: ['id_sitegroup'], + }, + site: { + hide: ['id_location', 'id_rack', 'id_clustergroup', 'id_cluster'], + show: ['id_region', 'id_sitegroup', 'id_site'], + }, + location: { + hide: ['id_rack', 'id_clustergroup', 'id_cluster'], + show: ['id_region', 'id_sitegroup', 'id_site', 'id_location'], + }, + rack: { + hide: ['id_clustergroup', 'id_cluster'], + show: ['id_region', 'id_sitegroup', 'id_site', 'id_location', 'id_rack'], + }, + 'cluster group': { + hide: ['id_region', 'id_sitegroup', 'id_site', 'id_location', 'id_rack', 'id_cluster'], + show: ['id_clustergroup'], + }, + cluster: { + hide: ['id_region', 'id_sitegroup', 'id_site', 'id_location', 'id_rack'], + show: ['id_clustergroup', 'id_cluster'], + }, + default: { + hide: [ + 'id_region', + 'id_sitegroup', + 'id_site', + 'id_location', + 'id_rack', + 'id_clustergroup', + 'id_cluster', + ], + show: [], + }, +}; + +/** + * Toggle visibility of a given element's parent. + * @param query CSS Query. + * @param action Show or Hide the Parent. + */ +function toggleParentVisibility(query: string, action: 'show' | 'hide') { + for (const element of getElements(query)) { + if (action === 'show') { + element.parentElement?.classList.remove('d-none', 'invisible'); + } else { + element.parentElement?.classList.add('d-none', 'invisible'); + } + } +} + +/** + * Handle changes to the Scope Type field. + */ +function handleScopeChange(event: Event) { + const element = event.currentTarget as HTMLSelectElement; + // Scope type's innerText looks something like `DCIM > region`. + const scopeType = element.options[element.selectedIndex].innerText.toLowerCase(); + + for (const [scope, fields] of Object.entries(showHideMap)) { + // If the scope type ends with the specified scope, toggle its field visibility according to + // the show/hide values. + if (scopeType.endsWith(scope)) { + for (const field of fields.hide) { + toggleParentVisibility(`#${field}`, 'hide'); + } + for (const field of fields.show) { + toggleParentVisibility(`#${field}`, 'show'); + } + // Stop on first match. + break; + } else { + // Otherwise, hide all fields. + for (const field of showHideMap.default.hide) { + toggleParentVisibility(`#${field}`, 'hide'); + } + } + } +} + +/** + * Initialize scope type select event listeners. + */ +function initScopeSelector() { + for (const element of getElements('#id_scope_type')) { + element.addEventListener('change', handleScopeChange); + } +} + export function initForms() { - for (const func of [initFormElements, initMoveButtons]) { + for (const func of [initFormElements, initMoveButtons, initScopeSelector]) { func(); } } diff --git a/netbox/templates/ipam/vlangroup_edit.html b/netbox/templates/ipam/vlangroup_edit.html index ef8019ffe..65a5e7a03 100644 --- a/netbox/templates/ipam/vlangroup_edit.html +++ b/netbox/templates/ipam/vlangroup_edit.html @@ -28,78 +28,3 @@ {% endif %} {% endblock %} -{% block javascript %} - -{% endblock %}