feat(charts): enhance tooltip functionality and improve data sorting logic
This commit is contained in:
parent
75af3db11f
commit
438410708f
104
web/default/src/features/dashboard/lib/charts.ts
vendored
104
web/default/src/features/dashboard/lib/charts.ts
vendored
@ -9,6 +9,16 @@ import type {
|
||||
} from '@/features/dashboard/types'
|
||||
|
||||
type TFunction = (key: string) => string
|
||||
type TooltipLineItem = {
|
||||
key: string
|
||||
value: string | number
|
||||
datum?: Record<string, unknown>
|
||||
hasShape?: boolean
|
||||
shapeType?: string
|
||||
shapeFill?: string
|
||||
shapeStroke?: string
|
||||
shapeSize?: number
|
||||
}
|
||||
|
||||
function getVChartDefaultColors(domainLength: number) {
|
||||
const scheme =
|
||||
@ -19,15 +29,6 @@ function getVChartDefaultColors(domainLength: number) {
|
||||
return scheme.scheme
|
||||
}
|
||||
|
||||
function buildModelColorSpec(models: string[]) {
|
||||
const domain = Array.from(new Set(models))
|
||||
return {
|
||||
type: 'ordinal',
|
||||
domain,
|
||||
range: getVChartDefaultColors(domain.length),
|
||||
}
|
||||
}
|
||||
|
||||
function renderQuotaCompat(rawQuota: number, digits = 4): string {
|
||||
const { config, meta } = getCurrencyDisplay()
|
||||
if (meta.kind === 'tokens') return rawQuota.toLocaleString()
|
||||
@ -59,19 +60,24 @@ export function processChartData(
|
||||
const formatQuotaTotal = (value: number) => renderQuotaCompat(value, 2)
|
||||
|
||||
const MAX_TOOLTIP_MODELS = 15
|
||||
const isOtherTooltipKey = (key: string) =>
|
||||
key === 'Other' || key === otherLabel
|
||||
|
||||
const makeTooltipDimensionUpdateContent = (options?: {
|
||||
collapseOverflow?: boolean
|
||||
}) => {
|
||||
const collapseOverflow = options?.collapseOverflow ?? true
|
||||
|
||||
return (array: TooltipLineItem[]) => {
|
||||
const modelItems = array.filter((item) => !isOtherTooltipKey(item.key))
|
||||
const otherItems = array.filter((item) => isOtherTooltipKey(item.key))
|
||||
modelItems.sort(
|
||||
(a, b) => (Number(b.value) || 0) - (Number(a.value) || 0)
|
||||
)
|
||||
array = [...modelItems, ...otherItems]
|
||||
|
||||
const makeTooltipDimensionUpdateContent = () => {
|
||||
return (
|
||||
array: Array<{
|
||||
key: string
|
||||
value: string | number
|
||||
datum?: Record<string, unknown>
|
||||
}>
|
||||
) => {
|
||||
array.sort((a, b) => (Number(b.value) || 0) - (Number(a.value) || 0))
|
||||
let sum = 0
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
if (array[i].key === 'Other' || array[i].key === otherLabel) continue
|
||||
const v = Number(array[i].value) || 0
|
||||
if (
|
||||
array[i].datum &&
|
||||
@ -83,20 +89,27 @@ export function processChartData(
|
||||
array[i].value = formatQuotaValue(v)
|
||||
}
|
||||
|
||||
if (array.length > MAX_TOOLTIP_MODELS) {
|
||||
const visible = array.slice(0, MAX_TOOLTIP_MODELS)
|
||||
let otherSum = 0
|
||||
for (let i = MAX_TOOLTIP_MODELS; i < array.length; i++) {
|
||||
const raw = array[i].datum
|
||||
? Number((array[i].datum as Record<string, unknown>)?.rawQuota) || 0
|
||||
: 0
|
||||
otherSum += raw
|
||||
}
|
||||
visible.push({
|
||||
key: otherLabel,
|
||||
value: formatQuotaValue(otherSum),
|
||||
})
|
||||
array = visible
|
||||
if (collapseOverflow && array.length > MAX_TOOLTIP_MODELS) {
|
||||
const visible = modelItems.slice(0, MAX_TOOLTIP_MODELS)
|
||||
const otherSum = [...modelItems.slice(MAX_TOOLTIP_MODELS), ...otherItems]
|
||||
.reduce((sum, item) => {
|
||||
const raw = item.datum
|
||||
? Number((item.datum as Record<string, unknown>)?.rawQuota) || 0
|
||||
: 0
|
||||
return sum + raw
|
||||
}, 0)
|
||||
array = [
|
||||
...visible,
|
||||
{
|
||||
key: otherLabel,
|
||||
value: formatQuotaValue(otherSum),
|
||||
hasShape: true,
|
||||
shapeType: 'square',
|
||||
shapeFill: otherTooltipColor,
|
||||
shapeStroke: otherTooltipColor,
|
||||
shapeSize: 8,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
array.unshift({
|
||||
@ -226,7 +239,16 @@ export function processChartData(
|
||||
const allModels = Array.from(modelTotalsMap.keys())
|
||||
const sortedTimes = Array.from(timeModelMap.keys()).sort()
|
||||
const sortedModels = [...allModels].sort()
|
||||
const modelColor = buildModelColorSpec([...sortedModels, otherLabel])
|
||||
const modelColorDomain = Array.from(new Set([...sortedModels, otherLabel]))
|
||||
const modelColorRange = getVChartDefaultColors(modelColorDomain.length)
|
||||
const otherColor = modelColorRange[modelColorDomain.indexOf(otherLabel)]
|
||||
const otherTooltipColor =
|
||||
typeof otherColor === 'string' ? otherColor : '#FF8A00'
|
||||
const modelColor = {
|
||||
type: 'ordinal',
|
||||
domain: modelColorDomain,
|
||||
range: modelColorRange,
|
||||
}
|
||||
|
||||
// Pad time points if too few (default 7 points)
|
||||
const MAX_TREND_POINTS = MAX_CHART_TREND_POINTS
|
||||
@ -508,7 +530,9 @@ export function processChartData(
|
||||
Number(datum?.rawQuota) || 0,
|
||||
},
|
||||
],
|
||||
updateContent: makeTooltipDimensionUpdateContent(),
|
||||
updateContent: makeTooltipDimensionUpdateContent({
|
||||
collapseOverflow: false,
|
||||
}),
|
||||
},
|
||||
},
|
||||
area: {
|
||||
@ -564,9 +588,17 @@ export function processChartData(
|
||||
value: string | number
|
||||
}>
|
||||
) => {
|
||||
array.sort(
|
||||
const modelItems = array.filter(
|
||||
(item) => !isOtherTooltipKey(item.key)
|
||||
)
|
||||
const otherItems = array.filter((item) =>
|
||||
isOtherTooltipKey(item.key)
|
||||
)
|
||||
modelItems.sort(
|
||||
(a, b) => (Number(b.value) || 0) - (Number(a.value) || 0)
|
||||
)
|
||||
array = [...modelItems, ...otherItems]
|
||||
|
||||
let sum = 0
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
const v = Number(array[i].value) || 0
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user