diff --git a/web/package-lock.json b/web/package-lock.json index 839d03979..947c7564c 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -2526,30 +2526,14 @@ "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" }, "chart.js": { - "version": "2.9.4", - "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-2.9.4.tgz", - "integrity": "sha512-B07aAzxcrikjAPyV+01j7BmOpxtQETxTSlQ26BEYJ+3iUkbNKaOJ/nDbT6JjyqYxseM0ON12COHYdU2cTIjC7A==", - "requires": { - "chartjs-color": "^2.1.0", - "moment": "^2.10.2" - } + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-3.0.2.tgz", + "integrity": "sha512-DR0GmFSlxcFJp/w//ZmbxSduAkH/AqwxoiZxK97KHnWZf6gvsKWS3160WvNMMHYvzW9OXqGWjPjVh1Qu+xDabg==" }, - "chartjs-color": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chartjs-color/-/chartjs-color-2.4.1.tgz", - "integrity": "sha512-haqOg1+Yebys/Ts/9bLo/BqUcONQOdr/hoEr2LLTRl6C5LXctUdHxsCYfvQVg5JIxITrfCNUDr4ntqmQk9+/0w==", - "requires": { - "chartjs-color-string": "^0.6.0", - "color-convert": "^1.9.3" - } - }, - "chartjs-color-string": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/chartjs-color-string/-/chartjs-color-string-0.6.0.tgz", - "integrity": "sha512-TIB5OKn1hPJvO7JcteW4WY/63v6KwEdt6udfnDE9iCAZgy+V4SrbSxoIbTw/xkUIapjEI4ExGtD0+6D3KyFd7A==", - "requires": { - "color-name": "^1.0.0" - } + "chartjs-adapter-moment": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/chartjs-adapter-moment/-/chartjs-adapter-moment-1.0.0.tgz", + "integrity": "sha512-PqlerEvQcc5hZLQ/NQWgBxgVQ4TRdvkW3c/t+SUEQSj78ia3hgLkf2VZ2yGJtltNbEEFyYGm+cA6XXevodYvWA==" }, "chokidar": { "version": "3.5.1", diff --git a/web/package.json b/web/package.json index 49cf6266c..20aa0a834 100644 --- a/web/package.json +++ b/web/package.json @@ -60,16 +60,19 @@ "authentik-api": "file:api", "babel-plugin-macros": "^3.0.1", "base64-js": "^1.5.1", - "chart.js": "^2.9.4", + "chart.js": "^3.0.2", + "chartjs-adapter-moment": "^1.0.0", "codemirror": "^5.60.0", "construct-style-sheets-polyfill": "^2.4.16", + "eslint": "^7.23.0", "eslint-config-google": "^0.14.0", "eslint-plugin-lit": "^1.3.0", - "eslint": "^7.23.0", "flowchart.js": "^1.15.0", "lit-element": "^2.4.0", "lit-html": "^1.3.0", + "moment": "^2.29.1", "rapidoc": "^9.0.0", + "rollup": "^2.44.0", "rollup-plugin-commonjs": "^10.1.0", "rollup-plugin-copy": "^3.4.0", "rollup-plugin-cssimport": "^1.0.2", @@ -77,7 +80,6 @@ "rollup-plugin-node-resolve": "^5.2.0", "rollup-plugin-sourcemaps": "^0.6.3", "rollup-plugin-terser": "^7.0.2", - "rollup": "^2.44.0", "ts-lit-plugin": "^1.2.1", "tslib": "^2.1.0", "typescript": "^4.2.3", diff --git a/web/rollup.config.js b/web/rollup.config.js index 8f47c10de..f207c7481 100644 --- a/web/rollup.config.js +++ b/web/rollup.config.js @@ -30,6 +30,9 @@ const resources = [ const isProdBuild = process.env.NODE_ENV === "production"; // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types function manualChunks(id) { + if (id.endsWith("web/api/dist/index.js")) { + return "api"; + } if (id.includes("locales")) { const parts = id.split("/"); const file = parts[parts.length - 1]; diff --git a/web/src/authentik.css b/web/src/authentik.css index e90262bb3..b61a0d566 100644 --- a/web/src/authentik.css +++ b/web/src/authentik.css @@ -129,7 +129,6 @@ body { --pf-c-card--BackgroundColor: var(--ak-dark-background-light); } .pf-c-card__title, - .pf-c-card__header-main, .pf-c-card__body { color: var(--ak-dark-foreground); } diff --git a/web/src/elements/cards/AggregateCard.ts b/web/src/elements/cards/AggregateCard.ts index 6f95a68e3..11898b415 100644 --- a/web/src/elements/cards/AggregateCard.ts +++ b/web/src/elements/cards/AggregateCard.ts @@ -45,7 +45,7 @@ export class AggregateCard extends LitElement { render(): TemplateResult { return html`
-
+
 ${this.header ? this.header : ""}
${this.renderHeaderLink()} diff --git a/web/src/elements/charts/AdminLoginsChart.ts b/web/src/elements/charts/AdminLoginsChart.ts index 9411597d3..4b827a781 100644 --- a/web/src/elements/charts/AdminLoginsChart.ts +++ b/web/src/elements/charts/AdminLoginsChart.ts @@ -1,5 +1,5 @@ import { customElement } from "lit-element"; -import Chart from "chart.js"; +import { ChartDataset } from "chart.js"; import { AdminApi, LoginMetrics } from "authentik-api"; import { AKChart } from "./Chart"; import { DEFAULT_CONFIG } from "../../api/Config"; @@ -11,7 +11,7 @@ export class AdminLoginsChart extends AKChart { return new AdminApi(DEFAULT_CONFIG).adminMetricsList(); } - getDatasets(data: LoginMetrics): Chart.ChartDataSets[] { + getDatasets(data: LoginMetrics): ChartDataset[] { return [ { label: "Failed Logins", @@ -19,10 +19,10 @@ export class AdminLoginsChart extends AKChart { spanGaps: true, data: data.loginsFailedPer1h?.map((cord) => { return { - x: cord.xCord, - y: cord.yCord, + x: cord.xCord || 0, + y: cord.yCord || 0, }; - }), + }) || [], }, { label: "Successful Logins", @@ -30,10 +30,10 @@ export class AdminLoginsChart extends AKChart { spanGaps: true, data: data.loginsPer1h?.map((cord) => { return { - x: cord.xCord, - y: cord.yCord, + x: cord.xCord || 0, + y: cord.yCord || 0, }; - }), + }) || [], }, ]; } diff --git a/web/src/elements/charts/ApplicationAuthorizeChart.ts b/web/src/elements/charts/ApplicationAuthorizeChart.ts index 4c33b7e77..d9f513b45 100644 --- a/web/src/elements/charts/ApplicationAuthorizeChart.ts +++ b/web/src/elements/charts/ApplicationAuthorizeChart.ts @@ -2,6 +2,7 @@ import { customElement, property } from "lit-element"; import { Coordinate, CoreApi } from "authentik-api"; import { DEFAULT_CONFIG } from "../../api/Config"; import { AKChart } from "./Chart"; +import { ChartDataset } from "chart.js"; @customElement("ak-charts-application-authorize") export class ApplicationAuthorizeChart extends AKChart { @@ -13,7 +14,7 @@ export class ApplicationAuthorizeChart extends AKChart { return new CoreApi(DEFAULT_CONFIG).coreApplicationsMetrics({ slug: this.applicationSlug }); } - getDatasets(data: Coordinate[]): Chart.ChartDataSets[] { + getDatasets(data: Coordinate[]): ChartDataset[] { return [ { label: "Authorizations", @@ -21,10 +22,10 @@ export class ApplicationAuthorizeChart extends AKChart { spanGaps: true, data: data.map((cord) => { return { - x: cord.xCord, - y: cord.yCord, + x: cord.xCord || 0, + y: cord.yCord || 0, }; - }), + }) || [], }, ]; } diff --git a/web/src/elements/charts/Chart.ts b/web/src/elements/charts/Chart.ts index a4fec4550..8a425dcc3 100644 --- a/web/src/elements/charts/Chart.ts +++ b/web/src/elements/charts/Chart.ts @@ -1,15 +1,13 @@ import { css, CSSResult, html, LitElement, TemplateResult } from "lit-element"; -import Chart from "chart.js"; +import { Chart, ChartDataset, Tick, LineController, TimeScale, LinearScale, BarController, BarElement, ChartConfiguration, Legend } from "chart.js"; +import "chartjs-adapter-moment"; -interface TickValue { - value: number; - major: boolean; -} +Chart.register(LineController, TimeScale, LinearScale, BarController, BarElement, Legend); export abstract class AKChart extends LitElement { abstract apiRequest(): Promise; - abstract getDatasets(data: T): Chart.ChartDataSets[]; + abstract getDatasets(data: T): ChartDataset[]; chart?: Chart; @@ -39,46 +37,45 @@ export abstract class AKChart extends LitElement { } configureChart(data: T, ctx: CanvasRenderingContext2D): Chart { - return new Chart(ctx, { + const config = { type: "bar", data: { datasets: this.getDatasets(data), }, options: { maintainAspectRatio: false, - spanGaps: true, scales: { - xAxes: [ - { - stacked: true, - gridLines: { - color: "rgba(0, 0, 0, 0)", - }, - type: "time", - offset: true, - ticks: { - callback: function (value, index: number, values) { - const valueStamp = (values[index]); - const delta = Date.now() - valueStamp.value; - const ago = Math.round(delta / 1000 / 3600); - return `${ago} Hours ago`; - }, - autoSkip: true, - maxTicksLimit: 8, + x: { + type: "time", + display: true, + ticks: { + callback: function (tickValue: string | number, index: number, ticks: Tick[]): string { + const valueStamp = (ticks[index]); + const delta = Date.now() - valueStamp.value; + const ago = Math.round(delta / 1000 / 3600); + return `${ago} Hours ago`; }, + autoSkip: true, + maxTicksLimit: 8, }, - ], - yAxes: [ - { - stacked: true, - gridLines: { - color: "rgba(0, 0, 0, 0)", - }, + stacked: true, + grid: { + color: "rgba(0, 0, 0, 0)", }, - ], + offset: true + }, + y: { + type: "linear", + display: true, + stacked: true, + grid: { + color: "rgba(0, 0, 0, 0)", + }, + } }, }, - }); + }; + return new Chart(ctx, config as ChartConfiguration); } firstUpdated(): void { diff --git a/web/src/elements/charts/UserChart.ts b/web/src/elements/charts/UserChart.ts index 4e959a73e..854bcc699 100644 --- a/web/src/elements/charts/UserChart.ts +++ b/web/src/elements/charts/UserChart.ts @@ -1,8 +1,8 @@ import { customElement, property } from "lit-element"; -import Chart from "chart.js"; import { CoreApi, UserMetrics } from "authentik-api"; import { AKChart } from "./Chart"; import { DEFAULT_CONFIG } from "../../api/Config"; +import { ChartDataset } from "chart.js"; @customElement("ak-charts-user") export class UserChart extends AKChart { @@ -16,7 +16,7 @@ export class UserChart extends AKChart { }); } - getDatasets(data: UserMetrics): Chart.ChartDataSets[] { + getDatasets(data: UserMetrics): ChartDataset[] { return [ { label: "Failed Logins", @@ -24,10 +24,10 @@ export class UserChart extends AKChart { spanGaps: true, data: data.loginsFailedPer1h?.map((cord) => { return { - x: cord.xCord, - y: cord.yCord, + x: cord.xCord || 0, + y: cord.yCord || 0, }; - }), + }) || [], }, { label: "Successful Logins", @@ -35,10 +35,10 @@ export class UserChart extends AKChart { spanGaps: true, data: data.loginsPer1h?.map((cord) => { return { - x: cord.xCord, - y: cord.yCord, + x: cord.xCord || 0, + y: cord.yCord || 0, }; - }), + }) || [], }, { label: "Application authorizations", @@ -46,10 +46,10 @@ export class UserChart extends AKChart { spanGaps: true, data: data.authorizationsPer1h?.map((cord) => { return { - x: cord.xCord, - y: cord.yCord, + x: cord.xCord || 0, + y: cord.yCord || 0, }; - }), + }) || [], }, ]; }