1import { 2 Controller 3} from "@hotwired/stimulus" 4 5export default class extends Controller { 6 static targets = ["sizeCard"] 7 8 connect() { 9 this.launcherId = document.getElementById('launcher-id').dataset.launcherId; 10 this.chart_size_period = '7d' 11 this.chart_points_period = '7d' 12 this.chart_partials_period = '7d' 13 activeTab('statistics'); 14 this.initFarmChart(); 15 this.initPointsChart(); 16 this.initPartialsChart(); 17 convertUTCTime(); 18 this.lastPartialHighlight(); 19 this.lastCardRefresh = Date.now(); 20 this.lastChartRefresh = Date.now(); 21 this.cardRefreshInterval = setInterval(() => { 22 if (document.hidden) return; 23 this.refreshCards(); 24 }, 300 * 1000); 25 this.chartRefreshInterval = setInterval(() => { 26 if (document.hidden) return; 27 this.refreshCharts(); 28 }, 900 * 1000); 29 this.handleVisibilityChange = () => { 30 if (document.hidden) return; 31 const now = Date.now(); 32 if (now - this.lastCardRefresh >= 300 * 1000) this.refreshCards(); 33 if (now - this.lastChartRefresh >= 900 * 1000) this.refreshCharts(); 34 }; 35 document.addEventListener('visibilitychange', this.handleVisibilityChange); 36 } 37 38 disconnect() { 39 clearInterval(this.cardRefreshInterval); 40 clearInterval(this.chartRefreshInterval); 41 document.removeEventListener('visibilitychange', this.handleVisibilityChange); 42 window.removeEventListener('farmer:partial', this.newPartial, false); 43 } 44 45 refreshCards() { 46 this.lastCardRefresh = Date.now(); 47 fetch(`/farmers/${this.launcherId}/statistics_cards`) 48 .then(response => response.text()) 49 .then(html => { 50 const parser = new DOMParser(); 51 const doc = parser.parseFromString(html, 'text/html'); 52 ['farmer-size-card', 'farmer-points-card', 'farmer-partials-card'].forEach(id => { 53 const source = doc.getElementById(id); 54 const target = document.getElementById(id); 55 if (source && target) { 56 target.innerHTML = source.innerHTML; 57 } 58 }); 59 convertUTCTime(); 60 this.lastPartialHighlight(); 61 }); 62 } 63 64 refreshCharts() { 65 this.lastChartRefresh = Date.now(); 66 this.getFarmSizeData(); 67 this.getFarmPointsData(); 68 this.getFarmPartialsData(false); 69 } 70 71 lastPartialHighlight() { 72 if (document.querySelectorAll('.time-to-words').length > 0) 73 timeago.render(document.querySelectorAll('.time-to-words')); 74 window.addEventListener('farmer:partial', this.newPartial, false); 75 document.getElementById('last-partial').addEventListener('animationend', () => { 76 document.getElementById('last-partial').classList.remove('blink-bg'); 77 }); 78 } 79 80 sizeCardTargetConnected() { 81 convertUTCTime(); 82 this.lastPartialHighlight(); 83 } 84 85 newPartial(e) { 86 const action = e.detail.action 87 const partial = e.detail.data 88 if (action == 'create') { 89 document.getElementById('last-partial-time').dataset.date = new Date(partial.timestamp * 1000); 90 document.getElementById('last-partial-time').classList.add('utc-time'); 91 convertUTCTime(); 92 document.getElementById('last-partial-time-ago').setAttribute('datetime', partial.timestamp * 1000); 93 timeago.cancel(document.getElementById('last-partial-time-ago')); 94 timeago.render(document.getElementById('last-partial-time-ago')); 95 document.getElementById('last-partial').classList.add('blink-bg'); 96 } 97 } 98 99 initFarmChart() { 100 var chart = document.getElementById('farmChart'); 101 var lineChartColor = getChartColorsArray('farmChart'); 102 if (lineChartColor) { 103 this.farmChart = new Chart(chart, { 104 type: 'line', 105 data: { 106 datasets: [{ 107 label: "Farm size (TiB)", 108 fill: true, 109 lineTension: 0.2, 110 backgroundColor: lineChartColor[0], 111 borderColor: lineChartColor[1], 112 pointRadius: 1, 113 pointHitRadius: 30, 114 data: [], 115 yAxisID: 'TiB' 116 }, 117 { 118 label: "Difficulty", 119 fill: false, 120 lineTension: 0.2, 121 backgroundColor: lineChartColor[2], 122 borderColor: lineChartColor[3], 123 pointRadius: 1, 124 pointHitRadius: 30, 125 stepped: true, 126 data: [], 127 yAxisID: 'Difficulty' 128 } 129 ] 130 }, 131 options: { 132 maintainAspectRatio: false, 133 scales: { 134 xAxis: { 135 type: 'time', 136 time: { 137 unit: 'day' 138 }, 139 parsing: false 140 }, 141 TiB: { 142 min: 0, 143 position: 'right', 144 afterSetDimensions: (scale) => { 145 scale.paddingLeft = (window.innerWidth >= 1000 ? 70 : 0) 146 } 147 }, 148 Difficulty: { 149 min: 0, 150 position: 'left', 151 grid: { 152 display: false 153 }, 154 afterSetDimensions: (scale) => { 155 scale.paddingRight = (window.innerWidth >= 1000 ? 70 : 0) 156 } 157 } 158 }, 159 interaction: { 160 intersect: false, 161 mode: 'index', 162 }, 163 plugins: { 164 htmlLegend: { 165 // ID of the container to put the legend in 166 containerID: 'farm-size-legend', 167 }, 168 legend: { 169 display: false, 170 }, 171 }, 172 }, 173 plugins: [htmlLegendPlugin], 174 }); 175 } 176 this.getFarmSizeData(); 177 } 178 179 getFarmSizeData() { 180 const launcherId = document.getElementById('launcher-id').dataset.launcherId; 181 const url = '/api/charts/farm_size?launcher_id=' + launcherId + '&period=' + this.chart_size_period; 182 const $this = this 183 axios(url).then(function (response) { 184 $this.farmChart.data.datasets[0].data = response.data;
185 $this.farmChart.update(); 186 $this.getFarmDifficultyData(); 187 }) 188 } 189 190 getFarmDifficultyData() { 191 const launcherId = document.getElementById('launcher-id').dataset.launcherId; 192 var url = '/api/charts/farm_difficulty?launcher_id=' + launcherId + '&period=' + this.chart_size_period; 193 var $this = this 194 axios(url).then(function (response) { 195 $this.farmChart.data.datasets[1].data = response.data; 196 $this.farmChart.update(); 197 }) 198 } 199 200 initPointsChart() { 201 var chart = document.getElementById('pointsChart'); 202 var lineChartColor = getChartColorsArray('pointsChart'); 203 if (lineChartColor) { 204 this.pointsChart = new Chart(chart, { 205 type: 'bar', 206 data: { 207 datasets: [{ 208 label: "Points", 209 backgroundColor: lineChartColor[1], 210 borderColor: lineChartColor[1], 211 data: [], 212 yAxisID: 'Points' 213 }] 214 }, 215 options: { 216 maintainAspectRatio: false, 217 scales: { 218 xAxis: { 219 type: 'time', 220 offset: false, 221 max: nextHour(), 222 time: { 223 unit: 'day' 224 }, 225 parsing: false 226 }, 227 Points: { 228 min: 0, 229 position: 'right', 230 afterSetDimensions: (scale) => { 231 scale.paddingLeft = (window.innerWidth >= 1000 ? 70 : 0) 232 } 233 }, 234 ySpacing: { 235 display: false, 236 afterSetDimensions: (scale) => { 237 scale.paddingRight = (window.innerWidth >= 1000 ? 70 : 0) 238 } 239 }, 240 }, 241 interaction: { 242 intersect: false, 243 mode: 'index', 244 }, 245 plugins: { 246 htmlLegend: { 247 // ID of the container to put the legend in 248 containerID: 'points-legend', 249 }, 250 legend: { 251 display: false, 252 }, 253 }, 254 }, 255 plugins: [htmlLegendPlugin], 256 }); 257 } 258 this.getFarmPointsData(); 259 } 260 261 getFarmPointsData() { 262 const launcherId = document.getElementById('launcher-id').dataset.launcherId; 263 var url = '/api/charts/farm_points?launcher_id=' + launcherId + '&period=' + this.chart_points_period; 264 var $this = this 265 axios(url).then(function (response) { 266 $this.pointsChart.data.datasets[0].data = response.data; 267 $this.pointsChart.update(); 268 }) 269 } 270 271 toggleFarmSizes() { 272 var elements = document.getElementsByClassName("farm-sizes"); 273 Array.from(elements).forEach(function (el) { 274 el.classList.toggle("d-none"); 275 }); 276 } 277 278 initPartialsChart() { 279 var chart = document.getElementById('partialsChart'); 280 var lineChartColor = getChartColorsArray('partialsChart'); 281 if (lineChartColor) { 282 this.partialsChart = new Chart(chart, { 283 type: 'bar', 284 data: { 285 datasets: [] 286 }, 287 options: { 288 maintainAspectRatio: false, 289 scales: { 290 xAxis: { 291 stacked: true, 292 type: 'time', 293 offset: false, 294 max: nextHour(), 295 time: { 296 unit: 'day' 297 }, 298 parsing: false 299 }, 300 y: { 301 position: 'right', 302 stacked: true, 303 afterSetDimensions: (scale) => { 304 scale.paddingLeft = (window.innerWidth >= 1000 ? 70 : 0) 305 } 306 }, 307 ySpacing: { 308 display: false, 309 afterSetDimensions: (scale) => { 310 scale.paddingRight = (window.innerWidth >= 1000 ? 70 : 0) 311 } 312 }, 313 }, 314 interaction: { 315 intersect: false, 316 mode: 'index', 317 }, 318 plugins: { 319 htmlLegend: { 320 // ID of the container to put the legend in 321 containerID: 'partials-legend', 322 }, 323 legend: { 324 display: false, 325 }, 326 }, 327 }, 328 plugins: [htmlLegendPlugin], 329 }); 330 } 331 this.getFarmPartialsData(); 332 } 333 334 getFarmPartialsData(animate = true) { 335 const launcherId = document.getElementById('launcher-id').dataset.launcherId; 336 var url = '/api/charts/farm_partials?launcher_id=' + launcherId + '&period=' + this.chart_partials_period; 337 var $this = this 338 axios(url).then(function (response) { 339 $this.partialsChart.data.datasets = []; 340 response.data.map(row => { 341 var data = []; 342 $this.partialsChart.data.datasets.push({ 343 label: row.status_text, 344 backgroundColor: row.color, 345 data: row.data, 346 }); 347 }); 348 $this.partialsChart.update(animate ? null : 'none'); 349 }) 350 } 351
352 changeFarmChartPeriod(event) { 353 var elements = document.getElementsByClassName("farm-chart-period"); 354 elements && Array.from(elements).forEach(function (el) { 355 el.classList.remove("btn-primary"); 356 el.classList.add("btn-soft-dark"); 357 }); 358 event.target.classList.remove("btn-soft-dark"); 359 event.target.classList.add("btn-primary"); 360 var chart = document.getElementById('farmChart'); 361 this.chart_size_period = event.params.period 362 this.getFarmSizeData(); 363 } 364 365 changePointsChartPeriod(event) { 366 var elements = document.getElementsByClassName("points-chart-period"); 367 elements && Array.from(elements).forEach(function (el) { 368 el.classList.remove("btn-primary"); 369 el.classList.add("btn-soft-dark"); 370 }); 371 event.target.classList.remove("btn-soft-dark"); 372 event.target.classList.add("btn-primary"); 373 var chart = document.getElementById('pointsChart'); 374 this.chart_points_period = event.params.period 375 this.getFarmPointsData(); 376 } 377 378 changePartialsChartPeriod(event) { 379 var elements = document.getElementsByClassName("partials-chart-period"); 380 elements && Array.from(elements).forEach(function (el) { 381 el.classList.remove("btn-primary"); 382 el.classList.add("btn-soft-dark"); 383 }); 384 event.target.classList.remove("btn-soft-dark"); 385 event.target.classList.add("btn-primary"); 386 var chart = document.getElementById('partialsChart'); 387 this.chart_partials_period = event.params.period 388 this.getFarmPartialsData(); 389 } 390};
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.