controllers/dashboard/histogram_controller.js

  1. import { Controller } from "@hotwired/stimulus"
  2. import { debounce } from "debounce"
  3. import { subscription } from "~/javascripts/store/mixins/subscription"
  4. import Histogram from "~/javascripts/dashboard/Histogram"
  5. /**
  6. * @class Dashboard.HistogramController
  7. * @classdesc Stimulus controller that handles the histogram data visualisation.
  8. * @extends Controller
  9. **/
  10. export default class extends Controller {
  11. static targets = [ "loading", "visualisation" ]
  12. static values = {
  13. storeId: String,
  14. xAxis: String,
  15. yAxis: String
  16. }
  17. /**
  18. * Subscribe to the store. Debounces the method for handling window resizes
  19. *
  20. * @instance
  21. * @memberof Dashboard.HistogramController
  22. **/
  23. connect() {
  24. subscription(this)
  25. this.subscribe()
  26. this.editStore("frameLoaded", true)
  27. this.reconnect()
  28. this.resize = debounce(this.resize, 250).bind(this)
  29. }
  30. /**
  31. * Handles a repeated Turbo visit to the dashboard page.
  32. *
  33. * @instance
  34. * @memberof Dashboard.HistogramController
  35. **/
  36. reconnect() {
  37. if (this.store("selectedContextData")) {
  38. this.storeUpdated("selectedContextData", this.storeIdValue)
  39. }
  40. }
  41. /**
  42. * Checks if the visualisation has been created yet
  43. *
  44. * @instance
  45. * @memberof Dashboard.HistogramController
  46. **/
  47. isDataVizEmpty() {
  48. return document.querySelector("[data-histogram='wrapper']").getElementsByTagName("svg").length === 0
  49. }
  50. /**
  51. * Creates a new instance of the Histogram class if not created, otherwise returns the instance of
  52. * the class
  53. *
  54. * @instance
  55. * @memberof Dashboard.HistogramController
  56. **/
  57. histogram() {
  58. if (this._histogram === undefined) {
  59. this._windowWidth = window.innerWidth
  60. this._histogram = new Histogram(
  61. this.store("selectedContextData"),
  62. this.store("contextSelected"),
  63. "value",
  64. "[data-histogram='wrapper']"
  65. )
  66. }
  67. return this._histogram
  68. }
  69. /**
  70. * Handles a resize of the screen by width but ignores height changes. Deletes the current
  71. * visualisation and the instance of the Histogram class so it will be created from scratch again.
  72. *
  73. * @instance
  74. * @memberof Dashboard.HistogramController
  75. **/
  76. resize() {
  77. if (window.innerWidth === this._windowWidth) return
  78. this._windowWidth = window.innerWidth
  79. this._histogram = undefined
  80. const wrapper = document.querySelector("[data-histogram='wrapper']")
  81. wrapper.removeChild(wrapper.lastChild)
  82. this.histogram().createDataVis()
  83. }
  84. /**
  85. * When the context is selected the data visualisation will either be creted or updated
  86. *
  87. * @instance
  88. * @memberof Dashboard.HistogramController
  89. **/
  90. storeUpdated(prop, storeId) {
  91. if (this.store("fetchingDataVizData")) {
  92. this.loadingTarget.style.display = "block"
  93. this.visualisationTarget.style.display = "none"
  94. } else {
  95. if (prop !== "selectedContextData" && storeId === this.storeIdValue) return
  96. this.loadingTarget.style.display = "none"
  97. this.visualisationTarget.style.display = "block"
  98. if(this.isDataVizEmpty()) {
  99. this.histogram().createDataVis()
  100. } else {
  101. this.histogram().updateDataVis(this.store("selectedContextData"), this.store("contextSelected"))
  102. }
  103. }
  104. }
  105. /**
  106. * Unsubscribe from the store
  107. *
  108. * @instance
  109. * @memberof Dashboard.HistogramController
  110. **/
  111. disconnect() {
  112. this.unsubscribe()
  113. }
  114. }