You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

374 line
9.4 KiB

  1. import { shuffle, getRandomBias } from '../../../src/js/utils/helpers';
  2. import { HEATMAP_COLORS_YELLOW, HEATMAP_COLORS_BLUE } from '../../../src/js/utils/constants';
  3. import { SEC_IN_DAY, clone, timestampToMidnight, timestampSec, addDays } from '../../../src/js/utils/date-utils';
  4. import { fireballOver25, fireball_2_5, fireball_5_25, lineCompositeData,
  5. barCompositeData, typeData, trendsData, moonData } from './data';
  6. import demoConfig from './demoConfig';
  7. // import { lineComposite, barComposite } from './demoConfig';
  8. // ================================================================================
  9. let Chart = frappe.Chart; // eslint-disable-line no-undef
  10. let lc = demoConfig.lineComposite;
  11. let lineCompositeChart = new Chart (lc.elementID, lc.options);
  12. let bc = demoConfig.barComposite;
  13. let barCompositeChart = new Chart (bc.elementID, bc.options);
  14. lineCompositeChart.parent.addEventListener('data-select', (e) => {
  15. let i = e.index;
  16. barCompositeChart.updateDatasets([
  17. fireballOver25[i], fireball_5_25[i], fireball_2_5[i]
  18. ]);
  19. });
  20. // ================================================================================
  21. let customColors = ['purple', 'magenta', 'light-blue'];
  22. let typeChartArgs = {
  23. title: "My Awesome Chart",
  24. data: typeData,
  25. type: 'axis-mixed',
  26. height: 300,
  27. colors: customColors,
  28. // maxLegendPoints: 6,
  29. maxSlices: 10,
  30. tooltipOptions: {
  31. formatTooltipX: d => (d + '').toUpperCase(),
  32. formatTooltipY: d => d + ' pts',
  33. }
  34. };
  35. let aggrChart = new Chart("#chart-aggr", typeChartArgs);
  36. Array.prototype.slice.call(
  37. document.querySelectorAll('.aggr-type-buttons button')
  38. ).map(el => {
  39. el.addEventListener('click', (e) => {
  40. let btn = e.target;
  41. let type = btn.getAttribute('data-type');
  42. typeChartArgs.type = type;
  43. if(type !== 'axis-mixed') {
  44. typeChartArgs.colors = undefined;
  45. } else {
  46. typeChartArgs.colors = customColors;
  47. }
  48. if(type !== 'percentage') {
  49. typeChartArgs.height = 300;
  50. } else {
  51. typeChartArgs.height = undefined;
  52. }
  53. let newChart = new Chart("#chart-aggr", typeChartArgs);
  54. if(newChart){
  55. aggrChart = newChart;
  56. }
  57. Array.prototype.slice.call(
  58. btn.parentNode.querySelectorAll('button')).map(el => {
  59. el.classList.remove('active');
  60. });
  61. btn.classList.add('active');
  62. });
  63. });
  64. document.querySelector('.export-aggr').addEventListener('click', () => {
  65. aggrChart.export();
  66. });
  67. // Update values chart
  68. // ================================================================================
  69. let updateDataAllLabels = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", "Mon", "Tue",
  70. "Wed", "Thu", "Fri", "Sat", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri",
  71. "Sat", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", "Mon"];
  72. let getRandom = () => Math.floor(getRandomBias(-40, 60, 0.8, 1));
  73. let updateDataAllValues = Array.from({length: 30}, getRandom);
  74. // We're gonna be shuffling this
  75. let updateDataAllIndices = updateDataAllLabels.map((d,i) => i);
  76. let getUpdateData = (source_array, length=10) => {
  77. let indices = updateDataAllIndices.slice(0, length);
  78. return indices.map((index) => source_array[index]);
  79. };
  80. let updateData = {
  81. labels: getUpdateData(updateDataAllLabels),
  82. datasets: [{
  83. "values": getUpdateData(updateDataAllValues)
  84. }],
  85. yMarkers: [
  86. {
  87. label: "Altitude",
  88. value: 25,
  89. type: 'dashed'
  90. }
  91. ],
  92. yRegions: [
  93. {
  94. label: "Range",
  95. start: 10,
  96. end: 45
  97. },
  98. ],
  99. };
  100. let updateChart = new Chart("#chart-update", {
  101. data: updateData,
  102. type: 'line',
  103. height: 300,
  104. colors: ['#ff6c03'],
  105. lineOptions: {
  106. // hideLine: 1,
  107. regionFill: 1
  108. },
  109. });
  110. let chartUpdateButtons = document.querySelector('.chart-update-buttons');
  111. chartUpdateButtons.querySelector('[data-update="random"]').addEventListener("click", () => {
  112. shuffle(updateDataAllIndices);
  113. let value = getRandom();
  114. let start = getRandom();
  115. let end = getRandom();
  116. let data = {
  117. labels: updateDataAllLabels.slice(0, 10),
  118. datasets: [{values: getUpdateData(updateDataAllValues)}],
  119. yMarkers: [
  120. {
  121. label: "Altitude",
  122. value: value,
  123. type: 'dashed'
  124. }
  125. ],
  126. yRegions: [
  127. {
  128. label: "Range",
  129. start: start,
  130. end: end
  131. },
  132. ],
  133. };
  134. updateChart.update(data);
  135. });
  136. chartUpdateButtons.querySelector('[data-update="add"]').addEventListener("click", () => {
  137. let index = updateChart.state.datasetLength; // last index to add
  138. if(index >= updateDataAllIndices.length) return;
  139. updateChart.addDataPoint(
  140. updateDataAllLabels[index], [updateDataAllValues[index]]
  141. );
  142. });
  143. chartUpdateButtons.querySelector('[data-update="remove"]').addEventListener("click", () => {
  144. updateChart.removeDataPoint();
  145. });
  146. document.querySelector('.export-update').addEventListener('click', () => {
  147. updateChart.export();
  148. });
  149. // Trends Chart
  150. // ================================================================================
  151. let plotChartArgs = {
  152. title: "Mean Total Sunspot Count - Yearly",
  153. data: trendsData,
  154. type: 'line',
  155. height: 300,
  156. colors: ['#238e38'],
  157. lineOptions: {
  158. hideDots: 1,
  159. heatline: 1,
  160. },
  161. axisOptions: {
  162. xAxisMode: 'tick',
  163. yAxisMode: 'span',
  164. xIsSeries: 1
  165. }
  166. };
  167. let trendsChart = new Chart("#chart-trends", plotChartArgs);
  168. Array.prototype.slice.call(
  169. document.querySelectorAll('.chart-plot-buttons button')
  170. ).map(el => {
  171. el.addEventListener('click', (e) => {
  172. let btn = e.target;
  173. let type = btn.getAttribute('data-type');
  174. let config = {};
  175. config[type] = 1;
  176. if(['regionFill', 'heatline'].includes(type)) {
  177. config.hideDots = 1;
  178. }
  179. // plotChartArgs.init = false;
  180. plotChartArgs.lineOptions = config;
  181. new Chart("#chart-trends", plotChartArgs);
  182. Array.prototype.slice.call(
  183. btn.parentNode.querySelectorAll('button')).map(el => {
  184. el.classList.remove('active');
  185. });
  186. btn.classList.add('active');
  187. });
  188. });
  189. document.querySelector('.export-trends').addEventListener('click', () => {
  190. trendsChart.export();
  191. });
  192. // Event chart
  193. // ================================================================================
  194. let eventsData = {
  195. labels: ["Ganymede", "Callisto", "Io", "Europa"],
  196. datasets: [
  197. {
  198. "values": moonData.distances,
  199. "formatted": moonData.distances.map(d => d*1000 + " km")
  200. }
  201. ]
  202. };
  203. let eventsChart = new Chart("#chart-events", {
  204. title: "Jupiter's Moons: Semi-major Axis (1000 km)",
  205. data: eventsData,
  206. type: 'bar',
  207. height: 330,
  208. colors: ['grey'],
  209. isNavigable: 1,
  210. });
  211. let dataDiv = document.querySelector('.chart-events-data');
  212. eventsChart.parent.addEventListener('data-select', (e) => {
  213. let name = moonData.names[e.index];
  214. dataDiv.querySelector('.moon-name').innerHTML = name;
  215. dataDiv.querySelector('.semi-major-axis').innerHTML = moonData.distances[e.index] * 1000;
  216. dataDiv.querySelector('.mass').innerHTML = moonData.masses[e.index];
  217. dataDiv.querySelector('.diameter').innerHTML = moonData.diameters[e.index];
  218. dataDiv.querySelector('img').src = "./assets/img/" + name.toLowerCase() + ".jpg";
  219. });
  220. // Heatmap
  221. // ================================================================================
  222. let today = new Date();
  223. let start = clone(today);
  224. addDays(start, 4);
  225. let end = clone(start);
  226. start.setFullYear( start.getFullYear() - 2 );
  227. end.setFullYear( end.getFullYear() - 1 );
  228. let dataPoints = {};
  229. let startTs = timestampSec(start);
  230. let endTs = timestampSec(end);
  231. startTs = timestampToMidnight(startTs);
  232. endTs = timestampToMidnight(endTs, true);
  233. while (startTs < endTs) {
  234. dataPoints[parseInt(startTs)] = Math.floor(getRandomBias(0, 5, 0.2, 1));
  235. startTs += SEC_IN_DAY;
  236. }
  237. const heatmapData = {
  238. dataPoints: dataPoints,
  239. start: start,
  240. end: end
  241. };
  242. let heatmapArgs = {
  243. title: "Monthly Distribution",
  244. data: heatmapData,
  245. type: 'heatmap',
  246. discreteDomains: 1,
  247. countLabel: 'Level',
  248. colors: HEATMAP_COLORS_BLUE,
  249. legendScale: [0, 1, 2, 4, 5]
  250. };
  251. let heatmapChart = new Chart("#chart-heatmap", heatmapArgs);
  252. Array.prototype.slice.call(
  253. document.querySelectorAll('.heatmap-mode-buttons button')
  254. ).map(el => {
  255. el.addEventListener('click', (e) => {
  256. let btn = e.target;
  257. let mode = btn.getAttribute('data-mode');
  258. let discreteDomains = 0;
  259. if(mode === 'discrete') {
  260. discreteDomains = 1;
  261. }
  262. let colors = [];
  263. let colors_mode = document
  264. .querySelector('.heatmap-color-buttons .active')
  265. .getAttribute('data-color');
  266. if(colors_mode === 'halloween') {
  267. colors = HEATMAP_COLORS_YELLOW;
  268. } else if (colors_mode === 'blue') {
  269. colors = HEATMAP_COLORS_BLUE;
  270. }
  271. heatmapArgs.discreteDomains = discreteDomains;
  272. heatmapArgs.colors = colors;
  273. new Chart("#chart-heatmap", heatmapArgs);
  274. Array.prototype.slice.call(
  275. btn.parentNode.querySelectorAll('button')).map(el => {
  276. el.classList.remove('active');
  277. });
  278. btn.classList.add('active');
  279. });
  280. });
  281. Array.prototype.slice.call(
  282. document.querySelectorAll('.heatmap-color-buttons button')
  283. ).map(el => {
  284. el.addEventListener('click', (e) => {
  285. let btn = e.target;
  286. let colors_mode = btn.getAttribute('data-color');
  287. let colors = [];
  288. if(colors_mode === 'halloween') {
  289. colors = HEATMAP_COLORS_YELLOW;
  290. } else if (colors_mode === 'blue') {
  291. colors = HEATMAP_COLORS_BLUE;
  292. }
  293. let discreteDomains = 1;
  294. let view_mode = document
  295. .querySelector('.heatmap-mode-buttons .active')
  296. .getAttribute('data-mode');
  297. if(view_mode === 'continuous') {
  298. discreteDomains = 0;
  299. }
  300. heatmapArgs.discreteDomains = discreteDomains;
  301. heatmapArgs.colors = colors;
  302. new Chart("#chart-heatmap", heatmapArgs);
  303. Array.prototype.slice.call(
  304. btn.parentNode.querySelectorAll('button')).map(el => {
  305. el.classList.remove('active');
  306. });
  307. btn.classList.add('active');
  308. });
  309. });
  310. document.querySelector('.export-heatmap').addEventListener('click', () => {
  311. heatmapChart.export();
  312. });