Adjust colors to be controlled from outside chart component (#1568)
* Adjust colors to be controlled from outside chart component * Access colors from source of truth * Change access method to omit projects from params * Just omit projects from query
This commit is contained in:
parent
81948a5c29
commit
9add661a5b
@ -88,7 +88,7 @@ function formatTooltipValue(value, props) {
|
||||
}
|
||||
|
||||
function generateListEntry(value, index, _, w, props) {
|
||||
const color = props.colors[index % props.colors.length]
|
||||
const color = w.globals.colors?.[index]
|
||||
|
||||
return `<div class="list-entry">
|
||||
<span class="circle" style="background-color: ${color}"></span>
|
||||
@ -102,7 +102,7 @@ function generateListEntry(value, index, _, w, props) {
|
||||
}
|
||||
|
||||
function generateTooltip({ series, seriesIndex, dataPointIndex, w }, props) {
|
||||
const label = w.globals.lastXAxis.categories[dataPointIndex]
|
||||
const label = w.globals.lastXAxis.categories?.[dataPointIndex]
|
||||
|
||||
const formattedLabel = props.formatLabels(label)
|
||||
|
||||
@ -158,7 +158,7 @@ function generateTooltip({ series, seriesIndex, dataPointIndex, w }, props) {
|
||||
return tooltip
|
||||
}
|
||||
|
||||
const chartOptions = ref({
|
||||
const chartOptions = {
|
||||
chart: {
|
||||
id: props.name,
|
||||
fontFamily:
|
||||
@ -254,7 +254,7 @@ const chartOptions = ref({
|
||||
tooltip: {
|
||||
custom: (d) => generateTooltip(d, props),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const fillOptions = {
|
||||
colors: props.colors,
|
||||
@ -292,7 +292,6 @@ const resetChart = () => {
|
||||
xaxis: {
|
||||
categories: props.labels,
|
||||
},
|
||||
colors: props.colors,
|
||||
})
|
||||
chart.value.resetSeries()
|
||||
legendValues.value.forEach((legend) => {
|
||||
@ -300,8 +299,16 @@ const resetChart = () => {
|
||||
})
|
||||
}
|
||||
|
||||
const updateColors = (colors) => {
|
||||
chart.value.updateOptions({
|
||||
colors,
|
||||
})
|
||||
chart.value.resetSeries()
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
resetChart,
|
||||
updateColors,
|
||||
flipLegend,
|
||||
})
|
||||
</script>
|
||||
|
||||
@ -73,6 +73,9 @@
|
||||
</span>
|
||||
</h2>
|
||||
<div class="chart-controls__buttons">
|
||||
<Button v-tooltip="'Toggle project colors'" icon-only @click="onToggleColors">
|
||||
<EyeIcon />
|
||||
</Button>
|
||||
<Button v-tooltip="'Download this data as CSV'" icon-only @click="onDownloadSetAsCSV">
|
||||
<DownloadIcon />
|
||||
</Button>
|
||||
@ -144,7 +147,9 @@
|
||||
>
|
||||
<div
|
||||
:style="{
|
||||
'--color-brand': intToRgba(project.color, project.id, theme || 'dark'),
|
||||
'--color-brand': isUsingProjectColors
|
||||
? intToRgba(project.color, project.id, theme.value ?? undefined)
|
||||
: getDefaultColor(project.id),
|
||||
}"
|
||||
class="legend__item__color"
|
||||
></div>
|
||||
@ -281,6 +286,7 @@ import {
|
||||
formatNumber,
|
||||
DropdownSelect,
|
||||
formatCategoryHeader,
|
||||
EyeIcon,
|
||||
} from 'omorphia'
|
||||
import dayjs from 'dayjs'
|
||||
import { defineProps, ref, computed } from 'vue'
|
||||
@ -357,6 +363,24 @@ const projectIsOnDisplay = (id: string) => {
|
||||
return selectedDisplayProjects.value.some((p) => p.id === id)
|
||||
}
|
||||
|
||||
const setChartColors = (updatedVal: Ref<boolean>) => {
|
||||
downloadsChart.value?.updateColors(
|
||||
updatedVal.value
|
||||
? analytics.formattedData.value.downloads.chart.colors
|
||||
: analytics.formattedData.value.downloads.chart.defaultColors
|
||||
)
|
||||
viewsChart.value?.updateColors(
|
||||
updatedVal.value
|
||||
? analytics.formattedData.value.views.chart.colors
|
||||
: analytics.formattedData.value.views.chart.defaultColors
|
||||
)
|
||||
revenueChart.value?.updateColors(
|
||||
updatedVal.value
|
||||
? analytics.formattedData.value.revenue.chart.colors
|
||||
: analytics.formattedData.value.revenue.chart.defaultColors
|
||||
)
|
||||
}
|
||||
|
||||
const resetCharts = () => {
|
||||
downloadsChart.value?.resetChart()
|
||||
viewsChart.value?.resetChart()
|
||||
@ -365,8 +389,15 @@ const resetCharts = () => {
|
||||
tinyDownloadChart.value?.resetChart()
|
||||
tinyViewChart.value?.resetChart()
|
||||
tinyRevenueChart.value?.resetChart()
|
||||
|
||||
setChartColors(isUsingProjectColors)
|
||||
}
|
||||
|
||||
const isUsingProjectColors = ref(true)
|
||||
watch(() => isUsingProjectColors, setChartColors, {
|
||||
deep: true,
|
||||
})
|
||||
|
||||
const analytics = useFetchAllAnalytics(resetCharts, selectedDisplayProjects)
|
||||
|
||||
const { startDate, endDate, timeRange, timeResolution } = analytics
|
||||
@ -425,6 +456,9 @@ const downloadSelectedSetAsCSV = () => {
|
||||
}
|
||||
|
||||
const onDownloadSetAsCSV = useClientTry(async () => await downloadSelectedSetAsCSV())
|
||||
const onToggleColors = () => {
|
||||
isUsingProjectColors.value = !isUsingProjectColors.value
|
||||
}
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
|
||||
@ -38,7 +38,7 @@ const hashProjectId = (projectId) => {
|
||||
return projectId.split('').reduce((acc, char) => acc + char.charCodeAt(0), 0) % 30
|
||||
}
|
||||
|
||||
const defaultColors = ['#ff496e', '#ffa347', '#1bd96a', '#4f9cff', '#c78aff']
|
||||
export const defaultColors = ['#ff496e', '#ffa347', '#1bd96a', '#4f9cff', '#c78aff']
|
||||
|
||||
/**
|
||||
* @param {string | number} value
|
||||
@ -51,7 +51,7 @@ export const getDefaultColor = (value) => {
|
||||
return defaultColors[value % defaultColors.length]
|
||||
}
|
||||
|
||||
export const intToRgba = (color, projectId = 'Unknown', theme) => {
|
||||
export const intToRgba = (color, projectId = 'Unknown', theme = 'dark') => {
|
||||
const hash = hashProjectId(projectId)
|
||||
|
||||
if (!color || color === 0) {
|
||||
@ -109,6 +109,7 @@ const emptyAnalytics = {
|
||||
},
|
||||
],
|
||||
colors: [],
|
||||
defaultColors: [],
|
||||
},
|
||||
}
|
||||
|
||||
@ -204,6 +205,10 @@ export const processAnalytics = (category, projects, labelFn, sortFn, mapFn, cha
|
||||
|
||||
return intToRgba(project.color, project.id, theme.value)
|
||||
}),
|
||||
defaultColors: projectData.map((_, i) => {
|
||||
const project = chartData[i]
|
||||
return getDefaultColor(project.id)
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -300,11 +305,10 @@ export const useFetchAllAnalytics = (onDataRefresh, projects) => {
|
||||
|
||||
const fetchData = async (query) => {
|
||||
const normalQuery = new URLSearchParams(query)
|
||||
|
||||
const revQuery = new URLSearchParams(query)
|
||||
|
||||
const revenueQuery = new URLSearchParams(query)
|
||||
revenueQuery.delete('projects')
|
||||
const qs = normalQuery.toString()
|
||||
const revQs = revQuery.toString()
|
||||
const revenueQs = revenueQuery.toString()
|
||||
|
||||
try {
|
||||
loading.value = true
|
||||
@ -313,14 +317,29 @@ export const useFetchAllAnalytics = (onDataRefresh, projects) => {
|
||||
const responses = await Promise.all([
|
||||
useFetchAnalytics(`analytics/downloads?${qs}`),
|
||||
useFetchAnalytics(`analytics/views?${qs}`),
|
||||
useFetchAnalytics(`analytics/revenue?${revQs}`),
|
||||
useFetchAnalytics(`analytics/revenue?${revenueQs}`),
|
||||
useFetchAnalytics(`analytics/countries/downloads?${qs}`),
|
||||
useFetchAnalytics(`analytics/countries/views?${qs}`),
|
||||
])
|
||||
|
||||
downloadData.value = responses[0] || {}
|
||||
viewData.value = responses[1] || {}
|
||||
revenueData.value = responses[2] || {}
|
||||
// collect project ids from projects.value into a set
|
||||
const projectIds = new Set()
|
||||
projects.value.forEach((p) => projectIds.add(p.id))
|
||||
|
||||
const filterProjectIds = (data) => {
|
||||
const filtered = {}
|
||||
Object.entries(data).forEach(([id, values]) => {
|
||||
if (projectIds.has(id)) {
|
||||
filtered[id] = values
|
||||
}
|
||||
})
|
||||
return filtered
|
||||
}
|
||||
|
||||
downloadData.value = filterProjectIds(responses[0] || {})
|
||||
viewData.value = filterProjectIds(responses[1] || {})
|
||||
revenueData.value = filterProjectIds(responses[2] || {})
|
||||
|
||||
downloadsByCountry.value = responses[3] || {}
|
||||
viewsByCountry.value = responses[4] || {}
|
||||
} catch (e) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user