diff --git a/frontend/src/components/ReportListens.tsx b/frontend/src/components/ReportListens.tsx index 0c47820..644a200 100644 --- a/frontend/src/components/ReportListens.tsx +++ b/frontend/src/components/ReportListens.tsx @@ -77,7 +77,7 @@ export const ReportListens: React.FC = () => { {isLoading && } {!reportHasItems && !isLoading && (
-

Report is emtpy! :(

+

Report is empty! :(

)} {reportHasItems && ( @@ -128,7 +128,7 @@ const ReportGraph: React.FC<{ diff --git a/src/reports/reports.service.ts b/src/reports/reports.service.ts index f2fc500..224fcf0 100644 --- a/src/reports/reports.service.ts +++ b/src/reports/reports.service.ts @@ -10,7 +10,6 @@ import { isSameMonth, isSameWeek, isSameYear, - min, parseJSON, startOfDay, sub, @@ -73,7 +72,13 @@ export class ReportsService { async getListens(options: GetListenReportDto): Promise { const { timeFrame, time: timePreset } = options; - const listens = await this.getListensQueryFromOptions(options).getMany(); + const results = await this.getListensQueryFromOptions(options) + .select(`count(*) as "listenCount"`) + .addSelect(`date_trunc(:timeFrame, "playedAt") as date`) + .groupBy("date") + .orderBy("date") + .setParameter("timeFrame", timeFrame) + .getRawMany<{ listenCount: string; date: Date }>(); const interval = this.getIntervalFromPreset(timePreset); const { eachOfInterval, isSame } = timeframeToDateFns[timeFrame]; @@ -81,18 +86,19 @@ export class ReportsService { // Optimize performance for ALL_TIME by skipping eachOfInterval for time // between 1970 and first listen if (timePreset.timePreset === TimePreset.ALL_TIME) { - let firstListen = min(listens.map(({ playedAt }) => playedAt)); - interval.start = startOfDay(firstListen); + interval.start = startOfDay(results[0].date); } - // TODO: This code blocks the eventloop for multiple seconds if running for - // a large interval and with many listens. Refactor to make this more - // efficient or make pauses for event loop. const reportItems = eachOfInterval(interval).map((date) => { - const count = listens.filter((listen) => - isSame(date, listen.playedAt), - ).length; - return { date: formatISO(date), count }; + const dayResults = results.find((listen) => isSame(date, listen.date)); + + return { + date: formatISO(date), + count: + dayResults && dayResults.listenCount + ? Number.parseInt(dayResults.listenCount) + : 0, + }; }); return { items: reportItems };