diff --git a/web/src/admin/applications/ApplicationListPage.ts b/web/src/admin/applications/ApplicationListPage.ts index fd8306c3f..e74715e7c 100644 --- a/web/src/admin/applications/ApplicationListPage.ts +++ b/web/src/admin/applications/ApplicationListPage.ts @@ -43,6 +43,7 @@ export class ApplicationListPage extends TablePage { } checkbox = true; + clearOnRefresh = true; @property() order = "name"; diff --git a/web/src/admin/blueprints/BlueprintListPage.ts b/web/src/admin/blueprints/BlueprintListPage.ts index 188bb4be5..9fa587ded 100644 --- a/web/src/admin/blueprints/BlueprintListPage.ts +++ b/web/src/admin/blueprints/BlueprintListPage.ts @@ -58,6 +58,7 @@ export class BlueprintListPage extends TablePage { expandable = true; checkbox = true; + clearOnRefresh = true; @property() order = "name"; diff --git a/web/src/admin/crypto/CertificateKeyPairListPage.ts b/web/src/admin/crypto/CertificateKeyPairListPage.ts index c76feff3a..fd7111227 100644 --- a/web/src/admin/crypto/CertificateKeyPairListPage.ts +++ b/web/src/admin/crypto/CertificateKeyPairListPage.ts @@ -29,6 +29,7 @@ import { export class CertificateKeyPairListPage extends TablePage { expandable = true; checkbox = true; + clearOnRefresh = true; searchEnabled(): boolean { return true; diff --git a/web/src/admin/enterprise/EnterpriseLicenseListPage.ts b/web/src/admin/enterprise/EnterpriseLicenseListPage.ts index 0d2f16cf3..97790e738 100644 --- a/web/src/admin/enterprise/EnterpriseLicenseListPage.ts +++ b/web/src/admin/enterprise/EnterpriseLicenseListPage.ts @@ -35,6 +35,7 @@ import { @customElement("ak-enterprise-license-list") export class EnterpriseLicenseListPage extends TablePage { checkbox = true; + clearOnRefresh = true; searchEnabled(): boolean { return true; diff --git a/web/src/admin/events/RuleListPage.ts b/web/src/admin/events/RuleListPage.ts index e997903b1..7afe34104 100644 --- a/web/src/admin/events/RuleListPage.ts +++ b/web/src/admin/events/RuleListPage.ts @@ -27,6 +27,7 @@ import { export class RuleListPage extends TablePage { expandable = true; checkbox = true; + clearOnRefresh = true; searchEnabled(): boolean { return true; diff --git a/web/src/admin/events/TransportListPage.ts b/web/src/admin/events/TransportListPage.ts index c36c21af9..ffa4f6263 100644 --- a/web/src/admin/events/TransportListPage.ts +++ b/web/src/admin/events/TransportListPage.ts @@ -38,6 +38,7 @@ export class TransportListPage extends TablePage { } checkbox = true; + clearOnRefresh = true; @property() order = "name"; diff --git a/web/src/admin/flows/BoundStagesList.ts b/web/src/admin/flows/BoundStagesList.ts index 65eb7ec56..5eeaee779 100644 --- a/web/src/admin/flows/BoundStagesList.ts +++ b/web/src/admin/flows/BoundStagesList.ts @@ -21,6 +21,7 @@ import { FlowStageBinding, FlowsApi } from "@goauthentik/api"; export class BoundStagesList extends Table { expandable = true; checkbox = true; + clearOnRefresh = true; @property() target?: string; diff --git a/web/src/admin/flows/FlowListPage.ts b/web/src/admin/flows/FlowListPage.ts index 5bcc6205d..1e264dc92 100644 --- a/web/src/admin/flows/FlowListPage.ts +++ b/web/src/admin/flows/FlowListPage.ts @@ -37,6 +37,7 @@ export class FlowListPage extends TablePage { } checkbox = true; + clearOnRefresh = true; @property() order = "slug"; diff --git a/web/src/admin/groups/GroupListPage.ts b/web/src/admin/groups/GroupListPage.ts index c35f17f8c..2ab387b6f 100644 --- a/web/src/admin/groups/GroupListPage.ts +++ b/web/src/admin/groups/GroupListPage.ts @@ -19,6 +19,7 @@ import { CoreApi, Group } from "@goauthentik/api"; @customElement("ak-group-list") export class GroupListPage extends TablePage { checkbox = true; + clearOnRefresh = true; searchEnabled(): boolean { return true; } diff --git a/web/src/admin/groups/RelatedGroupList.ts b/web/src/admin/groups/RelatedGroupList.ts index 19adf1276..50edeea2a 100644 --- a/web/src/admin/groups/RelatedGroupList.ts +++ b/web/src/admin/groups/RelatedGroupList.ts @@ -87,6 +87,7 @@ export class RelatedGroupAdd extends Form<{ groups: string[] }> { @customElement("ak-group-related-list") export class RelatedGroupList extends Table { checkbox = true; + clearOnRefresh = true; searchEnabled(): boolean { return true; } diff --git a/web/src/admin/groups/RelatedUserList.ts b/web/src/admin/groups/RelatedUserList.ts index 5e2c6b952..b8f945d88 100644 --- a/web/src/admin/groups/RelatedUserList.ts +++ b/web/src/admin/groups/RelatedUserList.ts @@ -113,6 +113,7 @@ export class RelatedUserAdd extends Form<{ users: number[] }> { export class RelatedUserList extends WithTenantConfig(WithCapabilitiesConfig(Table)) { expandable = true; checkbox = true; + clearOnRefresh = true; searchEnabled(): boolean { return true; diff --git a/web/src/admin/outposts/OutpostListPage.ts b/web/src/admin/outposts/OutpostListPage.ts index 318355585..f583171a3 100644 --- a/web/src/admin/outposts/OutpostListPage.ts +++ b/web/src/admin/outposts/OutpostListPage.ts @@ -107,6 +107,7 @@ export class OutpostListPage extends TablePage { } checkbox = true; + clearOnRefresh = true; @property() order = "name"; diff --git a/web/src/admin/outposts/ServiceConnectionListPage.ts b/web/src/admin/outposts/ServiceConnectionListPage.ts index a212358f5..e4bea3881 100644 --- a/web/src/admin/outposts/ServiceConnectionListPage.ts +++ b/web/src/admin/outposts/ServiceConnectionListPage.ts @@ -39,6 +39,7 @@ export class OutpostServiceConnectionListPage extends TablePage> { const connections = await new OutpostsApi(DEFAULT_CONFIG).outpostsServiceConnectionsAllList( diff --git a/web/src/admin/policies/BoundPoliciesList.ts b/web/src/admin/policies/BoundPoliciesList.ts index a9cff1972..217e088e0 100644 --- a/web/src/admin/policies/BoundPoliciesList.ts +++ b/web/src/admin/policies/BoundPoliciesList.ts @@ -3,7 +3,6 @@ import "@goauthentik/admin/policies/PolicyBindingForm"; import "@goauthentik/admin/policies/PolicyWizard"; import "@goauthentik/admin/users/UserForm"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; -import { EVENT_REFRESH } from "@goauthentik/common/constants"; import { uiConfig } from "@goauthentik/common/ui/config"; import "@goauthentik/components/ak-status-label"; import { PFSize } from "@goauthentik/elements/Spinner"; @@ -30,13 +29,7 @@ export class BoundPoliciesList extends Table { policyOnly = false; checkbox = true; - - constructor() { - super(); - this.addEventListener(EVENT_REFRESH, () => { - this.selectedElements = []; - }); - } + clearOnRefresh = true; async apiEndpoint(page: number): Promise> { return new PoliciesApi(DEFAULT_CONFIG).policiesBindingsList({ diff --git a/web/src/admin/policies/PolicyListPage.ts b/web/src/admin/policies/PolicyListPage.ts index 9a1dda215..b792df211 100644 --- a/web/src/admin/policies/PolicyListPage.ts +++ b/web/src/admin/policies/PolicyListPage.ts @@ -44,6 +44,7 @@ export class PolicyListPage extends TablePage { } checkbox = true; + clearOnRefresh = true; @property() order = "name"; diff --git a/web/src/admin/policies/reputation/ReputationListPage.ts b/web/src/admin/policies/reputation/ReputationListPage.ts index 8c25f1514..6a210d826 100644 --- a/web/src/admin/policies/reputation/ReputationListPage.ts +++ b/web/src/admin/policies/reputation/ReputationListPage.ts @@ -41,6 +41,7 @@ export class ReputationListPage extends TablePage { order = "identifier"; checkbox = true; + clearOnRefresh = true; async apiEndpoint(page: number): Promise> { return new PoliciesApi(DEFAULT_CONFIG).policiesReputationScoresList({ diff --git a/web/src/admin/property-mappings/PropertyMappingListPage.ts b/web/src/admin/property-mappings/PropertyMappingListPage.ts index 18521f5e4..183aba8ff 100644 --- a/web/src/admin/property-mappings/PropertyMappingListPage.ts +++ b/web/src/admin/property-mappings/PropertyMappingListPage.ts @@ -41,6 +41,7 @@ export class PropertyMappingListPage extends TablePage { } checkbox = true; + clearOnRefresh = true; @property() order = "name"; diff --git a/web/src/admin/providers/ProviderListPage.ts b/web/src/admin/providers/ProviderListPage.ts index 87a123c82..b95e9bc80 100644 --- a/web/src/admin/providers/ProviderListPage.ts +++ b/web/src/admin/providers/ProviderListPage.ts @@ -40,6 +40,7 @@ export class ProviderListPage extends TablePage { } checkbox = true; + clearOnRefresh = true; @property() order = "name"; diff --git a/web/src/admin/providers/rac/EndpointList.ts b/web/src/admin/providers/rac/EndpointList.ts index d3c3f88c3..06a8b542d 100644 --- a/web/src/admin/providers/rac/EndpointList.ts +++ b/web/src/admin/providers/rac/EndpointList.ts @@ -27,6 +27,7 @@ import { export class EndpointListPage extends Table { expandable = true; checkbox = true; + clearOnRefresh = true; searchEnabled(): boolean { return true; diff --git a/web/src/admin/roles/RoleListPage.ts b/web/src/admin/roles/RoleListPage.ts index 328acb186..26da56f63 100644 --- a/web/src/admin/roles/RoleListPage.ts +++ b/web/src/admin/roles/RoleListPage.ts @@ -21,6 +21,7 @@ import { RbacApi, Role } from "@goauthentik/api"; @customElement("ak-role-list") export class RoleListPage extends TablePage { checkbox = true; + clearOnRefresh = true; searchEnabled(): boolean { return true; } diff --git a/web/src/admin/roles/RolePermissionGlobalTable.ts b/web/src/admin/roles/RolePermissionGlobalTable.ts index 9a302c19c..a5df36801 100644 --- a/web/src/admin/roles/RolePermissionGlobalTable.ts +++ b/web/src/admin/roles/RolePermissionGlobalTable.ts @@ -21,6 +21,7 @@ export class RolePermissionGlobalTable extends Table { } checkbox = true; + clearOnRefresh = true; order = "content_type__app_label,content_type__model"; diff --git a/web/src/admin/roles/RolePermissionObjectTable.ts b/web/src/admin/roles/RolePermissionObjectTable.ts index 44bdf1183..7a73647a0 100644 --- a/web/src/admin/roles/RolePermissionObjectTable.ts +++ b/web/src/admin/roles/RolePermissionObjectTable.ts @@ -20,6 +20,7 @@ export class RolePermissionObjectTable extends Table } checkbox = true; + clearOnRefresh = true; apiEndpoint(page: number): Promise> { return new RbacApi(DEFAULT_CONFIG).rbacPermissionsRolesList({ diff --git a/web/src/admin/sources/SourceListPage.ts b/web/src/admin/sources/SourceListPage.ts index 5e627e7c9..6d33d0fcb 100644 --- a/web/src/admin/sources/SourceListPage.ts +++ b/web/src/admin/sources/SourceListPage.ts @@ -39,6 +39,7 @@ export class SourceListPage extends TablePage { } checkbox = true; + clearOnRefresh = true; @property() order = "name"; diff --git a/web/src/admin/stages/StageListPage.ts b/web/src/admin/stages/StageListPage.ts index fb28cf42d..0271c522d 100644 --- a/web/src/admin/stages/StageListPage.ts +++ b/web/src/admin/stages/StageListPage.ts @@ -55,6 +55,7 @@ export class StageListPage extends TablePage { } checkbox = true; + clearOnRefresh = true; @property() order = "name"; diff --git a/web/src/admin/stages/invitation/InvitationListPage.ts b/web/src/admin/stages/invitation/InvitationListPage.ts index 2288b0691..cbac2d4c3 100644 --- a/web/src/admin/stages/invitation/InvitationListPage.ts +++ b/web/src/admin/stages/invitation/InvitationListPage.ts @@ -51,6 +51,7 @@ export class InvitationListPage extends TablePage { } checkbox = true; + clearOnRefresh = true; @property() order = "expires"; diff --git a/web/src/admin/stages/prompt/PromptListPage.ts b/web/src/admin/stages/prompt/PromptListPage.ts index c2b84a689..3b3a7869e 100644 --- a/web/src/admin/stages/prompt/PromptListPage.ts +++ b/web/src/admin/stages/prompt/PromptListPage.ts @@ -33,6 +33,7 @@ export class PromptListPage extends TablePage { } checkbox = true; + clearOnRefresh = true; @property() order = "name"; diff --git a/web/src/admin/tenants/TenantListPage.ts b/web/src/admin/tenants/TenantListPage.ts index 1e4cd5d8a..000cd80d1 100644 --- a/web/src/admin/tenants/TenantListPage.ts +++ b/web/src/admin/tenants/TenantListPage.ts @@ -34,6 +34,7 @@ export class TenantListPage extends TablePage { } checkbox = true; + clearOnRefresh = true; @property() order = "domain"; diff --git a/web/src/admin/tokens/TokenListPage.ts b/web/src/admin/tokens/TokenListPage.ts index 953cd17dd..dd5aee23d 100644 --- a/web/src/admin/tokens/TokenListPage.ts +++ b/web/src/admin/tokens/TokenListPage.ts @@ -42,6 +42,7 @@ export class TokenListPage extends TablePage { } checkbox = true; + clearOnRefresh = true; @property() order = "expires"; diff --git a/web/src/admin/users/UserAssignedGlobalPermissionsTable.ts b/web/src/admin/users/UserAssignedGlobalPermissionsTable.ts index 99f171c81..5dfb9abe3 100644 --- a/web/src/admin/users/UserAssignedGlobalPermissionsTable.ts +++ b/web/src/admin/users/UserAssignedGlobalPermissionsTable.ts @@ -19,6 +19,7 @@ export class UserAssignedGlobalPermissionsTable extends Table { userId?: number; checkbox = true; + clearOnRefresh = true; apiEndpoint(page: number): Promise> { return new RbacApi(DEFAULT_CONFIG).rbacPermissionsList({ diff --git a/web/src/admin/users/UserAssignedObjectPermissionsTable.ts b/web/src/admin/users/UserAssignedObjectPermissionsTable.ts index 8e63ae8bb..74cd035f3 100644 --- a/web/src/admin/users/UserAssignedObjectPermissionsTable.ts +++ b/web/src/admin/users/UserAssignedObjectPermissionsTable.ts @@ -16,6 +16,7 @@ export class UserAssignedObjectPermissionsTable extends Table> { return new RbacApi(DEFAULT_CONFIG).rbacPermissionsUsersList({ diff --git a/web/src/admin/users/UserDevicesTable.ts b/web/src/admin/users/UserDevicesTable.ts index 06ead21df..9f02e7fcd 100644 --- a/web/src/admin/users/UserDevicesTable.ts +++ b/web/src/admin/users/UserDevicesTable.ts @@ -16,6 +16,7 @@ export class UserDeviceTable extends Table { userId?: number; checkbox = true; + clearOnRefresh = true; async apiEndpoint(): Promise> { return new AuthenticatorsApi(DEFAULT_CONFIG) diff --git a/web/src/admin/users/UserListPage.ts b/web/src/admin/users/UserListPage.ts index afb88f3f6..284e7b7cc 100644 --- a/web/src/admin/users/UserListPage.ts +++ b/web/src/admin/users/UserListPage.ts @@ -94,6 +94,7 @@ const recoveryButtonStyles = css` export class UserListPage extends WithTenantConfig(WithCapabilitiesConfig(TablePage)) { expandable = true; checkbox = true; + clearOnRefresh = true; searchEnabled(): boolean { return true; diff --git a/web/src/elements/oauth/UserRefreshList.ts b/web/src/elements/oauth/UserRefreshList.ts index 2c5915f74..327ad6eaf 100644 --- a/web/src/elements/oauth/UserRefreshList.ts +++ b/web/src/elements/oauth/UserRefreshList.ts @@ -34,6 +34,7 @@ export class UserOAuthRefreshList extends Table { } checkbox = true; + clearOnRefresh = true; order = "-expires"; columns(): TableColumn[] { diff --git a/web/src/elements/rbac/RoleObjectPermissionTable.ts b/web/src/elements/rbac/RoleObjectPermissionTable.ts index ee3c2161b..0c0f4bb9e 100644 --- a/web/src/elements/rbac/RoleObjectPermissionTable.ts +++ b/web/src/elements/rbac/RoleObjectPermissionTable.ts @@ -29,6 +29,7 @@ export class RoleAssignedObjectPermissionTable extends Table> { const perms = await new RbacApi(DEFAULT_CONFIG).rbacPermissionsAssignedByRolesList({ diff --git a/web/src/elements/rbac/UserObjectPermissionTable.ts b/web/src/elements/rbac/UserObjectPermissionTable.ts index a746447cc..4361de4d4 100644 --- a/web/src/elements/rbac/UserObjectPermissionTable.ts +++ b/web/src/elements/rbac/UserObjectPermissionTable.ts @@ -29,6 +29,7 @@ export class UserAssignedObjectPermissionTable extends Table> { const perms = await new RbacApi(DEFAULT_CONFIG).rbacPermissionsAssignedByUsersList({ diff --git a/web/src/elements/table/Table.ts b/web/src/elements/table/Table.ts index 82fb9f5ae..bf9083cc5 100644 --- a/web/src/elements/table/Table.ts +++ b/web/src/elements/table/Table.ts @@ -119,6 +119,14 @@ export abstract class Table extends AKElement implements TableLike { @property({ type: Number }) page = getURLParam("tablePage", 1); + /** @prop + * + * Set if your `selectedElements` use of the selection box is to enable bulk-delete, so that + * stale data is cleared out when the API returns a new list minus the deleted entries. + */ + @property({ attribute: "clear-on-refresh", type: Boolean, reflect: true }) + clearOnRefresh = false; + @property({ type: String }) order?: string; @@ -178,8 +186,11 @@ export abstract class Table extends AKElement implements TableLike { constructor() { super(); - this.addEventListener(EVENT_REFRESH, () => { - this.fetch(); + this.addEventListener(EVENT_REFRESH, async () => { + await this.fetch(); + if (this.clearOnRefresh) { + this.selectedElements = []; + } }); } diff --git a/web/src/elements/user/SessionList.ts b/web/src/elements/user/SessionList.ts index b0861763d..c7bb548b2 100644 --- a/web/src/elements/user/SessionList.ts +++ b/web/src/elements/user/SessionList.ts @@ -25,6 +25,7 @@ export class AuthenticatedSessionList extends Table { } checkbox = true; + clearOnRefresh = true; order = "-expires"; columns(): TableColumn[] { diff --git a/web/src/elements/user/UserConsentList.ts b/web/src/elements/user/UserConsentList.ts index 56a59ebe1..22e2bb463 100644 --- a/web/src/elements/user/UserConsentList.ts +++ b/web/src/elements/user/UserConsentList.ts @@ -25,6 +25,7 @@ export class UserConsentList extends Table { } checkbox = true; + clearOnRefresh = true; order = "-expires"; columns(): TableColumn[] { diff --git a/web/src/user/user-settings/mfa/MFADevicesPage.ts b/web/src/user/user-settings/mfa/MFADevicesPage.ts index 5b26d152e..86578c920 100644 --- a/web/src/user/user-settings/mfa/MFADevicesPage.ts +++ b/web/src/user/user-settings/mfa/MFADevicesPage.ts @@ -25,6 +25,7 @@ export class MFADevicesPage extends Table { userSettings?: UserSetting[]; checkbox = true; + clearOnRefresh = true; async apiEndpoint(): Promise> { const devices = await new AuthenticatorsApi(DEFAULT_CONFIG).authenticatorsAllList(); diff --git a/web/src/user/user-settings/tokens/UserTokenList.ts b/web/src/user/user-settings/tokens/UserTokenList.ts index 82cadeee1..2760ea16d 100644 --- a/web/src/user/user-settings/tokens/UserTokenList.ts +++ b/web/src/user/user-settings/tokens/UserTokenList.ts @@ -29,6 +29,7 @@ export class UserTokenList extends Table { expandable = true; checkbox = true; + clearOnRefresh = true; @property() order = "expires";