changed Et2SelectCategory to be the Et2TreeDropdownCategory and and removed theold one

This commit is contained in:
milan 2024-08-22 14:18:29 +02:00
parent 0605f6c2f5
commit 3e577c738f
3 changed files with 98 additions and 234 deletions

View File

@ -1,64 +1,56 @@
/** /**
* EGroupware eTemplate2 - Select Category WebComponent * Use a custom tag for when multiple=true
* *
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License * @returns {string}
* @package api
* @link https://www.egroupware.org
* @author Nathan Gray
*/ */
import {html, literal, StaticValue} from "lit/static-html.js";
import {property} from "lit/decorators/property.js";
import {css, html, nothing, PropertyValues, TemplateResult, unsafeCSS} from "lit"; import {css, PropertyValues, unsafeCSS} from "lit";
import {Et2Select} from "../Et2Select"; import {Et2TreeDropdown} from "../../Et2Tree/Et2TreeDropdown";
import {Et2CategoryTag} from "../Tag/Et2CategoryTag";
import {Et2StaticSelectMixin, StaticOptions as so} from "../StaticOptions"; import {Et2StaticSelectMixin, StaticOptions as so} from "../StaticOptions";
import {cleanSelectOptions} from "../FindSelectOptions";
import {StaticValue} from "lit/development/static-html";
import {literal} from "lit/static-html.js";
import {repeat} from "lit/directives/repeat.js";
/** /**
* Customised Select widget for categories * @since 23.1.x
* This widget gives us category colors and icons in the options and selected value. * This is not a classical Select box but a structured tree
*/ */
export class Et2SelectCategory extends Et2StaticSelectMixin(Et2Select) export class Et2SelectCategory extends Et2StaticSelectMixin(Et2TreeDropdown)
{ {
static get styles() static get styles()
{ {
return [ return [
...super.styles, ...super.styles,
css` css`
/* Category color on options */ :host {
--category-color: transparent;
}
sl-option { ::part(item-item) {
border-left: 6px solid var(--category-color, transparent); border-inline-start: 4px solid transparent;
} border-inline-start-color: var(--category-color, transparent);
/* Border on the (single) selected value */ }
:host(:not([multiple]))::part(combobox) {
border-left: 6px solid var(--category-color, var(--sl-input-border-color));
}
` `
] ];
} }
/**
* Application to get categories from
*/
@property({type: String}) application = '';
static get properties() /**
{ * Include global categories
return { */
...super.properties, @property({type: Boolean}) globalCategories = true;
/**
* Include global categories /**
*/ * Show categories below this parent category
globalCategories: {type: Boolean}, */
/** @property({type: Number}) parentCat: { type: Number }
* Show categories from this application. If not set, will be the current application
*/
application: {type: String},
/** private keep_import : Et2CategoryTag
* Show categories below this parent category
*/
parentCat: {type: Number}
}
}
constructor() constructor()
{ {
@ -67,40 +59,84 @@ export class Et2SelectCategory extends Et2StaticSelectMixin(Et2Select)
this.noLang = true; this.noLang = true;
} }
async connectedCallback() connectedCallback()
{ {
super.connectedCallback(); super.connectedCallback();
if(typeof this.application == 'undefined') // Default the application if not set
if(!this.application && this.getInstanceManager())
{ {
this.application = this.application = this.getInstanceManager().app;
// When the widget is first created, it doesn't have a parent and can't find it's instanceManager
(this.getInstanceManager() && this.getInstanceManager().app) ||
this.egw().app_name();
} }
}
// Set the search options from our properties
this.searchOptions.application = this.application;
this.searchOptions.globalCategories = this.globalCategories;
this.fetchComplete = so.cat(this).then(options => {
this.select_options = options;
this.requestUpdate("select_options");
if (this._tree)
{
this._tree._selectOptions = options
this._tree.requestUpdate();
}
});
}
willUpdate(changedProperties : PropertyValues) willUpdate(changedProperties : PropertyValues)
{ {
super.willUpdate(changedProperties); super.willUpdate(changedProperties);
if(changedProperties.has("globalCategories") || changedProperties.has("application") || changedProperties.has("parentCat")) if (changedProperties.has("globalCategories") ||
changedProperties.has("application") || changedProperties.has("parentCat"))
{ {
this.fetchComplete = so.cat(this).then(options => this.fetchComplete = so.cat(this).then(options => {
{ this.select_options = options;
this._static_options = cleanSelectOptions(options);
this.requestUpdate("select_options"); this.requestUpdate("select_options");
// Shoelace select has rejected our value due to missing option by now, so re-set it
this.updateComplete.then(() =>
{
this.value = this.value;
});
}); });
} }
if(changedProperties.has('application'))
{
this.searchOptions.application = this.application;
}
if(changedProperties.has('globalCategories'))
{
this.searchOptions.globalCategories = this.globalCategories;
}
} }
public get tagTag() : StaticValue
{
return literal`et2-category-tag`;
}
/**
* Set CSS category colors
* @returns {TemplateResult}
* @protected
*/
protected styleTemplate()
{
let css = "";
const catColor = (option) =>
{
css += ".cat_" + option.value + " {--category-color: " + (option.data?.color || "transparent") + ";}\n";
if (typeof option.children === 'object')
{
option.children?.forEach((option) => catColor(option))
}
}
this.select_options.forEach((option => catColor(option)));
// @formatter:off
return html`
<style>${unsafeCSS(css)}</style>
`;
// @formatter:on
}
protected handleValueChange(e) protected handleValueChange(e)
{ {
@ -109,43 +145,7 @@ export class Et2SelectCategory extends Et2StaticSelectMixin(Et2Select)
// Just re-draw to get the colors & icon // Just re-draw to get the colors & icon
this.requestUpdate(); this.requestUpdate();
} }
/**
* Custom, dynamic styling
*
* CSS variables are not making it through to options, re-declaring them here works
*
* @returns {TemplateResult}
* @protected
*/
protected _styleTemplate() : TemplateResult
{
return html`
<style>
${repeat(this.select_options, (option) =>
{
if(typeof option.color == "undefined" || !option.color)
{
return nothing;
}
return unsafeCSS(
(this.getValueAsArray().includes(option.value) ? "::part(combobox) { --category-color: " + option.color + ";}" : "") +
".cat_" + option.value + " {--category-color: " + option.color + ";}"
);
})}
</style>
`;
}
/**
* Use a custom tag for when multiple=true
*
* @returns {string}
*/
public get tagTag() : StaticValue
{
return literal`et2-category-tag`;
}
} }
// @ts-ignore Type problems because of Et2WidgetWithSelectMixin in parent
customElements.define("et2-select-cat", Et2SelectCategory); customElements.define("et2-select-cat", Et2SelectCategory);

