mirror of
https://github.com/apricote/Listory.git
synced 2026-01-13 21:21:02 +00:00
refactor(server): introduce TimePresets for reports
This commit is contained in:
parent
6f8fc0265a
commit
b8918889a1
5 changed files with 89 additions and 11 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
4
src/reports/interval.d.ts
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
export interface Interval {
|
||||
start: Date;
|
||||
end: Date;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
9
src/reports/timePreset.enum.ts
Normal file
9
src/reports/timePreset.enum.ts
Normal 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",
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue