import { Controller } from "@hotwired/stimulus"
import { subscription } from "~/javascripts/store/mixins/subscription"
import { metricsInPercentile } from "~/javascripts/dashboard/utils"
/**
* @class Dashboard.SelectContextController
* @classdesc Stimulus controller that handles the buttons for the various contexts.
* @extends Controller
**/
export default class extends Controller {
static targets = [ "button" ]
static values = {
contextKey: String,
defaultContext: String,
storeId: String
}
/**
* Subscribe to the store.
*
* @instance
* @memberof Dashboard.SelectContextController
**/
connect() {
subscription(this)
this.subscribe()
this.reconnect()
}
/**
* Handles a repeated Turbo visit to the dashboard page.
*
* @instance
* @memberof Dashboard.SelectContextController
**/
reconnect() {
if (this.store("selectedDataVizData")) {
this.storeUpdated("selectedDataVizData", this.storeIdValue)
}
}
/**
* Sets the selected class on the clicked button and updates the store with the context clicked and
* the data for the context
*
* @instance
* @memberof Dashboard.SelectContextController
**/
contextClicked(event) {
this.buttonTargets.forEach(buttonTarget => buttonTarget.classList.remove("selected"))
event.target.classList.add("selected")
const buttonText = event.target.innerHTML
this.editStore("contextSelected", this.contextSelected(buttonText))
this.editStore("selectedContextData", this.selectContextData(this.contextSelected(buttonText)))
}
/**
* Get the data for the selected context. Also set the value to be used on the x axis.
* If there is no data for the context then return a dummy object in an array.
*
* @instance
* @memberof Dashboard.SelectContextController
**/
selectContextData(context) {
let selectedDataVizData = !this.store("selectedDataVizData") ? [] : this.store("selectedDataVizData")
let contextData = selectedDataVizData.filter(data => data[this.contextKeyValue] === context)
if(this.storeIdValue === "builds_") {
if(contextData.length === 0) return [{ deploy_time: 0, build_number: 0 }]
return contextData.map((data, index) => Object.assign(data, { build_number: index + 1 }))
} else if (this.storeIdValue === "vitals_") {
if (this.store("frameSelected") === undefined) this.editStore("frameSelected", "daily")
contextData = metricsInPercentile(contextData, "data_float", 0.75)
if (this.store("frameSelected") === "daily") {
if(contextData.length === 0) return [{ value: 0, day: 0 }]
const groupSumCount = contextData.reduce((acc , data) => {
if (!acc.get(data.date)) {
acc.set(
data.date, { date: data.date, metric: data.metric, data_float: data.data_float, count: 1 }
)
return acc
}
const dateContent = acc.get(data.date)
dateContent.data_float += data.data_float
dateContent.count += 1
return acc
}, new Map())
for (let result of groupSumCount.values()) {
result.value = Math.round(((result.data_float/result.count) + Number.EPSILON) * 10000) / 10000
}
return [...groupSumCount.values()].map((data) => {
return Object.assign(data, { day: new Date(data.date).getDate() })
})
} else if (this.store("frameSelected") === "frequency") {
if(contextData.length === 0) return []
return contextData.map(data => {
return { value: data.data_float }
})
}
}
}
/**
* Use the button text to set the context.
*
* @instance
* @memberof Dashboard.SelectContextController
**/
contextSelected(buttonText) {
return buttonText.toLowerCase().replace(" ", "-")
}
/**
* Triggered by the store whenever any store data changes. In this case it checks for
* selectedDataVizData to be set and then sets production as the initially selected context
* button.
*
* @instance
* @memberof Dashboard.SelectContextController
**/
storeUpdated(prop, storeId) {
if ((prop === "frameLoaded" || prop === "selectedDataVizData") && storeId === this.storeIdValue) {
this.editStore("contextSelected", this.contextSelected(this.defaultContextValue))
this.editStore("selectedContextData", this.selectContextData(this.defaultContextValue))
this.buttonTargets.forEach(buttonTarget => buttonTarget.classList.remove("selected"))
this.buttonTargets[0].classList.add("selected")
}
}
/**
* Unsubscribe from the store
*
* @instance
* @memberof Dashboard.SelectContextController
**/
disconnect() {
this.unsubscribe()
}
}