mirror of
https://github.com/EGroupware/egroupware.git
synced 2025-02-09 23:11:57 +01:00
* Api: Use file selection dialog for selecting target merge document instead of nested menus
This commit is contained in:
parent
7c9b3dd9e8
commit
d24ca39d09
@ -20,6 +20,9 @@ import {et2_valueWidget} from "../etemplate/et2_core_valueWidget";
|
|||||||
import {nm_action} from "../etemplate/et2_extension_nextmatch_actions";
|
import {nm_action} from "../etemplate/et2_extension_nextmatch_actions";
|
||||||
import {Et2Dialog} from "../etemplate/Et2Dialog/Et2Dialog";
|
import {Et2Dialog} from "../etemplate/Et2Dialog/Et2Dialog";
|
||||||
import {Et2Favorites} from "../etemplate/Et2Favorites/Et2Favorites";
|
import {Et2Favorites} from "../etemplate/Et2Favorites/Et2Favorites";
|
||||||
|
import {loadWebComponent} from "../etemplate/Et2Widget/Et2Widget";
|
||||||
|
import {Et2VfsSelectDialog} from "../etemplate/Et2Vfs/Et2VfsSelectDialog";
|
||||||
|
import {Et2Checkbox} from "../etemplate/Et2Checkbox/Et2Checkbox";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Type for push-message
|
* Type for push-message
|
||||||
@ -795,7 +798,7 @@ export abstract class EgwApp
|
|||||||
* @param {egwAction} _action
|
* @param {egwAction} _action
|
||||||
* @param {egwActionObject[]} _selected
|
* @param {egwActionObject[]} _selected
|
||||||
*/
|
*/
|
||||||
merge(_action : egwAction, _selected : egwActionObject[])
|
async mergeAction(_action : egwAction, _selected : egwActionObject[])
|
||||||
{
|
{
|
||||||
// Find what we need
|
// Find what we need
|
||||||
let nm = null;
|
let nm = null;
|
||||||
@ -809,16 +812,10 @@ export abstract class EgwApp
|
|||||||
{
|
{
|
||||||
nm = action.data.nextmatch;
|
nm = action.data.nextmatch;
|
||||||
}
|
}
|
||||||
if(as_pdf === null && action.getActionById('as_pdf') !== null)
|
|
||||||
{
|
|
||||||
as_pdf = action.getActionById('as_pdf').checked;
|
|
||||||
}
|
|
||||||
action = action.parent;
|
action = action.parent;
|
||||||
}
|
}
|
||||||
let all = nm?.getSelection().all || false;
|
let all = nm?.getSelection().all || false;
|
||||||
|
|
||||||
as_pdf = as_pdf || false;
|
|
||||||
|
|
||||||
// Get list of entry IDs
|
// Get list of entry IDs
|
||||||
let ids = [];
|
let ids = [];
|
||||||
for(let i = 0; !all && i < _selected.length; i++)
|
for(let i = 0; !all && i < _selected.length; i++)
|
||||||
@ -826,16 +823,123 @@ export abstract class EgwApp
|
|||||||
let split = _selected[i].id.split("::");
|
let split = _selected[i].id.split("::");
|
||||||
ids.push(split[1]);
|
ids.push(split[1]);
|
||||||
}
|
}
|
||||||
|
let document = await this._getMergeDocument();
|
||||||
|
if(!document.document)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let vars = {
|
let vars = {
|
||||||
..._action.data.merge_data,
|
..._action.data.merge_data,
|
||||||
pdf: as_pdf,
|
document: document.document,
|
||||||
|
pdf: document.pdf ?? false,
|
||||||
select_all: all,
|
select_all: all,
|
||||||
id: JSON.stringify(ids)
|
id: ids
|
||||||
};
|
};
|
||||||
|
if(document.mime == "message/rfc822")
|
||||||
|
{
|
||||||
|
return this._mergeEmail(_action.clone(), vars);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vars.id = JSON.stringify(ids);
|
||||||
|
}
|
||||||
egw.open_link(egw.link('/index.php', vars), '_blank');
|
egw.open_link(egw.link('/index.php', vars), '_blank');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ask the user for a target document to merge into
|
||||||
|
*
|
||||||
|
* @returns {Promise<{document : string, pdf : boolean, mime : string}>}
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
|
||||||
|
protected _getMergeDocument() : Promise<{ document : string, pdf : boolean, mime : string }>
|
||||||
|
{
|
||||||
|
let dirPref = <string>this.egw.preference('document_dir', this.appname) ?? "";
|
||||||
|
let dirs = dirPref.split('/[,\s]+\//');
|
||||||
|
dirs.forEach((d, index) =>
|
||||||
|
{
|
||||||
|
if(index)
|
||||||
|
{
|
||||||
|
d = "/" + d;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let fileSelect = <Et2VfsSelectDialog><unknown>loadWebComponent('et2-vfs-select-dialog', {
|
||||||
|
class: "egw_app_merge_document",
|
||||||
|
title: this.egw.lang("Insert in document"),
|
||||||
|
mode: "open",
|
||||||
|
path: dirs.pop() ?? "",
|
||||||
|
open: true
|
||||||
|
}, this.et2);
|
||||||
|
let pdf = <Et2Checkbox><unknown>loadWebComponent("et2-checkbox", {
|
||||||
|
slot: "footer",
|
||||||
|
label: "As PDF"
|
||||||
|
}, fileSelect);
|
||||||
|
|
||||||
|
// Disable PDF checkbox for emails
|
||||||
|
fileSelect.addEventListener("et2-select", e =>
|
||||||
|
{
|
||||||
|
let canPDF = true;
|
||||||
|
fileSelect.value.forEach(path =>
|
||||||
|
{
|
||||||
|
if(fileSelect.fileInfo(path).mime == "message/rfc822")
|
||||||
|
{
|
||||||
|
canPDF = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
pdf.disabled = !canPDF;
|
||||||
|
});
|
||||||
|
return fileSelect.getComplete().then((values) =>
|
||||||
|
{
|
||||||
|
if(!values[0])
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const value = values[1].pop() ?? "";
|
||||||
|
const fileInfo = fileSelect.fileInfo(value) ?? {};
|
||||||
|
fileSelect.remove();
|
||||||
|
return {document: value, pdf: pdf.getValue(), mime: fileInfo.mime ?? ""};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merging into an email
|
||||||
|
*
|
||||||
|
* @param {object} data
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
protected _mergeEmail(action, data : object)
|
||||||
|
{
|
||||||
|
const ids = data['id'];
|
||||||
|
// egw.open() used if only 1 row selected
|
||||||
|
data['egw_open'] = 'edit-mail--';
|
||||||
|
data['target'] = 'compose_' + data.document;
|
||||||
|
|
||||||
|
// long_task runs menuaction once for each selected row
|
||||||
|
data['nm_action'] = 'long_task';
|
||||||
|
data['popup'] = this.egw.link_get_registry('mail', 'edit_popup');
|
||||||
|
data['message'] = this.egw.lang('insert in %1', data.document);
|
||||||
|
|
||||||
|
data['menuaction'] = 'mail.mail_compose.ajax_merge';
|
||||||
|
action.data = data;
|
||||||
|
|
||||||
|
if(data['select_all'] || ids.length > 1)
|
||||||
|
{
|
||||||
|
data['menuaction'] += "&document=" + data.document + "&merge=" + data.merge;
|
||||||
|
nm_action(action, null, data['target'], {all: data['select_all'], ids: ids});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.egw.open(ids.pop(), 'mail', 'edit', {
|
||||||
|
from: 'merge',
|
||||||
|
document: data.document,
|
||||||
|
merge: data.merge
|
||||||
|
}, data['target']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes actions and handlers on sidebox (delete)
|
* Initializes actions and handlers on sidebox (delete)
|
||||||
*
|
*
|
||||||
|
@ -2414,256 +2414,20 @@ abstract class Merge
|
|||||||
if($export_limit == null)
|
if($export_limit == null)
|
||||||
{
|
{
|
||||||
$export_limit = self::getExportLimit();
|
$export_limit = self::getExportLimit();
|
||||||
} // check if there is a globalsetting
|
|
||||||
|
|
||||||
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($default_doc && ($file = Api\Vfs::stat($default_doc))) // put default document on top
|
|
||||||
{
|
|
||||||
if(!$file['mime'])
|
|
||||||
{
|
|
||||||
$file['mime'] = Api\Vfs::mime_content_type($default_doc);
|
|
||||||
$file['path'] = $default_doc;
|
|
||||||
}
|
|
||||||
$documents['document'] = array(
|
|
||||||
'icon' => Api\Vfs::mime_icon($file['mime']),
|
|
||||||
'caption' => Api\Vfs::decodePath(Api\Vfs::basename($default_doc)),
|
|
||||||
'group' => 1
|
|
||||||
);
|
|
||||||
self::document_editable_action($documents['document'], $file);
|
|
||||||
if($file['mime'] == 'message/rfc822')
|
|
||||||
{
|
|
||||||
self::document_mail_action($documents['document'], $file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$files = array();
|
|
||||||
if($dirs)
|
|
||||||
{
|
|
||||||
// split multiple comma or whitespace separated directories
|
|
||||||
// to still allow space or comma in dirnames, we also use the trailing slash of all pathes to split
|
|
||||||
if(count($dirs = preg_split('/[,\s]+\//', $dirs)) > 1)
|
|
||||||
{
|
|
||||||
foreach($dirs as $n => &$d)
|
|
||||||
{
|
|
||||||
if($n)
|
|
||||||
{
|
|
||||||
$d = '/' . $d;
|
|
||||||
} // re-adding trailing slash removed by split
|
|
||||||
}
|
|
||||||
}
|
|
||||||
foreach($dirs as $dir)
|
|
||||||
{
|
|
||||||
$files += Api\Vfs::find($dir, array(
|
|
||||||
'need_mime' => true,
|
|
||||||
'order' => 'fs_name',
|
|
||||||
'sort' => 'ASC',
|
|
||||||
), true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$dircount = array();
|
|
||||||
foreach($files as $key => $file)
|
|
||||||
{
|
|
||||||
// use only the mime-types we support
|
|
||||||
$parts = explode('.', $file['name']);
|
|
||||||
if(!self::is_implemented($file['mime'], '.' . array_pop($parts)) ||
|
|
||||||
!Api\Vfs::check_access($file['path'], Api\Vfs::READABLE, $file) || // remove files not readable by user
|
|
||||||
$file['path'] === $default_doc) // default doc already added
|
|
||||||
{
|
|
||||||
unset($files[$key]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$dirname = Api\Vfs::dirname($file['path']);
|
|
||||||
if(!isset($dircount[$dirname]))
|
|
||||||
{
|
|
||||||
$dircount[$dirname] = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$dircount[$dirname]++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
foreach($files as $file)
|
|
||||||
{
|
|
||||||
if(count($dircount) > 1)
|
|
||||||
{
|
|
||||||
$name_arr = explode('/', $file['name']);
|
|
||||||
$current_level = &$documents;
|
|
||||||
for($count = 0; $count < count($name_arr); $count++)
|
|
||||||
{
|
|
||||||
if($count == 0)
|
|
||||||
{
|
|
||||||
$current_level = &$documents;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$current_level = &$current_level[$prefix . $name_arr[($count - 1)]]['children'];
|
|
||||||
}
|
|
||||||
switch($count)
|
|
||||||
{
|
|
||||||
case (count($name_arr) - 1):
|
|
||||||
if(!isset($current_level[$prefix . $file['name']]))
|
|
||||||
{
|
|
||||||
$current_level[$prefix . $file['name']] = [];
|
|
||||||
}
|
|
||||||
self::document_editable_action($current_level[$prefix . $file['name']], $file);
|
|
||||||
if($file['mime'] === 'message/rfc822')
|
|
||||||
{
|
|
||||||
self::document_mail_action($current_level[$prefix . $file['name']], $file);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
if(!isset($current_level[$prefix . $name_arr[$count]]))
|
|
||||||
{
|
|
||||||
// create parent folder
|
|
||||||
$current_level[$prefix . $name_arr[$count]] = array(
|
|
||||||
'icon' => 'phpgwapi/foldertree_folder',
|
|
||||||
'caption' => Api\Vfs::decodePath($name_arr[$count]),
|
|
||||||
'group' => 2,
|
|
||||||
'children' => array(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(count($files) >= self::SHOW_DOCS_BY_MIME_LIMIT)
|
|
||||||
{
|
|
||||||
if(!isset($documents[$file['mime']]))
|
|
||||||
{
|
|
||||||
$documents[$file['mime']] = array(
|
|
||||||
'icon' => Api\Vfs::mime_icon($file['mime']),
|
|
||||||
'caption' => Api\MimeMagic::mime2label($file['mime']),
|
|
||||||
'group' => 2,
|
|
||||||
'children' => array(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
$documents[$file['mime']]['children'][$prefix . $file['name']] = array();
|
|
||||||
self::document_editable_action($documents[$file['mime']]['children'][$prefix . $file['name']], $file);
|
|
||||||
if($file['mime'] == 'message/rfc822')
|
|
||||||
{
|
|
||||||
self::document_mail_action($documents[$file['mime']]['children'][$prefix . $file['name']], $file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$documents[$prefix . $file['name']] = array();
|
|
||||||
self::document_editable_action($documents[$prefix . $file['name']], $file);
|
|
||||||
if($file['mime'] == 'message/rfc822')
|
|
||||||
{
|
|
||||||
self::document_mail_action($documents[$prefix . $file['name']], $file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add PDF checkbox
|
|
||||||
$documents['as_pdf'] = array(
|
|
||||||
'caption' => 'As PDF',
|
|
||||||
'checkbox' => true,
|
|
||||||
);
|
|
||||||
return array(
|
return array(
|
||||||
'icon' => 'etemplate/merge',
|
'icon' => 'etemplate/merge',
|
||||||
'caption' => $caption,
|
'caption' => $caption,
|
||||||
'children' => $documents,
|
'onExecute' => 'javaScript:app.' . $GLOBALS['egw_info']['flags']['currentapp'] . '.mergeAction',
|
||||||
// disable action if no document or export completly forbidden for non-admins
|
// disable action if no document or export completly forbidden for non-admins
|
||||||
'enabled' => (boolean)$documents && (self::hasExportLimit($export_limit, 'ISALLOWED') || self::is_export_limit_excepted()),
|
'enabled' => (self::hasExportLimit($export_limit, 'ISALLOWED') || self::is_export_limit_excepted()),
|
||||||
'hideOnDisabled' => true,
|
'hideOnDisabled' => true,
|
||||||
// do not show 'Insert in document', if no documents defined or no export allowed
|
// do not show 'Insert in document', if no documents defined or no export allowed
|
||||||
'group' => $group,
|
'group' => $group,
|
||||||
);
|
'merge_data' => array(
|
||||||
}
|
'menuaction' => $GLOBALS['egw_info']['flags']['currentapp'] . '.' . get_called_class() . '.merge_entries',
|
||||||
|
'merge' => get_called_class()
|
||||||
/**
|
)
|
||||||
* Set up a document action for an eml (email) document
|
|
||||||
*
|
|
||||||
* Email (.eml) documents get special action handling. They don't send a file
|
|
||||||
* back to the client like the other documents. Merging for a single selected
|
|
||||||
* contact opens a compose window, multiple contacts just sends.
|
|
||||||
*
|
|
||||||
* @param array &$action Action to be modified for mail
|
|
||||||
* @param array $file Array of information about the document from Api\Vfs::find
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
private static function document_mail_action(array &$action, $file)
|
|
||||||
{
|
|
||||||
unset($action['postSubmit']);
|
|
||||||
unset($action['onExecute']);
|
|
||||||
|
|
||||||
// Lots takes a while, confirm
|
|
||||||
$action['confirm_multiple'] = lang('Do you want to send the message to all selected entries, WITHOUT further editing?');
|
|
||||||
|
|
||||||
// These parameters trigger compose + merge - only if 1 row
|
|
||||||
$extra = array(
|
|
||||||
'from=merge',
|
|
||||||
'document=' . $file['path'],
|
|
||||||
'merge=' . get_called_class()
|
|
||||||
);
|
|
||||||
|
|
||||||
// egw.open() used if only 1 row selected
|
|
||||||
$action['egw_open'] = 'edit-mail--' . implode('&', $extra);
|
|
||||||
$action['target'] = 'compose_' . $file['path'];
|
|
||||||
|
|
||||||
// long_task runs menuaction once for each selected row
|
|
||||||
$action['nm_action'] = 'long_task';
|
|
||||||
$action['popup'] = Api\Link::get_registry('mail', 'edit_popup');
|
|
||||||
$action['message'] = lang('insert in %1', Api\Vfs::decodePath($file['name']));
|
|
||||||
$action['menuaction'] = 'mail.mail_compose.ajax_merge&document=' . $file['path'] . '&merge=' . get_called_class();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set up a document action so the generated file is saved and opened in
|
|
||||||
* the collabora editor (if collabora is available)
|
|
||||||
*
|
|
||||||
* @param array &$action Action to be modified for editor
|
|
||||||
* @param array $file Array of information about the document from Api\Vfs::find
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
private static function document_editable_action(array &$action, $file)
|
|
||||||
{
|
|
||||||
static $action_base = array(
|
|
||||||
// The same for every file
|
|
||||||
'group' => 2,
|
|
||||||
// Overwritten for every file
|
|
||||||
'icon' => '', //Api\Vfs::mime_icon($file['mime']),
|
|
||||||
'caption' => '', //Api\Vfs::decodePath($name_arr[$count]),
|
|
||||||
);
|
|
||||||
$edit_attributes = array(
|
|
||||||
'menuaction' => $GLOBALS['egw_info']['flags']['currentapp'] . '.' . get_called_class() . '.merge_entries',
|
|
||||||
'document' => $file['path'],
|
|
||||||
'merge' => get_called_class(),
|
|
||||||
);
|
|
||||||
|
|
||||||
$action = array_merge(
|
|
||||||
$action_base,
|
|
||||||
array(
|
|
||||||
'icon' => Api\Vfs::mime_icon($file['mime']),
|
|
||||||
'caption' => Api\Vfs::decodePath(Api\Vfs::basename($file['name'])),
|
|
||||||
'onExecute' => 'javaScript:app.' . $GLOBALS['egw_info']['flags']['currentapp'] . '.merge',
|
|
||||||
'merge_data' => $edit_attributes
|
|
||||||
),
|
|
||||||
// Merge in provided action last, so we can customize if needed (eg: default document)
|
|
||||||
$action
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4202,4 +4202,10 @@ button.shortcut-buttons-flatpickr-button {
|
|||||||
/* Fix tinemce toolbar z-index is way higher (safari only) */
|
/* Fix tinemce toolbar z-index is way higher (safari only) */
|
||||||
.tox .tox-editor-container .tox-editor-header {
|
.tox .tox-editor-container .tox-editor-header {
|
||||||
z-index: auto;
|
z-index: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Right-align "As PDF" checkbox in merge dialog */
|
||||||
|
et2-vfs-select-dialog.egw_app_merge_document et2-checkbox {
|
||||||
|
order: 10;
|
||||||
|
margin-left: auto;
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user