2025-01-07 02:29:29 +08:00
|
|
|
import {
|
2025-03-08 07:02:56 +08:00
|
|
|
type ColumnLabelFormat,
|
2025-01-07 02:29:29 +08:00
|
|
|
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';
|
2025-01-07 02:29:29 +08:00
|
|
|
|
|
|
|
const DEFAULT_DATE_FORMAT = 'll';
|
|
|
|
|
|
|
|
export const formatLabel = (
|
2025-05-02 03:47:34 +08:00
|
|
|
textProp: string | number | Date | null | undefined | boolean,
|
2025-04-05 01:03:41 +08:00
|
|
|
props: ColumnLabelFormat = DEFAULT_COLUMN_LABEL_FORMAT,
|
2025-01-07 02:29:29 +08:00
|
|
|
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
|
2025-01-07 02:29:29 +08:00
|
|
|
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-04-19 06:48:18 +08:00
|
|
|
const textIsNotNullOrUndefined = textProp !== null && textProp !== undefined;
|
|
|
|
|
2025-01-30 01:35:34 +08:00
|
|
|
const text =
|
2025-04-19 06:48:18 +08:00
|
|
|
textIsNotNullOrUndefined &&
|
|
|
|
columnType === 'number' &&
|
|
|
|
!useKeyFormatter &&
|
|
|
|
replaceMissingDataWith === 0
|
2025-01-30 01:35:34 +08:00
|
|
|
? Number(textProp)
|
|
|
|
: textProp;
|
2025-01-07 02:29:29 +08:00
|
|
|
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');
|
2025-01-07 02:29:29 +08:00
|
|
|
} else if (style === 'date' && !useKeyFormatter) {
|
2025-05-02 03:47:34 +08:00
|
|
|
formattedText = formatLabelDate(text as string | number | Date, {
|
2025-01-07 02:29:29 +08:00
|
|
|
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);
|
2025-04-12 06:01:16 +08:00
|
|
|
|
2025-01-07 02:29:29 +08:00
|
|
|
if (style === 'currency') {
|
|
|
|
formattedText = formatNumber(roundedNumber, {
|
|
|
|
currency,
|
|
|
|
compact: compactNumbers
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
formattedText = formatNumber(roundedNumber, {
|
2025-04-12 06:01:16 +08:00
|
|
|
minDecimals: minimumFractionDigits,
|
2025-04-01 07:17:14 +08:00
|
|
|
minimumFractionDigits: Math.min(minimumFractionDigits, maximumFractionDigits),
|
|
|
|
maximumFractionDigits: Math.max(minimumFractionDigits, maximumFractionDigits),
|
2025-01-07 02:29:29 +08:00
|
|
|
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);
|
|
|
|
};
|