import { html } from "lit"; import { property, state } from "lit/decorators.js"; import { msg, localized } from "@lit/localize"; import orderBy from "lodash/fp/orderBy"; import type { AuthState } from "../utils/AuthService"; import LiteElement from "../utils/LiteElement"; import type { Profile } from "../pages/org/types"; import type { APIPaginatedList } from "../types/api"; /** * Browser profile select dropdown * * Usage example: * ```ts * selectedProfile = value} * > * ``` * * @event on-change */ @localized() export class SelectBrowserProfile extends LiteElement { @property({ type: Object }) authState!: AuthState; @property({ type: String }) orgId!: string; @property({ type: String }) profileId?: string; @state() private selectedProfile?: Profile; @state() private browserProfiles?: Profile[]; protected firstUpdated() { this.fetchBrowserProfiles(); } render() { return html` { // Refetch to keep list up to date this.fetchBrowserProfiles(); }} @sl-hide=${this.stopProp} @sl-after-hide=${this.stopProp} > ${this.browserProfiles ? html` ${msg("Default Profile")} ` : html` `} ${this.browserProfiles?.map( (profile) => html` ${profile.name}
` )} ${this.browserProfiles && !this.browserProfiles.length ? this.renderNoProfiles() : ""}
${this.browserProfiles && this.browserProfiles.length ? this.renderSelectedProfileInfo() : ""} `; } private renderSelectedProfileInfo() { if (!this.selectedProfile) return; return html`
${this.selectedProfile.description ? html`${this.selectedProfile.description}` : ""} ${msg("View profile")}
`; } private renderNoProfiles() { return html`
${msg("No additional browser profiles found.")} { const select = e.target.closest("sl-select"); if (select) { select.blur(); select.dropdown?.hide(); } }} >${msg("Create a browser profile")}
`; } private onChange(e: any) { this.selectedProfile = this.browserProfiles?.find( ({ id }) => id === e.target.value ); this.dispatchEvent( new CustomEvent("on-change", { detail: { value: this.selectedProfile, }, }) ); } /** * Fetch browser profiles and update internal state */ private async fetchBrowserProfiles(): Promise { try { const data = await this.getProfiles(); this.browserProfiles = orderBy(["name", "created"])(["asc", "desc"])( data ) as Profile[]; if (this.profileId && !this.selectedProfile) { this.selectedProfile = this.browserProfiles.find( ({ id }) => id === this.profileId ); } } catch (e) { this.notify({ message: msg("Sorry, couldn't retrieve browser profiles at this time."), variant: "danger", icon: "exclamation-octagon", }); } } private async getProfiles(): Promise { const data: APIPaginatedList = await this.apiFetch( `/orgs/${this.orgId}/profiles`, this.authState! ); return data.items; } /** * Stop propgation of sl-select events. * Prevents bug where sl-dialog closes when dropdown closes * https://github.com/shoelace-style/shoelace/issues/170 */ private stopProp(e: CustomEvent) { e.stopPropagation(); } }