1import { Controller } from '@hotwired/stimulus' 2import { CollapseUtils, collapse } from 'utils/collapse_utils' 3 4// Connects to data-controller='org--impound-update-multi' 5// The impound records index multi-update extras: reveals the update panel and 6// the checkbox column, enables only the checkboxes whose row supports the 7// selected update kind, and blocks submitting with nothing checked. The 8// kind-specific fields are handled by the separate org--impound-update controller. 9export default class extends Controller { 10 static targets = ['toggle', 'panel', 'kindSelect', 'error'] 11 static values = { openLabel: String, closedLabel: String, disabledTitle: String } 12 13 connect () { 14 // The panel may be rendered already-open (multi_update=true) â in that 15 // case sync the checkbox enabled state, since toggle() never runs. 16 if (this.panelOpen) { 17 this.refreshChecks() 18 } 19 } 20 21 toggle () { 22 this.panelOpen ? this.closePanel() : this.openPanel() 23 } 24 25 openPanel () { 26 collapse('show', this.panelTarget) 27 this.cells.forEach(cell => cell.classList.remove('tw:hidden')) 28 this.refreshChecks() 29 this.toggleTarget.textContent = this.openLabelValue 30 this.refreshTableEdges() 31 this.setUrlParam(true) 32 } 33 34 closePanel () { 35 collapse('hide', this.panelTarget) 36 this.cells.forEach(cell => cell.classList.add('tw:hidden')) 37 this.toggleTarget.textContent = this.closedLabelValue 38 this.refreshTableEdges() 39 this.setUrlParam(false) 40 } 41 42 // Showing/hiding the column changes which cell is last-visible â let the 43 // ui--table controller re-apply edge rounding/borders. 44 refreshTableEdges () { 45 window.dispatchEvent(new Event('ui-table:refresh')) 46 } 47 48 // Reflect the opened state in the URL without adding a history entry 49 setUrlParam (open) { 50 const url = new URL(window.location) 51 if (open) { 52 url.searchParams.set('multi_update', 'true') 53 } else { 54 url.searchParams.delete('multi_update') 55 } 56 window.history.replaceState(window.history.state, '', url) 57 } 58 59 get panelOpen () { 60 return CollapseUtils.isVisible(this.panelTarget) 61 } 62 63 // Block submitting the form with no rows checked, showing the error alert 64 validate (event) { 65 if (this.anyChecked) { 66 collapse('hide', this.errorTarget) 67 } else { 68 collapse('show', this.errorTarget) 69 event.preventDefault() 70 // stopImmediatePropagation keeps the event from reaching rails-ujs (which 71 // would disable the data-disable-with button and leave it stuck) and from 72 // reaching form-persist#clear (which would wipe the draft on a blocked submit). 73 event.stopImmediatePropagation() 74 } 75 } 76 77 // Once a row is checked, the "select a record" error no longer applies 78 hideErrorIfChecked () { 79 if (this.anyChecked) collapse('hide', this.errorTarget) 80 } 81 82 get anyChecked () { 83 return [...this.cells].some(cell => 84 cell.querySelector('input[type=checkbox]')?.checked 85 ) 86 } 87 88 // Enable only the checkboxes whose row supports the selected kind 89 refreshChecks () { 90 const kind = this.kindSelectTarget.value 91 this.cells.forEach(cell => { 92 const checkbox = cell.querySelector('input[type=checkbox]') 93 if (!checkbox) return 94 95 const allowed = checkbox.dataset.updateKinds.split(' ').includes(kind) 96 checkbox.disabled = !allowed 97 if (allowed) { 98 cell.removeAttribute('title') 99 } else { 100 checkbox.checked = false 101 cell.title = this.disabledTitleValue.replace('{kind}', this.kindLabel) 102 } 103 }) 104 } 105 106 get cells () { 107 return this.element.querySelectorAll('.multi-update-cell') 108 } 109 110 get kindLabel () { 111 return this.kindSelectTarget.selectedOptions[0]?.text 112 } 113};
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.