@@ -17,6 +17,13 @@ import { Knex } from 'knex';
1717import { Filters , EventDatabase , UserConfig } from '../event-database' ;
1818import { Event } from '../../models/Event' ;
1919import { LoggerService } from '@backstage/backend-plugin-api' ;
20+ import {
21+ DailyUser ,
22+ Grouping ,
23+ ResponseData ,
24+ ResponseWithGrouping ,
25+ } from '../../types/event' ;
26+ import { convertToLocalTimezone } from '../../utils/date' ;
2027
2128export abstract class BaseDatabaseAdapter implements EventDatabase {
2229 protected db : Knex ;
@@ -129,14 +136,7 @@ export abstract class BaseDatabaseAdapter implements EventDatabase {
129136 . groupBy ( 'ge.date' )
130137 . orderBy ( 'ge.date' ) ;
131138
132- return query . then ( data => {
133- return {
134- ...( data . length > 0
135- ? { grouping : this . getDynamicDateGrouping ( true ) }
136- : { } ) ,
137- data,
138- } ;
139- } ) ;
139+ return query . then ( data => this . getResponseWithGrouping < DailyUser [ ] > ( data ) ) ;
140140 }
141141
142142 async getUsers ( ) : Promise < Knex . QueryBuilder > {
@@ -156,9 +156,7 @@ export abstract class BaseDatabaseAdapter implements EventDatabase {
156156 return query . then ( result => {
157157 const { licensedUsers } = this . config ! ;
158158 result [ 0 ] = { ...result [ 0 ] , licensed_users : licensedUsers } as any ;
159- return {
160- data : result ,
161- } ;
159+ return this . getResponseData ( result ) ;
162160 } ) ;
163161 }
164162
@@ -182,7 +180,7 @@ export abstract class BaseDatabaseAdapter implements EventDatabase {
182180 . orderBy ( 'count' , 'desc' )
183181 . limit ( Number ( limit ) || 3 ) ;
184182
185- return query . then ( data => ( { data } ) ) ;
183+ return query . then ( data => this . getResponseData ( data , 'last_used' ) ) ;
186184 }
187185
188186 async getTopSearches ( ) : Promise < Knex . QueryBuilder > {
@@ -200,7 +198,7 @@ export abstract class BaseDatabaseAdapter implements EventDatabase {
200198 . orderBy ( 'date' , 'asc' )
201199 . limit ( Number ( limit ) || 3 ) ;
202200
203- return query . then ( data => ( { data } ) ) ;
201+ return query . then ( data => this . getResponseWithGrouping ( data ) ) ;
204202 }
205203
206204 async getTopTechDocsViews ( ) : Promise < Knex . QueryBuilder > {
@@ -221,7 +219,7 @@ export abstract class BaseDatabaseAdapter implements EventDatabase {
221219 . groupByRaw ( 'entityRef' )
222220 . limit ( Number ( limit ) || 3 ) ;
223221
224- return query . then ( data => ( { data } ) ) ;
222+ return query . then ( data => this . getResponseData ( data , 'last_used' ) ) ;
225223 }
226224
227225 async getTopCatalogEntitiesViews ( ) : Promise < Knex . QueryBuilder > {
@@ -248,7 +246,7 @@ export abstract class BaseDatabaseAdapter implements EventDatabase {
248246 if ( kind ) {
249247 query . andWhere ( db . raw ( `attributes->>'kind' = ?` , [ kind ] ) ) ;
250248 }
251- return query . then ( data => ( { data } ) ) ;
249+ return query . then ( data => this . getResponseData ( data , 'last_used' ) ) ;
252250 }
253251
254252 async getTopPluginViews ( ) : Promise < Knex . QueryBuilder > {
@@ -291,8 +289,8 @@ export abstract class BaseDatabaseAdapter implements EventDatabase {
291289 'plugin_id' ,
292290 db . raw ( `
293291 json(${ this . getJsonAggregationQuery ( 'date' , 'count' ) } ) AS trend,
294- ( SELECT count FROM trend_data td WHERE td.plugin_id = t.plugin_id ORDER BY date LIMIT 1) AS first_count,
295- ( SELECT count FROM trend_data td WHERE td.plugin_id = t.plugin_id ORDER BY date DESC LIMIT 1) AS last_count
292+ COALESCE(( SELECT count FROM trend_data td WHERE td.plugin_id = t.plugin_id ORDER BY date LIMIT 1),0 ) AS first_count,
293+ COALESCE(( SELECT count FROM trend_data td WHERE td.plugin_id = t.plugin_id ORDER BY date DESC LIMIT 1),0 ) AS last_count
296294 ` ) ,
297295 ] )
298296 . from ( 'trend_data AS t' )
@@ -320,20 +318,20 @@ export abstract class BaseDatabaseAdapter implements EventDatabase {
320318 . orderBy ( 'p.visit_count' , 'desc' )
321319 . limit ( limit ) ;
322320
323- return query . then ( data => ( {
324- ... ( data . length > 0
325- ? { grouping : this . getDynamicDateGrouping ( true ) }
326- : { } ) ,
327- data : this . transformJson ( data , 'trend' ) ,
328- } ) ) ;
321+ return query . then ( data => {
322+ return this . getResponseWithGrouping (
323+ this . transformJson ( data , 'trend' ) ,
324+ 'trend' ,
325+ ) ;
326+ } ) ;
329327 }
330328
331329 abstract getDate ( ) : string ;
332330 abstract getLastUsedDate ( ) : string ;
333331 abstract isJsonSupported ( ) : boolean ;
334332 abstract isPartitionSupported ( ) : boolean ;
335333 abstract getDateBetweenQuery ( ) : string ;
336- abstract getDynamicDateGrouping ( onlyText ?: boolean ) : string ;
334+ abstract getDynamicDateGrouping ( onlyText ?: boolean ) : Grouping | string ;
337335 abstract getFormatedDate ( column : string ) : string ;
338336 abstract getJsonAggregationQuery ( ...args : any [ ] ) : string ;
339337
@@ -351,7 +349,68 @@ export abstract class BaseDatabaseAdapter implements EventDatabase {
351349 } ) ) ;
352350 }
353351
354- private ensureFiltersSet ( ) {
352+ modifyDateInObject < T extends any > (
353+ obj : T & { [ key : string ] : string | number } ,
354+ datePath : string = 'date' ,
355+ ) {
356+ if ( obj [ datePath ] ) {
357+ return {
358+ ...obj ,
359+ [ datePath ] : convertToLocalTimezone ( obj [ datePath ] as string ) ,
360+ } ;
361+ }
362+ return obj ;
363+ }
364+
365+ getResponseData < T extends any [ ] > (
366+ data : T ,
367+ datePath : string = 'date' ,
368+ ) : ResponseData < T > {
369+ return {
370+ data : data . map ( d => {
371+ if ( Array . isArray ( d [ datePath ] ) ) {
372+ return {
373+ ...d ,
374+ [ datePath ] : d [ datePath ] . map ( ( dp : any ) =>
375+ this . modifyDateInObject ( dp ) ,
376+ ) ,
377+ } ;
378+ }
379+ return this . modifyDateInObject ( d , datePath ) ;
380+ } ) as T ,
381+ } ;
382+ }
383+
384+ getResponseWithGrouping = < T extends any [ ] > (
385+ data : T ,
386+ datePath : string = 'date' ,
387+ ) : ResponseWithGrouping < T > => {
388+ const grouping = this . getDynamicDateGrouping ( true ) as Grouping ;
389+
390+ if ( grouping === 'hourly' ) {
391+ return {
392+ grouping,
393+ data : data . map ( d => {
394+ if ( Array . isArray ( d [ datePath ] ) ) {
395+ return {
396+ ...d ,
397+ [ datePath ] : d [ datePath ] . map ( ( dp : any ) =>
398+ this . modifyDateInObject ( dp ) ,
399+ ) ,
400+ } ;
401+ }
402+ return this . modifyDateInObject ( d , datePath ) ;
403+ } ) as T ,
404+ } ;
405+ }
406+
407+ return {
408+ grouping,
409+ data,
410+ } ;
411+ } ;
412+
413+ ensureFiltersSet ( ) {
355414 if ( ! this . filters ) {
356415 throw new Error (
357416 'Filters must be set using setFilters() before calling methods.' ,
0 commit comments