buster/web/src/lib/columnFormatter.ts

146 lines
4.9 KiB
TypeScript
Raw Normal View History

import {
2025-03-08 07:02:56 +08:00
type ColumnLabelFormat,
DEFAULT_COLUMN_LABEL_FORMAT,
DEFAULT_DATE_FORMAT_DAY_OF_WEEK,
DEFAULT_DATE_FORMAT_MONTH_OF_YEAR,
2025-03-08 07:02:56 +08:00
DEFAULT_DATE_FORMAT_QUARTER,
IColumnLabelFormat
} from '@/api/asset_interfaces/metric';
2025-01-30 01:35:34 +08:00
import { formatDate } from './date';
import { formatNumber, roundNumber } from './numbers';
import { makeHumanReadble } from './text';
const DEFAULT_DATE_FORMAT = 'll';
export const formatLabel = (
2025-01-30 01:35:34 +08:00
textProp: string | number | Date | null | undefined,
2025-04-05 01:03:41 +08:00
props: ColumnLabelFormat = DEFAULT_COLUMN_LABEL_FORMAT,
useKeyFormatter: boolean = false
): string => {
const {
columnType = DEFAULT_COLUMN_LABEL_FORMAT.columnType,
style = DEFAULT_COLUMN_LABEL_FORMAT.style,
minimumFractionDigits = DEFAULT_COLUMN_LABEL_FORMAT.minimumFractionDigits,
maximumFractionDigits = DEFAULT_COLUMN_LABEL_FORMAT.maximumFractionDigits,
multiplier = DEFAULT_COLUMN_LABEL_FORMAT.multiplier,
prefix = DEFAULT_COLUMN_LABEL_FORMAT.prefix,
suffix = DEFAULT_COLUMN_LABEL_FORMAT.suffix,
numberSeparatorStyle = DEFAULT_COLUMN_LABEL_FORMAT.numberSeparatorStyle,
2025-01-30 01:35:34 +08:00
replaceMissingDataWith, //DO NOT USE THE DEFAULT
convertNumberTo,
currency = DEFAULT_COLUMN_LABEL_FORMAT.currency,
displayName = DEFAULT_COLUMN_LABEL_FORMAT.displayName,
//date stuff
dateFormat = DEFAULT_COLUMN_LABEL_FORMAT.dateFormat,
useRelativeTime = DEFAULT_COLUMN_LABEL_FORMAT.useRelativeTime,
isUTC = DEFAULT_COLUMN_LABEL_FORMAT.isUTC,
makeLabelHumanReadable = DEFAULT_COLUMN_LABEL_FORMAT.makeLabelHumanReadable,
compactNumbers = DEFAULT_COLUMN_LABEL_FORMAT.compactNumbers
} = props;
2025-01-30 01:35:34 +08:00
const text =
columnType === 'number' && !useKeyFormatter && replaceMissingDataWith === 0
? Number(textProp)
: textProp;
let formattedText = text;
if (text === null || text === undefined) {
2025-01-30 01:35:34 +08:00
if (columnType === 'number') {
if (replaceMissingDataWith === null) {
formattedText = 'null';
} else {
formattedText = String(
replaceMissingDataWith ?? DEFAULT_COLUMN_LABEL_FORMAT.replaceMissingDataWith
);
}
} else if (replaceMissingDataWith !== undefined) {
formattedText = String(replaceMissingDataWith);
} else formattedText = String('null');
} else if (style === 'date' && !useKeyFormatter) {
formattedText = formatLabelDate(text, {
dateFormat,
convertNumberTo,
isUTC,
useRelativeTime
});
} else if (makeLabelHumanReadable && useKeyFormatter) {
formattedText = displayName || makeHumanReadble(formattedText as string);
} else if (
(columnType === 'number' && style !== 'string') ||
style === 'currency' ||
style === 'percent'
) {
2025-03-08 07:02:56 +08:00
const newNumber = Number(text) * multiplier;
const roundedNumber = roundNumber(newNumber, minimumFractionDigits, maximumFractionDigits);
if (style === 'currency') {
formattedText = formatNumber(roundedNumber, {
currency,
compact: compactNumbers
});
} else {
formattedText = formatNumber(roundedNumber, {
2025-04-01 07:17:14 +08:00
minimumFractionDigits: Math.min(minimumFractionDigits, maximumFractionDigits),
maximumFractionDigits: Math.max(minimumFractionDigits, maximumFractionDigits),
useGrouping: numberSeparatorStyle !== null,
compact: compactNumbers
});
}
}
return prefixSuffixHandler(
formattedText as string,
prefix,
suffix,
replaceMissingDataWith,
style,
useKeyFormatter
);
};
const autoFormats = (convertNumberTo: ColumnLabelFormat['convertNumberTo']) => {
if (!convertNumberTo) return DEFAULT_DATE_FORMAT;
if (convertNumberTo === 'day_of_week') return DEFAULT_DATE_FORMAT_DAY_OF_WEEK;
if (convertNumberTo === 'month_of_year') return DEFAULT_DATE_FORMAT_MONTH_OF_YEAR;
if (convertNumberTo === 'quarter') return DEFAULT_DATE_FORMAT_QUARTER;
return DEFAULT_DATE_FORMAT;
};
const formatLabelDate = (
text: string | number | Date,
props: Pick<ColumnLabelFormat, 'dateFormat' | 'useRelativeTime' | 'isUTC' | 'convertNumberTo'>
): string => {
const {
dateFormat: dateFormatProp = DEFAULT_DATE_FORMAT,
useRelativeTime = false,
isUTC = true,
convertNumberTo
} = props;
const dateFormat = dateFormatProp === 'auto' ? autoFormats(convertNumberTo) : dateFormatProp;
return formatDate({
ignoreValidation: true,
date: text,
format: dateFormat,
isUTC,
convertNumberTo
});
};
const prefixSuffixHandler = (
text: string | number | null,
prefix: string | undefined,
suffix: string | undefined,
replaceMissingDataWith: ColumnLabelFormat['replaceMissingDataWith'],
style: IColumnLabelFormat['style'],
useKeyFormatter: boolean
): string => {
if (useKeyFormatter) return String(text);
if (replaceMissingDataWith === null && !text) return String(text);
if (prefix) text = prefix + text;
if (suffix) text = text + suffix;
if (style === 'percent' && suffix !== '%') text = `${text}%`;
return String(text);
};