Merge branch 'main' into web/add-htmltagmaps-to-activate-lit-analyzer
* main: core: bump setuptools from 69.5.1 to 70.0.0 (#10503) web: replace multi-select with dual-select for all propertyMapping invocations (#9359) web: enable custom-element-manifest and DOM/JS integration checking. (#10177)
This commit is contained in:
@ -0,0 +1,52 @@
|
||||
import { PropertyValues, html } from "lit";
|
||||
import { customElement, property } from "lit/decorators.js";
|
||||
import { ref } from "lit/directives/ref.js";
|
||||
|
||||
import { AkDualSelectProvider } from "./ak-dual-select-provider.js";
|
||||
import "./ak-dual-select.js";
|
||||
import type { DualSelectPair } from "./types.js";
|
||||
|
||||
/**
|
||||
* @element ak-dual-select-dynamic-provider
|
||||
*
|
||||
* A top-level component for multi-select elements have dynamically generated "selected"
|
||||
* lists.
|
||||
*/
|
||||
|
||||
@customElement("ak-dual-select-dynamic-selected")
|
||||
export class AkDualSelectDynamic extends AkDualSelectProvider {
|
||||
/**
|
||||
* An extra source of "default" entries. A number of our collections have an alternative default
|
||||
* source when initializing a new component instance of that collection's host object. Only run
|
||||
* on start-up.
|
||||
*
|
||||
* @attr
|
||||
*/
|
||||
@property({ attribute: false })
|
||||
selector: ([key, _]: DualSelectPair) => boolean = ([_key, _]) => false;
|
||||
|
||||
private firstUpdateHasRun = false;
|
||||
|
||||
willUpdate(changed: PropertyValues<this>) {
|
||||
super.willUpdate(changed);
|
||||
// On the first update *only*, even before rendering, when the options are handed up, update
|
||||
// the selected list with the contents derived from the selector.
|
||||
if (!this.firstUpdateHasRun && this.options.length > 0) {
|
||||
this.firstUpdateHasRun = true;
|
||||
this.selected = Array.from(
|
||||
new Set([...this.selected, ...this.options.filter(this.selector)]),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`<ak-dual-select
|
||||
${ref(this.dualSelector)}
|
||||
.options=${this.options}
|
||||
.pages=${this.pagination}
|
||||
.selected=${this.selected}
|
||||
available-label=${this.availableLabel}
|
||||
selected-label=${this.selectedLabel}
|
||||
></ak-dual-select>`;
|
||||
}
|
||||
}
|
||||
@ -27,36 +27,59 @@ import type { DataProvider, DualSelectPair } from "./types";
|
||||
|
||||
@customElement("ak-dual-select-provider")
|
||||
export class AkDualSelectProvider extends CustomListenerElement(AKElement) {
|
||||
/** A function that takes a page and returns the DualSelectPair[] collection with which to update
|
||||
/**
|
||||
* A function that takes a page and returns the DualSelectPair[] collection with which to update
|
||||
* the "Available" pane.
|
||||
*
|
||||
* @attr
|
||||
*/
|
||||
@property({ type: Object })
|
||||
provider!: DataProvider;
|
||||
|
||||
/**
|
||||
* The list of selected items. This is the *complete* list, not paginated, as presented by a
|
||||
* component with a multi-select list of items to track.
|
||||
*
|
||||
* @attr
|
||||
*/
|
||||
@property({ type: Array })
|
||||
selected: DualSelectPair[] = [];
|
||||
|
||||
/**
|
||||
* The label for the left ("available") pane
|
||||
*
|
||||
* @attr
|
||||
*/
|
||||
@property({ attribute: "available-label" })
|
||||
availableLabel = msg("Available options");
|
||||
|
||||
/**
|
||||
* The label for the right ("selected") pane
|
||||
*
|
||||
* @attr
|
||||
*/
|
||||
@property({ attribute: "selected-label" })
|
||||
selectedLabel = msg("Selected options");
|
||||
|
||||
/** The remote lists are debounced by definition. This is the interval for the debounce. */
|
||||
/**
|
||||
* The debounce for the search as the user is typing in a request
|
||||
*
|
||||
* @attr
|
||||
*/
|
||||
@property({ attribute: "search-delay", type: Number })
|
||||
searchDelay = 250;
|
||||
|
||||
@state()
|
||||
private options: DualSelectPair[] = [];
|
||||
options: DualSelectPair[] = [];
|
||||
|
||||
private dualSelector: Ref<AkDualSelect> = createRef();
|
||||
protected dualSelector: Ref<AkDualSelect> = createRef();
|
||||
|
||||
private isLoading = false;
|
||||
protected isLoading = false;
|
||||
|
||||
private doneFirstUpdate = false;
|
||||
private internalSelected: DualSelectPair[] = [];
|
||||
|
||||
private pagination?: Pagination;
|
||||
protected pagination?: Pagination;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
@ -4,7 +4,7 @@ import { Pagination } from "@goauthentik/api";
|
||||
|
||||
// Key, Label (string or TemplateResult), (optional) string to sort by. If the sort string is
|
||||
// missing, it will use the label, which doesn't always work for TemplateResults).
|
||||
export type DualSelectPair = [string, string | TemplateResult, string?];
|
||||
export type DualSelectPair<T = never> = [string, string | TemplateResult, string?, T?];
|
||||
|
||||
export type BasePagination = Pick<
|
||||
Pagination,
|
||||
|
||||
Reference in New Issue
Block a user