View File

@ -1,135 +0,0 @@
/**
* Use a custom tag for when multiple=true
*
* @returns {string}
*/
import {html, literal, StaticValue} from "lit/static-html.js";
import {property} from "lit/decorators/property.js";
import {css, PropertyValues, unsafeCSS} from "lit";
import {Et2TreeDropdown} from "./Et2TreeDropdown";
import {Et2CategoryTag} from "../Et2Select/Tag/Et2CategoryTag";
import {Et2StaticSelectMixin, StaticOptions as so} from "../Et2Select/StaticOptions";
/**
* @since 23.1.x
*/
export class Et2TreeDropdownCategory extends Et2StaticSelectMixin(Et2TreeDropdown)
{
static get styles()
{
return [
super.styles,
css`
:host {
--category-color: transparent;
}
::part(item-item) {
border-inline-start: 4px solid transparent;
border-inline-start-color: var(--category-color, transparent);
}
`
];
}
/**
* Application to get categories from
*/
@property({type: String}) application = '';
/**
* Include global categories
*/
@property({type: Boolean}) globalCategories = true;
private keep_import : Et2CategoryTag
connectedCallback()
{
super.connectedCallback();
// Default the application if not set
if(!this.application && this.getInstanceManager())
{
this.application = this.getInstanceManager().app;
}
// Set the search options from our properties
this.searchOptions.application = this.application;
this.searchOptions.globalCategories = this.globalCategories;
this.fetchComplete = so.cat(this).then(options => {
this.select_options = options;
this.requestUpdate("select_options");
if (this._tree)
{
this._tree._selectOptions = options
this._tree.requestUpdate();
}
});
}
willUpdate(changedProperties : PropertyValues)
{
super.willUpdate(changedProperties);
if (changedProperties.has("globalCategories") ||
changedProperties.has("application") || changedProperties.has("parentCat"))
{
this.fetchComplete = so.cat(this).then(options => {
this.select_options = options;
this.requestUpdate("select_options");
// Shoelace select has rejected our value due to missing option by now, so re-set it
// this.updateComplete.then(() => {
// this.value = this.value;
// });
});
}
if(changedProperties.has('application'))
{
this.searchOptions.application = this.application;
}
if(changedProperties.has('globalCategories'))
{
this.searchOptions.globalCategories = this.globalCategories;
}
}
public get tagTag() : StaticValue
{
return literal`et2-category-tag`;
}
/**
* Set CSS category colors
* @returns {TemplateResult}
* @protected
*/
protected styleTemplate()
{
let css = "";
const catColor = (option) =>
{
css += ".cat_" + option.value + " {--category-color: " + (option.data?.color || "transparent") + ";}\n";
if (typeof option.children === 'object')
{
option.children?.forEach((option) => catColor(option))
}
}
this.select_options.forEach((option => catColor(option)));
// @formatter:off
return html`
<style>${unsafeCSS(css)}</style>
`;
// @formatter:on
}
}
// @ts-ignore Type problems because of Et2WidgetWithSelectMixin in parent
customElements.define("et2-tree-cat", Et2TreeDropdownCategory);

View File

@ -113,7 +113,6 @@ import "./Et2Textbox/Et2Password";
import './Et2Textbox/Et2Searchbox'; import './Et2Textbox/Et2Searchbox';
import "./Et2Tree/Et2Tree"; import "./Et2Tree/Et2Tree";
import "./Et2Tree/Et2TreeDropdown"; import "./Et2Tree/Et2TreeDropdown";
import "./Et2Tree/Et2TreeDropdownCategory";
/* Include all widget classes here, we only care about them registering, not importing anything*/ /* Include all widget classes here, we only care about them registering, not importing anything*/