import {css, html, LitElement, nothing, TemplateResult} from "lit"; import {customElement} from "lit/decorators/custom-element.js"; import {Et2Widget} from "../Et2Widget/Et2Widget"; import {Favorite} from "./Favorite"; import {property} from "lit/decorators/property.js"; import {until} from "lit/directives/until.js"; import {repeat} from "lit/directives/repeat.js"; /** * @summary A menu listing a user's favorites. Populated from the user's preferences. * * @dependency sl-menu * @dependency sl-menu-item * @dependency sl-menu-label * @dependency et2-image * * @slot - Add additional menu items */ @customElement("et2-favorites-menu") export class Et2FavoritesMenu extends Et2Widget(LitElement) { static get styles() { return [ super.styles, css` :host { min-width: 15em; } et2-image[src="trash"] { display: none; } sl-menu-item:hover et2-image[src="trash"] { display: initial; }` ] }; /** * The current application we're showing favorites for. * * @type {string} */ @property() application : string; @property() noAdd : boolean = false; private favorites : { [name : string] : Favorite } = { 'blank': { name: typeof this.egw()?.lang == "function" ? this.egw().lang("No filters") : "No filters", state: {}, group: false } }; private loadingPromise = Promise.resolve(); constructor() { super(); this.handlePreferenceChange = this.handlePreferenceChange.bind(this); } connectedCallback() { super.connectedCallback(); if(this.application) { this._load(); } document.addEventListener("preferenceChange", this.handlePreferenceChange); } disconnectedCallback() { super.disconnectedCallback(); document.removeEventListener("preferenceChange", this.handlePreferenceChange); } private _load() { this.loadingPromise = Favorite.load(this.egw(), this.application).then((favorites) => { this.favorites = favorites; }); } handlePreferenceChange(e) { if(e && e.detail?.application == this.application) { this._load(); this.requestUpdate(); } } handleSelect(event) { if(event.detail.item.value == Favorite.ADD_VALUE) { return this.handleAdd(event); } Favorite.applyFavorite(this.egw(), this.application, event.detail.item.value); } handleAdd(event) { event.stopPropagation(); if(this.egw().window && this.egw().window.app[this.application]) { this.egw().window.app[this.application].add_favorite({}); } } handleDelete(event) { // Don't trigger click event.stopPropagation(); const menuItem = event.target.closest("sl-menu-item"); menuItem.setAttribute("loading", ""); const favoriteName = menuItem.value; // Remove from server Favorite.remove(this.egw(), this.application, favoriteName).then(() => { // Remove from widget delete this.favorites[favoriteName]; this.requestUpdate(); this.updateComplete.then(() => { this.dispatchEvent(new CustomEvent("preferenceChange", { bubbles: true, composed: true, detail: { application: this.application, preference: favoriteName } })); }); }); this.requestUpdate(); } protected menuItemTemplate(name : string, favorite : Favorite) : TemplateResult { let is_admin = (typeof this.egw()?.app == "function") && (typeof this.egw()?.app('admin') != "undefined"); //@ts-ignore option.group does not exist let icon = (favorite.group !== false && !is_admin || ['blank', '~add~'].includes(name)) ? "" : html` `; return html` ${icon} ${favorite.name} `; } protected loadingTemplate() { return html` ${typeof this.egw()?.lang == "function" ? this.egw().lang("Loading") : "Loading"} `; } render() { let content = this.loadingPromise.then(() => { return html` ${this.label ? html` ${this.label}` : nothing} ${repeat(Object.keys(this.favorites), (i) => this.menuItemTemplate(i, this.favorites[i]))} ${this.noAdd ? nothing : html` ${this.egw().lang("Current view as favourite")} ` } `; }); return html` ${until(content, this.loadingTemplate())} `; } }