web: A better fix
This fix creates a new property of Table, 'clearOnRefresh', which automatically empties the `selectedElements` list when an EVENT_REFRESH event completes. Set this flag on any table that uses the `selectedElements` list for bulk deletion; this ensures that stale data in the `selectedElements` list will not persist and interfere with future deletion events.
This commit is contained in:
parent
7bb30bea55
commit
078fe8ef06
|
@ -43,6 +43,7 @@ export class ApplicationListPage extends TablePage<Application> {
|
||||||
}
|
}
|
||||||
|
|
||||||
checkbox = true;
|
checkbox = true;
|
||||||
|
clearOnRefresh = true;
|
||||||
|
|
||||||
@property()
|
@property()
|
||||||
order = "name";
|
order = "name";
|
||||||
|
|
|
@ -58,6 +58,7 @@ export class BlueprintListPage extends TablePage<BlueprintInstance> {
|
||||||
|
|
||||||
expandable = true;
|
expandable = true;
|
||||||
checkbox = true;
|
checkbox = true;
|
||||||
|
clearOnRefresh = true;
|
||||||
|
|
||||||
@property()
|
@property()
|
||||||
order = "name";
|
order = "name";
|
||||||
|
|
|
@ -29,6 +29,7 @@ import {
|
||||||
export class CertificateKeyPairListPage extends TablePage<CertificateKeyPair> {
|
export class CertificateKeyPairListPage extends TablePage<CertificateKeyPair> {
|
||||||
expandable = true;
|
expandable = true;
|
||||||
checkbox = true;
|
checkbox = true;
|
||||||
|
clearOnRefresh = true;
|
||||||
|
|
||||||
searchEnabled(): boolean {
|
searchEnabled(): boolean {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -35,6 +35,7 @@ import {
|
||||||
@customElement("ak-enterprise-license-list")
|
@customElement("ak-enterprise-license-list")
|
||||||
export class EnterpriseLicenseListPage extends TablePage<License> {
|
export class EnterpriseLicenseListPage extends TablePage<License> {
|
||||||
checkbox = true;
|
checkbox = true;
|
||||||
|
clearOnRefresh = true;
|
||||||
|
|
||||||
searchEnabled(): boolean {
|
searchEnabled(): boolean {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -27,6 +27,7 @@ import {
|
||||||
export class RuleListPage extends TablePage<NotificationRule> {
|
export class RuleListPage extends TablePage<NotificationRule> {
|
||||||
expandable = true;
|
expandable = true;
|
||||||
checkbox = true;
|
checkbox = true;
|
||||||
|
clearOnRefresh = true;
|
||||||
|
|
||||||
searchEnabled(): boolean {
|
searchEnabled(): boolean {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -38,6 +38,7 @@ export class TransportListPage extends TablePage<NotificationTransport> {
|
||||||
}
|
}
|
||||||
|
|
||||||
checkbox = true;
|
checkbox = true;
|
||||||
|
clearOnRefresh = true;
|
||||||
|
|
||||||
@property()
|
@property()
|
||||||
order = "name";
|
order = "name";
|
||||||
|
|
|
@ -21,6 +21,7 @@ import { FlowStageBinding, FlowsApi } from "@goauthentik/api";
|
||||||
export class BoundStagesList extends Table<FlowStageBinding> {
|
export class BoundStagesList extends Table<FlowStageBinding> {
|
||||||
expandable = true;
|
expandable = true;
|
||||||
checkbox = true;
|
checkbox = true;
|
||||||
|
clearOnRefresh = true;
|
||||||
|
|
||||||
@property()
|
@property()
|
||||||
target?: string;
|
target?: string;
|
||||||
|
|
|
@ -37,6 +37,7 @@ export class FlowListPage extends TablePage<Flow> {
|
||||||
}
|
}
|
||||||
|
|
||||||
checkbox = true;
|
checkbox = true;
|
||||||
|
clearOnRefresh = true;
|
||||||
|
|
||||||
@property()
|
@property()
|
||||||
order = "slug";
|
order = "slug";
|
||||||
|
|
|
@ -19,6 +19,7 @@ import { CoreApi, Group } from "@goauthentik/api";
|
||||||
@customElement("ak-group-list")
|
@customElement("ak-group-list")
|
||||||
export class GroupListPage extends TablePage<Group> {
|
export class GroupListPage extends TablePage<Group> {
|
||||||
checkbox = true;
|
checkbox = true;
|
||||||
|
clearOnRefresh = true;
|
||||||
searchEnabled(): boolean {
|
searchEnabled(): boolean {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,6 +87,7 @@ export class RelatedGroupAdd extends Form<{ groups: string[] }> {
|
||||||
@customElement("ak-group-related-list")
|
@customElement("ak-group-related-list")
|
||||||
export class RelatedGroupList extends Table<Group> {
|
export class RelatedGroupList extends Table<Group> {
|
||||||
checkbox = true;
|
checkbox = true;
|
||||||
|
clearOnRefresh = true;
|
||||||
searchEnabled(): boolean {
|
searchEnabled(): boolean {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -113,6 +113,7 @@ export class RelatedUserAdd extends Form<{ users: number[] }> {
|
||||||
export class RelatedUserList extends WithTenantConfig(WithCapabilitiesConfig(Table<User>)) {
|
export class RelatedUserList extends WithTenantConfig(WithCapabilitiesConfig(Table<User>)) {
|
||||||
expandable = true;
|
expandable = true;
|
||||||
checkbox = true;
|
checkbox = true;
|
||||||
|
clearOnRefresh = true;
|
||||||
|
|
||||||
searchEnabled(): boolean {
|
searchEnabled(): boolean {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -107,6 +107,7 @@ export class OutpostListPage extends TablePage<Outpost> {
|
||||||
}
|
}
|
||||||
|
|
||||||
checkbox = true;
|
checkbox = true;
|
||||||
|
clearOnRefresh = true;
|
||||||
|
|
||||||
@property()
|
@property()
|
||||||
order = "name";
|
order = "name";
|
||||||
|
|
|
@ -39,6 +39,7 @@ export class OutpostServiceConnectionListPage extends TablePage<ServiceConnectio
|
||||||
}
|
}
|
||||||
|
|
||||||
checkbox = true;
|
checkbox = true;
|
||||||
|
clearOnRefresh = true;
|
||||||
|
|
||||||
async apiEndpoint(page: number): Promise<PaginatedResponse<ServiceConnection>> {
|
async apiEndpoint(page: number): Promise<PaginatedResponse<ServiceConnection>> {
|
||||||
const connections = await new OutpostsApi(DEFAULT_CONFIG).outpostsServiceConnectionsAllList(
|
const connections = await new OutpostsApi(DEFAULT_CONFIG).outpostsServiceConnectionsAllList(
|
||||||
|
|
|
@ -3,7 +3,6 @@ import "@goauthentik/admin/policies/PolicyBindingForm";
|
||||||
import "@goauthentik/admin/policies/PolicyWizard";
|
import "@goauthentik/admin/policies/PolicyWizard";
|
||||||
import "@goauthentik/admin/users/UserForm";
|
import "@goauthentik/admin/users/UserForm";
|
||||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||||
import { EVENT_REFRESH } from "@goauthentik/common/constants";
|
|
||||||
import { uiConfig } from "@goauthentik/common/ui/config";
|
import { uiConfig } from "@goauthentik/common/ui/config";
|
||||||
import "@goauthentik/components/ak-status-label";
|
import "@goauthentik/components/ak-status-label";
|
||||||
import { PFSize } from "@goauthentik/elements/Spinner";
|
import { PFSize } from "@goauthentik/elements/Spinner";
|
||||||
|
@ -30,13 +29,7 @@ export class BoundPoliciesList extends Table<PolicyBinding> {
|
||||||
policyOnly = false;
|
policyOnly = false;
|
||||||
|
|
||||||
checkbox = true;
|
checkbox = true;
|
||||||
|
clearOnRefresh = true;
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
this.addEventListener(EVENT_REFRESH, () => {
|
|
||||||
this.selectedElements = [];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async apiEndpoint(page: number): Promise<PaginatedResponse<PolicyBinding>> {
|
async apiEndpoint(page: number): Promise<PaginatedResponse<PolicyBinding>> {
|
||||||
return new PoliciesApi(DEFAULT_CONFIG).policiesBindingsList({
|
return new PoliciesApi(DEFAULT_CONFIG).policiesBindingsList({
|
||||||
|
|
|
@ -44,6 +44,7 @@ export class PolicyListPage extends TablePage<Policy> {
|
||||||
}
|
}
|
||||||
|
|
||||||
checkbox = true;
|
checkbox = true;
|
||||||
|
clearOnRefresh = true;
|
||||||
|
|
||||||
@property()
|
@property()
|
||||||
order = "name";
|
order = "name";
|
||||||
|
|
|
@ -41,6 +41,7 @@ export class ReputationListPage extends TablePage<Reputation> {
|
||||||
order = "identifier";
|
order = "identifier";
|
||||||
|
|
||||||
checkbox = true;
|
checkbox = true;
|
||||||
|
clearOnRefresh = true;
|
||||||
|
|
||||||
async apiEndpoint(page: number): Promise<PaginatedResponse<Reputation>> {
|
async apiEndpoint(page: number): Promise<PaginatedResponse<Reputation>> {
|
||||||
return new PoliciesApi(DEFAULT_CONFIG).policiesReputationScoresList({
|
return new PoliciesApi(DEFAULT_CONFIG).policiesReputationScoresList({
|
||||||
|
|
|
@ -41,6 +41,7 @@ export class PropertyMappingListPage extends TablePage<PropertyMapping> {
|
||||||
}
|
}
|
||||||
|
|
||||||
checkbox = true;
|
checkbox = true;
|
||||||
|
clearOnRefresh = true;
|
||||||
|
|
||||||
@property()
|
@property()
|
||||||
order = "name";
|
order = "name";
|
||||||
|
|
|
@ -40,6 +40,7 @@ export class ProviderListPage extends TablePage<Provider> {
|
||||||
}
|
}
|
||||||
|
|
||||||
checkbox = true;
|
checkbox = true;
|
||||||
|
clearOnRefresh = true;
|
||||||
|
|
||||||
@property()
|
@property()
|
||||||
order = "name";
|
order = "name";
|
||||||
|
|
|
@ -27,6 +27,7 @@ import {
|
||||||
export class EndpointListPage extends Table<Endpoint> {
|
export class EndpointListPage extends Table<Endpoint> {
|
||||||
expandable = true;
|
expandable = true;
|
||||||
checkbox = true;
|
checkbox = true;
|
||||||
|
clearOnRefresh = true;
|
||||||
|
|
||||||
searchEnabled(): boolean {
|
searchEnabled(): boolean {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -21,6 +21,7 @@ import { RbacApi, Role } from "@goauthentik/api";
|
||||||
@customElement("ak-role-list")
|
@customElement("ak-role-list")
|
||||||
export class RoleListPage extends TablePage<Role> {
|
export class RoleListPage extends TablePage<Role> {
|
||||||
checkbox = true;
|
checkbox = true;
|
||||||
|
clearOnRefresh = true;
|
||||||
searchEnabled(): boolean {
|
searchEnabled(): boolean {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ export class RolePermissionGlobalTable extends Table<Permission> {
|
||||||
}
|
}
|
||||||
|
|
||||||
checkbox = true;
|
checkbox = true;
|
||||||
|
clearOnRefresh = true;
|
||||||
|
|
||||||
order = "content_type__app_label,content_type__model";
|
order = "content_type__app_label,content_type__model";
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ export class RolePermissionObjectTable extends Table<ExtraRoleObjectPermission>
|
||||||
}
|
}
|
||||||
|
|
||||||
checkbox = true;
|
checkbox = true;
|
||||||
|
clearOnRefresh = true;
|
||||||
|
|
||||||
apiEndpoint(page: number): Promise<PaginatedResponse<ExtraRoleObjectPermission>> {
|
apiEndpoint(page: number): Promise<PaginatedResponse<ExtraRoleObjectPermission>> {
|
||||||
return new RbacApi(DEFAULT_CONFIG).rbacPermissionsRolesList({
|
return new RbacApi(DEFAULT_CONFIG).rbacPermissionsRolesList({
|
||||||
|
|
|
@ -39,6 +39,7 @@ export class SourceListPage extends TablePage<Source> {
|
||||||
}
|
}
|
||||||
|
|
||||||
checkbox = true;
|
checkbox = true;
|
||||||
|
clearOnRefresh = true;
|
||||||
|
|
||||||
@property()
|
@property()
|
||||||
order = "name";
|
order = "name";
|
||||||
|
|
|
@ -55,6 +55,7 @@ export class StageListPage extends TablePage<Stage> {
|
||||||
}
|
}
|
||||||
|
|
||||||
checkbox = true;
|
checkbox = true;
|
||||||
|
clearOnRefresh = true;
|
||||||
|
|
||||||
@property()
|
@property()
|
||||||
order = "name";
|
order = "name";
|
||||||
|
|
|
@ -51,6 +51,7 @@ export class InvitationListPage extends TablePage<Invitation> {
|
||||||
}
|
}
|
||||||
|
|
||||||
checkbox = true;
|
checkbox = true;
|
||||||
|
clearOnRefresh = true;
|
||||||
|
|
||||||
@property()
|
@property()
|
||||||
order = "expires";
|
order = "expires";
|
||||||
|
|
|
@ -33,6 +33,7 @@ export class PromptListPage extends TablePage<Prompt> {
|
||||||
}
|
}
|
||||||
|
|
||||||
checkbox = true;
|
checkbox = true;
|
||||||
|
clearOnRefresh = true;
|
||||||
|
|
||||||
@property()
|
@property()
|
||||||
order = "name";
|
order = "name";
|
||||||
|
|
|
@ -34,6 +34,7 @@ export class TenantListPage extends TablePage<Tenant> {
|
||||||
}
|
}
|
||||||
|
|
||||||
checkbox = true;
|
checkbox = true;
|
||||||
|
clearOnRefresh = true;
|
||||||
|
|
||||||
@property()
|
@property()
|
||||||
order = "domain";
|
order = "domain";
|
||||||
|
|
|
@ -42,6 +42,7 @@ export class TokenListPage extends TablePage<Token> {
|
||||||
}
|
}
|
||||||
|
|
||||||
checkbox = true;
|
checkbox = true;
|
||||||
|
clearOnRefresh = true;
|
||||||
|
|
||||||
@property()
|
@property()
|
||||||
order = "expires";
|
order = "expires";
|
||||||
|
|
|
@ -19,6 +19,7 @@ export class UserAssignedGlobalPermissionsTable extends Table<Permission> {
|
||||||
userId?: number;
|
userId?: number;
|
||||||
|
|
||||||
checkbox = true;
|
checkbox = true;
|
||||||
|
clearOnRefresh = true;
|
||||||
|
|
||||||
apiEndpoint(page: number): Promise<PaginatedResponse<Permission>> {
|
apiEndpoint(page: number): Promise<PaginatedResponse<Permission>> {
|
||||||
return new RbacApi(DEFAULT_CONFIG).rbacPermissionsList({
|
return new RbacApi(DEFAULT_CONFIG).rbacPermissionsList({
|
||||||
|
|
|
@ -16,6 +16,7 @@ export class UserAssignedObjectPermissionsTable extends Table<ExtraUserObjectPer
|
||||||
userId?: number;
|
userId?: number;
|
||||||
|
|
||||||
checkbox = true;
|
checkbox = true;
|
||||||
|
clearOnRefresh = true;
|
||||||
|
|
||||||
apiEndpoint(page: number): Promise<PaginatedResponse<ExtraUserObjectPermission>> {
|
apiEndpoint(page: number): Promise<PaginatedResponse<ExtraUserObjectPermission>> {
|
||||||
return new RbacApi(DEFAULT_CONFIG).rbacPermissionsUsersList({
|
return new RbacApi(DEFAULT_CONFIG).rbacPermissionsUsersList({
|
||||||
|
|
|
@ -16,6 +16,7 @@ export class UserDeviceTable extends Table<Device> {
|
||||||
userId?: number;
|
userId?: number;
|
||||||
|
|
||||||
checkbox = true;
|
checkbox = true;
|
||||||
|
clearOnRefresh = true;
|
||||||
|
|
||||||
async apiEndpoint(): Promise<PaginatedResponse<Device>> {
|
async apiEndpoint(): Promise<PaginatedResponse<Device>> {
|
||||||
return new AuthenticatorsApi(DEFAULT_CONFIG)
|
return new AuthenticatorsApi(DEFAULT_CONFIG)
|
||||||
|
|
|
@ -94,6 +94,7 @@ const recoveryButtonStyles = css`
|
||||||
export class UserListPage extends WithTenantConfig(WithCapabilitiesConfig(TablePage<User>)) {
|
export class UserListPage extends WithTenantConfig(WithCapabilitiesConfig(TablePage<User>)) {
|
||||||
expandable = true;
|
expandable = true;
|
||||||
checkbox = true;
|
checkbox = true;
|
||||||
|
clearOnRefresh = true;
|
||||||
|
|
||||||
searchEnabled(): boolean {
|
searchEnabled(): boolean {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -34,6 +34,7 @@ export class UserOAuthRefreshList extends Table<TokenModel> {
|
||||||
}
|
}
|
||||||
|
|
||||||
checkbox = true;
|
checkbox = true;
|
||||||
|
clearOnRefresh = true;
|
||||||
order = "-expires";
|
order = "-expires";
|
||||||
|
|
||||||
columns(): TableColumn[] {
|
columns(): TableColumn[] {
|
||||||
|
|
|
@ -29,6 +29,7 @@ export class RoleAssignedObjectPermissionTable extends Table<RoleAssignedObjectP
|
||||||
modelPermissions?: PaginatedPermissionList;
|
modelPermissions?: PaginatedPermissionList;
|
||||||
|
|
||||||
checkbox = true;
|
checkbox = true;
|
||||||
|
clearOnRefresh = true;
|
||||||
|
|
||||||
async apiEndpoint(page: number): Promise<PaginatedResponse<RoleAssignedObjectPermission>> {
|
async apiEndpoint(page: number): Promise<PaginatedResponse<RoleAssignedObjectPermission>> {
|
||||||
const perms = await new RbacApi(DEFAULT_CONFIG).rbacPermissionsAssignedByRolesList({
|
const perms = await new RbacApi(DEFAULT_CONFIG).rbacPermissionsAssignedByRolesList({
|
||||||
|
|
|
@ -29,6 +29,7 @@ export class UserAssignedObjectPermissionTable extends Table<UserAssignedObjectP
|
||||||
modelPermissions?: PaginatedPermissionList;
|
modelPermissions?: PaginatedPermissionList;
|
||||||
|
|
||||||
checkbox = true;
|
checkbox = true;
|
||||||
|
clearOnRefresh = true;
|
||||||
|
|
||||||
async apiEndpoint(page: number): Promise<PaginatedResponse<UserAssignedObjectPermission>> {
|
async apiEndpoint(page: number): Promise<PaginatedResponse<UserAssignedObjectPermission>> {
|
||||||
const perms = await new RbacApi(DEFAULT_CONFIG).rbacPermissionsAssignedByUsersList({
|
const perms = await new RbacApi(DEFAULT_CONFIG).rbacPermissionsAssignedByUsersList({
|
||||||
|
|
|
@ -119,6 +119,14 @@ export abstract class Table<T> extends AKElement implements TableLike {
|
||||||
@property({ type: Number })
|
@property({ type: Number })
|
||||||
page = getURLParam("tablePage", 1);
|
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 })
|
@property({ type: String })
|
||||||
order?: string;
|
order?: string;
|
||||||
|
|
||||||
|
@ -178,8 +186,11 @@ export abstract class Table<T> extends AKElement implements TableLike {
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.addEventListener(EVENT_REFRESH, () => {
|
this.addEventListener(EVENT_REFRESH, async () => {
|
||||||
this.fetch();
|
await this.fetch();
|
||||||
|
if (this.clearOnRefresh) {
|
||||||
|
this.selectedElements = [];
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ export class AuthenticatedSessionList extends Table<AuthenticatedSession> {
|
||||||
}
|
}
|
||||||
|
|
||||||
checkbox = true;
|
checkbox = true;
|
||||||
|
clearOnRefresh = true;
|
||||||
order = "-expires";
|
order = "-expires";
|
||||||
|
|
||||||
columns(): TableColumn[] {
|
columns(): TableColumn[] {
|
||||||
|
|
|
@ -25,6 +25,7 @@ export class UserConsentList extends Table<UserConsent> {
|
||||||
}
|
}
|
||||||
|
|
||||||
checkbox = true;
|
checkbox = true;
|
||||||
|
clearOnRefresh = true;
|
||||||
order = "-expires";
|
order = "-expires";
|
||||||
|
|
||||||
columns(): TableColumn[] {
|
columns(): TableColumn[] {
|
||||||
|
|
|
@ -25,6 +25,7 @@ export class MFADevicesPage extends Table<Device> {
|
||||||
userSettings?: UserSetting[];
|
userSettings?: UserSetting[];
|
||||||
|
|
||||||
checkbox = true;
|
checkbox = true;
|
||||||
|
clearOnRefresh = true;
|
||||||
|
|
||||||
async apiEndpoint(): Promise<PaginatedResponse<Device>> {
|
async apiEndpoint(): Promise<PaginatedResponse<Device>> {
|
||||||
const devices = await new AuthenticatorsApi(DEFAULT_CONFIG).authenticatorsAllList();
|
const devices = await new AuthenticatorsApi(DEFAULT_CONFIG).authenticatorsAllList();
|
||||||
|
|
|
@ -29,6 +29,7 @@ export class UserTokenList extends Table<Token> {
|
||||||
|
|
||||||
expandable = true;
|
expandable = true;
|
||||||
checkbox = true;
|
checkbox = true;
|
||||||
|
clearOnRefresh = true;
|
||||||
|
|
||||||
@property()
|
@property()
|
||||||
order = "expires";
|
order = "expires";
|
||||||
|
|
Reference in New Issue