mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-12-22 06:30:59 +01:00
Merge branch 'master' into new-js-loader to bring it up to date
This commit is contained in:
commit
6559a053f3
@ -14,7 +14,7 @@
|
|||||||
import { EgwApp } from '../../api/js/jsapi/egw_app';
|
import { EgwApp } from '../../api/js/jsapi/egw_app';
|
||||||
import { etemplate2 } from "../../api/js/etemplate/etemplate2";
|
import { etemplate2 } from "../../api/js/etemplate/etemplate2";
|
||||||
import { et2_dialog } from "../../api/js/etemplate/et2_widget_dialog";
|
import { et2_dialog } from "../../api/js/etemplate/et2_widget_dialog";
|
||||||
import { fetchAll } from "../../api/js/etemplate/et2_extension_nextmatch_actions.js";
|
import { nm_action, fetchAll } from "../../api/js/etemplate/et2_extension_nextmatch_actions.js";
|
||||||
import "./CRM.js";
|
import "./CRM.js";
|
||||||
import { egw } from "../../api/js/jsapi/egw_global";
|
import { egw } from "../../api/js/jsapi/egw_global";
|
||||||
/**
|
/**
|
||||||
|
@ -17,7 +17,7 @@ import {EgwApp, PushData} from '../../api/js/jsapi/egw_app';
|
|||||||
import {etemplate2} from "../../api/js/etemplate/etemplate2";
|
import {etemplate2} from "../../api/js/etemplate/etemplate2";
|
||||||
import {et2_dialog} from "../../api/js/etemplate/et2_widget_dialog";
|
import {et2_dialog} from "../../api/js/etemplate/et2_widget_dialog";
|
||||||
import {et2_selectbox} from "../../api/js/etemplate/et2_widget_selectbox";
|
import {et2_selectbox} from "../../api/js/etemplate/et2_widget_selectbox";
|
||||||
import {fetchAll} from "../../api/js/etemplate/et2_extension_nextmatch_actions.js";
|
import {nm_action, fetchAll} from "../../api/js/etemplate/et2_extension_nextmatch_actions.js";
|
||||||
import "./CRM.js";
|
import "./CRM.js";
|
||||||
import {egw} from "../../api/js/jsapi/egw_global";
|
import {egw} from "../../api/js/jsapi/egw_global";
|
||||||
|
|
||||||
|
@ -148,7 +148,7 @@ export class et2_DOMWidget extends et2_widget {
|
|||||||
*/
|
*/
|
||||||
insertChild(_node, _idx) {
|
insertChild(_node, _idx) {
|
||||||
super.insertChild(_node, _idx);
|
super.insertChild(_node, _idx);
|
||||||
if (_node.instanceOf(et2_DOMWidget) && typeof _node.hasOwnProperty('parentNode') && this.getDOMNode(this)) {
|
if (_node.instanceOf && _node.instanceOf(et2_DOMWidget) && typeof _node.hasOwnProperty('parentNode') && this.getDOMNode(this)) {
|
||||||
try {
|
try {
|
||||||
_node.setParentDOMNode(this.getDOMNode(_node));
|
_node.setParentDOMNode(this.getDOMNode(_node));
|
||||||
}
|
}
|
||||||
@ -157,6 +157,10 @@ export class et2_DOMWidget extends et2_widget {
|
|||||||
// will probably try again in doLoadingFinished()
|
// will probably try again in doLoadingFinished()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// _node is actually a Web Component
|
||||||
|
else if (_node instanceof Element) {
|
||||||
|
this.getDOMNode().append(_node);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
isAttached() {
|
isAttached() {
|
||||||
return this.parentNode != null;
|
return this.parentNode != null;
|
||||||
|
@ -270,7 +270,7 @@ export abstract class et2_DOMWidget extends et2_widget implements et2_IDOMNode
|
|||||||
{
|
{
|
||||||
super.insertChild(_node, _idx);
|
super.insertChild(_node, _idx);
|
||||||
|
|
||||||
if(_node.instanceOf(et2_DOMWidget) && typeof _node.hasOwnProperty('parentNode') && this.getDOMNode(this))
|
if(_node.instanceOf && _node.instanceOf(et2_DOMWidget) && typeof _node.hasOwnProperty('parentNode') && this.getDOMNode(this))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -282,6 +282,11 @@ export abstract class et2_DOMWidget extends et2_widget implements et2_IDOMNode
|
|||||||
// will probably try again in doLoadingFinished()
|
// will probably try again in doLoadingFinished()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// _node is actually a Web Component
|
||||||
|
else if (_node instanceof Element )
|
||||||
|
{
|
||||||
|
this.getDOMNode().append(_node);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
isAttached() {
|
isAttached() {
|
||||||
|
@ -544,11 +544,32 @@ export class et2_widget extends ClassWithAttributes {
|
|||||||
this.parseXMLAttrs(_node.attributes, attributes, constructor.prototype);
|
this.parseXMLAttrs(_node.attributes, attributes, constructor.prototype);
|
||||||
// Do an sanity check for the attributes
|
// Do an sanity check for the attributes
|
||||||
ClassWithAttributes.generateAttributeSet(et2_attribute_registry[constructor.name], attributes);
|
ClassWithAttributes.generateAttributeSet(et2_attribute_registry[constructor.name], attributes);
|
||||||
// Creates the new widget, passes this widget as an instance and
|
if (undefined == window.customElements.get(_nodeName)) {
|
||||||
// passes the widgetType. Then it goes on loading the XML for it.
|
// Creates the new widget, passes this widget as an instance and
|
||||||
var widget = new constructor(this, attributes);
|
// passes the widgetType. Then it goes on loading the XML for it.
|
||||||
// Load the widget itself from XML
|
var widget = new constructor(this, attributes);
|
||||||
widget.loadFromXML(_node);
|
// Load the widget itself from XML
|
||||||
|
widget.loadFromXML(_node);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
widget = this.loadWebComponent(_nodeName, _node, attributes);
|
||||||
|
if (this.addChild) {
|
||||||
|
// webcomponent going into old et2_widget
|
||||||
|
this.addChild(widget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return widget;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Load a Web Component
|
||||||
|
* @param _nodeName
|
||||||
|
* @param _node
|
||||||
|
*/
|
||||||
|
loadWebComponent(_nodeName, _node, attributes) {
|
||||||
|
let widget = document.createElement(_nodeName);
|
||||||
|
widget.textContent = _node.textContent;
|
||||||
|
// Apply any set attributes
|
||||||
|
_node.getAttributeNames().forEach(attribute => widget.setAttribute(attribute, attributes[attribute]));
|
||||||
return widget;
|
return widget;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
@ -25,6 +25,7 @@ import {et2_IDOMNode, et2_IInputNode} from "./et2_core_interfaces";
|
|||||||
// fixing circular dependencies by only importing type
|
// fixing circular dependencies by only importing type
|
||||||
import type {et2_container} from "./et2_core_baseWidget";
|
import type {et2_container} from "./et2_core_baseWidget";
|
||||||
import type {et2_inputWidget, et2_input} from "./et2_core_inputWidget";
|
import type {et2_inputWidget, et2_input} from "./et2_core_inputWidget";
|
||||||
|
import {decorateLanguageService} from "ts-lit-plugin/lib/decorate-language-service";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The registry contains all XML tag names and the corresponding widget
|
* The registry contains all XML tag names and the corresponding widget
|
||||||
@ -716,12 +717,40 @@ export class et2_widget extends ClassWithAttributes
|
|||||||
// Do an sanity check for the attributes
|
// Do an sanity check for the attributes
|
||||||
ClassWithAttributes.generateAttributeSet(et2_attribute_registry[constructor.name], attributes);
|
ClassWithAttributes.generateAttributeSet(et2_attribute_registry[constructor.name], attributes);
|
||||||
|
|
||||||
// Creates the new widget, passes this widget as an instance and
|
if(undefined == window.customElements.get(_nodeName))
|
||||||
// passes the widgetType. Then it goes on loading the XML for it.
|
{
|
||||||
var widget = new constructor(this, attributes);
|
// Creates the new widget, passes this widget as an instance and
|
||||||
|
// passes the widgetType. Then it goes on loading the XML for it.
|
||||||
|
var widget = new constructor(this, attributes);
|
||||||
|
|
||||||
// Load the widget itself from XML
|
// Load the widget itself from XML
|
||||||
widget.loadFromXML(_node);
|
widget.loadFromXML(_node);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
widget = this.loadWebComponent(_nodeName, _node, attributes);
|
||||||
|
|
||||||
|
if(this.addChild)
|
||||||
|
{
|
||||||
|
// webcomponent going into old et2_widget
|
||||||
|
this.addChild(widget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return widget;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load a Web Component
|
||||||
|
* @param _nodeName
|
||||||
|
* @param _node
|
||||||
|
*/
|
||||||
|
loadWebComponent(_nodeName : string, _node, attributes : Object) : HTMLElement
|
||||||
|
{
|
||||||
|
let widget = document.createElement(_nodeName);
|
||||||
|
widget.textContent = _node.textContent;
|
||||||
|
|
||||||
|
// Apply any set attributes
|
||||||
|
_node.getAttributeNames().forEach(attribute => widget.setAttribute(attribute, attributes[attribute]));
|
||||||
|
|
||||||
return widget;
|
return widget;
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,11 @@ export function nm_action(_action, _senders, _target, _ids)
|
|||||||
_ids = nm.getSelection();
|
_ids = nm.getSelection();
|
||||||
_action.data.nextmatch = nm;
|
_action.data.nextmatch = nm;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// This will probably fail without nm, but it depends on the action
|
||||||
|
_ids = {ids: _senders.map(function(s) {return s.id;})};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// row ids
|
// row ids
|
||||||
var row_ids = "";
|
var row_ids = "";
|
||||||
|
@ -31,6 +31,7 @@ class Merge extends Api\Storage\Merge
|
|||||||
var $public_functions = array(
|
var $public_functions = array(
|
||||||
'download_by_request' => true,
|
'download_by_request' => true,
|
||||||
'show_replacements' => true,
|
'show_replacements' => true,
|
||||||
|
"merge_entries" => true
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1085,7 +1085,8 @@ abstract class Framework extends Framework\Extra
|
|||||||
$java_script .= '<script type="importmap" nonce="'.htmlspecialchars(ContentSecurityPolicy::addNonce('script-src')).'">'."\n".
|
$java_script .= '<script type="importmap" nonce="'.htmlspecialchars(ContentSecurityPolicy::addNonce('script-src')).'">'."\n".
|
||||||
json_encode(self::getImportMap(), JSON_UNESCAPED_SLASHES|JSON_PRETTY_PRINT)."\n".
|
json_encode(self::getImportMap(), JSON_UNESCAPED_SLASHES|JSON_PRETTY_PRINT)."\n".
|
||||||
"</script>\n";
|
"</script>\n";
|
||||||
|
$java_script .='<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.0.0-beta.44/dist/themes/base.css">
|
||||||
|
<script type="module" src="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.0.0-beta.44/dist/shoelace.js"></script>';
|
||||||
// load our clientside entrypoint egw.js
|
// load our clientside entrypoint egw.js
|
||||||
$java_script .= '<script type="module" src="'.$GLOBALS['egw_info']['server']['webserver_url'].
|
$java_script .= '<script type="module" src="'.$GLOBALS['egw_info']['server']['webserver_url'].
|
||||||
'/api/js/jsapi/egw.js?'.filemtime(EGW_SERVER_ROOT.'/api/js/jsapi/egw.js').'" id="egw_script_id"';
|
'/api/js/jsapi/egw.js?'.filemtime(EGW_SERVER_ROOT.'/api/js/jsapi/egw.js').'" id="egw_script_id"';
|
||||||
@ -1151,6 +1152,9 @@ abstract class Framework extends Framework\Extra
|
|||||||
$prefix.'/api/js/jquery/jquery.noconflict.js';
|
$prefix.'/api/js/jquery/jquery.noconflict.js';
|
||||||
}, $imports);
|
}, $imports);
|
||||||
|
|
||||||
|
ContentSecurityPolicy::add("script-src","https://cdn.skypack.dev");
|
||||||
|
ContentSecurityPolicy::add("script-src","https://cdn.jsdelivr.net");
|
||||||
|
ContentSecurityPolicy::add("style-src","https://cdn.jsdelivr.net");
|
||||||
return ['imports' => $imports];
|
return ['imports' => $imports];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ namespace EGroupware\Api\Storage;
|
|||||||
|
|
||||||
use DOMDocument;
|
use DOMDocument;
|
||||||
use EGroupware\Api;
|
use EGroupware\Api;
|
||||||
|
use EGroupware\Api\Vfs;
|
||||||
use EGroupware\Stylite;
|
use EGroupware\Stylite;
|
||||||
use tidy;
|
use tidy;
|
||||||
use uiaccountsel;
|
use uiaccountsel;
|
||||||
@ -77,6 +78,9 @@ abstract class Merge
|
|||||||
public $export_limit;
|
public $export_limit;
|
||||||
|
|
||||||
|
|
||||||
|
public $public_functions = array(
|
||||||
|
"merge_entries" => true
|
||||||
|
);
|
||||||
/**
|
/**
|
||||||
* Configuration for HTML Tidy to clean up any HTML content that is kept
|
* Configuration for HTML Tidy to clean up any HTML content that is kept
|
||||||
*/
|
*/
|
||||||
@ -2083,10 +2087,6 @@ abstract class Merge
|
|||||||
{
|
{
|
||||||
self::document_mail_action($documents['document'], $file);
|
self::document_mail_action($documents['document'], $file);
|
||||||
}
|
}
|
||||||
else if ($editable_mimes[$file['mime']])
|
|
||||||
{
|
|
||||||
self::document_editable_action($documents['document'], $file);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$files = array();
|
$files = array();
|
||||||
@ -2164,10 +2164,6 @@ abstract class Merge
|
|||||||
{
|
{
|
||||||
self::document_mail_action($current_level[$prefix.$file['name']], $file);
|
self::document_mail_action($current_level[$prefix.$file['name']], $file);
|
||||||
}
|
}
|
||||||
else if ($editable_mimes[$file['mime']])
|
|
||||||
{
|
|
||||||
self::document_editable_action($current_level[$prefix.$file['name']], $file);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -2198,16 +2194,21 @@ abstract class Merge
|
|||||||
}
|
}
|
||||||
$documents[$file['mime']]['children'][$prefix.$file['name']] = array(
|
$documents[$file['mime']]['children'][$prefix.$file['name']] = array(
|
||||||
'caption' => Api\Vfs::decodePath($file['name']),
|
'caption' => Api\Vfs::decodePath($file['name']),
|
||||||
|
'target' => '_blank',
|
||||||
'postSubmit' => true, // download needs post submit (not Ajax) to work
|
'postSubmit' => true, // download needs post submit (not Ajax) to work
|
||||||
);
|
);
|
||||||
|
$edit_attributes = array(
|
||||||
|
'menuaction' => $GLOBALS['egw_info']['flags']['currentapp'].'.'.get_called_class().'.merge_entries',
|
||||||
|
'document' => $file['path'],
|
||||||
|
'merge' => get_called_class(),
|
||||||
|
'id' => '$id',
|
||||||
|
'select_all' => '$select_all'
|
||||||
|
);
|
||||||
|
$documents[$file['mime']]['children'][$prefix.$file['name']]['url'] = urldecode(http_build_query($edit_attributes));
|
||||||
if ($file['mime'] == 'message/rfc822')
|
if ($file['mime'] == 'message/rfc822')
|
||||||
{
|
{
|
||||||
self::document_mail_action($documents[$file['mime']]['children'][$prefix.$file['name']], $file);
|
self::document_mail_action($documents[$file['mime']]['children'][$prefix.$file['name']], $file);
|
||||||
}
|
}
|
||||||
else if ($editable_mimes[$file['mime']])
|
|
||||||
{
|
|
||||||
self::document_editable_action($documents[$file['mime']]['children'][$prefix.$file['name']], $file);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -2215,16 +2216,21 @@ abstract class Merge
|
|||||||
'icon' => Api\Vfs::mime_icon($file['mime']),
|
'icon' => Api\Vfs::mime_icon($file['mime']),
|
||||||
'caption' => Api\Vfs::decodePath($file['name']),
|
'caption' => Api\Vfs::decodePath($file['name']),
|
||||||
'group' => 2,
|
'group' => 2,
|
||||||
'postSubmit' => true, // download needs post submit (not Ajax) to work
|
'target' => '_blank'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$edit_attributes = array(
|
||||||
|
'menuaction' => $GLOBALS['egw_info']['flags']['currentapp'].'.'.get_called_class().'.merge_entries',
|
||||||
|
'document' => $file['path'],
|
||||||
|
'merge' => get_called_class(),
|
||||||
|
'id' => '$id',
|
||||||
|
'select_all' => '$select_all'
|
||||||
|
);
|
||||||
|
$documents[$prefix.$file['name']]['url'] = urldecode(http_build_query($edit_attributes));
|
||||||
if ($file['mime'] == 'message/rfc822')
|
if ($file['mime'] == 'message/rfc822')
|
||||||
{
|
{
|
||||||
self::document_mail_action($documents[$prefix.$file['name']], $file);
|
self::document_mail_action($documents[$prefix.$file['name']], $file);
|
||||||
}
|
}
|
||||||
else if ($editable_mimes[$file['mime']])
|
|
||||||
{
|
|
||||||
self::document_editable_action($documents[$prefix.$file['name']], $file);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2286,15 +2292,14 @@ abstract class Merge
|
|||||||
private static function document_editable_action(Array &$action, $file)
|
private static function document_editable_action(Array &$action, $file)
|
||||||
{
|
{
|
||||||
unset($action['postSubmit']);
|
unset($action['postSubmit']);
|
||||||
$action['nm_action'] = 'location';
|
$edit_attributes = array(
|
||||||
$action['url'] = urldecode(http_build_query(array(
|
|
||||||
'menuaction' => 'collabora.EGroupware\\collabora\\Ui.merge_edit',
|
'menuaction' => 'collabora.EGroupware\\collabora\\Ui.merge_edit',
|
||||||
'document' => $file['path'],
|
'document' => $file['path'],
|
||||||
'merge' => get_called_class(),
|
'merge' => get_called_class(),
|
||||||
'id' => '$id',
|
'id' => '$id',
|
||||||
'select_all' => '$select_all'
|
'select_all' => '$select_all'
|
||||||
)));
|
);
|
||||||
$action['target'] = '_blank';
|
$action['url'] = urldecode(http_build_query($edit_attributes));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2331,6 +2336,167 @@ abstract class Merge
|
|||||||
return lang("Document '%1' does not exist or is not readable for you!",$document);
|
return lang("Document '%1' does not exist or is not readable for you!",$document);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merge the selected IDs into the given document, save it to the VFS, then
|
||||||
|
* either open it in the editor or have the browser download the file.
|
||||||
|
*/
|
||||||
|
public static function merge_entries()
|
||||||
|
{
|
||||||
|
if (class_exists($_REQUEST['merge']) && is_subclass_of($_REQUEST['merge'], 'EGroupware\\Api\\Storage\\Merge'))
|
||||||
|
{
|
||||||
|
$document_merge = new $_REQUEST['merge']();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$document_merge = new Api\Contacts\Merge();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(($error = $document_merge->check_document($_REQUEST['document'],'')))
|
||||||
|
{
|
||||||
|
$response->error($error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ids = is_string($_REQUEST['id']) && strpos($_REQUEST['id'],'[') === FALSE ? explode(',',$_REQUEST['id']) : json_decode($_REQUEST['id'],true);
|
||||||
|
if($_REQUEST['select_all'] === 'true')
|
||||||
|
{
|
||||||
|
$ids = self::get_all_ids($document_merge);
|
||||||
|
}
|
||||||
|
|
||||||
|
$filename = '';
|
||||||
|
$result = $document_merge->merge_file($_REQUEST['document'], $ids, $filename, '', $header);
|
||||||
|
|
||||||
|
if(!is_file($result) || !is_readable($result))
|
||||||
|
{
|
||||||
|
throw new Api\Exception\AssertionFailed("Unable to generate merge file\n". $result);
|
||||||
|
}
|
||||||
|
// Put it into the vfs using user's configured home dir if writable,
|
||||||
|
// or expected home dir (/home/username) if not
|
||||||
|
$target = $_target = (Vfs::is_writable(Vfs::get_home_dir()) ?
|
||||||
|
Vfs::get_home_dir() :
|
||||||
|
"/home/{$GLOBALS['egw_info']['user']['account_lid']}"
|
||||||
|
)."/$filename";
|
||||||
|
$dupe_count = 0;
|
||||||
|
while(is_file(Vfs::PREFIX.$target))
|
||||||
|
{
|
||||||
|
$dupe_count++;
|
||||||
|
$target = Vfs::dirname($_target) . '/' .
|
||||||
|
pathinfo($filename, PATHINFO_FILENAME) .
|
||||||
|
' ('.($dupe_count + 1).')' . '.' .
|
||||||
|
pathinfo($filename, PATHINFO_EXTENSION);
|
||||||
|
}
|
||||||
|
copy($result, Vfs::PREFIX.$target);
|
||||||
|
unlink($result);
|
||||||
|
|
||||||
|
// Find out what to do with it
|
||||||
|
$editable_mimes = array();
|
||||||
|
try {
|
||||||
|
if (class_exists('EGroupware\\collabora\\Bo') &&
|
||||||
|
$GLOBALS['egw_info']['user']['apps']['collabora'] &&
|
||||||
|
($discovery = \EGroupware\collabora\Bo::discover()) &&
|
||||||
|
$GLOBALS['egw_info']['user']['preferences']['filemanager']['merge_open_handler'] != 'download'
|
||||||
|
)
|
||||||
|
{
|
||||||
|
$editable_mimes = $discovery;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (\Exception $e)
|
||||||
|
{
|
||||||
|
// ignore failed discovery
|
||||||
|
unset($e);
|
||||||
|
}
|
||||||
|
if($editable_mimes[Vfs::mime_content_type($target)])
|
||||||
|
{
|
||||||
|
\Egroupware\Api\Egw::redirect_link('/index.php', array(
|
||||||
|
'menuaction' => 'collabora.EGroupware\\Collabora\\Ui.editor',
|
||||||
|
'path'=> $target
|
||||||
|
));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
\Egroupware\Api\Egw::redirect_link(Vfs::download_url($target));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all ids for when they try to do 'Select All', then merge into document
|
||||||
|
*
|
||||||
|
* @param Api\Contacts\Merge $merge App-specific merge object
|
||||||
|
*/
|
||||||
|
protected function get_all_ids(Api\Storage\Merge $merge)
|
||||||
|
{
|
||||||
|
$ids = array();
|
||||||
|
$locations = array('index', 'session_data');
|
||||||
|
|
||||||
|
// Get app
|
||||||
|
list($appname, $_merge) = explode('_', get_class($merge));
|
||||||
|
|
||||||
|
if($merge instanceOf Api\Contacts\Merge)
|
||||||
|
{
|
||||||
|
$appname = 'addressbook';
|
||||||
|
}
|
||||||
|
switch(get_class($merge))
|
||||||
|
{
|
||||||
|
case \calendar_merge::class:
|
||||||
|
$ui_class = 'calendar_uilist';
|
||||||
|
$locations = array('calendar_list');
|
||||||
|
break;
|
||||||
|
case \projectmanager_merge::class;
|
||||||
|
$ui_class = 'projectmanager_ui';
|
||||||
|
$locations = array('project_list');
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$ui_class = $appname . '_ui';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ask app
|
||||||
|
if(class_exists($ui_class))
|
||||||
|
{
|
||||||
|
$ui = new $ui_class();
|
||||||
|
if( method_exists($ui_class, 'get_all_ids') )
|
||||||
|
{
|
||||||
|
return $ui->get_all_ids();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try cache
|
||||||
|
if( method_exists($ui_class, 'get_rows'))
|
||||||
|
{
|
||||||
|
foreach($locations as $location)
|
||||||
|
{
|
||||||
|
$session = Api\Cache::getSession($appname, $location);
|
||||||
|
if($session && $session['row_id'])
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$rows = $readonlys = array();
|
||||||
|
@set_time_limit(0); // switch off the execution time limit, as it's for big selections to small
|
||||||
|
$session['num_rows'] = -1; // all
|
||||||
|
$ui->get_rows($session, $rows, $readonlys);
|
||||||
|
foreach($rows as $row_number => $row)
|
||||||
|
{
|
||||||
|
if(!is_numeric($row_number)) continue;
|
||||||
|
$row_id = $row[$session['row_id'] ? $session['row_id'] : 'id'];
|
||||||
|
switch (get_class($merge))
|
||||||
|
{
|
||||||
|
case \calendar_merge::class:
|
||||||
|
$explody = explode(':',$row_id);
|
||||||
|
$ids[] = array('id' => $explody[0], 'recur_date' => $explody[1]);
|
||||||
|
break;
|
||||||
|
case \timesheet_merge::class:
|
||||||
|
// Skip the rows with totalss
|
||||||
|
if(!is_numeric($row_id)) continue 2; // +1 for switch
|
||||||
|
// Fall through
|
||||||
|
default:
|
||||||
|
$ids[] = $row_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $ids;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a list of supported extentions
|
* Get a list of supported extentions
|
||||||
*/
|
*/
|
||||||
|
@ -27,6 +27,7 @@ class calendar_merge extends Api\Storage\Merge
|
|||||||
var $public_functions = array(
|
var $public_functions = array(
|
||||||
'download_by_request' => true,
|
'download_by_request' => true,
|
||||||
'show_replacements' => true,
|
'show_replacements' => true,
|
||||||
|
'merge_entries' => true
|
||||||
);
|
);
|
||||||
|
|
||||||
// Object for getting calendar info
|
// Object for getting calendar info
|
||||||
|
@ -27,6 +27,7 @@ class filemanager_merge extends Api\Storage\Merge
|
|||||||
*/
|
*/
|
||||||
var $public_functions = array(
|
var $public_functions = array(
|
||||||
'show_replacements' => true,
|
'show_replacements' => true,
|
||||||
|
'merge_entries' => true
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -28,6 +28,7 @@ class infolog_merge extends Api\Storage\Merge
|
|||||||
var $public_functions = array(
|
var $public_functions = array(
|
||||||
'download_by_request' => true,
|
'download_by_request' => true,
|
||||||
'show_replacements' => true,
|
'show_replacements' => true,
|
||||||
|
'merge_entries' => true,
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -46,6 +46,7 @@ delete this entry resources de Diesen Eintrag löschen
|
|||||||
deleted resources de gelöscht
|
deleted resources de gelöscht
|
||||||
description (short) resources de Kurzbeschreibung
|
description (short) resources de Kurzbeschreibung
|
||||||
direct booking permissions resources de Erlaubnis direkt zu buchen
|
direct booking permissions resources de Erlaubnis direkt zu buchen
|
||||||
|
do you really want to delete this resource? resources de Wollen Sie diese Ressource wirklich löschen?
|
||||||
don't use vfs (this will need a symlink --> see readme) resources de Vfs nicht benutzen. (Dies erfordert einen symlink --> siehe README)
|
don't use vfs (this will need a symlink --> see readme) resources de Vfs nicht benutzen. (Dies erfordert einen symlink --> siehe README)
|
||||||
edit this entry resources de Diesen Eintrag bearbeiten
|
edit this entry resources de Diesen Eintrag bearbeiten
|
||||||
event start resources de Ereignis startet
|
event start resources de Ereignis startet
|
||||||
|
@ -46,6 +46,7 @@ delete this entry resources en Delete this entry
|
|||||||
deleted resources en deleted
|
deleted resources en deleted
|
||||||
description (short) resources en Short description
|
description (short) resources en Short description
|
||||||
direct booking permissions resources en Direct booking permissions
|
direct booking permissions resources en Direct booking permissions
|
||||||
|
do you really want to delete this resource? resources en Do you really want to delete this resource?
|
||||||
don't use vfs (this will need a symlink --> see readme) resources en Don't use vfs (this will need a symlink --> see README)
|
don't use vfs (this will need a symlink --> see readme) resources en Don't use vfs (this will need a symlink --> see README)
|
||||||
edit this entry resources en Edit this entry
|
edit this entry resources en Edit this entry
|
||||||
event start resources en Event start
|
event start resources en Event start
|
||||||
|
@ -200,7 +200,7 @@
|
|||||||
<button label="Apply" id="button[apply]" image="apply" background_image="1"/>
|
<button label="Apply" id="button[apply]" image="apply" background_image="1"/>
|
||||||
<button label="Cancel" id="button[cancel]" onclick="window.close();" image="cancel" background_image="1"/>
|
<button label="Cancel" id="button[cancel]" onclick="window.close();" image="cancel" background_image="1"/>
|
||||||
</hbox>
|
</hbox>
|
||||||
<button align="right" label="Delete" id="button[delete]" onclick="et2_dialog.confirm(widget,'Do you really want do delte this resource?','Delete')" image="delete" background_image="1"/>
|
<button align="right" label="Delete" id="button[delete]" onclick="et2_dialog.confirm(widget,'Do you really want to delete this resource?','Delete')" image="delete" background_image="1"/>
|
||||||
</row>
|
</row>
|
||||||
</rows>
|
</rows>
|
||||||
</grid>
|
</grid>
|
||||||
|
@ -82,7 +82,7 @@
|
|||||||
<button label="Book" onclick="window.open(egw::link('/index.php','menuaction=calendar.calendar_uiforms.edit&participants=r$cont[res_id]'),'','dependent=yes,width=750,height=400,location=no,menubar=no,toolbar=no,scrollbars=yes,status=yes');" id="btn_book" statustext="Book this resource"/>
|
<button label="Book" onclick="window.open(egw::link('/index.php','menuaction=calendar.calendar_uiforms.edit&participants=r$cont[res_id]'),'','dependent=yes,width=750,height=400,location=no,menubar=no,toolbar=no,scrollbars=yes,status=yes');" id="btn_book" statustext="Book this resource"/>
|
||||||
</hbox>
|
</hbox>
|
||||||
<hbox align="right">
|
<hbox align="right">
|
||||||
<button label="Delete" onclick="return confirm('Do you really want do delte this resource?');" id="btn_delete"/>
|
<button label="Delete" onclick="return confirm('Do you really want to delete this resource?');" id="btn_delete"/>
|
||||||
</hbox>
|
</hbox>
|
||||||
</hbox>
|
</hbox>
|
||||||
</row>
|
</row>
|
||||||
|
@ -143,7 +143,7 @@
|
|||||||
<row class="dialogHeadbar" >
|
<row class="dialogHeadbar" >
|
||||||
<hbox>
|
<hbox>
|
||||||
<button id="button[apply]" image="apply" background_image="1"/>
|
<button id="button[apply]" image="apply" background_image="1"/>
|
||||||
<button id="button[delete]" onclick="et2_dialog.confirm(widget,'Do you really want do delte this resource?','Delete')" image="delete" background_image="1"/>
|
<button id="button[delete]" onclick="et2_dialog.confirm(widget,'Do you really want to delete this resource?','Delete')" image="delete" background_image="1"/>
|
||||||
<textbox type="integer" id="res_id" readonly="true" class="entry_id"/>
|
<textbox type="integer" id="res_id" readonly="true" class="entry_id"/>
|
||||||
</hbox>
|
</hbox>
|
||||||
</row>
|
</row>
|
||||||
|
@ -29,6 +29,7 @@ class timesheet_merge extends Api\Storage\Merge
|
|||||||
'download_by_request' => true,
|
'download_by_request' => true,
|
||||||
'show_replacements' => true,
|
'show_replacements' => true,
|
||||||
'timesheet_replacements' => true,
|
'timesheet_replacements' => true,
|
||||||
|
'merge_entries' => true
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -239,7 +239,10 @@ class timesheet_ui extends timesheet_bo
|
|||||||
if ($this->data['old_pm_id'])
|
if ($this->data['old_pm_id'])
|
||||||
{
|
{
|
||||||
Link::unlink2(0,TIMESHEET_APP,$content['link_to']['to_id'],0,'projectmanager',$this->data['old_pm_id']);
|
Link::unlink2(0,TIMESHEET_APP,$content['link_to']['to_id'],0,'projectmanager',$this->data['old_pm_id']);
|
||||||
unset($content['link_to']['to_id']['projectmanager:'.$this->data['old_pm_id']]);
|
if(is_array($content['link_to']['to_id']))
|
||||||
|
{
|
||||||
|
unset($content['link_to']['to_id']['projectmanager:' . $this->data['old_pm_id']]);
|
||||||
|
}
|
||||||
unset($this->data['old_pm_id']);
|
unset($this->data['old_pm_id']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user