web/elements: add bulk delete form

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
Jens Langhammer 2021-08-12 21:14:51 +02:00
parent 2592fc3826
commit 9430a2eea2
6 changed files with 317 additions and 51 deletions

View File

@ -9,6 +9,7 @@ export function me(): Promise<SessionUser> {
user: { user: {
pk: -1, pk: -1,
isSuperuser: false, isSuperuser: false,
isActive: true,
groups: [], groups: [],
avatar: "", avatar: "",
uid: "", uid: "",

View File

@ -0,0 +1,195 @@
import { t } from "@lingui/macro";
import { CSSResult, customElement, html, property, TemplateResult } from "lit-element";
import { EVENT_REFRESH } from "../../constants";
import { ModalButton } from "../buttons/ModalButton";
import { MessageLevel } from "../messages/Message";
import { showMessage } from "../messages/MessageContainer";
import "../buttons/SpinnerButton";
import { UsedBy, UsedByActionEnum } from "authentik-api";
import PFList from "@patternfly/patternfly/components/List/list.css";
import { until } from "lit-html/directives/until";
import { Table, TableColumn } from "../table/Table";
import { AKResponse } from "../../api/Client";
import { PFSize } from "../Spinner";
export interface AKObject<T extends string | number> {
pk: T;
slug?: string;
name?: string;
[key: string]: unknown;
}
@customElement("ak-delete-objects-table")
export class DeleteObjectsTable<ObjPkT extends string | number> extends Table<AKObject<ObjPkT>> {
expandable = true;
paginated = false;
@property({ attribute: false })
objects: AKObject<ObjPkT>[] = [];
@property({ attribute: false })
usedBy?: (item: AKObject<ObjPkT>) => Promise<UsedBy[]>;
static get styles(): CSSResult[] {
return super.styles.concat(PFList);
}
apiEndpoint(page: number): Promise<AKResponse<AKObject<ObjPkT>>> {
return Promise.resolve({
pagination: {
count: this.objects.length,
current: 1,
totalPages: 1,
startIndex: 1,
endIndex: this.objects.length,
},
results: this.objects,
});
}
columns(): TableColumn[] {
return [new TableColumn(t`Name`), new TableColumn(t`ID`)];
}
row(item: AKObject<ObjPkT>): TemplateResult[] {
return [html`${item.name}`, html`${item.pk}`];
}
renderToolbarContainer(): TemplateResult {
return html``;
}
renderExpanded(item: AKObject<ObjPkT>): TemplateResult {
return html`${this.usedBy
? until(
this.usedBy(item).then((usedBy) => {
return this.renderUsedBy(item, usedBy);
}),
html`<ak-spinner size=${PFSize.XLarge}></ak-spinner>`,
)
: html``}`;
}
renderUsedBy(item: AKObject<ObjPkT>, usedBy: UsedBy[]): TemplateResult {
if (usedBy.length < 1) {
return html`<td role="cell" colspan="2">
<div class="pf-c-table__expandable-row-content">
<span>${t`Not used by any other object.`}</span>
</div>
</td>`;
}
return html`<td role="cell" colspan="2">
<div class="pf-c-table__expandable-row-content">
<p>${t`The following objects use ${item.name}:`}</p>
<ul class="pf-c-list">
${usedBy.map((ub) => {
let consequence = "";
switch (ub.action) {
case UsedByActionEnum.Cascade:
consequence = t`object will be DELETED`;
break;
case UsedByActionEnum.CascadeMany:
consequence = t`connection will be deleted`;
break;
case UsedByActionEnum.SetDefault:
consequence = t`reference will be reset to default value`;
break;
case UsedByActionEnum.SetNull:
consequence = t`reference will be set to an empty value`;
break;
}
return html`<li>${t`${ub.name} (${consequence})`}</li>`;
})}
</ul>
</div>
</td> `;
}
}
@customElement("ak-forms-delete-bulk")
export class DeleteBulkForm<ObjPkT extends string | number> extends ModalButton {
@property({ attribute: false })
objects: AKObject<ObjPkT>[] = [];
@property()
objectLabel?: string;
@property({ attribute: false })
usedBy?: (itemPk: AKObject<ObjPkT>) => Promise<UsedBy[]>;
@property({ attribute: false })
delete!: (itemPk: AKObject<ObjPkT>) => Promise<unknown>;
confirm(): Promise<void> {
return Promise.all(
this.objects.map((item) => {
return this.delete(item);
}),
)
.then(() => {
this.onSuccess();
this.open = false;
this.dispatchEvent(
new CustomEvent(EVENT_REFRESH, {
bubbles: true,
composed: true,
}),
);
})
.catch((e) => {
this.onError(e);
throw e;
});
}
onSuccess(): void {
showMessage({
message: t`Successfully deleted ${this.objects.length} ${this.objectLabel}`,
level: MessageLevel.success,
});
}
onError(e: Error): void {
showMessage({
message: t`Failed to delete ${this.objectLabel}: ${e.toString()}`,
level: MessageLevel.error,
});
}
renderModalInner(): TemplateResult {
return html`<section class="pf-c-page__main-section pf-m-light">
<div class="pf-c-content">
<h1 class="pf-c-title pf-m-2xl">${t`Delete ${this.objectLabel}`}</h1>
</div>
</section>
<section class="pf-c-page__main-section pf-m-light">
<form class="pf-c-form pf-m-horizontal">
<p>
${t`Are you sure you want to delete ${this.objects.length} ${this.objectLabel}?`}
</p>
</form>
</section>
<section class="pf-c-page__main-section">
<ak-delete-objects-table .objects=${this.objects} .usedBy=${this.usedBy}>
</ak-delete-objects-table>
</section>
<footer class="pf-c-modal-box__footer">
<ak-spinner-button
.callAction=${() => {
return this.confirm();
}}
class="pf-m-danger"
>
${t`Delete`} </ak-spinner-button
>&nbsp;
<ak-spinner-button
.callAction=${async () => {
this.open = false;
}}
class="pf-m-secondary"
>
${t`Cancel`}
</ak-spinner-button>
</footer>`;
}
}

View File

@ -123,6 +123,9 @@ export abstract class Table<T> extends LitElement {
@property({ attribute: false }) @property({ attribute: false })
selectedElements: T[] = []; selectedElements: T[] = [];
@property({ type: Boolean })
paginated = true;
@property({ type: Boolean }) @property({ type: Boolean })
expandable = false; expandable = false;
@ -326,25 +329,15 @@ export abstract class Table<T> extends LitElement {
return html``; return html``;
} }
firstUpdated(): void { renderToolbarContainer(): TemplateResult {
this.fetch(); return html`<div class="pf-c-toolbar">
}
renderTable(): TemplateResult {
return html` ${this.checkbox && this.checkboxChip
? html`<ak-chip-group>
${this.selectedElements.map((el) => {
return html`<ak-chip>${this.renderSelectedChip(el)}</ak-chip>`;
})}
</ak-chip-group>`
: html``}
<div class="pf-c-toolbar">
<div class="pf-c-toolbar__content"> <div class="pf-c-toolbar__content">
<div class="pf-m-search-filter">${this.renderSearch()}</div> <div class="pf-m-search-filter">${this.renderSearch()}</div>
<div class="pf-c-toolbar__bulk-select">${this.renderToolbar()}</div> <div class="pf-c-toolbar__bulk-select">${this.renderToolbar()}</div>
<div class="pf-c-toolbar__group">${this.renderToolbarAfter()}</div> <div class="pf-c-toolbar__group">${this.renderToolbarAfter()}</div>
<div class="pf-c-toolbar__group">${this.renderToolbarSelected()}</div> <div class="pf-c-toolbar__group">${this.renderToolbarSelected()}</div>
<ak-table-pagination ${this.paginated
? html`<ak-table-pagination
class="pf-c-toolbar__item pf-m-pagination" class="pf-c-toolbar__item pf-m-pagination"
.pages=${this.data?.pagination} .pages=${this.data?.pagination}
.pageChangeHandler=${(page: number) => { .pageChangeHandler=${(page: number) => {
@ -357,9 +350,25 @@ export abstract class Table<T> extends LitElement {
); );
}} }}
> >
</ak-table-pagination> </ak-table-pagination>`
</div> : html``}
</div> </div>
</div>`;
}
firstUpdated(): void {
this.fetch();
}
renderTable(): TemplateResult {
return html` ${this.checkbox && this.checkboxChip
? html`<ak-chip-group>
${this.selectedElements.map((el) => {
return html`<ak-chip>${this.renderSelectedChip(el)}</ak-chip>`;
})}
</ak-chip-group>`
: html``}
${this.renderToolbarContainer()}
<table class="pf-c-table pf-m-compact pf-m-grid-md pf-m-expandable"> <table class="pf-c-table pf-m-compact pf-m-grid-md pf-m-expandable">
<thead> <thead>
<tr role="row"> <tr role="row">
@ -384,7 +393,8 @@ export abstract class Table<T> extends LitElement {
</thead> </thead>
${this.isLoading || !this.data ? this.renderLoading() : this.renderRows()} ${this.isLoading || !this.data ? this.renderLoading() : this.renderRows()}
</table> </table>
<div class="pf-c-pagination pf-m-bottom"> ${this.paginated
? html` <div class="pf-c-pagination pf-m-bottom">
<ak-table-pagination <ak-table-pagination
class="pf-c-toolbar__item pf-m-pagination" class="pf-c-toolbar__item pf-m-pagination"
.pages=${this.data?.pagination} .pages=${this.data?.pagination}
@ -399,7 +409,8 @@ export abstract class Table<T> extends LitElement {
}} }}
> >
</ak-table-pagination> </ak-table-pagination>
</div>`; </div>`
: html``}`;
} }
render(): TemplateResult { render(): TemplateResult {

View File

@ -280,6 +280,10 @@ msgstr ""
"Are you sure you want to clear the policy cache?\n" "Are you sure you want to clear the policy cache?\n"
"This will cause all policies to be re-evaluated on their next usage." "This will cause all policies to be re-evaluated on their next usage."
#: src/elements/forms/DeleteBulkForm.ts
msgid "Are you sure you want to delete {0} {1}?"
msgstr "Are you sure you want to delete {0} {1}?"
#: src/elements/forms/DeleteForm.ts #: src/elements/forms/DeleteForm.ts
msgid "Are you sure you want to delete {0} {objName} ?" msgid "Are you sure you want to delete {0} {objName} ?"
msgstr "Are you sure you want to delete {0} {objName} ?" msgstr "Are you sure you want to delete {0} {objName} ?"
@ -513,6 +517,7 @@ msgid "Can be in the format of 'unix://' when connecting to a local docker daemo
msgstr "Can be in the format of 'unix://' when connecting to a local docker daemon, or 'https://:2376' when connecting to a remote system." msgstr "Can be in the format of 'unix://' when connecting to a local docker daemon, or 'https://:2376' when connecting to a remote system."
#: src/elements/forms/ConfirmationForm.ts #: src/elements/forms/ConfirmationForm.ts
#: src/elements/forms/DeleteBulkForm.ts
#: src/elements/forms/DeleteForm.ts #: src/elements/forms/DeleteForm.ts
#: src/elements/forms/ModalForm.ts #: src/elements/forms/ModalForm.ts
#: src/pages/groups/MemberSelectModal.ts #: src/pages/groups/MemberSelectModal.ts
@ -1085,6 +1090,7 @@ msgstr "Default?"
msgid "Define how notifications are sent to users, like Email or Webhook." msgid "Define how notifications are sent to users, like Email or Webhook."
msgstr "Define how notifications are sent to users, like Email or Webhook." msgstr "Define how notifications are sent to users, like Email or Webhook."
#: src/elements/forms/DeleteBulkForm.ts
#: src/elements/forms/DeleteForm.ts #: src/elements/forms/DeleteForm.ts
#: src/elements/oauth/UserCodeList.ts #: src/elements/oauth/UserCodeList.ts
#: src/elements/oauth/UserRefreshList.ts #: src/elements/oauth/UserRefreshList.ts
@ -1158,6 +1164,7 @@ msgstr ""
"Delete the currently pending user. CAUTION, this stage does not ask for\n" "Delete the currently pending user. CAUTION, this stage does not ask for\n"
"confirmation. Use a consent stage to ensure the user is aware of their actions." "confirmation. Use a consent stage to ensure the user is aware of their actions."
#: src/elements/forms/DeleteBulkForm.ts
#: src/elements/forms/DeleteForm.ts #: src/elements/forms/DeleteForm.ts
msgid "Delete {0}" msgid "Delete {0}"
msgstr "Delete {0}" msgstr "Delete {0}"
@ -1599,6 +1606,7 @@ msgstr "Failed to delete flow cache"
msgid "Failed to delete policy cache" msgid "Failed to delete policy cache"
msgstr "Failed to delete policy cache" msgstr "Failed to delete policy cache"
#: src/elements/forms/DeleteBulkForm.ts
#: src/elements/forms/DeleteForm.ts #: src/elements/forms/DeleteForm.ts
msgid "Failed to delete {0}: {1}" msgid "Failed to delete {0}: {1}"
msgstr "Failed to delete {0}: {1}" msgstr "Failed to delete {0}: {1}"
@ -1880,6 +1888,7 @@ msgstr "Hold control/command to select multiple items."
msgid "How many attempts a user has before the flow is canceled. To lock the user out, use a reputation policy and a user_write stage." msgid "How many attempts a user has before the flow is canceled. To lock the user out, use a reputation policy and a user_write stage."
msgstr "How many attempts a user has before the flow is canceled. To lock the user out, use a reputation policy and a user_write stage." msgstr "How many attempts a user has before the flow is canceled. To lock the user out, use a reputation policy and a user_write stage."
#: src/elements/forms/DeleteBulkForm.ts
#: src/pages/stages/invitation/InvitationListPage.ts #: src/pages/stages/invitation/InvitationListPage.ts
msgid "ID" msgid "ID"
msgstr "ID" msgstr "ID"
@ -2407,6 +2416,7 @@ msgstr "Monitor"
msgid "My Applications" msgid "My Applications"
msgstr "My Applications" msgstr "My Applications"
#: src/elements/forms/DeleteBulkForm.ts
#: src/pages/applications/ApplicationForm.ts #: src/pages/applications/ApplicationForm.ts
#: src/pages/applications/ApplicationListPage.ts #: src/pages/applications/ApplicationListPage.ts
#: src/pages/crypto/CertificateKeyPairForm.ts #: src/pages/crypto/CertificateKeyPairForm.ts
@ -2608,6 +2618,10 @@ msgstr "Not found"
msgid "Not synced yet." msgid "Not synced yet."
msgstr "Not synced yet." msgstr "Not synced yet."
#: src/elements/forms/DeleteBulkForm.ts
msgid "Not used by any other object."
msgstr "Not used by any other object."
#: src/flows/stages/authenticator_duo/AuthenticatorDuoStage.ts #: src/flows/stages/authenticator_duo/AuthenticatorDuoStage.ts
#: src/flows/stages/authenticator_static/AuthenticatorStaticStage.ts #: src/flows/stages/authenticator_static/AuthenticatorStaticStage.ts
#: src/flows/stages/authenticator_totp/AuthenticatorTOTPStage.ts #: src/flows/stages/authenticator_totp/AuthenticatorTOTPStage.ts
@ -3839,6 +3853,7 @@ msgstr "Successfully created transport."
msgid "Successfully created user." msgid "Successfully created user."
msgstr "Successfully created user." msgstr "Successfully created user."
#: src/elements/forms/DeleteBulkForm.ts
#: src/elements/forms/DeleteForm.ts #: src/elements/forms/DeleteForm.ts
msgid "Successfully deleted {0} {1}" msgid "Successfully deleted {0} {1}"
msgstr "Successfully deleted {0} {1}" msgstr "Successfully deleted {0} {1}"
@ -4132,6 +4147,10 @@ msgstr "The external URL you'll access the application at. Include any non-stand
msgid "The external URL you'll authenticate at. Can be the same domain as authentik." msgid "The external URL you'll authenticate at. Can be the same domain as authentik."
msgstr "The external URL you'll authenticate at. Can be the same domain as authentik." msgstr "The external URL you'll authenticate at. Can be the same domain as authentik."
#: src/elements/forms/DeleteBulkForm.ts
msgid "The following objects use {0}:"
msgstr "The following objects use {0}:"
#: src/elements/forms/DeleteForm.ts #: src/elements/forms/DeleteForm.ts
msgid "The following objects use {objName}" msgid "The following objects use {objName}"
msgstr "The following objects use {objName}" msgstr "The following objects use {objName}"
@ -4596,7 +4615,6 @@ msgstr "Use this tenant for each domain that doesn't have a dedicated tenant."
#: src/pages/tokens/TokenListPage.ts #: src/pages/tokens/TokenListPage.ts
#: src/pages/user-settings/tokens/UserTokenList.ts #: src/pages/user-settings/tokens/UserTokenList.ts
#: src/pages/users/UserListPage.ts #: src/pages/users/UserListPage.ts
#: src/pages/users/UserListPage.ts
msgid "User" msgid "User"
msgstr "User" msgstr "User"
@ -4664,6 +4682,10 @@ msgstr "User's avatar"
msgid "User's display name." msgid "User's display name."
msgstr "User's display name." msgstr "User's display name."
#: src/pages/users/UserListPage.ts
msgid "User(s)"
msgstr "User(s)"
#: src/pages/providers/proxy/ProxyProviderForm.ts #: src/pages/providers/proxy/ProxyProviderForm.ts
msgid "User/Group Attribute used for the password part of the HTTP-Basic Header." msgid "User/Group Attribute used for the password part of the HTTP-Basic Header."
msgstr "User/Group Attribute used for the password part of the HTTP-Basic Header." msgstr "User/Group Attribute used for the password part of the HTTP-Basic Header."
@ -4906,18 +4928,25 @@ msgstr "authentik LDAP Backend"
msgid "connecting object will be deleted" msgid "connecting object will be deleted"
msgstr "connecting object will be deleted" msgstr "connecting object will be deleted"
#: src/elements/forms/DeleteBulkForm.ts
msgid "connection will be deleted"
msgstr "connection will be deleted"
#: src/elements/Tabs.ts #: src/elements/Tabs.ts
msgid "no tabs defined" msgid "no tabs defined"
msgstr "no tabs defined" msgstr "no tabs defined"
#: src/elements/forms/DeleteBulkForm.ts
#: src/elements/forms/DeleteForm.ts #: src/elements/forms/DeleteForm.ts
msgid "object will be DELETED" msgid "object will be DELETED"
msgstr "object will be DELETED" msgstr "object will be DELETED"
#: src/elements/forms/DeleteBulkForm.ts
#: src/elements/forms/DeleteForm.ts #: src/elements/forms/DeleteForm.ts
msgid "reference will be reset to default value" msgid "reference will be reset to default value"
msgstr "reference will be reset to default value" msgstr "reference will be reset to default value"
#: src/elements/forms/DeleteBulkForm.ts
#: src/elements/forms/DeleteForm.ts #: src/elements/forms/DeleteForm.ts
msgid "reference will be set to an empty value" msgid "reference will be set to an empty value"
msgstr "reference will be set to an empty value" msgstr "reference will be set to an empty value"
@ -4935,6 +4964,7 @@ msgstr "{0} (\"{1}\", of type {2})"
msgid "{0} ({1})" msgid "{0} ({1})"
msgstr "{0} ({1})" msgstr "{0} ({1})"
#: src/elements/forms/DeleteBulkForm.ts
#: src/elements/forms/DeleteForm.ts #: src/elements/forms/DeleteForm.ts
msgid "{0} ({consequence})" msgid "{0} ({consequence})"
msgstr "{0} ({consequence})" msgstr "{0} ({consequence})"

View File

@ -276,6 +276,10 @@ msgid ""
"This will cause all policies to be re-evaluated on their next usage." "This will cause all policies to be re-evaluated on their next usage."
msgstr "" msgstr ""
#: src/elements/forms/DeleteBulkForm.ts
msgid "Are you sure you want to delete {0} {1}?"
msgstr ""
#: src/elements/forms/DeleteForm.ts #: src/elements/forms/DeleteForm.ts
msgid "Are you sure you want to delete {0} {objName} ?" msgid "Are you sure you want to delete {0} {objName} ?"
msgstr "" msgstr ""
@ -509,6 +513,7 @@ msgid "Can be in the format of 'unix://' when connecting to a local docker daemo
msgstr "" msgstr ""
#: src/elements/forms/ConfirmationForm.ts #: src/elements/forms/ConfirmationForm.ts
#: src/elements/forms/DeleteBulkForm.ts
#: src/elements/forms/DeleteForm.ts #: src/elements/forms/DeleteForm.ts
#: src/elements/forms/ModalForm.ts #: src/elements/forms/ModalForm.ts
#: src/pages/groups/MemberSelectModal.ts #: src/pages/groups/MemberSelectModal.ts
@ -1079,6 +1084,7 @@ msgstr ""
msgid "Define how notifications are sent to users, like Email or Webhook." msgid "Define how notifications are sent to users, like Email or Webhook."
msgstr "" msgstr ""
#: src/elements/forms/DeleteBulkForm.ts
#: src/elements/forms/DeleteForm.ts #: src/elements/forms/DeleteForm.ts
#: src/elements/oauth/UserCodeList.ts #: src/elements/oauth/UserCodeList.ts
#: src/elements/oauth/UserRefreshList.ts #: src/elements/oauth/UserRefreshList.ts
@ -1150,6 +1156,7 @@ msgid ""
"confirmation. Use a consent stage to ensure the user is aware of their actions." "confirmation. Use a consent stage to ensure the user is aware of their actions."
msgstr "" msgstr ""
#: src/elements/forms/DeleteBulkForm.ts
#: src/elements/forms/DeleteForm.ts #: src/elements/forms/DeleteForm.ts
msgid "Delete {0}" msgid "Delete {0}"
msgstr "" msgstr ""
@ -1591,6 +1598,7 @@ msgstr ""
msgid "Failed to delete policy cache" msgid "Failed to delete policy cache"
msgstr "" msgstr ""
#: src/elements/forms/DeleteBulkForm.ts
#: src/elements/forms/DeleteForm.ts #: src/elements/forms/DeleteForm.ts
msgid "Failed to delete {0}: {1}" msgid "Failed to delete {0}: {1}"
msgstr "" msgstr ""
@ -1872,6 +1880,7 @@ msgstr ""
msgid "How many attempts a user has before the flow is canceled. To lock the user out, use a reputation policy and a user_write stage." msgid "How many attempts a user has before the flow is canceled. To lock the user out, use a reputation policy and a user_write stage."
msgstr "" msgstr ""
#: src/elements/forms/DeleteBulkForm.ts
#: src/pages/stages/invitation/InvitationListPage.ts #: src/pages/stages/invitation/InvitationListPage.ts
msgid "ID" msgid "ID"
msgstr "" msgstr ""
@ -2399,6 +2408,7 @@ msgstr ""
msgid "My Applications" msgid "My Applications"
msgstr "" msgstr ""
#: src/elements/forms/DeleteBulkForm.ts
#: src/pages/applications/ApplicationForm.ts #: src/pages/applications/ApplicationForm.ts
#: src/pages/applications/ApplicationListPage.ts #: src/pages/applications/ApplicationListPage.ts
#: src/pages/crypto/CertificateKeyPairForm.ts #: src/pages/crypto/CertificateKeyPairForm.ts
@ -2600,6 +2610,10 @@ msgstr ""
msgid "Not synced yet." msgid "Not synced yet."
msgstr "" msgstr ""
#: src/elements/forms/DeleteBulkForm.ts
msgid "Not used by any other object."
msgstr ""
#: src/flows/stages/authenticator_duo/AuthenticatorDuoStage.ts #: src/flows/stages/authenticator_duo/AuthenticatorDuoStage.ts
#: src/flows/stages/authenticator_static/AuthenticatorStaticStage.ts #: src/flows/stages/authenticator_static/AuthenticatorStaticStage.ts
#: src/flows/stages/authenticator_totp/AuthenticatorTOTPStage.ts #: src/flows/stages/authenticator_totp/AuthenticatorTOTPStage.ts
@ -3831,6 +3845,7 @@ msgstr ""
msgid "Successfully created user." msgid "Successfully created user."
msgstr "" msgstr ""
#: src/elements/forms/DeleteBulkForm.ts
#: src/elements/forms/DeleteForm.ts #: src/elements/forms/DeleteForm.ts
msgid "Successfully deleted {0} {1}" msgid "Successfully deleted {0} {1}"
msgstr "" msgstr ""
@ -4124,6 +4139,10 @@ msgstr ""
msgid "The external URL you'll authenticate at. Can be the same domain as authentik." msgid "The external URL you'll authenticate at. Can be the same domain as authentik."
msgstr "" msgstr ""
#: src/elements/forms/DeleteBulkForm.ts
msgid "The following objects use {0}:"
msgstr ""
#: src/elements/forms/DeleteForm.ts #: src/elements/forms/DeleteForm.ts
msgid "The following objects use {objName}" msgid "The following objects use {objName}"
msgstr "" msgstr ""
@ -4581,7 +4600,6 @@ msgstr ""
#: src/pages/tokens/TokenListPage.ts #: src/pages/tokens/TokenListPage.ts
#: src/pages/user-settings/tokens/UserTokenList.ts #: src/pages/user-settings/tokens/UserTokenList.ts
#: src/pages/users/UserListPage.ts #: src/pages/users/UserListPage.ts
#: src/pages/users/UserListPage.ts
msgid "User" msgid "User"
msgstr "" msgstr ""
@ -4649,6 +4667,10 @@ msgstr ""
msgid "User's display name." msgid "User's display name."
msgstr "" msgstr ""
#: src/pages/users/UserListPage.ts
msgid "User(s)"
msgstr ""
#: src/pages/providers/proxy/ProxyProviderForm.ts #: src/pages/providers/proxy/ProxyProviderForm.ts
msgid "User/Group Attribute used for the password part of the HTTP-Basic Header." msgid "User/Group Attribute used for the password part of the HTTP-Basic Header."
msgstr "" msgstr ""
@ -4889,18 +4911,25 @@ msgstr ""
msgid "connecting object will be deleted" msgid "connecting object will be deleted"
msgstr "" msgstr ""
#: src/elements/forms/DeleteBulkForm.ts
msgid "connection will be deleted"
msgstr ""
#: src/elements/Tabs.ts #: src/elements/Tabs.ts
msgid "no tabs defined" msgid "no tabs defined"
msgstr "" msgstr ""
#: src/elements/forms/DeleteBulkForm.ts
#: src/elements/forms/DeleteForm.ts #: src/elements/forms/DeleteForm.ts
msgid "object will be DELETED" msgid "object will be DELETED"
msgstr "" msgstr ""
#: src/elements/forms/DeleteBulkForm.ts
#: src/elements/forms/DeleteForm.ts #: src/elements/forms/DeleteForm.ts
msgid "reference will be reset to default value" msgid "reference will be reset to default value"
msgstr "" msgstr ""
#: src/elements/forms/DeleteBulkForm.ts
#: src/elements/forms/DeleteForm.ts #: src/elements/forms/DeleteForm.ts
msgid "reference will be set to an empty value" msgid "reference will be set to an empty value"
msgstr "" msgstr ""
@ -4918,6 +4947,7 @@ msgstr ""
msgid "{0} ({1})" msgid "{0} ({1})"
msgstr "" msgstr ""
#: src/elements/forms/DeleteBulkForm.ts
#: src/elements/forms/DeleteForm.ts #: src/elements/forms/DeleteForm.ts
msgid "{0} ({consequence})" msgid "{0} ({consequence})"
msgstr "" msgstr ""

View File

@ -10,7 +10,7 @@ import { TableColumn } from "../../elements/table/Table";
import { PAGE_SIZE } from "../../constants"; import { PAGE_SIZE } from "../../constants";
import { CoreApi, User } from "authentik-api"; import { CoreApi, User } from "authentik-api";
import { DEFAULT_CONFIG, tenant } from "../../api/Config"; import { DEFAULT_CONFIG, tenant } from "../../api/Config";
import "../../elements/forms/DeleteForm"; import "../../elements/forms/DeleteBulkForm";
import "./UserActiveForm"; import "./UserActiveForm";
import "./UserForm"; import "./UserForm";
import "./UserResetEmailForm"; import "./UserResetEmailForm";
@ -71,26 +71,25 @@ export class UserListPage extends TablePage<User> {
} }
renderToolbarSelected(): TemplateResult { renderToolbarSelected(): TemplateResult {
const disabled = this.selectedElements.length !== 1; const disabled = this.selectedElements.length < 1;
const item = this.selectedElements[0]; return html` <ak-forms-delete-bulk
return html` <ak-forms-delete objectLabel=${t`User(s)`}
.obj=${item} .objects=${this.selectedElements}
objectLabel=${t`User`} .usedBy=${(itemPk: number) => {
.usedBy=${() => {
return new CoreApi(DEFAULT_CONFIG).coreUsersUsedByList({ return new CoreApi(DEFAULT_CONFIG).coreUsersUsedByList({
id: item.pk, id: itemPk,
}); });
}} }}
.delete=${() => { .delete=${(itemPk: number) => {
return new CoreApi(DEFAULT_CONFIG).coreUsersDestroy({ return new CoreApi(DEFAULT_CONFIG).coreUsersDestroy({
id: item.pk, id: itemPk,
}); });
}} }}
> >
<button ?disabled=${disabled} slot="trigger" class="pf-c-button pf-m-danger"> <button ?disabled=${disabled} slot="trigger" class="pf-c-button pf-m-danger">
${t`Delete`} ${t`Delete`}
</button> </button>
</ak-forms-delete>`; </ak-forms-delete-bulk>`;
} }
row(item: User): TemplateResult[] { row(item: User): TemplateResult[] {