mirror of
https://github.com/EGroupware/egroupware.git
synced 2025-01-22 05:49:03 +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 {Et2Dialog} from "../etemplate/Et2Dialog/Et2Dialog";
|
||||
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
|
||||
@ -795,7 +798,7 @@ export abstract class EgwApp
|
||||
* @param {egwAction} _action
|
||||
* @param {egwActionObject[]} _selected
|
||||
*/
|
||||
merge(_action : egwAction, _selected : egwActionObject[])
|
||||
async mergeAction(_action : egwAction, _selected : egwActionObject[])
|
||||
{
|
||||
// Find what we need
|
||||
let nm = null;
|
||||
@ -809,16 +812,10 @@ export abstract class EgwApp
|
||||
{
|
||||
nm = action.data.nextmatch;
|
||||
}
|
||||
if(as_pdf === null && action.getActionById('as_pdf') !== null)
|
||||
{
|
||||
as_pdf = action.getActionById('as_pdf').checked;
|
||||
}
|
||||
action = action.parent;
|
||||
}
|
||||
let all = nm?.getSelection().all || false;
|
||||
|
||||
as_pdf = as_pdf || false;
|
||||
|
||||
// Get list of entry IDs
|
||||
let ids = [];
|
||||
for(let i = 0; !all && i < _selected.length; i++)
|
||||
@ -826,16 +823,123 @@ export abstract class EgwApp
|
||||
let split = _selected[i].id.split("::");
|
||||
ids.push(split[1]);
|
||||
}
|
||||
let document = await this._getMergeDocument();
|
||||
if(!document.document)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
let vars = {
|
||||
..._action.data.merge_data,
|
||||
pdf: as_pdf,
|
||||
document: document.document,
|
||||
pdf: document.pdf ?? false,
|
||||
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');
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
*
|
||||
|
@ -2414,256 +2414,20 @@ abstract class Merge
|
||||
if($export_limit == null)
|
||||
{
|
||||
$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(
|
||||
'icon' => 'etemplate/merge',
|
||||
'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
|
||||
'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,
|
||||
// do not show 'Insert in document', if no documents defined or no export allowed
|
||||
'group' => $group,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
'merge_data' => array(
|
||||
'menuaction' => $GLOBALS['egw_info']['flags']['currentapp'] . '.' . get_called_class() . '.merge_entries',
|
||||
'merge' => get_called_class()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -4202,4 +4202,10 @@ button.shortcut-buttons-flatpickr-button {
|
||||
/* Fix tinemce toolbar z-index is way higher (safari only) */
|
||||
.tox .tox-editor-container .tox-editor-header {
|
||||
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