client-side data padding

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
Jens Langhammer
2025-06-06 03:57:33 +02:00
parent 41f5d42ba9
commit b046181947
6 changed files with 50 additions and 18 deletions

View File

@ -48,7 +48,10 @@ export class AdminLoginAuthorizeChart extends AKChart<EventVolume[]> {
cubicInterpolationMode: "monotone",
tension: 0.4,
});
return this.eventVolume(data, optsMap);
return this.eventVolume(data, {
optsMap: optsMap,
padToDays: 7,
});
}
}

View File

@ -27,14 +27,14 @@ export class AdminModelPerDay extends AKChart<EventVolume[]> {
async apiRequest(): Promise<EventVolume[]> {
return new EventsApi(DEFAULT_CONFIG).eventsEventsVolumeList({
action: this.action,
historyDays: 30,
...this.query,
});
}
getChartData(data: EventVolume[]): ChartData {
return this.eventVolume(
data,
new Map([
return this.eventVolume(data, {
optsMap: new Map([
[
this.action,
{
@ -44,7 +44,8 @@ export class AdminModelPerDay extends AKChart<EventVolume[]> {
},
],
]),
);
padToDays: 30,
});
}
}

View File

@ -20,9 +20,8 @@ export class ApplicationAuthorizeChart extends AKChart<EventVolume[]> {
}
getChartData(data: EventVolume[]): ChartData {
return this.eventVolume(
data,
new Map([
return this.eventVolume(data, {
optsMap: new Map([
[
EventActions.AuthorizeApplication,
{
@ -32,7 +31,8 @@ export class ApplicationAuthorizeChart extends AKChart<EventVolume[]> {
},
],
]),
);
padToDays: 7,
});
}
}

View File

@ -38,7 +38,9 @@ export class EventVolumeChart extends AKChart<EventVolume[]> {
}
getChartData(data: EventVolume[]): ChartData {
return this.eventVolume(data);
return this.eventVolume(data, {
padToDays: 14,
});
}
render(): TemplateResult {

View File

@ -24,9 +24,8 @@ export class UserChart extends AKChart<EventVolume[]> {
}
getChartData(data: EventVolume[]): ChartData {
return this.eventVolume(
data,
new Map([
return this.eventVolume(data, {
optsMap: new Map([
[
EventActions.LoginFailed,
{
@ -52,7 +51,8 @@ export class UserChart extends AKChart<EventVolume[]> {
},
],
]),
);
padToDays: 7,
});
}
}

View File

@ -241,13 +241,19 @@ export abstract class AKChart<T> extends AKElement {
eventVolume(
data: EventVolume[],
optsMap?: Map<EventActions, Partial<ChartDataset>>,
options?: {
optsMap?: Map<EventActions, Partial<ChartDataset>>;
padToDays?: number;
},
): ChartData {
const datasets: ChartData = {
datasets: [],
};
if (!optsMap) {
optsMap = new Map<EventActions, Partial<ChartDataset>>();
if (!options) {
options = {};
}
if (!options.optsMap) {
options.optsMap = new Map<EventActions, Partial<ChartDataset>>();
}
const actions = new Set(data.map((v) => v.action));
actions.forEach((action) => {
@ -258,11 +264,31 @@ export abstract class AKChart<T> extends AKElement {
y: v.count,
});
});
// Check if we need to pad the data to reach a certain time window
const earliestDate = data
.filter((v) => v.action === action)
.map((v) => v.day)
.sort((a, b) => b.getTime() - a.getTime())
.reverse();
if (earliestDate.length > 0 && options.padToDays) {
const earliestPadded = new Date(
new Date().getTime() - options.padToDays * (1000 * 3600 * 24),
);
const daysDelta = Math.round(
(earliestDate[0].getTime() - earliestPadded.getTime()) / (1000 * 3600 * 24),
);
if (daysDelta > 0) {
actionData.push({
x: earliestPadded.getTime(),
y: 0,
});
}
}
datasets.datasets.push({
data: actionData,
label: actionToLabel(action),
backgroundColor: getColorFromString(action).toString(),
...optsMap.get(action),
...options.optsMap?.get(action),
});
});
return datasets;