/** * Ext.space.Applications is an API that lets applications retrieve information about * an organization's other applications. * * To fetch a list of applications, use the .list() method: * * Ext.space.Applications.list().then(function(list) { * list.forEach(function(app) { * // do something with the app object; for example, to open them all: * Ext.space.Applications.open(app); * }); * }); * * The API also allows applications to listen for updates to the list of applications * and run a callback in response: * * Ext.space.Applications.onUpdate(function(reason, operation, list) { * // process the list when it changes (`reason` and `operation` are hints) * }); * * Additionally, the API allows applications to listen for badge/alert/data * notifications being pushed to <i>any</i> application in the organization (as * opposed to Ext.space.Notification, which listens for notifications for the * current application only). This is useful for creating administration dashboards * that need to display data from multiple applications simultaneously. */Ext.define("Ext.space.Applications", { extend: Ext.space.Observable, singleton: true, /** * @private */ events: null, /** * @private */ _listeningForNotifications: false, /** * Whether or not the module is watching the list for changes * @readonly * @private * @type {boolean} */ _watchingList: false, /** * @private */ constructor: function() { this.events = { badge: new Ext.space.Observable(), alert: new Ext.space.Observable(), data: new Ext.space.Observable() }; var args = Array.prototype.slice.call(arguments); Ext.onSpaceReady().then(function() { Ext.space.Applications.superclass.constructor.apply(this, args); }.bind(this)); }, /** * Listen for changes to the applications list * @private */ _watchList: function() { if (!this._watchingList) { Ext.space.Communicator.send({ command: "Applications#watchList", callbacks: { onSuccess: this._onUpdate.bind(this) } }); this._watchingList = true; // TODO: when Observable gets the ability to remove listeners, unwatch when // there are no more listeners left } }, /** * Callback that fires when the application list changes * * @private * @param {string} reason The thing that changed (categories, applications, etc...) * @param {string} operation The type of change (add, remove, update) * @param {Array} list List of objects containing the current applications list */ _onUpdate: function(reason, operation, list) { this.invokeListeners(reason, operation, list); }, /** * Retrieve the current organization's applications list * * @return {Ext.space.Promise} Promise that resolves with the list */ list: function() { var result = new Ext.space.Promise(); Ext.space.Communicator.send({ command: "Applications#list", callbacks: { onSuccess: function(apps) { // TODO: determine how much else to transform these, if at all // (e.g., remove 'deleted', convert dates to objects, etc...) result.fulfill(apps.map(function(app) { return new Ext.space.applications.Application(app); })); }, onError: function(error) { result.reject(error); } } }); return result; }, /** * Open an application. * * @param {Object|string} app The application object or application ID * @return {Ext.space.Promise} Promise that resolves when the app is launched */ open: function(app) { var result = new Ext.space.Promise(); if (app) { Ext.space.Communicator.send({ command: "Applications#open", id: app.id || app, callbacks: { onSuccess: function() { result.fulfill(); }, onError: function(error) { result.reject(error); } } }); } else { result.reject("Cannot open application; no ID provided."); } return result; }, /** * Register a callback to run when the application list changes in some way. * * The callback will be passed a three parameters, a string indicating the * reason for the callback being invoked ("categories", etc...), a * string indicating the operation that happened (such as "add", "remove", * "update"), and an array of objects representing the current state of the * applications list itself. * * function onListUpdate(reason, operation, list) { * Ext.space.Logger.log("Updated: ", reason, operation); * // do something with the items in `list`... * } * * Ext.space.Applications.onUpdate(onListUpdate); * * @param {Function} callback Callback to fire when the application list changes. */ onUpdate: function(callback) { var args = Array.prototype.slice.call(arguments); Ext.onSpaceReady().then(function() { if (!this._watchingList) { this._watchList(); } this.addListener.apply(this, args); }.bind(this)); }, /** * Start listening for push notifications for all apps in the current organization. * * @private */ _listenForNotifications: function() { this._listeningForNotifications = true; Ext.onSpaceReady().then(function() { Ext.space.Communicator.send({ command: "Notification#registerHandler", callbacks: { onGlobalBadgeChange: this._onBadgeChange.bind(this), onGlobalAlertReceived: this._onAlert.bind(this), onGlobalDataReceived: this._onData.bind(this), onSuccess: function() { /* no need to do anything */ } } }); }.bind(this)); }, /** * Callback that fires when any application's badge has changed. * * @private * @param {Object} change object containing the application ID and the new * badge's value: {appId: "...", badgeValue: "..."} */ _onBadgeChange: function(change) { this.events.badge.invokeListeners(change.appId, change.badgeValue); }, /** * Register a callback to run when any application's badge has changed, across * all applications in the current organization. * * function onBadgeChanged(appId, badge) { * Ext.space.Logger.log("New Badge (" + appId + "): " + badge); * } * * Ext.space.Applications.onBadgeChange(onBadgeChanged); * * @param {Function} callback Callback for when any application's badge has changed. */ onBadgeChange: function(callback) { if (!this._listeningForNotifications) { this._listenForNotifications(); } this.events.badge.addListener(callback); }, /** * Callback that fires when an alert is received by any application in the * current organization. * * @private * @param {Object} change object containing the application ID and the alert * object: {appId: "...", alert: "..."} */ _onAlert: function(change) { this.events.alert.invokeListeners(change.appId, change.alert); }, /** * Register a callback to run when an alert is received for any application in * the current organization. * * function onAlertReceived(appId, alert) { * Ext.space.Logger.log("New alert (" + appId + "): " + alert.message); * // alert.icon string of the icon * // alert.tags contains an array of tags * } * * Ext.space.Applications.onAlert(onAlertReceived); * * @param {Function} callback Callback for when an alert is received by any application. */ onAlert: function(callback) { if (!this._listeningForNotifications) { this._listenForNotifications(); } this.events.alert.addListener(callback); }, /** * Callback that fires when data is received for any application in the current * organization. * * @private * @param {string} change object containing the application ID and the data * string: {appId: "...", data: "..."} */ _onData: function(change) { this.events.data.invokeListeners(change.appId, change.data); }, /** * Register a callback to run when data is received by any application in the * current organization. * * function onDataReceived(appId, data) { * Ext.space.Logger.log("Data (" + appId + "): " + data); * } * * Ext.space.Applications.onData(onDataReceived); * * @param {Function} callback Callback for when data is received by any application. */ onData: function(callback) { if (!this._listeningForNotifications) { this._listenForNotifications(); } this.events.data.addListener(callback); }});