mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-12-22 14:41:29 +01:00
W.I.P on collabora placeholder insert
This commit is contained in:
parent
13198e12c9
commit
29bd739955
271
api/js/etemplate/et2_widget_placeholder.ts
Normal file
271
api/js/etemplate/et2_widget_placeholder.ts
Normal file
@ -0,0 +1,271 @@
|
|||||||
|
/**
|
||||||
|
* EGroupware eTemplate2 - JS Placeholder widgets
|
||||||
|
*
|
||||||
|
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||||
|
* @package etemplate
|
||||||
|
* @subpackage api
|
||||||
|
* @link https://www.egroupware.org
|
||||||
|
* @author Nathan Gray
|
||||||
|
* @copyright Nathan Gray 2021
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*egw:uses
|
||||||
|
et2_core_inputWidget;
|
||||||
|
et2_core_valueWidget;
|
||||||
|
et2_widget_description;
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {et2_valueWidget} from "./et2_core_valueWidget";
|
||||||
|
import {et2_createWidget, et2_register_widget, WidgetConfig} from "./et2_core_widget";
|
||||||
|
import {ClassWithAttributes} from "./et2_core_inheritance";
|
||||||
|
import {et2_dialog} from "./et2_widget_dialog";
|
||||||
|
import {et2_inputWidget} from "./et2_core_inputWidget";
|
||||||
|
import type {egw} from "../jsapi/egw_global";
|
||||||
|
import {et2_selectbox} from "./et2_widget_selectbox";
|
||||||
|
import {et2_description} from "./et2_widget_description";
|
||||||
|
import {et2_link_entry} from "./et2_widget_link";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display a dialog to choose a placeholder
|
||||||
|
*/
|
||||||
|
export class et2_placeholder_select extends et2_inputWidget
|
||||||
|
{
|
||||||
|
static readonly _attributes : any = {
|
||||||
|
insert_callback: {
|
||||||
|
"name": "Insert callback",
|
||||||
|
"description": "Method called with the selected placeholder text",
|
||||||
|
"type": "js"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static placeholders : Object | null = null;
|
||||||
|
|
||||||
|
button : JQuery;
|
||||||
|
submit_callback : any;
|
||||||
|
dialog : et2_dialog;
|
||||||
|
protected value : any;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param _parent
|
||||||
|
* @param _attrs
|
||||||
|
* @memberOf et2_vfsSelect
|
||||||
|
*/
|
||||||
|
constructor(_parent, _attrs? : WidgetConfig, _child? : object)
|
||||||
|
{
|
||||||
|
// Call the inherited constructor
|
||||||
|
super(_parent, _attrs, ClassWithAttributes.extendAttributes(et2_placeholder_select._attributes, _child || {}));
|
||||||
|
|
||||||
|
// Allow no child widgets
|
||||||
|
this.supportedWidgetClasses = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
_content(_content, _callback)
|
||||||
|
{
|
||||||
|
let self = this;
|
||||||
|
if(this.dialog && this.dialog.div)
|
||||||
|
{
|
||||||
|
this.dialog.div.dialog('close');
|
||||||
|
}
|
||||||
|
|
||||||
|
var callback = _callback || this._buildDialog;
|
||||||
|
if(et2_placeholder_select.placeholders === null)
|
||||||
|
{
|
||||||
|
this.egw().loading_prompt('placeholder_select', true, '', 'body');
|
||||||
|
this.egw().json(
|
||||||
|
'EGroupware\\Api\\Etemplate\\Widget\\Placeholder::ajax_get_placeholders',
|
||||||
|
[],
|
||||||
|
function(_content)
|
||||||
|
{
|
||||||
|
this.egw().loading_prompt('placeholder_select', false);
|
||||||
|
et2_placeholder_select.placeholders = _content;
|
||||||
|
callback.apply(self, arguments);
|
||||||
|
}.bind(this)
|
||||||
|
).sendRequest(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this._buildDialog(et2_placeholder_select.placeholders);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds file navigator dialog
|
||||||
|
*
|
||||||
|
* @param {object} _data content
|
||||||
|
*/
|
||||||
|
private _buildDialog(_data)
|
||||||
|
{
|
||||||
|
|
||||||
|
let self = this;
|
||||||
|
let buttons = [
|
||||||
|
{
|
||||||
|
text: this.egw().lang("Insert"),
|
||||||
|
id: "submit",
|
||||||
|
}
|
||||||
|
];
|
||||||
|
let extra_buttons_action = {};
|
||||||
|
|
||||||
|
if(this.options.extra_buttons && this.options.method)
|
||||||
|
{
|
||||||
|
for(let i = 0; i < this.options.extra_buttons.length; i++)
|
||||||
|
{
|
||||||
|
delete (this.options.extra_buttons[i]['click']);
|
||||||
|
buttons.push(this.options.extra_buttons[i]);
|
||||||
|
extra_buttons_action[this.options.extra_buttons[i]['id']] = this.options.extra_buttons[i]['id'];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
buttons.push({text: this.egw().lang("Cancel"), id: "cancel", image: "cancel"});
|
||||||
|
|
||||||
|
let data = {
|
||||||
|
content: {app: '', group: ''},
|
||||||
|
sel_options: {app: [], group: []}
|
||||||
|
};
|
||||||
|
|
||||||
|
Object.keys(_data).map((key) =>
|
||||||
|
{
|
||||||
|
data.sel_options.app.push(
|
||||||
|
{
|
||||||
|
value: key,
|
||||||
|
label: this.egw().lang(key)
|
||||||
|
});
|
||||||
|
});
|
||||||
|
data.sel_options.group = this._get_group_options(Object.keys(_data)[0]);
|
||||||
|
data.content.app = data.sel_options.app[0].value;
|
||||||
|
data.content.group = data.sel_options.group[0].value;
|
||||||
|
|
||||||
|
// callback for dialog
|
||||||
|
this.submit_callback = function(submit_button_id, submit_value, savemode)
|
||||||
|
{
|
||||||
|
if((submit_button_id == 'submit' || (extra_buttons_action && extra_buttons_action[submit_button_id])) && submit_value)
|
||||||
|
{
|
||||||
|
this.options.insert_callback(submit_value.placeholder_list);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}.bind(this);
|
||||||
|
|
||||||
|
this.dialog = <et2_dialog>et2_createWidget("dialog",
|
||||||
|
{
|
||||||
|
callback: this.submit_callback,
|
||||||
|
title: this.options.dialog_title || this.egw().lang("Insert Placeholder"),
|
||||||
|
buttons: buttons,
|
||||||
|
minWidth: 500,
|
||||||
|
minHeight: 400,
|
||||||
|
width: 400,
|
||||||
|
value: data,
|
||||||
|
template: this.egw().webserverUrl + '/api/templates/default/insert_merge_placeholder.xet?1',
|
||||||
|
resizable: true
|
||||||
|
}, et2_dialog._create_parent('api'));
|
||||||
|
this.dialog.template.uniqueId = 'api.insert_merge_placeholder';
|
||||||
|
|
||||||
|
// Keep the dialog always at the top
|
||||||
|
this.dialog.div.parent().css({"z-index": 100000});
|
||||||
|
|
||||||
|
this.dialog.div.on('load', function(e)
|
||||||
|
{
|
||||||
|
console.log(this);
|
||||||
|
|
||||||
|
let app = <et2_selectbox>this.dialog.template.widgetContainer.getDOMWidgetById("app");
|
||||||
|
let group = <et2_selectbox>this.dialog.template.widgetContainer.getDOMWidgetById("group");
|
||||||
|
let placeholder_list = <et2_selectbox>this.dialog.template.widgetContainer.getDOMWidgetById("placeholder_list");
|
||||||
|
let preview = <et2_description>this.dialog.template.widgetContainer.getDOMWidgetById("preview_placeholder");
|
||||||
|
let entry = <et2_link_entry>this.dialog.template.widgetContainer.getDOMWidgetById("entry");
|
||||||
|
|
||||||
|
|
||||||
|
placeholder_list.set_select_options(this._get_placeholders(app.get_value(), group.get_value()));
|
||||||
|
|
||||||
|
// Further setup / styling that can't be done in etemplate
|
||||||
|
this.dialog.template.DOMContainer.style.display = "flex";
|
||||||
|
this.dialog.template.DOMContainer.firstChild.style.display = "flex";
|
||||||
|
group.getDOMNode().size = 5;
|
||||||
|
placeholder_list.getDOMNode().size = 5;
|
||||||
|
|
||||||
|
// Bind some handlers
|
||||||
|
group.onchange = (select_node, select_widget) =>
|
||||||
|
{
|
||||||
|
console.log(this, arguments);
|
||||||
|
placeholder_list.set_select_options(this._get_placeholders(app.get_value(), group.get_value()));
|
||||||
|
preview.set_value("");
|
||||||
|
}
|
||||||
|
placeholder_list.onchange = this._on_placeholder_select.bind(this);
|
||||||
|
entry.onchange = this._on_placeholder_select.bind(this);
|
||||||
|
}.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
doLoadingFinished()
|
||||||
|
{
|
||||||
|
this._content.call(this, null);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
_on_placeholder_select(node, widget : et2_selectbox | et2_link_entry)
|
||||||
|
{
|
||||||
|
let app = <et2_selectbox>this.dialog.template.widgetContainer.getDOMWidgetById("app");
|
||||||
|
let entry = <et2_link_entry>this.dialog.template.widgetContainer.getDOMWidgetById("entry");
|
||||||
|
let placeholder_list = <et2_selectbox>this.dialog.template.widgetContainer.getDOMWidgetById("placeholder_list");
|
||||||
|
let preview = <et2_description>this.dialog.template.widgetContainer.getDOMWidgetById("preview_placeholder");
|
||||||
|
let preview_content = <et2_description>this.dialog.template.widgetContainer.getDOMWidgetById("preview_content");
|
||||||
|
console.log(this, arguments);
|
||||||
|
preview.set_value(placeholder_list.get_value());
|
||||||
|
if(placeholder_list.get_value() && entry.get_value() && entry.get_value().app && entry.get_value().id)
|
||||||
|
{
|
||||||
|
// Show the selected placeholder replaced with value from the selected entry
|
||||||
|
this.egw().json(
|
||||||
|
'EGroupware\\Api\\Etemplate\\Widget\\Placeholder::ajax_fill_placeholders',
|
||||||
|
[entry.get_value().app, placeholder_list.get_value(), entry.get_value().id],
|
||||||
|
function(_content)
|
||||||
|
{
|
||||||
|
preview_content.set_value(_content);
|
||||||
|
preview_content.getDOMNode().parentNode.style.visibility = _content.trim() ? null : 'hidden';
|
||||||
|
}.bind(this)
|
||||||
|
).sendRequest(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
preview_content.getDOMNode().parentNode.style.visibility = 'hidden';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_get_group_options(appname)
|
||||||
|
{
|
||||||
|
let options = [];
|
||||||
|
Object.keys(et2_placeholder_select.placeholders[appname]).map((key) =>
|
||||||
|
{
|
||||||
|
options.push(
|
||||||
|
{
|
||||||
|
value: key,
|
||||||
|
label: this.egw().lang(key)
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
_get_placeholders(appname, group)
|
||||||
|
{
|
||||||
|
let options = [];
|
||||||
|
Object.keys(et2_placeholder_select.placeholders[appname][group]).map((key) =>
|
||||||
|
{
|
||||||
|
options.push(
|
||||||
|
{
|
||||||
|
value: key,
|
||||||
|
label: et2_placeholder_select.placeholders[appname][group][key]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
set_value(value)
|
||||||
|
{
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
getValue()
|
||||||
|
{
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
et2_register_widget(et2_placeholder_select, ["placeholder-select"]);
|
||||||
|
|
@ -62,6 +62,7 @@ import './et2_widget_image';
|
|||||||
import './et2_widget_iframe';
|
import './et2_widget_iframe';
|
||||||
import './et2_widget_file';
|
import './et2_widget_file';
|
||||||
import './et2_widget_link';
|
import './et2_widget_link';
|
||||||
|
import './et2_widget_placeholder';
|
||||||
import './et2_widget_progress';
|
import './et2_widget_progress';
|
||||||
import './et2_widget_portlet';
|
import './et2_widget_portlet';
|
||||||
import './et2_widget_selectAccount';
|
import './et2_widget_selectAccount';
|
||||||
|
@ -246,14 +246,21 @@ class Merge extends Api\Storage\Merge
|
|||||||
'owner' => lang('Owner'),
|
'owner' => lang('Owner'),
|
||||||
) as $name => $label)
|
) as $name => $label)
|
||||||
{
|
{
|
||||||
if (in_array($name,array('start','end')) && $n&1) // main values, which should be in the first column
|
if(in_array($name, array('start',
|
||||||
|
'end')) && $n & 1) // main values, which should be in the first column
|
||||||
{
|
{
|
||||||
echo "</tr>\n";
|
echo "</tr>\n";
|
||||||
$n++;
|
$n++;
|
||||||
}
|
}
|
||||||
if (!($n&1)) echo '<tr>';
|
if(!($n & 1))
|
||||||
echo '<td>{{calendar/#/'.$name.'}}</td><td>'.$label.'</td>';
|
{
|
||||||
if ($n&1) echo "</tr>\n";
|
echo '<tr>';
|
||||||
|
}
|
||||||
|
echo '<td>{{calendar/#/' . $name . '}}</td><td>' . $label . '</td>';
|
||||||
|
if($n & 1)
|
||||||
|
{
|
||||||
|
echo "</tr>\n";
|
||||||
|
}
|
||||||
$n++;
|
$n++;
|
||||||
}
|
}
|
||||||
echo "</table>\n";
|
echo "</table>\n";
|
||||||
@ -261,6 +268,55 @@ class Merge extends Api\Storage\Merge
|
|||||||
$GLOBALS['egw']->framework->render(ob_get_clean());
|
$GLOBALS['egw']->framework->render(ob_get_clean());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a list of placeholders provided.
|
||||||
|
*
|
||||||
|
* Placeholders are grouped logically. Group key should have a user-friendly translation.
|
||||||
|
*/
|
||||||
|
public function get_placeholder_list()
|
||||||
|
{
|
||||||
|
$placeholders = [];
|
||||||
|
$group = 'contact';
|
||||||
|
foreach($this->contacts->contact_fields as $name => $label)
|
||||||
|
{
|
||||||
|
if(in_array($name, array('tid', 'label', 'geo')))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
} // dont show them, as they are not used in the UI atm.
|
||||||
|
|
||||||
|
switch($name)
|
||||||
|
{
|
||||||
|
case 'adr_one_street':
|
||||||
|
$group = 'business';
|
||||||
|
break;
|
||||||
|
case 'adr_two_street':
|
||||||
|
$group = 'private';
|
||||||
|
break;
|
||||||
|
case 'tel_work':
|
||||||
|
$group = 'phone';
|
||||||
|
break;
|
||||||
|
case 'email':
|
||||||
|
case 'email_home':
|
||||||
|
$group = 'email';
|
||||||
|
break;
|
||||||
|
case 'url':
|
||||||
|
$group = 'details';
|
||||||
|
}
|
||||||
|
$placeholders[$group]["{{" . $name . "}}"] = $label;
|
||||||
|
if($name == 'cat_id')
|
||||||
|
{
|
||||||
|
$placeholders[$group]["{{" . $name . "}}"] = lang('Category path');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$group = 'customfields';
|
||||||
|
foreach($this->contacts->customfields as $name => $field)
|
||||||
|
{
|
||||||
|
$placeholders[$group]["{{" . $name . "}}"] = $field['label'];
|
||||||
|
}
|
||||||
|
return $placeholders;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get insert-in-document action with optional default document on top
|
* Get insert-in-document action with optional default document on top
|
||||||
*
|
*
|
||||||
|
207
api/src/Etemplate/Widget/Placeholder.php
Normal file
207
api/src/Etemplate/Widget/Placeholder.php
Normal file
@ -0,0 +1,207 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* EGroupware - eTemplate serverside of linking widgets
|
||||||
|
*
|
||||||
|
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||||
|
* @package api
|
||||||
|
* @subpackage etemplate
|
||||||
|
* @link http://www.egroupware.org
|
||||||
|
* @author Nathan Gray
|
||||||
|
* @copyright 2011 Nathan Gray
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace EGroupware\Api\Etemplate\Widget;
|
||||||
|
|
||||||
|
use EGroupware\Api\Etemplate;
|
||||||
|
use EGroupware\Api;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* eTemplate Placeholder
|
||||||
|
* Deals with listing & inserting placeholders, usually into Collabora
|
||||||
|
*/
|
||||||
|
class Placeholder extends Etemplate\Widget
|
||||||
|
{
|
||||||
|
|
||||||
|
public $public_functions = array(
|
||||||
|
'ajax_get_placeholders' => true,
|
||||||
|
'ajax_fill_placeholder' => true
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param string|\XMLReader $xml string with xml or XMLReader positioned on the element to construct
|
||||||
|
* @throws Api\Exception\WrongParameter
|
||||||
|
*/
|
||||||
|
public function __construct($xml = '')
|
||||||
|
{
|
||||||
|
if($xml)
|
||||||
|
{
|
||||||
|
parent::__construct($xml);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set up what we know on the server side.
|
||||||
|
*
|
||||||
|
* Set the options for the application select.
|
||||||
|
*
|
||||||
|
* @param string $cname
|
||||||
|
* @param array $expand values for keys 'c', 'row', 'c_', 'row_', 'cont'
|
||||||
|
*/
|
||||||
|
public function beforeSendToClient($cname, array $expand = null)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the placeholders that match the given parameters.
|
||||||
|
* Default options will get all placeholders in a single request.
|
||||||
|
*/
|
||||||
|
public static function ajax_get_placeholders($apps = null, $group = null)
|
||||||
|
{
|
||||||
|
$placeholders = [];
|
||||||
|
|
||||||
|
if(is_null($apps))
|
||||||
|
{
|
||||||
|
$apps = ['addressbook'];
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach($apps as $appname)
|
||||||
|
{
|
||||||
|
$merge = Api\Storage\Merge::get_app_class($appname);
|
||||||
|
switch($appname)
|
||||||
|
{
|
||||||
|
case 'user':
|
||||||
|
$list = $merge->get_user_replacement_list();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$list = $merge->get_placeholder_list();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(!is_null($group))
|
||||||
|
{
|
||||||
|
$list = array_intersect_key($list, $group);
|
||||||
|
}
|
||||||
|
$placeholders[$appname] = $list;
|
||||||
|
}
|
||||||
|
|
||||||
|
$response = Api\Json\Response::get();
|
||||||
|
$response->data($placeholders);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function ajax_fill_placeholders($app, $content, $entry)
|
||||||
|
{
|
||||||
|
$merge = Api\Storage\Merge::get_app_class($app);
|
||||||
|
$err = "";
|
||||||
|
|
||||||
|
switch($app)
|
||||||
|
{
|
||||||
|
case 'addressbook':
|
||||||
|
default:
|
||||||
|
$merged = $merge->merge_string($content, [$entry['id']], $err, 'text/plain');
|
||||||
|
}
|
||||||
|
$response = Api\Json\Response::get();
|
||||||
|
$response->data($merged);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate input
|
||||||
|
*
|
||||||
|
* Following attributes get checked:
|
||||||
|
* - needed: value must NOT be empty
|
||||||
|
* - min, max: int and float widget only
|
||||||
|
* - maxlength: maximum length of string (longer strings get truncated to allowed size)
|
||||||
|
* - preg: perl regular expression incl. delimiters (set by default for int, float and colorpicker)
|
||||||
|
* - int and float get casted to their type
|
||||||
|
*
|
||||||
|
* @param string $cname current namespace
|
||||||
|
* @param array $expand values for keys 'c', 'row', 'c_', 'row_', 'cont'
|
||||||
|
* @param array $content
|
||||||
|
* @param array &$validated =array() validated content
|
||||||
|
*/
|
||||||
|
public function validate($cname, array $expand, array $content, &$validated = array())
|
||||||
|
{
|
||||||
|
$form_name = self::form_name($cname, $this->id, $expand);
|
||||||
|
|
||||||
|
if(!$this->is_readonly($cname, $form_name))
|
||||||
|
{
|
||||||
|
$value = $value_in =& self::get_array($content, $form_name);
|
||||||
|
|
||||||
|
// keep values added into request by other ajax-functions, eg. files draged into htmlarea (Vfs)
|
||||||
|
if((!$value || is_array($value) && !$value['to_id']) && is_array($expand['cont'][$this->id]) && !empty($expand['cont'][$this->id]['to_id']))
|
||||||
|
{
|
||||||
|
if(!is_array($value))
|
||||||
|
{
|
||||||
|
$value = array(
|
||||||
|
'to_app' => $expand['cont'][$this->id]['to_app'],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
$value['to_id'] = $expand['cont'][$this->id]['to_id'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Link widgets can share IDs, make sure to preserve values from others
|
||||||
|
$already = self::get_array($validated, $form_name);
|
||||||
|
if($already != null)
|
||||||
|
{
|
||||||
|
$value = array_merge($value, $already);
|
||||||
|
}
|
||||||
|
// Automatically do link if user selected entry but didn't click 'Link' button
|
||||||
|
$link = self::get_array($content, self::form_name($cname, $this->id . '_link_entry'));
|
||||||
|
if($this->type == 'link-to' && is_array($link) && $link['app'] && $link['id'])
|
||||||
|
{
|
||||||
|
// Do we have enough information to link automatically?
|
||||||
|
if(is_array($value) && $value['to_id'])
|
||||||
|
{
|
||||||
|
Api\Link::link($value['to_app'], $value['to_id'], $link['app'], $link['id']);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Not enough information, leave it to the application
|
||||||
|
if(!is_array($value['to_id']))
|
||||||
|
{
|
||||||
|
$value['to_id'] = array();
|
||||||
|
}
|
||||||
|
$value['to_id'][] = $link;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look for files - normally handled by ajax
|
||||||
|
$files = self::get_array($content, self::form_name($cname, $this->id . '_file'));
|
||||||
|
if(is_array($files) && !(is_array($value) && $value['to_id']))
|
||||||
|
{
|
||||||
|
$value = array();
|
||||||
|
if(is_dir($GLOBALS['egw_info']['server']['temp_dir']) && is_writable($GLOBALS['egw_info']['server']['temp_dir']))
|
||||||
|
{
|
||||||
|
$path = $GLOBALS['egw_info']['server']['temp_dir'] . '/';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$path = '';
|
||||||
|
}
|
||||||
|
foreach($files as $name => $attrs)
|
||||||
|
{
|
||||||
|
if(!is_array($value['to_id']))
|
||||||
|
{
|
||||||
|
$value['to_id'] = array();
|
||||||
|
}
|
||||||
|
$value['to_id'][] = array(
|
||||||
|
'app' => Api\Link::VFS_APPNAME,
|
||||||
|
'id' => array(
|
||||||
|
'name' => $attrs['name'],
|
||||||
|
'type' => $attrs['type'],
|
||||||
|
'tmp_name' => $path . $name
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$valid =& self::get_array($validated, $form_name, true);
|
||||||
|
if(true)
|
||||||
|
{
|
||||||
|
$valid = $value;
|
||||||
|
}
|
||||||
|
//error_log($this);
|
||||||
|
//error_log(" " . array2string($valid));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1572,6 +1572,25 @@ abstract class Merge
|
|||||||
return $app;
|
return $app;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the correct class for the given app
|
||||||
|
*
|
||||||
|
* @param $appname
|
||||||
|
*/
|
||||||
|
public static function get_app_class($appname)
|
||||||
|
{
|
||||||
|
if(class_exists($appname) && is_subclass_of($appname, 'EGroupware\\Api\\Storage\\Merge'))
|
||||||
|
{
|
||||||
|
$classname = "{$appname}_merge";
|
||||||
|
$document_merge = new $classname();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$document_merge = new Api\Contacts\Merge();
|
||||||
|
}
|
||||||
|
return $document_merge;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the replacements for any entry specified by app & id
|
* Get the replacements for any entry specified by app & id
|
||||||
*
|
*
|
||||||
@ -1580,7 +1599,7 @@ abstract class Merge
|
|||||||
* @param string $content
|
* @param string $content
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function get_app_replacements($app, $id, $content, $prefix='')
|
public function get_app_replacements($app, $id, $content, $prefix = '')
|
||||||
{
|
{
|
||||||
$replacements = array();
|
$replacements = array();
|
||||||
if($app == 'addressbook')
|
if($app == 'addressbook')
|
||||||
|
68
api/templates/default/insert_merge_placeholder.xet
Normal file
68
api/templates/default/insert_merge_placeholder.xet
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE overlay PUBLIC "-//EGroupware GmbH//eTemplate 2//EN" "http://www.egroupware.org/etemplate2.dtd">
|
||||||
|
<!-- $Id$ -->
|
||||||
|
<overlay>
|
||||||
|
<template id="etemplate.insert_merge_placeholder" template="" lang="" group="0" version="21.1.001">
|
||||||
|
<vbox id="outer_box">
|
||||||
|
<hbox id="selects">
|
||||||
|
<vbox>
|
||||||
|
<select id="app"/>
|
||||||
|
<select id="group"/>
|
||||||
|
|
||||||
|
</vbox>
|
||||||
|
<select id="placeholder_list"/>
|
||||||
|
</hbox>
|
||||||
|
<link-entry id="entry" label="Preview with entry"/>
|
||||||
|
<hbox class="preview">
|
||||||
|
<description id="preview_placeholder"/>
|
||||||
|
<button id="insert_placeholder"></button>
|
||||||
|
</hbox>
|
||||||
|
<hbox class="preview">
|
||||||
|
<description id="preview_content"/>
|
||||||
|
<button id="insert_content"></button>
|
||||||
|
</hbox>
|
||||||
|
</vbox>
|
||||||
|
<styles>
|
||||||
|
|
||||||
|
#api\.insert_merge_placeholder_outer_box > #api\.insert_merge_placeholder_selects {
|
||||||
|
flex: 1 1 80%;
|
||||||
|
}
|
||||||
|
#api\.insert_merge_placeholder_outer_box > label.et2_label {
|
||||||
|
flex: 0 1 auto;
|
||||||
|
}
|
||||||
|
#api\.insert_merge_placeholder_outer_box .preview {
|
||||||
|
flex: 1 1 2em;
|
||||||
|
font-size: larger;
|
||||||
|
}
|
||||||
|
select#api\.insert_merge_placeholder_app {
|
||||||
|
flex-grow: 0;
|
||||||
|
}
|
||||||
|
.ui-dialog-content, div.et2_box_widget, div.et2_box_widget > div.et2_box_widget {
|
||||||
|
display: flex;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
}
|
||||||
|
div.et2_hbox {
|
||||||
|
flex-direction: row;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
div.et2_vbox {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 5px;
|
||||||
|
}
|
||||||
|
div.et2_box_widget > * {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
div.et2_link_entry {
|
||||||
|
flex-grow: 0;
|
||||||
|
}
|
||||||
|
div.et2_link_entry input.ui-autocomplete-input {
|
||||||
|
width: 75%
|
||||||
|
}
|
||||||
|
.et2_hbox button {
|
||||||
|
flex: 0 1 24px;
|
||||||
|
height: 24px;
|
||||||
|
}
|
||||||
|
</styles>
|
||||||
|
</template>
|
||||||
|
</overlay>
|
Loading…
Reference in New Issue
Block a user