forked from fixin.me/fixin.me
Migrate all inline JS to Stimulus controllers
Add stimulus-rails gem and wire up 7 controllers: - measurements_view_controller: view toggle (compact/wide) via localStorage - measurements_controller: grouped rows MutationObserver - charts_controller: Plotly chart rendering - form_controller: keyboard shortcuts (Escape/Enter) and submit validation - details_controller: quantity picker state, focusout close, MutationObserver - readout_unit_controller: default unit button enable/disable + PATCH submission - drag_controller: drag-and-drop for quantity reparenting and unit rebasing Remove all inline onclick/onkeydown/ondrag*/onsubmit handlers from templates. Remove all window.* global exports from application.js. Remove bare <script> block from measurements/_form.html.erb. Remove turbo:load listeners for behavior now in controller connect(). application.js now only contains: Turbo Stream custom action definitions and the showPage visibility listener. Document Stimulus conventions in CLAUDE.md. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
45
app/javascript/controllers/charts_controller.js
Normal file
45
app/javascript/controllers/charts_controller.js
Normal file
@@ -0,0 +1,45 @@
|
||||
import { Controller } from "@hotwired/stimulus"
|
||||
|
||||
export default class extends Controller {
|
||||
static targets = ["container", "data"]
|
||||
|
||||
connect() {
|
||||
const readouts = JSON.parse(this.dataTarget.textContent)
|
||||
if (readouts.length === 0) return
|
||||
|
||||
const quantities = new Map()
|
||||
readouts.forEach(r => {
|
||||
if (!r.takenAt) return
|
||||
if (!quantities.has(r.quantityId)) {
|
||||
quantities.set(r.quantityId, { name: r.quantityName, unit: r.unit, x: [], y: [] })
|
||||
}
|
||||
const q = quantities.get(r.quantityId)
|
||||
q.x.push(r.takenAt)
|
||||
q.y.push(r.value)
|
||||
})
|
||||
|
||||
const traces = []
|
||||
quantities.forEach(q => {
|
||||
traces.push({
|
||||
x: q.x, y: q.y,
|
||||
mode: 'lines+markers', type: 'scatter',
|
||||
name: q.name + ' (' + q.unit + ')',
|
||||
marker: { size: 5 }
|
||||
})
|
||||
})
|
||||
|
||||
const div = document.createElement('div')
|
||||
div.className = 'chart-panel'
|
||||
this.containerTarget.appendChild(div)
|
||||
|
||||
Plotly.newPlot(div, traces, {
|
||||
xaxis: { type: 'date', tickformat: '%Y-%m-%d %H:%M' },
|
||||
yaxis: {},
|
||||
margin: { t: 20, r: 20, b: 80, l: 60 },
|
||||
paper_bgcolor: 'transparent',
|
||||
plot_bgcolor: 'transparent',
|
||||
font: { family: 'system-ui' },
|
||||
legend: { orientation: 'h', y: -0.25 }
|
||||
}, { responsive: true, displayModeBar: false })
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user