Add and delete new folders to the list to be synchronised

Write a php code for adding and removing device folder from device.
Write a js code for adding and removing folder into store while user select / deselect folder
This commit is contained in:
csoni 2017-09-13 17:42:57 +05:30
parent 41cc4f675d
commit 6bc2a9788c
12 changed files with 658 additions and 254 deletions

View File

@ -1,33 +1,62 @@
Ext.namespace('Zarafa.plugins.mdm.data'); Ext.namespace('Zarafa.plugins.mdm.data');
/** /**
* @class Zarafa.plugins.mdm.data.MDMDeviceFolderStore * @class Zarafa.plugins.mdm.data.MDMDeviceFolderStore
* @extends Zarafa.core.data.MAPISubStore * @extends Zarafa.core.data.MAPISubStore
* @xtype mdm.devicefolderstore * @xtype mdm.devicefolderstore
* Store specific for MDM Plugin which creates {@link Zarafa.plugins.mdm.MDMDeviceFolderStore record}. * Store specific for MDM Plugin which creates {@link Zarafa.plugins.mdm.MDMDeviceFolderStore record}.
*/ */
Zarafa.plugins.mdm.data.MDMDeviceFolderStore = Ext.extend(Zarafa.core.data.MAPISubStore, { Zarafa.plugins.mdm.data.MDMDeviceFolderStore = Ext.extend(Zarafa.core.data.MAPISubStore, {
/** /**
* @constructor * @constructor
* @param config Configuration object * @param config Configuration object
*/ */
constructor: function (config) constructor: function (config)
{ {
config = config || {}; config = config || {};
Ext.applyIf(config, { Ext.applyIf(config, {
autoLoad: true, autoLoad: true,
remoteSort: false, remoteSort: false,
reader: new Zarafa.plugins.mdm.data.JsonDeviceFolderReader(), reader: new Zarafa.plugins.mdm.data.JsonDeviceFolderReader(),
writer: new Zarafa.core.data.JsonWriter(), writer: new Zarafa.plugins.mdm.data.MDMDeviceFolderWriter(),
proxy: new Zarafa.core.data.IPMProxy({ proxy: new Zarafa.core.data.IPMProxy({
listModuleName: 'pluginmdmmodule', listModuleName: 'pluginmdmmodule',
itemModuleName: 'pluginmdmmodule' itemModuleName: 'pluginmdmmodule'
}) })
}); });
Zarafa.plugins.mdm.data.MDMDeviceFolderStore.superclass.constructor.call(this, config); Zarafa.plugins.mdm.data.MDMDeviceFolderStore.superclass.constructor.call(this, config);
} },
});
/**
* Function which is use to add {@link Zarafa.plugins.mdm.data.MDMDeviceFolderRecord folder} into
* {@link Zarafa.plugins.mdm.MDMDeviceFolderStore store} which will share with respective device.
* @param {Zarafa.hierarchy.data.IPFRecord} folder folder which is will add into {@link Zarafa.plugins.mdm.MDMDeviceFolderStore store}
*/
addFolder : function (folder)
{
var record = Zarafa.core.data.RecordFactory.createRecordObjectByCustomType(Zarafa.core.data.RecordCustomObjectType.MDM_Device_Folder, {
"entryid": folder.get("entryid")
});
this.add(record);
},
/**
* Function which is use to remove {@link Zarafa.plugins.mdm.data.MDMDeviceFolderRecord folder} from
* {@link Zarafa.plugins.mdm.MDMDeviceFolderStore store}.
* @param {Zarafa.hierarchy.data.IPFRecord} folder folder which is will remove from {@link Zarafa.plugins.mdm.MDMDeviceFolderStore store}
*/
removeFolder : function (folder)
{
var found = this.findBy(function (record) {
return Zarafa.core.EntryId.compareEntryIds(record.get("entryid"), folder.get("entryid"));
});
if (found >= 0) {
this.removeAt(found);
}
}
});
Ext.reg('mdm.devicefolderstore', Zarafa.plugins.mdm.data.MDMDeviceFolderStore); Ext.reg('mdm.devicefolderstore', Zarafa.plugins.mdm.data.MDMDeviceFolderStore);

View File

