diff --git a/web/src/elements/events/ObjectChangelog.ts b/web/src/elements/events/ObjectChangelog.ts new file mode 100644 index 000000000..d7f4125c4 --- /dev/null +++ b/web/src/elements/events/ObjectChangelog.ts @@ -0,0 +1,86 @@ +import { gettext } from "django"; +import { customElement, html, property, TemplateResult } from "lit-element"; +import { AKResponse } from "../../api/Client"; +import { Table, TableColumn } from "../table/Table"; +import { Event, EventsApi } from "authentik-api"; + +import "../forms/DeleteForm"; +import "../Tabs"; +import "../buttons/ModalButton"; +import "../buttons/SpinnerButton"; +import "../buttons/Dropdown"; +import "../../pages/events/EventInfo"; +import { PAGE_SIZE } from "../../constants"; +import { DEFAULT_CONFIG } from "../../api/Config"; +import { EventWithContext } from "../../api/Events"; + +@customElement("ak-object-changelog") +export class ObjectChangelog extends Table { + expandable = true; + + @property() + order = "-created"; + + @property() + targetModelPk!: string | number; + + @property() + targetModelApp!: string; + + @property() + targetModelName!: string; + + apiEndpoint(page: number): Promise> { + return new EventsApi(DEFAULT_CONFIG).eventsEventsList({ + action: "model_", + page: page, + ordering: this.order, + pageSize: PAGE_SIZE, + contextModelApp: this.targetModelApp, + contextModelName: this.targetModelName, + contextModelPk: this.targetModelPk.toString(), + }); + } + + columns(): TableColumn[] { + return [ + new TableColumn("Action", "action"), + new TableColumn("User", "enabled"), + new TableColumn("Creation Date", "created"), + new TableColumn("Client IP", "client_ip"), + ]; + } + + row(item: EventWithContext): TemplateResult[] { + return [ + html`${item.action}`, + html`
${item.user?.username}
+ ${item.user.on_behalf_of ? html` + ${gettext(`On behalf of ${item.user.on_behalf_of.username}`)} + ` : html``}`, + html`${item.created?.toLocaleString()}`, + html`${item.clientIp}`, + ]; + } + + renderExpanded(item: Event): TemplateResult { + return html` + +
+ +
+ + + + `; + } + + renderEmpty(): TemplateResult { + return super.renderEmpty(html` +
+ ${gettext("No matching events could be found.")} +
+
`); + } + +} diff --git a/web/src/elements/forms/DeleteForm.ts b/web/src/elements/forms/DeleteForm.ts index 93060b630..bbe2d1af4 100644 --- a/web/src/elements/forms/DeleteForm.ts +++ b/web/src/elements/forms/DeleteForm.ts @@ -13,7 +13,7 @@ export class DeleteForm extends ModalButton { objectLabel?: string; @property({attribute: false}) - delete!: () => Promise; + delete!: () => Promise; confirm(): void { this.delete().then(() => { diff --git a/web/src/pages/applications/ApplicationViewPage.ts b/web/src/pages/applications/ApplicationViewPage.ts index ca0c12069..e0360ee67 100644 --- a/web/src/pages/applications/ApplicationViewPage.ts +++ b/web/src/pages/applications/ApplicationViewPage.ts @@ -7,6 +7,7 @@ import "../../elements/buttons/ModalButton"; import "../../elements/buttons/SpinnerButton"; import "../../elements/policies/BoundPoliciesList"; import "../../elements/EmptyState"; +import "../../elements/events/ObjectChangelog"; import { Application, CoreApi } from "authentik-api"; import { DEFAULT_CONFIG } from "../../api/Config"; import PFPage from "@patternfly/patternfly/components/Page/page.css"; @@ -111,6 +112,20 @@ export class ApplicationViewPage extends LitElement { +
diff --git a/web/src/pages/flows/FlowViewPage.ts b/web/src/pages/flows/FlowViewPage.ts index c5165e353..fa3fad4c3 100644 --- a/web/src/pages/flows/FlowViewPage.ts +++ b/web/src/pages/flows/FlowViewPage.ts @@ -2,6 +2,7 @@ import { gettext } from "django"; import { css, CSSResult, customElement, html, LitElement, property, TemplateResult } from "lit-element"; import "../../elements/Tabs"; +import "../../elements/events/ObjectChangelog"; import "../../elements/buttons/ModalButton"; import "../../elements/buttons/SpinnerButton"; import "../../elements/policies/BoundPoliciesList"; @@ -79,6 +80,15 @@ export class FlowViewPage extends LitElement {
+
+
+ + +
+
`; } }