/* * Copyright 2007-2017 Charles du Jeu - Abstrium SAS * This file is part of Pydio. * * Pydio is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Pydio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Pydio. If not, see . * * The latest code can be found at . */ 'use strict'; exports.__esModule = true; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } var _langObservable = require('../lang/Observable'); var _langObservable2 = _interopRequireDefault(_langObservable); var _langLogger = require('../lang/Logger'); var _langLogger2 = _interopRequireDefault(_langLogger); var _httpPydioApi = require('../http/PydioApi'); var _httpPydioApi2 = _interopRequireDefault(_httpPydioApi); var _utilXMLUtils = require('../util/XMLUtils'); var _utilXMLUtils2 = _interopRequireDefault(_utilXMLUtils); var _Action = require('./Action'); var _Action2 = _interopRequireDefault(_Action); /** * Singleton class that manages all actions. Can be called directly using pydio.getController(). */ var Controller = (function (_Observable) { _inherits(Controller, _Observable); /** * Standard constructor * @param pydioObject Pydio * @param dataModelElementId */ function Controller(pydioObject) { var dataModelElementId = arguments.length <= 1 || arguments[1] === undefined ? null : arguments[1]; _classCallCheck(this, Controller); _Observable.call(this); this._pydioObject = pydioObject; this._registeredKeys = new Map(); this.usersEnabled = pydioObject.Parameters.get("usersEnabled"); this.subMenus = []; this.actions = new Map(); this.defaultActions = new Map(); this.toolbars = new Map(); this._guiActions = new Map(); this.contextChangedObs = (function (event) { window.setTimeout((function () { this.fireContextChange(); }).bind(this), 0); }).bind(this); this.selectionChangedObs = (function (event) { window.setTimeout((function () { this.fireSelectionChange(); }).bind(this), 0); }).bind(this); if (dataModelElementId) { this.localDataModel = true; try { this._dataModel = document.getElementById(dataModelElementId).ajxpPaneObject.getDataModel(); } catch (e) {} if (this._dataModel) { this._connectDataModel(); } else { this._pydioObject.observeOnce("datamodel-loaded-" + dataModelElementId, (function () { this._dataModel = document.getElementById(dataModelElementId).ajxpPaneObject.getDataModel(); this._connectDataModel(); }).bind(this)); } } else { this.localDataModel = false; this._connectDataModel(); } if (this.usersEnabled) { this._pydioObject.observe("user_logged", (function (user) { this.setUser(user); }).bind(this)); if (this._pydioObject.user) { this.setUser(this._pydioObject.user); } } } Controller.prototype.publishActionEvent = function publishActionEvent(eventName, data) { this._pydioObject.fire(eventName, data); }; Controller.prototype._connectDataModel = function _connectDataModel() { if (this.localDataModel) { this._dataModel.observe("context_changed", this.contextChangedObs); this._dataModel.observe("selection_changed", this.selectionChangedObs); this.loadActionsFromRegistry(); this._pydioObject.observe("registry_loaded", (function (registry) { this.loadActionsFromRegistry(registry); }).bind(this)); } else { this._pydioObject.observe("context_changed", this.contextChangedObs); this._pydioObject.observe("selection_changed", this.selectionChangedObs); this._dataModel = this._pydioObject.getContextHolder(); } }; Controller.prototype.updateGuiActions = function updateGuiActions(actions) { actions.forEach((function (v, k) { this._guiActions.set(k, v); this.registerAction(v); }).bind(this)); //this.notify("actions_refreshed"); }; Controller.prototype.deleteFromGuiActions = function deleteFromGuiActions(actionName) { this._guiActions['delete'](actionName); //this.notify("actions_refreshed"); }; Controller.prototype.refreshGuiActionsI18n = function refreshGuiActionsI18n() { this._guiActions.forEach(function (value, key) { value.refreshFromI18NHash(); }); }; Controller.prototype.getDataModel = function getDataModel() { return this._dataModel; }; Controller.prototype.destroy = function destroy() { if (this.localDataModel && this._dataModel) { this._dataModel.stopObserving("context_changed", this.contextChangedObs); this._dataModel.stopObserving("selection_changed", this.selectionChangedObs); } }; Controller.prototype.getMessage = function getMessage(messageId) { try { return this._pydioObject.MessageHash[messageId]; } catch (e) { return messageId; } }; /** * COMPATIBILITY METHD * @param xmlDoc * @returns {*} */ Controller.prototype.parseXmlMessage = function parseXmlMessage(xmlDoc) { _langLogger2['default'].debug("Controller.parseXmlMessage() is deprecated, use PydioApi instead"); return _httpPydioApi2['default'].getClient().parseXmlMessage(xmlDoc); }; /** * Submits a form using Connexion class. * @param formName String The id of the form * @param post Boolean Whether to POST or GET * @param completeCallback Function Callback to be called on complete */ Controller.prototype.submitForm = function submitForm(formName, post, completeCallback) { _langLogger2['default'].debug("Controller.submitForm() is deprecated, use PydioApi instead"); return _httpPydioApi2['default'].getClient().submitForm(formName, post, completeCallback); }; /** * Stores the currently logged user object * @param oUser User User instance */ Controller.prototype.setUser = function setUser(oUser) { this.oUser = oUser; if (oUser != null && oUser.id != 'guest' && oUser.getPreference('lang') != null && oUser.getPreference('lang') != "" && oUser.getPreference('lang') != this._pydioObject.currentLanguage && !oUser.lock) { this._pydioObject.loadI18NMessages(oUser.getPreference('lang')); } }; /** * Filter the actions given the srcElement passed as arguments. * @param actionsSelectorAtt String An identifier among selectionContext, genericContext, a webfx object id * @param ignoreGroups Array a list of groups to ignore * @returns Array */ Controller.prototype.getContextActions = function getContextActions(actionsSelectorAtt, ignoreGroups, onlyGroups) { var contextActions = []; var defaultGroup = undefined; var contextActionsGroup = new Map(); this.actions.forEach((function (action) { if (!action.context.contextMenu && !(onlyGroups && onlyGroups.length)) return; if (actionsSelectorAtt == 'selectionContext' && !action.context.selection) return; if (actionsSelectorAtt == 'directoryContext' && !action.context.dir) return; if (actionsSelectorAtt == 'genericContext' && action.context.selection) return; if (action.contextHidden || action.deny) return; action.context.actionBarGroup.split(',').forEach(function (barGroup) { if (!contextActionsGroup.has(barGroup)) { contextActionsGroup.set(barGroup, []); } }); var isDefault = false; if (actionsSelectorAtt == 'selectionContext') { // set default in bold var userSelection = this._dataModel; if (!userSelection.isEmpty()) { var defaultAction = 'file'; if (userSelection.isUnique() && (userSelection.hasDir() || userSelection.hasMime(['ajxp_browsable_archive']))) { defaultAction = 'dir'; } if (this.defaultActions.get(defaultAction) && action.options.name == this.defaultActions.get(defaultAction)) { isDefault = true; } } } action.context.actionBarGroup.split(',').forEach(function (barGroup) { var menuItem = action.getMenuData(); menuItem.isDefault = isDefault; contextActionsGroup.get(barGroup).push(menuItem); if (isDefault) { defaultGroup = barGroup; } }); }).bind(this)); var first = true, keys = []; contextActionsGroup = this._sortToolbarsActions(contextActionsGroup); contextActionsGroup.forEach(function (v, k) { if (defaultGroup && k == defaultGroup) return; keys.push(k); }); keys.sort(); if (defaultGroup && contextActionsGroup.has(defaultGroup)) { keys.unshift(defaultGroup); } var actionsPushed = {}; keys.map(function (key) { var value = contextActionsGroup.get(key); if (!first) { contextActions.push({ separator: true }); } if (ignoreGroups && ignoreGroups.indexOf(key) !== -1) { return; } if (onlyGroups && onlyGroups.indexOf(key) === -1) { return; } first = false; value.forEach(function (mItem) { var actionId = mItem.action_id; if (!actionsPushed[actionId]) { contextActions.push(mItem); actionsPushed[actionId] = true; } }); }); return contextActions; }; Controller.prototype.getToolbarsActions = function getToolbarsActions() { var _this = this; var toolbarsList = arguments.length <= 0 || arguments[0] === undefined ? [] : arguments[0]; var groupOtherList = arguments.length <= 1 || arguments[1] === undefined ? [] : arguments[1]; var toolbars = new Map(), groupOtherBars = new Map(); var lastTbarAdded = undefined; this.actions.forEach((function (action) { if (action.context.actionBar) { action.context.actionBarGroup.split(",").map((function (barGroup) { if (toolbarsList.indexOf(barGroup) === -1 && groupOtherList.indexOf(barGroup) === -1) { return; } var tBarUpdate = toolbarsList.indexOf(barGroup) !== -1 ? toolbars : groupOtherBars; if (tBarUpdate.get(barGroup) == null) { tBarUpdate.set(barGroup, []); } tBarUpdate.get(barGroup).push(action); if (tBarUpdate === toolbars) { lastTbarAdded = barGroup; } }).bind(this)); } }).bind(this)); // Regroup actions artificially if (groupOtherList.length) { (function () { var submenuItems = []; groupOtherList.map((function (otherToolbar) { var otherActions = groupOtherBars.get(otherToolbar); if (!otherActions) return; otherActions.map(function (act) { submenuItems.push({ actionId: act }); }); if (groupOtherList.indexOf(otherToolbar) < groupOtherList.length - 1) { submenuItems.push({ separator: true }); } }).bind(_this)); var moreAction = new _Action2['default']({ name: 'group_more_action', icon_class: 'icon-none', text: MessageHash[456], title: MessageHash[456], hasAccessKey: false, subMenu: true, callback: function callback() {} }, { selection: false, dir: true, actionBar: true, actionBarGroup: '', contextMenu: false, infoPanel: false }, {}, {}, { dynamicItems: submenuItems }); _this.registerAction(moreAction); _this.actions.set("group_more_action", moreAction); toolbars.set('MORE_ACTION', [moreAction]); })(); } this._sortToolbarsActions(toolbars); return toolbars; }; /** * Generic method to get actions for a given component part. * @param ajxpClassName String * @param widgetId String * @returns [] */ Controller.prototype.getActionsForAjxpWidget = function getActionsForAjxpWidget(ajxpClassName, widgetId) { var actions = []; this.actions.forEach(function (action) { if (action.context.ajxpWidgets && (action.context.ajxpWidgets.indexOf(ajxpClassName + '::' + widgetId) != -1 || action.context.ajxpWidgets.indexOf(ajxpClassName) != -1) && !action.deny) actions.push(action); }); return actions; }; /** * Finds a default action and fires it. * @param defaultName String ("file", "dir", "dragndrop", "ctrldragndrop") */ Controller.prototype.fireDefaultAction = function fireDefaultAction(defaultName) { var actionName = this.defaultActions.get(defaultName); if (actionName) { arguments[0] = actionName; if (actionName === "ls") { var action = this.actions.get(actionName); if (action) action.enable(); // Force enable on default action } this.fireAction.apply(this, arguments); } }; /** * Fire an action based on its name * @param actionName String The name of the action */ Controller.prototype.fireAction = function fireAction(actionName) { var action = this.actions.get(actionName); if (action != null) { var args = Array.from(arguments).slice(1); action.apply(args); } }; /** * Registers an accesskey for a given action. * @param key String The access key * @param actionName String The name of the action * @param optionnalCommand String An optionnal argument * that will be passed to the action when fired. */ Controller.prototype.registerKey = function registerKey(key, actionName, optionnalCommand) { if (optionnalCommand) { actionName = actionName + "::" + optionnalCommand; } this._registeredKeys.set(key.toLowerCase(), actionName); }; /** * Remove all registered keys. */ Controller.prototype.clearRegisteredKeys = function clearRegisteredKeys() { this._registeredKeys = new Map(); }; /** * Triggers an action by its access key. * @param keyName String A key name */ Controller.prototype.fireActionByKey = function fireActionByKey(keyName) { if (this._registeredKeys.get(keyName)) { if (this._registeredKeys.get(keyName).indexOf("::") !== -1) { var parts = this._registeredKeys.get(keyName).split("::"); this.fireAction(parts[0], parts[1]); } else { this.fireAction(this._registeredKeys.get(keyName)); } return true; } return false; }; /** * Complex function called when drag'n'dropping. Basic checks of who is child of who. * @param fileName String The dragged element * @param destDir String The drop target node path * @param destNodeName String The drop target node name * @param copy Boolean Copy or Move */ Controller.prototype.applyDragMove = function applyDragMove(fileName, destDir, destNodeName, copy) { if (!copy && (!this.defaultActions.has('dragndrop') || this.getDefaultAction('dragndrop').deny) || copy && (!this.defaultActions.has('ctrldragndrop') || this.getDefaultAction('ctrldragndrop').deny)) { return; } var fileNames = undefined; if (fileName == null) fileNames = this._dataModel.getFileNames();else fileNames = [fileName]; // Check that dest is not the direct parent of source, ie current rep! if (destDir == this._dataModel.getContextNode().getPath()) { this._pydioObject.displayMessage('ERROR', MessageHash[203]); return; } // Check that dest is not child of source it self for (var i = 0; i < fileNames.length; i++) { if (destDir.lastIndexOf(fileNames[i], 0) === 0) { this._pydioObject.displayMessage('ERROR', MessageHash[202]); return; } } var params = {}; params['get_action'] = this.defaultActions.get(copy ? 'ctrldragndrop' : 'dragndrop'); params['nodes[]'] = fileNames; params['dest'] = destDir; params['dir'] = this._dataModel.getContextNode().getPath(); _httpPydioApi2['default'].getClient().request(params, (function (transport) { this.parseXmlMessage(transport.responseXML); }).bind(_httpPydioApi2['default'].getClient())); }; /** * Get the action defined as default for a given default string * @param defaultName String * @returns Action */ Controller.prototype.getDefaultAction = function getDefaultAction(defaultName) { if (this.defaultActions.has(defaultName)) { return this.actions.get(this.defaultActions.get(defaultName)); } return null; }; /** * Spreads a selection change to all actions and to registered components * by triggering ajaxplorer:actions_refreshed event. */ Controller.prototype.fireSelectionChange = function fireSelectionChange() { this.actions.forEach((function (action) { action.fireSelectionChange(this._dataModel); }).bind(this)); this.notify("actions_refreshed"); }; /** * Spreads a context change to all actions and to registered components * by triggering ajaxplorer:actions_refreshed event. */ Controller.prototype.fireContextChange = function fireContextChange() { this.actions.forEach((function (action) { action.fireContextChange(this._dataModel, this.usersEnabled, this.oUser); }).bind(this)); this.notify("actions_refreshed"); }; Controller.prototype.notify = function notify(eventName, memo) { if (this.localDataModel) { _Observable.prototype.notify.call(this, "actions_refreshed", memo); } else { this._pydioObject.fire("actions_refreshed"); } }; /** * Remove all actions */ Controller.prototype.removeActions = function removeActions() { this.actions.forEach(function (action) { action.remove(); }); this.actions = new Map(); this.clearRegisteredKeys(); }; /** * Create actions from XML Registry * @param registry DOMDocument */ Controller.prototype.loadActionsFromRegistry = function loadActionsFromRegistry() { var registry = arguments.length <= 0 || arguments[0] === undefined ? null : arguments[0]; if (!registry) { registry = pydio.getXmlRegistry(); } this.removeActions(); this.parseActions(registry); this._guiActions.forEach((function (act) { this.registerAction(act); }).bind(this)); this.notify("actions_loaded"); this.fireContextChange(); this.fireSelectionChange(); }; /** * Registers an action to this manager (default, accesskey). * @param action Action */ Controller.prototype.registerAction = function registerAction(action) { var actionName = action.options.name; this.actions.set(actionName, action); if (action.defaults) { for (var key in action.defaults) { if (action.defaults.hasOwnProperty(key)) { this.defaultActions.set(key, actionName); } } } if (action.options.hasAccessKey) { this.registerKey(action.options.accessKey, actionName); } if (action.options.specialAccessKey) { this.registerKey("key_" + action.options.specialAccessKey, actionName); } action.setManager(this); }; /** * Parse an XML action node and registers the action * @param documentElement DOMNode The node to parse */ Controller.prototype.parseActions = function parseActions(documentElement) { var actions = _utilXMLUtils2['default'].XPathSelectNodes(documentElement, "actions/action"); for (var i = 0; i < actions.length; i++) { if (actions[i].nodeName != 'action') continue; if (actions[i].getAttribute('enabled') == 'false') continue; var newAction = new _Action2['default'](); newAction.setManager(this); newAction.createFromXML(actions[i]); this.registerAction(newAction); } }; /** * Find an action by its name * @param actionName String * @returns Action */ Controller.prototype.getActionByName = function getActionByName(actionName) { return this.actions.get(actionName); }; Controller.prototype._sortToolbarsActions = function _sortToolbarsActions(toolbars) { // Sort toolbars.forEach(function (v, k) { if (!v.sort) return; v.sort(function (a, b) { var wA = a.weight || a.options && a.options.weight || 0; var wB = b.weight || b.options && b.options.weight || 0; return wA === wB ? 0 : wA > wB ? 1 : -1; }); }); return toolbars; }; return Controller; })(_langObservable2['default']); exports['default'] = Controller; module.exports = exports['default'];