@ -0,0 +1,52 @@
Ext.namespace('Zarafa.plugins.mdm.data');
/**
* @class Zarafa.plugins.mdm.data.MDMDeviceFolderWriter
* @extends Zarafa.core.data.JsonWriter
*
* This extension of the {@link Zarafa.core.data.JsonWriter} for writing
* {@link Zarafa.plugins.mdm.data.MDMDeviceFolderRecord records} in preparation for executing CRUD action on
* {@link Zarafa.plugins.mdm.data.MDMDeviceFolderStore stores}
*/
Zarafa.plugins.mdm.data.MDMDeviceFolderWriter = Ext.extend(Zarafa.core.data.JsonWriter, {
/**
* Similar to {@link Ext.data.JsonWriter#toHash}
*
* Convert sharedFolder into a hash. {@link Zarafa.plugins.mdm.data.MDMDeviceFolderRecord folder} exists
* within a {@link Zarafa.plugins.mdm.data.MDMDeviceRecord IPMRecord} and thus must be serialized
* seperately into the hash object.
*
* @param {Ext.data.Record} record The record to hash
* @return {Object} The hashed object
* @override
* @private
*/
toPropHash : function(record)
{
var sharedFolderStore = record.getSubStore('sharedfolders');
var hash = {};
if (!Ext.isDefined(sharedFolderStore)) {
return hash;
}
// Get list of modified (modified and newly added) records
var modifiedRecords = sharedFolderStore.getModifiedRecords();
// Get list of removed records
var deletedRecords = sharedFolderStore.getRemovedRecords();
// Adding the modified folder to the add or modified part of the sharedFolder bit
if (modifiedRecords.length) {
hash.sharedfolders = {};
hash.sharedfolders.add = modifiedRecords.map(function(r){return r.data;});
}
// Adding the removed folders to the remove part of the sharedFolder bit
if (deletedRecords.length) {
hash.sharedfolders = hash.sharedfolders || {};
hash.sharedfolders.remove = deletedRecords.map(function(r){return r.data;});
}
return hash;
}
});

View File

@ -1,57 +1,49 @@
Ext.namespace('Zarafa.hierarchy.data'); Ext.namespace('Zarafa.hierarchy.data');
/** /**
* @class Zarafa.plugins.mdm.data.MDMHierarchyTreeLoader * @class Zarafa.plugins.mdm.data.MDMHierarchyTreeLoader
* @extends Zarafa.hierarchy.data.HierarchyTreeLoader * @extends Zarafa.hierarchy.data.HierarchyTreeLoader
* *
* A Special treeloader to be used by the {@link Zarafa.plugins.mdm.data.MDMHierarchyTreeLoader MDMHierarchyTree}. * A Special treeloader to be used by the {@link Zarafa.plugins.mdm.data.MDMHierarchyTreeLoader MDMHierarchyTree}.
* This wil dynamically load the child nodes for a given node by obtaining the subfolders of * This wil dynamically load the child nodes for a given node by obtaining the subfolders of
* the folder related to the given node. * the folder related to the given node.
*/ */
Zarafa.plugins.mdm.data.MDMHierarchyTreeLoader = Ext.extend(Zarafa.hierarchy.data.HierarchyTreeLoader, { Zarafa.plugins.mdm.data.MDMHierarchyTreeLoader = Ext.extend(Zarafa.hierarchy.data.HierarchyTreeLoader, {
/** /**
* @constructor * @constructor
* @param {Object} config Configuration object * @param {Object} config Configuration object
*/ */
constructor : function(config) constructor : function(config)
{ {
Zarafa.plugins.mdm.data.MDMHierarchyTreeLoader.superclass.constructor.call(this, config); Zarafa.plugins.mdm.data.MDMHierarchyTreeLoader.superclass.constructor.call(this, config);
}, },
/** /**
* Add extra attributes for a new {@link Zarafa.hierarchy.ui.FolderNode folderNode} which is about * Add extra attributes for a new {@link Zarafa.hierarchy.ui.FolderNode folderNode} which is about
* to be created. This will check the {@link Zarafa.hierarchy.ui.FolderNode#folder folder} to * to be created. This will check the {@link Zarafa.hierarchy.ui.FolderNode#folder folder} to
* see what properties must be set. * see what properties must be set.
* *
* Override to provide (@link Zarafa.plugins.mdm.ui.MDMFolderNodeUI MDMFolderNodeUI} to ui provider * Override to provide (@link Zarafa.plugins.mdm.ui.MDMFolderNodeUI MDMFolderNodeUI} to ui provider
* @param {Object} attr The attributes which will be used to create the node * @param {Object} attr The attributes which will be used to create the node
* @return {Zarafa.hierarchy.ui.FolderNode} The created node * @return {Zarafa.hierarchy.ui.FolderNode} The created node
*/ */
createNode : function(attr) createNode : function(attr)
{ {
var folder = attr.folder; var folder = attr.folder;
if (folder) { if (folder) {
if (attr.nodeType === 'rootfolder') { if (attr.nodeType === 'rootfolder') {
attr.extendedDisplayName = this.tree.hasFilter(); attr.extendedDisplayName = this.tree.hasFilter();
} }
// To uniquely identify the favorites tree nodes we append the "favorites-" key word with node id attr.leaf = !folder.get('has_subfolder');
// when the node is created. attr.uiProvider = Zarafa.plugins.mdm.ui.MDMFolderNodeUI;
attr.id = folder.isFavoritesFolder() ? "favorites-" + folder.get('entryid') : folder.get('entryid'); attr.expanded = this.tree.isFolderOpened(folder);
if (folder.isFavoritesRootFolder()) { attr.allowDrag = !folder.isDefaultFolder();
attr.leaf = folder.get('assoc_content_count') === 0; }
} else {
attr.leaf = !folder.get('has_subfolder'); // call parent of parent because of parent class will change ui provider
} return Zarafa.hierarchy.data.HierarchyTreeLoader.superclass.createNode.apply(this, arguments);
}
attr.uiProvider = Zarafa.plugins.mdm.ui.MDMFolderNodeUI; });
attr.expanded = this.tree.isFolderOpened(folder);
attr.allowDrag = !folder.isDefaultFolder();
}
// call parent of parent because of parent class will change ui provider
return Zarafa.hierarchy.data.HierarchyTreeLoader.superclass.createNode.apply(this, arguments);
}
});

