mirror of
https://github.com/netbox-community/netbox.git
synced 2025-08-18 05:28:16 -06:00
Refactor TomSelect implementation
This commit is contained in:
parent
36824d16e0
commit
04c6083ff6
BIN
netbox/project-static/dist/netbox.js
vendored
BIN
netbox/project-static/dist/netbox.js
vendored
Binary file not shown.
BIN
netbox/project-static/dist/netbox.js.map
vendored
BIN
netbox/project-static/dist/netbox.js.map
vendored
Binary file not shown.
@ -1,11 +1,11 @@
|
|||||||
import { getElements, isTruthy } from './util';
|
import { getElements, isTruthy } from './util';
|
||||||
import { initButtons } from './buttons';
|
import { initButtons } from './buttons';
|
||||||
import { initSelect } from './select';
|
import { initSelects } from './select';
|
||||||
import { initObjectSelector } from './objectSelector';
|
import { initObjectSelector } from './objectSelector';
|
||||||
import { initBootstrap } from './bs';
|
import { initBootstrap } from './bs';
|
||||||
|
|
||||||
function initDepedencies(): void {
|
function initDepedencies(): void {
|
||||||
for (const init of [initButtons, initSelect, initObjectSelector, initBootstrap]) {
|
for (const init of [initButtons, initSelects, initObjectSelector, initBootstrap]) {
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import { initForms } from './forms';
|
import { initForms } from './forms';
|
||||||
import { initBootstrap } from './bs';
|
import { initBootstrap } from './bs';
|
||||||
import { initQuickSearch } from './search';
|
import { initQuickSearch } from './search';
|
||||||
// import { initSelect } from './select';
|
import { initSelects } from './select';
|
||||||
import { initSelects } from './tomSelect';
|
|
||||||
import { initButtons } from './buttons';
|
import { initButtons } from './buttons';
|
||||||
import { initColorMode } from './colorMode';
|
import { initColorMode } from './colorMode';
|
||||||
import { initMessages } from './messages';
|
import { initMessages } from './messages';
|
||||||
@ -23,7 +22,6 @@ function initDocument(): void {
|
|||||||
initMessages,
|
initMessages,
|
||||||
initForms,
|
initForms,
|
||||||
initQuickSearch,
|
initQuickSearch,
|
||||||
// initSelect,
|
|
||||||
initSelects,
|
initSelects,
|
||||||
initDateSelector,
|
initDateSelector,
|
||||||
initButtons,
|
initButtons,
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
import { getElements } from './util';
|
import { RecursivePartial, TomInput, TomSettings } from 'tom-select/dist/types/types';
|
||||||
import { RecursivePartial, TomInput, TomOption, TomSettings } from 'tom-select/src/types';
|
|
||||||
import { addClasses } from 'tom-select/src/vanilla'
|
import { addClasses } from 'tom-select/src/vanilla'
|
||||||
import queryString from 'query-string';
|
import queryString from 'query-string';
|
||||||
import TomSelect from 'tom-select';
|
import TomSelect from 'tom-select';
|
||||||
import type { Stringifiable } from 'query-string';
|
import type { Stringifiable } from 'query-string';
|
||||||
|
|
||||||
// Transitional
|
// Transitional
|
||||||
import { QueryFilter } from './select/api/types'
|
import { QueryFilter } from '../../select_old/api/types'
|
||||||
|
|
||||||
|
|
||||||
class DynamicTomSelect extends TomSelect {
|
// Extends TomSelect to provide enhanced fetching of options via the REST API
|
||||||
|
export class DynamicTomSelect extends TomSelect {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Transitional code from APISelect
|
* Transitional code from APISelect
|
||||||
@ -24,6 +24,7 @@ class DynamicTomSelect extends TomSelect {
|
|||||||
constructor( input_arg: string|TomInput, user_settings: RecursivePartial<TomSettings> ) {
|
constructor( input_arg: string|TomInput, user_settings: RecursivePartial<TomSettings> ) {
|
||||||
super(input_arg, user_settings);
|
super(input_arg, user_settings);
|
||||||
|
|
||||||
|
// Glean the REST API endpoint URL from the <select> element
|
||||||
this.api_url = this.input.getAttribute('data-url') as string;
|
this.api_url = this.input.getAttribute('data-url') as string;
|
||||||
|
|
||||||
// Populate static query parameters.
|
// Populate static query parameters.
|
||||||
@ -35,6 +36,7 @@ class DynamicTomSelect extends TomSelect {
|
|||||||
|
|
||||||
load(value: string) {
|
load(value: string) {
|
||||||
const self = this;
|
const self = this;
|
||||||
|
const url = self.getRequestUrl(value);
|
||||||
|
|
||||||
// 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.)
|
||||||
@ -45,16 +47,13 @@ class DynamicTomSelect extends TomSelect {
|
|||||||
addClasses(self.wrapper, self.settings.loadingClass);
|
addClasses(self.wrapper, self.settings.loadingClass);
|
||||||
self.loading++;
|
self.loading++;
|
||||||
|
|
||||||
const callback = self.loadCallback.bind(self);
|
|
||||||
const url = self.getRequestUrl(value);
|
|
||||||
|
|
||||||
// Make the API request
|
// Make the API request
|
||||||
fetch(url)
|
fetch(url)
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(json => {
|
.then(json => {
|
||||||
callback(json.results);
|
self.loadCallback(json.results, []);
|
||||||
}).catch(()=>{
|
}).catch(()=>{
|
||||||
callback();
|
self.loadCallback([], []);
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -63,9 +62,7 @@ class DynamicTomSelect extends TomSelect {
|
|||||||
* Custom methods
|
* Custom methods
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
// Formulate and return the complete URL for an API request, including any query parameters.
|
||||||
* Formulate and return the complete URL for an API request, including any query parameters.
|
|
||||||
*/
|
|
||||||
getRequestUrl(search: string): string {
|
getRequestUrl(search: string): string {
|
||||||
const url = this.api_url;
|
const url = this.api_url;
|
||||||
|
|
||||||
@ -91,13 +88,9 @@ class DynamicTomSelect extends TomSelect {
|
|||||||
* Transitional methods
|
* Transitional methods
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
// Determine if this instance's options should be filtered by static values passed from the
|
||||||
* Determine if this instance's options should be filtered by static values passed from the
|
// server. Looks for the DOM attribute `data-static-params`, the value of which is a JSON
|
||||||
* server.
|
// array of objects containing key/value pairs to add to `this.staticParams`.
|
||||||
*
|
|
||||||
* Looks for the DOM attribute `data-static-params`, the value of which is a JSON array of
|
|
||||||
* objects containing key/value pairs to add to `this.staticParams`.
|
|
||||||
*/
|
|
||||||
private getStaticParams(): void {
|
private getStaticParams(): void {
|
||||||
const serialized = this.input.getAttribute('data-static-params');
|
const serialized = this.input.getAttribute('data-static-params');
|
||||||
|
|
||||||
@ -122,53 +115,3 @@ class DynamicTomSelect extends TomSelect {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize <select> elements with statically-defined options
|
|
||||||
function initStaticSelects(): void {
|
|
||||||
|
|
||||||
for (const select of getElements<HTMLSelectElement>('select:not(.api-select):not(.color-select)')) {
|
|
||||||
new TomSelect(select, {
|
|
||||||
plugins: ['clear_button']
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize <select> elements which are populated via a REST API call
|
|
||||||
function initDynamicSelects(): void {
|
|
||||||
|
|
||||||
for (const select of getElements<HTMLSelectElement>('select.api-select')) {
|
|
||||||
new DynamicTomSelect(select, {
|
|
||||||
plugins: ['clear_button'],
|
|
||||||
valueField: 'id',
|
|
||||||
labelField: 'display',
|
|
||||||
searchField: [],
|
|
||||||
copyClassesToDropdown: false,
|
|
||||||
dropdownParent: 'body',
|
|
||||||
controlInput: '<input>',
|
|
||||||
preload: 'focus',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize color selection fields
|
|
||||||
function initColorSelects(): void {
|
|
||||||
|
|
||||||
for (const select of getElements<HTMLSelectElement>('select.color-select')) {
|
|
||||||
new TomSelect(select, {
|
|
||||||
render: {
|
|
||||||
option: function(item: TomOption, escape: Function) {
|
|
||||||
return `<div style="background-color: #${escape(item.value)}">${escape(item.text)}</div>`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
export function initSelects(): void {
|
|
||||||
initStaticSelects();
|
|
||||||
initDynamicSelects();
|
|
||||||
initColorSelects();
|
|
||||||
}
|
|
21
netbox/project-static/src/select/dynamic.ts
Normal file
21
netbox/project-static/src/select/dynamic.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { getElements } from '../util';
|
||||||
|
import { DynamicTomSelect } from './classes/dynamicTomSelect'
|
||||||
|
|
||||||
|
|
||||||
|
// Initialize <select> elements which are populated via a REST API call
|
||||||
|
export function initDynamicSelects(): void {
|
||||||
|
|
||||||
|
for (const select of getElements<HTMLSelectElement>('select.api-select')) {
|
||||||
|
new DynamicTomSelect(select, {
|
||||||
|
plugins: ['clear_button'],
|
||||||
|
valueField: 'id',
|
||||||
|
labelField: 'display',
|
||||||
|
searchField: [],
|
||||||
|
copyClassesToDropdown: false,
|
||||||
|
dropdownParent: 'body',
|
||||||
|
controlInput: '<input>',
|
||||||
|
preload: 'focus',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,9 +1,9 @@
|
|||||||
import { initApiSelect } from './api';
|
import { initColorSelects, initStaticSelects } from './static';
|
||||||
import { initColorSelect } from './color';
|
import { initDynamicSelects } from './dynamic';
|
||||||
import { initStaticSelect } from './static';
|
|
||||||
|
|
||||||
export function initSelect(): void {
|
|
||||||
for (const func of [initApiSelect, initColorSelect, initStaticSelect]) {
|
export function initSelects(): void {
|
||||||
func();
|
initStaticSelects();
|
||||||
}
|
initDynamicSelects();
|
||||||
|
initColorSelects();
|
||||||
}
|
}
|
||||||
|
@ -1,27 +1,30 @@
|
|||||||
import SlimSelect from 'slim-select';
|
|
||||||
import { getElements } from '../util';
|
import { getElements } from '../util';
|
||||||
|
import { TomOption } from 'tom-select/src/types';
|
||||||
|
import TomSelect from 'tom-select';
|
||||||
|
|
||||||
export function initStaticSelect(): void {
|
|
||||||
for (const select of getElements<HTMLSelectElement>('.netbox-static-select:not([data-ssid])')) {
|
|
||||||
if (select !== null) {
|
|
||||||
const label = document.querySelector(`label[for="${select.id}"]`) as HTMLLabelElement;
|
|
||||||
|
|
||||||
let placeholder;
|
// Initialize <select> elements with statically-defined options
|
||||||
if (label !== null) {
|
export function initStaticSelects(): void {
|
||||||
placeholder = `Select ${label.innerText.trim()}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
const instance = new SlimSelect({
|
for (const select of getElements<HTMLSelectElement>('select:not(.api-select):not(.color-select)')) {
|
||||||
select,
|
new TomSelect(select, {
|
||||||
allowDeselect: true,
|
plugins: ['clear_button']
|
||||||
deselectLabel: `<i class="mdi mdi-close-circle"></i>`,
|
|
||||||
placeholder,
|
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize color selection fields
|
||||||
|
export function initColorSelects(): void {
|
||||||
|
|
||||||
|
for (const select of getElements<HTMLSelectElement>('select.color-select')) {
|
||||||
|
new TomSelect(select, {
|
||||||
|
render: {
|
||||||
|
option: function(item: TomOption, escape: Function) {
|
||||||
|
return `<div style="background-color: #${escape(item.value)}">${escape(item.text)}</div>`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Don't copy classes from select element to SlimSelect instance.
|
|
||||||
for (const className of select.classList) {
|
|
||||||
instance.slim.container.classList.remove(className);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
9
netbox/project-static/src/select_old/index.ts
Normal file
9
netbox/project-static/src/select_old/index.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { initApiSelect } from './api';
|
||||||
|
import { initColorSelect } from './color';
|
||||||
|
import { initStaticSelect } from './static';
|
||||||
|
|
||||||
|
export function initSelect(): void {
|
||||||
|
for (const func of [initApiSelect, initColorSelect, initStaticSelect]) {
|
||||||
|
func();
|
||||||
|
}
|
||||||
|
}
|
27
netbox/project-static/src/select_old/static.ts
Normal file
27
netbox/project-static/src/select_old/static.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import SlimSelect from 'slim-select';
|
||||||
|
import { getElements } from '../util';
|
||||||
|
|
||||||
|
export function initStaticSelect(): void {
|
||||||
|
for (const select of getElements<HTMLSelectElement>('.netbox-static-select:not([data-ssid])')) {
|
||||||
|
if (select !== null) {
|
||||||
|
const label = document.querySelector(`label[for="${select.id}"]`) as HTMLLabelElement;
|
||||||
|
|
||||||
|
let placeholder;
|
||||||
|
if (label !== null) {
|
||||||
|
placeholder = `Select ${label.innerText.trim()}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const instance = new SlimSelect({
|
||||||
|
select,
|
||||||
|
allowDeselect: true,
|
||||||
|
deselectLabel: `<i class="mdi mdi-close-circle"></i>`,
|
||||||
|
placeholder,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Don't copy classes from select element to SlimSelect instance.
|
||||||
|
for (const className of select.classList) {
|
||||||
|
instance.slim.container.classList.remove(className);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user