1import { Controller } from '@hotwired/stimulus' 2 3/* global localStorage */ 4 5// Connects to data-controller='org--search-column-settings' 6export default class extends Controller { 7 static targets = ['checkboxes'] 8 static values = { enabledColumns: Array, assignBikeSticker: Boolean } 9 10 connect () { 11 this.refreshEnabledColumns() 12 // The registrations search renders the checkboxes inside the results frame, which 13 // hasn't loaded yet - the frame's own render is what applies the stored selection there 14 if (this.hasCheckboxesTarget) this.selectStoredVisibleColumns() 15 document.addEventListener('turbo:frame-render', this.handleFrameRender) 16 } 17 18 disconnect () { 19 document.removeEventListener('turbo:frame-render', this.handleFrameRender) 20 } 21 22 // The checkboxes render inside the results frame, so a search replaces them unchecked - 23 // re-read the stored selection rather than applying what's in the DOM 24 handleFrameRender = (event) => { 25 if (!this.element.contains(event.target) || !this.hasCheckboxesTarget) return 26 this.refreshEnabledColumns() 27 this.selectStoredVisibleColumns() 28 } 29 30 refreshEnabledColumns () { 31 // Stimulus Array values return a fresh copy on each read, so mutating 32 // via push won't persist (and assign_bike_sticker_cell is ignored) 33 // build the full array, then assign it once. 34 const columns = [...this.element.querySelectorAll('th.hideableColumn')].map(th => 35 [...th.classList].find(c => c.endsWith('_cell')) 36 ).filter(Boolean) 37 38 if (this.assignBikeStickerValue) { 39 columns.push('assign_bike_sticker_cell') 40 } 41 42 this.enabledColumnsValue = columns 43 } 44 45 // An always-visible column's checkbox is disabled, and stays checked 46 get toggleableCheckboxes () { 47 return this.checkboxesTarget.querySelectorAll('input[type=checkbox]:not(:disabled)') 48 } 49 50 selectStoredVisibleColumns () { 51 const stored = localStorage.getItem('orgRegistrationColumns') 52 let columns = null 53 if (stored) { 54 try { columns = JSON.parse(stored) } catch { localStorage.removeItem('orgRegistrationColumns') } 55 } 56 57 this.toggleableCheckboxes.forEach(cb => { 58 cb.checked = columns ? columns.includes(cb.name) : cb.dataset.default === 'true' 59 }) 60 this.updateVisibleColumns() 61 } 62 63 updateVisibleColumns () { 64 const checked = [] 65 this.toggleableCheckboxes.forEach(cb => { 66 if (cb.checked) checked.push(cb.name) 67 }) 68 localStorage.setItem('orgRegistrationColumns', JSON.stringify(checked)) 69 70 if (this.assignBikeStickerValue) { 71 checked.push('assign_bike_sticker_cell') 72 } 73 74 this.enabledColumnsValue.forEach(col => { 75 const isVisible = checked.includes(col) 76 this.element.querySelectorAll(`.${col}`).forEach(el => { 77 el.classList.toggle('tw:hidden', !isVisible) 78 }) 79 }) 80 81 // Re-apply first/last visible column border styles via ui-table controller 82 window.dispatchEvent(new Event('ui-table:refresh')) 83 } 84};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.