4
0

statsWithChartjs.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. // @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-3.0
  2. 'use strict';
  3. /* globals Chart */
  4. function initCharts() {
  5. if (!window.Chart) {
  6. if (window.console) {
  7. console.log('FreshRSS is waiting for Chart.js…');
  8. }
  9. window.setTimeout(initCharts, 25);
  10. return;
  11. }
  12. const jsonData = document.getElementsByClassName('jsonData-stats');
  13. let jsonDataParsed;
  14. let chartConfig;
  15. for (let i = 0; i < jsonData.length; i++) {
  16. jsonDataParsed = JSON.parse(jsonData[i].innerHTML);
  17. switch (jsonDataParsed.charttype) {
  18. case 'bar':
  19. chartConfig = jsonChartBar(jsonDataParsed.label, jsonDataParsed.data, jsonDataParsed.xAxisLabels);
  20. break;
  21. case 'doughnut':
  22. chartConfig = jsonChartDoughnut(jsonDataParsed.labels, jsonDataParsed.data);
  23. break;
  24. case 'barWithAverage':
  25. chartConfig = jsonChartBarWithAverage(jsonDataParsed.labelBarChart, jsonDataParsed.dataBarChart,
  26. jsonDataParsed.labelAverage, jsonDataParsed.dataAverage, jsonDataParsed.xAxisLabels);
  27. }
  28. /* eslint-disable no-new */
  29. new Chart(document.getElementById(jsonDataParsed.canvasID), chartConfig);
  30. /* eslint-enable no-new */
  31. }
  32. // Force resize after clicking enlarge button (needed since chart.js v4)
  33. for (const id in Chart.instances) {
  34. const instance = Chart.instances[id];
  35. const boxTitle = instance.canvas.parentElement.previousElementSibling;
  36. const enlargeBtns = boxTitle.querySelectorAll('a.btn');
  37. function forceResize() {
  38. function waitHash() {
  39. requestAnimationFrame(() => instance.resize());
  40. window.removeEventListener('hashchange', waitHash);
  41. }
  42. instance.resize(); // try early resize
  43. window.addEventListener('hashchange', waitHash);
  44. }
  45. for (const btn of enlargeBtns) {
  46. btn.addEventListener('click', forceResize);
  47. }
  48. }
  49. window.addEventListener('resize', () => {
  50. for (const id in Chart.instances) {
  51. const instance = Chart.instances[id];
  52. // Workaround for a chart.js bug which makes the canvas blurry if
  53. // page was loaded with very low zoom level and later zoomed in
  54. instance.update();
  55. instance.resize();
  56. }
  57. });
  58. if (window.console) {
  59. console.log('Chart.js finished');
  60. }
  61. }
  62. function jsonChartBar(label, data, xAxisLabels = '') {
  63. return {
  64. type: 'bar',
  65. data: {
  66. labels: xAxisLabels,
  67. datasets: [{
  68. label,
  69. backgroundColor: '#0062BD',
  70. borderColor: '#0062BD',
  71. data,
  72. barPercentage: 1.0,
  73. categoryPercentage: 1.0,
  74. order: 2,
  75. }],
  76. },
  77. options: {
  78. scales: {
  79. y: {
  80. beginAtZero: true,
  81. },
  82. x: {
  83. grid: {
  84. display: false,
  85. },
  86. },
  87. },
  88. plugins: {
  89. legend: {
  90. display: false,
  91. },
  92. },
  93. },
  94. };
  95. }
  96. function jsonChartDoughnut(labels, data) {
  97. return {
  98. type: 'doughnut',
  99. data: {
  100. labels,
  101. datasets: [{
  102. backgroundColor: [
  103. '#0b84a5', // petrol
  104. '#f6c85f', // sand
  105. '#6f4e7c', // purple
  106. '#9dd866', // green
  107. '#ca472f', // red
  108. '#ffa056', // orange
  109. '#8dddd0', // turkis
  110. '#f6c85f', // sand
  111. '#6f4e7c', // purple
  112. '#9dd866', // green
  113. '#ca472f', // red
  114. '#ffa056', // orange
  115. '#8dddd0', // turkis
  116. ],
  117. data,
  118. }],
  119. },
  120. options: {
  121. layout: {
  122. padding: 20,
  123. },
  124. plugins: {
  125. legend: {
  126. position: 'bottom',
  127. align: 'start',
  128. },
  129. },
  130. },
  131. };
  132. }
  133. function jsonChartBarWithAverage(labelBarChart, dataBarChart, labelAverage, dataAverage, xAxisLabels = '') {
  134. return {
  135. type: 'bar',
  136. data: {
  137. datasets: [
  138. {
  139. // bar chart layout
  140. label: labelBarChart,
  141. backgroundColor: '#0062BD',
  142. borderColor: '#0062BD',
  143. data: dataBarChart,
  144. barPercentage: 1.0,
  145. categoryPercentage: 1.0,
  146. order: 2,
  147. },
  148. {
  149. // average line chart
  150. type: 'line',
  151. label: labelAverage, // Todo: i18n
  152. borderColor: 'rgb(192,216,0)',
  153. data: {
  154. '-30': dataAverage,
  155. '-1': dataAverage,
  156. },
  157. order: 1,
  158. },
  159. ],
  160. },
  161. options: {
  162. scales: {
  163. y: {
  164. beginAtZero: true,
  165. },
  166. x: {
  167. ticks: {
  168. callback: function (val) {
  169. if (xAxisLabels.length > 0) {
  170. return xAxisLabels[val];
  171. } else {
  172. return val;
  173. }
  174. },
  175. },
  176. grid: {
  177. display: false,
  178. },
  179. },
  180. },
  181. elements: {
  182. point: {
  183. radius: 0,
  184. },
  185. },
  186. plugins: {
  187. tooltip: {
  188. callbacks: {
  189. title: function (tooltipitem) {
  190. if (xAxisLabels.length > 0) {
  191. return xAxisLabels[tooltipitem[0].dataIndex];
  192. } else {
  193. return tooltipitem[0].label;
  194. }
  195. },
  196. },
  197. },
  198. legend: {
  199. display: false,
  200. },
  201. },
  202. },
  203. };
  204. }
  205. initCharts();
  206. // @license-end