web: code quality pass, extra comments, pre-commit check.

This commit is contained in:
Ken Sternberg 2024-01-04 13:21:13 -08:00
parent e1c0cd44ae
commit 8fa2bf4713
6 changed files with 68 additions and 62 deletions

View file

@ -1,4 +1,5 @@
import { AKElement } from "@goauthentik/elements/Base"; import { AKElement } from "@goauthentik/elements/Base";
import { debounce } from "@goauthentik/elements/utils/debounce";
import { CustomListenerElement } from "@goauthentik/elements/utils/eventEmitter"; import { CustomListenerElement } from "@goauthentik/elements/utils/eventEmitter";
import { msg } from "@lit/localize"; import { msg } from "@lit/localize";
@ -6,7 +7,6 @@ import { PropertyValues, html } from "lit";
import { customElement, property, state } from "lit/decorators.js"; import { customElement, property, state } from "lit/decorators.js";
import { createRef, ref } from "lit/directives/ref.js"; import { createRef, ref } from "lit/directives/ref.js";
import type { Ref } from "lit/directives/ref.js"; import type { Ref } from "lit/directives/ref.js";
import { debounce } from "@goauthentik/elements/utils/debounce";
import type { Pagination } from "@goauthentik/api"; import type { Pagination } from "@goauthentik/api";
@ -45,7 +45,7 @@ export class AkDualSelectProvider extends CustomListenerElement(AKElement) {
/** The remote lists are debounced by definition. This is the interval for the debounce. */ /** The remote lists are debounced by definition. This is the interval for the debounce. */
@property({ attribute: "search-delay", type: Number }) @property({ attribute: "search-delay", type: Number })
searchDelay = 250; searchDelay = 250;
@state() @state()
private options: DualSelectPair[] = []; private options: DualSelectPair[] = [];
@ -55,10 +55,6 @@ export class AkDualSelectProvider extends CustomListenerElement(AKElement) {
private pagination?: Pagination; private pagination?: Pagination;
get value() {
return this.dualSelector.value!.selected.map(([k, _]) => k);
}
selectedMap: WeakMap<DataProvider, DualSelectPair[]> = new WeakMap(); selectedMap: WeakMap<DataProvider, DualSelectPair[]> = new WeakMap();
constructor() { constructor() {
@ -74,32 +70,6 @@ export class AkDualSelectProvider extends CustomListenerElement(AKElement) {
this.addCustomListener("ak-dual-select-search", this.onSearch); this.addCustomListener("ak-dual-select-search", this.onSearch);
} }
onNav(event: Event) {
if (!(event instanceof CustomEvent)) {
throw new Error(`Expecting a CustomEvent for navigation, received ${event} instead`);
}
this.fetch(event.detail);
}
onChange(event: Event) {
if (!(event instanceof CustomEvent)) {
throw new Error(`Expecting a CustomEvent for change, received ${event} instead`);
}
this.selected = event.detail.value;
}
doSearch(search: string) {
this.pagination = undefined;
this.fetch(undefined, search);
}
onSearch(event: Event) {
if (!(event instanceof CustomEvent)) {
throw new Error(`Expecting a CustomEvent for change, received ${event} instead`);
}
this.doSearch(event.detail);
}
willUpdate(changedProperties: PropertyValues<this>) { willUpdate(changedProperties: PropertyValues<this>) {
if (changedProperties.has("searchDelay")) { if (changedProperties.has("searchDelay")) {
this.doSearch = debounce(this.doSearch.bind(this), this.searchDelay); this.doSearch = debounce(this.doSearch.bind(this), this.searchDelay);
@ -127,6 +97,36 @@ export class AkDualSelectProvider extends CustomListenerElement(AKElement) {
this.isLoading = false; this.isLoading = false;
} }
onNav(event: Event) {
if (!(event instanceof CustomEvent)) {
throw new Error(`Expecting a CustomEvent for navigation, received ${event} instead`);
}
this.fetch(event.detail);
}
onChange(event: Event) {
if (!(event instanceof CustomEvent)) {
throw new Error(`Expecting a CustomEvent for change, received ${event} instead`);
}
this.selected = event.detail.value;
}
onSearch(event: Event) {
if (!(event instanceof CustomEvent)) {
throw new Error(`Expecting a CustomEvent for change, received ${event} instead`);
}
this.doSearch(event.detail);
}
doSearch(search: string) {
this.pagination = undefined;
this.fetch(undefined, search);
}
get value() {
return this.dualSelector.value!.selected.map(([k, _]) => k);
}
render() { render() {
return html`<ak-dual-select return html`<ak-dual-select
${ref(this.dualSelector)} ${ref(this.dualSelector)}

View file

@ -113,10 +113,6 @@ export class AkDualSelect extends CustomEmitterElement(CustomListenerElement(AKE
this.addCustomListener("ak-search", this.handleSearch); this.addCustomListener("ak-search", this.handleSearch);
} }
get value() {
return this.selected;
}
willUpdate(changedProperties: PropertyValues<this>) { willUpdate(changedProperties: PropertyValues<this>) {
if (changedProperties.has("selected")) { if (changedProperties.has("selected")) {
this.selectedKeys = new Set(this.selected.map(([key, _]) => key)); this.selectedKeys = new Set(this.selected.map(([key, _]) => key));
@ -246,6 +242,10 @@ export class AkDualSelect extends CustomEmitterElement(CustomListenerElement(AKE
this.selectedPane.value!.clearMove(); this.selectedPane.value!.clearMove();
} }
get value() {
return this.selected;
}
get canAddAll() { get canAddAll() {
// False unless any visible option cannot be found in the selected list, so can still be // False unless any visible option cannot be found in the selected list, so can still be
// added. // added.
@ -268,15 +268,17 @@ export class AkDualSelect extends CustomEmitterElement(CustomListenerElement(AKE
} }
render() { render() {
const selected = this.selectedFilter === "" ? this.selected : const selected =
this.selected.filter(([_k, v, s]) => { this.selectedFilter === ""
const value = s !== undefined ? s : v; ? this.selected
if (typeof value !== "string") { : this.selected.filter(([_k, v, s]) => {
throw new Error("Filter only works when there's a string comparator"); const value = s !== undefined ? s : v;
} if (typeof value !== "string") {
return value.toLowerCase().includes(this.selectedFilter.toLowerCase()) throw new Error("Filter only works when there's a string comparator");
}); }
return value.toLowerCase().includes(this.selectedFilter.toLowerCase());
});
const availableCount = this.availablePane.value?.toMove.size ?? 0; const availableCount = this.availablePane.value?.toMove.size ?? 0;
const selectedCount = this.selectedPane.value?.toMove.size ?? 0; const selectedCount = this.selectedPane.value?.toMove.size ?? 0;
const selectedTotal = selected.length; const selectedTotal = selected.length;

View file

@ -80,10 +80,6 @@ export class AkDualSelectAvailablePane extends CustomEmitterElement(AKElement) {
}); });
} }
get moveable() {
return Array.from(this.toMove.values());
}
clearMove() { clearMove() {
this.toMove = new Set(); this.toMove = new Set();
} }
@ -112,6 +108,10 @@ export class AkDualSelectAvailablePane extends CustomEmitterElement(AKElement) {
this.requestUpdate(); this.requestUpdate();
} }
get moveable() {
return Array.from(this.toMove.values());
}
// DO NOT use `Array.map()` instead of Lit's `map()` function. Lit's `map()` is object-aware and // DO NOT use `Array.map()` instead of Lit's `map()` function. Lit's `map()` is object-aware and
// will not re-arrange or reconstruct the list automatically if the actual sources do not // will not re-arrange or reconstruct the list automatically if the actual sources do not
// change; this allows the available pane to illustrate selected items with the checkmark // change; this allows the available pane to illustrate selected items with the checkmark

View file

@ -63,8 +63,13 @@ export class AkDualSelectSelectedPane extends CustomEmitterElement(AKElement) {
this.onMove = this.onMove.bind(this); this.onMove = this.onMove.bind(this);
} }
get moveable() { connectedCallback() {
return Array.from(this.toMove.values()); super.connectedCallback();
hostAttributes.forEach(([attr, value]) => {
if (!this.hasAttribute(attr)) {
this.setAttribute(attr, value);
}
});
} }
clearMove() { clearMove() {
@ -92,13 +97,8 @@ export class AkDualSelectSelectedPane extends CustomEmitterElement(AKElement) {
this.requestUpdate(); this.requestUpdate();
} }
connectedCallback() { get moveable() {
super.connectedCallback(); return Array.from(this.toMove.values());
hostAttributes.forEach(([attr, value]) => {
if (!this.hasAttribute(attr)) {
this.setAttribute(attr, value);
}
});
} }
render() { render() {

View file

@ -19,14 +19,18 @@ export class AkSearchbar extends CustomEmitterElement(AKElement) {
return styles; return styles;
} }
input: Ref<HTMLInputElement> = createRef();
@property({ type: String, reflect: true }) @property({ type: String, reflect: true })
value = ""; value = "";
/**
* If you're using more than one search, this token can help listeners distinguishing between
* those searches. Lit's own helpers sometimes erase the source and current targets.
*/
@property({ type: String }) @property({ type: String })
name = ""; name = "";
input: Ref<HTMLInputElement> = createRef();
constructor() { constructor() {
super(); super();
this.onChange = this.onChange.bind(this); this.onChange = this.onChange.bind(this);
@ -38,7 +42,7 @@ export class AkSearchbar extends CustomEmitterElement(AKElement) {
} }
this.dispatchCustomEvent<SearchbarEvent>("ak-search", { this.dispatchCustomEvent<SearchbarEvent>("ak-search", {
source: this.name, source: this.name,
value: this.value value: this.value,
}); });
} }

View file

@ -22,5 +22,5 @@ export interface SearchbarEvent extends CustomEvent {
detail: { detail: {
source: string; source: string;
value: string; value: string;
} };
} }