From 9c247d9a19451d88b03835b467116a9f0d3ad0ef Mon Sep 17 00:00:00 2001 From: checktheroads Date: Tue, 6 Jul 2021 17:56:49 -0700 Subject: [PATCH] #5203: Persist Show/Hide Images state in rack view --- netbox/project-static/dist/netbox.js | Bin 687406 -> 692061 bytes netbox/project-static/dist/netbox.js.map | Bin 1623876 -> 1633522 bytes netbox/project-static/src/buttons.ts | 42 -------- netbox/project-static/src/netbox.ts | 2 + netbox/project-static/src/racks.ts | 92 ++++++++++++++++++ netbox/project-static/src/stores/index.ts | 1 + .../project-static/src/stores/rackImages.ts | 6 ++ 7 files changed, 101 insertions(+), 42 deletions(-) create mode 100644 netbox/project-static/src/racks.ts create mode 100644 netbox/project-static/src/stores/index.ts create mode 100644 netbox/project-static/src/stores/rackImages.ts diff --git a/netbox/project-static/dist/netbox.js b/netbox/project-static/dist/netbox.js index 1c713010408a3c3b7664774a328ee9d1076aee86..742da18197ab695f8f5f9fcc7582e0c1636e5779 100644 GIT binary patch delta 3921 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 Hb+!Eq2xT_@ delta 1512 zcmZWpPiz!b7|)c#?)Pc~l`fQp(Cr%9d3KzZXajWiby-RmA(TI%@zM}7`(}3M$?Qyb zXLhwN8){fYKqI%0a3GvK7(z5LR!@5Hq8yAS985GOdNT1~Le#`W;+x$TmT-ID``-J0 zzu))$-uwCXi}(JeD=nqf)7sGLZEb9AYQ@ShSF8fPPunvcFmhVbG( zF!0W=@ucG8jkifs;rQo1P^0J=Bv$qP@UF5$s5WiX&1x!SwjP?*k{xO;3-uCya*1pk zriLi0>ZIoBB3P)_LT8z(F74bfHG${yunlKgWG9}Vmyo9bdWX5@Yk^i{Rn@Dx?g(Ql zXVHqumCsCkbeWvX@hqQSJWGwRy4)!GRkfxEDm6ybfYo$QrBt_k&o(+h77O&c>DFvx zt&DZyf`z8no9J_dW!YYuMjP+FLsFmozrtif>W`-p|80@zt<1oGN}VdK38I0Q?o@rXeeR)@Q(&j3V-VL5*`e2+~yA z<+K5B$#h%PF9sy=l?)8v9~p_&pMmGruHZ`TD^YgaFM)p$LJ%loTa0tG`fjlJf%~?2rUQXKj zn^_on^3JlHnQMj#*9&F2Zi&Dwxb2$L-O=Q_Pkh=C(kDLt)ED203wcQ4%3-KJUzY?r zPU5r?$`c%K94CV~GzTj^Ws0}1#8MlhpF-f5b1=3+D!_pvN#LV7i1nAGE!QpN;JI1Y zf#Z3gN})5LyGc3X3wb!9IBoyzUXqiE-hEWiW|LaT7J2k*$TwEh3V3l>{002y1R1!J zKLV@yBZQ9Q#8vW9(q~n>QWI5MP3sffcm3+TZ`smZCO*7Mj?1APyhf7S-R@&y)R4%4 z94psIV#avPw9>_*B3TsJqR@pW!b83v24U4)()@NjyN)Dre!NEPtyX(`A*wv#j!_vOrw#d+78Wab`#Krzsi?U5v)F`ES^fJu NnNwCzy-)gk{s-zn>KFh3 diff --git a/netbox/project-static/dist/netbox.js.map b/netbox/project-static/dist/netbox.js.map index 0ca4ba92c9a4e7b075d965e8fbd4d339a6584f2e..8720570f1c2da842885d7f9874382d7e485b7fa1 100644 GIT binary patch delta 8068 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 V?fr|$Lmpl}9FA-q{V>wu`5&{zG#&r| delta 1237 zcmb7?U1%It6vx?3cIPJBY(8dpy{JiUDa~fXV2Gt{+9Wh*?rzsLiEDP7CXs?2cchkk5%S$uM9)VZTAZQf$+?i$nt5>}9W7s~f^kdhsqIm5r zK08Yo9(l#n>YD;9%h97LVYf7_tTh}jW#U>EAgd(+D!P^geqPs703ZXk=!BLAeo7vv zb0ERXTi8K7}M9`+BE-4Zb)_k3qKB%;jcrA^eLj%e6u`_pyTe>U<+63^&L<=}B zm2O~b<$UJm&8HcmjiTzeZzLDs3M(^CDYHW&w9o1*S` z8emqN1inw#IB?M@1#w#n_#BQNRJxnu#kh#^N&+v3l*8D)LS8@cAAb4Kzc>>!q@}Y# zj+3vEUQYrcqVx=8$7RmHnKB?<;ycrd{yBU)NA?C5bcpYlCU;iXhery8sHKEv=>TGP zlk$2}aC8PgCH|g<*#X_{7*)Os;K_FzefZs&!dfy(*%^k0fDcSAi9f<^A1Buj6HDKh z5Vu&upWh%K;rnlr4;l)rZ zcr}<$CQagnP5L9npf7 z&zp8M7GqDz@{D2g7VX2-Z{ZeXMBPPL-56$W($W3d!u*pgB`a1=3P(~<_g(pW-x`ZX zao`0tgd6K(3wJwgzT*%t_D9qeQ}yE~-_qzm_0K$H<<0-w|Mr$@J7jE8+Af<;wQP$C z7BP5>>Ud=^62dQU(J+4ToEpHvirR;dY}0OhYnxKM`FXf0STO8-(aadRvvPj?<-SO# z`*COFYFALk5=Ha8;aKywwp1LB2<~x('.rack_elevation')) { - const images = elevation.contentDocument?.querySelectorAll('image.device-image') ?? []; - for (const image of images) { - if (image !== null && !image.classList.contains('hidden')) { - image.classList.add('hidden'); - } - } - } - target.innerHTML = ` Show Images`; - target.setAttribute('selected', ''); - } else { - for (const elevation of getElements('.rack_elevation')) { - const images = elevation.contentDocument?.querySelectorAll('image.device-image') ?? []; - for (const image of images) { - if (image !== null) { - image.classList.remove('hidden'); - } - } - } - target.innerHTML = ` Hide Images`; - target.setAttribute('selected', 'selected'); - } - return; -} -/** - * Add onClick callback for toggling rack elevation images. - */ -function initRackElevation() { - for (const button of getElements('button.toggle-images')) { - button.addEventListener('click', handleRackImageToggle); - } -} - /** * When the toggle button is clicked, swap the connection status via the API and toggle CSS * classes to reflect the connection status. @@ -280,7 +239,6 @@ function initPerPage() { export function initButtons() { for (const func of [ - initRackElevation, initConnectionToggle, initReslug, initSelectAll, diff --git a/netbox/project-static/src/netbox.ts b/netbox/project-static/src/netbox.ts index 2b2d81979..7a5709aa9 100644 --- a/netbox/project-static/src/netbox.ts +++ b/netbox/project-static/src/netbox.ts @@ -10,6 +10,7 @@ import { initDateSelector } from './dateSelector'; import { initTableConfig } from './tableConfig'; import { initInterfaceTable } from './tables'; import { initSideNav } from './sidenav'; +import { initRackElevation } from './racks'; function init() { for (const init of [ @@ -25,6 +26,7 @@ function init() { initTableConfig, initInterfaceTable, initSideNav, + initRackElevation, ]) { init(); } diff --git a/netbox/project-static/src/racks.ts b/netbox/project-static/src/racks.ts new file mode 100644 index 000000000..ebf20a024 --- /dev/null +++ b/netbox/project-static/src/racks.ts @@ -0,0 +1,92 @@ +import { rackImagesState } from './stores'; +import { getElements } from './util'; + +import type { StateManager } from './state'; + +type RackToggleState = { hidden: boolean }; + +/** + * Toggle the Rack Image button to reflect the current state. If the current state is hidden and + * the images are therefore hidden, the button should say "Show Images". Likewise, if the current + * state is *not* hidden, and therefore the images are shown, the button should say "Hide Images". + * + * @param hidden Current State - `true` if images are hidden, `false` otherwise. + * @param button Button element. + */ +function toggleRackImagesButton(hidden: boolean, button: HTMLButtonElement): void { + const text = hidden ? 'Show Images' : 'Hide Images'; + const selected = hidden ? '' : 'selected'; + button.setAttribute('selected', selected); + button.innerHTML = ` ${text}`; +} + +/** + * Show all rack images. + */ +function showRackImages(): void { + for (const elevation of getElements('.rack_elevation')) { + const images = elevation.contentDocument?.querySelectorAll('image.device-image') ?? []; + for (const image of images) { + image.classList.remove('hidden'); + } + } +} + +/** + * Hide all rack images. + */ +function hideRackImages(): void { + for (const elevation of getElements('.rack_elevation')) { + const images = elevation.contentDocument?.querySelectorAll('image.device-image') ?? []; + for (const image of images) { + image.classList.add('hidden'); + } + } +} + +/** + * Toggle the visibility of device images and update the toggle button style. + */ +function handleRackImageToggle( + target: HTMLButtonElement, + state: StateManager, +): void { + const initiallyHidden = state.get('hidden'); + state.set('hidden', !initiallyHidden); + const hidden = state.get('hidden'); + + if (hidden) { + hideRackImages(); + } else { + showRackImages(); + } + toggleRackImagesButton(hidden, target); +} + +/** + * Add onClick callback for toggling rack elevation images. Synchronize the image toggle button + * text and display state of images with the local state. + */ +export function initRackElevation() { + const initiallyHidden = rackImagesState.get('hidden'); + for (const button of getElements('button.toggle-images')) { + toggleRackImagesButton(initiallyHidden, button); + + button.addEventListener( + 'click', + event => { + handleRackImageToggle(event.currentTarget as HTMLButtonElement, rackImagesState); + }, + false, + ); + } + for (const element of getElements('.rack_elevation')) { + element.addEventListener('load', () => { + if (initiallyHidden) { + hideRackImages(); + } else if (!initiallyHidden) { + showRackImages(); + } + }); + } +} diff --git a/netbox/project-static/src/stores/index.ts b/netbox/project-static/src/stores/index.ts new file mode 100644 index 000000000..5ee4adabb --- /dev/null +++ b/netbox/project-static/src/stores/index.ts @@ -0,0 +1 @@ +export * from './rackImages'; diff --git a/netbox/project-static/src/stores/rackImages.ts b/netbox/project-static/src/stores/rackImages.ts new file mode 100644 index 000000000..beeb25bce --- /dev/null +++ b/netbox/project-static/src/stores/rackImages.ts @@ -0,0 +1,6 @@ +import { createState } from '../state'; + +export const rackImagesState = createState<{ hidden: boolean }>( + { hidden: false }, + { persist: true }, +);