mirror of
https://github.com/EGroupware/egroupware.git
synced 2025-01-03 04:29:28 +01:00
got LinkEntry mostly working
This commit is contained in:
parent
9b0e1b9206
commit
0aa813a0ff
@ -17,7 +17,7 @@ const ADD_ET2_PREFIX_REGEXP = '#<((/?)([vh]?box|date(-time[^\s]*|-duration|-sinc
|
||||
const ADD_ET2_PREFIX_LAST_GROUP = 6;
|
||||
|
||||
// unconditional of legacy add et2- prefix to this widgets
|
||||
const ADD_ET2_PREFIX_LEGACY_REGEXP = '#<(description|label|image|vfs-mime|vfs-uid|vfs-gid|link|link-string|link-list|favorites)\s([^>]+)/>#m';
|
||||
const ADD_ET2_PREFIX_LEGACY_REGEXP = '#<(description|label|image|vfs-mime|vfs-uid|vfs-gid|link|link-string|link-list|link-search|link-entry|link-apps|favorites)\s([^>]+)/>#m';
|
||||
|
||||
// switch evtl. set output-compression off, as we can't calculate a Content-Length header with transparent compression
|
||||
ini_set('zlib.output_compression', 0);
|
||||
@ -67,6 +67,59 @@ function send_template()
|
||||
// fix <menulist...><menupopup type="select-*"/></menulist> --> <select type="select-*" .../>
|
||||
$str = preg_replace('#<menulist([^>]*)>[\r\n\s]*<menupopup([^>]+>)[\r\n\s]*</menulist>#', '<select$1$2', $str);
|
||||
|
||||
// fix legacy options, so new client-side has not to deal with them
|
||||
$str = preg_replace_callback('#<([^- />]+)(-[^ ]+)?[^>]* (options="([^"]+)")[ />]#', static function ($matches) {
|
||||
// take care of (static) type attribute, if used
|
||||
if (preg_match('/ type="([a-z-]+)"/', $matches[0], $type))
|
||||
{
|
||||
str_replace('<' . $matches[1] . $matches[2], '<' . $type[1], $matches[0]);
|
||||
str_replace($type[0], '', $matches[0]);
|
||||
list($matches[1], $matches[2]) = explode('-', $type[1], 2);
|
||||
}
|
||||
static $legacy_options = array( // use "ignore" to ignore further comma-sep. values, otherwise they are all in last attribute
|
||||
'select' => 'empty_label,ignore',
|
||||
'select-account' => 'empty_label,account_type,ignore',
|
||||
'box' => ',cellpadding,cellspacing,keep',
|
||||
'hbox' => 'cellpadding,cellspacing,keep',
|
||||
'vbox' => 'cellpadding,cellspacing,keep',
|
||||
'groupbox' => 'cellpadding,cellspacing,keep',
|
||||
'checkbox' => 'selected_value,unselected_value,ro_true,ro_false',
|
||||
'radio' => 'set_value,ro_true,ro_false',
|
||||
'customfields' => 'sub-type,use-private,field-names',
|
||||
'date' => 'data_format,ignore', // Legacy option "mode" was never implemented in et2
|
||||
'description' => 'bold-italic,link,activate_links,label_for,link_target,link_popup_size,link_title',
|
||||
'button' => 'image,ro_image',
|
||||
'buttononly' => 'image,ro_image',
|
||||
'link-entry' => 'only_app,application_list',
|
||||
);
|
||||
// prefer more specific type-subtype over just type
|
||||
$names = $legacy_options[$matches[1] . $matches[2]] ?? $legacy_options[$matches[1]] ?? null;
|
||||
if (isset($names))
|
||||
{
|
||||
$names = explode(',', $names);
|
||||
$values = Api\Etemplate\Widget::csv_split($matches[4], count($names));
|
||||
if (count($values) < count($names))
|
||||
{
|
||||
$values = array_merge($values, array_fill(count($values), count($names) - count($values), ''));
|
||||
}
|
||||
$attrs = array_diff(array_combine($names, $values), ['', null]);
|
||||
unset($attrs['ignore']);
|
||||
// fix select options can be either multiple or empty_label
|
||||
if ($matches[1] === 'select' && !empty($attrs['empty_label']) && (int)$attrs['empty_label'] > 0)
|
||||
{
|
||||
$attrs['multiple'] = (int)$attrs['empty_label'];
|
||||
unset($matches['empty_label']);
|
||||
}
|
||||
$options = '';
|
||||
foreach ($attrs as $attr => $value)
|
||||
{
|
||||
$options .= $attr . '="' . $value . '" ';
|
||||
}
|
||||
return str_replace($matches[3], $options, $matches[0]);
|
||||
}
|
||||
return $matches[0];
|
||||
}, $str);
|
||||
|
||||
// Change splitter dockside -> primary + vertical
|
||||
$str = preg_replace_callback('#<split([^>]*?)>(.*)</split>#su', static function ($matches) use ($name) {
|
||||
$tag = 'et2-split';
|
||||
@ -110,58 +163,6 @@ function send_template()
|
||||
}
|
||||
else
|
||||
{
|
||||
// fix legacy options, so new client-side has not to deal with them
|
||||
$str = preg_replace_callback('#<([^- />]+)(-[^ ]+)?[^>]* (options="([^"]+)")[ />]#', static function ($matches) {
|
||||
// take care of (static) type attribute, if used
|
||||
if (preg_match('/ type="([a-z-]+)"/', $matches[0], $type))
|
||||
{
|
||||
str_replace('<' . $matches[1] . $matches[2], '<' . $type[1], $matches[0]);
|
||||
str_replace($type[0], '', $matches[0]);
|
||||
list($matches[1], $matches[2]) = explode('-', $type[1], 2);
|
||||
}
|
||||
static $legacy_options = array( // use "ignore" to ignore further comma-sep. values, otherwise they are all in last attribute
|
||||
'select' => 'empty_label,ignore',
|
||||
'select-account' => 'empty_label,account_type,ignore',
|
||||
'box' => ',cellpadding,cellspacing,keep',
|
||||
'hbox' => 'cellpadding,cellspacing,keep',
|
||||
'vbox' => 'cellpadding,cellspacing,keep',
|
||||
'groupbox' => 'cellpadding,cellspacing,keep',
|
||||
'checkbox' => 'selected_value,unselected_value,ro_true,ro_false',
|
||||
'radio' => 'set_value,ro_true,ro_false',
|
||||
'customfields' => 'sub-type,use-private,field-names',
|
||||
'date' => 'data_format,ignore', // Legacy option "mode" was never implemented in et2
|
||||
'description' => 'bold-italic,link,activate_links,label_for,link_target,link_popup_size,link_title',
|
||||
'button' => 'image,ro_image',
|
||||
'buttononly' => 'image,ro_image',
|
||||
);
|
||||
// prefer more specific type-subtype over just type
|
||||
$names = $legacy_options[$matches[1] . $matches[2]] ?? $legacy_options[$matches[1]] ?? null;
|
||||
if (isset($names))
|
||||
{
|
||||
$names = explode(',', $names);
|
||||
$values = Api\Etemplate\Widget::csv_split($matches[4], count($names));
|
||||
if (count($values) < count($names))
|
||||
{
|
||||
$values = array_merge($values, array_fill(count($values), count($names) - count($values), ''));
|
||||
}
|
||||
$attrs = array_diff(array_combine($names, $values), ['', null]);
|
||||
unset($attrs['ignore']);
|
||||
// fix select options can be either multiple or empty_label
|
||||
if ($matches[1] === 'select' && !empty($attrs['empty_label']) && (int)$attrs['empty_label'] > 0)
|
||||
{
|
||||
$attrs['multiple'] = (int)$attrs['empty_label'];
|
||||
unset($matches['empty_label']);
|
||||
}
|
||||
$options = '';
|
||||
foreach ($attrs as $attr => $value)
|
||||
{
|
||||
$options .= $attr . '="' . $value . '" ';
|
||||
}
|
||||
return str_replace($matches[3], $options, $matches[0]);
|
||||
}
|
||||
return $matches[0];
|
||||
}, $str);
|
||||
|
||||
// fix deprecated attributes: needed, blur, ...
|
||||
static $deprecated = [
|
||||
'needed' => 'required',
|
||||
|
@ -71,8 +71,8 @@ export class Et2LinkAppSelect extends SlotMixin(Et2Select)
|
||||
}
|
||||
}
|
||||
|
||||
protected __app_icons : boolean;
|
||||
protected __application_list : string[];
|
||||
protected __only_app : string;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
@ -91,6 +91,17 @@ export class Et2LinkAppSelect extends SlotMixin(Et2Select)
|
||||
this._handleChange = this._handleChange.bind(this);
|
||||
}
|
||||
|
||||
set only_app(app : string)
|
||||
{
|
||||
this.__only_app = app;
|
||||
this.style.display = app ? 'inline' : 'none';
|
||||
}
|
||||
|
||||
get only_app() : string
|
||||
{
|
||||
return this.__only_app;
|
||||
}
|
||||
|
||||
connectedCallback()
|
||||
{
|
||||
super.connectedCallback();
|
||||
@ -108,6 +119,8 @@ export class Et2LinkAppSelect extends SlotMixin(Et2Select)
|
||||
|
||||
// Register to
|
||||
this.addEventListener("change", this._handleChange);
|
||||
|
||||
if (this.__only_app) this.style.display = 'none';
|
||||
}
|
||||
|
||||
disconnectedCallback()
|
||||
|
@ -4,6 +4,12 @@ import {Et2InputWidget} from "../Et2InputWidget/Et2InputWidget";
|
||||
import {FormControlMixin, ValidateMixin} from "@lion/form-core";
|
||||
import {Et2LinkSearch} from "./Et2LinkSearch";
|
||||
|
||||
export interface LinkEntry {
|
||||
app: string;
|
||||
id: string|number;
|
||||
title?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* EGroupware eTemplate2 - Search & select link entry WebComponent
|
||||
*
|
||||
@ -62,12 +68,24 @@ export class Et2LinkEntry extends Et2InputWidget(FormControlMixin(ValidateMixin(
|
||||
...super.slots,
|
||||
app: () =>
|
||||
{
|
||||
const app = document.createElement("et2-link-apps")
|
||||
const app = <Et2LinkAppSelect>document.createElement("et2-link-apps")
|
||||
app.only_app = this.__only_app;
|
||||
return app;
|
||||
},
|
||||
select: () =>
|
||||
{
|
||||
const select = <Et2LinkSearch><unknown>document.createElement("et2-link-search");
|
||||
select.app = this.__only_app || this.__app;
|
||||
if (this.__value && typeof this.__value === 'object')
|
||||
{
|
||||
select.app = this.__value.app;
|
||||
select.select_options = [{value: this.__value.id, label: this.__value.title}];
|
||||
select.value = this.__value.id;
|
||||
}
|
||||
else
|
||||
{
|
||||
select.value = this.__value;
|
||||
}
|
||||
return select;
|
||||
}
|
||||
}
|
||||
@ -85,15 +103,31 @@ export class Et2LinkEntry extends Et2InputWidget(FormControlMixin(ValidateMixin(
|
||||
this._handleAppChange = this._handleAppChange.bind(this);
|
||||
}
|
||||
|
||||
protected __only_app : string;
|
||||
protected __app : string;
|
||||
|
||||
set only_app(app)
|
||||
{
|
||||
this._appNode.only_app = app;
|
||||
this._searchNode.app = app;
|
||||
this.__only_app = app;
|
||||
if (this._appNode) this._appNode.only_app = app;
|
||||
if (this._searchNode) this._searchNode.app = app;
|
||||
}
|
||||
|
||||
get only_app()
|
||||
{
|
||||
return this._appNode.only_app;
|
||||
return this.__only_app;
|
||||
}
|
||||
|
||||
set app(app)
|
||||
{
|
||||
this.__app = app;
|
||||
if (this._appNode) this._appNode.value = app;
|
||||
if (this._searchNode) this._searchNode.app = app;
|
||||
}
|
||||
|
||||
get app()
|
||||
{
|
||||
return this._appNode?.value || this.__app;
|
||||
}
|
||||
|
||||
get _appNode() : Et2LinkAppSelect
|
||||
@ -122,6 +156,49 @@ export class Et2LinkEntry extends Et2InputWidget(FormControlMixin(ValidateMixin(
|
||||
this._searchNode.app = this._appNode.value;
|
||||
}
|
||||
|
||||
protected __value : LinkEntry|string|number;
|
||||
|
||||
get value() : LinkEntry|string|number
|
||||
{
|
||||
if (this.only_app)
|
||||
{
|
||||
return this._searchNode?.value || this.__value;
|
||||
}
|
||||
return this._searchNode ? {
|
||||
id: this._searchNode?.value || this.__value,
|
||||
app: this._appNode?.value || this.__onlyApp || this.__app,
|
||||
//search: this._searchNode... // content of search field
|
||||
} : this.__value;
|
||||
}
|
||||
|
||||
set value(val: LinkEntry|string|number)
|
||||
{
|
||||
if (!val)
|
||||
{
|
||||
if (this._searchNode) this._searchNode.value = '';
|
||||
}
|
||||
else if (typeof val === 'string')
|
||||
{
|
||||
if (val.indexOf(',') > 0) val = val.replace(",", ":");
|
||||
const vals = val.split(':');
|
||||
this.app = vals[0];
|
||||
if (this._searchNode)
|
||||
{
|
||||
this._searchNode.value = vals[1];
|
||||
}
|
||||
}
|
||||
else // object with attributes: app, id, title
|
||||
{
|
||||
this.app = val.app;
|
||||
if (this._searchNode)
|
||||
{
|
||||
this._searchNode.value = val.id;
|
||||
this._searchNode.select_options = [{value: val.id, label: val.title}];
|
||||
}
|
||||
}
|
||||
this.__value = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {TemplateResult}
|
||||
* @protected
|
||||
|
@ -61,9 +61,16 @@ export class Et2LinkSearch extends Et2Select
|
||||
return;
|
||||
}
|
||||
}
|
||||
// ToDo use egw.request(), not old egw.json()
|
||||
request.sendRequest().then((result) =>
|
||||
{
|
||||
this.processRemoteResults(result);
|
||||
result.response.forEach((response) =>
|
||||
{
|
||||
if (typeof response.data !== 'undefined')
|
||||
{
|
||||
this.processRemoteResults(response.data);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -152,7 +152,13 @@ export const Et2widgetWithSelectMixin = dedupeMixin((superclass) =>
|
||||
let fixed_options = [];
|
||||
for(let key in <any>new_options)
|
||||
{
|
||||
fixed_options.push({value: key, label: new_options[key]});
|
||||
let option : any = new_options[key];
|
||||
if (typeof option === 'string')
|
||||
{
|
||||
option = { label: option };
|
||||
}
|
||||
option.value = key.trim(); // link_search prefixes keys with one space
|
||||
fixed_options.push(option);
|
||||
}
|
||||
this.__select_options = fixed_options;
|
||||
}
|
||||
|
@ -295,7 +295,7 @@ export const Et2WithSearchMixin = dedupeMixin((superclass) =>
|
||||
if(this.getItems().length === 1)
|
||||
{
|
||||
this.getItems()[0].click();
|
||||
this.hide();
|
||||
// not jQuery this.hide();
|
||||
return;
|
||||
}
|
||||
event.preventDefault();
|
||||
@ -379,7 +379,7 @@ export const Et2WithSearchMixin = dedupeMixin((superclass) =>
|
||||
|
||||
protected remoteQuery(search : string, options : object)
|
||||
{
|
||||
return this.egw().json(this.searchUrl, [search]).sendRequest().then((result) =>
|
||||
return this.egw().request(this.searchUrl, [search]).sendRequest().then((result) =>
|
||||
{
|
||||
this.processRemoteResults(result);
|
||||
});
|
||||
@ -392,7 +392,7 @@ export const Et2WithSearchMixin = dedupeMixin((superclass) =>
|
||||
*/
|
||||
protected processRemoteResults(results)
|
||||
{
|
||||
// TODO: Add the results in
|
||||
this.select_options = results;
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user