Closes #17256: Fix translation support in VLAN group scope assignment form (#17270)

* Closes #17256: Fix translation support in VLAN group scope assignment form

* Disable scope field if scope type not selected; update label on type change

* Reset selected scope object when changing scope type
This commit is contained in:
Jeremy Stretch
2024-08-27 13:58:56 -04:00
committed by GitHub
parent 4f225b4e56
commit c2d67fa17e
5 changed files with 47 additions and 250 deletions

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,9 +1,8 @@
import { initFormElements } from './elements';
import { initSpeedSelector } from './speedSelector';
import { initScopeSelector } from './scopeSelector';
export function initForms(): void {
for (const func of [initFormElements, initSpeedSelector, initScopeSelector]) {
for (const func of [initFormElements, initSpeedSelector]) {
func();
}
}

View File

@@ -1,153 +0,0 @@
import { getElements, toggleVisibility } from '../util';
type ShowHideMap = {
/**
* Name of view to which this map should apply.
*
* @example vlangroup_edit
*/
[view: string]: string;
};
type ShowHideLayout = {
/**
* Name of layout config
*
* @example vlangroup
*/
[config: string]: {
/**
* Default layout.
*/
default: { hide: string[]; show: string[] };
/**
* Field name to layout mapping.
*/
[fieldName: string]: { hide: string[]; show: string[] };
};
};
/**
* Mapping of layout 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 showHideLayout: ShowHideLayout = {
vlangroup: {
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: [],
},
},
};
/**
* Mapping of view names to layout configurations
*
* For example, if `vlangroup_add` is the view, use the layout configuration `vlangroup`.
*/
const showHideMap: ShowHideMap = {
vlangroup_add: 'vlangroup',
vlangroup_edit: 'vlangroup',
vlangroup_bulk_edit: 'vlangroup',
};
/**
* 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)) {
const parent = element.parentElement?.parentElement as Nullable<HTMLDivElement>;
if (parent !== null) {
if (action === 'show') {
toggleVisibility(parent, 'show');
} else {
toggleVisibility(parent, 'hide');
}
}
}
}
/**
* Handle changes to the Scope Type field.
*/
function handleScopeChange<P extends keyof ShowHideMap>(view: P, element: HTMLSelectElement) {
// Scope type's innerText looks something like `DCIM > region`.
const scopeType = element.options[element.selectedIndex].innerText.toLowerCase();
const layoutConfig = showHideMap[view];
for (const [scope, fields] of Object.entries(showHideLayout[layoutConfig])) {
// 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 showHideLayout[layoutConfig].default.hide) {
toggleParentVisibility(`#${field}`, 'hide');
}
}
}
}
/**
* Initialize scope type select event listeners.
*/
export function initScopeSelector(): void {
for (const view of Object.keys(showHideMap)) {
for (const element of getElements<HTMLSelectElement>(
`html[data-netbox-url-name="${view}"] #id_scope_type`,
)) {
handleScopeChange(view, element);
element.addEventListener('change', () => handleScopeChange(view, element));
}
}
}