coveo-search-ui
Version:
Coveo JavaScript Search Framework
130 lines (108 loc) • 4.15 kB
text/typescript
import * as Globalize from 'globalize';
import { RangeType, IRangeValue, RangeEndScope } from '../../../rest/RangeValue';
import { NumberUtils } from '../../../utils/NumberUtils';
import { isNull } from 'util';
import { DateUtils } from '../../../utils/DateUtils';
import { IDynamicFacetRange, DynamicFacetRangeValueFormat } from '../IDynamicFacetRange';
import { Logger } from '../../../misc/Logger';
import { CurrencyUtils } from '../../../Core';
import { isUndefined } from 'underscore';
export class DynamicFacetRangeValueParser {
constructor(private facet: IDynamicFacetRange) {}
private get valueFormat() {
return this.facet.options.valueFormat;
}
private get valueSeparator() {
return this.facet.options.valueSeparator;
}
private parseDateFromRangeType(value: RangeType) {
const parsedDate = DateUtils.convertToStandardDate(value);
if (!DateUtils.isValid(parsedDate)) {
new Logger(this).warn('Date value is not valid', value);
return null;
}
return parsedDate;
}
private formatDisplayValueFromLimit(value: RangeType) {
switch (this.valueFormat) {
case DynamicFacetRangeValueFormat.number:
const numberOfDecimals = isUndefined(this.facet.options.numberOfDecimals)
? NumberUtils.countDecimals(`${value}`)
: this.facet.options.numberOfDecimals;
return Globalize.format(value, `n${numberOfDecimals}`);
case DynamicFacetRangeValueFormat.currency:
return CurrencyUtils.currencyToString(parseFloat(`${value}`), {
symbol: this.facet.options.currencySymbol,
decimals: NumberUtils.countDecimals(`${value}`) ? 2 : 0
});
case DynamicFacetRangeValueFormat.date:
return DateUtils.dateToString(this.parseDateFromRangeType(value), {
alwaysIncludeTime: false,
includeTimeIfThisWeek: false,
includeTimeIfToday: false,
omitYearIfCurrentOne: false,
useTodayYesterdayAndTomorrow: false,
useWeekdayIfThisWeek: false
});
default:
return `${value}`;
}
}
public formatDisplayValue(range: IRangeValue) {
const formattedStart = this.formatDisplayValueFromLimit(range.start);
const formattedEnd = this.formatDisplayValueFromLimit(range.end);
return `${formattedStart} ${this.valueSeparator} ${formattedEnd}`;
}
private validateRangeLimit(value: RangeType) {
switch (this.valueFormat) {
case DynamicFacetRangeValueFormat.number:
case DynamicFacetRangeValueFormat.currency:
return this.validateNumberValue(value);
case DynamicFacetRangeValueFormat.date:
return this.validateDateValue(value);
default:
return `${value}`;
}
}
private validateNumberValue(value: RangeType) {
const number = parseFloat(`${value}`);
return isNaN(number) ? null : number;
}
private validateDateValue(value: RangeType) {
const parsedValue = DateUtils.dateTimeForQuery(this.parseDateFromRangeType(value));
return parsedValue === 'Invalid date' ? null : parsedValue;
}
public validate(unvalidatedRange: IRangeValue): IRangeValue {
const start = this.validateRangeLimit(unvalidatedRange.start);
const end = this.validateRangeLimit(unvalidatedRange.end);
if (isNull(start) || isNull(end)) {
return null;
}
return {
...unvalidatedRange,
start,
end
};
}
public formatValue(range: IRangeValue) {
const scope = range.endInclusive ? RangeEndScope.Inclusive : RangeEndScope.Exclusive;
return `${range.start}..${range.end}${scope}`;
}
public parse(value: string): IRangeValue {
const valueRegex = new RegExp(`^(.+)\\.\\.(.+)(${RangeEndScope.Inclusive}|${RangeEndScope.Exclusive})$`);
const startAndEnd = valueRegex.exec(value);
if (!startAndEnd) {
return null;
}
const start = this.validateRangeLimit(startAndEnd[1]);
const end = this.validateRangeLimit(startAndEnd[2]);
if (isNull(start) || isNull(end)) {
return null;
}
return {
start,
end,
endInclusive: startAndEnd[3] === RangeEndScope.Inclusive
};
}
}