diff --git a/api/js/etemplate/Et2Link/Et2LinkString.ts b/api/js/etemplate/Et2Link/Et2LinkString.ts index 4363f383c8..05501c3e24 100644 --- a/api/js/etemplate/Et2Link/Et2LinkString.ts +++ b/api/js/etemplate/Et2Link/Et2LinkString.ts @@ -10,14 +10,13 @@ */ -import {css, html, LitElement, nothing, PropertyValues, render, TemplateResult} from "lit"; +import {css, html, LitElement, PropertyValues, render, TemplateResult} from "lit"; import {until} from "lit/directives/until.js"; import {Et2Widget} from "../Et2Widget/Et2Widget"; import {LinkInfo} from "./Et2Link"; import {et2_IDetachedDOM} from "../et2_core_interfaces"; import {property} from "lit/decorators/property.js"; import {customElement} from "lit/decorators/custom-element.js"; -import {repeat} from "lit/directives/repeat.js"; /** * Display a list of entries in a comma separated list @@ -37,34 +36,30 @@ export class Et2LinkString extends Et2Widget(LitElement) implements et2_IDetache return [ ...super.styles, css` - :host { - list-style-type: none; - display: inline; - padding: 0px; - } + :host { + list-style-type: none; + display: inline; + padding: 0px; + } - et2-link, et2-link::part(base), et2-description { - display: inline; - } + ::slotted(*) { + display: inline; + } - et2-link::part(icon) { - display: none; - } - - et2-link:hover { - text-decoration: underline; - } + ::slotted(*):hover { + text-decoration: underline; + } - /* CSS for child elements */ + /* CSS for child elements */ - et2-link::part(title):after { - content: ", " - } + ::slotted(*):after { + content: ", " + } - et2-link:last-child::part(title):after { - content: initial; - } + ::slotted(*:last-child):after { + content: initial; + } ` ]; } @@ -117,14 +112,13 @@ export class Et2LinkString extends Et2Widget(LitElement) implements et2_IDetache @property({type: Number}) limit = 20; - protected _totalResults : number = 0; - protected _link_list : LinkInfo[] = []; - protected _loadingPromise : Promise = Promise.resolve([]); - protected _loading = false; + protected _link_list : LinkInfo[]; + protected _loadingPromise : Promise; constructor() { super(); + this._link_list = [] } async getUpdateComplete() @@ -150,12 +144,6 @@ export class Et2LinkString extends Et2Widget(LitElement) implements et2_IDetache public set_value(_value : string | { to_app : string, to_id : string } | LinkInfo[]) { this._link_list = []; - if(typeof _value["total"] !== "undefined") - { - this._totalResults = _value["total"]; - delete _value["total"]; - } - if(typeof _value == "object" && !Array.isArray(_value) && !_value.to_app && this.application) { _value.to_app = this.application; @@ -167,12 +155,7 @@ export class Et2LinkString extends Et2Widget(LitElement) implements et2_IDetache { this.application = _value.to_app; this.entryId = _value.to_id; - - // Let update complete finish first, if it's not done yet - this.updateComplete.then(() => - { - this.get_links(); - }) + this.get_links(); return; } @@ -183,9 +166,9 @@ export class Et2LinkString extends Et2Widget(LitElement) implements et2_IDetache ids.forEach((id) => (this._link_list).push({app: this.application, id: id})); } // List of LinkInfo - else if(Array.isArray(_value) || typeof _value[0] == "object") + else if(Array.isArray(_value)) { - this._link_list = Object.values(_value); + this._link_list = _value; } // List of LinkInfo stuffed into to_id - entry is not yet saved else if(_value.to_id && typeof _value.to_id !== "string") @@ -196,7 +179,8 @@ export class Et2LinkString extends Et2Widget(LitElement) implements et2_IDetache this._link_list.push(_value.to_id[key]); }); } - this.requestUpdate(); + this._addLinks(this._link_list); + super.requestUpdate(); } public updated(changedProperties : PropertyValues) @@ -216,21 +200,20 @@ export class Et2LinkString extends Et2Widget(LitElement) implements et2_IDetache { // This shows loading template until loadingPromise resolves, then shows _listTemplate return html` - ${until(this._loadingPromise?.then(res => + ${this._loadingPromise ? until( + this._loadingPromise?.then(res => { - return this._listTemplate(); + this._listTemplate(); }), this._loadingTemplate() - )} - ${until(this.moreResultsTemplate(), nothing)} + ) : this._listTemplate()} `; } protected _listTemplate() { return html` - ${repeat(this._link_list, l => l.link_id, this._linkTemplate)} - `; + `; } /** @@ -244,9 +227,22 @@ export class Et2LinkString extends Et2Widget(LitElement) implements et2_IDetache { const id = typeof link.id === "string" ? link.id : link.link_id; return html` - `; + `; + } + + /** + * Render "more links available" + * + * @param link + * @returns {TemplateResult} + * @protected + */ + protected _moreAvailableTemplate(link : LinkInfo) : TemplateResult + { + return html` + `; } /** @@ -256,27 +252,7 @@ export class Et2LinkString extends Et2Widget(LitElement) implements et2_IDetache */ protected _loadingTemplate() : TemplateResult { - return html` -
- -
- `; - } - - protected async moreResultsTemplate() - { - if(this._totalResults <= 0 || !this._loadingPromise) - { - return nothing; - } - return this._loadingPromise.then(() => - { - const moreCount = this._totalResults - this._link_list.length; - const more = html` - ... - `; - return html`${moreCount > 0 ? more : nothing}`; - }); + return html`loading...`; } /** @@ -288,7 +264,6 @@ export class Et2LinkString extends Et2Widget(LitElement) implements et2_IDetache */ protected _addLinks(links : LinkInfo[]) { - return; // Remove anything there right now while(this.lastChild) { @@ -298,7 +273,7 @@ export class Et2LinkString extends Et2Widget(LitElement) implements et2_IDetache links.forEach((link) => { let temp = document.createElement("div"); - render(this._linkTemplate(link), temp); + render(link.app === 'exceeded' ? this._moreAvailableTemplate(link) : this._linkTemplate(link), temp); temp.childNodes.forEach((node) => this.appendChild(node)); }) @@ -322,15 +297,8 @@ export class Et2LinkString extends Et2Widget(LitElement) implements et2_IDetache * Called internally to fetch the list. May be called externally to trigger a refresh if a link is added. * */ - public get_links(not_saved_links? : LinkInfo[], offset = 0) + public get_links(not_saved_links? : LinkInfo[]) { - if(this._loading) - { - // Already waiting - return; - } - this._loading = true; - if(typeof not_saved_links === "undefined") { not_saved_links = []; @@ -340,31 +308,31 @@ export class Et2LinkString extends Et2Widget(LitElement) implements et2_IDetache to_id: this.entryId, only_app: this.onlyApp, show_deleted: this.showDeleted, - limit: [offset, /* num_rows: */this.limit] + limit: this.limit }; + this.limit *= 2; // double number of loaded links on next call + + if(this._loadingPromise) + { + // Already waiting + return; + } this._loadingPromise = >(this.egw().jsonq('EGroupware\\Api\\Etemplate\\Widget\\Link::ajax_link_list', [_value])) .then(_value => { - if(typeof _value.total) + if(_value && Array.isArray(_value)) { - this._totalResults = _value.total; - delete _value.total; - } - if(_value) - { - for(let link of Object.values(_value)) + for(let link of _value) { - // Avoid duplicates, files are always sent - if(!not_saved_links.some(l => l.app == link.app && l.id == link.id) && - !this._link_list.some(l => l.app == link.app && l.id == link.id)) + if(!not_saved_links.some(l => l.app == link.app && l.id == link.id)) { - this._link_list.push(link); + not_saved_links.push(link); } } } - this._loading = false; - this.requestUpdate(); + this._addLinks(not_saved_links); + this._loadingPromise = null; }) } @@ -383,7 +351,6 @@ export class Et2LinkString extends Et2Widget(LitElement) implements et2_IDetache for(let k in _values) { this[k] = _values[k]; - this.requestUpdate(k); } } } \ No newline at end of file