From 546a3870dd4f85cf44faaeb66a912123a7bffe9e Mon Sep 17 00:00:00 2001 From: Johannes Hoermann <j.hoermann@adito.de> Date: Wed, 12 Jun 2019 15:57:43 +0200 Subject: [PATCH] remove logging --- .../entityfields/deleteseries/stateProcess.js | 1 - .../recordcontainers/jdito/contentProcess.js | 1 - .../entityfields/icon/valueProcess.js | 1 - .../entityfields/contact_id/valueProcess.js | 1 - .../entityfields/object_type/valueProcess.js | 1 - .../recordcontainers/jdito/contentProcess.js | 291 ++++--- .../recordcontainers/jdito/contentProcess.js | 1 - process/ActivityTask_lib/process.js | 2 - process/Context_lib/process.js | 1 - process/DocumentTemplate_lib/process.js | 736 +++++++++--------- process/Email_lib/process.js | 370 +++++---- process/KeywordData_lib/process.js | 2 - process/Keyword_lib/process.js | 6 - process/Turnover_lib/process.js | 4 - 14 files changed, 697 insertions(+), 721 deletions(-) diff --git a/entity/Appointment_entity/entityfields/deleteseries/stateProcess.js b/entity/Appointment_entity/entityfields/deleteseries/stateProcess.js index 8d6b8cb3ec..5b986b8804 100644 --- a/entity/Appointment_entity/entityfields/deleteseries/stateProcess.js +++ b/entity/Appointment_entity/entityfields/deleteseries/stateProcess.js @@ -1,5 +1,4 @@ import("system.tools"); -import("system.logging"); import("system.vars"); import("system.result"); import("system.calendars"); diff --git a/entity/Context_entity/recordcontainers/jdito/contentProcess.js b/entity/Context_entity/recordcontainers/jdito/contentProcess.js index 17ad5303c6..724a3ee8aa 100644 --- a/entity/Context_entity/recordcontainers/jdito/contentProcess.js +++ b/entity/Context_entity/recordcontainers/jdito/contentProcess.js @@ -1,4 +1,3 @@ -import("system.logging"); import("system.vars"); import("system.result"); import("Context_lib"); diff --git a/entity/Member_entity/entityfields/icon/valueProcess.js b/entity/Member_entity/entityfields/icon/valueProcess.js index a19d7b291a..71433b6fd1 100644 --- a/entity/Member_entity/entityfields/icon/valueProcess.js +++ b/entity/Member_entity/entityfields/icon/valueProcess.js @@ -1,4 +1,3 @@ -import("system.logging"); import("system.vars"); import("system.result"); import("system.neon"); diff --git a/entity/Offer_entity/entityfields/contact_id/valueProcess.js b/entity/Offer_entity/entityfields/contact_id/valueProcess.js index 1fca2af19c..b863ff7acb 100644 --- a/entity/Offer_entity/entityfields/contact_id/valueProcess.js +++ b/entity/Offer_entity/entityfields/contact_id/valueProcess.js @@ -1,4 +1,3 @@ -import("system.logging"); import("system.neon"); import("system.db"); import("system.result"); diff --git a/entity/Offer_entity/entityfields/object_type/valueProcess.js b/entity/Offer_entity/entityfields/object_type/valueProcess.js index 93f98305df..2ef4eb50b1 100644 --- a/entity/Offer_entity/entityfields/object_type/valueProcess.js +++ b/entity/Offer_entity/entityfields/object_type/valueProcess.js @@ -1,4 +1,3 @@ -import("system.logging"); import("system.neon"); import("system.vars"); import("system.result"); diff --git a/entity/PermissionDetail_entity/recordcontainers/jdito/contentProcess.js b/entity/PermissionDetail_entity/recordcontainers/jdito/contentProcess.js index 055d366a91..44edb699f0 100644 --- a/entity/PermissionDetail_entity/recordcontainers/jdito/contentProcess.js +++ b/entity/PermissionDetail_entity/recordcontainers/jdito/contentProcess.js @@ -1,147 +1,146 @@ -import("system.logging"); -import("system.util"); -import("system.vars"); -import("system.db"); -import("system.result"); -import("Permission_lib"); -import("system.project"); - -var selectedPermission = vars.get("$local.idvalues"); -var sqlStr; -var whereCond = " where"; -var alias = "_____SYSTEMALIAS"; -var entitiesMetaData = project.getDataModels(project.DATAMODEL_KIND_ENTITY); -var entityStructure; -var entitiesUsePermFlagSet = []; -var fieldsUsePermFlagSet = []; - -// gets all names of the entites which have the 'usePermission'-flag set (positive list) -// gets all names of the fields which have the 'usePermission'-flag set (positive list) -for each (let entityMetaData in entitiesMetaData) { - if (entityMetaData[6] == "true") { - entitiesUsePermFlagSet.push(entityMetaData[0]) - entityStructure = project.getEntityStructure(entityMetaData[0]); - for (fieldname in entityStructure.fields) { - field = entityStructure.fields[fieldname]; - if (field.usePermissions == true) { - fieldsUsePermFlagSet.push(field.name); - } - } - } -} - -whereCond += " ENTITY_ID in ('" + entitiesUsePermFlagSet.join("','") + "')"; -whereCond += " and (FIELD_ID in ('" + fieldsUsePermFlagSet.join("','") + "') or FIELD_ID is NULL)"; - -if (vars.exists("$param.RoleTitle_param") && vars.get("$param.RoleTitle_param")) { - whereCond += " and ASYS_PERMISSIONSET.ROLE_ID = '" + vars.getString("$param.RoleTitle_param") + "'"; -} else if (vars.exists("$param.EntityTitle_param") && vars.get("$param.EntityTitle_param")) { - whereCond += " and ASYS_PERMISSIONSET.ENTITY_ID = '" + vars.getString("$param.EntityTitle_param") + "'"; -} - -sqlStr = - "select ASYS_PERMISSION.ASYS_PERMISSIONID, ASYS_PERMISSIONSET.ENTITY_ID, ASYS_PERMISSIONSET.ROLE_ID," - + " ASYS_PERMISSIONSET.FIELD_ID, ASYS_PERMISSION.COND, ASYS_PERMISSIONACTION.ACTION, ASYS_PERMISSIONSET.ACCESSTYPE, ASYS_PERMISSION.CONDTYPE from ASYS_PERMISSIONSET" - + " join ASYS_PERMISSION on ASYS_PERMISSION.ASYS_PERMISSIONSET_ID = ASYS_PERMISSIONSET.ASYS_PERMISSIONSETID" - + " join ASYS_PERMISSIONACTION on ASYS_PERMISSIONACTION.ASYS_PERMISSION_ID = ASYS_PERMISSION.ASYS_PERMISSIONID" - + whereCond - + " order by ASYS_PERMISSION.ASYS_PERMISSIONID"; - -var sqlRes = db.table(sqlStr, alias); -var permissionTable = PermissionUtil.convertArrToObj(sqlRes); - -// group all permissions by permissionid and condition, concat actions -var groupedPermissionTable = [], concatAction; -for (let i = 0; i < permissionTable.length - 1; i++) { - for (let j = i + 1; j < permissionTable.length; j++) { - if (permissionTable[i].permissionid == permissionTable[j].permissionid && permissionTable[i].cond == permissionTable[j].cond) { - var currPermId = permissionTable[i].permissionid; - var indexCurrPermGrouped = PermissionUtil.indexOfPermId(groupedPermissionTable, currPermId); - if (indexCurrPermGrouped > -1) { - // permissionset got already grouped before - // concat current action with the actions which got already grouped - concatAction = groupedPermissionTable[indexCurrPermGrouped].action + "," + permissionTable[j].action; - groupedPermissionTable[indexCurrPermGrouped].action = concatAction; - break; - } else { - concatAction = permissionTable[i].action + "," + permissionTable[j].action; - groupedPermissionTable.push(permissionTable[i]); - groupedPermissionTable[groupedPermissionTable.length-1].action = concatAction; - break; - } - } - } -} - -var res = []; -var permissionTableOrigin = PermissionUtil.convertArrToObj(sqlRes); - -// no permission selected, return all permission entrys -if (selectedPermission == null) { - for each (let entry in groupedPermissionTable) { - res = prepareResultArray(entry, res); - } - - for each (let entry in permissionTableOrigin) { - if (PermissionUtil.indexOfPermId(PermissionUtil.convertArrToObj(res), entry.permissionid) == -1) { - res = prepareResultArray(entry, res); - } - } -} else { // permission selected, return only the selected permission entry - for each (let entry in groupedPermissionTable) { - if (selectedPermission == entry.permissionid) { - res = prepareResultArray(entry, res); - break; - } - } - - for each (let entry in permissionTableOrigin) { - if (selectedPermission == entry.permissionid) { - if (PermissionUtil.indexOfPermId(PermissionUtil.convertArrToObj(res), entry.permissionid) == -1) { - res = prepareResultArray(entry, res); - break; - } - } - } -} - -result.object(res.sort(sortFunction)); - -function prepareResultArray(pEntry, pRes) { - var rootPermission = ""; - if (pEntry.accesstype != "E") { - if (pEntry.accesstype == "F" && pEntry.cond != "") { - rootPermission = PermissionUtil.getRootFieldPermission(pEntry.permissionid); - if (rootPermission == "") { - rootPermission = PermissionUtil.getRootPermission(pEntry.permissionid); - } - } else - rootPermission = PermissionUtil.getRootPermission(pEntry.permissionid); - } - pRes.push([pEntry.permissionid, pEntry.entity, pEntry.role, pEntry.field, pEntry.cond, pEntry.action, pEntry.accesstype, pEntry.condtype, rootPermission]); - return pRes; -} - -// used to sort result array: Entity -> Records -> Fields -function sortFunction(a, b) { - if (a[6] == b[6] && a[6] != "F" && a[6] != "R") - return 0; - else if (a[6] == "E") - return -1; - else if (b[6] == "E") - return 1; - else if (a[6] == "R" && b[6] == "F") - return -1; - else if (a[6] == "F" && b[6] == "R") - return 1; - else if (a[6] == "R" && b[6] == "R" && a[4] == "") - return -1; - else if (a[6] == "R" && b[6] == "R" && b[4] == "") - return 1; - else if (a[6] == "F" && b[6] == "F" && a[4] == "") - return -1; - else if (a[6] == "F" && b[6] == "F" && b[4] == "") - return 1; - else - return 0; +import("system.util"); +import("system.vars"); +import("system.db"); +import("system.result"); +import("Permission_lib"); +import("system.project"); + +var selectedPermission = vars.get("$local.idvalues"); +var sqlStr; +var whereCond = " where"; +var alias = "_____SYSTEMALIAS"; +var entitiesMetaData = project.getDataModels(project.DATAMODEL_KIND_ENTITY); +var entityStructure; +var entitiesUsePermFlagSet = []; +var fieldsUsePermFlagSet = []; + +// gets all names of the entites which have the 'usePermission'-flag set (positive list) +// gets all names of the fields which have the 'usePermission'-flag set (positive list) +for each (let entityMetaData in entitiesMetaData) { + if (entityMetaData[6] == "true") { + entitiesUsePermFlagSet.push(entityMetaData[0]) + entityStructure = project.getEntityStructure(entityMetaData[0]); + for (fieldname in entityStructure.fields) { + field = entityStructure.fields[fieldname]; + if (field.usePermissions == true) { + fieldsUsePermFlagSet.push(field.name); + } + } + } +} + +whereCond += " ENTITY_ID in ('" + entitiesUsePermFlagSet.join("','") + "')"; +whereCond += " and (FIELD_ID in ('" + fieldsUsePermFlagSet.join("','") + "') or FIELD_ID is NULL)"; + +if (vars.exists("$param.RoleTitle_param") && vars.get("$param.RoleTitle_param")) { + whereCond += " and ASYS_PERMISSIONSET.ROLE_ID = '" + vars.getString("$param.RoleTitle_param") + "'"; +} else if (vars.exists("$param.EntityTitle_param") && vars.get("$param.EntityTitle_param")) { + whereCond += " and ASYS_PERMISSIONSET.ENTITY_ID = '" + vars.getString("$param.EntityTitle_param") + "'"; +} + +sqlStr = + "select ASYS_PERMISSION.ASYS_PERMISSIONID, ASYS_PERMISSIONSET.ENTITY_ID, ASYS_PERMISSIONSET.ROLE_ID," + + " ASYS_PERMISSIONSET.FIELD_ID, ASYS_PERMISSION.COND, ASYS_PERMISSIONACTION.ACTION, ASYS_PERMISSIONSET.ACCESSTYPE, ASYS_PERMISSION.CONDTYPE from ASYS_PERMISSIONSET" + + " join ASYS_PERMISSION on ASYS_PERMISSION.ASYS_PERMISSIONSET_ID = ASYS_PERMISSIONSET.ASYS_PERMISSIONSETID" + + " join ASYS_PERMISSIONACTION on ASYS_PERMISSIONACTION.ASYS_PERMISSION_ID = ASYS_PERMISSION.ASYS_PERMISSIONID" + + whereCond + + " order by ASYS_PERMISSION.ASYS_PERMISSIONID"; + +var sqlRes = db.table(sqlStr, alias); +var permissionTable = PermissionUtil.convertArrToObj(sqlRes); + +// group all permissions by permissionid and condition, concat actions +var groupedPermissionTable = [], concatAction; +for (let i = 0; i < permissionTable.length - 1; i++) { + for (let j = i + 1; j < permissionTable.length; j++) { + if (permissionTable[i].permissionid == permissionTable[j].permissionid && permissionTable[i].cond == permissionTable[j].cond) { + var currPermId = permissionTable[i].permissionid; + var indexCurrPermGrouped = PermissionUtil.indexOfPermId(groupedPermissionTable, currPermId); + if (indexCurrPermGrouped > -1) { + // permissionset got already grouped before + // concat current action with the actions which got already grouped + concatAction = groupedPermissionTable[indexCurrPermGrouped].action + "," + permissionTable[j].action; + groupedPermissionTable[indexCurrPermGrouped].action = concatAction; + break; + } else { + concatAction = permissionTable[i].action + "," + permissionTable[j].action; + groupedPermissionTable.push(permissionTable[i]); + groupedPermissionTable[groupedPermissionTable.length-1].action = concatAction; + break; + } + } + } +} + +var res = []; +var permissionTableOrigin = PermissionUtil.convertArrToObj(sqlRes); + +// no permission selected, return all permission entrys +if (selectedPermission == null) { + for each (let entry in groupedPermissionTable) { + res = prepareResultArray(entry, res); + } + + for each (let entry in permissionTableOrigin) { + if (PermissionUtil.indexOfPermId(PermissionUtil.convertArrToObj(res), entry.permissionid) == -1) { + res = prepareResultArray(entry, res); + } + } +} else { // permission selected, return only the selected permission entry + for each (let entry in groupedPermissionTable) { + if (selectedPermission == entry.permissionid) { + res = prepareResultArray(entry, res); + break; + } + } + + for each (let entry in permissionTableOrigin) { + if (selectedPermission == entry.permissionid) { + if (PermissionUtil.indexOfPermId(PermissionUtil.convertArrToObj(res), entry.permissionid) == -1) { + res = prepareResultArray(entry, res); + break; + } + } + } +} + +result.object(res.sort(sortFunction)); + +function prepareResultArray(pEntry, pRes) { + var rootPermission = ""; + if (pEntry.accesstype != "E") { + if (pEntry.accesstype == "F" && pEntry.cond != "") { + rootPermission = PermissionUtil.getRootFieldPermission(pEntry.permissionid); + if (rootPermission == "") { + rootPermission = PermissionUtil.getRootPermission(pEntry.permissionid); + } + } else + rootPermission = PermissionUtil.getRootPermission(pEntry.permissionid); + } + pRes.push([pEntry.permissionid, pEntry.entity, pEntry.role, pEntry.field, pEntry.cond, pEntry.action, pEntry.accesstype, pEntry.condtype, rootPermission]); + return pRes; +} + +// used to sort result array: Entity -> Records -> Fields +function sortFunction(a, b) { + if (a[6] == b[6] && a[6] != "F" && a[6] != "R") + return 0; + else if (a[6] == "E") + return -1; + else if (b[6] == "E") + return 1; + else if (a[6] == "R" && b[6] == "F") + return -1; + else if (a[6] == "F" && b[6] == "R") + return 1; + else if (a[6] == "R" && b[6] == "R" && a[4] == "") + return -1; + else if (a[6] == "R" && b[6] == "R" && b[4] == "") + return 1; + else if (a[6] == "F" && b[6] == "F" && a[4] == "") + return -1; + else if (a[6] == "F" && b[6] == "F" && b[4] == "") + return 1; + else + return 0; } \ No newline at end of file diff --git a/entity/Turnover_entity/recordcontainers/jdito/contentProcess.js b/entity/Turnover_entity/recordcontainers/jdito/contentProcess.js index 4bc466e09a..f8be0738cc 100644 --- a/entity/Turnover_entity/recordcontainers/jdito/contentProcess.js +++ b/entity/Turnover_entity/recordcontainers/jdito/contentProcess.js @@ -1,4 +1,3 @@ -import("system.logging"); import("Turnover_lib"); import("system.vars"); import("system.result"); diff --git a/process/ActivityTask_lib/process.js b/process/ActivityTask_lib/process.js index ed6f8af1ee..174dfc5ff2 100644 --- a/process/ActivityTask_lib/process.js +++ b/process/ActivityTask_lib/process.js @@ -1,4 +1,3 @@ -import("system.logging"); import("system.vars"); import("system.util"); import("system.datetime"); @@ -132,7 +131,6 @@ TaskUtils.getTypeAttributes = function(pType) TaskUtils.getAvailableStatus = function(pType) { - logging.log("hääää" + KeywordUtils.getAttributeRelation(pType, $KeywordRegistry.taskType(), "availableStatus", "")) return JSON.parse(KeywordUtils.getAttributeRelation(pType, $KeywordRegistry.taskType(), "availableStatus", "")); } diff --git a/process/Context_lib/process.js b/process/Context_lib/process.js index 711da7bd3e..8eb5ede48e 100644 --- a/process/Context_lib/process.js +++ b/process/Context_lib/process.js @@ -1,4 +1,3 @@ -import("system.logging"); import("system.db"); import("system.translate"); import("system.project"); diff --git a/process/DocumentTemplate_lib/process.js b/process/DocumentTemplate_lib/process.js index ba6e8e61be..ba8ec78cfb 100644 --- a/process/DocumentTemplate_lib/process.js +++ b/process/DocumentTemplate_lib/process.js @@ -1,369 +1,369 @@ -import("Communication_lib"); -import("system.neon"); -import("Employee_lib"); -import("KeywordRegistry_basic"); -import("Document_lib"); -import("KeywordData_lib"); -import("Sql_lib"); -import("Address_lib"); -import("system.process"); -import("system.vars"); -import("system.db"); -import("system.util"); -import("system.pack"); -import("system.fileIO"); -import("system.translate"); -import("system.datetime"); -import("system.text"); -import("system.mail"); -import("Keyword_lib"); - -/** - * Object for working with document templates, holds the content and type of the template. - * Provides functions to replace placeholders in the content. - */ -function DocumentTemplate (pTemplateContent, pType, pFilename) -{ - this.content = pTemplateContent; - this.type = pType; - this.filename = pFilename; -} - -/** - * The types a DocumentTemplate can have. Depending on the type, - * the correct method for replacing the placeholders can be chosen - */ -DocumentTemplate.types = { - TXT : "txt", - HTML : "html", - EML : "eml", - ODT : "odt", - DOCX : "docx" -}; - -/** - * Loads the content of a document template and creates a new DocumentTemplate object with that. - * - * @param {String} pTemplateId id of the template - * - * @return {DocumentTemplate} template object - */ -DocumentTemplate.loadTemplate = function (pTemplateId) -{ - var alias = "_____SYSTEMALIAS"; - var templateDocument = db.getBinaryMetadata("DOCUMENTTEMPLATE", "DOCUMENT", pTemplateId, false, alias, null); - if (!templateDocument[0]) - return new DocumentTemplate(); - var binaryId = templateDocument[0][db.BINARY_ID]; - var filename = templateDocument[0][db.BINARY_FILENAME]; - var type = DocumentUtil.getFileExtensionFromUpload(filename); //TODO: if unknown type, throw error? - if (binaryId) - return new DocumentTemplate(db.getBinaryContent(binaryId, alias), type, filename); - return new DocumentTemplate(); //TODO: throw error? -} - -DocumentTemplate._replaceText = function (pText, pReplacements) -{ - for (let placeholder in pReplacements) - pText = pText.replace(placeholder, pReplacements[placeholder], "ig"); - return pText; -} - -DocumentTemplate.prototype.toString = function () -{ - return this.content; -} - -/** - * Returns the template content with replaced placeholders by choosing the right - * replace function for the type. - * - * @param {Object} pReplacements map, the structure is {placeholder : value} - * - * @return {String} the replaced content - */ -DocumentTemplate.prototype.getReplacedContent = function (pReplacements) -{ - switch (this.type) - { - case DocumentTemplate.types.HTML: - for (let i in pReplacements) - pReplacements[i] = text.replaceAll(pReplacements[i], {"\n" : "<br>"}); - case DocumentTemplate.types.TXT: - let decodedContent = util.decodeBase64String(this.content) - return DocumentTemplate._replaceText(decodedContent, pReplacements); - case DocumentTemplate.types.EML: - return this._getReplacedEML(pReplacements); - case DocumentTemplate.types.ODT: - return this._getReplacedODT(pReplacements); - case DocumentTemplate.types.DOCX: - return this._getReplacedDOCX(pReplacements); - default: - return null; //TODO: throw error - } -} - -DocumentTemplate.prototype.getReplacedContentByContactId = function (pContactId) -{ - var config = PlaceholderUtils.getPlaceholders(); - var addressData = getAddressesData([pContactId], config, EmployeeUtils.getCurrentContactId()); //TODO: add sender selection - var replacements = {}; - for (let i = 0, l = addressData[0].length; i < l; i++) - { - replacements[addressData[0][i]] = addressData[1][i]; - } - return this.getReplacedContent(replacements); -} - -/** - * replaces placeholders for EML - * - * @param {Object} pReplacements mapping with replacements for every placeholder - * - * @return {String} the replaced content - */ -DocumentTemplate.prototype._getReplacedEML = function (pReplacements) -{ - var email = mail.parseRFC(util.decodeBase64String(this.content)); - var htmlText = email[mail.MAIL_HTMLTEXT]; - return DocumentTemplate._replaceText(htmlText, pReplacements); -} - -/* - * replaces a given Odt-File on the server and returns the replaced base64-file - * - * @param {String|String[]} pAddrDataCondition req a SQL-Condition or an Array of Relation-Ids for reducing the default-placeholders - * @param {String} pAddressID opt if you want to use the standard address you can pass undefined, otherwise you need to specify a Address-Id - * - * @return {String} base64-encoded replaced file - */ -DocumentTemplate.prototype._getReplacedODT = function (pReplacements) -{ - //save the file on the server so it can be unzipped via pack.getFromZip - var serverFilePath = vars.get("$sys.servertemp") + "/clientid_" + vars.get("$sys.clientid") - + "/" + util.getNewUUID() + "/" + this.filename.replace(/\\/g, "/"); - - fileIO.storeData(serverFilePath, this.content, util.DATA_BINARY, false); - if (!_replaceODTFile(pReplacements, serverFilePath)) - return null; - - var replacedFileData = fileIO.getData(serverFilePath, util.DATA_BINARY); - fileIO.remove(serverFilePath); - - return replacedFileData; - - /* - * ersetzt die Platzhalter in ODT-Datei - * - * @param {String} pCondition req Condition - * @param {String} pODTFileName req Filename des odt-Datei - * @param {String} pAddressID opt ID von der die Adressdaten geholt werden - * - * @return {Boolean} - */ - function _replaceODTFile (pReplacements, pODTFileName) - { - var senderRelId = EmployeeUtils.getCurrentContactId(); - if (senderRelId == null) - return false; - if (Object.keys(pReplacements).length) - { - // ersetzen Platzhalter in content.xml - - var textS = util.decodeBase64String(pack.getFromZip(pODTFileName, "content.xml")); - var bodybegin = textS.indexOf("<office:body>"); - var bodyend = textS.indexOf("</office:body>") + 14; - var body = textS.substring( bodybegin, bodyend ); - var lastbody = textS.substr( bodyend ); - textS = textS.substring( 0, bodybegin ); - for (let placeholder in pReplacements) - { - body = body.replace(placeholder, - pReplacements[placeholder].replace(/\n/ig, "<text:line-break/>").replace(/&/ig, "&"), "ig"); - } - textS += body; - textS += lastbody; - pack.addToZip(pODTFileName, "content.xml", util.encodeBase64String(textS)) - // ersetzen Platzhalter in styles.xml - var styles = util.decodeBase64String(pack.getFromZip(pODTFileName, "styles.xml")); - for (let placeholder in pReplacements) - { - styles = styles.replace(placeholder, - pReplacements[placeholder].replace(/\n/ig, "<text:line-break/>").replace(/&/ig, "&"), "ig"); - } - pack.addToZip(pODTFileName, "styles.xml", util.encodeBase64String(styles)); - return true; - } - return false; - } -} - -/* - * This function is used to replace placeholders via DocXTemplater - * - * @param {Object} pReplacements - Must contain an object, which holds the placeholders - * - * @return {String} returns the modified document in a BASE64 coded string - */ -DocumentTemplate.prototype._getReplacedDOCX = function (pReplacements) -{ - var replacements = {}; - for (let placeholder in pReplacements) - replacements[placeholder.slice(3, -3)] = pReplacements[placeholder]; - - //this is executed as a process because of better performance - var documentData = process.execute("getDocxDocument_serverProcess", { - templateb64: this.content, - placeholderConfig: JSON.stringify(replacements) //process.execute is only able to handle strings - }); - - return documentData; -} - -/** - * Provides functions for document templates - */ -function DocumentTemplateUtils () {} - -/** - * loads a document template and replaces the placeholders - * - * @param {String} pTemplateId id of the document template - * @param {String} pContactId the contact whose address data is used - */ -DocumentTemplateUtils.getSingleReplacedDocument = function (pTemplateId, pContactId) -{ - var template = DocumentTemplate.loadTemplate(pTemplateId); - return template.getReplacedTextByContactId(pContactId); -} - -/** - * represents a placeholder - * - * @param {String} pName name of the placeholder (without prefix and postfix) - * @param {String} pType type of the placeholder, see PlaceholderUtils.types - * @param {String|Function} pValueDef string or function (depends on the type) defining the value - * @param {String} [pTarget] what contact is used to get the data, see PlaceholderUtils.targets - */ -function Placeholder (pName, pType, pValueDef, pTarget) -{ - this.placeholderName = PlaceholderUtils.formatPlaceholder(pName); - this.type = pType; - this.target = pTarget || Placeholder.targets.RECIPIENT; - this.valueDefinition = pValueDef; -} - - -/** - * placeholder types, defines how the value is acquired - */ -Placeholder.types = { - ADDRESSFORMAT : "ADDRESSFORMAT", - SQLPART : "SQLPART", - SQLPARTFUNCTION : "SQLPARTFUNCTION" -}; -/** - * placeholder targets, defines whose data is used - */ -Placeholder.targets = { - /** - * use the data of the recipient (default) - */ - RECIPIENT : "RECIPIENT", - /** - * use the data of the sender - */ - SENDER : "SENDER", - /** - * use the data of the user - */ - EMPLOYEE : "EMPLOYEE" -}; - -function PlaceholderUtils () {} - -/** - * Returns the placeholder with the required prefix and postfix added. - * This function defines the format for placeholders. - */ -PlaceholderUtils.formatPlaceholder = function (pPlaceholder, pEscapeForRegex) -{ - return "{@" + pPlaceholder + "@}"; -} - -/** - * placeholder configuration - * - * @return {Array} array of placeholders - */ -PlaceholderUtils.getPlaceholders = function () -{ - //these functions should make adding placeholders easier and require less code: - - /** - * add an address format placeholder to placeholders - */ - function _addAddressFormat (pName, pFormat, pTarget) - { - placeholders.push(new Placeholder(pName, Placeholder.types.ADDRESSFORMAT, pFormat, pTarget)); - } - - /** - * Add a sub-sql placeholder to placeholders. For further information regarding the full query, you can take - * a look at the function 'fetchAddressData' in Address_lib. You can use fields from CONTACT, ADDRESS, ORGANISATION and PERSON. - */ - function _addSqlPart (pName, pSqlPart, pTarget, pAddBraces) - { - placeholders.push(new Placeholder(pName, Placeholder.types.SQLPART, pAddBraces ? "(" + pSqlPart + ")" : pSqlPart, pTarget)); - } - - /** - * Add a placeholder to placeholders with a function that returns a sub-sql. The function will be called - * with no parameters. You have to deliver an actual function, don't call it here. - */ - function _addSqlPartFunction (pName, pSqlPartFunction, pTarget) - { - placeholders.push(new Placeholder(pName, Placeholder.types.SQLPARTFUNCTION, pSqlPartFunction, pTarget)); - } - - - var placeholders = []; - - //placeholders should be added here: - - _addAddressFormat("address", "{street} {buildingno}"); - _addAddressFormat("zipCode", "{zip}"); - _addAddressFormat("city", "{city}"); - _addAddressFormat("district", "{district}"); - _addAddressFormat("region", "{region}"); - _addAddressFormat("country", "{country}"); - _addAddressFormat("letterSalutation", "{letter_salutation}"); - _addAddressFormat("fullAddress", ""); - _addAddressFormat("senderOrgname", "{organisation_name}", Placeholder.targets.SENDER); - _addAddressFormat("senderAddress", "{street} {buildingno}", Placeholder.targets.SENDER); - _addAddressFormat("senderZipCity", "{country} - {zip} {city}", Placeholder.targets.SENDER); - _addAddressFormat("senderFullAddress", "", Placeholder.targets.SENDER); - - _addSqlPart("orgname", "ORGANISATION.NAME"); - - _addSqlPartFunction("phone", CommUtil.getStandardSubSqlPhone); - _addSqlPartFunction("email", CommUtil.getStandardSubSqlMail); - _addSqlPartFunction("senderPhone", CommUtil.getStandardSubSqlPhone, Placeholder.targets.SENDER); - _addSqlPartFunction("senderEmail", CommUtil.getStandardSubSqlMail, Placeholder.targets.SENDER); - - - return placeholders; -} - -/** - * functions for working with letters - */ -function LetterUtils () {} - -LetterUtils.openNewLetter = function (pContactId) -{ - var params = { - "ContactId_param" : pContactId - }; - neon.openContext("Letter", "LetterEdit_view", null, neon.OPERATINGSTATE_NEW, params); +import("Communication_lib"); +import("system.neon"); +import("Employee_lib"); +import("KeywordRegistry_basic"); +import("Document_lib"); +import("KeywordData_lib"); +import("Sql_lib"); +import("Address_lib"); +import("system.process"); +import("system.vars"); +import("system.db"); +import("system.util"); +import("system.pack"); +import("system.fileIO"); +import("system.translate"); +import("system.datetime"); +import("system.text"); +import("system.mail"); +import("Keyword_lib"); + +/** + * Object for working with document templates, holds the content and type of the template. + * Provides functions to replace placeholders in the content. + */ +function DocumentTemplate (pTemplateContent, pType, pFilename) +{ + this.content = pTemplateContent; + this.type = pType; + this.filename = pFilename; +} + +/** + * The types a DocumentTemplate can have. Depending on the type, + * the correct method for replacing the placeholders can be chosen + */ +DocumentTemplate.types = { + TXT : "txt", + HTML : "html", + EML : "eml", + ODT : "odt", + DOCX : "docx" +}; + +/** + * Loads the content of a document template and creates a new DocumentTemplate object with that. + * + * @param {String} pTemplateId id of the template + * + * @return {DocumentTemplate} template object + */ +DocumentTemplate.loadTemplate = function (pTemplateId) +{ + var alias = "_____SYSTEMALIAS"; + var templateDocument = db.getBinaryMetadata("DOCUMENTTEMPLATE", "DOCUMENT", pTemplateId, false, alias, null); + if (!templateDocument[0]) + return new DocumentTemplate(); + var binaryId = templateDocument[0][db.BINARY_ID]; + var filename = templateDocument[0][db.BINARY_FILENAME]; + var type = DocumentUtil.getFileExtensionFromUpload(filename); //TODO: if unknown type, throw error? + if (binaryId) + return new DocumentTemplate(db.getBinaryContent(binaryId, alias), type, filename); + return new DocumentTemplate(); //TODO: throw error? +} + +DocumentTemplate._replaceText = function (pText, pReplacements) +{ + for (let placeholder in pReplacements) + pText = pText.replace(placeholder, pReplacements[placeholder], "ig"); + return pText; +} + +DocumentTemplate.prototype.toString = function () +{ + return this.content; +} + +/** + * Returns the template content with replaced placeholders by choosing the right + * replace function for the type. + * + * @param {Object} pReplacements map, the structure is {placeholder : value} + * + * @return {String} the replaced content + */ +DocumentTemplate.prototype.getReplacedContent = function (pReplacements) +{ + switch (this.type) + { + case DocumentTemplate.types.HTML: + for (let i in pReplacements) + pReplacements[i] = text.replaceAll(pReplacements[i], {"\n" : "<br>"}); + case DocumentTemplate.types.TXT: + let decodedContent = util.decodeBase64String(this.content) + return DocumentTemplate._replaceText(decodedContent, pReplacements); + case DocumentTemplate.types.EML: + return this._getReplacedEML(pReplacements); + case DocumentTemplate.types.ODT: + return this._getReplacedODT(pReplacements); + case DocumentTemplate.types.DOCX: + return this._getReplacedDOCX(pReplacements); + default: + return null; //TODO: throw error + } +} + +DocumentTemplate.prototype.getReplacedContentByContactId = function (pContactId) +{ + var config = PlaceholderUtils.getPlaceholders(); + var addressData = getAddressesData([pContactId], config, EmployeeUtils.getCurrentContactId()); //TODO: add sender selection + var replacements = {}; + for (let i = 0, l = addressData[0].length; i < l; i++) + { + replacements[addressData[0][i]] = addressData[1][i]; + } + return this.getReplacedContent(replacements); +} + +/** + * replaces placeholders for EML + * + * @param {Object} pReplacements mapping with replacements for every placeholder + * + * @return {String} the replaced content + */ +DocumentTemplate.prototype._getReplacedEML = function (pReplacements) +{ + var email = mail.parseRFC(util.decodeBase64String(this.content)); + var htmlText = email[mail.MAIL_HTMLTEXT]; + return DocumentTemplate._replaceText(htmlText, pReplacements); +} + +/* + * replaces a given Odt-File on the server and returns the replaced base64-file + * + * @param {String|String[]} pAddrDataCondition req a SQL-Condition or an Array of Relation-Ids for reducing the default-placeholders + * @param {String} pAddressID opt if you want to use the standard address you can pass undefined, otherwise you need to specify a Address-Id + * + * @return {String} base64-encoded replaced file + */ +DocumentTemplate.prototype._getReplacedODT = function (pReplacements) +{ + //save the file on the server so it can be unzipped via pack.getFromZip + var serverFilePath = vars.get("$sys.servertemp") + "/clientid_" + vars.get("$sys.clientid") + + "/" + util.getNewUUID() + "/" + this.filename.replace(/\\/g, "/"); + + fileIO.storeData(serverFilePath, this.content, util.DATA_BINARY, false); + if (!_replaceODTFile(pReplacements, serverFilePath)) + return null; + + var replacedFileData = fileIO.getData(serverFilePath, util.DATA_BINARY); + fileIO.remove(serverFilePath); + + return replacedFileData; + + /* + * ersetzt die Platzhalter in ODT-Datei + * + * @param {String} pCondition req Condition + * @param {String} pODTFileName req Filename des odt-Datei + * @param {String} pAddressID opt ID von der die Adressdaten geholt werden + * + * @return {Boolean} + */ + function _replaceODTFile (pReplacements, pODTFileName) + { + var senderRelId = EmployeeUtils.getCurrentContactId(); + if (senderRelId == null) + return false; + if (Object.keys(pReplacements).length) + { + // ersetzen Platzhalter in content.xml + + var textS = util.decodeBase64String(pack.getFromZip(pODTFileName, "content.xml")); + var bodybegin = textS.indexOf("<office:body>"); + var bodyend = textS.indexOf("</office:body>") + 14; + var body = textS.substring( bodybegin, bodyend ); + var lastbody = textS.substr( bodyend ); + textS = textS.substring( 0, bodybegin ); + for (let placeholder in pReplacements) + { + body = body.replace(placeholder, + pReplacements[placeholder].replace(/\n/ig, "<text:line-break/>").replace(/&/ig, "&"), "ig"); + } + textS += body; + textS += lastbody; + pack.addToZip(pODTFileName, "content.xml", util.encodeBase64String(textS)) + // ersetzen Platzhalter in styles.xml + var styles = util.decodeBase64String(pack.getFromZip(pODTFileName, "styles.xml")); + for (let placeholder in pReplacements) + { + styles = styles.replace(placeholder, + pReplacements[placeholder].replace(/\n/ig, "<text:line-break/>").replace(/&/ig, "&"), "ig"); + } + pack.addToZip(pODTFileName, "styles.xml", util.encodeBase64String(styles)); + return true; + } + return false; + } +} + +/* + * This function is used to replace placeholders via DocXTemplater + * + * @param {Object} pReplacements - Must contain an object, which holds the placeholders + * + * @return {String} returns the modified document in a BASE64 coded string + */ +DocumentTemplate.prototype._getReplacedDOCX = function (pReplacements) +{ + var replacements = {}; + for (let placeholder in pReplacements) + replacements[placeholder.slice(3, -3)] = pReplacements[placeholder]; + + //this is executed as a process because of better performance + var documentData = process.execute("getDocxDocument_serverProcess", { + templateb64: this.content, + placeholderConfig: JSON.stringify(replacements) //process.execute is only able to handle strings + }); + + return documentData; +} + +/** + * Provides functions for document templates + */ +function DocumentTemplateUtils () {} + +/** + * loads a document template and replaces the placeholders + * + * @param {String} pTemplateId id of the document template + * @param {String} pContactId the contact whose address data is used + */ +DocumentTemplateUtils.getSingleReplacedDocument = function (pTemplateId, pContactId) +{ + var template = DocumentTemplate.loadTemplate(pTemplateId); + return template.getReplacedTextByContactId(pContactId); +} + +/** + * represents a placeholder + * + * @param {String} pName name of the placeholder (without prefix and postfix) + * @param {String} pType type of the placeholder, see PlaceholderUtils.types + * @param {String|Function} pValueDef string or function (depends on the type) defining the value + * @param {String} [pTarget] what contact is used to get the data, see PlaceholderUtils.targets + */ +function Placeholder (pName, pType, pValueDef, pTarget) +{ + this.placeholderName = PlaceholderUtils.formatPlaceholder(pName); + this.type = pType; + this.target = pTarget || Placeholder.targets.RECIPIENT; + this.valueDefinition = pValueDef; +} + + +/** + * placeholder types, defines how the value is acquired + */ +Placeholder.types = { + ADDRESSFORMAT : "ADDRESSFORMAT", + SQLPART : "SQLPART", + SQLPARTFUNCTION : "SQLPARTFUNCTION" +}; +/** + * placeholder targets, defines whose data is used + */ +Placeholder.targets = { + /** + * use the data of the recipient (default) + */ + RECIPIENT : "RECIPIENT", + /** + * use the data of the sender + */ + SENDER : "SENDER", + /** + * use the data of the user + */ + EMPLOYEE : "EMPLOYEE" +}; + +function PlaceholderUtils () {} + +/** + * Returns the placeholder with the required prefix and postfix added. + * This function defines the format for placeholders. + */ +PlaceholderUtils.formatPlaceholder = function (pPlaceholder, pEscapeForRegex) +{ + return "{@" + pPlaceholder + "@}"; +} + +/** + * placeholder configuration + * + * @return {Array} array of placeholders + */ +PlaceholderUtils.getPlaceholders = function () +{ + //these functions should make adding placeholders easier and require less code: + + /** + * add an address format placeholder to placeholders + */ + function _addAddressFormat (pName, pFormat, pTarget) + { + placeholders.push(new Placeholder(pName, Placeholder.types.ADDRESSFORMAT, pFormat, pTarget)); + } + + /** + * Add a sub-sql placeholder to placeholders. For further information regarding the full query, you can take + * a look at the function 'fetchAddressData' in Address_lib. You can use fields from CONTACT, ADDRESS, ORGANISATION and PERSON. + */ + function _addSqlPart (pName, pSqlPart, pTarget, pAddBraces) + { + placeholders.push(new Placeholder(pName, Placeholder.types.SQLPART, pAddBraces ? "(" + pSqlPart + ")" : pSqlPart, pTarget)); + } + + /** + * Add a placeholder to placeholders with a function that returns a sub-sql. The function will be called + * with no parameters. You have to deliver an actual function, don't call it here. + */ + function _addSqlPartFunction (pName, pSqlPartFunction, pTarget) + { + placeholders.push(new Placeholder(pName, Placeholder.types.SQLPARTFUNCTION, pSqlPartFunction, pTarget)); + } + + + var placeholders = []; + + //placeholders should be added here: + + _addAddressFormat("address", "{street} {buildingno}"); + _addAddressFormat("zipCode", "{zip}"); + _addAddressFormat("city", "{city}"); + _addAddressFormat("district", "{district}"); + _addAddressFormat("region", "{region}"); + _addAddressFormat("country", "{country}"); + _addAddressFormat("letterSalutation", "{letter_salutation}"); + _addAddressFormat("fullAddress", ""); + _addAddressFormat("senderOrgname", "{organisation_name}", Placeholder.targets.SENDER); + _addAddressFormat("senderAddress", "{street} {buildingno}", Placeholder.targets.SENDER); + _addAddressFormat("senderZipCity", "{country} - {zip} {city}", Placeholder.targets.SENDER); + _addAddressFormat("senderFullAddress", "", Placeholder.targets.SENDER); + + _addSqlPart("orgname", "ORGANISATION.NAME"); + + _addSqlPartFunction("phone", CommUtil.getStandardSubSqlPhone); + _addSqlPartFunction("email", CommUtil.getStandardSubSqlMail); + _addSqlPartFunction("senderPhone", CommUtil.getStandardSubSqlPhone, Placeholder.targets.SENDER); + _addSqlPartFunction("senderEmail", CommUtil.getStandardSubSqlMail, Placeholder.targets.SENDER); + + + return placeholders; +} + +/** + * functions for working with letters + */ +function LetterUtils () {} + +LetterUtils.openNewLetter = function (pContactId) +{ + var params = { + "ContactId_param" : pContactId + }; + neon.openContext("Letter", "LetterEdit_view", null, neon.OPERATINGSTATE_NEW, params); } \ No newline at end of file diff --git a/process/Email_lib/process.js b/process/Email_lib/process.js index e0e8cdf0ef..dc52ef7627 100644 --- a/process/Email_lib/process.js +++ b/process/Email_lib/process.js @@ -1,187 +1,185 @@ -import("system.logging"); -import("system.translate"); -import("system.text"); -import("system.db"); -import("system.util"); -import("Communication_lib"); -import("DocumentTemplate_lib"); -import("system.neon"); -import("system.mail"); - -function EmailUtils () {} - -/** - * creates a new E-Mail-Object and ask for a download of a eml where all fields are prefilled - * The eml can be open with a mailclient and sent via the mailclient. Each mailclient has a different behaviour: - * In Outlook the mail is automatically opened in draft-mode - * In Thunderbird the mail is opened in view mode and you've to manually "edit as new" - * - * @param {String|Array} pToRecipients mailaddresses of the recipients, can either be a 1D-Array with several addresses or a string with one address - * @param {String} pSenderContactId contactId of the sender. the standard mailadress of the contact is used as sender-address - * @param {String} [pTemplateId] if a document-template shall be used, give the templateId here - * @param {String} [pRecipientContactId] contactId of the recipient, required to fill placeholders - */ -EmailUtils.openMailTemplate = function (pToRecipients, pSenderContactId, pTemplateId, pRecipientContactId) -{ - var email = new Email(pToRecipients); - email.setSender(pSenderContactId); - if (pTemplateId) - email.setTemplate(pTemplateId, pRecipientContactId); - - email.openMail(); -} - -/** - * opens a view where a new mail can be sent. In the view the use CAN select a DocumentTemplate if needed - * - * @param {String} pToContactId contactId with contacts to filter the communication-addresses - */ -EmailUtils.openNewMail = function (pToContactId) -{ - var params = { - "ContactId_param" : pToContactId - }; - neon.openContext("Email", "EmailEdit_view", null, neon.OPERATINGSTATE_NEW, params); -} - -/** - * object for handling emails - * - * @param {String|Array} [pToRecipients=[]] recipient email address or array of recipient email addresses - * @param {String} [pSender=null] email address of the sender - * @param {String} [pSubject=null] subject - * @param {String} [pBody=null] mail body - * @param {Array} [pCcRecipients=[]] array of recipient cc addresses - * @param {Array} [pBccRecipients=[]] array of recipient bcc addresses - * - * @class - */ -function Email (pToRecipients, pSender, pSubject, pBody, pCcRecipients, pBccRecipients) -{ - if (pToRecipients && typeof(pToRecipients) == "string") - pToRecipients = [pToRecipients]; - - this.sender = pSender; - this.subject = pSubject; - this.body = pBody; - this.toRecipients = pToRecipients || []; - this.ccRecipients = pCcRecipients || []; - this.bccRecipients = pBccRecipients || []; -} - -/** - * loads a document template into the mail body - * - * @param {String} pTemplateId the id of the template - * @param {String} pContactId the id of the template - * - * @throws {Error} if the type of the template is invalid - */ -Email.prototype.setTemplate = function (pTemplateId, pContactId) -{ - var template = DocumentTemplate.loadTemplate(pTemplateId); - - //TODO: also set other properties if the template is a eml - if (template) - { - if (template.type != DocumentTemplate.types.EML && template.type != DocumentTemplate.types.HTML && template.type != DocumentTemplate.types.TXT) - throw new Error("Invalid document type for an email template"); - - this.body = template.getReplacedContentByContactId(pContactId); - } -} - -/** - * sets the sender of the mail - * - * @param {String} pContactId the contactId of the sender - */ -Email.prototype.setSender = function (pContactId) -{ - this.sender = CommUtil.getStandardMail(pContactId); -} - -/** - * generates a 'mailto:' URL from the email object - */ -Email.prototype.getMailtoUrl = function () -{ - var url = []; - - if (this.toRecipients.length) - url.push("to=" + this.toRecipients.join()); - - if (this.ccRecipients.length) - url.push("cc=" + this.ccRecipients.join()); - - if (this.bccRecipients.length) - url.push("bcc=" + this.bccRecipients.join()); - - if (this.subject) - url.push("subject=" + this.subject); - - if (this.body) - url.push("body=" + text.html2text(this.body)); - - url = "mailto:?" + url.join("&"); - - return encodeURI(url); -} - -/** - * generates a eml-element from the email object - */ -Email.prototype.getRFCmail = function () -{ - logging.log(this.body) - var ENCODING = "UTF-8"; - var mailId = mail.newMail(); - - if (this.toRecipients.length) - mail.addRecipients(mailId, mail.RECIPIENT_TO, this.toRecipients); - - if (this.ccRecipients.length) - mail.addRecipients(mailId, mail.RECIPIENT_CC, this.ccRecipients); - - if (this.bccRecipients.length) - mail.addRecipients(mailId, mail.RECIPIENT_BCC, this.bccRecipients); - - if (this.subject) - mail.setSubject(mailId, this.subject, ENCODING); - - if (this.body) - mail.addText(mailId, this.body, "text/html", ENCODING, null); - else - mail.addText(mailId, "", "text/html", ENCODING, null); - - //"X-Unsent" is a very badly, non-standardised header to gently ask the mail client that the mail should open in a compose-mode - //this is mainly done for Microsoft Outlook for Windows. - //Thunderbird has a dinosaur-request (it's from the year 2002) to also support this: https://bugzilla.mozilla.org/show_bug.cgi?id=166541 - mail.addHeader(mailId, "X-Unsent", "1"); - - //accoding to this entry: https://stackoverflow.com/questions/11330628/os-x-mail-open-eml-files-in-compose-mode/33224913 - //something similar exists for OS X Mail - //X-Uniform-Type-Identifier: com.apple.mail-draft - //this could be added later if needed - - - var mailObj = mail.getCachedMail(mailId); - return mail.toRFC(mailObj); -} - -/** - * opens the email - */ -Email.prototype.openMail = function () -{ - neon.openUrl(this.getMailtoUrl(), false); -} - -/** - * ask for a download of the email - */ -Email.prototype.downloadEML = function() -{ - neon.download(util.encodeBase64String(this.getRFCmail(), null), (this.subject || translate.text("Email Template")) + ".eml"); -} +import("system.translate"); +import("system.text"); +import("system.db"); +import("system.util"); +import("Communication_lib"); +import("DocumentTemplate_lib"); +import("system.neon"); +import("system.mail"); + +function EmailUtils () {} + +/** + * creates a new E-Mail-Object and ask for a download of a eml where all fields are prefilled + * The eml can be open with a mailclient and sent via the mailclient. Each mailclient has a different behaviour: + * In Outlook the mail is automatically opened in draft-mode + * In Thunderbird the mail is opened in view mode and you've to manually "edit as new" + * + * @param {String|Array} pToRecipients mailaddresses of the recipients, can either be a 1D-Array with several addresses or a string with one address + * @param {String} pSenderContactId contactId of the sender. the standard mailadress of the contact is used as sender-address + * @param {String} [pTemplateId] if a document-template shall be used, give the templateId here + * @param {String} [pRecipientContactId] contactId of the recipient, required to fill placeholders + */ +EmailUtils.openMailTemplate = function (pToRecipients, pSenderContactId, pTemplateId, pRecipientContactId) +{ + var email = new Email(pToRecipients); + email.setSender(pSenderContactId); + if (pTemplateId) + email.setTemplate(pTemplateId, pRecipientContactId); + + email.openMail(); +} + +/** + * opens a view where a new mail can be sent. In the view the use CAN select a DocumentTemplate if needed + * + * @param {String} pToContactId contactId with contacts to filter the communication-addresses + */ +EmailUtils.openNewMail = function (pToContactId) +{ + var params = { + "ContactId_param" : pToContactId + }; + neon.openContext("Email", "EmailEdit_view", null, neon.OPERATINGSTATE_NEW, params); +} + +/** + * object for handling emails + * + * @param {String|Array} [pToRecipients=[]] recipient email address or array of recipient email addresses + * @param {String} [pSender=null] email address of the sender + * @param {String} [pSubject=null] subject + * @param {String} [pBody=null] mail body + * @param {Array} [pCcRecipients=[]] array of recipient cc addresses + * @param {Array} [pBccRecipients=[]] array of recipient bcc addresses + * + * @class + */ +function Email (pToRecipients, pSender, pSubject, pBody, pCcRecipients, pBccRecipients) +{ + if (pToRecipients && typeof(pToRecipients) == "string") + pToRecipients = [pToRecipients]; + + this.sender = pSender; + this.subject = pSubject; + this.body = pBody; + this.toRecipients = pToRecipients || []; + this.ccRecipients = pCcRecipients || []; + this.bccRecipients = pBccRecipients || []; +} + +/** + * loads a document template into the mail body + * + * @param {String} pTemplateId the id of the template + * @param {String} pContactId the id of the template + * + * @throws {Error} if the type of the template is invalid + */ +Email.prototype.setTemplate = function (pTemplateId, pContactId) +{ + var template = DocumentTemplate.loadTemplate(pTemplateId); + + //TODO: also set other properties if the template is a eml + if (template) + { + if (template.type != DocumentTemplate.types.EML && template.type != DocumentTemplate.types.HTML && template.type != DocumentTemplate.types.TXT) + throw new Error("Invalid document type for an email template"); + + this.body = template.getReplacedContentByContactId(pContactId); + } +} + +/** + * sets the sender of the mail + * + * @param {String} pContactId the contactId of the sender + */ +Email.prototype.setSender = function (pContactId) +{ + this.sender = CommUtil.getStandardMail(pContactId); +} + +/** + * generates a 'mailto:' URL from the email object + */ +Email.prototype.getMailtoUrl = function () +{ + var url = []; + + if (this.toRecipients.length) + url.push("to=" + this.toRecipients.join()); + + if (this.ccRecipients.length) + url.push("cc=" + this.ccRecipients.join()); + + if (this.bccRecipients.length) + url.push("bcc=" + this.bccRecipients.join()); + + if (this.subject) + url.push("subject=" + this.subject); + + if (this.body) + url.push("body=" + text.html2text(this.body)); + + url = "mailto:?" + url.join("&"); + + return encodeURI(url); +} + +/** + * generates a eml-element from the email object + */ +Email.prototype.getRFCmail = function () +{ + var ENCODING = "UTF-8"; + var mailId = mail.newMail(); + + if (this.toRecipients.length) + mail.addRecipients(mailId, mail.RECIPIENT_TO, this.toRecipients); + + if (this.ccRecipients.length) + mail.addRecipients(mailId, mail.RECIPIENT_CC, this.ccRecipients); + + if (this.bccRecipients.length) + mail.addRecipients(mailId, mail.RECIPIENT_BCC, this.bccRecipients); + + if (this.subject) + mail.setSubject(mailId, this.subject, ENCODING); + + if (this.body) + mail.addText(mailId, this.body, "text/html", ENCODING, null); + else + mail.addText(mailId, "", "text/html", ENCODING, null); + + //"X-Unsent" is a very badly, non-standardised header to gently ask the mail client that the mail should open in a compose-mode + //this is mainly done for Microsoft Outlook for Windows. + //Thunderbird has a dinosaur-request (it's from the year 2002) to also support this: https://bugzilla.mozilla.org/show_bug.cgi?id=166541 + mail.addHeader(mailId, "X-Unsent", "1"); + + //accoding to this entry: https://stackoverflow.com/questions/11330628/os-x-mail-open-eml-files-in-compose-mode/33224913 + //something similar exists for OS X Mail + //X-Uniform-Type-Identifier: com.apple.mail-draft + //this could be added later if needed + + + var mailObj = mail.getCachedMail(mailId); + return mail.toRFC(mailObj); +} + +/** + * opens the email + */ +Email.prototype.openMail = function () +{ + neon.openUrl(this.getMailtoUrl(), false); +} + +/** + * ask for a download of the email + */ +Email.prototype.downloadEML = function() +{ + neon.download(util.encodeBase64String(this.getRFCmail(), null), (this.subject || translate.text("Email Template")) + ".eml"); +} \ No newline at end of file diff --git a/process/KeywordData_lib/process.js b/process/KeywordData_lib/process.js index c2f3f563fe..f64dd8e497 100644 --- a/process/KeywordData_lib/process.js +++ b/process/KeywordData_lib/process.js @@ -1,4 +1,3 @@ -import("system.logging"); import("system.translate"); import("system.db"); import("DataCaching_lib"); @@ -93,7 +92,6 @@ KeywordData.getKeywordAttributeRelations = function (pKeywordContainer) } return res; }); - logging.log(data.toSource()); return data; } diff --git a/process/Keyword_lib/process.js b/process/Keyword_lib/process.js index a5ff004df2..a7d93bfb2f 100644 --- a/process/Keyword_lib/process.js +++ b/process/Keyword_lib/process.js @@ -1,4 +1,3 @@ -import("system.logging"); import("KeywordRegistry_basic"); import("KeywordData_lib"); import("system.vars"); @@ -71,7 +70,6 @@ KeywordUtils.getAttributeRelationsByKey = function(pKeyId, pContainerName) return ""; var data = KeywordData.getKeywordAttributeRelations(pContainerName); - logging.log("byKey " + data.toSource()) if (data[pKeyId] == undefined) return {}; else @@ -92,10 +90,6 @@ KeywordUtils.getAttributeRelationsByKey = function(pKeyId, pContainerName) KeywordUtils.getAttributeRelation = function(pKeyId, pContainerName, pAttrName, pDefault) { var attributes = KeywordUtils.getAttributeRelationsByKey(pKeyId, pContainerName); - logging.log("getRel " + attributes.toSource()); - logging.log("ggggg " + pAttrName); - logging.log("ggggg " + pKeyId); - logging.log("ggggg " + attributes[pAttrName]); if (attributes && attributes[pAttrName] != null) { return attributes[pAttrName]; diff --git a/process/Turnover_lib/process.js b/process/Turnover_lib/process.js index cda5a8b009..4310d902ba 100644 --- a/process/Turnover_lib/process.js +++ b/process/Turnover_lib/process.js @@ -1,4 +1,3 @@ -import("system.logging"); import("Sql_lib"); import("system.translate"); import("KeywordRegistry_basic"); @@ -87,13 +86,10 @@ TurnoverUtil.getForecastData = function (pMaxYear, pYearCount, pSalesprojectId) TurnoverUtil.getTurnoverAndForecastData = function (pMaxYear, pYearCount, pShowForecast, pShowTurnover, pSalesprojectId) { var data = []; - logging.log(pShowTurnover); - logging.log(pShowForecast); if (pShowTurnover) data = data.concat(TurnoverUtil.getTurnoverData(pMaxYear, pYearCount, pSalesprojectId)); if (pShowForecast) data = data.concat(TurnoverUtil.getForecastData(pMaxYear, pYearCount, pSalesprojectId)); - logging.log(data.toSource()); return data; } \ No newline at end of file -- GitLab