Et2SelectAccount improvements

- Fix always including all accounts
- Limit included accounts to 100 to avoid breaking
- Let repeat() cache
- Improved "more results" count
- Reduce repeats & iteration needed
This commit is contained in:
nathan 2023-10-06 11:37:11 -06:00
parent 58d486e6ba
commit 235ff7a2cf
5 changed files with 32 additions and 14 deletions

View File

@ -689,7 +689,7 @@ export class Et2Select extends Et2WithSearchMixin(Et2WidgetWithSelect)
{
return html`${repeat(this.select_options
// Filter out empty values if we have empty label to avoid duplicates
.filter(o => this.emptyLabel ? o.value !== '' : o), this._groupTemplate.bind(this))
.filter(o => this.emptyLabel ? o.value !== '' : o), o => o.value, this._groupTemplate.bind(this))
}`;
}

View File

@ -15,6 +15,7 @@ import {StaticOptions} from "./StaticOptions";
import {dedupeMixin} from "@open-wc/dedupe-mixin";
import {SlOption} from "@shoelace-style/shoelace";
import {Et2Textbox} from "../Et2Textbox/Et2Textbox";
import {until} from "lit/directives/until.js";
// Otherwise import gets stripped
let keep_import : Et2Tag;
@ -428,18 +429,20 @@ export const Et2WithSearchMixin = dedupeMixin(<T extends Constructor<LitElement>
return html`
${this._searchInputTemplate()}
${this._moreResultsTemplate()}
${until(this._moreResultsTemplate(), nothing)}
${this._noResultsTemplate()}
`;
}
protected _moreResultsTemplate()
protected async _moreResultsTemplate()
{
if(this._total_result_count == 0 || this._total_result_count - this._remote_options.length == 0)
await this.updateComplete;
const moreCount = this._total_result_count - this.select?.querySelectorAll("sl-option.match").length;
if(this._total_result_count == 0 || moreCount == 0 || !this.select)
{
return nothing;
}
const more = this.egw().lang("%1 more...", this._total_result_count - this._remote_options.length);
const more = this.egw().lang("%1 more...", moreCount);
return html`<span class="more">${more}</span>`;
}
@ -1107,6 +1110,8 @@ export const Et2WithSearchMixin = dedupeMixin(<T extends Constructor<LitElement>
this._remote_options = [];
this._total_result_count = 0;
// Not searching anymore, clear flag
this.select_options.map((o) => o.isMatch = null);
this.requestUpdate("select_options");
@ -1179,7 +1184,7 @@ export const Et2WithSearchMixin = dedupeMixin(<T extends Constructor<LitElement>
return option.label.toLowerCase().includes(lower_search) || option.value.includes(search)
});
// Limit results
this._total_result_count = filtered.length;
this._total_result_count += filtered.length;
if(filtered.length > Et2WidgetWithSearch.RESULT_LIMIT)
{
filtered.splice(Et2WidgetWithSearch.RESULT_LIMIT);
@ -1223,12 +1228,15 @@ export const Et2WithSearchMixin = dedupeMixin(<T extends Constructor<LitElement>
{
// If results have a total included, pull it out.
// It will cause errors if left in the results
this._total_result_count = results.length;
if(typeof results.total !== "undefined")
{
this._total_result_count = results.total;
this._total_result_count += results.total;
delete results.total;
}
else
{
this._total_result_count += results.length;
}
let entries = cleanSelectOptions(results);
this.processRemoteResults(entries);
return entries;

View File

@ -53,19 +53,28 @@ export class Et2SelectAccount extends SelectAccountMixin(Et2StaticSelectMixin(Et
// Start fetch of select_options
const type = this.egw().preference('account_selection', 'common');
let fetch = [];
let process = (options) =>
{
// Shallow copy to avoid re-using the same object.
// Uses more memory, but otherwise multiple selectboxes get "tied" together
let cleaned = cleanSelectOptions(options)
// slice to avoid problems with lots of accounts
.slice(0, /* Et2WidgetWithSearch.RESULT_LIMIT */ 100);
this.account_options = this.account_options.concat(cleaned);
};
// for primary_group we only display owngroups == own memberships, not other groups
if(type === 'primary_group' && this.accountType !== 'accounts')
{
if(this.accountType === 'both')
{
fetch.push(this.egw().accounts('accounts').then(options => {this._static_options = this._static_options.concat(cleanSelectOptions(options))}));
fetch.push(this.egw().accounts('accounts').then(process));
}
fetch.push(this.egw().accounts('owngroups').then(options => {this._static_options = this._static_options.concat(cleanSelectOptions(options))}));
fetch.push(this.egw().accounts('owngroups').then(process));
}
else
else if(["primary_group", "groupmembers"].includes(type))
{
fetch.push(this.egw().accounts(this.accountType).then(options => {this._static_options = this._static_options.concat(cleanSelectOptions(options))}));
fetch.push(this.egw().accounts(this.accountType).then(process));
}
this.fetchComplete = Promise.all(fetch);
}

View File

@ -110,7 +110,8 @@ export const SelectAccountMixin = <T extends Constructor<LitElement>>(superclass
get select_options()
{
return [...(this.account_options || []), ...super.select_options];
return [...new Map([...this.account_options, ...(super.select_options || [])].map(item =>
[item.value, item])).values()];
}
set select_options(value : SelectOption[])

View File

@ -117,7 +117,7 @@ egw.extend('user', egw.MODULE_GLOBAL, function()
{
if (typeof data[t] === "object")
{
accountStore[t] = jQuery.extend(true, [], data[t] || []);
accountStore[t] = (Array.isArray(data[t]) ? data[t]:Object.values(data[t]) ?? []).map(a => {a.value = ""+a.value; return a});
}
}
}