View File

@ -27,6 +27,7 @@ Zarafa.plugins.mdm.dialogs.MDMDeviceContentPanel = Ext.extend(Zarafa.core.ui.Rec
}), }),
layout: 'fit', layout: 'fit',
stateful: false, stateful: false,
showInfoMask : false,
showLoadMask: false, showLoadMask: false,
width: isKOE ? 440 : 405, width: isKOE ? 440 : 405,
height: isKOE ? 450 : 420, height: isKOE ? 450 : 420,

View File

@ -32,15 +32,11 @@ Zarafa.plugins.mdm.dialogs.MDMDeviceDetailsTab = Ext.extend(Ext.form.FormPanel,
layout: 'form', layout: 'form',
labelWidth: 150 labelWidth: 150
}, },
plugins : ['zarafa.recordcomponentupdaterplugin'],
items: [ items: [
this.createDeviceInfoPanel(config.isKoe), this.createDeviceInfoPanel(config.isKoe),
this.createVersionInfoPanel(config.isKoe) this.createVersionInfoPanel(config.isKoe)
], ]
listeners: {
afterlayout: this.onAfterLayout,
scope: this
}
}); });
// KOE information // KOE information
@ -156,12 +152,14 @@ Zarafa.plugins.mdm.dialogs.MDMDeviceDetailsTab = Ext.extend(Ext.form.FormPanel,
}, },
/** /**
* Function which handles the afterlayout event * Updates the panel by loading data from the record.
* Which is use to set record values into form fields. *
* @param {Zarafa.core.data.IPMRecord} record The record update the panel with.
* @param {Boolean} contentReset force the component to perform a full update of the data.
*/ */
onAfterLayout: function () update : function(record, contentReset)
{ {
this.getForm().loadRecord(this.record); this.getForm().loadRecord(record);
} }
}); });

View File

