Extend eXo Cloud Drive to new cloud services with the Connector API: Customization and configuration (Part 3 of 3)
In case you missed them, you can quickly jump to the previous parts of the series:
In this post we will finish the introduction to Cloud Drive add-on’s Connector API. As you already read in the first post, the Cloud Drive is an add-on that connects cloud files into eXo. It is extensible, thanks to the Connector API, and we have already reviewed its architecture and its Java API.
In this post you will learn how the client side can be customized via connector’s CSS and Javascript API. We will end by seeing how configuration and packaging work.
Styles customization
The eXo Platform and Cloud Drive offer UI customization via CSS. Drives, files (by their mimetype), and menu icons already have dedicated class names. To add your styles you will need to follow the conventions and place a properly named file, with required class names, in the right place. Then, when your connector initializes the cloud provider via UI context, this file will be loaded by the Cloud Drive client script. An example of how such a CSS file can look is in the template project in this file.
Javascript client
Cloud Drive uses client side Javascript for better integration with existing user interface of eXo Platform. File icons and ECMS context menus are customized directly in the browser to reuse the existing applications infrastructure. The client is also responsible for initiation of new drives’ connection and synchronization.
Cloud Drive client it is an AMD module registered in the Platform portal and loaded to ECMS Documents pages when the user opens a cloud drive folder. If the connector needs a custom Javascript, it should be registered as a module with the name . Then it behaves similarly to CSS loading: if the module is available for a drive provider, it will be loaded by the client and used to serve the drive.
One of important purposes of a connector Javascript is managing automatic synchronization. By default, the Cloud Drive client will do a periodic sync when a user opens the drive folder. But making periodic requests to the server isn’t the best approach, especially when nothing changes remotely. If your cloud service can inform you of changes in real time (e.g. by a “long-polling” request), there is a way to leverage this via Connector API.
Cloud Drive’s Javascript is based on asynchronous processing; it uses jQuery Deferred internally to implement this technique. If the connector script has a method initiate the synchronization during the work. In this case, the logic of your connector will manage when a next sync request will be invoked, thereby reducing network traffic and making the experience better for your users.
it will be used to obtain a Promise instance that will be used toIf the client needs to deal with data specific only to your connector, Connector API offers several possibilities:
- each connected drive may have a state—an object of any type that also will be returned to a client as a part of the drive response (/clouddrive/drive web-service)
- you can implement your own RESTful service (somewhere at ) and request it from custom client module.
To customize or initialize the UI elements, the connector client can use jQuery.ready() handlers registered from its module. Below is a simplified example of a client module (it implements
and read custom data from connector’s REST-service):/** * My Cloud support for eXo Cloud Drive. */ (function($, cloudDrive, utils) { /** * My Cloud connector class. */ function MyCloud() { // Provider Id for My Cloud var PROVIDER_ID = "mycloud"; var prefixUrl = utils.pageBaseUrl(location); /** * It is a method that Cloud Drive core client will look for when loading the connector module. * We request cloud service, when it will respond OK it will mean My Cloud drive has remote changes. * Return jQuery Promise object that will be resolved when some change will appear, or rejected on error. */ this.onChange = function(drive) { var process = $.Deferred(); if (drive) { if (drive.state) { var changes = cloudDrive.ajaxGet(drive.state.url); changes.done(function(info, status) { process.resolve(); // this will cause drive synchronization }); changes.fail(function(response, status, err) { process.reject("Changes request failed on " + drive.path + ". " + err + " (" + status + ") "); }); } else { process.reject("Cannot check for changes. No state object for Cloud Drive on " + drive.path); } } else { process.reject("Null drive in onChange()"); } return process.promise(); }; /** * Request custom web-service (file comments) asynchronously and proceed data via jQuery Promise. */ this.fileComments = function(workspace, path) { return cloudDrive.ajaxGet(prefixUrl + "/portal/rest/clouddrive/drive/mycloud", {"workspace" : workspace, "path" : path}); }; }; var client = new MyCloud(); // client will be used below in DOM-ready handler // On DOM-ready handler to initialize custom UI (or any other specific work on a client) // We do initialization only if run in top window, not in iframe (gadgets doesn’t need it) if (window == top) { $(function() { // Add an action to some button "Show File Comments" $("#file_comments_button").click(function() { var drive = cloudDrive.getContextDrive(); var file = cloudDrive.getContextFile(); if (drive && file) { var comments = client.readComments(drive.workspace, file.path); comments.done(function(commentsArray, status) { // Append comments to a some invisible div on the page and then show it var container = $("#file_comments_div"); $.each(commentsArray, function(i, c) { $("<div class='myCloudFileComment'>" + c + "</div>").appendTo(container); }); container.show(); }); comments.fail(function(response, status, err){ utils.log("Comments request failed. " + err + " (" + status + ") " + JSON.stringify(response)); }); } }); }); } return client; // return client from the module })($, cloudDrive, cloudDriveUtils);
Configuration
When code needs to be executed, you will need a configuration for your connector. Follow this guide to learn how to configure existing connectors, and use it to practice for new connectors. Instructions for creating a configuration of components and connector extension can be found here.
In general, each connector needs the following configurations:
- the connector’s extension in . The connector should depend on the Cloud Drive extension and has priority higher than 1000.
- The connector plugin of . This defines all required parameters of the connector (ID, name, etc.)
- proper in the WAR of the connector
- optionally it may need configuration of dedicated JCR namespaces and node types
- optionally it may need UI extensions configuration (e.g. when offering a dedicated connect-menu)
- optionally it may need CSS and Javascript configuration in the portal’s
- finally, if component configuration relies on variables, you need to define variables in or via JVM settings of the server.
Packaging and Deployment
At some point, you will need to deploy your connector to a Platform server. There are several ways, but we recommend using a proper one: use eXo Add-ons manager, a modern and friendly tool with a rich user experience. The Extension manager script, an older tool that already exists in eXo 4.0, can also do the job. In both cases you will need to package your connector as an add-on and make it available to the deployer.
Our template project already contains a packaging artifact. It is able to package all connector files in an archive compatible with the add-ons managers. If your connector uses third-party libraries, add them in the Maven dependencies and the assembly of the packaging. Build the project and use the resulting zip-archive, from the packaging, as an add-on for the installation.
An important notice about uninstallation: if you create some specific data that might damage the Platform in case of your add-on removal, consider using a correct uninstallation process. Note that dedicated UI actions, if they follow Cloud Drive UI requirements, will be automatically removed by the core add-on.
Done!
So, there you are. Now it’s time for you to create a new Cloud Drive connector and deploy it to the eXo Platform. Connector API opens a way for any developer to do this without changing the Cloud Drive code or configuration. I hope to see new connectors soon in the eXo Community.
Have a good time coding!
Join the eXo tribe by registering for the community and get updates, tutorials, support, and access to the Platform and add-on downloads!
Make the most out of eXo Platform 4
Register to the next webinar and get a complete overview of what you can do with eXo Platform 4. Reserve your seat now!