web/admin: show users and groups as chart
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
		| @ -7,14 +7,14 @@ import "./TopApplicationsTable"; | ||||
|  | ||||
| import "./cards/AdminStatusCard"; | ||||
| import "./cards/BackupStatusCard"; | ||||
| import "./cards/ProviderStatusCard"; | ||||
| import "./cards/UserCountStatusCard"; | ||||
| import "./cards/VersionStatusCard"; | ||||
| import "./cards/WorkerStatusCard"; | ||||
|  | ||||
| import "./graphs/FlowStatusCard"; | ||||
| import "./graphs/LDAPSyncStatusCard"; | ||||
| import "./graphs/OutpostStatusCard"; | ||||
| import "./graphs/UserCountStatusCard"; | ||||
| import "./graphs/GroupCountStatusCard"; | ||||
| import "./graphs/PolicyStatusCard"; | ||||
|  | ||||
| import PFPage from "@patternfly/patternfly/components/Page/page.css"; | ||||
| @ -54,43 +54,49 @@ export class AdminOverviewPage extends LitElement { | ||||
|         <section class="pf-c-page__main-section"> | ||||
|             <div class="pf-l-grid pf-m-gutter"> | ||||
|                 <!-- row 1 --> | ||||
|                 <div class="pf-l-grid__item pf-m-6-col pf-m-4-col-on-md pf-m-3-col-on-xl graph-container"> | ||||
|                 <div class="pf-l-grid__item pf-m-6-col pf-m-4-col-on-xl pf-m-2-col-on-xl2 graph-container"> | ||||
|                     <ak-aggregate-card icon="pf-icon pf-icon-infrastructure" header=${t`Policies`} headerLink="#/policy/policies"> | ||||
|                         <ak-admin-status-card-policy></ak-admin-status-card-policy> | ||||
|                     </ak-aggregate-card> | ||||
|                 </div> | ||||
|                 <div class="pf-l-grid__item pf-m-6-col pf-m-4-col-on-md pf-m-3-col-on-xl graph-container"> | ||||
|                 <div class="pf-l-grid__item pf-m-6-col pf-m-4-col-on-xl pf-m-2-col-on-xl2 graph-container"> | ||||
|                     <ak-aggregate-card icon="pf-icon pf-icon-server" header=${t`Flows`} headerLink="#/flow/flows"> | ||||
|                         <ak-admin-status-card-flow></ak-admin-status-card-flow> | ||||
|                     </ak-aggregate-card> | ||||
|                 </div> | ||||
|                 <div class="pf-l-grid__item pf-m-6-col pf-m-4-col-on-md pf-m-3-col-on-xl graph-container"> | ||||
|                     <ak-aggregate-card icon="fa fa-sync-alt" header=${t`LDAP Sync status`} headerLink="#/core/sources"> | ||||
|                         <ak-admin-status-card-ldap-sync></ak-admin-status-card-ldap-sync> | ||||
|                     </ak-aggregate-card> | ||||
|                 </div> | ||||
|                 <div class="pf-l-grid__item pf-m-6-col pf-m-4-col-on-md pf-m-3-col-on-xl graph-container"> | ||||
|                 <div class="pf-l-grid__item pf-m-6-col pf-m-4-col-on-xl pf-m-2-col-on-xl2 graph-container"> | ||||
|                     <ak-aggregate-card icon="fa fa-sync-alt" header=${t`Outpost status`} headerLink="#/outpost/outposts"> | ||||
|                         <ak-admin-status-card-outpost></ak-admin-status-card-outpost> | ||||
|                     </ak-aggregate-card> | ||||
|                 </div> | ||||
|                 <div class="pf-l-grid__item pf-m-6-col pf-m-4-col-on-xl pf-m-2-col-on-xl2 graph-container"> | ||||
|                     <ak-aggregate-card icon="fa fa-sync-alt" header=${t`Users`} headerLink="#/identity/users"> | ||||
|                         <ak-admin-status-card-user-count></ak-admin-status-card-user-count> | ||||
|                     </ak-aggregate-card> | ||||
|                 </div> | ||||
|                 <div class="pf-l-grid__item pf-m-6-col pf-m-4-col-on-xl pf-m-2-col-on-xl2 graph-container"> | ||||
|                     <ak-aggregate-card icon="fa fa-sync-alt" header=${t`Groups`} headerLink="#/identity/groups"> | ||||
|                         <ak-admin-status-card-group-count></ak-admin-status-card-group-count> | ||||
|                     </ak-aggregate-card> | ||||
|                 </div> | ||||
|                 <div class="pf-l-grid__item pf-m-6-col pf-m-4-col-on-xl pf-m-2-col-on-xl2 graph-container"> | ||||
|                     <ak-aggregate-card icon="fa fa-sync-alt" header=${t`LDAP Sync status`} headerLink="#/core/sources"> | ||||
|                         <ak-admin-status-card-ldap-sync></ak-admin-status-card-ldap-sync> | ||||
|                     </ak-aggregate-card> | ||||
|                 </div> | ||||
|                 <div class="pf-l-grid__item pf-m-12-col row-divider"> | ||||
|                     <hr> | ||||
|                 </div> | ||||
|                 <!-- row 2 --> | ||||
|                 <div class="pf-l-grid__item pf-m-6-col pf-m-4-col-on-md pf-m-3-col-on-xl card-container"> | ||||
|                 <div class="pf-l-grid__item pf-m-6-col pf-m-4-col-on-md pf-m-4-col-on-xl card-container"> | ||||
|                     <ak-admin-status-version icon="pf-icon pf-icon-bundle" header=${t`Version`} headerLink="https://github.com/goauthentik/authentik/releases"> | ||||
|                     </ak-admin-status-version> | ||||
|                 </div> | ||||
|                 <div class="pf-l-grid__item pf-m-6-col pf-m-4-col-on-md pf-m-3-col-on-xl card-container"> | ||||
|                 <div class="pf-l-grid__item pf-m-6-col pf-m-4-col-on-md pf-m-4-col-on-xl card-container"> | ||||
|                     <ak-admin-status-card-backup icon="fa fa-database" header=${t`Backup status`} headerLink="#/administration/system-tasks"> | ||||
|                     </ak-admin-status-card-backup> | ||||
|                 </div> | ||||
|                 <div class="pf-l-grid__item pf-m-6-col pf-m-4-col-on-md pf-m-3-col-on-xl card-container"> | ||||
|                     <ak-admin-status-card-user-count icon="pf-icon pf-icon-user" header=${t`Users`} headerLink="#/identity/users"> | ||||
|                     </ak-admin-status-card-user-count> | ||||
|                 </div> | ||||
|                 <div class="pf-l-grid__item pf-m-6-col pf-m-4-col-on-md pf-m-3-col-on-xl card-container"> | ||||
|                 <div class="pf-l-grid__item pf-m-6-col pf-m-4-col-on-md pf-m-4-col-on-xl card-container"> | ||||
|                     <ak-admin-status-card-workers icon="pf-icon pf-icon-server" header=${t`Workers`}> | ||||
|                     </ak-admin-status-card-workers> | ||||
|                 </div> | ||||
| @ -98,12 +104,12 @@ export class AdminOverviewPage extends LitElement { | ||||
|                     <hr> | ||||
|                 </div> | ||||
|                 <!-- row 3 --> | ||||
|                 <div class="pf-l-grid__item pf-m-12-col pf-m-6-col-on-md pf-m-6-col-on-xl big-graph-container"> | ||||
|                 <div class="pf-l-grid__item pf-m-12-col pf-m-6-col-on-xl pf-m-9-col-on-xl2 big-graph-container"> | ||||
|                     <ak-aggregate-card icon="pf-icon pf-icon-server" header=${t`Logins over the last 24 hours`}> | ||||
|                         <ak-charts-admin-login></ak-charts-admin-login> | ||||
|                     </ak-aggregate-card> | ||||
|                 </div> | ||||
|                 <div class="pf-l-grid__item pf-m-12-col pf-m-6-col-on-md pf-m-6-col-on-xl big-graph-container"> | ||||
|                 <div class="pf-l-grid__item pf-m-12-col pf-m-6-col-on-xl pf-m-3-col-on-xl2 big-graph-container"> | ||||
|                     <ak-aggregate-card icon="pf-icon pf-icon-server" header=${t`Apps with most usage`}> | ||||
|                         <ak-top-applications-table></ak-top-applications-table> | ||||
|                     </ak-aggregate-card> | ||||
|  | ||||
| @ -1,31 +0,0 @@ | ||||
| import { t } from "@lingui/macro"; | ||||
| import { customElement } from "lit-element"; | ||||
| import { ProvidersApi } from "authentik-api"; | ||||
| import { DEFAULT_CONFIG } from "../../../api/Config"; | ||||
| import { AdminStatusCard, AdminStatus } from "./AdminStatusCard"; | ||||
|  | ||||
| @customElement("ak-admin-status-card-provider") | ||||
| export class ProviderStatusCard extends AdminStatusCard<number> { | ||||
|  | ||||
|     getPrimaryValue(): Promise<number> { | ||||
|         return new ProvidersApi(DEFAULT_CONFIG).providersAllList({ | ||||
|             applicationIsnull: "true" | ||||
|         }).then((value) => { | ||||
|             return value.pagination.count; | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     getStatus(value: number): Promise<AdminStatus> { | ||||
|         if (value > 0) { | ||||
|             return Promise.resolve<AdminStatus>({ | ||||
|                 icon: "fa fa-exclamation-triangle pf-m-warning", | ||||
|                 message: t`Warning: At least one Provider has no application assigned.`, | ||||
|             }); | ||||
|         } else { | ||||
|             return Promise.resolve<AdminStatus>({ | ||||
|                 icon: "fa fa-check-circle pf-m-success" | ||||
|             }); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| } | ||||
| @ -1,24 +0,0 @@ | ||||
| import { customElement } from "lit-element"; | ||||
| import { CoreApi } from "authentik-api"; | ||||
| import { DEFAULT_CONFIG } from "../../../api/Config"; | ||||
| import { AdminStatusCard, AdminStatus } from "./AdminStatusCard"; | ||||
|  | ||||
| @customElement("ak-admin-status-card-user-count") | ||||
| export class UserCountStatusCard extends AdminStatusCard<number> { | ||||
|  | ||||
|     getPrimaryValue(): Promise<number> { | ||||
|         return new CoreApi(DEFAULT_CONFIG).coreUsersList({ | ||||
|             pageSize: 1 | ||||
|         }).then((value) => { | ||||
|             return value.pagination.count; | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     // eslint-disable-next-line @typescript-eslint/no-unused-vars | ||||
|     getStatus(value: number): Promise<AdminStatus> { | ||||
|         return Promise.resolve<AdminStatus>({ | ||||
|             icon: "fa fa-check-circle pf-m-success" | ||||
|         }); | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										68
									
								
								web/src/pages/admin-overview/graphs/GroupCountStatusCard.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								web/src/pages/admin-overview/graphs/GroupCountStatusCard.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,68 @@ | ||||
| import { customElement } from "lit-element"; | ||||
| import { CoreApi } from "authentik-api"; | ||||
| import { DEFAULT_CONFIG } from "../../../api/Config"; | ||||
| import { AKChart } from "../../../elements/charts/Chart"; | ||||
| import { t } from "@lingui/macro"; | ||||
| import { ChartOptions, ChartData } from "chart.js"; | ||||
|  | ||||
| interface GroupMetrics { | ||||
|     count: number; | ||||
|     superusers: number; | ||||
| } | ||||
|  | ||||
| @customElement("ak-admin-status-card-group-count") | ||||
| export class GroupCountStatusCard extends AKChart<GroupMetrics> { | ||||
|  | ||||
|     getChartType(): string { | ||||
|         return "doughnut"; | ||||
|     } | ||||
|  | ||||
|     getOptions(): ChartOptions { | ||||
|         return { | ||||
|             plugins: { | ||||
|                 legend: { | ||||
|                     display: false, | ||||
|                 }, | ||||
|             }, | ||||
|             maintainAspectRatio: false, | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     async apiRequest(): Promise<GroupMetrics> { | ||||
|         const api = new CoreApi(DEFAULT_CONFIG); | ||||
|         const count = (await api.coreGroupsList({ | ||||
|             pageSize: 1 | ||||
|         })).pagination.count; | ||||
|         const superusers = (await api.coreGroupsList({ | ||||
|             isSuperuser: "true" | ||||
|         })).pagination.count; | ||||
|         this.centerText = count.toString(); | ||||
|         return { | ||||
|             count: count - superusers, | ||||
|             superusers, | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     getChartData(data: GroupMetrics): ChartData { | ||||
|         return { | ||||
|             labels: [ | ||||
|                 t`Total groups`, | ||||
|                 t`Superuser-groups`, | ||||
|             ], | ||||
|             datasets: [ | ||||
|                 { | ||||
|                     backgroundColor: [ | ||||
|                         "#2b9af3", | ||||
|                         "#3e8635", | ||||
|                     ], | ||||
|                     spanGaps: true, | ||||
|                     data: [ | ||||
|                         data.count, | ||||
|                         data.superusers, | ||||
|                     ], | ||||
|                 }, | ||||
|             ] | ||||
|         }; | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										68
									
								
								web/src/pages/admin-overview/graphs/UserCountStatusCard.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								web/src/pages/admin-overview/graphs/UserCountStatusCard.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,68 @@ | ||||
| import { customElement } from "lit-element"; | ||||
| import { CoreApi } from "authentik-api"; | ||||
| import { DEFAULT_CONFIG } from "../../../api/Config"; | ||||
| import { AKChart } from "../../../elements/charts/Chart"; | ||||
| import { t } from "@lingui/macro"; | ||||
| import { ChartOptions, ChartData } from "chart.js"; | ||||
|  | ||||
| interface UserMetrics { | ||||
|     count: number; | ||||
|     superusers: number; | ||||
| } | ||||
|  | ||||
| @customElement("ak-admin-status-card-user-count") | ||||
| export class UserCountStatusCard extends AKChart<UserMetrics> { | ||||
|  | ||||
|     getChartType(): string { | ||||
|         return "doughnut"; | ||||
|     } | ||||
|  | ||||
|     getOptions(): ChartOptions { | ||||
|         return { | ||||
|             plugins: { | ||||
|                 legend: { | ||||
|                     display: false, | ||||
|                 }, | ||||
|             }, | ||||
|             maintainAspectRatio: false, | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     async apiRequest(): Promise<UserMetrics> { | ||||
|         const api = new CoreApi(DEFAULT_CONFIG); | ||||
|         const count = (await api.coreUsersList({ | ||||
|             pageSize: 1 | ||||
|         })).pagination.count; | ||||
|         const superusers = (await api.coreUsersList({ | ||||
|             isSuperuser: "true" | ||||
|         })).pagination.count; | ||||
|         this.centerText = count.toString(); | ||||
|         return { | ||||
|             count: count - superusers, | ||||
|             superusers, | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     getChartData(data: UserMetrics): ChartData { | ||||
|         return { | ||||
|             labels: [ | ||||
|                 t`Total users`, | ||||
|                 t`Superusers`, | ||||
|             ], | ||||
|             datasets: [ | ||||
|                 { | ||||
|                     backgroundColor: [ | ||||
|                         "#2b9af3", | ||||
|                         "#3e8635", | ||||
|                     ], | ||||
|                     spanGaps: true, | ||||
|                     data: [ | ||||
|                         data.count, | ||||
|                         data.superusers, | ||||
|                     ], | ||||
|                 }, | ||||
|             ] | ||||
|         }; | ||||
|     } | ||||
|  | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 Jens Langhammer
					Jens Langhammer