@ -33,14 +33,11 @@ Zarafa.plugins.mdm.dialogs.MDMDeviceGeneralTab = Ext.extend(Ext.form.FormPanel,
labelWidth: 150, labelWidth: 150,
cls: 'mdm-device-panel' cls: 'mdm-device-panel'
}, },
plugins : ['zarafa.recordcomponentupdaterplugin'],
items: [ items: [
this.createDeviceInfoPanel(config), this.createDeviceInfoPanel(config),
this.createFolderInfoPanel() this.createFolderInfoPanel()
], ]
listeners: {
afterlayout: this.onAfterLayout,
scope: this
}
}); });
Zarafa.plugins.mdm.dialogs.MDMDeviceGeneralTab.superclass.constructor.call(this, config); Zarafa.plugins.mdm.dialogs.MDMDeviceGeneralTab.superclass.constructor.call(this, config);
@ -173,12 +170,15 @@ Zarafa.plugins.mdm.dialogs.MDMDeviceGeneralTab = Ext.extend(Ext.form.FormPanel,
}, },
/** /**
* Function which handles the after layoutevent. * Updates the panel by loading data from the record into the header template, and
* Which is use to set record values into form fields. * loading the body html into the embedded iframe.
*
* @param {Zarafa.core.data.IPMRecord} record The record update the panel with.
* @param {Boolean} contentReset force the component to perform a full update of the data.
*/ */
onAfterLayout: function () update : function(record, contentReset)
{ {
this.getForm().loadRecord(this.record); this.getForm().loadRecord(record);
}, },
/** /**
@ -198,6 +198,7 @@ Zarafa.plugins.mdm.dialogs.MDMDeviceGeneralTab = Ext.extend(Ext.form.FormPanel,
*/ */
onClickManageSharedFolder: function () onClickManageSharedFolder: function ()
{ {
this.dialog.record.opened = false;
Zarafa.core.data.UIFactory.openLayerComponent(Zarafa.core.data.SharedComponentType['mdm.dialog.mdmmanagesharedfoldercontentpanel'], undefined, { Zarafa.core.data.UIFactory.openLayerComponent(Zarafa.core.data.SharedComponentType['mdm.dialog.mdmmanagesharedfoldercontentpanel'], undefined, {
manager: Ext.WindowMgr, manager: Ext.WindowMgr,
record: this.dialog.record record: this.dialog.record

View File

@ -2,13 +2,13 @@ Ext.namespace('Zarafa.plugins.mdm.dialogs');
/** /**
* @class Zarafa.plugins.mdm.dialogs.MDMManageSharedFolderContentPanel * @class Zarafa.plugins.mdm.dialogs.MDMManageSharedFolderContentPanel
* @extends Zarafa.core.ui.ContentPanel * @extends Zarafa.core.ui.RecordContentPanel
* @xtype zarafa.managesharedfoldercontentpanel * @xtype zarafa.managesharedfoldercontentpanel
* *
* This will display a {@link Zarafa.plugins.mdm.dialogs.MDMManageSharedFolderPanel contentpanel} * This will display a {@link Zarafa.plugins.mdm.dialogs.MDMManageSharedFolderPanel contentpanel}
* to show {@link Zarafa.core.data.IPFRecord folders} which are shared with device. * to show {@link Zarafa.core.data.IPFRecord folders} which are shared with device.
*/ */
Zarafa.plugins.mdm.dialogs.MDMManageSharedFolderContentPanel = Ext.extend(Zarafa.core.ui.ContentPanel, { Zarafa.plugins.mdm.dialogs.MDMManageSharedFolderContentPanel = Ext.extend(Zarafa.core.ui.RecordContentPanel, {
/** /**
* @constructor * @constructor
@ -22,6 +22,11 @@ Zarafa.plugins.mdm.dialogs.MDMManageSharedFolderContentPanel = Ext.extend(Zarafa
xtype: 'mdm.managesharedfoldercontentpanel', xtype: 'mdm.managesharedfoldercontentpanel',
layout: 'fit', layout: 'fit',
title: dgettext('plugin_mdm','Manage Shared Folder'), title: dgettext('plugin_mdm','Manage Shared Folder'),
modal: true,
stateful: false,
showInfoMask : false,
showLoadMask: false,
closeOnSave: true,
width: 300, width: 300,
height: 350, height: 350,
items: [{ items: [{

View File

@ -1,132 +1,217 @@
Ext.namespace('Zarafa.plugins.mdm.dialogs'); Ext.namespace('Zarafa.plugins.mdm.dialogs');
/** /**
* @class Zarafa.plugins.mdm.dialogs.MDMManageSharedFolderPanel * @class Zarafa.plugins.mdm.dialogs.MDMManageSharedFolderPanel
* @extends Ext.Panel * @extends Ext.Panel
* @xtype mdm.managesharedfolderpanel * @xtype mdm.managesharedfolderpanel
* *
* Panel for users to show the {@link Zarafa.core.data.IPFRecord folders} which are shared with device * Panel for users to show the {@link Zarafa.core.data.IPFRecord folders} which are shared with device
*/ */
Zarafa.plugins.mdm.dialogs.MDMManageSharedFolderPanel = Ext.extend(Ext.Panel, { Zarafa.plugins.mdm.dialogs.MDMManageSharedFolderPanel = Ext.extend(Ext.Panel, {
/** /**
* @constructor * @cfg {Zarafa.plugins.mdm.data.MDMDeviceFolderStore} store contains {@link Zarafa.plugins.mdm.data.MDMDeviceFolderRecord folders} which
* @param {Object} config Configuration structure * is going to shared with device.
*/ */
constructor: function (config) sharedFoldersStore : undefined,
{
config = config || {}; /**
* @cfg {Zarafa.core.data.IPMRecord} record The mail which
Ext.applyIf(config, { * is being update by this panel.
xtype: 'mdm.managesharedfolderpanel', */
layout: { record: null,
type: 'fit',
align: 'stretch' /**
}, * @constructor
border: false, * @param {Object} config Configuration structure
header: false, */
items: [ constructor: function (config)
this.createTreePanel() {
], config = config || {};
buttonAlign: 'right',
buttons: [{ Ext.applyIf(config, {
text: _('Apply'), xtype: 'mdm.managesharedfolderpanel',
ref: '../okButton', layout: {
cls: 'zarafa-action', type: 'fit',
scope: this align: 'stretch'
}, { },
text: _('Cancel'), border: false,
ref: '../cancelButton', header: false,
handler: this.onCancel, items: [
scope: this this.createTreePanel()
}] ],
}); buttonAlign: 'right',
plugins : ['zarafa.recordcomponentupdaterplugin'],
Zarafa.plugins.mdm.dialogs.MDMManageSharedFolderPanel.superclass.constructor.call(this, config); buttons: [{
}, text: _('Apply'),
handler: this.onApply,
/** cls: 'zarafa-action',
* Creates a {@link Zarafa.hierarchy.ui.Tree treepanel} scope: this
* which contains all the {@link Zarafa.hierarchy.data.MAPIFolderRecord folders} }, {
* on which search get perform. text: _('Cancel'),
* @return {Object} Configuration object for the tree panel. handler: this.onCancel,
* @private scope: this
*/ }]
createTreePanel: function () });
{
return { Zarafa.plugins.mdm.dialogs.MDMManageSharedFolderPanel.superclass.constructor.call(this, config);
xtype: 'panel', },
layout : 'form',
defaults: { /**
cls : 'mdm-create-tree-panel-item' * Creates a {@link Zarafa.hierarchy.ui.Tree treepanel}
}, * which contains all the {@link Zarafa.hierarchy.data.MAPIFolderRecord folders}
border: false, * on which search get perform.
flex: 1, * @return {Object} Configuration object for the tree panel.
items: [{ * @private
xtype: 'displayfield', */
hideLabel : true, createTreePanel: function ()
value: dgettext('plugin_mdm','Select folders to sync on your device') {
}, { return {
xtype: 'mdm.hierarchytree', xtype: 'panel',
autoScroll : true, layout : 'form',
nodeConfig : { defaults: {
checked : false cls : 'mdm-create-tree-panel-item'
}, },
multiSelect: true, border: false,
hideShowAllFolders: true, flex: 1,
border: true, items: [{
treeSorter: true, xtype: 'displayfield',
bbarConfig: { hideLabel : true,
hidden: true value: dgettext('plugin_mdm','Select folders to sync on your device')
}, }, {
enableDD: false, xtype: 'mdm.hierarchytree',
anchor: '100% 90%', autoScroll : true,
ref: '../hierarchyTree' hideOwnTree : true,
}] nodeConfig : {
}; checked : false
}, },
multiSelect: true,
/** hideShowAllFolders: true,
* Initialize the events border: true,
* @private treeSorter: true,
*/ bbarConfig: {
initEvents: function () hidden: true
{ },
Zarafa.plugins.mdm.dialogs.MDMManageSharedFolderPanel.superclass.initEvents.apply(this, arguments); enableDD: false,
this.mon(this.hierarchyTree, 'load', this.onTreeNodeLoad, this); anchor: '100% 90%',
}, ref: '../hierarchyTree'
}]
/** };
* Fired when the {@link Zarafa.hierarchy.ui.Tree Tree} fires the {@link Zarafa.hierarchy.ui.Tree#load load} },
* event. This function will try to select those {@link Ext.tree.TreeNode TreeNode} in
* {@link Zarafa.hierarchy.ui.Tree Tree} which was shared with respective device. When the given node is not loaded yet, it will try again /**
* later when the event is fired again. * Initialize the events
* * @private
* @private */
*/ initEvents: function ()
onTreeNodeLoad: function () {
{ Zarafa.plugins.mdm.dialogs.MDMManageSharedFolderPanel.superclass.initEvents.apply(this, arguments);
var subStore = this.dialog.record.getSubStore('sharedfolders'); this.mon(this.hierarchyTree, {
var folders = subStore.getRange(); expandnode: this.onTreeNodeExpand,
folders.forEach(function (folder) { checkchange: this.onTreeNodeCheckChange,
var node = this.hierarchyTree.getNodeById(folder.get('entryid')); click: this.onTreeNodeClick,
if (Ext.isDefined(node)) { scope: this
if(node.hasChildNodes()){ });
node.expand(); },
}
node.getUI().toggleCheck(true) /**
} * Fired when the {@link Zarafa.hierarchy.ui.Tree Tree} fires the {@link Zarafa.hierarchy.ui.Tree#nodeexpand nodeexpand}
}, this); * event.
}, * It will update the hierarchy by selecting child node if it will shared with device.
* @private
/** */
* Action handler when the user presses the "Cancel" button. onTreeNodeExpand: function ()
* This will close the panel. {
*/ if (!this.record.isOpened()) {
onCancel: function () return false;
{ }
this.dialog.close(); this.updateHierarchy();
} },
});
/**
* Updates the panel by loading data from the record.
*
* @param {Zarafa.core.data.IPMRecord} record The record update the panel with.
* @param {Boolean} contentReset force the component to perform a full update of the data.
*/
update : function(record, contentReset)
{
this.record = record;
this.sharedFoldersStore = record.getSubStore('sharedfolders');
this.updateHierarchy();
},
/**
* Function will try to select those {@link Ext.tree.TreeNode TreeNode} in
* {@link Zarafa.hierarchy.ui.Tree Tree} which was shared with respective device.
*/
updateHierarchy : function ()
{
var folders = this.sharedFoldersStore.getRange();
folders.forEach(function (folder) {
var node = this.hierarchyTree.getNodeById(folder.get('entryid'));
if (Ext.isDefined(node)) {
if (node.hasChildNodes()) {
node.expand();
}
node.isNodeSelected = true;
node.getUI().toggleCheck(true);
}
}, this);
},
/**
* Called when a treeNode is click in tree. The corresponding folder is added to,
* or removed from the active folder list depending on the state of the check box.
* @param {Ext.tree.TreeNode} treeNode tree node.
* @private
*/
onTreeNodeClick : function(treeNode)
{
var treeNodeui = treeNode.getUI();
if (treeNodeui.checkbox.checked && treeNode.isNodeSelected) {
treeNodeui.toggleCheck(false);
return false;
}
treeNode.isNodeSelected = true;
this.sharedFoldersStore.addFolder(treeNode.getFolder());
treeNodeui.toggleCheck(true);
},
/**
* Called when a check box in the calendar tree is toggled. The corresponding folder is added to,
* or removed from the active folder list depending on the state of the check box.
* @param {Ext.tree.TreeNode} node tree node.
* @param {Boolean} checked indicates whether the box is checked.
* @private
*/
onTreeNodeCheckChange : function(node, checked)
{
if (!checked) {
node.isNodeSelected = false;
this.sharedFoldersStore.removeFolder(node.getFolder());
} else if (checked && !node.isNodeSelected) {
this.onTreeNodeClick(node);
}
},
/**
* Action handler when the user presses the "Apply" button.
* This save the record and close the panel.
*/
onApply : function ()
{
this.record.save();
},
/**
* Action handler when the user presses the "Cancel" button.
* This will close the panel.
*/
onCancel: function ()
{
this.dialog.close();
}
});
Ext.reg('mdm.managesharedfolderpanel', Zarafa.plugins.mdm.dialogs.MDMManageSharedFolderPanel); Ext.reg('mdm.managesharedfolderpanel', Zarafa.plugins.mdm.dialogs.MDMManageSharedFolderPanel);

View File

@ -38,6 +38,25 @@ Zarafa.plugins.mdm.ui.MDMHierarchyTreePanel = Ext.extend(Zarafa.hierarchy.ui.Tre
// call parent // call parent
Zarafa.plugins.mdm.ui.MDMHierarchyTreePanel.superclass.initComponent.apply(this, arguments); Zarafa.plugins.mdm.ui.MDMHierarchyTreePanel.superclass.initComponent.apply(this, arguments);
},
/**
* The filter which is applied for filtering nodes from the
* {@link Zarafa.hierarchy.ui.Tree HierarchyTree}.
* It will hide own user store.
*
* @param {Object} folder the folder to filter
* @return {Boolean} true to accept the folder
*/
nodeFilter: function (folder)
{
var hide = Zarafa.plugins.mdm.ui.MDMHierarchyTreePanel.superclass.nodeFilter.apply(this, arguments);
if(hide && this.hideOwnTree) {
hide = !folder.getMAPIStore().isDefaultStore();
}
return hide;
} }
}); });

View File

@ -32,6 +32,7 @@
<clientfile load="source">js/data/MDMResponseHandler.js</clientfile> <clientfile load="source">js/data/MDMResponseHandler.js</clientfile>
<clientfile load="source">js/data/MDMDeviceRecord.js</clientfile> <clientfile load="source">js/data/MDMDeviceRecord.js</clientfile>
<clientfile load="source">js/data/JsonDeviceReader.js</clientfile> <clientfile load="source">js/data/JsonDeviceReader.js</clientfile>
<clientfile load="source">js/data/MDMDeviceFolderWriter.js</clientfile>
<clientfile load="source">js/data/MDMDeviceStore.js</clientfile> <clientfile load="source">js/data/MDMDeviceStore.js</clientfile>
<clientfile load="source">js/data/ProvisioningStatus.js</clientfile> <clientfile load="source">js/data/ProvisioningStatus.js</clientfile>
<clientfile load="source">js/data/MDMDeviceProxy.js</clientfile> <clientfile load="source">js/data/MDMDeviceProxy.js</clientfile>

View File

@ -121,6 +121,22 @@ class PluginMDMModule extends Module
return $client->RemoveDevice($deviceid); return $client->RemoveDevice($deviceid);
} }
/**
* Function witch is use get details of given device.
* @param string $deviceid id of device.
* @return array contains device props.
*/
function getDeviceDetails($deviceid)
{
$client = $this->getSoapClient();
$deviceRawData = $client->GetDeviceDetails($deviceid);
$device = array();
$device['props'] = $this->getDeviceProps($deviceRawData->data);
$device["sharedfolders"] = array("item" => $this->getAdditionalFolderList($deviceid));
return $device;
}
/** /**
* Executes all the actions in the $data variable. * Executes all the actions in the $data variable.
* @return boolean true on success of false on fialure. * @return boolean true on success of false on fialure.
@ -173,18 +189,18 @@ class PluginMDMModule extends Module
break; break;
case 'open': case 'open':
$data = array(); $device = $this->getDeviceDetails($actionData["entryid"]);
$rawData = $this->getDevices(); $item = array("item" => $device);
foreach($rawData as $device){
if($device->data['deviceid'] === $actionData['entryid']) {
$data['props'] = $this->getDeviceProps($device->data);
$data["sharedfolders"] = array("item" => $this->getAdditionalFolderList($actionData['entryid']));
}
}
$item = array("item" => $data);
$this->addActionData('item', $item); $this->addActionData('item', $item);
$GLOBALS['bus']->addData($this->getResponseData()); $GLOBALS['bus']->addData($this->getResponseData());
break; break;
case 'save':
$this ->saveDevice($actionData);
$device = $this->getDeviceDetails($actionData["entryid"]);
$item = array("item" => $device);
$this->addActionData('update', $item);
$GLOBALS['bus']->addData($this->getResponseData());
break;
default: default:
$this->handleUnknownActionType($actionType); $this->handleUnknownActionType($actionType);
} }
@ -201,8 +217,21 @@ class PluginMDMModule extends Module
$display_message = dgettext('plugin_mdm', 'Unable to connect to Z-Push Server. Not found.'); $display_message = dgettext('plugin_mdm', 'Unable to connect to Z-Push Server. Not found.');
} }
} else if ($fault->faultcode === "ERROR") { } else if ($fault->faultcode === "ERROR") {
$display_message = dgettext('plugin_mdm', 'Device ID could not be found'); $errors = (explode(": ", $fault->getMessage()));
} switch ($errors[0]) {
case "ASDevice->AddAdditionalFolder()":
case "ZPushAdmin::AdditionalFolderAdd()":
$display_message = dgettext('plugin_mdm', "Folder can not be added because there is already an additional folder with the same name");
break;
case "ASDevice->RemoveAdditionalFolder()":
case "ZPushAdmin::AdditionalFolderRemove()":
$display_message = dgettext('plugin_mdm', "Folder can not be removed because there is no folder known with given folder id");
break;
default:
$display_message = dgettext('plugin_mdm', "Device ID could not be found");
}
}
$this->sendFeedback(false, array("type" => ERROR_GENERAL, "info" => array('display_message' => $display_message))); $this->sendFeedback(false, array("type" => ERROR_GENERAL, "info" => array('display_message' => $display_message)));
} }
catch (Exception $e) { catch (Exception $e) {
@ -268,7 +297,11 @@ class PluginMDMModule extends Module
$folderType = $this->getSyncFolderType($type, $name); $folderType = $this->getSyncFolderType($type, $name);
if (isset($contentData[$folderid][self::FOLDERUUID])) { if (isset($contentData[$folderid][self::FOLDERUUID])) {
$synchedFolderTypes[$folderType]++; if(isset($synchedFolderTypes[$folderType])){
$synchedFolderTypes[$folderType]++;
} else {
$synchedFolderTypes[$folderType] = 1;
}
} }
} }
} }
@ -295,7 +328,6 @@ class PluginMDMModule extends Module
*/ */
function getSyncFolderType($type, $name) function getSyncFolderType($type, $name)
{ {
$folderType = '';
switch ($type) { switch ($type) {
case SYNC_FOLDER_TYPE_APPOINTMENT: case SYNC_FOLDER_TYPE_APPOINTMENT:
case SYNC_FOLDER_TYPE_USER_APPOINTMENT: case SYNC_FOLDER_TYPE_USER_APPOINTMENT:
@ -353,5 +385,193 @@ class PluginMDMModule extends Module
} }
return $data; return $data;
} }
/**
* Function which is use to remove additional folder which was shared with given device.
* @param string $entryId id of device.
* @param string $folderid id of folder which will remove from device.
*/
function additionalFolderRemove($entryId, $folderid)
{
$client = $this->getSoapClient();
$client->AdditionalFolderRemove($entryId, $folderid);
}
/**
* Function which is use to add additional folder which will share with given device.
* @param string $entryId id of device.
* @param array $folder folder which will share with device.
*/
function additionalFolderAdd($entryId, $folder)
{
$client = $this->getSoapClient();
$containerClass = isset($folder[PR_CONTAINER_CLASS]) ? $folder[PR_CONTAINER_CLASS] : "IPF.Note";
$folderId = bin2hex($folder[PR_SOURCE_KEY]);
$userName = $folder["user"];
$folderName = $userName === "SYSTEM" ? $folder[PR_DISPLAY_NAME] : $folder[PR_DISPLAY_NAME]." - ".$userName;
$folderType = $this->getFolderTypeFromContainerClass($containerClass);
$client->AdditionalFolderAdd($entryId, $userName, $folderId, $folderName, $folderType, FLD_FLAGS_REPLYASUSER);
}
/**
* Function which use to save the device.
* It will use to add or remove folders in the device.
* @param array $data array of added and removed folders.
*/
function saveDevice($data)
{
$entryid = $data["entryid"];
if (isset($data['sharedfolders'])) {
if (isset($data['sharedfolders']['remove'])) {
$deletedFolders = $data['sharedfolders']['remove'];
foreach ($deletedFolders as $folder) {
$this->additionalFolderRemove($entryid, $folder["folderid"]);
}
}
if (isset($data['sharedfolders']['add'])) {
$addFolders = $data['sharedfolders']['add'];
$hierarchyFolders = $this->getHierarchyList();
foreach ($addFolders as $folder) {
foreach ($hierarchyFolders as $hierarchyFolder) {
$folderEntryid = bin2hex($hierarchyFolder[PR_ENTRYID]);
if ($folderEntryid === $folder["entryid"]) {
$this->additionalFolderAdd($entryid, $hierarchyFolder);
continue 2;
}
}
}
}
}
}
/**
* Gets the hierarchy list of all required stores.
* Function which is use to get the hierarchy list with PR_SOURCE_KEY.
* @return array the array of all hierarchy folders.
*/
function getHierarchyList()
{
$storeList = $GLOBALS["mapisession"]->getAllMessageStores();
$properties = $GLOBALS["properties"]->getFolderListProperties();
$properties["source_key"] = PR_SOURCE_KEY;
$storeData = array();
foreach ($storeList as $store) {
$msgstore_props = mapi_getprops($store, array(PR_ENTRYID, PR_DISPLAY_NAME, PR_IPM_SUBTREE_ENTRYID, PR_IPM_OUTBOX_ENTRYID, PR_IPM_SENTMAIL_ENTRYID, PR_IPM_WASTEBASKET_ENTRYID, PR_MDB_PROVIDER, PR_IPM_PUBLIC_FOLDERS_ENTRYID, PR_IPM_FAVORITES_ENTRYID, PR_OBJECT_TYPE, PR_STORE_SUPPORT_MASK, PR_MAILBOX_OWNER_ENTRYID, PR_MAILBOX_OWNER_NAME, PR_USER_ENTRYID, PR_USER_NAME, PR_QUOTA_WARNING_THRESHOLD, PR_QUOTA_SEND_THRESHOLD, PR_QUOTA_RECEIVE_THRESHOLD, PR_MESSAGE_SIZE_EXTENDED, PR_MAPPING_SIGNATURE, PR_COMMON_VIEWS_ENTRYID, PR_FINDER_ENTRYID));
$storeType = $msgstore_props[PR_MDB_PROVIDER];
if ($storeType == ZARAFA_STORE_DELEGATE_GUID) {
$storeUserName = $GLOBALS["mapisession"]->getUserNameOfStore($msgstore_props[PR_ENTRYID]);
} else if( $storeType == ZARAFA_STORE_PUBLIC_GUID){
$storeUserName = "SYSTEM";
} else {
$storeUserName = $msgstore_props[PR_USER_NAME];
}
if (isset($msgstore_props[PR_IPM_SUBTREE_ENTRYID])) {
$subtreeFolderEntryID = $msgstore_props[PR_IPM_SUBTREE_ENTRYID];
try {
$subtreeFolder = mapi_msgstore_openentry($store, $subtreeFolderEntryID);
} catch (MAPIException $e) {
// We've handled the event
$e->setHandled();
}
try {
// remove hidden folders, folders with PR_ATTR_HIDDEN property set
// should not be shown to the client
$restriction = Array(RES_OR, Array(
Array(RES_PROPERTY,
Array(
RELOP => RELOP_EQ,
ULPROPTAG => PR_ATTR_HIDDEN,
VALUE => Array(PR_ATTR_HIDDEN => false)
)
),
Array(RES_NOT,
Array(
Array(RES_EXIST,
Array(
ULPROPTAG => PR_ATTR_HIDDEN
)
)
)
)
));
$expand = Array(
Array(
'folder' => $subtreeFolder,
'props' => mapi_getprops($subtreeFolder, Array(PR_ENTRYID, PR_SUBFOLDERS))
)
);
// Start looping through the $expand array, during each loop we grab the first item in
// the array and obtain the hierarchy table for that particular folder. If one of those
// subfolders has subfolders of its own, it will be appended to $expand again to ensure
// it will be expanded later.
while (!empty($expand)) {
$item = array_shift($expand);
$hierarchyTable = mapi_folder_gethierarchytable($item['folder'], MAPI_DEFERRED_ERRORS);
mapi_table_restrict($hierarchyTable, $restriction, TBL_BATCH);
mapi_table_setcolumns($hierarchyTable, $properties);
// Load the hierarchy in small batches
$batchcount = 100;
do {
$rows = mapi_table_queryrows($hierarchyTable, null, 0, $batchcount);
foreach ($rows as $subfolder) {
// If the subfolders has subfolders of its own, append the folder
// to the $expand array, so it can be expanded in the next loop.
if ($subfolder[PR_SUBFOLDERS]) {
$folderObject = mapi_msgstore_openentry($store, $subfolder[PR_ENTRYID]);
array_push($expand, array('folder' => $folderObject, 'props' => $subfolder));
}
$subfolder["user"] = $storeUserName;
// Add the folder to the return list.
array_push($storeData, $subfolder);
}
// When the server returned a different number of rows then was requested,
// we have reached the end of the table and we should exit the loop.
} while (count($rows) === $batchcount);
}
} catch (MAPIException $e) {
// We've handled the event
$e->setHandled();
}
}
}
return $storeData;
}
/**
* Function which is use get folder types from the container class
* @param string $containerClass container class of folder
* @return int folder type
*/
function getFolderTypeFromContainerClass($containerClass)
{
switch ($containerClass) {
case "IPF.Note":
return SYNC_FOLDER_TYPE_USER_MAIL;
case "IPF.Appointment":
return SYNC_FOLDER_TYPE_USER_APPOINTMENT;
case "IPF.Contact":
return SYNC_FOLDER_TYPE_USER_CONTACT;
case "IPF.StickyNote":
return SYNC_FOLDER_TYPE_USER_NOTE;
case "IPF.Task":
return SYNC_FOLDER_TYPE_USER_TASK;
case "IPF.Journal":
return SYNC_FOLDER_TYPE_USER_JOURNAL;
default:
return SYNC_FOLDER_TYPE_UNKNOWN;
}
}
}; };
?> ?>

View File

@ -20,6 +20,7 @@ define("SYNC_FOLDER_TYPE_USER_NOTE", 17);
define("SYNC_FOLDER_TYPE_UNKNOWN", 18); define("SYNC_FOLDER_TYPE_UNKNOWN", 18);
define("SYNC_FOLDER_TYPE_RECIPIENT_CACHE", 19); define("SYNC_FOLDER_TYPE_RECIPIENT_CACHE", 19);
define("SYNC_FOLDER_TYPE_DUMMY", 999999); define("SYNC_FOLDER_TYPE_DUMMY", 999999);
define("FLD_FLAGS_REPLYASUSER", 1);
// Other constant // Other constant
define('KOE_GAB_NAME', 'Z-Push-KOE-GAB'); define('KOE_GAB_NAME', 'Z-Push-KOE-GAB');