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:
Ken Sternberg
2024-07-15 10:29:21 -07:00
19 changed files with 394 additions and 439 deletions

View File

@ -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>`;
}
}

View File

@ -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();

View File

@ -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,