List folders that have been opened through the api

Added button in MDMDeviceGeneralTab
Created MDMManageSharedFolderContentPanel and MDMManageSharedFolderPanel to show a dialog with multi select hierarchy
Created substore sharedfolder
Added proxy and response handler to handel device response

Used message class instead of object type,
Override hierarchy tree , hierarchy loader and folder node ui
This commit is contained in:
csoni 2017-04-20 17:19:55 +05:30 committed by root
parent 42dda5a34b
commit 568eb9170d
21 changed files with 808 additions and 69 deletions

View File

@ -16,6 +16,12 @@ Zarafa.plugins.mdm.MDM = Ext.extend(Zarafa.core.Plugin, {
constructor : function(config) {
config = config || {};
Zarafa.plugins.mdm.MDM.superclass.constructor.call(this, config);
// Module information for MDM which will use in shadow store.
Zarafa.core.ModuleNames["IPM.MDM"] = {
list: 'pluginmdmmodule',
item: 'pluginmdmmodule'
}
},
/**
@ -28,6 +34,7 @@ Zarafa.plugins.mdm.MDM = Ext.extend(Zarafa.core.Plugin, {
this.registerInsertionPoint('context.settings.categories', this.createSettingCategory, this);
this.registerInsertionPoint('settings.versioninformation', this.createVersionInfo, this);
Zarafa.core.data.SharedComponentType.addProperty('mdm.dialog.mdmdevicecontentpanel');
Zarafa.core.data.SharedComponentType.addProperty('mdm.dialog.mdmmanagesharedfoldercontentpanel');
Zarafa.plugins.mdm.MDM.superclass.initPlugin.apply(this, arguments);
},
@ -44,6 +51,9 @@ Zarafa.plugins.mdm.MDM = Ext.extend(Zarafa.core.Plugin, {
case Zarafa.core.data.SharedComponentType['mdm.dialog.mdmdevicecontentpanel']:
bid = 1;
break;
case Zarafa.core.data.SharedComponentType['mdm.dialog.mdmmanagesharedfoldercontentpanel']:
bid = 1;
break;
}
return bid;
},
@ -57,7 +67,16 @@ Zarafa.plugins.mdm.MDM = Ext.extend(Zarafa.core.Plugin, {
*/
getSharedComponent : function (type, record)
{
return Zarafa.plugins.mdm.dialogs.MDMDeviceContentPanel;
var component;
switch (type) {
case Zarafa.core.data.SharedComponentType['mdm.dialog.mdmdevicecontentpanel']:
component = Zarafa.plugins.mdm.dialogs.MDMDeviceContentPanel;
break;
case Zarafa.core.data.SharedComponentType['mdm.dialog.mdmmanagesharedfoldercontentpanel']:
component = Zarafa.plugins.mdm.dialogs.MDMManageSharedFolderContentPanel;
break;
}
return component;
},

View File

@ -0,0 +1,41 @@
Ext.namespace('Zarafa.plugins.mdm.data');
/**
* @class Zarafa.plugins.mdm.data.JsonDeviceFolderReader
* @extends Zarafa.core.data.JsonReader
*
* This extension of the {@link Zarafa.core.data.JsonReader} supports
* {@link Zarafa.plugins.mdm.data.MDMDeviceStore stores} which can hold different type of
* {@link Zarafa.plugins.mdm.data.MDMDeviceRecord records}.
*/
Zarafa.plugins.mdm.data.JsonDeviceFolderReader = Ext.extend(Zarafa.core.data.JsonReader, {
/**
* @cfg {Zarafa.core.data.RecordCustomObjectType} customObjectType The custom object type
* which represents the {@link Ext.data.Record records} which should be created using
* {@link Zarafa.core.data.RecordFactory#createRecordObjectByCustomType}.
*/
customObjectType: Zarafa.core.data.RecordCustomObjectType.MDM_Device_Folder,
/**
* @constructor
* @param {Object} meta Metadata configuration options.
* @param {Object} recordType (optional) Optional Record type matches the type
* which must be read from response. If no type is given, it will use the
* record type for the {@link Zarafa.core.data.RecordCustomObjectType#ZARAFA_RECIPIENT}.
*/
constructor: function (meta, recordType)
{
meta = Ext.applyIf(meta || {}, {
id: 'folderid',
idProperty: 'folderid',
dynamicRecord: false
});
if (!Ext.isDefined(recordType)) {
recordType = Zarafa.core.data.RecordFactory.getRecordClassByCustomType(meta.customObjectType || this.customObjectType);
}
Zarafa.plugins.mdm.data.JsonDeviceFolderReader.superclass.constructor.call(this, meta, recordType);
}
});

View File

@ -5,28 +5,21 @@ Ext.namespace('Zarafa.plugins.mdm.data');
* @extends Zarafa.core.data.JsonReader
*/
Zarafa.plugins.mdm.data.JsonCertificateReader = Ext.extend(Zarafa.core.data.JsonReader, {
/**
* @cfg {Zarafa.core.data.RecordCustomObjectType} customObjectType The custom object type
* which represents the {@link Ext.data.Record records} which should be created using
* {@link Zarafa.core.data.RecordFactory#createRecordObjectByCustomType}.
*/
customObjectType : Zarafa.core.data.RecordCustomObjectType.ZARAFA_MDM,
/**
* @constructor
* @param {Object} meta Metadata configuration options.
* @param {Object} recordType (optional) Optional Record type matches the type
* which must be read from response. If no type is given, it will use the
* record type for the {@link Zarafa.core.data.RecordCustomObjectType#ZARAFA_MDM}.
*/
constructor : function(meta, recordType)
{
meta = Ext.applyIf(meta || {}, {
dynamicRecord : false
});
/**
* @constructor
* @param {Object} meta Metadata configuration options.
* @param {Object} recordType (optional) Optional Record type matches the type
* which must be read from response. If no type is given, it will use the
* record type for the {@link Zarafa.core.mapi.ObjectType#MAPI_MDM}.
*/
constructor: function (meta, recordType)
{
meta = Ext.applyIf(meta || {}, {
dynamicRecord: false
});
recordType = Zarafa.core.data.RecordFactory.getRecordClassByMessageClass('IPM.MDM');
recordType = Zarafa.core.data.RecordFactory.getRecordClassByCustomType(Zarafa.core.data.RecordCustomObjectType.ZARAFA_MDM);
Zarafa.plugins.mdm.data.JsonCertificateReader.superclass.constructor.call(this, meta, recordType);
}
Zarafa.plugins.mdm.data.JsonCertificateReader.superclass.constructor.call(this, meta, recordType);
}
});

View File

@ -0,0 +1,21 @@
Ext.namespace('Zarafa.plugins.mdm');
/**
* @class Zarafa.plugins.mdm.data.MDMDeviceFolderRecordFields
*
* Array of default fields for the {@link Zarafa.plugins.mdm.data.MDMDeviceFolderRecord} object.
* These fields will always be added, regardless of the exact type of
* {@link Zarafa.plugins.mdm.data.MDMDeviceFolderRecord record}.
*/
Zarafa.plugins.mdm.data.MDMDeviceFolderRecordFields = [
{name: 'store', type: 'string'},
{name: 'folderid', type: 'string'},
{name: 'name', type: 'string'},
{name: 'type', type: 'int'},
{name: 'flags', type: 'int'},
{name: 'entryid', type: 'string'}
];
Zarafa.core.data.RecordCustomObjectType.addProperty('MDM_Device_Folder');
Zarafa.core.data.RecordFactory.addFieldToCustomType(Zarafa.core.data.RecordCustomObjectType.MDM_Device_Folder, Zarafa.plugins.mdm.data.MDMDeviceFolderRecordFields);
Zarafa.core.data.RecordFactory.setBaseClassToCustomType(Zarafa.core.data.RecordCustomObjectType.MDM_Device_Folder, Zarafa.core.data.MAPIRecord);

View File

@ -0,0 +1,33 @@
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.reg('mdm.devicefolderstore', Zarafa.plugins.mdm.data.MDMDeviceFolderStore);

54
js/data/MDMDeviceProxy.js Normal file
View File

@ -0,0 +1,54 @@
Ext.namespace('Zarafa.plugins.mdm.data');
/**
* @class Zarafa.plugins.mdm.data.MDMDeviceProxy
* @extends Zarafa.core.data.MAPIProxy
*/
Zarafa.plugins.mdm.data.MDMDeviceProxy = Ext.extend(Zarafa.core.data.MAPIProxy, {
/**
* @constructor
* @param {Object} config Configuration object
*/
constructor: function (config)
{
config = config || {};
Ext.applyIf(config, {
listModuleName: 'pluginmdmmodule',
itemModuleName: 'pluginmdmmodule'
});
Zarafa.plugins.mdm.data.MDMDeviceProxy.superclass.constructor.call(this, config);
},
/**
* This will create a {@link Zarafa.core.data.ProxyResponseHandler ProxyResponseHandler} object
* which will be used by the {@link Zarafa.core.data.ResponseRouter ResponseRouter} when the
* response for the given request has returned.
*
* @param {String} modulename The modulename which is being accessed with this request
* @param {Zarafa.core.Actions} serverAction The action to perform on the server.
* @param {Ext.data.Api.action} action name of the action to perform.
* @param {Ext.data.Record[]} records list of records to operate on.
* @param {Object} parameters object containing user parameters such as range (pagination) information, sorting information, etc.
* @param {Ext.data.DataReader} reader data reader. Converts raw JavaScript objects (in our case) to instances of {@link Ext.data.Record}
* @param {Function} callback call back function to call when the request has finished successfully.
* @param {Object} scope scope for the call back function.
* @param {Object} args arguments object. This will be passed to the call back function on successful read.
* @return {Object} An instance of the {@link Zarafa.plugins.mdm.data.MDMDeviceResponseHandler ProxyResponseHandler}
* which should be used for this request.
* @private
*/
getResponseHandlerForRequest: function (modulename, serverAction, action, records, parameters, reader, callback, scope, args)
{
return new Zarafa.plugins.mdm.data.MDMDeviceResponseHandler({
proxy: this,
action: action,
reader: reader,
sendRecords: records,
options: args,
callback: callback,
scope: scope
});
}
});

View File

@ -1,5 +1,10 @@
Ext.namespace('Zarafa.plugins.mdm');
/**
* @class Zarafa.plugins.mdm.data.MDMDeviceRecordFields Array of {@link Ext.data.Field field} configurations for the
* {@link Zarafa.plugins.mdm.data.MDMDeviceRecord record} object.
* @private
*/
Zarafa.plugins.mdm.data.MDMDeviceRecordFields = [
{name: 'entryid', type: 'string'},
{name: 'devicetype', type: 'string'},
@ -12,30 +17,22 @@ Zarafa.plugins.mdm.data.MDMDeviceRecordFields = [
{name: 'lastupdatetime', type: 'date', dateFormat: 'timestamp'},
{name: 'wipestatus', type: 'string'},
{name: 'policyname', type: 'string'},
{name: 'totalfolders', type: 'string'},
{name: 'sharedfolders', type: 'string'},
{name: 'shortfolderids', type: 'string'},
{name: 'synchronizedfolders', type: 'string'},
{name: 'emailsfolder', type: 'string'},
{name: 'contactsfolder', type: 'string'},
{name: 'tasksfolder', type: 'string'},
{name: 'calendarsfolder', type: 'string'},
{name: 'notesfolder', type: 'string'},
{name: 'synchronizedfolders', type: 'string', defaultValue:'0'},
{name: 'emailsfolder', type: 'string', defaultValue:'0'},
{name: 'contactsfolder', type: 'string', defaultValue:'0'},
{name: 'tasksfolder', type: 'string', defaultValue:'0'},
{name: 'calendarsfolder', type: 'string', defaultValue:'0'},
{name: 'notesfolder', type: 'string', defaultValue:'0'},
{name: 'koeversion', type: 'string'},
{name: 'koebuild', type: 'string'},
{name: 'koebuilddate', type: 'date', dateFormat: 'timestamp'}
{name: 'koebuilddate', type: 'date', dateFormat: 'timestamp'},
{name: 'message_class', type: 'string', defaultValue:"IPM.MDM"}
];
/**
*
*/
Zarafa.plugins.mdm.data.MDMDeviceRecord = Ext.extend(Zarafa.core.data.IPMRecord, {});
Zarafa.core.data.RecordCustomObjectType.addProperty('ZARAFA_MDM');
Zarafa.core.data.RecordFactory.addFieldToCustomType(Zarafa.core.data.RecordCustomObjectType.ZARAFA_MDM, Zarafa.plugins.mdm.data.MDMDeviceRecordFields);
Zarafa.core.data.RecordFactory.addListenerToCustomType(Zarafa.core.data.RecordCustomObjectType.ZARAFA_MDM, 'createphantom', function(record)
{
// Phantom records must always be marked as opened (they contain the full set of data)
record.afterOpen();
});
Zarafa.core.data.RecordFactory.setBaseClassToCustomType(Zarafa.core.data.RecordCustomObjectType.ZARAFA_MDM, Zarafa.plugins.mdm.data.MDMDeviceRecord);
Zarafa.core.data.RecordFactory.addFieldToMessageClass('IPM.MDM', Zarafa.plugins.mdm.data.MDMDeviceRecordFields);
Zarafa.core.data.RecordFactory.setBaseClassToMessageClass('IPM.MDM', Zarafa.plugins.mdm.data.MDMDeviceRecord);
Zarafa.core.data.RecordFactory.setSubStoreToMessageClass('IPM.MDM', 'sharedfolders', Zarafa.plugins.mdm.data.MDMDeviceFolderStore);

View File

@ -0,0 +1,41 @@
Ext.namespace('Zarafa.plugins.mdm.data');
/**
* @class Zarafa.plugins.mdm.data.MDMDeviceResponseHandler
* @extends Zarafa.core.data.ProxyResponseHandler
*
* A Simple implementation for a {@link Zarafa.plugins.mdm.data.MDMDeviceResponseHandler ResponseHandler}.
* This one can only be used by {@link Ext.data.DataProxy proxies} which wish to handle a Response
* to their Request.
*
* This implementation limits itself to firing an {@link Ext.data.DataProxy#exception exception}
* on error, and calling a callback function when all processing has been completed.
*/
Zarafa.plugins.mdm.data.MDMDeviceResponseHandler = Ext.extend(Zarafa.core.data.ProxyResponseHandler, {
/**
* Handles the list response. Gathers the stores from the response data, converts each entry
* into a {@link Zarafa.core.MAPIStore MAPIStore} and pushes them into the collectedItems.
* @param {Object} data The response object belonging to the given command.
* @return {Boolean} False when action could not be handled successfully. This will
* not cancel the transaction itself, but rather causes the 'success' argument for the
* {@link #done} function to be false.
*/
doOpen: function(response)
{
this.receivedRecords = this.readRecordsFromResponse(response, 'item');
},
/**
* Handles the list response. Gathers the stores from the response data, converts each entry
* into a {@link Zarafa.core.MAPIStore MAPIStore} and pushes them into the collectedItems.
* @param {Object} data The response object belonging to the given command.
* @return {Boolean} False when action could not be handled successfully. This will
* not cancel the transaction itself, but rather causes the 'success' argument for the
* {@link #done} function to be false.
*/
doList: function(response)
{
this.receivedRecords = this.readRecordsFromResponse(response, 'item');
}
});

View File

@ -20,10 +20,7 @@ Zarafa.plugins.mdm.data.MDMDeviceStore = Ext.extend(Zarafa.core.data.ListModuleS
remoteSort: false,
reader : new Zarafa.plugins.mdm.data.JsonCertificateReader(),
writer : new Zarafa.core.data.JsonWriter(),
proxy : new Zarafa.core.data.IPMProxy({
listModuleName: 'pluginmdmmodule',
itemModuleName: 'pluginmdmmodule'
})
proxy : new Zarafa.plugins.mdm.data.MDMDeviceProxy()
});
Zarafa.plugins.mdm.data.MDMDeviceStore.superclass.constructor.call(this, config);

View File

@ -0,0 +1,57 @@
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);
}
});

