refactor(server): introduce TimePresets for reports

This commit is contained in:
Julian Tölle 2020-06-01 20:34:59 +02:00
parent 6f8fc0265a
commit b8918889a1
5 changed files with 89 additions and 11 deletions

View file

@ -1,12 +1,13 @@
import { IsOptional, ValidateNested, IsISO8601 } from "class-validator";
import { IsDate, IsOptional, ValidateNested } from "class-validator";
import { Interval } from "date-fns";
import { User } from "src/users/user.entity";
// tslint:disable-next-line: max-classes-per-file
export class GetListensFilterTimeDto {
@IsISO8601()
start: string;
@IsISO8601()
end: string;
export class GetListensFilterTimeDto implements Interval {
@IsDate()
start: Date;
@IsDate()
end: Date;
}
// tslint:disable-next-line: max-classes-per-file

View file

@ -60,8 +60,8 @@ export class ListensService {
queryBuilder = queryBuilder.andWhere(
"l.playedAt BETWEEN :timeStart AND :timeEnd",
{
timeStart: parseISO(filter.time.start),
timeEnd: parseISO(filter.time.end),
timeStart: filter.time.start,
timeEnd: filter.time.end,
}
);
}

4
src/reports/interval.d.ts vendored Normal file
View file

@ -0,0 +1,4 @@
export interface Interval {
start: Date;
end: Date;
}

View file

@ -1,21 +1,25 @@
import { Injectable } from "@nestjs/common";
import { BadRequestException, Injectable } from "@nestjs/common";
import {
eachDayOfInterval,
eachMonthOfInterval,
eachWeekOfInterval,
eachYearOfInterval,
endOfDay,
formatISO,
Interval,
isSameDay,
isSameMonth,
isSameWeek,
isSameYear,
parseISO,
parseJSON,
startOfDay,
sub,
} from "date-fns";
import { ListensService } from "../listens/listens.service";
import { GetListenReportDto } from "./dto/get-listen-report.dto";
import { ListenReportDto } from "./dto/listen-report.dto";
import { Timeframe } from "./timeframe.enum";
import { TimePreset } from "./timePreset.enum";
const timeframeToDateFns: {
[x in Timeframe]: {
@ -41,6 +45,16 @@ const timeframeToDateFns: {
},
};
const timePresetToDays: { [x in TimePreset]: number } = {
[TimePreset.LAST_7_DAYS]: 7,
[TimePreset.LAST_30_DAYS]: 30,
[TimePreset.LAST_90_DAYS]: 90,
[TimePreset.LAST_180_DAYS]: 180,
[TimePreset.LAST_365_DAYS]: 365,
[TimePreset.ALL_TIME]: 0, // Not used for this
[TimePreset.CUSTOM]: 0, // Not used for this
};
@Injectable()
export class ReportsService {
constructor(private readonly listensService: ListensService) {}
@ -48,9 +62,16 @@ export class ReportsService {
async getListens(options: GetListenReportDto): Promise<ListenReportDto> {
const { user, timeFrame, timeStart, timeEnd } = options;
// Function should eventually be rewritten to accept a timepreset
const interval = this.getIntervalFromPreset({
timePreset: TimePreset.CUSTOM,
customTimeStart: timeStart,
customTimeEnd: timeEnd,
});
const { items: listens } = await this.listensService.getListens({
user,
filter: { time: { start: timeStart, end: timeEnd } },
filter: { time: interval },
page: 1,
limit: 10000000,
});
@ -70,4 +91,47 @@ export class ReportsService {
return { items: reportItems, timeStart, timeEnd, timeFrame };
}
private getIntervalFromPreset(options: {
timePreset: TimePreset;
customTimeStart?: string;
customTimeEnd?: string;
}): Interval {
let interval = {
start: startOfDay(new Date()),
end: endOfDay(new Date()), // NOW
};
switch (options.timePreset) {
case TimePreset.LAST_7_DAYS:
case TimePreset.LAST_30_DAYS:
case TimePreset.LAST_90_DAYS:
case TimePreset.LAST_180_DAYS:
case TimePreset.LAST_365_DAYS: {
interval.start = startOfDay(
sub(interval.start, { days: timePresetToDays[options.timePreset] })
);
break;
}
case TimePreset.ALL_TIME: {
interval.start = new Date(0); // Start of epoch
break;
}
case TimePreset.CUSTOM: {
if (!options.customTimeStart && !options.customTimeEnd) {
throw new BadRequestException("MissingCustomTime");
}
interval = {
start: parseJSON(options.customTimeStart),
end: parseJSON(options.customTimeEnd),
};
break;
}
}
return interval;
}
}

View file

@ -0,0 +1,9 @@
export enum TimePreset {
LAST_7_DAYS = "last_7_days",
LAST_30_DAYS = "last_30_days",
LAST_90_DAYS = "last_90_days",
LAST_180_DAYS = "last_180_days",
LAST_365_DAYS = "last_365_days",
ALL_TIME = "all_time",
CUSTOM = "custom",
}