mirror of
https://github.com/goauthentik/authentik
synced 2026-04-25 17:15:26 +02:00
web: Fix table visibility checks, search params. (#21623)
Fix visibility check, search params.
This commit is contained in:
@@ -1,22 +0,0 @@
|
||||
const isStyledVisible = ({ visibility, display }: CSSStyleDeclaration) =>
|
||||
visibility !== "hidden" && display !== "none";
|
||||
|
||||
const isDisplayContents = ({ display }: CSSStyleDeclaration) => display === "contents";
|
||||
|
||||
function computedStyleIsVisible(element: HTMLElement) {
|
||||
const computedStyle = window.getComputedStyle(element);
|
||||
return (
|
||||
isStyledVisible(computedStyle) &&
|
||||
(isDisplayContents(computedStyle) ||
|
||||
!!(element.offsetWidth || element.offsetHeight || element.getClientRects().length))
|
||||
);
|
||||
}
|
||||
|
||||
export function isVisible(element: HTMLElement) {
|
||||
return (
|
||||
element &&
|
||||
element.isConnected &&
|
||||
isStyledVisible(element.style) &&
|
||||
computedStyleIsVisible(element)
|
||||
);
|
||||
}
|
||||
@@ -22,6 +22,7 @@ import { type TransclusionChildElement, TransclusionChildSymbol } from "#element
|
||||
import { WithSession } from "#elements/mixins/session";
|
||||
import { getURLParam, updateURLParams } from "#elements/router/RouteMatch";
|
||||
import Styles from "#elements/table/Table.css";
|
||||
import { TableSearchForm } from "#elements/table/TableSearch";
|
||||
import { SlottedTemplateResult } from "#elements/types";
|
||||
import { ifPresent } from "#elements/utils/attributes";
|
||||
import { isInteractiveElement } from "#elements/utils/interactivity";
|
||||
@@ -315,9 +316,20 @@ export abstract class Table<T extends object, D = T>
|
||||
return this.selectedElements as unknown as D[];
|
||||
}
|
||||
|
||||
public clearSearch = () => {
|
||||
this.data = null;
|
||||
this.searchInputRef.value?.reset();
|
||||
this.requestUpdate("search");
|
||||
|
||||
return this.fetch();
|
||||
};
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region Lifecycle
|
||||
|
||||
#selectAllCheckboxRef = createRef<HTMLInputElement>();
|
||||
protected selectAllCheckboxRef = createRef<HTMLInputElement>();
|
||||
protected searchInputRef = createRef<TableSearchForm>();
|
||||
|
||||
protected refreshListener = (event?: Event) => {
|
||||
this.logger.debug("Received refresh event:", event);
|
||||
@@ -460,7 +472,7 @@ export abstract class Table<T extends object, D = T>
|
||||
if (this.selectedMap.size) {
|
||||
this.selectedMap = new Map();
|
||||
|
||||
const selectAllCheckbox = this.#selectAllCheckboxRef.value;
|
||||
const selectAllCheckbox = this.selectAllCheckboxRef.value;
|
||||
|
||||
if (selectAllCheckbox) {
|
||||
selectAllCheckbox.checked = false;
|
||||
@@ -677,7 +689,7 @@ export abstract class Table<T extends object, D = T>
|
||||
this.requestUpdate("selectedMap");
|
||||
}
|
||||
|
||||
const selectAllCheckbox = this.#selectAllCheckboxRef.value;
|
||||
const selectAllCheckbox = this.selectAllCheckboxRef.value;
|
||||
const pageItemCount = this.data?.results?.length ?? 0;
|
||||
const selectedCount = this.selectedMap.size;
|
||||
|
||||
@@ -868,9 +880,13 @@ export abstract class Table<T extends object, D = T>
|
||||
#searchListener = (value: string) => {
|
||||
this.search = value;
|
||||
this.page = 1;
|
||||
this.fetch();
|
||||
|
||||
return this.fetch();
|
||||
};
|
||||
|
||||
/**
|
||||
* Whether the search input should be rendered.
|
||||
*/
|
||||
protected searchEnabled = false;
|
||||
|
||||
protected renderSearch(): SlottedTemplateResult {
|
||||
@@ -879,6 +895,7 @@ export abstract class Table<T extends object, D = T>
|
||||
}
|
||||
|
||||
return html`<ak-table-search
|
||||
${ref(this.searchInputRef)}
|
||||
exportparts="input:toolbar-search-input"
|
||||
class="pf-c-toolbar__item pf-m-search-filter ${this.supportsQL ? "ql" : ""}"
|
||||
part="toolbar-search"
|
||||
@@ -888,8 +905,7 @@ export abstract class Table<T extends object, D = T>
|
||||
.onSearch=${this.#searchListener}
|
||||
.supportsQL=${this.supportsQL}
|
||||
.apiResponse=${this.data}
|
||||
>
|
||||
</ak-table-search>`;
|
||||
></ak-table-search>`;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
@@ -897,7 +913,7 @@ export abstract class Table<T extends object, D = T>
|
||||
//#region Chips
|
||||
|
||||
#synchronizeCheckboxAll = () => {
|
||||
const checkbox = this.#selectAllCheckboxRef.value;
|
||||
const checkbox = this.selectAllCheckboxRef.value;
|
||||
|
||||
if (!checkbox) return;
|
||||
|
||||
@@ -935,7 +951,7 @@ export abstract class Table<T extends object, D = T>
|
||||
|
||||
return html`<th class="pf-c-table__check" role="presentation">
|
||||
<input
|
||||
${ref(this.#selectAllCheckboxRef)}
|
||||
${ref(this.selectAllCheckboxRef)}
|
||||
name="select-all"
|
||||
type="checkbox"
|
||||
aria-label=${msg(
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import "#elements/EmptyState";
|
||||
|
||||
import { updateURLParams } from "#elements/router/RouteMatch";
|
||||
import { Table } from "#elements/table/Table";
|
||||
import Styles from "#elements/table/TablePage.css";
|
||||
import { SlottedTemplateResult } from "#elements/types";
|
||||
@@ -84,22 +83,6 @@ export abstract class TablePage<T extends object> extends Table<T> {
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region Protected methods
|
||||
|
||||
protected clearSearch = () => {
|
||||
this.search = "";
|
||||
|
||||
this.requestUpdate();
|
||||
|
||||
updateURLParams({
|
||||
search: "",
|
||||
});
|
||||
|
||||
return this.fetch();
|
||||
};
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region Render methods
|
||||
|
||||
/**
|
||||
@@ -125,15 +108,7 @@ export abstract class TablePage<T extends object> extends Table<T> {
|
||||
if (!this.search) {
|
||||
return nothing;
|
||||
}
|
||||
return html`<button
|
||||
@click=${() => {
|
||||
this.search = "";
|
||||
this.requestUpdate();
|
||||
this.fetch();
|
||||
this.page = 1;
|
||||
}}
|
||||
class="pf-c-button pf-m-link"
|
||||
>
|
||||
return html`<button @click=${this.clearSearch} class="pf-c-button pf-m-link">
|
||||
${msg("Clear search")}
|
||||
</button>`;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,9 @@ export const InteractiveElementsQuery =
|
||||
export function isInteractiveElement(
|
||||
target: EventTarget | Element | null | undefined,
|
||||
): target is HTMLElement {
|
||||
if (!target || !(target instanceof HTMLElement)) {
|
||||
if (!target) return false;
|
||||
|
||||
if (!(target instanceof HTMLElement)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -16,5 +18,9 @@ export function isInteractiveElement(
|
||||
// so we fallback to assuming the element is visible.
|
||||
const visible = target.checkVisibility?.() ?? true;
|
||||
|
||||
return visible && target.matches(InteractiveElementsQuery);
|
||||
const { tabIndex } = target;
|
||||
|
||||
return (
|
||||
visible && (tabIndex === 0 || tabIndex === -1 || target.matches(InteractiveElementsQuery))
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user