forked from extern/egroupware
More work in progress of mail tree:
-Initiate first level of mailboxes in subscription dialog, and let autoloading do the rest of expensive operation -Save last state of tree in subscription dialog -Uses new approach for comparing subscribed and unsubscribed folders
This commit is contained in:
parent
a0c38411e9
commit
0c7e104027
@ -97,20 +97,36 @@ class mail_tree
|
|||||||
* @param string $path a node path
|
* @param string $path a node path
|
||||||
* @return array returns an array of data extracted from given node path
|
* @return array returns an array of data extracted from given node path
|
||||||
*/
|
*/
|
||||||
static function getFolderData ($_path, $_hDelimiter)
|
static function pathToFolderData ($_path, $_hDelimiter)
|
||||||
{
|
{
|
||||||
list(,$path) = explode(self::$delimiter, $_path);
|
list(,$path) = explode(self::$delimiter, $_path);
|
||||||
$parts = explode($_hDelimiter, $path);
|
$path_chain = $parts = explode($_hDelimiter, $path);
|
||||||
$name = array_pop($parts);
|
$name = array_pop($parts);
|
||||||
return array (
|
return array (
|
||||||
'name' => $name,
|
'name' => $name,
|
||||||
'mailbox' => $path,
|
'mailbox' => $path,
|
||||||
'parent' => implode($_hDelimiter, $parts),
|
'parent' => implode($_hDelimiter, $parts),
|
||||||
'text' => $name,
|
'text' => $name,
|
||||||
'tooltip' => $name
|
'tooltip' => $name,
|
||||||
|
'path' => $path_chain
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a given node has children attribute set
|
||||||
|
*
|
||||||
|
* @param array $_node array of a node
|
||||||
|
* @return int returns 1 if it has children flag set otherwise 0
|
||||||
|
*/
|
||||||
|
private static function nodeHasChildren ($_node)
|
||||||
|
{
|
||||||
|
$hasChildren = 0;
|
||||||
|
if (in_array('\haschildren', $_node['ATTRIBUTES']) ||
|
||||||
|
in_array('\Haschildren', $_node['ATTRIBUTES']) ||
|
||||||
|
in_array('\HasChildren', $_node['ATTRIBUTES'])) $hasChildren = 1;
|
||||||
|
return $hasChildren;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* getTree provides tree structure regarding to selected node
|
* getTree provides tree structure regarding to selected node
|
||||||
*
|
*
|
||||||
@ -118,22 +134,15 @@ class mail_tree
|
|||||||
* @param string $_profileID = '' icServer id
|
* @param string $_profileID = '' icServer id
|
||||||
* @param int|boolean $_openTopLevel = 1 Open top level folders on load if it's set to 1|true,
|
* @param int|boolean $_openTopLevel = 1 Open top level folders on load if it's set to 1|true,
|
||||||
* false|0 leaves them in closed state
|
* false|0 leaves them in closed state
|
||||||
|
* @param $_noCheckboxNS = false no checkbox for namesapaces makes sure to not put checkbox for namespaces node
|
||||||
*
|
*
|
||||||
* @return array returns an array of mail tree structure according to provided node
|
* @return array returns an array of mail tree structure according to provided node
|
||||||
*/
|
*/
|
||||||
function getTree ($_parent = null, $_profileID = '', $_openTopLevel = 1)
|
function getTree ($_parent = null, $_profileID = '', $_openTopLevel = 1, $_noCheckboxNS = false)
|
||||||
{
|
{
|
||||||
//Init mail folders
|
//Init mail folders
|
||||||
$tree = array(tree::ID=> $_parent?$_parent:0,tree::CHILDREN => array());
|
$tree = array(tree::ID=> $_parent?$_parent:0,tree::CHILDREN => array());
|
||||||
$hDelimiter = $this->ui->mail_bo->getHierarchyDelimiter();
|
$hDelimiter = $this->ui->mail_bo->getHierarchyDelimiter();
|
||||||
$fn_nodeHasChildren = function ($_node)
|
|
||||||
{
|
|
||||||
$hasChildren = 0;
|
|
||||||
if (in_array('\haschildren', $_node['ATTRIBUTES']) ||
|
|
||||||
in_array('\Haschildren', $_node['ATTRIBUTES']) ||
|
|
||||||
in_array('\HasChildren', $_node['ATTRIBUTES'])) $hasChildren = 1;
|
|
||||||
return $hasChildren;
|
|
||||||
};
|
|
||||||
|
|
||||||
if ($_parent) list($_profileID) = explode(self::$delimiter, $_parent);
|
if ($_parent) list($_profileID) = explode(self::$delimiter, $_parent);
|
||||||
|
|
||||||
@ -151,20 +160,20 @@ class mail_tree
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
$nodeInfo = self::getFolderData($_parent, $hDelimiter);
|
$nodeInfo = self::pathToFolderData($_parent, $hDelimiter);
|
||||||
$folders = $this->ui->mail_bo->getFolderArray($nodeInfo['mailbox']);
|
$folders = $this->ui->mail_bo->getFolderArray($nodeInfo['mailbox'],false,2);
|
||||||
} catch (Exception $ex) {
|
} catch (Exception $ex) {
|
||||||
return self::treeLeafNoConnectionArray($_profileID, $ex->getMessage(),array($_profileID), '');
|
return self::treeLeafNoConnectionArray($_profileID, $ex->getMessage(),array($_profileID), '');
|
||||||
}
|
}
|
||||||
|
|
||||||
$childrenNode = array();
|
$childrenNode = array();
|
||||||
foreach ($folders as &$node)
|
foreach ($folders as &$node)
|
||||||
{
|
{
|
||||||
$nodeId = $_profileID.self::$delimiter.$node['MAILBOX'];
|
$nodeId = $_profileID.self::$delimiter.$node['MAILBOX'];
|
||||||
$nodeData = self::getFolderData($nodeId, $node['delimiter']);
|
$nodeData = self::pathToFolderData($nodeId, $node['delimiter']);
|
||||||
$childrenNode[] = array(
|
$childrenNode[] = array(
|
||||||
tree::ID=> $nodeId,
|
tree::ID=> $nodeId,
|
||||||
tree::AUTOLOAD_CHILDREN => $fn_nodeHasChildren($node),
|
tree::AUTOLOAD_CHILDREN => self::nodeHasChildren($node),
|
||||||
tree::CHILDREN =>array(),
|
tree::CHILDREN =>array(),
|
||||||
tree::LABEL => $nodeData['text'],
|
tree::LABEL => $nodeData['text'],
|
||||||
tree::TOOLTIP => $nodeData['tooltip'],
|
tree::TOOLTIP => $nodeData['tooltip'],
|
||||||
@ -201,6 +210,7 @@ class mail_tree
|
|||||||
'sieve' => $accObj->imapServer()->acc_sieve_enabled,
|
'sieve' => $accObj->imapServer()->acc_sieve_enabled,
|
||||||
'spamfolder'=> $accObj->imapServer()->acc_folder_junk?true:false
|
'spamfolder'=> $accObj->imapServer()->acc_folder_junk?true:false
|
||||||
),
|
),
|
||||||
|
tree::NOCHECKBOX => $_noCheckboxNS
|
||||||
);
|
);
|
||||||
self::setOutStructure($baseNode, $tree,self::$delimiter);
|
self::setOutStructure($baseNode, $tree,self::$delimiter);
|
||||||
}
|
}
|
||||||
@ -212,14 +222,21 @@ class mail_tree
|
|||||||
|
|
||||||
foreach ($foldersList as $index => $topFolder)
|
foreach ($foldersList as $index => $topFolder)
|
||||||
{
|
{
|
||||||
|
$nameSpaces = $this->ui->mail_bo->_getNameSpaces();
|
||||||
|
$noCheckbox = false;
|
||||||
|
foreach ($nameSpaces as &$ns)
|
||||||
|
{
|
||||||
|
if($_noCheckboxNS && $ns['prefix'] === $index.$hDelimiter) $noCheckbox = true;
|
||||||
|
}
|
||||||
$parentNode = array(
|
$parentNode = array(
|
||||||
tree::ID=>$_profileID.self::$delimiter.$topFolder[$index]['MAILBOX'],
|
tree::ID=>$_profileID.self::$delimiter.$topFolder[$index]['MAILBOX'],
|
||||||
tree::AUTOLOAD_CHILDREN => $fn_nodeHasChildren($topFolder[$index]),
|
tree::AUTOLOAD_CHILDREN => self::nodeHasChildren($topFolder[$index]),
|
||||||
tree::CHILDREN =>array(),
|
tree::CHILDREN =>array(),
|
||||||
tree::LABEL =>lang($topFolder[$index]['MAILBOX']),
|
tree::LABEL =>lang($topFolder[$index]['MAILBOX']),
|
||||||
tree::OPEN => $_openTopLevel,
|
tree::OPEN => $_openTopLevel,
|
||||||
tree::TOOLTIP => lang($topFolder[$index]['MAILBOX']),
|
tree::TOOLTIP => lang($topFolder[$index]['MAILBOX']),
|
||||||
tree::CHECKED => $topFolder[$index]['SUBSCRIBED']
|
tree::CHECKED => $topFolder[$index]['SUBSCRIBED'],
|
||||||
|
tree::NOCHECKBOX => $noCheckbox
|
||||||
);
|
);
|
||||||
if ($index === "INBOX")
|
if ($index === "INBOX")
|
||||||
{
|
{
|
||||||
@ -267,7 +284,7 @@ class mail_tree
|
|||||||
|
|
||||||
$childNode = array(
|
$childNode = array(
|
||||||
tree::ID => $nodeId,
|
tree::ID => $nodeId,
|
||||||
tree::AUTOLOAD_CHILDREN => $fn_nodeHasChildren($node),
|
tree::AUTOLOAD_CHILDREN => self::nodeHasChildren($node),
|
||||||
tree::CHILDREN => array(),
|
tree::CHILDREN => array(),
|
||||||
tree::LABEL => lang($folderName),
|
tree::LABEL => lang($folderName),
|
||||||
'parent' => $parentPath,
|
'parent' => $parentPath,
|
||||||
@ -387,5 +404,5 @@ class mail_tree
|
|||||||
$insert['item'][] = $data;
|
$insert['item'][] = $data;
|
||||||
//error_log(__METHOD__."() leaving with out=".array2string($out));
|
//error_log(__METHOD__."() leaving with out=".array2string($out));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -238,10 +238,11 @@ class mail_ui
|
|||||||
/**
|
/**
|
||||||
* Ajax function to request next branch of a tree branch
|
* Ajax function to request next branch of a tree branch
|
||||||
*/
|
*/
|
||||||
static function ajax_tree_autoloading ()
|
static function ajax_tree_autoloading ($_id = null)
|
||||||
{
|
{
|
||||||
$mail_ui = new mail_ui();
|
$mail_ui = new mail_ui();
|
||||||
etemplate_widget_tree::send_quote_json($mail_ui->mail_tree->getTree($_GET['id']));
|
$_id = $_id? $_id:$_GET['id'];
|
||||||
|
etemplate_widget_tree::send_quote_json($mail_ui->mail_tree->getTree($_id,'',1,false));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -262,19 +263,28 @@ class mail_ui
|
|||||||
{
|
{
|
||||||
egw_framework::window_close('Missing acc_id!');
|
egw_framework::window_close('Missing acc_id!');
|
||||||
}
|
}
|
||||||
$sel_options['foldertree'] = $this->getFolderTree(false, $profileId, false, false);
|
// Initial tree's options, the rest would be loaded dynamicaly by autoloading,
|
||||||
|
// triggered from client-side. Also, we keep this here as
|
||||||
|
$sel_options['foldertree'] = $this->mail_tree->getTree(null,$profileId,1,true);
|
||||||
|
|
||||||
|
//Get all subscribed folder
|
||||||
|
// as getting all subscribed folder is very fast operation
|
||||||
|
// we can use it to get a comparison base for folders which
|
||||||
|
// got subscribed or unsubscribed by the user
|
||||||
|
try {
|
||||||
|
$subscribed = $this->mail_bo->icServer->listSubscribedMailboxes('',0,true);
|
||||||
|
} catch (Exception $ex) {
|
||||||
|
egw_framework::message($ex->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
if (!is_array($content))
|
if (!is_array($content))
|
||||||
{
|
{
|
||||||
$content['foldertree'] = array();
|
$content['foldertree'] = array();
|
||||||
$allFolders = $this->mail_bo->getFolderObjects(false,false,false,false);
|
|
||||||
foreach ($allFolders as $folder)
|
foreach ($subscribed as $folder)
|
||||||
{
|
{
|
||||||
$folderName = $profileId . self::$delimiter . $folder->folderName;
|
$folderName = $profileId . self::$delimiter . $folder['MAILBOX'];
|
||||||
if ($folder->subscribed)
|
array_push($content['foldertree'], $folderName);
|
||||||
{
|
|
||||||
array_push($content['foldertree'], $folderName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -291,13 +301,30 @@ class mail_ui
|
|||||||
{
|
{
|
||||||
$namespace_roots[] = $profileId . self::$delimiter . str_replace($namespace['delimiter'], '', $namespace['prefix']);
|
$namespace_roots[] = $profileId . self::$delimiter . str_replace($namespace['delimiter'], '', $namespace['prefix']);
|
||||||
}
|
}
|
||||||
error_log(__METHOD__."() namespace_roots=".array2string($namespace_roots));
|
$to_unsubscribe = $to_subscribe = array();
|
||||||
$to_subscribe = array_diff($content['foldertree'], $content['current_subscribed'], $namespace_roots);
|
//$allFoldersData = $this->mail_bo->getFolderArray(null,false,0);
|
||||||
$to_unsubscribe = array_diff($content['current_subscribed'], $content['foldertree'], $namespace_roots);
|
foreach ($content['foldertree'] as $path => $value)
|
||||||
|
{
|
||||||
|
list(,$node) = explode($profileId.self::$delimiter, $path);
|
||||||
|
if ($node)
|
||||||
|
{
|
||||||
|
if (is_array($subscribed) && $subscribed[$node] && !$value['value']) $to_unsubscribe []= $node;
|
||||||
|
if (is_array($subscribed) && !$subscribed[$node] && $value['value']) $to_subscribe [] = $node;
|
||||||
|
if ($value['value']) $cont[] = $path;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
$content['foldertree'] = $cont;
|
||||||
|
// set foldertree options to basic node in order to avoid initial autoloading
|
||||||
|
// from client side, as no options would trigger that.
|
||||||
|
$sel_options['foldertree'] = array('id' => '0', 'item'=> array());
|
||||||
foreach(array_merge($to_subscribe, $to_unsubscribe) as $mailbox)
|
foreach(array_merge($to_subscribe, $to_unsubscribe) as $mailbox)
|
||||||
{
|
{
|
||||||
|
if (in_array($profileId.self::$delimiter.$mailbox, $namespace_roots, true))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
$subscribe = in_array($mailbox, $to_subscribe);
|
$subscribe = in_array($mailbox, $to_subscribe);
|
||||||
list(,$mailbox) = explode(self::$delimiter, $mailbox); // remove profileId and delimiter
|
|
||||||
try {
|
try {
|
||||||
$this->mail_bo->icServer->subscribeMailbox($mailbox, $subscribe);
|
$this->mail_bo->icServer->subscribeMailbox($mailbox, $subscribe);
|
||||||
}
|
}
|
||||||
@ -329,7 +356,9 @@ class mail_ui
|
|||||||
// update foldertree in main window
|
// update foldertree in main window
|
||||||
$parentFolder='INBOX';
|
$parentFolder='INBOX';
|
||||||
$refreshData = array(
|
$refreshData = array(
|
||||||
$profileId => lang($parentFolder)
|
$profileId => lang($parentFolder),
|
||||||
|
'subscribed' => $to_subscribe,
|
||||||
|
'unsubscribed' => $to_unsubscribe
|
||||||
);
|
);
|
||||||
$response = egw_json_response::get();
|
$response = egw_json_response::get();
|
||||||
foreach($refreshData as $folder => &$name)
|
foreach($refreshData as $folder => &$name)
|
||||||
@ -337,7 +366,9 @@ class mail_ui
|
|||||||
$name = $this->getFolderTree(true, $folder, true, true, false);
|
$name = $this->getFolderTree(true, $folder, true, true, false);
|
||||||
}
|
}
|
||||||
// give success/error message to opener and popup itself
|
// give success/error message to opener and popup itself
|
||||||
|
//$response->call('opener.app.mail.subscription_refresh',$refreshData);
|
||||||
$response->call('opener.app.mail.mail_reloadNode',$refreshData);
|
$response->call('opener.app.mail.mail_reloadNode',$refreshData);
|
||||||
|
|
||||||
egw_framework::refresh_opener($msg, 'mail', null, null, null, null, null, $msg_type);
|
egw_framework::refresh_opener($msg, 'mail', null, null, null, null, null, $msg_type);
|
||||||
if ($button == 'apply')
|
if ($button == 'apply')
|
||||||
{
|
{
|
||||||
@ -353,7 +384,7 @@ class mail_ui
|
|||||||
}
|
}
|
||||||
|
|
||||||
$preserv['profileId'] = $profileId;
|
$preserv['profileId'] = $profileId;
|
||||||
$preserv['current_subscribed'] = $content['foldertree'];
|
|
||||||
$readonlys = array();
|
$readonlys = array();
|
||||||
|
|
||||||
$stmpl->exec('mail.mail_ui.subscription', $content,$sel_options,$readonlys,$preserv,2);
|
$stmpl->exec('mail.mail_ui.subscription', $content,$sel_options,$readonlys,$preserv,2);
|
||||||
|
@ -44,7 +44,11 @@ app.classes.mail = AppJS.extend(
|
|||||||
timeout: null,
|
timeout: null,
|
||||||
request: null
|
request: null
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
subscription_treeLastState : "",
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* abbrevations for common access rights
|
* abbrevations for common access rights
|
||||||
* @array
|
* @array
|
||||||
@ -277,6 +281,15 @@ app.classes.mail = AppJS.extend(
|
|||||||
jQuery('input',to.node).focus();
|
jQuery('input',to.node).focus();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'mail.subscribe':
|
||||||
|
if (this.subscription_treeLastState != "")
|
||||||
|
{
|
||||||
|
var tree = this.et2.getWidgetById('foldertree');
|
||||||
|
//Saved state of tree
|
||||||
|
var state = jQuery.parseJSON(this.subscription_treeLastState);
|
||||||
|
|
||||||
|
tree.input.loadJSONObject(tree._htmlencode_node(state));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -3654,7 +3667,29 @@ app.classes.mail = AppJS.extend(
|
|||||||
var acc_id = parseInt(_senders[0].id);
|
var acc_id = parseInt(_senders[0].id);
|
||||||
this.egw.open_link('mail.mail_sieve.editVacation&acc_id='+acc_id,'_blank','700x480');
|
this.egw.open_link('mail.mail_sieve.editVacation&acc_id='+acc_id,'_blank','700x480');
|
||||||
},
|
},
|
||||||
|
|
||||||
|
subscription_refresh: function(_data)
|
||||||
|
{
|
||||||
|
console.log(_data);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Submit on apply button and save current tree state
|
||||||
|
*
|
||||||
|
* @param {type} _egw
|
||||||
|
* @param {type} _widget
|
||||||
|
* @returns {undefined}
|
||||||
|
*/
|
||||||
|
subscription_apply: function (_egw, _widget)
|
||||||
|
{
|
||||||
|
var tree = etemplate2.getByApplication('mail')[0].widgetContainer.getWidgetById('foldertree');
|
||||||
|
if (tree)
|
||||||
|
{
|
||||||
|
tree.input._xfullXML = true;
|
||||||
|
this.subscription_treeLastState = tree.input.serializeTreeToJSON();
|
||||||
|
}
|
||||||
|
this.et2._inst.submit(_widget);
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
* Popup the subscription dialog
|
* Popup the subscription dialog
|
||||||
*
|
*
|
||||||
|
@ -13,14 +13,14 @@
|
|||||||
</row>
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<box scrolling="auto">
|
<box scrolling="auto">
|
||||||
<tree id="foldertree" onclick="app.mail.subscribe_onclick" multiple="true"/>
|
<tree id="foldertree" multiple="true" autoloading="mail_ui::ajax_tree_autoloading"/>
|
||||||
</box>
|
</box>
|
||||||
</row>
|
</row>
|
||||||
</rows>
|
</rows>
|
||||||
</grid>
|
</grid>
|
||||||
<hbox class="dialogFooterToolbar">
|
<hbox class="dialogFooterToolbar">
|
||||||
<button statustext="Saves subscription changes" label="Save" id="button[save]"/>
|
<button statustext="Saves subscription changes" label="Save" id="button[save]"/>
|
||||||
<button statustext="Applies the changes made" label="Apply" id="button[apply]"/>
|
<button statustext="Applies the changes made" label="Apply" id="button[apply]" onclick="app.mail.subscription_apply"/>
|
||||||
<button label="Cancel" id="button[cancel]" onclick="window.close()"/>
|
<button label="Cancel" id="button[cancel]" onclick="window.close()"/>
|
||||||
</hbox>
|
</hbox>
|
||||||
</template>
|
</template>
|
||||||
|
Loading…
Reference in New Issue
Block a user