importPackage(Packages.de.elo.ix.client); //@include lib_Class.js //@include lib_sol.common.JsonUtils.js //@include lib_sol.common.ix.RfUtils.js //@include lib_sol.common.IxUtils.js //@include lib_sol.common.ObjectUtils.js //@include lib_sol.common.WfUtils.js //@include lib_sol.common.Template.js //@include lib_sol.common.ix.FunctionBase.js //@include lib_sol.common.Injection.js /** * To be executed on a sord[1] which contains one or more fields[2] which contain handlebars templates. * The handlebars template may contain fields from multiple sords[3] (sord.objKeys, CANDIDATE.objKeys, POSTING.objKeys ...). * For each of these sords, a search instruction [4] must be defined. The search must be enriched with data of sord[1]. * The fields'[2] handlebars template strings will then be rendered using the data which was fetched from the sords[3]. * Finally, the rendered strings are saved to the sord[1]. * * In the learning solution, this is used to render e.g. personalized e-mail templates which are sent to the course participants. * * A search instruction [4] may consist of the parameters defined in {@link sol.common.ix.services.SordProvider SordProvider}. * * @author ESt, ELO Digital Office GmbH * @version 1.0 * * @eloix * * @requires sol.common.JsonUtils * @requires sol.common.ix.RfUtils * @requires sol.common.IxUtils * @requires sol.common.ix.FunctionBase */ sol.define("sol.common.ix.functions.RenderTemplate", { extend: "sol.common.ix.FunctionBase", mixins: ["sol.common.mixins.Inject"], requiredConfig: ["templateFields"], inject: { templateFields: { prop: "templateFields", forTemplating: false }, searches: { prop: "searches", forTemplating: false, template: true, emptyNonRendered: true }, redactor: { prop: "redactor", forTemplating: false }, sord: { sordIdFromProp: "objId", flowIdFromProp: "flowId", includeBlobs: true } }, // checks if all mandatory properties are available in the sord. checkSordValues: function (sord, paths, optional) { var me = this, ok = true; paths .forEach(function (path) { if (!(String(sol.common.ObjectUtils.getProp(sord, path) || ""))) { if (optional) { me.logger.warn("Optional property " + path + " not found in sord! Skipping search ..."); ok = false; } else { throw "A search field did not have a value! Aborting ... Field path:" + path; } } }); return ok; }, // checks if all mandatory search properties are not empty. finalizeSearchValues: function (search) { var me = this; return search .filter(function (criterion) { if (!criterion.value) { if (criterion.optional) { me.logger.warn("Optional property " + criterion.key + " not included in search because it was empty!"); return false; } else { throw "A search field did not have a value! Aborting ... Field:" + criterion.key; } } return true; }); }, getObjIdOf: function (config) { var me = this; if (me.checkSordValues(me.sord, config.const.checkSordValues, !!config.const.optional)) { config.output = [{ source: { type: "SORD", key: "id" } }]; config.search = me.finalizeSearchValues(config.search); config.options || (config.options = {}); config.options.maxResults = 1; return sol.common.IxUtils.execute("RF_sol_common_service_SordProvider", config).sords[0]; } }, addSordsToTemplatingData: function (templatingData, sordNames) { var me = this; sordNames .forEach(function (sordName) { var config = me.searches[sordName], objId = me.getObjIdOf(config); if (!objId) { if (!config.const.optional) { throw "Could not find " + sordName; } } else { templatingData[sordName] = sol.common.WfUtils.getTemplateSord( ixConnect.ix().checkoutSord(objId, SordC.mbAllIndex, LockC.NO) ).sord; } }); }, getTplPath: function (field) { var t = field.type; return field.templatePath || ("sord." + ( ((t === "GRP") && "objKeys.") || ((t === "MAP") && "mapKeys.") || ((t === "WFMAP") && "wfMapKeys.") || ((t === "FORMBLOB") && "formBlobs.") || "" ) + field.key ); }, renderTemplateFields: function (fields, templatingData) { var me = this; fields = fields .map(function (field) { field.value = String(sol.common.ObjectUtils.getProp(templatingData, me.getTplPath(field)) || ""); return field; }) .map(function (field) { field.value = me.renderValue(field, templatingData); return field; }) .map(function (field) { // rerender value so that templateFields are rendered twice to support template fields which also contain handlebar expressions if (me.shouldRerenderValue(field)) { field.value = me.renderValue(field, templatingData); } return field; }); }, shouldRerenderValue: function (field) { var me = this; return (me.rerenderValues || field.rerenderValue) && (field.value || "").indexOf("{{"); }, renderValue: function (field, templatingData) { var me = this; return sol.common.TemplateUtils.render( field.value, templatingData, { emptyNonRendered: !me.keepUnrenderedTemplates } ); }, addRedactorTemplates: function (templateFields, templatingData, targetBlob, clips) { var clipStr; if (!targetBlob) { throw "A taget BLOB-fieldname must be defined in redactor.storeInBlob config property!"; } clipStr = sol.common.JsonUtils.stringifyQuick((sol.common.IxUtils.execute("RF_sol_common_service_GetRedactorTemplates", { templates: clips, render: { data: templatingData } }) || {}).templates || []); templateFields.push({ type: "FORMBLOB", key: targetBlob, value: clipStr }); }, process: function () { var me = this, templatingData = me.$templatingData, templateFields = me.templateFields, redactor = me.redactor; if (!Array.isArray(templateFields) || !templateFields.length) { throw "No fields were defined for rendering!"; } templatingData.wfOwner = me.wfOwnerName; me.excludeUserData || (templatingData.ELOUSER = sol.common.WfUtils.getTemplateSord(sol.common.UserUtils.getUserFolder(ixConnect.loginResult.user.name)).sord); me.excludeSord && (templatingData.sord = undefined); me.excludeStaticData || (templatingData.CUSTOM = me.staticData); me.dontSearchForAdditionalData || me.addSordsToTemplatingData(templatingData, Object.keys(me.searches || {})); me.sordIsAlso && (templatingData[String(me.sordIsAlso)] = me.sord); me.renderTemplateFields(templateFields, templatingData); redactor && me.addRedactorTemplates(templateFields, templatingData, String(redactor.storeInBlob || ""), redactor.clips); sol.common.IxUtils.execute("RF_sol_function_Set", { objId: String(me.objId), flowId: String(me.flowId), entries: templateFields }); } }); /** * @member sol.common.ix.functions.RenderTemplate * @static * @inheritdoc sol.common.ix.FunctionBase#onEnterNode */ function onEnterNode(_clInfo, _userId, wfDiagram, nodeId) { var params; sol.common.WfUtils.checkMainAdminWf(wfDiagram); params = sol.common.WfUtils.parseAndCheckParams(wfDiagram, nodeId), params.objId = params.objId || wfDiagram.objId; params.flowId = params.flowId || wfDiagram.id; params.wfOwnerName = String(wfDiagram.ownerName); (sol.create("sol.common.ix.functions.RenderTemplate", params)).process(); } /** * @member sol.common.ix.functions.RenderTemplate * @static * @inheritdoc sol.common.ix.FunctionBase#onEnterNode */ function onExitNode(_clInfo, _userId, wfDiagram, nodeId) { var params; sol.common.WfUtils.checkMainAdminWf(wfDiagram); params = sol.common.WfUtils.parseAndCheckParams(wfDiagram, nodeId), params.objId = params.objId || wfDiagram.objId; params.flowId = params.flowId || wfDiagram.id; params.wfOwnerName = String(wfDiagram.ownerName); (sol.create("sol.common.ix.functions.RenderTemplate", params)).process(); }