mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-11-21 23:43:17 +01:00
Just get it working WIP
- Fix category tree structure - Switch on tree multiple probably lots of bugs still, looks like we may have to do click on tree = add / remove and not show the value after all
This commit is contained in:
parent
6fa102dfc5
commit
62d9c222b6
@ -148,7 +148,7 @@
|
||||
</columns>
|
||||
<rows>
|
||||
<row valign="top">
|
||||
<tree-cat id="cat_id_tree" options="13,,width:99%"/>
|
||||
<et2-tree-cat id="cat_id_tree" multiple="true" placeholder="Category"/>
|
||||
<et2-select-cat id="cat_id" width="100%" height="195" multiple="true" placeholder="Category"></et2-select-cat>
|
||||
<et2-description></et2-description>
|
||||
<grid width="100%">
|
||||
|
@ -58,7 +58,6 @@ export class Et2MultiselectTree extends Et2Tree {
|
||||
}
|
||||
|
||||
_optionTemplate(selectOption: TreeItemData): TemplateResult<1> {
|
||||
this._currentOption = selectOption
|
||||
let img: String = selectOption.im0 ?? selectOption.im1 ?? selectOption.im2;
|
||||
if (img) {
|
||||
//sl-icon images need to be svgs if there is a png try to find the corresponding svg
|
||||
@ -70,7 +69,8 @@ export class Et2MultiselectTree extends Et2Tree {
|
||||
<sl-tree-item
|
||||
|
||||
id=${selectOption.id}
|
||||
?lazy=${this._currentOption.item?.length === 0 && this._currentOption.child}
|
||||
?selected=${this.value.includes(selectOption.id)}
|
||||
?lazy=${selectOption.item?.length === 0 && selectOption.child}
|
||||
|
||||
@sl-lazy-load=${(event) => {
|
||||
this.handleLazyLoading(selectOption).then((result) => {
|
||||
@ -82,8 +82,8 @@ export class Et2MultiselectTree extends Et2Tree {
|
||||
>
|
||||
<sl-icon src="${img ?? nothing}"></sl-icon>
|
||||
|
||||
${this._currentOption.text}
|
||||
${repeat(this._currentOption.item, this._optionTemplate.bind(this))}
|
||||
${selectOption.text}
|
||||
${(selectOption.item) ? html`${repeat(selectOption.item, this._optionTemplate.bind(this))}` : nothing}
|
||||
</sl-tree-item>`
|
||||
}
|
||||
|
||||
@ -100,8 +100,10 @@ export class Et2MultiselectTree extends Et2Tree {
|
||||
}
|
||||
this.selectedNodes = event.detail.selection;
|
||||
//TODO look at what signature is expected here
|
||||
this.onchange(event,this)
|
||||
|
||||
if(typeof this.onclick == "function")
|
||||
{
|
||||
this.onclick(event.detail.selection[0].id, this, event.detail.previous)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -16,12 +16,14 @@ import {EgwDragDropShoelaceTree} from "../../egw_action/EgwDragDropShoelaceTree"
|
||||
|
||||
export type TreeItemData = {
|
||||
focused?: boolean;
|
||||
// Has children, but they may not be provided in item
|
||||
child: Boolean | 1,
|
||||
data?: Object,//{sieve:true,...} or {acl:true} or other
|
||||
id: string,
|
||||
im0: String,
|
||||
im1: String,
|
||||
im2: String,
|
||||
// Child items
|
||||
item: TreeItemData[],
|
||||
checked?: Boolean,
|
||||
nocheckbox: number | Boolean,
|
||||
@ -98,6 +100,8 @@ export class Et2Tree extends Et2WidgetWithSelectMixin(LitElement)
|
||||
{
|
||||
super();
|
||||
this._selectOptions = [];
|
||||
|
||||
this._optionTemplate = this._optionTemplate.bind(this);
|
||||
}
|
||||
|
||||
//Sl-Trees handle their own onClick events
|
||||
@ -592,7 +596,11 @@ export class Et2Tree extends Et2WidgetWithSelectMixin(LitElement)
|
||||
|
||||
return html`
|
||||
<sl-tree-item
|
||||
part="item"
|
||||
exportparts="checkbox"
|
||||
id=${selectOption.id}
|
||||
title=${selectOption.tooltip || nothing}
|
||||
?selected=${this.value.includes(selectOption.id)}
|
||||
?expanded=${(this.calculateExpandState(selectOption))}
|
||||
?lazy=${selectOption.item?.length === 0 && selectOption.child}
|
||||
?focused=${selectOption.focused || nothing}
|
||||
@ -607,7 +615,7 @@ export class Et2Tree extends Et2WidgetWithSelectMixin(LitElement)
|
||||
<sl-icon src="${img ?? nothing}"></sl-icon>
|
||||
|
||||
${selectOption.text}
|
||||
${selectOption.item ? repeat(selectOption.item, this._optionTemplate.bind(this)) : ""}
|
||||
${selectOption.item ? repeat(selectOption.item, this._optionTemplate) : nothing}
|
||||
</sl-tree-item>`
|
||||
}
|
||||
|
||||
@ -616,6 +624,7 @@ export class Et2Tree extends Et2WidgetWithSelectMixin(LitElement)
|
||||
{
|
||||
return html`
|
||||
<sl-tree
|
||||
.selection=${this.multiple ? "multiple" : "single"}
|
||||
@sl-selection-change=${
|
||||
(event: any) => {
|
||||
this._previousOption = this._currentOption
|
||||
@ -646,7 +655,7 @@ export class Et2Tree extends Et2WidgetWithSelectMixin(LitElement)
|
||||
}
|
||||
|
||||
>
|
||||
${repeat(this._selectOptions, this._optionTemplate.bind(this))}
|
||||
${repeat(this._selectOptions, this._optionTemplate)}
|
||||
</sl-tree>
|
||||
`;
|
||||
}
|
||||
@ -750,7 +759,7 @@ export class Et2Tree extends Et2WidgetWithSelectMixin(LitElement)
|
||||
|
||||
protected updated(_changedProperties: PropertyValues)
|
||||
{
|
||||
this._link_actions(this.actions)
|
||||
// this._link_actions(this.actions)
|
||||
super.updated(_changedProperties);
|
||||
}
|
||||
|
||||
@ -772,15 +781,12 @@ export class Et2Tree extends Et2WidgetWithSelectMixin(LitElement)
|
||||
}
|
||||
|
||||
private calculateExpandState = (selectOption: TreeItemData) => {
|
||||
if (selectOption.id.endsWith("INBOX") || selectOption.id == window.egw.preference("ActiveProfileID", "mail"))
|
||||
{
|
||||
return true
|
||||
}
|
||||
|
||||
if (selectOption.open)
|
||||
{
|
||||
return true
|
||||
}
|
||||
if (
|
||||
if(this._selectOptions.length > 1 &&
|
||||
this._selectOptions[0] == selectOption &&
|
||||
(this._selectOptions.find((selectOption) => {
|
||||
return selectOption.open
|
||||
@ -790,7 +796,10 @@ export class Et2Tree extends Et2WidgetWithSelectMixin(LitElement)
|
||||
{
|
||||
return true //open the first item, if no item is opened
|
||||
}
|
||||
|
||||
if(selectOption.id && (selectOption.id.endsWith("INBOX") || selectOption.id == window.egw.preference("ActiveProfileID", "mail")))
|
||||
{
|
||||
return true
|
||||
}
|
||||
return false
|
||||
;
|
||||
}
|
||||
@ -855,8 +864,5 @@ export class Et2Tree extends Et2WidgetWithSelectMixin(LitElement)
|
||||
}
|
||||
|
||||
customElements.define("et2-tree", Et2Tree);
|
||||
customElements.define("et2-tree-cat", class extends Et2Tree
|
||||
{
|
||||
});
|
||||
|
||||
|
||||
|
@ -44,15 +44,12 @@ export default css`
|
||||
flex-wrap: nowrap;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
gap: 0.1rem 0.5rem;
|
||||
|
||||
background-color: var(--sl-input-background-color);
|
||||
border: solid var(--sl-input-border-width) var(--sl-input-border-color);
|
||||
|
||||
border-radius: var(--sl-input-border-radius-medium);
|
||||
font-size: var(--sl-input-font-size-medium);
|
||||
min-height: var(--sl-input-height-medium);
|
||||
max-height: calc(var(--height, 5) * var(--sl-input-height-medium));
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
padding-block: 0;
|
||||
@ -107,6 +104,9 @@ export default css`
|
||||
.tree-dropdown__tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.1rem 0.5rem;
|
||||
min-height: var(--sl-input-height-medium);
|
||||
max-height: calc(var(--height, 5) * var(--sl-input-height-medium));
|
||||
}
|
||||
|
||||
/* End tags */
|
||||
@ -157,14 +157,17 @@ export default css`
|
||||
border-radius: var(--sl-border-radius-medium);
|
||||
padding-block: var(--sl-spacing-x-small);
|
||||
padding-inline: 0;
|
||||
overflow: auto;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
overscroll-behavior: none;
|
||||
z-index: var(--sl-z-index-dropdown);
|
||||
|
||||
/* Make sure it adheres to the popup's auto size */
|
||||
height: auto;
|
||||
max-width: var(--auto-size-available-width);
|
||||
}
|
||||
|
||||
/* This doesn't work for some reason, it's overwritten somewhere */
|
||||
--size: 1.8em;
|
||||
et2-tree::part(checkbox) {
|
||||
display: none;
|
||||
}
|
||||
`;
|
@ -90,7 +90,8 @@ export class Et2TreeDropdown extends Et2WidgetWithSelectMixin(LitElement)
|
||||
new_value = new_value.split(",")
|
||||
}
|
||||
const oldValue = this.__value;
|
||||
this.__value = <string[]>new_value;
|
||||
// Filter to make sure there are no trailing commas
|
||||
this.__value = <string[]>new_value.filter(v => v);
|
||||
this.requestUpdate("value", oldValue);
|
||||
}
|
||||
|
||||
@ -316,19 +317,41 @@ export class Et2TreeDropdown extends Et2WidgetWithSelectMixin(LitElement)
|
||||
{
|
||||
// Find the tag value and remove it from current value
|
||||
let valueArray = this.getValueAsArray();
|
||||
const oldValue = valueArray.slice(0);
|
||||
const index = valueArray.indexOf(value);
|
||||
valueArray.splice(index, 1);
|
||||
this.value = valueArray;
|
||||
this.requestUpdate("value");
|
||||
this.requestUpdate("value", oldValue);
|
||||
// TODO: Clean up this scope violation
|
||||
// sl-tree-item is not getting its selected attribute updated
|
||||
Array.from(this._tree._tree.querySelectorAll('sl-tree-item')).forEach(e =>
|
||||
{
|
||||
if(this.value.includes(e.id))
|
||||
{
|
||||
e.setAttribute("selected", "");
|
||||
}
|
||||
else
|
||||
{
|
||||
e.removeAttribute("selected");
|
||||
}
|
||||
});
|
||||
this._tree.requestUpdate();
|
||||
this.updateComplete.then(() =>
|
||||
{
|
||||
this.dispatchEvent(new Event("change", {bubbles: true}));
|
||||
});
|
||||
}
|
||||
|
||||
handleTreeChange(event)
|
||||
{
|
||||
const oldValue = this.value;
|
||||
this.value = this._tree.getValue();
|
||||
this.value = event?.detail?.selection?.map(i => i.id) ?? [];
|
||||
this.requestUpdate("value", oldValue);
|
||||
|
||||
this.updateComplete.then(() =>
|
||||
{
|
||||
this.dispatchEvent(new Event("change", {bubbles: true}));
|
||||
});
|
||||
if(!this.multiple)
|
||||
{
|
||||
this.hide();
|
||||
@ -394,14 +417,21 @@ export class Et2TreeDropdown extends Et2WidgetWithSelectMixin(LitElement)
|
||||
tagsTemplate()
|
||||
{
|
||||
const value = this.getValueAsArray();
|
||||
return html`${keyed(this._valueUID, map(value, (value, index) => this.tagTemplate(this.optionSearch(value, this.select_options))))}`;
|
||||
return html`${keyed(this._valueUID, map(value, (value, index) =>
|
||||
{
|
||||
// Deal with value that is not in options
|
||||
const option = this.optionSearch(value, this.select_options);
|
||||
return option ? this.tagTemplate(option) : nothing;
|
||||
}))}`;
|
||||
}
|
||||
|
||||
tagTemplate(option : TreeItemData)
|
||||
{
|
||||
const readonly = (this.readonly || option && typeof (option.disabled) != "undefined" && option.disabled);
|
||||
const isEditable = false && !readonly;
|
||||
const image = this.iconTemplate(option?.option ?? option);
|
||||
const image = option ? this.iconTemplate(option?.option ?? option) : null;
|
||||
const isValid = true;
|
||||
|
||||
return html`
|
||||
<et2-tag
|
||||
part="tag"
|
||||
@ -414,7 +444,7 @@ export class Et2TreeDropdown extends Et2WidgetWithSelectMixin(LitElement)
|
||||
"
|
||||
class=${"tree_tag " + option.class ?? ""}
|
||||
tabindex="-1"
|
||||
?pill=${this.pill}
|
||||
variant=${isValid ? nothing : "danger"}
|
||||
size=${this.size || "medium"}
|
||||
?removable=${!readonly}
|
||||
?readonly=${readonly}
|
||||
@ -468,7 +498,6 @@ export class Et2TreeDropdown extends Et2WidgetWithSelectMixin(LitElement)
|
||||
'tree-dropdown--focused': this.hasFocus,
|
||||
'tree-dropdown--placeholder-visible': isPlaceholderVisible,
|
||||
})}
|
||||
strategy="fixed"
|
||||
flip
|
||||
shift
|
||||
sync="width"
|
||||
@ -504,7 +533,7 @@ export class Et2TreeDropdown extends Et2WidgetWithSelectMixin(LitElement)
|
||||
multiple=${this.multiple}
|
||||
?readonly=${this.readonly}
|
||||
?disabled=${this.disabled}
|
||||
.value=${this.value}
|
||||
value=${this.value}
|
||||
._selectOptions=${this.select_options}
|
||||
|
||||
@sl-selection-change=${this.handleTreeChange}
|
||||
@ -517,3 +546,7 @@ export class Et2TreeDropdown extends Et2WidgetWithSelectMixin(LitElement)
|
||||
}
|
||||
|
||||
customElements.define("et2-tree-dropdown", Et2TreeDropdown);
|
||||
|
||||
customElements.define("et2-tree-cat", class extends Et2TreeDropdown
|
||||
{
|
||||
});
|
@ -473,34 +473,8 @@ class Tree extends Etemplate\Widget
|
||||
$categories = new Api\Categories('',$type3);
|
||||
}
|
||||
$cat2path=array();
|
||||
foreach((array)$categories->return_sorted_array(0,False,'','','',!$type,0,true) as $cat)
|
||||
{
|
||||
$s = stripslashes($cat['name']);
|
||||
|
||||
if ($cat['app_name'] == 'phpgw' || $cat['owner'] == '-1')
|
||||
{
|
||||
$s .= ' ♦';
|
||||
}
|
||||
$cat2path[$cat['id']] = $path = ($cat['parent'] ? $cat2path[$cat['parent']].'/' : '').(string)$cat['id'];
|
||||
|
||||
// 1D array
|
||||
$options[] = $cat + array(
|
||||
'text' => $s,
|
||||
'path' => $path,
|
||||
|
||||
/*
|
||||
These ones to play nice when a user puts a tree & a selectbox with the same
|
||||
ID on the form (addressbook edit):
|
||||
if tree overwrites selectbox options, selectbox will still work
|
||||
*/
|
||||
'value' => $cat['id'],
|
||||
'label' => $s,
|
||||
'title' => $cat['description']
|
||||
);
|
||||
|
||||
// Tree in array
|
||||
//$options[$cat['parent']][] = $cat;
|
||||
}
|
||||
static::processCategory(0, $options, $categories, !$type);
|
||||
// change cat-ids to pathes and preserv unavailible cats (eg. private user-cats)
|
||||
if ($value)
|
||||
{
|
||||
@ -533,4 +507,39 @@ class Tree extends Etemplate\Widget
|
||||
//error_log(__METHOD__."('$widget_type', '$legacy_options', no_lang=".array2string($no_lang).', readonly='.array2string($readonly).", value=$value) returning ".array2string($options));
|
||||
return $options;
|
||||
}
|
||||
|
||||
protected static function processCategory($cat_id, &$options, &$categories, $globals)
|
||||
{
|
||||
foreach((array)$categories->return_array($cat_id ? 'subs' : 'mains', 0, false, '', 'ASC', '', $globals, $cat_id) as $cat)
|
||||
{
|
||||
|
||||
$s = stripslashes($cat['name']);
|
||||
|
||||
if($cat['app_name'] == 'phpgw' || $cat['owner'] == '-1')
|
||||
{
|
||||
$s .= ' ♦';
|
||||
}
|
||||
|
||||
// 1D array
|
||||
$category = $cat + array(
|
||||
'text' => $s,
|
||||
|
||||
/*
|
||||
These ones to play nice when a user puts a tree & a selectbox with the same
|
||||
ID on the form (addressbook edit):
|
||||
if tree overwrites selectbox options, selectbox will still work
|
||||
*/
|
||||
'value' => $cat['id'],
|
||||
'label' => $s,
|
||||
'title' => $cat['description']
|
||||
);
|
||||
if(!empty($cat['children']))
|
||||
{
|
||||
$category['item'] = [];
|
||||
unset($cat['children']);
|
||||
static::processCategory($cat['id'], $category['item'], $categories, $globals);
|
||||
}
|
||||
$options[] = $category;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user