1import { Controller } from "@hotwired/stimulus" 2 3// Connects to data-controller="strategy-feedback" 4export default class extends Controller { 5 static targets = ["button"] 6 static values = { 7 url: String, 8 current: String, 9 quarter: String 10 } 11 12 submit(event) { 13 const feedback = event.currentTarget.dataset.feedback 14 const csrfToken = document.querySelector('[name="csrf-token"]')?.content 15 16 // Optimistic UI: immediately show selected state 17 this.updateButtonStyles(feedback) 18 19 // Disable buttons during submission 20 this.buttonTargets.forEach(btn => { btn.disabled = true }) 21 22 fetch(this.urlValue, { 23 method: "POST", 24 headers: { 25 "Content-Type": "application/json", 26 "X-CSRF-Token": csrfToken, 27 "Accept": "text/vnd.turbo-stream.html" 28 }, 29 body: JSON.stringify(this.hasQuarterValue ? { feedback, quarter: this.quarterValue } : { feedback }) 30 }) 31 .then(response => { 32 if (!response.ok) throw new Error("Failed to submit feedback") 33 return response.text() 34 }) 35 .then(html => { 36 // Turbo Stream will replace the frame with server-rendered state 37 window.Turbo.renderStreamMessage(html) 38 }) 39 .catch(() => { 40 // Revert to previous state on error 41 this.updateButtonStyles(this.currentValue) 42 this.buttonTargets.forEach(btn => { btn.disabled = false }) 43 }) 44 } 45 46 updateButtonStyles(selectedFeedback) { 47 const styles = { 48 yes: { filled: "btn-success", outline: "btn-outline-success" }, 49 partially: { filled: "btn-warning", outline: "btn-outline-warning" }, 50 no: { filled: "btn-danger", outline: "btn-outline-danger" } 51 } 52 53 this.buttonTargets.forEach(btn => { 54 const value = btn.dataset.feedback 55 const style = styles[value] 56 if (!style) return 57 58 if (value === selectedFeedback) { 59 btn.classList.remove(style.outline) 60 btn.classList.add(style.filled) 61 } else { 62 btn.classList.remove(style.filled) 63 btn.classList.add(style.outline) 64 } 65 }) 66 } 67}
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.