// GraalJS Script (engine type: 2)
//////// START "main()" /////////////////////////////////////////////////////////////////
main();
function main(){
//// == Config Retrieving / 工程コンフィグの参照 ==
const strTsv = configs.get( "StrConfA1" ); /// REQUIRED
if( strTsv === "" ){
throw new Error( "\n AutomatedTask ConfigError:" +
" Config {A1: TSV} is empty \n" );
}
let strTextAlign = configs.get( "StrConfA2" ); // NotRequired
if( strTextAlign === "center" || strTextAlign === "right" ){
engine.log( " AutomatedTask Config: text-align: " + strTextAlign );
}else{
engine.log( " AutomatedTask ConfigWarning: text-align: " + strTextAlign + " is illegal" );
strTextAlign = "left";
engine.log( " AutomatedTask Config: text-align: " + strTextAlign + " (overwriten)" );
}
let strAbstract = configs.get( "StrConfB" ); // NotRequired
strAbstract = encodeHTML( strAbstract ).replace(/\n/g, '<br>\n');
if( strAbstract === "" ){
engine.log( " AutomatedTask ConfigWarning: " +
" {B: Abstract} is empty" );
}
let strApplicationRoot = configs.get( "StrConfC" ); // NotRequired
const strPocketHtml = configs.getObject( "SelectConfD" ); /// REQUIRED
//// == Data Retrieving / ワークフローデータの参照 ==
// (Nothing. Retrieved via Expression Language in Config Retrieving)
//// == Calculating / 演算 ==
/// Build HTML String
let strBlockHeader = `<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="Content-Style-Type" content="text/css">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>TSV Table</title>
</head>
<body bgcolor="#ffffff" style="background-color:#ffffff; margin:0 auto; padding:0; width:100%">
`;
// for Note
let strBlockAbstract = '<div style="margin:0 auto 30px 0px; padding:10px;';
strBlockAbstract += ' display:inline-block; border:medium solid #009900; background-color:#ffffff">\n';
strBlockAbstract += ' ' + strAbstract + '\n';
strBlockAbstract += '</div>\n';
// for TSV
let strBlockTsv = '<div style="margin:0; padding:5px; background-color:#eeeeee">\n'; // start
strBlockTsv += '<table cellpadding="2" cellspacing="2" bgcolor="#eeeeee">\n';
const arrRows = strTsv.split("\n");
for( let i = 0; i < arrRows.length; i++ ){
strBlockTsv += '<tr>\n';
let arrCells = arrRows[i].split("\t");
for( let j = 0; j < arrCells.length; j++ ){
let strCell = arrCells[j];
strCell = encodeHTML( strCell );
strCell = convertMultiSpaces( strCell );
strBlockTsv += ' <td bgcolor="#ffffff" align="' + strTextAlign + '"';
strBlockTsv += ' style="background-color:#ffffff; padding:2px; text-align:' + strTextAlign + '">';
strBlockTsv += strCell + '</td>\n';
}
strBlockTsv += '</tr>\n';
}
strBlockTsv += '</table></div>\n'; // end
// for FooterLink
const strProcessInstanceId = processInstance.getProcessInstanceId() + "";
const strProcessInstanceTitle = processInstance.getProcessInstanceTitle() + "";
let strBlockFooter = `<div style="margin:30px auto 0px 20px">
<span style="color:#009900">p${strProcessInstanceId}</span><br>
<span style="padding-left:20px; font-weight:bold">${strProcessInstanceTitle}</span>
</div>
<div style="margin:10px auto 10px 20px">
<a href="${strApplicationRoot}PE/Workitem/list?processInstanceId=${strProcessInstanceId}"
style="display:inline-block; font-weight:bold; border-radius:8px; padding:8px 16px;
color:#ffffff; background:#009900; border:solid 4px #009900">Desktop View</a>
<a href="${strApplicationRoot}SP/PE/ProcessInstance/view?processInstanceId=${strProcessInstanceId}"
style="display:inline-block; font-weight:bold; border-radius:8px; padding:8px 16px;
color:#ffffff; background:#009900; border:solid 4px #009900">Mobile View</a>
</div>
`;
/// Assembles
let strHtml = strBlockHeader;
if( strAbstract !== "" ){
strHtml += strBlockAbstract;
}
strHtml += strBlockTsv;
if( strApplicationRoot !== "" ){
strHtml += strBlockFooter;
}
strHtml += "</body></html>";
//// == Data Updating / ワークフローデータへの代入 ==
engine.setData( strPocketHtml, strHtml );
} //////// END "main()" /////////////////////////////////////////////////////////////////
function encodeHTML( str ){
return str.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
// convert multiple consecutive spaces to " .."
function convertMultiSpaces( strArg ){
let re = /\ {2,}/g;
let strReturn = strArg.replace( re, function( strMatch ){
let strNbspSpRepeat = "";
for( let i = 0; i < strMatch.length; i++ ){
if( (i % 2) === 0 ){ // Even number
strNbspSpRepeat += " ";
}else{ // Odd number
strNbspSpRepeat += " ";
}
}
return strNbspSpRepeat;
});
return strReturn;
}
/*
Notes:
- Used when displaying / notifying TSV-converted aggregated values or Spreadsheet data by email.
- e.g. Total sales by store, Number of web access, Working hours of the previous week
- When a token reaches the automated step, the code for HTML mail is automatically generated.
- The generated code can be set in "Message Sending Intermediate Event (Email)" (v13.1) as it is.
- https://support.questetra.com/bpmn-icons/throwing-message-intermediate-event-email/
- Some data will be converted automatically.
- Special characters are escaped as appropriate. For example, `<` is automatically converted to `<`.
- Continuous spaces (two or more) are replaced with ` ` every other character.
APPENDIX:
- The generated HTML code is not guaranteed to be displayed properly in all mailers.
- If the number of cells in each row is not constant, the number of Table Data (TD) will not match.
- The row is displayed out of alignment. No error will occur.
Notes-ja:
- TSV化された集計値やSpreadsheetデータを、Emailインターフェースで表示/通知する際に利用します。
- 例: 店舗別売上高、Webアクセス数、前週の就労時間
- 案件が自動処理工程に到達した際、HTMLメール用のコードが自動的に生成されます。
- 生成されたコードは、そのまま『メッセージ送信中間イベント(メール)』(v13.1)にセットできます。
- https://support.questetra.com/ja/bpmn-icons/throwing-message-intermediate-event-email/
- 一部のデータは自動的に変換されます。
- 特殊文字は、適宜エスケープ処理されます。たとえば `<` は `<` に自動的に変換されます。
- 連続スペース(2文字以上)は、一文字おきに ` ` に置換されます。
APPENDIX-ja:
- 生成されるHTMLコードは、全てのメーラで正常に表示されることが保証されている訳ではありません。
- 各行のセル数が一定でない場合、当該行はズレて表示されます。
- Table Data (TD) の数が一致しませんが、エラーにはなりません。
*/