From 6ff38efb4e0e1a23a61ca94ab0296234fa7fd6d0 Mon Sep 17 00:00:00 2001 From: Rocky Date: Mon, 19 Feb 2024 10:42:40 -0500 Subject: [PATCH] feat(utilities): add new timeframe methods [MA-1960] (#1165) - Bump version to 1.0.0; no breaking changes - Add cacheKey method for improved usage with SWRV - Add v4Query method for better explore v4 support - Fix types --- .../analytics-utilities/package.json | 2 +- .../src/timeframes.spec.ts | 54 ++++++++++++++++++- .../analytics-utilities/src/timeframes.ts | 28 +++++++++- .../src/types/explore-v4.ts | 2 +- .../src/types/timeframe-options.ts | 3 +- 5 files changed, 84 insertions(+), 5 deletions(-) diff --git a/packages/analytics/analytics-utilities/package.json b/packages/analytics/analytics-utilities/package.json index c203fce6c7..9d97f5ddd5 100644 --- a/packages/analytics/analytics-utilities/package.json +++ b/packages/analytics/analytics-utilities/package.json @@ -1,6 +1,6 @@ { "name": "@kong-ui-public/analytics-utilities", - "version": "0.15.0", + "version": "1.0.0", "type": "module", "main": "./dist/vitals-utilities.umd.js", "module": "./dist/vitals-utilities.es.js", diff --git a/packages/analytics/analytics-utilities/src/timeframes.spec.ts b/packages/analytics/analytics-utilities/src/timeframes.spec.ts index 00b2a19085..00793a476e 100644 --- a/packages/analytics/analytics-utilities/src/timeframes.spec.ts +++ b/packages/analytics/analytics-utilities/src/timeframes.spec.ts @@ -1,6 +1,6 @@ import { expect } from 'vitest' import { GranularityKeys, TimeframeKeys } from './types' -import { TimePeriods } from './timeframes' +import { Timeframe, TimePeriods } from './timeframes' const freeTierMax = TimePeriods.get(TimeframeKeys.ONE_DAY)?.timeframeLength() || 86400 const sevenDays = TimePeriods.get(TimeframeKeys.SEVEN_DAY)?.timeframeLength() || 86400 * 7 @@ -62,3 +62,55 @@ describe('allowedGranularities', () => { .toEqual(new Set([GranularityKeys.DAILY, GranularityKeys.WEEKLY])) }) }) + +describe('cacheKey', () => { + it('handles relative keys', () => { + expect(TimePeriods.get(TimeframeKeys.ONE_DAY)?.cacheKey()).toBe('24h') + expect(TimePeriods.get(TimeframeKeys.CURRENT_MONTH)?.cacheKey()).toBe('current_month') + }) + + it('handles absolute keys', () => { + expect((new Timeframe({ + key: 'custom', + timeframeText: 'custom', + display: 'custom', + startCustom: new Date('2024-01-01T00:00:00Z'), + endCustom: new Date('2024-01-02T00:00:00Z'), + timeframeLength: () => 0, + defaultResponseGranularity: GranularityKeys.DAILY, + dataGranularity: GranularityKeys.DAILY, + isRelative: false, + allowedTiers: ['free', 'plus', 'enterprise'], + })).cacheKey()).toBe('2024-01-01T00:00:00.000Z-2024-01-02T00:00:00.000Z') + }) +}) + +describe('v4Query', () => { + it('handles relative keys', () => { + expect(TimePeriods.get(TimeframeKeys.ONE_DAY)!.v4Query()).toEqual({ + type: 'relative', + time_range: '24h', + }) + }) + + it('handles custom timeframes', () => { + const customTime = new Timeframe({ + key: 'custom', + timeframeText: 'custom', + display: 'custom', + startCustom: new Date('2024-01-01T00:00:00Z'), + endCustom: new Date('2024-02-01T00:00:00Z'), + timeframeLength: () => 0, + defaultResponseGranularity: GranularityKeys.DAILY, + dataGranularity: GranularityKeys.DAILY, + isRelative: false, + allowedTiers: ['free', 'plus', 'enterprise'], + }) + + expect(customTime.v4Query()).toEqual({ + type: 'absolute', + start: new Date('2024-01-01T00:00:00Z'), + end: new Date('2024-02-01T00:00:00Z'), + }) + }) +}) diff --git a/packages/analytics/analytics-utilities/src/timeframes.ts b/packages/analytics/analytics-utilities/src/timeframes.ts index 5e8b15aad5..5a885995e0 100644 --- a/packages/analytics/analytics-utilities/src/timeframes.ts +++ b/packages/analytics/analytics-utilities/src/timeframes.ts @@ -18,6 +18,7 @@ import type { DatePickerSelection, TimeframeOptions, TimePeriod, + RelativeTimeRangeValuesV4, TimeRangeV4, } from './types' import { getTimezoneOffset, utcToZonedTime, zonedTimeToUtc } from 'date-fns-tz' import type { ITimeframe } from './types/timeframe' @@ -30,7 +31,7 @@ const adjustForTz = (d: Date, tz: string) => { export class Timeframe implements ITimeframe { readonly timeframeText: string - readonly key: string + readonly key: RelativeTimeRangeValuesV4 | 'custom' readonly display: string @@ -121,6 +122,31 @@ export class Timeframe implements ITimeframe { return allowedValues } + cacheKey(): string { + if (this.key !== 'custom') { + // Right now, `key === custom` is our flag for whether we're dealing with an absolute or relative timeframe. + return this.key + } + + return `${this.rawStart().toISOString()}-${this.rawEnd().toISOString()}` + } + + v4Query(): TimeRangeV4 { + if (this.key === 'custom') { + // Right now, `key === custom` is our flag for whether we're dealing with an absolute or relative timeframe. + return { + type: 'absolute', + start: this.rawStart(), + end: this.rawEnd(), + } + } + + return { + type: 'relative', + time_range: this.key, + } + } + protected tzAdjustedDate(tz?: string): Date { if (!tz) { return new Date() diff --git a/packages/analytics/analytics-utilities/src/types/explore-v4.ts b/packages/analytics/analytics-utilities/src/types/explore-v4.ts index 01ee87cefa..e3b6cf6cb8 100644 --- a/packages/analytics/analytics-utilities/src/types/explore-v4.ts +++ b/packages/analytics/analytics-utilities/src/types/explore-v4.ts @@ -105,7 +105,7 @@ export interface ExploreQuery { dimensions?: QueryableExploreDimensions[] filters?: ExploreFilter[] granularity?: GranularityValues - time_range: TimeRangeV4 + time_range?: TimeRangeV4 limit?: number descending?: boolean meta?: { diff --git a/packages/analytics/analytics-utilities/src/types/timeframe-options.ts b/packages/analytics/analytics-utilities/src/types/timeframe-options.ts index 9d2c5243f7..d8c17886d9 100644 --- a/packages/analytics/analytics-utilities/src/types/timeframe-options.ts +++ b/packages/analytics/analytics-utilities/src/types/timeframe-options.ts @@ -1,7 +1,8 @@ import type { GranularityKeys } from './granularity-keys' +import type { RelativeTimeRangeValuesV4 } from './explore-v4' export interface TimeframeOptions { - key: string + key: RelativeTimeRangeValuesV4 | 'custom' timeframeText: string display: string defaultResponseGranularity: GranularityKeys