View File

View File

@ -2,12 +2,12 @@ Ext.namespace('Zarafa.plugins.mdm.dialogs');
/**
* @class Zarafa.plugins.mdm.dialogs.MDMDeviceContentPanel
* @extends Zarafa.core.ui.ContentPanel
* @extends Zarafa.core.ui.RecordContentPanel
* @xtype mdmplugin.devicecontentpanel
*
* The content panel which is use to show device detail panel.
*/
Zarafa.plugins.mdm.dialogs.MDMDeviceContentPanel = Ext.extend(Zarafa.core.ui.ContentPanel, {
Zarafa.plugins.mdm.dialogs.MDMDeviceContentPanel = Ext.extend(Zarafa.core.ui.RecordContentPanel, {
/**
* @constructor
@ -16,19 +16,24 @@ Zarafa.plugins.mdm.dialogs.MDMDeviceContentPanel = Ext.extend(Zarafa.core.ui.Con
constructor: function (config)
{
config = config || {};
var isKOE = config.record && config.record.get('koeversion') ? true : false;
var isKOE = config.record && config.record.get('koeversion') ? true : false;
Ext.applyIf(config, {
xtype: 'mdmplugin.devicecontentpanel',
modal: true,
title: dgettext('plugin_mdm', config.record.get('devicetype')),
layout : 'fit',
stateful : false,
width : isKOE ? 440 : 405,
height : isKOE ? 395 : 360,
recordComponentPluginConfig: Ext.applyIf(config.recordComponentPluginConfig || {}, {
allowWrite: true,
useShadowStore: true
}),
layout: 'fit',
stateful: false,
showLoadMask: false,
width: isKOE ? 440 : 405,
height: isKOE ? 450 : 420,
items: [{
xtype: 'mdmplugin.mdmdevicepanel',
record: config.record,
isKoe : isKOE,
isKoe: isKOE,
buttons: [{
text: _('Ok'),
handler: this.onOk,

View File

@ -12,7 +12,7 @@ Zarafa.plugins.mdm.dialogs.MDMDeviceGeneralTab = Ext.extend(Ext.form.FormPanel,
/**
* @cfg {Boolean} isKoe True if device has Kopano Outlook Extension information.
*/
isKoe : false,
isKoe: false,
/**
* @constructor
@ -54,7 +54,7 @@ Zarafa.plugins.mdm.dialogs.MDMDeviceGeneralTab = Ext.extend(Ext.form.FormPanel,
createDeviceInfoPanel: function (config)
{
return {
cls : 'mdm-device-panel',
cls: 'mdm-device-panel',
defaultType: 'displayfield',
defaults: {
disabled: true
@ -89,7 +89,7 @@ Zarafa.plugins.mdm.dialogs.MDMDeviceGeneralTab = Ext.extend(Ext.form.FormPanel,
createFolderInfoPanel: function ()
{
return {
cls : 'mdm-device-panel mdm-field-sep',
cls: 'mdm-device-panel mdm-field-sep',
defaultType: 'displayfield',
items: [{
cls: 'mdm-display-name',
@ -104,7 +104,7 @@ Zarafa.plugins.mdm.dialogs.MDMDeviceGeneralTab = Ext.extend(Ext.form.FormPanel,
xtype: 'fieldset',
layout: 'form',
labelWidth: 140,
cls : 'mdm-synchronize-panel',
cls: 'mdm-synchronize-panel',
defaultType: 'displayfield',
defaults: {
labelSeparator: '',
@ -126,7 +126,48 @@ Zarafa.plugins.mdm.dialogs.MDMDeviceGeneralTab = Ext.extend(Ext.form.FormPanel,
}, {
fieldLabel: _('Tasks'),
name: 'tasksfolder'
}]
},
this.createSharedFolderInfoPanel()
]
}]
};
},
/**
* Function which is use to create shared folders panel
* @returns {Object} Configuration object for the panel which shows folders properties
*/
createSharedFolderInfoPanel: function ()
{
return {
xtype: 'panel',
border: false,
cls: 'mdm-synchronize-shared-panel',
height: 50,
disabled: false,
layout: {
type: 'hbox',
align: 'stretch',
pack: 'start'
},
items: [{
layout: 'form',
border: false,
items: [{
xtype: 'displayfield',
fieldLabel: 'Shared Folders',
disabled: true,
name : 'sharedfolders'
}],
flex: 1
}, {
xtype: 'button',
text: dgettext('plugin_mdm', 'Managed shared Folders'),
cls: 'mdm-managesharedfolder-button',
listeners: {
click: this.onClickManageSharedFolder,
scope: this
}
}]
};
},
@ -142,13 +183,25 @@ Zarafa.plugins.mdm.dialogs.MDMDeviceGeneralTab = Ext.extend(Ext.form.FormPanel,
/**
* Function which handles the after render event of status field.
* Which is use to set the the display name for the given Provisioning Status into given field
* Which is use to set the display name for the given Provisioning Status into given field
* @param {Ext.form.TextField} statusField text field
*/
onAfterRenderStatus: function (statusField)
{
var status = parseInt(this.record.get("wipestatus"));
statusField.setValue(Zarafa.plugins.mdm.data.ProvisioningStatus.getDisplayName(status));
},
/**
* Function which handles the click event of manage shared folder button.
* It will open {@link Zarafa.plugins.mdm.dialogs.MDMManageSharedFolderContentPanel dialog}
*/
onClickManageSharedFolder: function ()
{
Zarafa.core.data.UIFactory.openLayerComponent(Zarafa.core.data.SharedComponentType['mdm.dialog.mdmmanagesharedfoldercontentpanel'], undefined, {
manager: Ext.WindowMgr,
record: this.dialog.record
});
}
});

View File

@ -0,0 +1,36 @@
Ext.namespace('Zarafa.plugins.mdm.dialogs');
/**
* @class Zarafa.plugins.mdm.dialogs.MDMManageSharedFolderContentPanel
* @extends Zarafa.core.ui.ContentPanel
* @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, {
/**
* @constructor
* @param config Configuration structure
*/
constructor: function (config) {
config = config || {};
Ext.applyIf(config,
{
xtype: 'mdm.managesharedfoldercontentpanel',
layout: 'fit',
title: dgettext('plugin_mdm','Manage Shared Folder'),
width: 300,
height: 350,
items: [{
xtype: 'mdm.managesharedfolderpanel'
}]
});
Zarafa.plugins.mdm.dialogs.MDMManageSharedFolderContentPanel.superclass.constructor.call(this, config);
}
});
Ext.reg('mdm.managesharedfoldercontentpanel', Zarafa.plugins.mdm.dialogs.MDMManageSharedFolderContentPanel);

View File

@ -0,0 +1,132 @@
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.reg('mdm.managesharedfolderpanel', Zarafa.plugins.mdm.dialogs.MDMManageSharedFolderPanel);

View File

@ -207,6 +207,7 @@ Zarafa.plugins.mdm.settings.MDMSettingsWidget = Ext.extend(Zarafa.settings.ui.Se
onRowDblClick : function (grid, rowIndex)
{
var record = grid.getStore().getAt(rowIndex);
record.opened = false;
Zarafa.core.data.UIFactory.openLayerComponent(Zarafa.core.data.SharedComponentType['mdm.dialog.mdmdevicecontentpanel'], undefined, {
manager : Ext.WindowMgr,
record : record

151
js/ui/MDMFolderNodeUI.js Normal file
View File

@ -0,0 +1,151 @@
Ext.namespace('Zarafa.plugins.mdm.ui');
/**
* @class Zarafa.plugins.mdm.ui.MDMFolderNodeUI
* @extends Zarafa.hierarchy.ui.FolderNodeUI
*
* {@link Zarafa.hierarchy.ui.FolderNodeUI} has limitation that it can add
* (@link Ext.form.Checkbox check box} preceded to calendar item only.
* So, It will add (@link Ext.form.Checkbox check box} preceded to all context items.
*/
Zarafa.plugins.mdm.ui.MDMFolderNodeUI = Ext.extend(Zarafa.hierarchy.ui.FolderNodeUI, {
/**
* Function will render {@link Zarafa.hierachy.ui.FolderNode FolderNode} based on modified template for
* our custom needs.
* @param {Zarafa.hierarchy.ui.FolderNode} node tree node.
* @param {Object} config config object of {@link Zarafa.hierarchy.ui.FolderNode FolderNode}.
* @param {Ext.Element} targetNode element in which {@link Zarafa.hierarchy.ui.FolderNode FolderNode} will be rendered.
* @param {Boolean} bulkRender
*/
renderElements : function(node, config, targetNode, bulkRender)
{
// add some indent caching, this helps performance when rendering a large tree
this.indentMarkup = node.parentNode ? node.parentNode.ui.getChildIndent() : '';
var scheme;
var cb = Ext.isBoolean(config.checked);
var isCalenderNode = config.folder.isCalendarFolder();
var calendarSVGIcon = '';
if (isCalenderNode) {
var calendarContextModel = node.getOwnerTree().model;
// We started providing color choosing facility to all the calendar tree-nodes.
// CalendarContextModel is responsible for this facility.
// There is no CalendarContextModel available in the case where that particular
// calendar-tree-node doesn't belongs to MultiSelectHierarchyTree.
// So, simply made that ContextModel available to current HierarchyTree.
if (!calendarContextModel) {
var calendarContext = container.getContextByName('calendar');
calendarContextModel = calendarContext.getModel();
node.getOwnerTree().model = calendarContextModel;
}
scheme = calendarContextModel.getColorScheme(config.folder.get('entryid'));
// Get the scheme base only if we are able to get scheme successfully,
// otherwise let it be undefined instead of a JS fatal error.
if(scheme && scheme.base) {
calendarSVGIcon = '<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" width="15" height="13" viewBox="0 0 15 13" style="color:'+scheme.base+'; position:relative; top:2px;">' +
'<g>' +
'<g class="icbg" style="fill:currentColor;stroke:none">' +
'<rect width="15" height="12" x="0" y="1" />' +
'<rect width="1" height="1" x="2" y="0" />' +
'<rect width="1" height="1" x="7" y="0" />' +
'<rect width="1" height="1" x="12" y="0" />' +
'</g>' +
'<path class="icgr" d="M 2.5,6.5 h 10 v 4 h -10 v -4.5 M 4.5,6.5 v 4 M 6.5,6.5 v 4 M 8.5,6.5 v 4 M 10.5,6.5 v 4 M 2.5,8.5 h 9.5" style="fill:currentColor;stroke:#ffffff;stroke-width:1;stroke-linejoin=miter" />' +
'</g>' +
'</svg>' ;
}
}
var icon = '<img src="' + (config.icon || this.emptyIcon) + '" class="x-tree-node-icon" unselectable="on" />',
nel,
href = config.href ? config.href : Ext.isGecko ? "" : "#",
buf = '<li class="x-tree-node">' +
'<div ext:tree-node-id="' + node.id + '" class="x-tree-node-el x-tree-node-leaf x-unselectable zarafa-hierarchy-node" unselectable="on">' +
// indent space
'<span class="x-tree-node-indent">' + this.indentMarkup + "</span>" +
// expand icon
'<img src="' + this.emptyIcon + '" class="x-tree-ec-icon x-tree-elbow" />' +
// checkbox
(cb ? '<input class="x-tree-node-cb zarafa-hierarchy-node-cb" type="checkbox" ' + (config.checked ? 'checked="checked" />' : '/>') : '') +
// node icon
(isCalenderNode ? calendarSVGIcon : icon) +
// node element (this.elNode)
'<a hidefocus="on" class="x-tree-node-anchor zarafa-hierarchy-node-anchor" ' +
'href="' + href + '" tabIndex="1" ' +
(config.hrefTarget ? ' target="' + config.hrefTarget + '"' : "") + ">" +
// hierarchy node text (this.textNode)
'<span unselectable="on">' + (node.tpl ? node.tpl.apply(config) : node.text) + '</span>' +
// counter node (this.counterNode)
'<span class="zarafa-hierarchy-node-counter" unselectable="on"></span>' +
'<span class="zarafa-hierarchy-node-owner" unselectable="on"></span>'+
"</a>" +
"</div>" +
'<ul class="x-tree-node-ct" style="display:none;"></ul>' +
"</li>";
if (bulkRender !== true && node.nextSibling && (nel = node.nextSibling.ui.getEl())) {
this.wrap = Ext.DomHelper.insertHtml("beforeBegin", nel, buf);
}else{
this.wrap = Ext.DomHelper.insertHtml("beforeEnd", targetNode, buf);
}
this.elNode = this.wrap.childNodes[0];
this.ctNode = this.wrap.childNodes[1];
var cs = this.elNode.childNodes;
this.indentNode = cs[0];
this.ecNode = cs[1];
this.iconNode = cs[2];
var index = 3;
if (cb) {
this.checkbox = cs[2];
this.iconNode = cs[3];
// Get child elements of caledar icon which is used to register in drag and drop manager.
var groupContainerNode = this.iconNode.childNodes[0];
if (Ext.isDefined(groupContainerNode)) {
var groupNode = groupContainerNode.childNodes[0];
var rectNode = groupNode.childNodes[0];
var pathNode = groupContainerNode.childNodes[1];
this.calendarSVGIconChilds = [rectNode, pathNode];
}
index++;
}
this.anchor = cs[index];
this.textNode = cs[index].firstChild;
this.counterNode = cs[index].firstChild.nextSibling;
this.folderOwnerNode = this.counterNode.nextSibling;
// Apply some optional CSS classes
var elNode = Ext.get(this.elNode);
var iconNode = Ext.get(this.iconNode);
var containerNode = Ext.get(this.wrap);
var textNode = Ext.get(this.textNode);
if (isCalenderNode) {
textNode.addClass('zarafa-hierarchy-node-color');
}
if (!Ext.isEmpty(config.cls)) {
elNode.addClass(config.cls);
}
if (config.icon) {
iconNode.addClass('x-tree-node-inline-icon');
}
if (config.iconCls) {
iconNode.addClass(config.iconCls);
}
if (!Ext.isEmpty(config.containerCls)) {
containerNode.addClass(config.containerCls);
}
this.updateCounter(node);
this.showFolderOwner(node);
}
});

View File

@ -0,0 +1,44 @@
Ext.namespace('Zarafa.plugins.mdm.ui');
/**
* @class Zarafa.plugins.mdm.ui.MDMHierarchyTreePanel
* @extends Zarafa.hierarchy.ui.Tree
* @xtype mdm.hierarchytree
*
* MDMHierarchyTreePanel for hierachy list in the
* {@link Zarafa.plugins.mdm.dialogs.MDMManageSharedFolderPanel manageSharedFolderPanel}.
*/
Zarafa.plugins.mdm.ui.MDMHierarchyTreePanel = Ext.extend(Zarafa.hierarchy.ui.Tree, {
/**
* @constructor
* @param {Object} config Configuration object
*/
constructor : function(config)
{
Zarafa.plugins.mdm.ui.MDMHierarchyTreePanel.superclass.constructor.call(this, config);
},
/**
* Function will initialize {@link Zarafa.hierarchy.ui.Tree Tree} and creates a
* {@link Zarafa.common.ui.LoadMask} if {@link Zarafa.hierarchy.ui.Tree Tree} is intantiated as full tree.
* @protected
*/
initComponent : function()
{
// Intialize the loader
if (!this.loader) {
this.loader = new Zarafa.plugins.mdm.data.MDMHierarchyTreeLoader({
tree : this,
store : this.store,
nodeConfig : this.nodeConfig,
deferredLoading : this.deferredLoading
});
}
// call parent
Zarafa.plugins.mdm.ui.MDMHierarchyTreePanel.superclass.initComponent.apply(this, arguments);
}
});
Ext.reg('mdm.hierarchytree', Zarafa.plugins.mdm.ui.MDMHierarchyTreePanel);

View File

@ -26,18 +26,28 @@
<clientfile load="release">js/mdm.js</clientfile>
<clientfile load="debug">js/mdm-debug.js</clientfile>
<clientfile load="source">js/MDM.js</clientfile>
<clientfile load="source">js/data/MDMDeviceFolderStore.js</clientfile>
<clientfile load="source">js/data/MDMDeviceFolderRecord.js</clientfile>
<clientfile load="source">js/data/JsonDeviceFolderReader.js</clientfile>
<clientfile load="source">js/data/MDMResponseHandler.js</clientfile>
<clientfile load="source">js/data/MDMDeviceRecord.js</clientfile>
<clientfile load="source">js/data/JsonDeviceReader.js</clientfile>
<clientfile load="source">js/data/MDMDeviceStore.js</clientfile>
<clientfile load="source">js/data/ProvisioningStatus.js</clientfile>
<clientfile load="source">js/data/MDMDeviceProxy.js</clientfile>
<clientfile load="source">js/data/MDMDeviceResponseHandler.js</clientfile>
<clientfile load="source">js/data/MDMHierarchyTreeLoader.js</clientfile>
<clientfile load="source">js/settings/MDMSettingsWidget.js</clientfile>
<clientfile load="source">js/settings/MDMSettingsCategory.js</clientfile>
<clientfile load="source">js/dialogs/MDMDeviceContentPanel.js</clientfile>
<clientfile load="source">js/dialogs/MDMDeviceGeneralTab.js</clientfile>
<clientfile load="source">js/dialogs/MDMDevicePanel.js</clientfile>
<clientfile load="source">js/dialogs/MDMDeviceDetailsTab.js</clientfile>
<clientfile load="source">js/dialogs/MDMManageSharedFolderContentPanel.js</clientfile>
<clientfile load="source">js/dialogs/MDMManageSharedFolderPanel.js</clientfile>
<clientfile load="source">js/ui/Renderers.js</clientfile>
<clientfile load="source">js/ui/MDMFolderNodeUI.js</clientfile>
<clientfile load="source">js/ui/MDMHierarchyTreePanel.js</clientfile>
</client>
<resources>
<resourcefile load="release">resources/css/mdm.css</resourcefile>

View File

@ -171,6 +171,20 @@ class PluginMDMModule extends Module
$this->addActionData('list', $data);
$GLOBALS['bus']->addData($this->getResponseData());
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);
$this->addActionData('item', $item);
$GLOBALS['bus']->addData($this->getResponseData());
break;
default:
$this->handleUnknownActionType($actionType);
}
@ -212,6 +226,7 @@ class PluginMDMModule extends Module
'lastsynctime', 'lastupdatetime', 'wipestatus', 'policyname', 'koeversion', 'koebuild', 'koebuilddate'];
$item['entryid'] = $device['deviceid'];
$item['message_class'] = "IPM.MDM";
foreach ($propsList as $prop) {
if (isset($device[$prop])) {
$item[$prop] = $device[$prop];
@ -262,11 +277,11 @@ class PluginMDMModule extends Module
$synchronizedFolders += $value;
$syncFoldersProps[strtolower($key) . 'folder'] = $value;
}
$syncFoldersProps["totalfolders"] = count($folders);
$client = $this->getSoapClient();
$items = $client->AdditionalFolderList($device['deviceid']);
$syncFoldersProps['sharedfolders'] = count($items);
$syncFoldersProps["shortfolderids"] = $device['hasfolderidmapping'] ? dgettext('plugin_mdm', "Yes") : dgettext('plugin_mdm', "No");
$syncFoldersProps['synchronizedfolders'] = $synchronizedFolders;
$syncFoldersProps['synchronizedfolders'] = $synchronizedFolders + count($items);
return $syncFoldersProps;
}
@ -309,5 +324,34 @@ class PluginMDMModule extends Module
}
return $folderType;
}
/**
* Function which is use to get list of additional folders which was shared with given device
* @param string $devid device id
* @return array has list of properties related to shared folders
*/
function getAdditionalFolderList($devid)
{
$stores = $GLOBALS["mapisession"]->getAllMessageStores();
$client = $this->getSoapClient();
$items = $client->AdditionalFolderList($devid);
$data = array();
foreach ($items as $item)
{
foreach ($stores as $store)
{
try {
$entryid = mapi_msgstore_entryidfromsourcekey($store, hex2bin($item->folderid));
} catch (MAPIException $me) {
continue;
}
}
if (isset($entryid)) {
$item->entryid = bin2hex($entryid);
}
array_push($data, array("props" => $item));
}
return $data;
}
};
?>

View File

@ -2,7 +2,6 @@
background-image:url(../icons/mdm_icon.png) !important;
}
.mdm-devicepanel.x-panel.tabpanel-container
> .x-panel-bwrap
> .x-panel-body {
@ -17,7 +16,6 @@
padding: 0!important;
}
.mdm-display-name {
font-weight: bold !important;
padding: 4px 0 2px 0;
@ -36,5 +34,17 @@
.mdm-synchronize-panel {
border: 0px;
margin-left: 10px;
padding: 0px;
padding: 9px 0 0 0;
}
.mdm-managesharedfolder-button {
padding-right: 10px;
}
.mdm-create-tree-panel-item {
margin: 0 0 5px 0;
}
.mdm-synchronize-shared-panel {
padding-top: 9px;
}