importClass(Packages.de.elo.client.scripting.constants.CONSTANTS); //@include lib_handlebars.js //@include lib_Class.js //@include lib_sol.common.Config.js //@include lib_sol.common.Template.js //@include lib_sol.common.JsonUtils.js //@include lib_sol.common.IxUtils.js //@include lib_sol.common.RepoUtils.js //@include lib_sol.common.AsUtils.js //@include lib_sol.common.HttpUtils.js //@include lib_sol.common.ObjectUtils.js //@include lib_sol.common.jc.ClipboardUtils.js /** * This class provides helper functions for executing complex actions. * * @author PZ, ELO Digital Office GmbH * @version 1.0 * * @elojc * @requires sol.common.Config * @requires sol.common.IxUtils * @requires sol.common.jc.ActionHandler */ sol.define("sol.common.jc.ActionHelper", { singleton: true, initialize: function (config) { var me = this; me.$super("sol.Base", "initialize", [config]); }, executeSimpleAction: function (objId, cfg) { var me = this, actionCfg = me.initActionCfg(objId); me.logger.info(["executing simple action on objId: {0}", objId], cfg); if (!cfg || !cfg.fct) { throw "executing simple action is missing mandatory config properties."; } me.handleExecuteAction(cfg, actionCfg); }, /** * Helps in executing advanced actions that include precondition checks and * different object types. * * Advanced action configurations are handled in the following order: * * 1. select types (optional) * 2. check preconditions (type selection possible if returned by check) (optional) * 3. select target (optional) * 4. execute action (IX/ AS) (required) * * Please note that step 1 and 2 can be used for selecting types. If a special function * is used for type selection (Step 1), the user selection is overriden if a second * type selection is handled by step 2. * * { * preconditions: { * fct: 'RF_sol_contact_service_CheckContactPreconditions', * }, * fct: 'RF_sol_contact_action_CreateContact', * cfgTemplate: '{ * "parentId": "{{objId}}", * "contactType": "{{type.name}}, * "templateId": "{{type.objId}} * }', * locale: { * errorDlgTitle: locale['sol.contact.client.contact.create.dialog.error.title'], * typesDlgTitle: locale['sol.contact.client.contact.create.dialog.title'], * typesDlgHeader: locale['sol.contact.client.contact.create.dialog.header'], * typesDlgText: locale['sol.contact.client.contact.create.dialog.text'], * typesDlgNoTypes: locale['sol.contact.client.contact.create.msg.notype'], * * targetDlgTitle: locale['sol.contact.client.contact.create.dialog.title'], * targetDlgHeader: locale['sol.contact.client.contact.create.dialog.header'], * targetDlgText: locale['sol.contact.client.contact.create.dialog.text'], * } * } * * @param {String} objId Object ID * @param {Object} cfg Configuration */ executeAdvancedAction: function (objId, cfg) { var me = this, actionCfg = me.initActionCfg(objId), checkResult, selectedType, selectedTarget; me.logger.info(["executing advanced action on objId: {0}", objId], cfg); if (!cfg || !cfg.fct || !cfg.cfgTemplate) { throw "executing advanced action is missing mandatory config properties."; } // handle type selection if (me.requiresTypeSelection(cfg)) { selectedType = me.handleTypeSelection(cfg, actionCfg); if (!selectedType) { return; } actionCfg.type = selectedType; } // handle prepare & preconditions if (me.requiresPrepare(cfg)) { checkResult = sol.common.IxUtils.execute(cfg.preconditions.fct, { targetId: objId }); if (checkResult.valid !== true) { workspace.showAlertBox(cfg.locale.errorDlgTitle, checkResult.msg); return; } } if (checkResult) { if (checkResult.targetId && (checkResult.targetId != objId)) { me.logger.info(["changed objId by prepare: {0} -> {1}", objId, checkResult.targetId]); actionCfg.objId = checkResult.targetId; } if (checkResult.types) { actionCfg.type = me.handleTypeSelection(cfg, actionCfg, checkResult.types); if (!actionCfg.type) { return; } } actionCfg.preconditions = checkResult; } // handle target selection if (me.requiresTargetSelection(cfg)) { selectedTarget = me.handleTargetSelection(cfg); if (!selectedTarget) { return; } actionCfg.tree = selectedTarget; } // handle execution me.handleExecuteAction(cfg, actionCfg); }, initActionCfg: function (objId) { var actionCfg = { objId: objId }; return actionCfg; }, getConfigObject: function (cfgTemplate, data) { var str = Handlebars.compile(cfgTemplate)(data); return JSON.parse(str); }, requiresPrepare: function (cfg) { return cfg.preconditions && cfg.preconditions.fct; }, requiresTypeSelection: function (cfg) { if (cfg.selectType && cfg.selectType.fct) { return true; } return false; }, requiresTargetSelection: function (cfg) { return !!cfg.selectTree; }, handleTypeSelection: function (cfg, actionCfg, types) { var me = this, typeServiceCfg, optionNames, optionDescriptions, icons, selected; if (!types) { typeServiceCfg = (cfg.selectType.cfgTemplate) ? me.getConfigObject(cfg.selectType.cfgTemplate, actionCfg) : {}; types = sol.common.IxUtils.execute(cfg.selectType.fct, typeServiceCfg); } if (!types || (types.length === 0)) { workspace.setFeedbackMessage(cfg.locale.typesDlgNoTypes); return null; } if (types.length > 1) { optionNames = types.map(function (type) { return type.name; }); optionDescriptions = types.map(function (type) { return type.desc || ""; }); icons = []; selected = workspace.showCommandLinkDialog( cfg.locale.typesDlgTitle, cfg.locale.typesDlgHeader, cfg.locale.typesDlgText, CONSTANTS.DIALOG_ICON.QUESTION, optionNames, optionDescriptions, icons); } else { selected = 1; } return (selected < 0) ? null : types[selected - 1]; }, handleTargetSelection: function (cfg) { var me = this, documentsSelectable = (cfg.selectTree.hasOwnProperty("document")) ? cfg.selectTree.document : true, folderSelectable = (cfg.selectTree.hasOwnProperty("folder")) ? cfg.selectTree.folder : true, showFavorites = (cfg.selectTree.hasOwnProperty("favorite")) ? cfg.selectTree.favorite : true, dlgRootId, config, selectedId, selectedElement; if (cfg.selectTree.root) { dlgRootId = ixConnect.ix().checkoutSord(cfg.selectTree.root, SordC.mbOnlyId, LockC.NO).id; } else if (cfg.selectTree.rootFromCfgFile && cfg.selectTree.rootFromCfgProperty) { config = sol.create("sol.common.Config", { compose: cfg.selectTree.rootFromCfgFile }); dlgRootId = ixConnect.ix().checkoutSord(me.getConfigObject(cfg.selectTree.rootFromCfgProperty, config), SordC.mbOnlyId, LockC.NO).id; } if (!dlgRootId) { return null; } me.logger.info("action requires target selection. Using root: {0}", dlgRootId); selectedId = workspace.showTreeSelectDialog( cfg.locale.treeDlgTitle, cfg.locale.treeDlgHeader, dlgRootId, documentsSelectable, folderSelectable, showFavorites); if (selectedId > 0) { selectedElement = archive.getElement(selectedId); return { name: selectedElement.name + "", objId: selectedElement.id + "" }; } return null; }, prepareCfgObj: function (cfgTemplate, actionCfg) { var cfgObj, regex, objIdReplacement; cfgTemplate = cfgTemplate.replace(/\\{{/g, "{{"); if (cfgTemplate.indexOf("\"{{objId}}\"") > -1) { regex = new RegExp("\"{{objId}}\"", "g"); objIdReplacement = (actionCfg.objId) ? "\"" + actionCfg.objId + "\"" : null; } else { regex = new RegExp("{{objId}}", "g"); objIdReplacement = (actionCfg.objId) ? actionCfg.objId : null; } cfgTemplate = cfgTemplate.replace(regex, objIdReplacement); cfgObj = cfgTemplate ? JSON.parse(cfgTemplate) : {}; cfgObj.$templating = { $type: actionCfg.type, $tree: actionCfg.tree, $preconditions: actionCfg.preconditions }; return cfgObj; }, /** * Handles the final execution of the action. * @private * @param {Object} cfg Configuration * @param {Object} actionCfg Action configuration */ handleExecuteAction: function (cfg, actionCfg) { var me = this, cfgObj; cfgObj = me.prepareCfgObj(cfg.cfgTemplate, actionCfg); // render objId and setup serverside templating data try { switch (cfg.type) { case "AS": sol.common.jc.ActionHandler.executeAS(cfg.solution, cfg.fct, cfgObj); break; default: sol.common.jc.ActionHandler.execute(cfg.fct, cfgObj); } } catch (ex) { me.logger.error(["Error executing action: '{0}'", cfg.fct], ex); workspace.showAlertBox("Error executing action", ex); } } }); /** * This class provides utility functions to call IX or AS functions and handle the response in a standardized way. * * Following example shows executing an Index Server action. * * sol.common.jc.ActionHandler.execute('RF_sol_pubsec_functions_CreateFile', { * objId: '123' * }, function ( result ) { * // handle resultObj returned by the action * }); * * # Supported events * * - REFRESH * - GOTO * - DIALOG * - ERROR * - ACTION * - FEEDBACK * * # Conditional events * It is possible for actions to declare the events as conditional. * Therefor they have to declare a `ON` attribute (see {@link sol.common.ActionBase}). * * @author PZ, ELO Digital Office GmbH * @version 1.03.000 * * @elojc * @requires sol.common.ObjectUtils * @requires sol.common.JsonUtils * @requires sol.common.IxUtils */ sol.define("sol.common.jc.ActionHandler", { singleton: true, /** * Executes a IX registered function and handles the response in a standardized way. * * Depricated feature: * If special handling is needed a custom callback can be spezified as parameter. * This callback get's the result Object of the registered function as only parameter. * * @param {String} registeredFunctionName * @param {Object} params (optional) The configuration object which will be send to the registered function * @param {Function} callback (optional) Should not be used, due to client interoperability */ execute: function (registeredFunctionName, params, callback) { var me = this, resultObj; workspace.setWaitCursor(); try { resultObj = sol.common.IxUtils.execute(registeredFunctionName, params); if (callback && Object.prototype.toString.call(callback) === "[object Function]") { me.logger.warn("Use of 'callback' parameter is depricated and therefore not recommended."); callback.call(me, resultObj); workspace.setNormalCursor(); return; } if (resultObj) { me.handleEvents(resultObj.events); } } catch (ex) { sol.common.jc.ClipboardUtils.setText(ex); me.logger.error(["Error calling RF '{0}'", registeredFunctionName], ex); throw ex; } finally { workspace.setNormalCursor(); } }, /** * Executes an ELOas ruleset and handles the response in a standardized way. * * If spezial handling is needed a custom callback can be spezified as parameter. * This callback get's the result Object of the registered function as only parameter. * * @param {String} solutionName Name used to determine the ELOas configuration (see {@link sol.common.Config#loadEloAsConfig loadEloAsConfig}) * @param {String} ruleName Rule name * @param {Object} param2Obj (optional) The configuration object which will be send to the ELOas rule as PARAM2 (JSON String) * @param {Function} callback (optional) Should not be used anymore, due to client interoperability * @param {Boolean} async (optional) Not supported anymore, due to client interoperability */ executeAS: function (solutionName, ruleName, param2Obj, callback, async) { var me = this, resultObj = {}, language, result; workspace.setWaitCursor(); try { language = ixConnect.loginResult.clientInfo.language + ""; result = sol.common.IxUtils.execute("RF_sol_common_service_ExecuteAsAction", { solution: solutionName, action: ruleName, config: param2Obj, connParams: { language: language } }); if (async) { workspace.setNormalCursor(); return; } resultObj = {}; if (result) { resultObj = JSON.parse(result.content); } if (callback && Object.prototype.toString.call(callback) === "[object Function]") { me.logger.warn("Use of 'callback' parameter is depricated and therefore not recommended."); callback.call(me, resultObj); workspace.setNormalCursor(); return; } if (resultObj.events && (resultObj.events.length > 0)) { resultObj.events.forEach(function (event) { event.solutionName = solutionName; event.async = async; }); } if (resultObj) { me.handleEvents(resultObj.events); } } catch (ex) { sol.common.jc.ClipboardUtils.setText(ex); me.logger.error(["Error calling ELOas direct rule '{0}'", ruleName], ex); throw ex; } finally { workspace.setNormalCursor(); } }, /** * @private * @param {Array} events */ handleEvents: function (events) { var eventTypes = sol.common.IxUtils.CONST.EVENT_TYPES, eventChain; if (events) { eventChain = sol.create("sol.common.jc.ActionHandler.EventChain"); events.forEach(function (event) { switch (event.ID) { case eventTypes.REFRESH: event.$handler = sol.create("sol.common.jc.ActionHandler.Refresh"); break; case eventTypes.GOTO: event.$handler = sol.create("sol.common.jc.ActionHandler.Goto"); break; case eventTypes.DIALOG: event.$handler = sol.create("sol.common.jc.ActionHandler.Dialog"); break; case eventTypes.ERROR: event.$handler = sol.create("sol.common.jc.ActionHandler.Error"); break; case eventTypes.ACTION: event.$handler = sol.create("sol.common.jc.ActionHandler.Action"); break; case eventTypes.FEEDBACK: event.$handler = sol.create("sol.common.jc.ActionHandler.Feedback"); break; default: break; } eventChain.add(event); }); eventChain.chain(); } } }); /** * This class handles the asynchrous event handling for the JavaClient `sol.common.jc.ActionHandler` * * @author PZ, ELO Digital Office GmbH * @version 1.01.002 * * @elojc * @requires sol.common.ObjectUtils * @requires sol.common.SordUtils * @requires sol.common.IxUtils */ sol.define("sol.common.jc.ActionHandler.EventChain", { /** * @private * @property {Object[]} events The remaining event chain. */ /** * @private * @property {Object} context The execution context. */ initialize: function (config) { var me = this; me.$super("sol.Base", "initialize", [config]); me.events = []; me.context = { dirtySord: true, dirtyWfStatus: true }; }, /** * Adds an event to the event chain. * @param {Object} event */ add: function (event) { var me = this; if (event) { me.events.push(event); } }, /** * Retrieves the current active event. * @return {Object} */ getCurrent: function () { var me = this; return me.current; }, /** * Retrieves the context. * @return {Object} */ getContext: function () { var me = this; return me.context; }, /** * Handles the event chaining. * If the next event is executable, this will call it's handler (and the handler needs to take care of the further chaining), if not the chain will be continued. */ chain: function () { var me = this; me.logger.enter("chaining"); me.current = me.events.shift(); if (!me.current) { me.logger.exit("chaining"); return; // event chain finished } if (me.checkExecution(me.current)) { me.current.$handler.execute(me); } else { me.chain(); } }, /** * @private * Checks, if an event defines a valid handler, and if the event has an `ON` property it will be evaluated. * @return {Boolean} */ checkExecution: function () { var me = this, event = me.current, canExecute = true, ignore = false, checkValue; me.logger.enter("checkExecution", event); if (!event) { me.logger.warn("No event to check"); canExecute = false; } if (canExecute && (!event.$handler || !sol.common.ObjectUtils.isFunction(event.$handler.execute))) { me.logger.warn(["No handler for event of type '{0}' -> skip", event.ID]); canExecute = false; } if (canExecute && event.ON) { if (me.context.dirtySord && event.ON.objId) { me.context.sord = ixConnect.ix().checkoutSord(event.ON.objId, SordC.mbAllIndex, LockC.NO); me.context.dirtySord = false; } if (me.context.dirtyWfStatus && event.ON.flowId) { me.context.wfStatus = sol.common.IxUtils.execute("RF_sol_common_service_GetWorkflowMetadata", { flowId: event.ON.flowId }).status; me.context.dirtyWfStatus = false; } switch (event.ON.type) { case "WF_STATUS": checkValue = me.context.wfStatus; break; case "GRP": checkValue = sol.common.SordUtils.getValue(me.context.sord, event.ON); break; case "SORD": checkValue = sol.common.SordUtils.getValue(me.context.sord, event.ON); break; case "MAP": checkValue = sol.common.SordUtils.getValue(me.context.sord, event.ON); break; default: me.logger.warn(["event defines non existing ON.type={0}, ON condition will be ignored", event.ON.type]); ignore = true; } if (!ignore) { canExecute = checkValue == event.ON.value; } } me.logger.exit("checkExecution", { canExecute: canExecute }); return canExecute; } }); /** * This class handles the refresh event. * * @author PZ, ELO Digital Office GmbH * @version 1.01.002 * * @elojc * @requires sol.common.ObjectUtils * @requires sol.common.SordUtils * @requires sol.common.IxUtils * @requires sol.common.jc.ActionHandler.EventChain */ sol.define("sol.common.jc.ActionHandler.Refresh", { execute: function (eventChain) { var event, eventConfig, element, taskViewIterator, taskView; event = eventChain.getCurrent(); if (event.ID !== sol.common.IxUtils.CONST.EVENT_TYPES.REFRESH) { throw "'sol.common.jc.ActionHandler.REFRESH' can only handle '" + sol.common.IxUtils.CONST.EVENT_TYPES.REFRESH + "' events, but event-ID was '" + event.ID + "'"; } taskViewIterator = tasksViews.tasksViews.iterator(); while (taskViewIterator.hasNext()) { taskView = taskViewIterator.next(); taskView.refresh(); } if (event.obj) { eventConfig = event.obj; element = archive.getElement(eventConfig.objId); if (element instanceof Packages.de.elo.client.scripting.items.ArchiveElement) { element.refresh(); } } eventChain.chain(); } }); /** * This class handles the goto event. * * @author PZ, ELO Digital Office GmbH * @version 1.01.002 * * @elojc * @requires sol.common.ObjectUtils * @requires sol.common.SordUtils * @requires sol.common.IxUtils * @requires sol.common.jc.ActionHandler.EventChain */ sol.define("sol.common.jc.ActionHandler.Goto", { execute: function (eventChain) { var event, eventConfig, firstTaskView, taskView, element, lastCheckedOut, docFile; event = eventChain.getCurrent(); if (event.ID !== sol.common.IxUtils.CONST.EVENT_TYPES.GOTO) { throw "'sol.common.jc.ActionHandler.GOTO' can only handle '" + sol.common.IxUtils.CONST.EVENT_TYPES.GOTO + "' events, but event-ID was '" + event.ID + "'"; } if (event.obj) { eventConfig = event.obj; if (eventConfig.flowId) { firstTaskView = tasksViews.tasksViews.get(0); firstTaskView.show(); firstTaskView.refresh(); taskView = tasksViews.getTasksViewForWorkflow(eventConfig.flowId); if (taskView) { taskView.show(); taskView.clearSelection(); taskView.selectWorkflow(eventConfig.flowId); } } else if (eventConfig.objId) { workspace.updateSordLists(); workspace.activeView && workspace.activeView.refresh(); workspace.gotoId(eventConfig.objId); element = archive.getElement(eventConfig.objId); if (eventConfig.checkout && (element instanceof Packages.de.elo.client.scripting.items.ArchiveDocument)) { element.checkOut(); lastCheckedOut = checkout.getLastDocument(); if (lastCheckedOut.id === element.id) { docFile = lastCheckedOut.getDocumentFile(); if (docFile) { docFile.setWritable(true); utils.editFile(docFile); } } } workspace.updateEnabledFunctions(); } } eventChain.chain(); } }); /** * This class handles the dialog event. * * @author PZ, ELO Digital Office GmbH * @version 1.01.002 * * @elojc * @requires sol.common.ObjectUtils * @requires sol.common.SordUtils * @requires sol.common.IxUtils * @requires sol.common.RepoUtils * @requires sol.common.jc.ActionHandler.EventChain */ sol.define("sol.common.jc.ActionHandler.Dialog", { execute: function (eventChain) { var me = this, event, context, eventConfig, dlg; event = eventChain.getCurrent(); if (event.ID !== sol.common.IxUtils.CONST.EVENT_TYPES.DIALOG) { throw "'sol.common.jc.ActionHandler.DIALOG' can only handle '" + sol.common.IxUtils.CONST.EVENT_TYPES.DIALOG + "' events, but event-ID was '" + event.ID + "'"; } context = eventChain.getContext(); context.dirtySord = true; context.dirtyWfStatus = true; if (event.obj) { eventConfig = event.obj; dlg = workspace.createAppDialog(eventConfig.title || ""); dlg.hideStatusBar = true; if (eventConfig.dialogId) { dlg.dialogId = eventConfig.dialogId; } if (eventConfig.url) { dlg.loadUrl(eventConfig.url); } else if (eventConfig.flowId && eventConfig.nodeId) { dlg.loadWFForm(eventConfig.flowId, eventConfig.nodeId); } if (sol.common.RepoUtils.checkVersion(workspace.clientVersion, "10.00.012")) { dlg.show(null, function (dialog, closeSource) { if (closeSource == "ABORT") { sol.common.IxUtils.execute("RF_sol_common_service_ActionCancelForm", { flowId: eventConfig.flowId, nodeId: eventConfig.nodeId }); } eventChain.chain(); }, me); } else { dlg.show(); eventChain.chain(); } } } }); /** * This class handles the error event. * * @author PZ, ELO Digital Office GmbH * @version 1.01.002 * * @elojc * @requires sol.common.ObjectUtils * @requires sol.common.SordUtils * @requires sol.common.IxUtils * @requires sol.common.jc.ActionHandler.EventChain */ sol.define("sol.common.jc.ActionHandler.Error", { execute: function (eventChain) { var event, eventConfig; event = eventChain.getCurrent(); if (event.ID !== sol.common.IxUtils.CONST.EVENT_TYPES.ERROR) { throw "'sol.common.jc.ActionHandler.ERROR' can only handle '" + sol.common.IxUtils.CONST.EVENT_TYPES.ERROR + "' events, but event-ID was '" + event.ID + "'"; } if (event.obj) { eventConfig = event.obj; workspace.showAlertBox(utils.getText("sol.common", "sol.common.client.ActionHandler.errordlg.title"), eventConfig.msg); } eventChain.chain(); } }); /** * This class handles the action event. * * @author PZ, ELO Digital Office GmbH * @version 1.01.002 * * @elojc * @requires sol.common.ObjectUtils * @requires sol.common.SordUtils * @requires sol.common.IxUtils * @requires sol.common.jc.ActionHandler * @requires sol.common.jc.ActionHandler.EventChain */ sol.define("sol.common.jc.ActionHandler.Action", { execute: function (eventChain) { var event, context; event = eventChain.getCurrent(); if (event.ID !== sol.common.IxUtils.CONST.EVENT_TYPES.ACTION) { throw "'sol.common.jc.ActionHandler.ACTION' can only handle '" + sol.common.IxUtils.CONST.EVENT_TYPES.ACTION + "' events, but event-ID was '" + event.ID + "'"; } context = eventChain.getContext(); context.dirtySord = true; context.dirtyWfStatus = true; if (event.COMPONENT === sol.common.IxUtils.CONST.COMPONENTS.IX) { sol.common.jc.ActionHandler.execute(event.obj.registeredFunction, event.obj.params); } else if (event.COMPONENT === sol.common.IxUtils.CONST.COMPONENTS.AS) { sol.common.jc.ActionHandler.executeAS(event.solutionName, event.obj.directRule, event.obj.params, null, event.async); } eventChain.chain(); } }); /** * This class handles the feedback event. * * @author PZ, ELO Digital Office GmbH * @version 1.03.000 * * @elojc * @requires sol.common.ObjectUtils * @requires sol.common.SordUtils * @requires sol.common.IxUtils * @requires sol.common.jc.ActionHandler.EventChain */ sol.define("sol.common.jc.ActionHandler.Feedback", { execute: function (eventChain) { var event, eventConfig; event = eventChain.getCurrent(); if (event.ID !== sol.common.IxUtils.CONST.EVENT_TYPES.FEEDBACK) { throw "'sol.common.jc.ActionHandler.FEEDBACK' can only handle '" + sol.common.IxUtils.CONST.EVENT_TYPES.FEEDBACK + "' events, but event-ID was '" + event.ID + "'"; } if (event.obj) { eventConfig = event.obj; if (eventConfig.permanent === true) { workspace.showInfoBox(utils.getText("sol.common", "sol.common.client.ActionHandler.infodlg.title"), eventConfig.msg); } else { workspace.setFeedbackMessage(eventConfig.msg); } } eventChain.chain(); } });