This commit is contained in:
2022-12-16 06:01:23 +00:00
parent 26c2ae5cc9
commit effd96143f
310 changed files with 48715 additions and 0 deletions

1495
server/resource/de.json Normal file

File diff suppressed because it is too large Load Diff

1495
server/resource/en.json Normal file

File diff suppressed because it is too large Load Diff

1495
server/resource/es.json Normal file

File diff suppressed because it is too large Load Diff

1495
server/resource/fr.json Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,445 @@
let PreParedReportDataObject = null;
//////////////////////////////////
// Pre render function
//
async function ayPreRender(ayData) {
if (typeof ayPrepareData === "function") {
PreParedReportDataObject = await ayPrepareData(ayData);
} else {
PreParedReportDataObject = ayData;
}
return true;
}
//##################################### HANDLEBARS HELPERS ###################################################
///////////////////////////////////////
// Set our stock handlebars helpers
//
function ayRegisterHelpers() {
Handlebars.registerHelper("ayCaps", function (ayValue) {
return ayValue.toUpperCase();
});
Handlebars.registerHelper("ayDateTime", function (ayValue) {
return utcDateToShortDateAndTimeLocalized(ayValue);
});
Handlebars.registerHelper("ayDate", function (ayValue) {
return utcDateToShortDateLocalized(ayValue);
});
Handlebars.registerHelper("ayTime", function (ayValue) {
return utcDateToShortTimeLocalized(ayValue);
});
Handlebars.registerHelper("ayDecimal", function (ayValue) {
return decimalLocalized(ayValue);
});
Handlebars.registerHelper("ayCurrency", function (ayValue) {
return currencyLocalized(ayValue);
});
Handlebars.registerHelper("ayWiki", function (ayValue) {
if (ayValue == null) {
return "";
}
//replace attachment urls with tokenized local urls
let src = ayValue.replace(/\[ATTACH:(.*)\]/g, function (match, p1) {
return attachmentDownloadUrl(p1);
});
return new Handlebars.SafeString(
DOMPurify.sanitize(marked.parse(src, { breaks: true }))
);
});
Handlebars.registerHelper("ayJSON", function (obj) {
return JSON.stringify(obj, null, 3);
});
Handlebars.registerHelper("ayLink", function (text, url) {
var url = Handlebars.escapeExpression(url),
text = Handlebars.escapeExpression(text);
return new Handlebars.SafeString(
"<a href='" + url + "'>" + text + "</a>"
);
});
Handlebars.registerHelper("ayLogo", function (size) {
if (AYMETA.ayServerMetaData) {
switch (size) {
case "small":
if (!AYMETA.ayServerMetaData.HasSmallLogo) {
return "";
}
break;
case "medium":
if (!AYMETA.ayServerMetaData.HasMediumLogo) {
return "";
}
break;
case "large":
if (!AYMETA.ayServerMetaData.HasLargeLogo) {
return "";
}
break;
}
}
var url = `${Handlebars.escapeExpression(
AYMETA.ayServerMetaData.ayApiUrl
)}logo/${size}`;
return new Handlebars.SafeString("<img src='" + url + "'/>");
});
Handlebars.registerHelper("ayT", function (translationKey) {
if (ayTranslationKeyCache[translationKey] == undefined) {
throw `ayT reporting helper error: the key "${translationKey}" is not present in the translation cache, did you forget to include it in your call to "await ayGetTranslations(['ExampleTranslationKey1','ExampleTranslationKey2','etc']);" in ayPrepareData()\nTranslationKeyCache contains: ${JSON.stringify(
ayTranslationKeyCache,
null,
3
)}?`;
// return translationKey;
}
return ayTranslationKeyCache[translationKey];
});
///////////////////////////////////////////
// BarCode helper using
// https://github.com/metafloor/bwip-js#browser-usage
//
Handlebars.registerHelper("ayBC", function (text, options) {
let canvas = document.getElementById("aybarcode");
if (canvas == null) {
canvas = document.createElement("canvas");
canvas.id = "aybarcode";
}
let opt = JSON.parse(options);
if (text == null) {
text = "";
} else {
text = text.toString();
}
opt.text = text;
opt.textxalign = opt.textxalign || "center";
bwipjs.toCanvas(canvas, opt);
var url = canvas.toDataURL("image/png");
return new Handlebars.SafeString("<img src='" + url + "'/>");
});
} //eof
///////////////////////////////////////////
// Concat helper using
// https://stackoverflow.com/a/52571635/8939
//
Handlebars.registerHelper("ayConcat", function () {
arguments = [...arguments].slice(0, -1);
return arguments.join("");
});
//##################################### LOCALIZATION & TRANSLATION ###################################################
///////////////////////////////////////////
// Turn a utc date into a displayable
// short date and time
//
function utcDateToShortDateAndTimeLocalized(ayValue) {
if (!ayValue) {
return "";
}
//parse the date which is identified as utc ("2020-02-06T18:18:49.148011Z")
let parsedDate = new Date(ayValue);
//is it a valid date?
if (!(parsedDate instanceof Date && !isNaN(parsedDate))) {
return "not valid";
}
return parsedDate.toLocaleString(
AYMETA.ayClientMetaData.LanguageName || "en-US",
{
timeZone:
AYMETA.ayClientMetaData.TimeZoneName || "America/Winnipeg",
dateStyle: "short",
timeStyle: "short",
hour12: AYMETA.ayClientMetaData.Hour12
}
);
}
///////////////////////////////////////////
// Turn a utc date into a displayable
// short date
function utcDateToShortDateLocalized(ayValue) {
if (!ayValue) {
return "";
}
//parse the date which is identified as utc ("2020-02-06T18:18:49.148011Z")
let parsedDate = new Date(ayValue);
//is it a valid date?
if (!(parsedDate instanceof Date && !isNaN(parsedDate))) {
return "not valid";
}
return parsedDate.toLocaleDateString(
AYMETA.ayClientMetaData.LanguageName || "en-US",
{
timeZone:
AYMETA.ayClientMetaData.TimeZoneName || "America/Winnipeg",
dateStyle: "short"
}
);
}
///////////////////////////////////////////
// Turn a utc date into a displayable
// short time
function utcDateToShortTimeLocalized(ayValue) {
if (!ayValue) {
return "";
}
//parse the date which is identified as utc ("2020-02-06T18:18:49.148011Z")
let parsedDate = new Date(ayValue);
//is it a valid date?
if (!(parsedDate instanceof Date && !isNaN(parsedDate))) {
return "not valid";
}
return parsedDate.toLocaleTimeString(
AYMETA.ayClientMetaData.LanguageName || "en-US",
{
timeZone:
AYMETA.ayClientMetaData.TimeZoneName || "America/Winnipeg",
timeStyle: "short",
hour12: AYMETA.ayClientMetaData.Hour12
}
);
}
///////////////////////////////////////////
// CURRENCY LOCALIZATION
//
function currencyLocalized(ayValue) {
if (!ayValue) {
return "";
}
return new Intl.NumberFormat(
AYMETA.ayClientMetaData.LanguageName || "en-US",
{
style: "currency",
currency: AYMETA.ayClientMetaData.CurrencyName || "USD"
}
).format(ayValue);
}
///////////////////////////////////////////
// DECIMAL LOCALIZATION
//
function decimalLocalized(ayValue) {
if (!ayValue) {
return "";
}
return new Intl.NumberFormat(
AYMETA.ayClientMetaData.LanguageName || "en-US"
).format(ayValue);
}
//////////////////////////////////
// cache to hold translations keys
//
var ayTranslationKeyCache = {};
///////////////////////////////////
// GET TRANSLATIONS FROM API SERVER
//
async function ayGetTranslations(keys) {
if (!keys || keys.length == 0) {
return;
}
try {
let transData = await ayPostToAPI("translation/subset", keys);
transData.data.forEach(function storeFetchedTranslationItemsInCache(
item
) {
ayTranslationKeyCache[item.key] = item.value;
});
} catch (error) {
throw error;
}
}
//##################################### API UTILITIES ###################################################
///////////////////////////////////
// GET DATA FROM API SERVER
//
async function ayGetFromAPI(route, token) {
token = token || AYMETA.ayClientMetaData.Authorization;
if (route && !route.startsWith("http")) {
route = AYMETA.ayServerMetaData.ayApiUrl + route;
}
try {
let r = await fetch(route, {
method: "get",
mode: "cors",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
Authorization: token
}
});
return await extractBodyEx(r);
} catch (error) {
throw error;
}
}
///////////////////////////////////
// POST DATA TO API SERVER
//
async function ayPostToAPI(route, data, token) {
token = token || AYMETA.ayClientMetaData.Authorization;
if (route && !route.startsWith("http")) {
route = AYMETA.ayServerMetaData.ayApiUrl + route;
}
//api expects custom fields to be a string not an object
if (data && data.CustomFields && data.CustomFields.constructor === Object) {
data.CustomFields = JSON.stringify(data.CustomFields);
}
try {
fetchOptions = {
method: "post",
mode: "cors",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
Authorization: token
},
body: JSON.stringify(data)
};
let r = await fetch(route, fetchOptions);
return await extractBodyEx(r);
} catch (error) {
throw error;
}
}
///////////////////////////////////
// PUT DATA TO API SERVER
//
async function ayPutToAPI(route, data, token) {
token = token || AYMETA.ayClientMetaData.Authorization;
if (route && !route.startsWith("http")) {
route = AYMETA.ayServerMetaData.ayApiUrl + route;
}
//api expects custom fields to be a string not an object
if (data && data.CustomFields && data.CustomFields.constructor === Object) {
data.CustomFields = JSON.stringify(data.CustomFields);
}
try {
fetchOptions = {
method: "put",
mode: "cors",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
Authorization: token
},
body: JSON.stringify(data)
};
let r = await fetch(route, fetchOptions);
return await extractBodyEx(r);
} catch (error) {
throw error;
}
}
/////////////////////////////
// attachment download URL
// (INTERNAL USE NOT DOCUMENTED FOR HELPER USE)
function attachmentDownloadUrl(fileId, ctype) {
let url =
"attachment/download/" +
fileId +
"?t=" +
AYMETA.ayClientMetaData.DownloadToken;
if (ctype && ctype.includes("image")) {
url += "&i=1";
}
return AYMETA.ayServerMetaData.ayApiUrl + url;
}
//##################################### CODE UTILITIES ###################################################
async function extractBodyEx(response) {
if (response.status == 204) {
//no content, nothing to process
return response;
}
if (response.status == 202) {
//Accepted, nothing to process
return response;
}
const contentType = response.headers.get("content-type");
if (!contentType) {
return response;
}
if (contentType.includes("json")) {
return await response.json();
}
if (contentType.includes("text/plain")) {
return await response.text();
}
if (contentType.includes("application/pdf")) {
return await response.blob();
}
return response;
}
/////////////////////////////////////////////////////////
// Group by function
// reshapes input array into a new array grouped with
// a key named "group" with that group's key value
// and a key named "items" to contain all items
// for that group and also a "count" of items added
//
//
function ayGroupByKey(reportDataArray, groupByKeyName) {
//array to hold grouped data
const ret = [];
//iterate through the raw reprot data
for (let i = 0; i < reportDataArray.length; i++) {
//search the ret array for a group with this name and if found return a reference to that group object
let groupObject = ret.find(
(z) => z.group == reportDataArray[i][groupByKeyName]
);
if (groupObject != undefined) {
//there is already a matching group in the return array so just push this raw report data record into it
groupObject.items.push(reportDataArray[i]);
//update the count for this group's items
groupObject.count++;
} else {
//No group yet, so start a new one in the ret array and push this raw report data record
ret.push({
group: reportDataArray[i][groupByKeyName],
items: [reportDataArray[i]],
count: 1
});
}
}
return ret;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
{"Name":"Contacts list","Active":true,"Notes":"HTML example of using multiple nested #if else statements for display of value","Roles":50538,"SockType":3,"IncludeWoItemDescendants":false,"Template":"<html>\n\n<body>\n <div>\n <div class=\"reporttitle\">\n <p>{{ayT 'UserList'}} &amp; {{ayT 'Contacts'}} List</p>\n </div>\n\n <table>\n \n <thead>\n <tr>\n <th colspan=\"5\" class=\"leftlean\">{{ayT 'Name'}} &amp; {{ayT 'UserType'}} </th>\n <th colspan=\"2\">{{ayT 'LastLogin'}}</th>\n <th colspan=\"2\">{{ayT 'UserPhone1'}}</th>\n <th colspan=\"2\">{{ayT 'UserEmailAddress'}}</th>\n </tr>\n <tr>\n <td colspan=\"11\">&nbsp;</td>\n </tr>\n </thead>\n\n <tbody>\n {{#each ayReportData}}\n <tr>\n <td colspan=\"2\">{{Name}}</td>\n <!-- below line is example of nested #if / else / #if / else statements - note the TWO /if's at the end to close the two #ifs -->\n {{#if CustomerViz}}<td colspan=\"3\">Customer: {{CustomerViz}}</td>{{else}} {{#if HeadOfficeViz}}<td colspan=\"3\">Headoffice: {{HeadOfficeViz}}</td>{{else}}<td colspan=\"3\">Employee: {{UserTypeViz}}</td>{{/if}}{{/if}}\n <td colspan=\"2\">{{ayDateTime LastLogin}}</td>\n <td colspan=\"2\">{{UserOptions.Phone1}}</td>\n <td colspan=\"2\">{{UserOptions.EmailAddress}}</td>\n </tr>\n {{/each}}\n </tbody>\n\n <tfoot>\n </tfoot>\n\n </table>\n\n </div>\n</body>\n\n</html>","Style":"body {\r\n font-family: 'Helvetica', 'Helvetica Neue', Arial, sans-serif; \r\n}\r\n\r\n.reporttitle { \r\n margin-bottom: 20pt; \r\n font-weight: bold; \r\n font-size: 13pt; \r\n color: #9e9e9e;\r\n} \r\n\r\ntable { \r\n border-collapse: collapse;\r\n white-space: pre-wrap;\r\n width: 100%;\r\n table-layout: fixed;\r\n }\r\n\r\nth {\r\n height: 20px;\r\n font-size: 10pt; \r\n color: #9e9e9e;\r\n}\r\n\r\ntbody td {\r\n padding: 10px;\r\n word-wrap: break-word;\r\n font-size: 8pt;\r\n}\r\n\r\n\r\ntbody tr:nth-child(even) {\r\n background-color: #f8f8f8; /* MUST checkmark Print background in PDF Options for this to show */\r\n}\r\n\r\n\r\n.rightlean {\r\n text-align: right;\r\n}\r\n.leftlean {\r\n text-align: left;\r\n}\r\n.centerlean {\r\n text-align: center;\r\n}\r\n\r\n\r\n.fontgreen {\r\n color: green;\r\n font-size: 16pt;\r\n}\r\n.fontblue {\r\n color: blue;\r\n}\r\n.fontred {\r\n color:red;\r\n}\r\n\r\n","JsPrerender":" \n //this function (if present) is called with the report data \n //before the report is rendered\n //modify data as required here and return it to change the data before the report renders\n //see the help documentation for details\n\nasync function ayPrepareData(ayData) { \n\n await ayGetTranslations([ \"UserList\", \"Contacts\", \"UserType\", \"Contact\", \"Name\", \"Customer\", \"HeadOffice\", \"User\", \"LastLogin\", \"UserPhone1\", \"UserEmailAddress\" ]);\n\n \n return ayData;\n}","JsHelpers":"","RenderType":0,"HeaderTemplate":"<span>&nbsp; </span>","FooterTemplate":"<span style=\"font-size:6pt; width: 96%;text-align:left; \">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; Printed date: PDFDate</span>\n<span style=\"font-size:6pt;width: 96%; text-align: right; \">Page <span class=\"pageNumber\"></span> of <span class=\"totalPages\"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>","DisplayHeaderFooter":true,"PaperFormat":0,"Landscape":true,"MarginOptionsBottom":"15mm","MarginOptionsLeft":"20mm","MarginOptionsRight":"20mm","MarginOptionsTop":"10mm","PageRanges":null,"PreferCSSPageSize":false,"PrintBackground":true,"Scale":1.00000}

View File

@@ -0,0 +1 @@
{"Name":"Customer Notes","Active":true,"Notes":"Uses custom Prepare ayGroupByKey to group by the customer","Roles":50538,"SockType":59,"IncludeWoItemDescendants":false,"Template":"<html>\n\n<body>\n <div>\n <table>\n {{#each ayReportData}}\n <thead>\n\n <tr>\n <th colspan=\"5\" class=\"leftlean\">{{ayT 'CustomerNoteList'}} for {{ayT 'Customer'}}:</th>\n <td colspan=\"10\">{{group}}</td>\n </tr>\n <tr>\n <th colspan=\"15\">&nbsp;</th>\n </tr>\n <tr>\n <th colspan=\"3\">Who entered:</th>\n <th colspan=\"3\">{{ayT 'CustomerNoteNoteDate'}}</th>\n <th colspan=\"3\">{{ayT 'Tags'}}</th>\n <th colspan=\"6\">{{ayT 'CustomerNoteList'}}</th>\n </tr>\n <tr>\n <th colspan=\"15\">&nbsp;</th>\n <tr>\n </thead>\n\n <tbody>\n\n {{#each items}}\n\n <tr>\n <td colspan=\"3\">{{UserViz}}</td>\n <td colspan=\"3\">{{ayDateTime NoteDate}}</td>\n <td colspan=\"3\">{{Tags}}</td>\n <td colspan=\"6\">{{Notes}}</td>\n </tr>\n {{/each}}\n\n </tbody>\n\n <tfoot>\n </tfoot>\n {{/each}}\n </table>\n\n <!-- <p> uncomment to see the raw data returned from the custom Prepare </p>\n <div>\n <p>{{ayJSON ayReportData}} </p>\n </div> -->\n\n\n </div>\n</body>\n\n</html>","Style":"body {\r\n font-family: 'Helvetica', 'Helvetica Neue', Arial, sans-serif; \r\n}\r\n\r\n.reporttitle { \r\n margin-bottom: 20pt; \r\n font-weight: bold; \r\n font-size: 13pt; \r\n color: #9e9e9e;\r\n} \r\n\r\ntable { \r\n border-collapse: collapse;\r\n white-space: pre-wrap;\r\n width: 100%;\r\n table-layout: fixed;\r\n }\r\n\r\nth {\r\n height: 20px;\r\n font-size: 10pt; \r\n color: #9e9e9e;\r\n\r\n}\r\n\r\ntbody td {\r\n padding: 10px;\r\n word-wrap: break-word;\r\n font-size: 8pt;\r\n}\r\n\r\n\r\ntbody tr:nth-child(even) {\r\n background-color: #f8f8f8; /* MUST checkmark Print background in PDF Options for this to show */\r\n}\r\n\r\n\r\n.rightlean {\r\n text-align: right;\r\n}\r\n.leftlean {\r\n text-align: left;\r\n}\r\n.centerlean {\r\n text-align: center;\r\n}\r\n\r\n\r\n.fontgreen {\r\n color: green;\r\n font-size: 16pt;\r\n}\r\n.fontblue {\r\n color: blue;\r\n}\r\n.fontred {\r\n color:red;\r\n}\r\n\r\n","JsPrerender":" \n //this function (if present) is called with the report data \n //before the report is rendered\n //modify data as required here and return it to change the data before the report renders\n //see the help documentation for details\n\nasync function ayPrepareData(ayData) { \n\n await ayGetTranslations([ \"CustomerNoteNotes\", \"CustomerNoteList\", \"Customer\", \"CustomerNoteNoteDate\", \"Tags\" ]);\n\n ayData.ayReportData = ayGroupByKey(ayData.ayReportData, 'CustomerViz')\n \n return ayData;\n}","JsHelpers":"","RenderType":0,"HeaderTemplate":"<span>&nbsp; </span>","FooterTemplate":"<span style=\"font-size:6pt; width: 96%;text-align:left; \">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; Printed date: PDFDate</span>\n<span style=\"font-size:6pt;width: 96%; text-align: right; \">Page <span class=\"pageNumber\"></span> of <span class=\"totalPages\"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>","DisplayHeaderFooter":true,"PaperFormat":0,"Landscape":false,"MarginOptionsBottom":"15mm","MarginOptionsLeft":"20mm","MarginOptionsRight":"20mm","MarginOptionsTop":"10mm","PageRanges":null,"PreferCSSPageSize":false,"PrintBackground":true,"Scale":1.00000}

View File

@@ -0,0 +1 @@
{"Name":"Head Offices list","Active":true,"Notes":"","Roles":50538,"SockType":15,"IncludeWoItemDescendants":false,"Template":"<html>\n\n<body>\n <div>\n <div class=\"reporttitle\">\n <p>{{ayT 'HeadOfficeList'}} List</p>\n </div>\n\n <table>\n \n <thead>\n <tr>\n <th colspan=\"3\" class=\"leftlean\">{{ayT 'Name'}}</th>\n <th colspan=\"2\" class=\"leftlean\">{{ayT 'HeadOfficeAccountNumber'}}</th>\n <th colspan=\"2\">{{ayT 'AddressTypePostal'}}</th>\n <th colspan=\"2\">{{ayT 'HeadOfficePhone1'}}</th>\n <th colspan=\"2\">{{ayT 'HeadOfficeEmail'}}</th>\n </tr>\n </thead>\n\n <tbody>\n {{#each ayReportData}}\n <tr>\n <td colspan=\"3\">{{Name}}</td>\n <td colspan=\"2\">{{AccountNumber}}</td>\n <td colspan=\"2\">{{PostAddress}}</td>\n <td colspan=\"2\">{{Phone1}}</td>\n <td colspan=\"2\">{{EmailAddress}}</td>\n </tr>\n {{/each}}\n </tbody>\n\n <tfoot>\n </tfoot>\n\n </table>\n\n\n </div>\n</body>\n\n</html>","Style":"body {\r\n font-family: 'Helvetica', 'Helvetica Neue', Arial, sans-serif; \r\n}\r\n\r\n.reporttitle { \r\n margin-bottom: 20pt; \r\n font-weight: bold; \r\n font-size: 13pt; \r\n color: #9e9e9e;\r\n} \r\n\r\ntable { \r\n border-collapse: collapse;\r\n white-space: pre-wrap;\r\n width: 100%;\r\n table-layout: fixed;\r\n }\r\n\r\nth {\r\n height: 20px;\r\n font-size: 10pt; \r\n color: #9e9e9e;\r\n}\r\n\r\ntbody td {\r\n padding: 10px;\r\n word-wrap: break-word;\r\n font-size: 8pt;\r\n}\r\n\r\n\r\ntbody tr:nth-child(even) {\r\n background-color: #f8f8f8; /* MUST checkmark Print background in PDF Options for this to show */\r\n}\r\n\r\n\r\n.rightlean {\r\n text-align: right;\r\n}\r\n.leftlean {\r\n text-align: left;\r\n}\r\n.centerlean {\r\n text-align: center;\r\n}\r\n\r\n\r\n.fontgreen {\r\n color: green;\r\n font-size: 16pt;\r\n}\r\n.fontblue {\r\n color: blue;\r\n}\r\n.fontred {\r\n color:red;\r\n}\r\n\r\n","JsPrerender":" \n //this function (if present) is called with the report data \n //before the report is rendered\n //modify data as required here and return it to change the data before the report renders\n //see the help documentation for details\n\nasync function ayPrepareData(ayData) { \n\n await ayGetTranslations([ \"Contact\", \"Name\", \"HeadOfficeList\", \"HeadOffice\", \"HeadOfficeAccountNumber\", \"AddressTypePostal\", \"HeadOfficePhone1\", \"HeadOfficeEmail\" ]);\n\n \n return ayData;\n}","JsHelpers":"","RenderType":0,"HeaderTemplate":"<span>&nbsp; </span>","FooterTemplate":"<span style=\"font-size:6pt; width: 96%;text-align:left; \">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; Printed date: PDFDate</span>\n<span style=\"font-size:6pt;width: 96%; text-align: right; \">Page <span class=\"pageNumber\"></span> of <span class=\"totalPages\"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>","DisplayHeaderFooter":true,"PaperFormat":0,"Landscape":true,"MarginOptionsBottom":"15mm","MarginOptionsLeft":"20mm","MarginOptionsRight":"20mm","MarginOptionsTop":"10mm","PageRanges":null,"PreferCSSPageSize":false,"PrintBackground":true,"Scale":1.00000}

View File

@@ -0,0 +1 @@
{"Name":"Memos","Active":true,"Notes":"","Roles":124927,"SockType":60,"IncludeWoItemDescendants":false,"Template":"<html>\n\n<body>\n <div>\n <div class=\"reporttitle\">\n <p>{{ayT 'MemoList'}} List</p>\n </div>\n\n <table>\n \n <thead>\n <tr>\n <th colspan=\"1\">{{ayT 'MemoViewed'}}</th>\n <th colspan=\"2\">{{ayT 'MemoSent'}}</th>\n <th colspan=\"2\">{{ayT 'MemoFromID'}}</th>\n <th colspan=\"3\">{{ayT 'MemoSubject'}}</th> \n <th colspan=\"5\">{{ayT 'MemoMessage'}}</th>\n \n </tr>\n </thead>\n\n <tbody>\n {{#each ayReportData}}\n <tr>\n <!-- if Viewed is true, will show checkmarked checkbox -->\n\t\t\t\t\t{{#if Viewed}}<td colspan=\"1\" class=\"centerlean\"><input type=\"checkbox\" id=\"manual1\" checked><label for=\"manual1\"> </label></td>\n\t\t\t\t\t{{else}}<td colspan=\"1\" class=\"centerlean\"><input type=\"checkbox\" id=\"manual1\" ><label for=\"manual1\"> </label></td>{{/if}}\n\n <td colspan=\"2\">{{ayDateTime Sent}}</td>\n <td colspan=\"2\">{{FromViz}}</td>\n <td colspan=\"3\">{{Name}}</td>\n <td colspan=\"5\">{{Notes}}</td>\n \n </tr>\n {{/each}}\n </tbody>\n\n <tfoot>\n </tfoot>\n\n </table>\n\n\n </div>\n</body>\n\n</html>","Style":"body {\r\n font-family: 'Helvetica', 'Helvetica Neue', Arial, sans-serif; \r\n}\r\n\r\n.reporttitle { \r\n margin-bottom: 20pt; \r\n font-weight: bold; \r\n font-size: 13pt; \r\n color: #9e9e9e;\r\n} \r\n\r\ntable { \r\n border-collapse: collapse;\r\n white-space: pre-wrap;\r\n width: 100%;\r\n table-layout: fixed;\r\n }\r\n\r\nth {\r\n height: 20px;\r\n font-size: 10pt; \r\n color: #9e9e9e;\r\n}\r\n\r\ntbody td {\r\n padding: 10px;\r\n word-wrap: break-word;\r\n font-size: 8pt;\r\n}\r\n\r\n\r\ntbody tr:nth-child(even) {\r\n background-color: #f8f8f8; /* MUST checkmark Print background in PDF Options for this to show */\r\n}\r\n\r\n\r\n.rightlean {\r\n text-align: right;\r\n}\r\n.leftlean {\r\n text-align: left;\r\n}\r\n.centerlean {\r\n text-align: center;\r\n}\r\n\r\n\r\n.fontgreen {\r\n color: green;\r\n font-size: 16pt;\r\n}\r\n.fontblue {\r\n color: blue;\r\n}\r\n.fontred {\r\n color:red;\r\n}\r\n\r\n","JsPrerender":" \n //this function (if present) is called with the report data \n //before the report is rendered\n //modify data as required here and return it to change the data before the report renders\n //see the help documentation for details\n\nasync function ayPrepareData(ayData) { \n\n await ayGetTranslations([ \"MemoFromID\", \"MemoSent\", \"MemoList\", \"MemoSubject\", \"MemoViewed\", \"MemoMessage\" ]);\n\n \n return ayData;\n}","JsHelpers":"","RenderType":0,"HeaderTemplate":"<span>&nbsp; </span>","FooterTemplate":"<span style=\"font-size:6pt; width: 96%;text-align:left; \">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; Printed date: PDFDate</span>\n<span style=\"font-size:6pt;width: 96%; text-align: right; \">Page <span class=\"pageNumber\"></span> of <span class=\"totalPages\"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>","DisplayHeaderFooter":true,"PaperFormat":0,"Landscape":true,"MarginOptionsBottom":"15mm","MarginOptionsLeft":"20mm","MarginOptionsRight":"20mm","MarginOptionsTop":"10mm","PageRanges":null,"PreferCSSPageSize":false,"PrintBackground":true,"Scale":1.00000}

View File

@@ -0,0 +1 @@
{"Name":"Projects list","Active":true,"Notes":"","Roles":50538,"SockType":25,"IncludeWoItemDescendants":false,"Template":"<html>\n\n<body>\n <div>\n <div class=\"reporttitle\">\n <p>{{ayT 'ProjectList'}} List</p>\n </div>\n\n <table>\n <thead>\n <tr>\n <!-- to repeat column headers on every page, include in the thead -->\n <th colspan=\"6\" class=\"leftlean\">{{ayT 'Project'}}</th>\n <th colspan=\"2\">{{ayT 'ProjectDateStarted'}}</th>\n <th colspan=\"2\">{{ayT 'ProjectDateCompleted'}}</th>\n <th colspan=\"2\">{{ayT 'ProjectAccountNumber'}}</th>\n <th colspan=\"3\">{{ayT 'ProjectProjectOverseerID'}}</th>\n <th colspan=\"6\">{{ayT 'ProjectNotes'}}</th>\n </tr>\n </thead>\n\n <tbody>\n {{#each ayReportData}}\n <tr>\n <td colspan=\"6\">{{Name}}</td>\n <td colspan=\"2\" class=\"centerlean\">{{ayDate DateStarted}}</td>\n <td colspan=\"2\" class=\"centerlean\">{{ayDate DateCompleted}}</td>\n <td colspan=\"2\">{{AccountNumber}}</td>\n <td colspan=\"3\">{{ProjectOverseerViz}}</td>\n <td colspan=\"6\">{{Notes}}</td>\n </tr>\n {{/each}}\n </tbody>\n\n <tfoot>\n </tfoot>\n\n </table>\n\n\n </div>\n</body>\n\n</html>","Style":"body {\r\n font-family: 'Helvetica', 'Helvetica Neue', Arial, sans-serif; \r\n}\r\n\r\n.reporttitle { \r\n margin-bottom: 20pt; \r\n font-weight: bold; \r\n font-size: 13pt; \r\n color: #9e9e9e;\r\n} \r\n\r\ntable { \r\n border-collapse: collapse;\r\n white-space: pre-wrap;\r\n width: 100%;\r\n table-layout: fixed;\r\n }\r\n\r\nth {\r\n border-bottom: solid 1pt #9e9e9e;\r\n height: 50px;\r\n font-size: 11pt; \r\n color: #9e9e9e;\r\n}\r\n\r\ntbody td {\r\n padding: 10px;\r\n word-wrap: break-word;\r\n font-size: 9pt;\r\n}\r\n\r\n\r\ntbody tr:nth-child(even) {\r\n background-color: #f8f8f8; /* MUST checkmark Print background in PDF Options for this to show */\r\n}\r\n\r\n\r\n.rightlean {\r\n text-align: right;\r\n}\r\n.leftlean {\r\n text-align: left;\r\n}\r\n.centerlean {\r\n text-align: center;\r\n}\r\n\r\n\r\n.fontgreen {\r\n color: green;\r\n font-size: 16pt;\r\n}\r\n.fontblue {\r\n color: blue;\r\n}\r\n.fontred {\r\n color:red;\r\n}\r\n\r\n","JsPrerender":" \n //this function (if present) is called with the report data \n //before the report is rendered\n //modify data as required here and return it to change the data before the report renders\n //see the help documentation for details\n\nasync function ayPrepareData(ayData) { \n\n await ayGetTranslations([ \"ProjectList\", \"Project\", \"ProjectProjectOverseerID\", \"ProjectDateStarted\", \"ProjectDateCompleted\", \"ProjectAccountNumber\", \"ProjectNotes\" ]);\n \n return ayData;\n}","JsHelpers":"","RenderType":0,"HeaderTemplate":"<span>&nbsp; </span>","FooterTemplate":"<span style=\"font-size:6pt; width: 96%;text-align:left; \">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; Printed date: PDFDate</span>\n<span style=\"font-size:6pt;width: 96%; text-align: right; \">Page <span class=\"pageNumber\"></span> of <span class=\"totalPages\"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>","DisplayHeaderFooter":true,"PaperFormat":10,"Landscape":true,"MarginOptionsBottom":"15mm","MarginOptionsLeft":"20mm","MarginOptionsRight":"20mm","MarginOptionsTop":"10mm","PageRanges":null,"PreferCSSPageSize":false,"PrintBackground":true,"Scale":1.00000}

View File

@@ -0,0 +1 @@
{"Name":"Reminders","Active":true,"Notes":"","Roles":124927,"SockType":52,"IncludeWoItemDescendants":false,"Template":"<html>\n\n<body>\n <div>\n <div class=\"reporttitle\">\n <p>{{ayT 'ReminderList'}} List</p>\n </div>\n\n <table>\n \n <thead>\n <tr>\n <th colspan=\"3\">{{ayT 'ReminderName'}}</th>\n <th colspan=\"2\">{{ayT 'ReminderStartDate'}}</th>\n <th colspan=\"2\">{{ayT 'ReminderStopDate'}}</th> \n <th colspan=\"2\">{{ayT 'Tags'}}</th>\n <th colspan=\"3\">{{ayT 'ReminderNotes'}}</th>\n </tr>\n </thead>\n\n <tbody>\n {{#each ayReportData}}\n <tr>\n <td colspan=\"3\">{{Name}}</td>\n <td colspan=\"2\">{{ayDateTime StartDate}}</td>\n <td colspan=\"2\">{{ayDateTime StopDate}}</td>\n <td colspan=\"2\">{{Tags}}</td>\n <td colspan=\"3\">{{Notes}}</td>\n </tr>\n {{/each}}\n </tbody>\n\n <tfoot>\n </tfoot>\n\n </table>\n\n\n </div>\n</body>\n\n</html>","Style":"body {\r\n font-family: 'Helvetica', 'Helvetica Neue', Arial, sans-serif; \r\n}\r\n\r\n.reporttitle { \r\n margin-bottom: 20pt; \r\n font-weight: bold; \r\n font-size: 13pt; \r\n color: #9e9e9e;\r\n} \r\n\r\ntable { \r\n border-collapse: collapse;\r\n white-space: pre-wrap;\r\n width: 100%;\r\n table-layout: fixed;\r\n }\r\n\r\nth {\r\n height: 20px;\r\n font-size: 10pt; \r\n color: #9e9e9e;\r\n}\r\n\r\ntbody td {\r\n padding: 10px;\r\n word-wrap: break-word;\r\n font-size: 8pt;\r\n}\r\n\r\n\r\ntbody tr:nth-child(even) {\r\n background-color: #f8f8f8; /* MUST checkmark Print background in PDF Options for this to show */\r\n}\r\n\r\n\r\n.rightlean {\r\n text-align: right;\r\n}\r\n.leftlean {\r\n text-align: left;\r\n}\r\n.centerlean {\r\n text-align: center;\r\n}\r\n\r\n\r\n.fontgreen {\r\n color: green;\r\n font-size: 16pt;\r\n}\r\n.fontblue {\r\n color: blue;\r\n}\r\n.fontred {\r\n color:red;\r\n}\r\n\r\n","JsPrerender":" \n //this function (if present) is called with the report data \n //before the report is rendered\n //modify data as required here and return it to change the data before the report renders\n //see the help documentation for details\n\nasync function ayPrepareData(ayData) { \n\n await ayGetTranslations([ \"Reminder\", \"ReminderName\", \"ReminderList\", \"Tags\", \"ReminderStartDate\", \"ReminderStopDate\", \"ReminderNotes\", \"ReminderColor\" ]);\n\n \n return ayData;\n}","JsHelpers":"","RenderType":0,"HeaderTemplate":"<span>&nbsp; </span>","FooterTemplate":"<span style=\"font-size:6pt; width: 96%;text-align:left; \">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; Printed date: PDFDate</span>\n<span style=\"font-size:6pt;width: 96%; text-align: right; \">Page <span class=\"pageNumber\"></span> of <span class=\"totalPages\"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>","DisplayHeaderFooter":true,"PaperFormat":0,"Landscape":true,"MarginOptionsBottom":"15mm","MarginOptionsLeft":"20mm","MarginOptionsRight":"20mm","MarginOptionsTop":"10mm","PageRanges":null,"PreferCSSPageSize":false,"PrintBackground":true,"Scale":1.00000}

View File

@@ -0,0 +1 @@
{"Name":"Reviews grouped by user","Active":true,"Notes":"Uses custom Prepare ayGroupByKey to group by the UserViz","Roles":124927,"SockType":61,"IncludeWoItemDescendants":false,"Template":"<html>\n\n<body>\n <div>\n <table>\n {{#each ayReportData}}\n <thead> \n </thead>\n\n <tbody>\n <tr>\n <th colspan=\"16\" class=\"leftlean reporttitle\">{{count}} {{ayT 'ReviewList'}} {{ayT 'ReviewUserId'}} {{group}} </th>\n </tr>\n <tr>\n <th colspan=\"16\">&nbsp;</th>\n </tr>\n\n {{#each items}}\n <tr>\n <th colspan=\"1\">&nbsp;</th>\n <th colspan=\"3\">{{ayT 'ReviewDate'}}:</th>\n <td colspan=\"4\">{{ReviewDate}}</td>\n <th colspan=\"3\">{{ayT 'ReviewAssignedByUserId'}}:</th>\n <td colspan=\"5\">{{AssignedByUserViz}}</td>\n </tr>\n <tr>\n <th colspan=\"1\">&nbsp;</th>\n <th colspan=\"3\">{{ayT 'ReviewName'}}:</th>\n <td colspan=\"12\">{{Name}}</td>\n </tr>\n <tr>\n <th colspan=\"1\">&nbsp;</th>\n <th colspan=\"3\">{{ayT 'ReviewNotes'}}:</th>\n <td colspan=\"12\">{{Notes}}</td>\n </tr>\n <tr>\n <th colspan=\"1\">&nbsp;</th>\n <th colspan=\"3\">{{ayT 'ReviewCompletedDate'}}:</th>\n <td colspan=\"12\">{{ayDateTime CompletedDate}}</td>\n </tr>\n <tr>\n <th colspan=\"1\">&nbsp;</th>\n <th colspan=\"3\">{{ayT 'ReviewCompletionNotes'}}:</th>\n <td colspan=\"12\">{{CompletionNotes}}</td>\n </tr>\n <tr>\n <th colspan=\"1\">&nbsp;</th>\n <th colspan=\"3\">{{ayT 'Tags'}}:</th>\n <td colspan=\"12\">{{Tags}}</td>\n </tr>\n <tr>\n <th colspan=\"1\">&nbsp;</th>\n <th colspan=\"3\">Wiki:</th>\n <td colspan=\"12\">{{ayWiki Wiki}}</td>\n </tr>\n <tr>\n <th colspan=\"16\">&nbsp;</th>\n </tr>\n <tr>\n <th colspan=\"16\">&nbsp;</th>\n </tr>\n {{/each}}\n\n </tbody>\n\n <tfoot>\n </tfoot>\n {{/each}}\n </table>\n\n <!-- <p> uncomment to see the raw data returned from the custom Prepare </p>\n <div>\n <p>{{ayJSON ayReportData}} </p>\n</div> -->\n\n\n </div>\n</body>\n\n</html>","Style":"body {\r\n font-family: 'Helvetica', 'Helvetica Neue', Arial, sans-serif; \r\n}\r\n\r\n.reporttitle { \r\n margin-bottom: 20pt; \r\n font-weight: bold; \r\n font-size: 13pt; \r\n color: #9e9e9e;\r\n} \r\n\r\ntable { \r\n border-collapse: collapse;\r\n white-space: pre-wrap;\r\n width: 100%;\r\n table-layout: fixed;\r\n }\r\n\r\nth {\r\n height: 20px;\r\n font-size: 10pt; \r\n color: #9e9e9e;\r\n text-align: right;\r\n\r\n}\r\n\r\ntbody td {\r\n padding: 10px;\r\n word-wrap: break-word;\r\n font-size: 8pt;\r\n}\r\n\r\n\r\ntbody tr:nth-child(even) {\r\n background-color: #f8f8f8; /* MUST checkmark Print background in PDF Options for this to show */\r\n}\r\n\r\n\r\n.rightlean {\r\n text-align: right;\r\n}\r\n.leftlean {\r\n text-align: left;\r\n}\r\n.centerlean {\r\n text-align: center;\r\n}\r\n\r\n\r\n.fontgreen {\r\n color: green;\r\n font-size: 16pt;\r\n}\r\n.fontblue {\r\n color: blue;\r\n}\r\n.fontred {\r\n color:red;\r\n}\r\n\r\n","JsPrerender":" \n //this function (if present) is called with the report data \n //before the report is rendered\n //modify data as required here and return it to change the data before the report renders\n //see the help documentation for details\n\nasync function ayPrepareData(ayData) { \n\n await ayGetTranslations([ \"ReviewList\", \"User\", \"ReviewUserId\", \"ReviewName\",\"ReviewDate\", \"ReviewNotes\", \"Tags\", \"ReviewAssignedByUserId\", \"ReviewCompletedDate\", \"ReviewCompletionNotes\" ]);\n\n ayData.ayReportData = ayGroupByKey(ayData.ayReportData, 'UserViz')\n \n return ayData;\n}","JsHelpers":"","RenderType":0,"HeaderTemplate":"<span>&nbsp; </span>","FooterTemplate":"<span style=\"font-size:6pt; width: 96%;text-align:left; \">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; Printed date: PDFDate</span>\n<span style=\"font-size:6pt;width: 96%; text-align: right; \">Page <span class=\"pageNumber\"></span> of <span class=\"totalPages\"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>","DisplayHeaderFooter":true,"PaperFormat":0,"Landscape":false,"MarginOptionsBottom":"15mm","MarginOptionsLeft":"20mm","MarginOptionsRight":"20mm","MarginOptionsTop":"10mm","PageRanges":null,"PreferCSSPageSize":false,"PrintBackground":true,"Scale":1.00000}

View File

@@ -0,0 +1 @@
{"Name":"Users Grouped By User Type","Active":true,"Notes":"","Roles":51050,"SockType":3,"IncludeWoItemDescendants":false,"Template":"<html>\n<body>\t\n\t<h2>{{ayT 'UserList'}} grouped by {{ayT 'UserType'}}</h2>\n\t<table>\n\t<thead>\n\t\t<tr>\n\t\t\t<th colspan=\"3\">&nbsp;</th>\n <th colspan=\"3\">{{ayT 'Name'}}</th>\n <th colspan=\"2\">{{ayT 'UserEmployeeNumber'}}</th>\n <th colspan=\"3\">{{ayT 'UserTypeService'}}</th>\n <th colspan=\"4\">{{ayT 'UserEmailAddress'}}</th>\n <th colspan=\"3\">{{ayT 'UserPhone1'}}</th>\n <th colspan=\"3\">{{ayT 'Vendor'}}</th>\n\t\t</tr>\n\t</thead>\n\n\t\n\t<tbody>\n {{#each ayReportData}}\n <tr>\n <td colspan=\"21\" class=\"leftlean\">{{count}} {{ayT 'UserList'}} assigned to {{ayT 'UserType'}} {{group}}</td> \n </tr>\n {{#each items}}\n <tr>\n <td colspan=\"3\">&nbsp;</td>\n <td colspan=\"3\">{{Name}}</td>\n <td colspan=\"2\">{{EmployeeNumber}}</td>\n {{#if IsTech}}<td colspan=\"3\"><input type=\"checkbox\" id=\"manual1\" checked><label for=\"manual1\"> </label></td>\n\t\t\t\t\t{{else}}<td colspan=\"3\"><input type=\"checkbox\" id=\"manual1\" ><label for=\"manual1\"> </label></td>{{/if}} \n <td colspan=\"4\">{{UserOptions.EmailAddress}}</td>\n <td colspan=\"3\">{{UserOptions.Phone1}}</td>\n <td colspan=\"3\">{{VendorViz}}</td>\n </tr>\t\n {{/each}}\n <tr>\n <td colspan=\"21\">&nbsp;</td>\n </tr>\n {{/each}}\n\t</tbody>\n\t\n <tfoot>\n </tfoot>\n\t</table>\n</body>\n</html>","Style":"h2 {\r\n color: #9e9e9e;\r\n}\r\n\r\ntfoot {\r\n border-top: 2px solid #9e9e9e;\r\n font-size: 7pt;\r\n text-align: center;\r\n}\r\n\r\n.singlePage\r\n{\r\npage-break-after: always;\r\n}\r\n\r\nbody {\r\n font-family: 'Helvetica', 'Helvetica Neue', Arial, sans-serif; \r\n}\r\n\r\n.reporttitle { \r\n margin-bottom: 20pt; \r\n font-weight: bold; \r\n font-size: 13pt; \r\n color: #9e9e9e;\r\n} \r\n\r\ntable { \r\n border-collapse: collapse;\r\n white-space: pre-wrap;\r\n width: 100%;\r\n table-layout: fixed; \r\n }\r\n\r\nth {\r\n height: 30px;\r\n font-size: 9pt; \r\n color: #9e9e9e;\r\n}\r\n\r\ntbody td {\r\n padding: 10px;\r\n word-wrap: break-word;\r\n font-size: 7pt;\r\n text-align: center;\r\n}\r\n\r\n\r\ntbody tr:nth-child(even) {\r\n background-color: #f8f8f8; /* MUST checkmark Print background in PDF Options for this to show */\r\n}\r\n\r\n\r\n.rightlean {\r\n text-align: right;\r\n}\r\n.leftlean {\r\n text-align: left;\r\n}\r\n.centerlean {\r\n text-align: center;\r\n}\r\n\r\n\r\n.fontgreen {\r\n color: green;\r\n}\r\n.fontblue {\r\n color: blue;\r\n}\r\n.fontred {\r\n color:red;\r\n}\r\n\r\n","JsPrerender":"async function ayPrepareData(ayData){ \n\n await ayGetTranslations([ \"UserList\", \"Name\", \"UserType\", \"UserEmployeeNumber\", \"UserPhone1\", \"UserEmailAddress\", \"UserTypeService\", \"Vendor\" ]);\n\n ayData.ayReportData = ayGroupByKey(ayData.ayReportData, 'UserTypeViz')\n\n\n return ayData;\n}","JsHelpers":"","RenderType":0,"HeaderTemplate":"<span>&nbsp; </span>","FooterTemplate":"<span style=\"font-size:6pt; width: 96%;text-align:left; \">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; Printed date: PDFDate</span>\n<span style=\"font-size:6pt;width: 96%; text-align: right; \">Page <span class=\"pageNumber\"></span> of <span class=\"totalPages\"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>","DisplayHeaderFooter":true,"PaperFormat":10,"Landscape":true,"MarginOptionsBottom":"15mm","MarginOptionsLeft":"15mm","MarginOptionsRight":"15mm","MarginOptionsTop":"15mm","PageRanges":null,"PreferCSSPageSize":false,"PrintBackground":true,"Scale":1.00000}