Et2TreeDropdown: server round-trip working

This commit is contained in:
nathan 2024-02-14 10:42:17 -07:00
parent c6bf9954ae
commit 8b21d21291
3 changed files with 37 additions and 18 deletions

View File

@ -77,7 +77,7 @@ export class Et2Tree extends Et2WidgetWithSelectMixin(LitElement)
imagePath: String = egw().webserverUrl + "/api/templates/default/images/dhtmlxtree/" //TODO we will need a different path here! maybe just rename the path?
// description: "Directory for tree structure images, set on server-side to 'dhtmlx' subdir of templates image-directory"
@property()
value = {}
value = []
protected autoloading_url: any;
// private selectOptions: TreeItemData[] = [];

View File

@ -5,7 +5,6 @@ import {property} from "lit/decorators/property.js";
import {classMap} from "lit/directives/class-map.js";
import {state} from "lit/decorators/state.js";
import {HasSlotController} from "../Et2Widget/slot";
import {keyed} from "lit/directives/keyed.js";
import {map} from "lit/directives/map.js";
import {SlPopup, SlRemoveEvent} from "@shoelace-style/shoelace";
import shoelace from "../Styles/shoelace";
@ -344,9 +343,22 @@ export class Et2TreeDropdown extends Et2WidgetWithSelectMixin(LitElement)
handleTreeChange(event)
{
const oldValue = this.value;
this.value = event?.detail?.selection?.map(i => i.id) ?? [];
this.requestUpdate("value", oldValue);
const oldValue = this.value.slice(0);
// For single value, we can just grab selected from the tree. For multiple, we need to manage it.
if(!this.multiple)
{
this.value = event?.detail?.selection?.map(i => i.id) ?? []
}
else
{
const id = event?.detail?.selection?.map(i => i.id).pop();
if(id)
{
// Copy so LitElement knows it changed
this.value = [...this.value, id];
}
}
this.updateComplete.then(() =>
{
@ -417,12 +429,12 @@ export class Et2TreeDropdown extends Et2WidgetWithSelectMixin(LitElement)
tagsTemplate()
{
const value = this.getValueAsArray();
return html`${keyed(this._valueUID, map(value, (value, index) =>
return html`${map(value, (value, index) =>
{
// Deal with value that is not in options
const option = this.optionSearch(value, this.select_options);
const option = this.optionSearch(value, this.select_options, 'item');
return option ? this.tagTemplate(option) : nothing;
}))}`;
})}`;
}
tagTemplate(option : TreeItemData)
@ -530,10 +542,9 @@ export class Et2TreeDropdown extends Et2WidgetWithSelectMixin(LitElement)
</div>
<et2-tree
class="tree-dropdown__tree"
multiple=${this.multiple}
?readonly=${this.readonly}
?disabled=${this.disabled}
value=${this.value}
value=${this.multiple ? nothing : this.value}
._selectOptions=${this.select_options}
@sl-selection-change=${this.handleTreeChange}

View File

@ -225,7 +225,9 @@ class Tree extends Etemplate\Widget
{
return (boolean)array_filter($cats, function($cat) use($id)
{
return $cat['id'] == $id;
return $cat['id'] == $id || (
!empty($cat['item']) && is_array($cat['item']) && static::in_cats($id, $cat['item'])
);
});
}
@ -246,6 +248,8 @@ class Tree extends Etemplate\Widget
$ok = true;
if (!$this->is_readonly($cname, $form_name))
{
$unavailable_name = $form_name . self::UNAVAILABLE_CAT_POSTFIX;
$unavailable_values = (array)self::$request->preserv[$unavailable_name];
$value = $value_in = self::get_array($content, $form_name);
// we can not validate if autoloading is enabled
@ -255,12 +259,16 @@ class Tree extends Etemplate\Widget
$allowed += self::selOptions($form_name);
foreach((array) $value as $val)
{
if(in_array($val, $unavailable_values))
{
continue;
}
if ($this->type == 'tree-cat' && !($this->attrs['multiple'] && !$val) && !self::in_cats($val, $allowed) ||
$this->type == 'tree' && !self::in_tree($val, $allowed))
{
self::set_validation_error($form_name,lang("'%1' is NOT allowed%2)!", $val,
$this->type == 'tree-cat' ? " ('".implode("','",array_keys($allowed)).')' : ''), '');
$value = '';
$val = '';
break;
}
}
@ -269,7 +277,6 @@ class Tree extends Etemplate\Widget
if (is_array($value) && $this->type == 'tree-cat')
{
// unavailable cats need to be merged in again
$unavailable_name = $form_name.self::UNAVAILABLE_CAT_POSTFIX;
if (isset(self::$request->preserv[$unavailable_name]))
{
if ($this->attrs['multiple'])
@ -474,16 +481,16 @@ class Tree extends Etemplate\Widget
}
$cat2path=array();
static::processCategory(0, $options, $categories, !$type);
static::processCategory(0, $options, $categories, !$type, $cat2path);
// change cat-ids to pathes and preserv unavailible cats (eg. private user-cats)
if ($value)
{
$pathes = $unavailable = array();
foreach(is_array($value) ? $value : explode(',',$value) as $cat)
{
if (isset($cat2path[$cat]))
if(in_array($cat, $cat2path))
{
$pathes[] = $cat2path[$cat];
$pathes[] = $cat;
}
else
{
@ -508,7 +515,7 @@ class Tree extends Etemplate\Widget
return $options;
}
protected static function processCategory($cat_id, &$options, &$categories, $globals)
protected static function processCategory($cat_id, &$options, &$categories, $globals, &$cat_id_list)
{
foreach((array)$categories->return_array($cat_id ? 'subs' : 'mains', 0, false, '', 'ASC', '', $globals, $cat_id) as $cat)
{
@ -533,11 +540,12 @@ class Tree extends Etemplate\Widget
'label' => $s,
'title' => $cat['description']
);
$cat_id_list[] = $cat['id'];
if(!empty($cat['children']))
{
$category['item'] = [];
unset($cat['children']);
static::processCategory($cat['id'], $category['item'], $categories, $globals);
static::processCategory($cat['id'], $category['item'], $categories, $globals, $cat_id_list);
}
$options[] = $category;
}