mirror of
https://github.com/netbox-community/netbox.git
synced 2026-01-17 01:02:18 -06:00
Compare commits
6 Commits
20383-rack
...
20911-drop
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5a1282e326 | ||
|
|
cb13eb277f | ||
|
|
24642be351 | ||
|
|
89af9efd85 | ||
|
|
99d678502f | ||
|
|
e6300ee06d |
@@ -722,9 +722,6 @@ class DeviceForm(TenancyForm, PrimaryModelForm):
|
|||||||
if position:
|
if position:
|
||||||
self.fields['position'].widget.choices = [(position, f'U{position}')]
|
self.fields['position'].widget.choices = [(position, f'U{position}')]
|
||||||
|
|
||||||
# Clear face field when rack is cleared
|
|
||||||
self.fields['face'].widget.attrs['ts-clear-field'] = 'rack'
|
|
||||||
|
|
||||||
|
|
||||||
class ModuleForm(ModuleCommonForm, PrimaryModelForm):
|
class ModuleForm(ModuleCommonForm, PrimaryModelForm):
|
||||||
device = DynamicModelChoiceField(
|
device = DynamicModelChoiceField(
|
||||||
@@ -736,9 +733,10 @@ class ModuleForm(ModuleCommonForm, PrimaryModelForm):
|
|||||||
)
|
)
|
||||||
module_bay = DynamicModelChoiceField(
|
module_bay = DynamicModelChoiceField(
|
||||||
label=_('Module bay'),
|
label=_('Module bay'),
|
||||||
queryset=ModuleBay.objects.all(),
|
queryset=ModuleBay.objects.order_by('name'),
|
||||||
query_params={
|
query_params={
|
||||||
'device_id': '$device'
|
'device_id': '$device',
|
||||||
|
'ordering': 'name',
|
||||||
},
|
},
|
||||||
context={
|
context={
|
||||||
'disabled': 'installed_module',
|
'disabled': 'installed_module',
|
||||||
|
|||||||
8
netbox/project-static/dist/netbox.js
vendored
8
netbox/project-static/dist/netbox.js
vendored
File diff suppressed because one or more lines are too long
6
netbox/project-static/dist/netbox.js.map
vendored
6
netbox/project-static/dist/netbox.js.map
vendored
File diff suppressed because one or more lines are too long
@@ -1,4 +1,3 @@
|
|||||||
import TomSelect from 'tom-select';
|
|
||||||
import { getElements } from '../util';
|
import { getElements } from '../util';
|
||||||
|
|
||||||
function handleFormSubmit(): void {
|
function handleFormSubmit(): void {
|
||||||
@@ -9,37 +8,6 @@ function handleFormSubmit(): void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize clear-field dependencies.
|
|
||||||
* When a field with ts-clear-field attribute's parent field is cleared, this field will also be cleared.
|
|
||||||
*/
|
|
||||||
function initClearFieldDependencies(): void {
|
|
||||||
// Find all fields with ts-clear-field attribute
|
|
||||||
for (const field of getElements<HTMLSelectElement>('[ts-clear-field]')) {
|
|
||||||
const parentFieldName = field.getAttribute('ts-clear-field');
|
|
||||||
if (!parentFieldName) continue;
|
|
||||||
|
|
||||||
// Find the parent field
|
|
||||||
const parentField = document.querySelector<HTMLSelectElement>(`[name="${parentFieldName}"]`);
|
|
||||||
if (!parentField) continue;
|
|
||||||
|
|
||||||
// Listen for changes on the parent field
|
|
||||||
parentField.addEventListener('change', () => {
|
|
||||||
// If parent field is cleared, also clear this dependent field
|
|
||||||
if (!parentField.value || parentField.value === '') {
|
|
||||||
// Check if this field uses TomSelect
|
|
||||||
const tomselect = (field as HTMLSelectElement & { tomselect?: TomSelect }).tomselect;
|
|
||||||
if (tomselect) {
|
|
||||||
tomselect.clear();
|
|
||||||
} else {
|
|
||||||
// Regular select field
|
|
||||||
field.value = '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attach event listeners to each form's submit/reset buttons.
|
* Attach event listeners to each form's submit/reset buttons.
|
||||||
*/
|
*/
|
||||||
@@ -60,7 +28,4 @@ export function initFormElements(): void {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize clear-field dependencies
|
|
||||||
initClearFieldDependencies();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,11 +75,15 @@ export class DynamicTomSelect extends TomSelect {
|
|||||||
load(value: string) {
|
load(value: string) {
|
||||||
const self = this;
|
const self = this;
|
||||||
|
|
||||||
|
const currentValue = self.getValue();
|
||||||
|
|
||||||
// Automatically clear any cached options. (Only options included
|
// Automatically clear any cached options. (Only options included
|
||||||
// in the API response should be present.)
|
// in the API response should be present.)
|
||||||
self.clearOptions();
|
self.clearOptions();
|
||||||
|
|
||||||
// Populate the null option (if any) if not searching
|
// Clear user_options to prevent the pre-selected option from being treated specially
|
||||||
|
(self as any).user_options = {};
|
||||||
|
|
||||||
if (self.nullOption && !value) {
|
if (self.nullOption && !value) {
|
||||||
self.addOption(self.nullOption);
|
self.addOption(self.nullOption);
|
||||||
}
|
}
|
||||||
@@ -93,21 +97,33 @@ export class DynamicTomSelect extends TomSelect {
|
|||||||
addClasses(self.wrapper, self.settings.loadingClass);
|
addClasses(self.wrapper, self.settings.loadingClass);
|
||||||
self.loading++;
|
self.loading++;
|
||||||
|
|
||||||
// Make the API request
|
|
||||||
fetch(url)
|
fetch(url)
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(apiData => {
|
.then(apiData => {
|
||||||
const results: Dict[] = apiData.results;
|
const results: Dict[] = apiData.results;
|
||||||
const options: Dict[] = [];
|
|
||||||
for (const result of results) {
|
// Add options and set $order to preserve API response order
|
||||||
|
results.forEach((result, index) => {
|
||||||
const option = self.getOptionFromData(result);
|
const option = self.getOptionFromData(result);
|
||||||
options.push(option);
|
self.addOption(option);
|
||||||
|
const key = option[self.settings.valueField as string] as string;
|
||||||
|
if (self.options[key]) {
|
||||||
|
(self.options[key] as any).$order = index;
|
||||||
}
|
}
|
||||||
return options;
|
});
|
||||||
})
|
|
||||||
// Pass the options to the callback function
|
if (self.loading > 0) {
|
||||||
.then(options => {
|
self.loading--;
|
||||||
self.loadCallback(options, []);
|
if (self.loading === 0) {
|
||||||
|
self.wrapper.classList.remove(self.settings.loadingClass as string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentValue && !self.items.includes(currentValue as string)) {
|
||||||
|
self.items.push(currentValue as string);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.refreshOptions(false);
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
self.loadCallback([], []);
|
self.loadCallback([], []);
|
||||||
|
|||||||
Reference in New Issue
Block a user