{"version":3,"file":"equation_chart_controller-BKmLcsdW.js","sources":["../../../app/javascript/entrypoints/controllers/equation_chart_controller.jsx"],"sourcesContent":["/** @jsx renderer.create */\n\nimport { Controller } from \"@hotwired/stimulus\";\nimport dayjs from \"dayjs\";\n\nimport {\n Chart,\n CategoryScale,\n LinearScale,\n PointElement,\n LineElement,\n Title,\n Tooltip,\n Legend,\n} from \"chart.js\";\nimport ChartDataLabels from \"chartjs-plugin-datalabels\";\n\nimport _ from \"lodash\";\n\nimport { useWindowResize } from \"stimulus-use\";\nimport { useResize } from \"stimulus-use\";\nimport currency from \"currency.js\";\n\nimport { CommonDOMRenderer } from \"render-jsx/dom\";\n\nimport numbro from \"numbro\";\n\nimport { ticksCallback } from \"../utils\";\n\nChart.register(\n CategoryScale,\n LinearScale,\n PointElement,\n LineElement,\n Title,\n Tooltip,\n Legend,\n ChartDataLabels\n);\n\nconst red = \"rgba(255, 0, 0, 1)\";\nconst black = \"rgb(0, 0, 0, 1)\";\n\nconst tooltipWidth = 500;\n\nconst getOrCreateLegendList = (chart, id) => {\n const legendContainer = document.getElementById(id);\n let listContainer = legendContainer.querySelector(\"ul\");\n\n if (!listContainer) {\n listContainer = document.createElement(\"ul\");\n listContainer.style.display = \"flex\";\n listContainer.style.flexDirection = \"row\";\n listContainer.style.margin = 0;\n listContainer.style.padding = 0;\n\n legendContainer.appendChild(listContainer);\n }\n\n return listContainer;\n};\n\nexport default class extends Controller {\n chart = null;\n initial = false;\n values = [];\n labels = [];\n\n static targets = [\"chart\"];\n\n static values = {\n jsonData: Object,\n };\n\n initialize() {\n this.resize = _.debounce(this.resize, 250).bind(this);\n this.windowResize = _.debounce(this.windowResize, 250).bind(this);\n\n Chart.defaults.plugins.legend.onHover = function () {\n document.body.style.cursor = \"pointer\";\n };\n\n Chart.defaults.plugins.legend.onLeave = function () {\n document.body.style.cursor = \"unset\";\n };\n }\n\n chartTargetDisconnect(element) {\n const chart = Chart.getChart(element.id);\n if (chart) {\n chart.destroy();\n }\n }\n\n jsonDataValueChanged() {\n if (!this.initial) {\n this.initial = true;\n } else {\n let chart = Chart.getChart(\"canvas-element\");\n\n const parsedData = this.jsonDataValue;\n\n const parsedEntries = parsedData.entries.map((entry) =>\n JSON.parse(entry)\n );\n const datasets = parsedEntries.map((entry) => ({\n type: \"line\",\n label: entry.name,\n data: Object.values(entry.rows),\n backgroundColor: entry.color,\n segmentColor: entry.color,\n borderColor: entry.color,\n ...this.baseDatalabelOptions(),\n }));\n\n const firstDataset = parsedEntries[0];\n const rows = firstDataset.rows;\n\n this.values = datasets;\n\n this.min = Math.min(...parsedEntries.map((entry) => entry.min)) || null;\n this.max = Math.max(...parsedEntries.map((entry) => entry.max)) || null;\n\n this.dataType = firstDataset.data_type;\n this.reverse = firstDataset.upside_down;\n this.decimalPlaces = firstDataset.decimal_places;\n this.tracking = firstDataset.tracking;\n this.endOfWeek = firstDataset.end_of_week;\n\n this.equations = firstDataset.equations;\n\n if (this.tracking == \"week\") {\n this.labels = Object.keys(firstDataset.rows).map(\n (key) => this.endOfWeek[key]\n );\n } else {\n this.labels = Object.keys(firstDataset.rows) || [];\n }\n\n if (chart) {\n chart.data.labels = this.labels;\n chart.data.datasets = this.values;\n\n chart.options = this.options(rows);\n\n chart.update(\"reset\");\n chart.update(\"normal\");\n } else {\n const ctx = document.getElementById(\"canvas-element\").getContext(\"2d\");\n this.createChart(ctx, rows, this.element);\n }\n }\n }\n\n chartTargetConnected(element) {\n useWindowResize(this);\n useResize(this);\n\n const parsedData = this.jsonDataValue;\n\n if (_.isEmpty(parsedData)) {\n return;\n }\n\n const ctx = document.getElementById(element.id).getContext(\"2d\");\n\n const parsedEntries = parsedData.entries.map((entry) => JSON.parse(entry));\n const datasets = parsedEntries.map((entry) => ({\n type: \"line\",\n label: entry.name,\n data: Object.values(entry.rows),\n backgroundColor: entry.color,\n segmentColor: entry.color,\n borderColor: entry.color,\n ...this.baseDatalabelOptions(),\n }));\n\n const firstDataset = JSON.parse(parsedData.entries[0]);\n const data = firstDataset.rows;\n\n this.values = datasets;\n this.equations = firstDataset.equations;\n\n this.min = Math.min(...parsedEntries.map((entry) => entry.min)) || null;\n this.max = Math.max(...parsedEntries.map((entry) => entry.max)) || null;\n\n this.dataType = firstDataset.data_type;\n this.reverse = firstDataset.upside_down;\n this.decimalPlaces = firstDataset.decimal_places;\n this.tracking = firstDataset.tracking;\n this.endOfWeek = firstDataset.end_of_week;\n\n if (this.tracking == \"week\") {\n this.labels = Object.keys(firstDataset.rows).map(\n (key) => this.endOfWeek[key]\n );\n } else {\n this.labels = Object.keys(firstDataset.rows) || [];\n }\n\n if (_.isEmpty(this.labels) || _.isEmpty(this.values)) {\n return;\n }\n\n this.createChart(ctx, data, element);\n }\n\n getOrCreateTooltip = (chart) => {\n let tooltipEl = chart.canvas.parentNode.querySelector(\"div\");\n\n if (!tooltipEl) {\n tooltipEl = document.createElement(\"div\");\n\n tooltipEl.classList.add(\n \"bg-gray-100\",\n \"text-black\",\n \"rounded\",\n \"shadow-lg\",\n \"border\"\n );\n\n tooltipEl.style.opacity = 1;\n tooltipEl.style.pointerEvents = \"none\";\n tooltipEl.style.position = \"absolute\";\n tooltipEl.style.transform = \"translate(-50%, 0)\";\n tooltipEl.style.transition = \"all .1s ease\";\n tooltipEl.style.zIndex = \"9999999999999999999999\";\n\n const table = document.createElement(\"table\");\n table.style.margin = \"0px\";\n\n tooltipEl.appendChild(table);\n chart.canvas.parentNode.appendChild(tooltipEl);\n }\n\n return tooltipEl;\n };\n\n externalTooltipHandler = (context) => {\n const { chart, tooltip } = context;\n const tooltipEl = this.getOrCreateTooltip(chart);\n\n tooltipEl.innerHTML = \"\";\n\n if (tooltip.opacity === 0) {\n tooltipEl.style.opacity = 0;\n return;\n }\n\n if (tooltip.body) {\n const bodyLines = tooltip.body.map((b) => b.lines);\n const titleLines = tooltip.title || [];\n const renderer = new CommonDOMRenderer();\n\n renderer\n .render(\n