Entry share changes

- Writable share is now a checkbox
- Add Sharing -> Merge entry into email template, share gets selected options
- Add {{share}} placeholder which creates (by default) read only share
This commit is contained in:
nathangray 2018-10-11 10:09:16 -06:00
parent 970fb80675
commit 117b559a5e
6 changed files with 166 additions and 58 deletions

View File

@ -1895,18 +1895,55 @@ var AppJS = (function(){ "use strict"; return Class.extend(
* @param {egwAction} _action egw actions * @param {egwAction} _action egw actions
* @param {egwActionObject[]} _senders selected nm row * @param {egwActionObject[]} _senders selected nm row
* @param {egwActionObject} _target Drag source. Not used here. * @param {egwActionObject} _target Drag source. Not used here.
* @param {Boolean} _writable Allow edit access from the share.
* @param {Boolean} _files Allow access to files from the share. * @param {Boolean} _files Allow access to files from the share.
* @param {Function} _callback Callback with results
* @returns {Boolean} returns false if not successful * @returns {Boolean} returns false if not successful
*/ */
share_link: function(_action, _senders, _target, _files){ share_link: function(_action, _senders, _target, _writable, _files, _callback){
var path = _senders[0].id; var path = _senders[0].id;
if(typeof _writable === 'undefined' && _action.parent && _action.parent.getActionById('shareWritable'))
{
_writable = _action.parent.getActionById('shareWritable').checked || false;
}
if(typeof _files === 'undefined' && _action.parent && _action.parent.getActionById('shareFiles')) if(typeof _files === 'undefined' && _action.parent && _action.parent.getActionById('shareFiles'))
{ {
_files = _action.parent.getActionById('shareFiles').checked || false; _files = _action.parent.getActionById('shareFiles').checked || false;
} }
egw.json('EGroupware\\Api\\Sharing::ajax_create', [_action.id, path, _files],
this._share_link_callback, this, true, this).sendRequest(); return egw.json('EGroupware\\Api\\Sharing::ajax_create', [_action.id, path, _writable, _files],
return true; _callback ? _callback : this._share_link_callback, this, true, this).sendRequest();
},
share_merge: function(_action, _senders, _target)
{
var parent = _action.parent.parent;
var _writable = false;
var _files = false;
if(parent && parent.getActionById('shareWritable'))
{
_writable = parent.getActionById('shareWritable').checked || false;
}
if(parent && parent.getActionById('shareFiles'))
{
_files = parent.getActionById('shareFiles').checked || false;
}
// Share only works on one at a time
var promises = [];
for(var i = 0; i < _senders.length; i++)
{
promises.push(new Promise(function(resolve, reject) {
this.share_link(_action, [_senders[i]], _target, _writable, _files, resolve);
}.bind(this)));
}
// But merge into email can handle several
Promise.all(promises.map(p => p.catch(e => e)))
.then(function(values) {
// Process document after all shares created
return nm_action(_action, _senders, _target);
});
}, },
/** /**
@ -1938,7 +1975,7 @@ var AppJS = (function(){ "use strict"; return Class.extend(
jQuery("body").off("click", "[name=share_link]", copy_link_to_clipboard); jQuery("body").off("click", "[name=share_link]", copy_link_to_clipboard);
return true; return true;
}, },
title: _data.title ? _data.title : egw.lang("%1 Share Link", _data.action ==='shareWritableLink'? egw.lang("Writable"): egw.lang("Readonly")), title: _data.title ? _data.title : egw.lang("%1 Share Link", _data.writable ? egw.lang("Writable"): egw.lang("Readonly")),
template: _data.template, template: _data.template,
width: 450, width: 450,
value: {content:{ "share_link": _data.share_link }} value: {content:{ "share_link": _data.share_link }}

View File

@ -218,6 +218,9 @@ class Merge extends Api\Storage\Merge
echo '<tr><td>{{'.$name.'}}</td><td colspan="3">'.$label."</td></tr>\n"; echo '<tr><td>{{'.$name.'}}</td><td colspan="3">'.$label."</td></tr>\n";
} }
echo '<tr><td colspan="4"><h3>'.lang('EPL Only').":</h3></td></tr>";
echo '<tr><td>{{share}}</td><td colspan="3">'.lang('Public sharing URL')."</td></tr>\n";
Api\Translation::add_app('calendar'); Api\Translation::add_app('calendar');
echo '<tr><td colspan="4"><h3>'.lang('Calendar fields:')." # = 1, 2, ..., 20, -1</h3></td></tr>"; echo '<tr><td colspan="4"><h3>'.lang('Calendar fields:')." # = 1, 2, ..., 20, -1</h3></td></tr>";
foreach(array( foreach(array(

View File

@ -76,49 +76,33 @@ class Sharing extends \EGroupware\Api\Sharing
*/ */
public static function get_actions($appname, $group = 6) public static function get_actions($appname, $group = 6)
{ {
$actions = array( $actions = parent::get_actions($appname, $group);
'share' => array(
'caption' => lang('Share'), // Add in merge to mail document
'icon' => 'api/share', if ($GLOBALS['egw_info']['user']['apps']['mail'] && class_exists($appname.'_merge'))
'group' => $group,
'allowOnMultiple' => false,
'children' => array(
'shareReadonlyLink' => array(
'caption' => lang('Readonly Share'),
'group' => 1,
'icon' => 'view',
'order' => 11,
'enabled' => "javaScript:app.$appname.is_share_enabled",
'onExecute' => "javaScript:app.$appname.share_link"
),
'shareWritableLink' => array(
'caption' => lang('Writable Share'),
'group' => 1,
'icon' => 'edit',
'allowOnMultiple' => false,
'order' => 11,
'enabled' => "javaScript:app.$appname.is_share_enabled",
'onExecute' => "javaScript:app.$appname.share_link"
),
'shareFiles' => array(
'caption' => lang('Share files'),
'group' => 2,
'enabled' => "javaScript:app.$appname.is_share_enabled",
'checkbox' => true
)
),
));
if(!$GLOBALS['egw_info']['apps']['stylite'])
{ {
array_unshift($actions['share']['children'], array( $documents = call_user_func(array($appname.'_merge', 'document_action'),
'caption' => lang('EPL Only'), $GLOBALS['egw_info']['user']['preferences']['addressbook']['document_dir'],
'group' => 0 1, 'Insert in document', 'shareDocument_'
)); );
foreach($actions['share']['children'] as &$child) $documents['order'] = 20;
// Mail only
foreach($documents['children'] as $key => &$document)
{ {
$child['enabled'] = false; if(strpos($document['target'],'compose_') === FALSE)
{
unset($documents['children'][$key]);
continue;
} }
$document['allowOnMultiple'] = true;
$document['onExecute'] = "javaScript:app.$appname.share_merge";
} }
$documents['enabled'] = !!($GLOBALS['egw_info']['user']['apps']['stylite']);
$actions['share']['children']['shareDocuments'] = $documents;
}
return $actions; return $actions;
} }

View File

@ -389,31 +389,31 @@ class Sharing
'allowOnMultiple' => false, 'allowOnMultiple' => false,
'children' => array( 'children' => array(
'shareReadonlyLink' => array( 'shareReadonlyLink' => array(
'caption' => lang('Readonly Share'), 'caption' => lang('Share link'),
'group' => 1, 'group' => 1,
'icon' => 'view', 'icon' => 'view',
'order' => 11, 'order' => 11,
'enabled' => "javaScript:app.$appname.is_share_enabled", 'enabled' => "javaScript:app.$appname.is_share_enabled",
'onExecute' => "javaScript:app.$appname.share_link" 'onExecute' => "javaScript:app.$appname.share_link"
), ),
'shareWritableLink' => array( 'shareWritable' => array(
'caption' => lang('Writable Share'), 'caption' => lang('Writable'),
'group' => 1, 'group' => 2,
'icon' => 'edit', 'icon' => 'edit',
'allowOnMultiple' => false, 'allowOnMultiple' => true,
'order' => 11,
'enabled' => "javaScript:app.$appname.is_share_enabled", 'enabled' => "javaScript:app.$appname.is_share_enabled",
'onExecute' => "javaScript:app.$appname.share_link" 'checkbox' => true
), ),
'shareFiles' => array( 'shareFiles' => array(
'caption' => lang('Share files'), 'caption' => lang('Share files'),
'group' => 2, 'group' => 2,
'allowOnMultiple' => true,
'enabled' => "javaScript:app.$appname.is_share_enabled", 'enabled' => "javaScript:app.$appname.is_share_enabled",
'checkbox' => true 'checkbox' => true
) )
), ),
)); ));
if(!$GLOBALS['egw_info']['apps']['stylite']) if(!$GLOBALS['egw_info']['user']['apps']['stylite'])
{ {
array_unshift($actions['share']['children'], array( array_unshift($actions['share']['children'], array(
'caption' => lang('EPL Only'), 'caption' => lang('EPL Only'),
@ -591,24 +591,28 @@ class Sharing
* *
* @param String $action * @param String $action
* @param String $path * @param String $path
* @param boolean $writable
* @param boolean $files * @param boolean $files
*/ */
public static function ajax_create($action, $path, $files) public static function ajax_create($action, $path, $writable = false, $files = false)
{ {
$class = self::get_share_class(array('share_path' => $path)); $class = self::get_share_class(array('share_path' => $path));
$share = $class::create( $share = $class::create(
$path, $path,
$action == 'shareWritableLink' ? Sharing::WRITABLE : Sharing::READONLY, $action == $writable ? Sharing::WRITABLE : Sharing::READONLY,
basename($selected), basename($path),
array(), array(),
array( array(
'share_writable' => $action == 'shareWritableLink', 'share_writable' => $writable,
'include_files' => $files 'include_files' => $files
) )
); );
// Store share in session so Merge can find this one and not create a read-only one
\EGroupware\Api\Cache::setSession(__CLASS__, $path, $share);
$arr = array( $arr = array(
'action' => $action, 'action' => $action,
'writable' => $writable,
'share_link' => $class::share2link($share), 'share_link' => $class::share2link($share),
'template' => Etemplate\Widget\Template::rel2url('/filemanager/templates/default/share_dialog.xet') 'template' => Etemplate\Widget\Template::rel2url('/filemanager/templates/default/share_dialog.xet')
); );

View File

@ -450,6 +450,58 @@ abstract class Merge
return $array; return $array;
} }
/**
* Get share placeholder
*
* If the placeholder is present in the content, the share will be automatically
* created.
*/
protected function share_placeholder($app, $id, $prefix, &$content)
{
$replacements = array();
// Skip if no content or content has no share placeholder
if(!$content || strpos($content, '$$share') === FALSE)
{
return $replacements;
}
if(!$GLOBALS['egw_info']['user']['apps']['stylite'])
{
$replacements['$$'.$prefix.'share$$'] = lang('EPL Only');
return $replacements;
}
// Get or create the share
// Check if some other process created the share (with custom options)
// and put it in the session cache for us
$path = "$app::$id";
$session = \EGroupware\Api\Cache::getSession(Api\Sharing::class, $path);
if($session && $session['share_path'] == $path)
{
$share = $session;
}
else
{
// Need to create the share here.
// No way to know here if it should be writable, or who it's going to
$mode = /* ? ? Sharing::WRITABLE :*/ Api\Sharing::READONLY;
$recipients = array();
$extra = array();
//$extra['share_writable'] |= ($mode == Sharing::WRITABLE ? 1 : 0);
$share = \EGroupware\Stylite\Link\Sharing::create($path, $mode, NULL, $recipients, $extra);
}
if($share)
{
$replacements['$$'.$prefix.'share$$'] = $link = Api\Sharing::share2link($share);
}
return $replacements;
}
/** /**
* Format a datetime * Format a datetime
* *
@ -850,6 +902,9 @@ abstract class Merge
$replacements['$$datetime$$'] = Api\DateTime::to('now'); $replacements['$$datetime$$'] = Api\DateTime::to('now');
$replacements['$$time$$'] = Api\DateTime::to('now',false); $replacements['$$time$$'] = Api\DateTime::to('now',false);
$app = $this->get_app();
$replacements += $this->share_placeholder($app, $id, $prefix, $content);
// does our extending class registered table-plugins AND document contains table tags // does our extending class registered table-plugins AND document contains table tags
if ($this->table_plugins && preg_match_all('/\\$\\$table\\/([A-Za-z0-9_]+)\\$\\$(.*?)\\$\\$endtable\\$\\$/s',$content,$matches,PREG_SET_ORDER)) if ($this->table_plugins && preg_match_all('/\\$\\$table\\/([A-Za-z0-9_]+)\\$\\$(.*?)\\$\\$endtable\\$\\$/s',$content,$matches,PREG_SET_ORDER))
{ {
@ -1438,6 +1493,31 @@ abstract class Merge
} }
} }
/**
* Figure out which app we're running as
*
* @return string
*/
protected function get_app()
{
switch (get_class($this))
{
case 'EGroupware\Api\Contacts\Merge':
$app = 'addressbook';
break;
default:
$app = str_replace('_merge','',get_class($this));
if(!in_array($app, $GLOBALS['egw_info']['apps']))
{
$app = false;
}
break;
}
return $app;
}
/** /**
* Get the replacements for any entry specified by app & id * Get the replacements for any entry specified by app & id
* *