diff --git a/js/data/MDMDeviceFolderStore.js b/js/data/MDMDeviceFolderStore.js
index 3981838..1f89c4c 100644
--- a/js/data/MDMDeviceFolderStore.js
+++ b/js/data/MDMDeviceFolderStore.js
@@ -1,33 +1,62 @@
-Ext.namespace('Zarafa.plugins.mdm.data');
-
-/**
- * @class Zarafa.plugins.mdm.data.MDMDeviceFolderStore
- * @extends Zarafa.core.data.MAPISubStore
- * @xtype mdm.devicefolderstore
- * Store specific for MDM Plugin which creates {@link Zarafa.plugins.mdm.MDMDeviceFolderStore record}.
- */
-Zarafa.plugins.mdm.data.MDMDeviceFolderStore = Ext.extend(Zarafa.core.data.MAPISubStore, {
- /**
- * @constructor
- * @param config Configuration object
- */
- constructor: function (config)
- {
- config = config || {};
-
- Ext.applyIf(config, {
- autoLoad: true,
- remoteSort: false,
- reader: new Zarafa.plugins.mdm.data.JsonDeviceFolderReader(),
- writer: new Zarafa.core.data.JsonWriter(),
- proxy: new Zarafa.core.data.IPMProxy({
- listModuleName: 'pluginmdmmodule',
- itemModuleName: 'pluginmdmmodule'
- })
- });
-
- Zarafa.plugins.mdm.data.MDMDeviceFolderStore.superclass.constructor.call(this, config);
- }
-});
-
+Ext.namespace('Zarafa.plugins.mdm.data');
+
+/**
+ * @class Zarafa.plugins.mdm.data.MDMDeviceFolderStore
+ * @extends Zarafa.core.data.MAPISubStore
+ * @xtype mdm.devicefolderstore
+ * Store specific for MDM Plugin which creates {@link Zarafa.plugins.mdm.MDMDeviceFolderStore record}.
+ */
+Zarafa.plugins.mdm.data.MDMDeviceFolderStore = Ext.extend(Zarafa.core.data.MAPISubStore, {
+ /**
+ * @constructor
+ * @param config Configuration object
+ */
+ constructor: function (config)
+ {
+ config = config || {};
+
+ Ext.applyIf(config, {
+ autoLoad: true,
+ remoteSort: false,
+ reader: new Zarafa.plugins.mdm.data.JsonDeviceFolderReader(),
+ writer: new Zarafa.plugins.mdm.data.MDMDeviceFolderWriter(),
+ proxy: new Zarafa.core.data.IPMProxy({
+ listModuleName: 'pluginmdmmodule',
+ itemModuleName: 'pluginmdmmodule'
+ })
+ });
+
+ 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);
\ No newline at end of file
diff --git a/js/data/MDMDeviceFolderWriter.js b/js/data/MDMDeviceFolderWriter.js
new file mode 100644
index 0000000..5999891
--- /dev/null
+++ b/js/data/MDMDeviceFolderWriter.js
@@ -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;
+ }
+});
diff --git a/js/data/MDMHierarchyTreeLoader.js b/js/data/MDMHierarchyTreeLoader.js
index 8eb159c..78e7c98 100644
--- a/js/data/MDMHierarchyTreeLoader.js
+++ b/js/data/MDMHierarchyTreeLoader.js
@@ -1,57 +1,49 @@
-Ext.namespace('Zarafa.hierarchy.data');
-
-/**
- * @class Zarafa.plugins.mdm.data.MDMHierarchyTreeLoader
- * @extends Zarafa.hierarchy.data.HierarchyTreeLoader
- *
- * 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
- * the folder related to the given node.
- */
-Zarafa.plugins.mdm.data.MDMHierarchyTreeLoader = Ext.extend(Zarafa.hierarchy.data.HierarchyTreeLoader, {
-
- /**
- * @constructor
- * @param {Object} config Configuration object
- */
- constructor : function(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
- * to be created. This will check the {@link Zarafa.hierarchy.ui.FolderNode#folder folder} to
- * see what properties must be set.
- *
- * 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
- * @return {Zarafa.hierarchy.ui.FolderNode} The created node
- */
- createNode : function(attr)
- {
- var folder = attr.folder;
-
- if (folder) {
- if (attr.nodeType === 'rootfolder') {
- attr.extendedDisplayName = this.tree.hasFilter();
- }
-
- // To uniquely identify the favorites tree nodes we append the "favorites-" key word with node id
- // when the node is created.
- attr.id = folder.isFavoritesFolder() ? "favorites-" + folder.get('entryid') : folder.get('entryid');
- if (folder.isFavoritesRootFolder()) {
- attr.leaf = folder.get('assoc_content_count') === 0;
- } else {
- attr.leaf = !folder.get('has_subfolder');
- }
-
- 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);
- }
-});
+Ext.namespace('Zarafa.hierarchy.data');
+
+/**
+ * @class Zarafa.plugins.mdm.data.MDMHierarchyTreeLoader
+ * @extends Zarafa.hierarchy.data.HierarchyTreeLoader
+ *
+ * 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
+ * the folder related to the given node.
+ */
+Zarafa.plugins.mdm.data.MDMHierarchyTreeLoader = Ext.extend(Zarafa.hierarchy.data.HierarchyTreeLoader, {
+
+ /**
+ * @constructor
+ * @param {Object} config Configuration object
+ */
+ constructor : function(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
+ * to be created. This will check the {@link Zarafa.hierarchy.ui.FolderNode#folder folder} to
+ * see what properties must be set.
+ *
+ * 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
+ * @return {Zarafa.hierarchy.ui.FolderNode} The created node
+ */
+ createNode : function(attr)
+ {
+ var folder = attr.folder;
+
+ if (folder) {
+ if (attr.nodeType === 'rootfolder') {
+ attr.extendedDisplayName = this.tree.hasFilter();
+ }
+
+ attr.leaf = !folder.get('has_subfolder');
+ 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);
+ }
+});
diff --git a/js/dialogs/MDMDeviceContentPanel.js b/js/dialogs/MDMDeviceContentPanel.js
index 497ac7e..b93a1d5 100644
--- a/js/dialogs/MDMDeviceContentPanel.js
+++ b/js/dialogs/MDMDeviceContentPanel.js
@@ -27,6 +27,7 @@ Zarafa.plugins.mdm.dialogs.MDMDeviceContentPanel = Ext.extend(Zarafa.core.ui.Rec
}),
layout: 'fit',
stateful: false,
+ showInfoMask : false,
showLoadMask: false,
width: isKOE ? 440 : 405,
height: isKOE ? 450 : 420,
diff --git a/js/dialogs/MDMDeviceDetailsTab.js b/js/dialogs/MDMDeviceDetailsTab.js
index 5b8105a..9ea9b91 100644
--- a/js/dialogs/MDMDeviceDetailsTab.js
+++ b/js/dialogs/MDMDeviceDetailsTab.js
@@ -32,15 +32,11 @@ Zarafa.plugins.mdm.dialogs.MDMDeviceDetailsTab = Ext.extend(Ext.form.FormPanel,
layout: 'form',
labelWidth: 150
},
-
+ plugins : ['zarafa.recordcomponentupdaterplugin'],
items: [
this.createDeviceInfoPanel(config.isKoe),
this.createVersionInfoPanel(config.isKoe)
- ],
- listeners: {
- afterlayout: this.onAfterLayout,
- scope: this
- }
+ ]
});
// KOE information
@@ -156,12 +152,14 @@ Zarafa.plugins.mdm.dialogs.MDMDeviceDetailsTab = Ext.extend(Ext.form.FormPanel,
},
/**
- * Function which handles the afterlayout event
- * Which is use to set record values into form fields.
+ * 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.
*/
- onAfterLayout: function ()
+ update : function(record, contentReset)
{
- this.getForm().loadRecord(this.record);
+ this.getForm().loadRecord(record);
}
});
diff --git a/js/dialogs/MDMDeviceGeneralTab.js b/js/dialogs/MDMDeviceGeneralTab.js
index e46b0c6..2730456 100644
--- a/js/dialogs/MDMDeviceGeneralTab.js
+++ b/js/dialogs/MDMDeviceGeneralTab.js
@@ -33,14 +33,11 @@ Zarafa.plugins.mdm.dialogs.MDMDeviceGeneralTab = Ext.extend(Ext.form.FormPanel,
labelWidth: 150,
cls: 'mdm-device-panel'
},
+ plugins : ['zarafa.recordcomponentupdaterplugin'],
items: [
this.createDeviceInfoPanel(config),
this.createFolderInfoPanel()
- ],
- listeners: {
- afterlayout: this.onAfterLayout,
- scope: this
- }
+ ]
});
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.
- * Which is use to set record values into form fields.
+ * Updates the panel by loading data from the record into the header template, and
+ * 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 ()
{
+ this.dialog.record.opened = false;
Zarafa.core.data.UIFactory.openLayerComponent(Zarafa.core.data.SharedComponentType['mdm.dialog.mdmmanagesharedfoldercontentpanel'], undefined, {
manager: Ext.WindowMgr,
record: this.dialog.record
diff --git a/js/dialogs/MDMManageSharedFolderContentPanel.js b/js/dialogs/MDMManageSharedFolderContentPanel.js
index b77d673..47e9b50 100644
--- a/js/dialogs/MDMManageSharedFolderContentPanel.js
+++ b/js/dialogs/MDMManageSharedFolderContentPanel.js
@@ -2,13 +2,13 @@ Ext.namespace('Zarafa.plugins.mdm.dialogs');
/**
* @class Zarafa.plugins.mdm.dialogs.MDMManageSharedFolderContentPanel
- * @extends Zarafa.core.ui.ContentPanel
+ * @extends Zarafa.core.ui.RecordContentPanel
* @xtype zarafa.managesharedfoldercontentpanel
*
* This will display a {@link Zarafa.plugins.mdm.dialogs.MDMManageSharedFolderPanel contentpanel}
* 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
@@ -22,6 +22,11 @@ Zarafa.plugins.mdm.dialogs.MDMManageSharedFolderContentPanel = Ext.extend(Zarafa
xtype: 'mdm.managesharedfoldercontentpanel',
layout: 'fit',
title: dgettext('plugin_mdm','Manage Shared Folder'),
+ modal: true,
+ stateful: false,
+ showInfoMask : false,
+ showLoadMask: false,
+ closeOnSave: true,
width: 300,
height: 350,
items: [{
diff --git a/js/dialogs/MDMManageSharedFolderPanel.js b/js/dialogs/MDMManageSharedFolderPanel.js
index b7dd667..486c845 100644
--- a/js/dialogs/MDMManageSharedFolderPanel.js
+++ b/js/dialogs/MDMManageSharedFolderPanel.js
@@ -1,132 +1,217 @@
-Ext.namespace('Zarafa.plugins.mdm.dialogs');
-
-/**
- * @class Zarafa.plugins.mdm.dialogs.MDMManageSharedFolderPanel
- * @extends Ext.Panel
- * @xtype mdm.managesharedfolderpanel
- *
- * 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, {
-
- /**
- * @constructor
- * @param {Object} config Configuration structure
- */
- constructor: function (config)
- {
- config = config || {};
-
- Ext.applyIf(config, {
- xtype: 'mdm.managesharedfolderpanel',
- layout: {
- type: 'fit',
- align: 'stretch'
- },
- border: false,
- header: false,
- items: [
- this.createTreePanel()
- ],
- buttonAlign: 'right',
- buttons: [{
- text: _('Apply'),
- ref: '../okButton',
- cls: 'zarafa-action',
- scope: this
- }, {
- text: _('Cancel'),
- ref: '../cancelButton',
- handler: this.onCancel,
- scope: this
- }]
- });
-
- Zarafa.plugins.mdm.dialogs.MDMManageSharedFolderPanel.superclass.constructor.call(this, config);
- },
-
- /**
- * Creates a {@link Zarafa.hierarchy.ui.Tree treepanel}
- * which contains all the {@link Zarafa.hierarchy.data.MAPIFolderRecord folders}
- * on which search get perform.
- * @return {Object} Configuration object for the tree panel.
- * @private
- */
- createTreePanel: function ()
- {
- return {
- xtype: 'panel',
- layout : 'form',
- defaults: {
- cls : 'mdm-create-tree-panel-item'
- },
- border: false,
- flex: 1,
- items: [{
- xtype: 'displayfield',
- hideLabel : true,
- value: dgettext('plugin_mdm','Select folders to sync on your device')
- }, {
- xtype: 'mdm.hierarchytree',
- autoScroll : true,
- nodeConfig : {
- checked : false
- },
- multiSelect: true,
- hideShowAllFolders: true,
- border: true,
- treeSorter: true,
- bbarConfig: {
- hidden: true
- },
- enableDD: false,
- anchor: '100% 90%',
- ref: '../hierarchyTree'
- }]
- };
- },
-
- /**
- * Initialize the events
- * @private
- */
- initEvents: function ()
- {
- Zarafa.plugins.mdm.dialogs.MDMManageSharedFolderPanel.superclass.initEvents.apply(this, arguments);
- this.mon(this.hierarchyTree, 'load', this.onTreeNodeLoad, this);
- },
-
- /**
- * 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.
- *
- * @private
- */
- onTreeNodeLoad: function ()
- {
- var subStore = this.dialog.record.getSubStore('sharedfolders');
- var folders = subStore.getRange();
- folders.forEach(function (folder) {
- var node = this.hierarchyTree.getNodeById(folder.get('entryid'));
- if (Ext.isDefined(node)) {
- if(node.hasChildNodes()){
- node.expand();
- }
- node.getUI().toggleCheck(true)
- }
- }, this);
- },
-
- /**
- * Action handler when the user presses the "Cancel" button.
- * This will close the panel.
- */
- onCancel: function ()
- {
- this.dialog.close();
- }
-});
-
+Ext.namespace('Zarafa.plugins.mdm.dialogs');
+
+/**
+ * @class Zarafa.plugins.mdm.dialogs.MDMManageSharedFolderPanel
+ * @extends Ext.Panel
+ * @xtype mdm.managesharedfolderpanel
+ *
+ * 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, {
+
+ /**
+ * @cfg {Zarafa.plugins.mdm.data.MDMDeviceFolderStore} store contains {@link Zarafa.plugins.mdm.data.MDMDeviceFolderRecord folders} which
+ * is going to shared with device.
+ */
+ sharedFoldersStore : undefined,
+
+ /**
+ * @cfg {Zarafa.core.data.IPMRecord} record The mail which
+ * is being update by this panel.
+ */
+ record: null,
+
+ /**
+ * @constructor
+ * @param {Object} config Configuration structure
+ */
+ constructor: function (config)
+ {
+ config = config || {};
+
+ Ext.applyIf(config, {
+ xtype: 'mdm.managesharedfolderpanel',
+ layout: {
+ type: 'fit',
+ align: 'stretch'
+ },
+ border: false,
+ header: false,
+ items: [
+ this.createTreePanel()
+ ],
+ buttonAlign: 'right',
+ plugins : ['zarafa.recordcomponentupdaterplugin'],
+ buttons: [{
+ text: _('Apply'),
+ handler: this.onApply,
+ cls: 'zarafa-action',
+ scope: this
+ }, {
+ text: _('Cancel'),
+ handler: this.onCancel,
+ scope: this
+ }]
+ });
+
+ Zarafa.plugins.mdm.dialogs.MDMManageSharedFolderPanel.superclass.constructor.call(this, config);
+ },
+
+ /**
+ * Creates a {@link Zarafa.hierarchy.ui.Tree treepanel}
+ * which contains all the {@link Zarafa.hierarchy.data.MAPIFolderRecord folders}
+ * on which search get perform.
+ * @return {Object} Configuration object for the tree panel.
+ * @private
+ */
+ createTreePanel: function ()
+ {
+ return {
+ xtype: 'panel',
+ layout : 'form',
+ defaults: {
+ cls : 'mdm-create-tree-panel-item'
+ },
+ border: false,
+ flex: 1,
+ items: [{
+ xtype: 'displayfield',
+ hideLabel : true,
+ value: dgettext('plugin_mdm','Select folders to sync on your device')
+ }, {
+ xtype: 'mdm.hierarchytree',
+ autoScroll : true,
+ hideOwnTree : true,
+ nodeConfig : {
+ checked : false
+ },
+ multiSelect: true,
+ hideShowAllFolders: true,
+ border: true,
+ treeSorter: true,
+ bbarConfig: {
+ hidden: true
+ },
+ enableDD: false,
+ anchor: '100% 90%',
+ ref: '../hierarchyTree'
+ }]
+ };
+ },
+
+ /**
+ * Initialize the events
+ * @private
+ */
+ initEvents: function ()
+ {
+ Zarafa.plugins.mdm.dialogs.MDMManageSharedFolderPanel.superclass.initEvents.apply(this, arguments);
+ this.mon(this.hierarchyTree, {
+ expandnode: this.onTreeNodeExpand,
+ checkchange: this.onTreeNodeCheckChange,
+ click: this.onTreeNodeClick,
+ scope: this
+ });
+ },
+
+ /**
+ * Fired when the {@link Zarafa.hierarchy.ui.Tree Tree} fires the {@link Zarafa.hierarchy.ui.Tree#nodeexpand nodeexpand}
+ * event.
+ * It will update the hierarchy by selecting child node if it will shared with device.
+ * @private
+ */
+ onTreeNodeExpand: function ()
+ {
+ if (!this.record.isOpened()) {
+ return false;
+ }
+ 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);
\ No newline at end of file
diff --git a/js/ui/MDMHierarchyTreePanel.js b/js/ui/MDMHierarchyTreePanel.js
index f0aa48a..05f9fa5 100644
--- a/js/ui/MDMHierarchyTreePanel.js
+++ b/js/ui/MDMHierarchyTreePanel.js
@@ -38,6 +38,25 @@ Zarafa.plugins.mdm.ui.MDMHierarchyTreePanel = Ext.extend(Zarafa.hierarchy.ui.Tre
// call parent
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;
}
});
diff --git a/manifest.xml b/manifest.xml
index fa102d2..a002150 100755
--- a/manifest.xml
+++ b/manifest.xml
@@ -32,6 +32,7 @@
js/data/MDMResponseHandler.js
js/data/MDMDeviceRecord.js
js/data/JsonDeviceReader.js
+ js/data/MDMDeviceFolderWriter.js
js/data/MDMDeviceStore.js
js/data/ProvisioningStatus.js
js/data/MDMDeviceProxy.js
diff --git a/php/class.pluginmdmmodule.php b/php/class.pluginmdmmodule.php
index 22ce717..f57f87b 100755
--- a/php/class.pluginmdmmodule.php
+++ b/php/class.pluginmdmmodule.php
@@ -121,6 +121,22 @@ class PluginMDMModule extends Module
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.
* @return boolean true on success of false on fialure.
@@ -173,18 +189,18 @@ class PluginMDMModule extends Module
break;
case 'open':
- $data = array();
- $rawData = $this->getDevices();
- 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);
+ $device = $this->getDeviceDetails($actionData["entryid"]);
+ $item = array("item" => $device);
$this->addActionData('item', $item);
$GLOBALS['bus']->addData($this->getResponseData());
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:
$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.');
}
} 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)));
}
catch (Exception $e) {
@@ -268,7 +297,11 @@ class PluginMDMModule extends Module
$folderType = $this->getSyncFolderType($type, $name);
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)
{
- $folderType = '';
switch ($type) {
case SYNC_FOLDER_TYPE_APPOINTMENT:
case SYNC_FOLDER_TYPE_USER_APPOINTMENT:
@@ -353,5 +385,193 @@ class PluginMDMModule extends Module
}
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;
+ }
+ }
};
?>
diff --git a/php/zpushprops.php b/php/zpushprops.php
index 70d31cb..22cf4ae 100644
--- a/php/zpushprops.php
+++ b/php/zpushprops.php
@@ -20,6 +20,7 @@ define("SYNC_FOLDER_TYPE_USER_NOTE", 17);
define("SYNC_FOLDER_TYPE_UNKNOWN", 18);
define("SYNC_FOLDER_TYPE_RECIPIENT_CACHE", 19);
define("SYNC_FOLDER_TYPE_DUMMY", 999999);
+define("FLD_FLAGS_REPLYASUSER", 1);
// Other constant
define('KOE_GAB_NAME', 'Z-Push-KOE-GAB');