mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-21 19:47:20 -06:00
parent
60f48326e1
commit
6c1507c88c
@ -6,6 +6,7 @@
|
||||
|
||||
* [#8548](https://github.com/netbox-community/netbox/issues/8548) - Fix display of VC members when position is zero
|
||||
* [#8561](https://github.com/netbox-community/netbox/issues/8561) - Include option to connect a rear port to a console port
|
||||
* [#8331](https://github.com/netbox-community/netbox/issues/8331) - Implement `replaceAll` string utility function to improve browser compatibility
|
||||
|
||||
---
|
||||
|
||||
|
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.
BIN
netbox/project-static/dist/status.js
vendored
BIN
netbox/project-static/dist/status.js
vendored
Binary file not shown.
@ -8,11 +8,12 @@ import { DynamicParamsMap } from './dynamicParams';
|
||||
import { isStaticParams, isOption } from './types';
|
||||
import {
|
||||
hasMore,
|
||||
isTruthy,
|
||||
hasError,
|
||||
getElement,
|
||||
isTruthy,
|
||||
getApiData,
|
||||
getElement,
|
||||
isApiError,
|
||||
replaceAll,
|
||||
createElement,
|
||||
uniqueByProperty,
|
||||
findFirstAdjacent,
|
||||
@ -461,7 +462,7 @@ export class APISelect {
|
||||
// Set any primitive k/v pairs as data attributes on each option.
|
||||
for (const [k, v] of Object.entries(result)) {
|
||||
if (!['id', 'slug'].includes(k) && ['string', 'number', 'boolean'].includes(typeof v)) {
|
||||
const key = k.replace(/_/g, '-');
|
||||
const key = replaceAll(k, '_', '-');
|
||||
data[key] = String(v);
|
||||
}
|
||||
// Set option to disabled if the result contains a matching key and is truthy.
|
||||
@ -659,7 +660,7 @@ export class APISelect {
|
||||
for (const [key, value] of this.pathValues.entries()) {
|
||||
for (const result of this.url.matchAll(new RegExp(`({{${key}}})`, 'g'))) {
|
||||
if (isTruthy(value)) {
|
||||
url = url.replace(result[1], value.toString());
|
||||
url = replaceAll(url, result[1], value.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -741,7 +742,7 @@ export class APISelect {
|
||||
* @param id DOM ID of the other element.
|
||||
*/
|
||||
private updatePathValues(id: string): void {
|
||||
const key = id.replace(/^id_/gi, '');
|
||||
const key = replaceAll(id, /^id_/i, '');
|
||||
const element = getElement<HTMLSelectElement>(`id_${key}`);
|
||||
if (element !== null) {
|
||||
// If this element's URL contains Django template tags ({{), replace the template tag
|
||||
@ -919,16 +920,18 @@ export class APISelect {
|
||||
style.setAttribute('data-netbox', id);
|
||||
|
||||
// Scope the CSS to apply both the list item and the selected item.
|
||||
style.innerHTML = `
|
||||
style.innerHTML = replaceAll(
|
||||
`
|
||||
div.ss-values div.ss-value[data-id="${id}"],
|
||||
div.ss-list div.ss-option:not(.ss-disabled)[data-id="${id}"]
|
||||
{
|
||||
background-color: ${bg} !important;
|
||||
color: ${fg} !important;
|
||||
}
|
||||
`
|
||||
.replace(/\n/g, '')
|
||||
.trim();
|
||||
`,
|
||||
'\n',
|
||||
'',
|
||||
).trim();
|
||||
|
||||
// Add the style element to the DOM.
|
||||
document.head.appendChild(style);
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { getElements, findFirstAdjacent } from '../util';
|
||||
import { getElements, replaceAll, findFirstAdjacent } from '../util';
|
||||
|
||||
type InterfaceState = 'enabled' | 'disabled';
|
||||
type ShowHide = 'show' | 'hide';
|
||||
@ -105,9 +105,9 @@ class ButtonState {
|
||||
*/
|
||||
private toggleButton(): void {
|
||||
if (this.buttonState === 'show') {
|
||||
this.button.innerText = this.button.innerText.replace(/Show/g, 'Hide');
|
||||
this.button.innerText = replaceAll(this.button.innerText, 'Show', 'Hide');
|
||||
} else if (this.buttonState === 'hide') {
|
||||
this.button.innerText = this.button.innerText.replace(/Hide/g, 'Show');
|
||||
this.button.innerText = replaceAll(this.button.innerHTML, 'Hide', 'Show');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -315,7 +315,7 @@ export function* getRowValues(table: HTMLTableRowElement): Generator<string> {
|
||||
for (const element of table.querySelectorAll<HTMLTableCellElement>('td')) {
|
||||
if (element !== null) {
|
||||
if (isTruthy(element.innerText) && element.innerText !== '—') {
|
||||
yield element.innerText.replace(/[\n\r]/g, '').trim();
|
||||
yield replaceAll(element.innerText, '[\n\r]', '').trim();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -436,3 +436,49 @@ export function uniqueByProperty<T extends unknown, P extends keyof T>(arr: T[],
|
||||
}
|
||||
return Array.from(baseMap.values());
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace all occurrences of a pattern with a replacement string.
|
||||
*
|
||||
* This is a browser-compatibility-focused drop-in replacement for `String.prototype.replaceAll()`,
|
||||
* introduced in ES2021.
|
||||
*
|
||||
* @param input string to be processed.
|
||||
* @param pattern regex pattern string or RegExp object to search for.
|
||||
* @param replacement replacement substring with which `pattern` matches will be replaced.
|
||||
* @returns processed version of `input`.
|
||||
*/
|
||||
export function replaceAll(input: string, pattern: string | RegExp, replacement: string): string {
|
||||
// Ensure input is a string.
|
||||
if (typeof input !== 'string') {
|
||||
throw new TypeError("replaceAll 'input' argument must be a string");
|
||||
}
|
||||
// Ensure pattern is a string or RegExp.
|
||||
if (typeof pattern !== 'string' && !(pattern instanceof RegExp)) {
|
||||
throw new TypeError("replaceAll 'pattern' argument must be a string or RegExp instance");
|
||||
}
|
||||
// Ensure replacement is able to be stringified.
|
||||
switch (typeof replacement) {
|
||||
case 'boolean':
|
||||
replacement = String(replacement);
|
||||
break;
|
||||
case 'number':
|
||||
replacement = String(replacement);
|
||||
break;
|
||||
case 'string':
|
||||
break;
|
||||
default:
|
||||
throw new TypeError("replaceAll 'replacement' argument must be stringifyable");
|
||||
}
|
||||
|
||||
if (pattern instanceof RegExp) {
|
||||
// Add global flag to existing RegExp object and deduplicate
|
||||
const flags = Array.from(new Set([...pattern.flags.split(''), 'g'])).join('');
|
||||
pattern = new RegExp(pattern.source, flags);
|
||||
} else {
|
||||
// Create a RegExp object with the global flag set.
|
||||
pattern = new RegExp(pattern, 'g');
|
||||
}
|
||||
|
||||
return input.replace(pattern, replacement);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user