diff --git a/server/AyaNova/Controllers/ReportController.cs b/server/AyaNova/Controllers/ReportController.cs index e01c1509..aa9f99a6 100644 --- a/server/AyaNova/Controllers/ReportController.cs +++ b/server/AyaNova/Controllers/ReportController.cs @@ -236,9 +236,9 @@ namespace AyaNova.Api.Controllers //Don't send the full stack trace, just the initial error message from the javascript eval // "Evaluation failed: ReferenceError: reportdata is not defined\n at ayPrepareData (:5:17)\n at ayPreRender (C:\\data\\code\\raven\\server\\AyaNova\\resource\\rpt\\ay-report.js:13:12)\n at __puppeteer_evaluation_script__:10:25" var v = ex.Message; - int positionOfNewLine = v.IndexOf("\n at"); - if (positionOfNewLine >= 0) - v = v.Substring(0, positionOfNewLine); + // int positionOfNewLine = v.IndexOf("\n at"); + // if (positionOfNewLine >= 0) + // v = v.Substring(0, positionOfNewLine); return BadRequest(new ApiErrorResponse(ApiErrorCode.INVALID_OPERATION, null, v)); } diff --git a/server/AyaNova/biz/ReportBiz.cs b/server/AyaNova/biz/ReportBiz.cs index 925257d9..e37ef0de 100644 --- a/server/AyaNova/biz/ReportBiz.cs +++ b/server/AyaNova/biz/ReportBiz.cs @@ -381,7 +381,7 @@ namespace AyaNova.Biz //add Marked for markdown processing await page.AddScriptTagAsync(new AddTagOptions() { Path = Path.Combine(ReportJSFolderPath, "ay-md.js") }); - + //Wait, might not need luxon, it appears I only use that for relative date calculations //Luxon https://moment.github.io/luxon/ // await page.AddScriptTagAsync(new AddTagOptions() { Path = Path.Combine(ReportJSFolderPath, "ay-lux.js") }); @@ -403,14 +403,19 @@ namespace AyaNova.Biz await page.AddScriptTagAsync(new AddTagOptions() { Content = report.JsHelpers }); await page.AddStyleTagAsync(new AddTagOptions() { Content = report.Style }); + + log.LogDebug($"Preparing page: adding Client meta data"); + //Client meta data var clientMeta = "{}"; if (reportParam.ClientMeta != null) clientMeta = reportParam.ClientMeta.ToString(); + log.LogDebug($"Preparing page: adding Server meta data"); //Server meta data var serverMeta = $"{{ayApiUrl:`{apiUrl}`}}"; + log.LogDebug($"Preparing page: adding Report meta data"); //Report meta data var reportMeta = $"{{Id:{report.Id},Name:`{report.Name}`,Notes:`{report.Notes}`,ObjectType:`{report.ObjectType}`,DataListKey:`{reportParam.DataListKey}`,ListView:`{reportParam.ListView}`,SelectedRowIds: `{string.Join(",", reportParam.SelectedRowIds)}`}}"; @@ -427,29 +432,37 @@ namespace AyaNova.Biz #endif //prePareData / preRender var ReportDataObject = $"{{ ayReportData:{ReportData}, ayReportMetaData:{reportMeta}, ayClientMetaData:{clientMeta}, ayServerMetaData:{serverMeta} }}"; + log.LogDebug($"Calling ayPreRender..."); var PreParedReportDataObject = await page.EvaluateExpressionAsync($"ayPreRender({ReportDataObject});");//note ayPreRender is async but dont' use await to call it as the EvaluateExpressionAsync function knows how to handle that already //compile the template + log.LogDebug($"Calling Handlebars.compile..."); var compileScript = $"Handlebars.compile(`{report.Template}`)({PreParedReportDataObject});"; var compiledHTML = await page.EvaluateExpressionAsync(compileScript); - //render report as HTML + //render report as HTML + log.LogDebug($"Setting page content to compiled HTML"); await page.SetContentAsync(compiledHTML); //add style (after page or it won't work) if (!string.IsNullOrWhiteSpace(report.Style)) + { + log.LogDebug($"Adding report template Style CSS"); await page.AddStyleTagAsync(new AddTagOptions { Content = report.Style }); + } string outputFileName = StringUtil.ReplaceLastOccurrence(FileUtil.NewRandomFileName, ".", "") + ".pdf"; string outputFullPath = System.IO.Path.Combine(FileUtil.TemporaryFilesFolder, outputFileName); //render to pdf and return + log.LogDebug($"Calling render page contents to PDF"); await page.PdfAsync(outputFullPath); - log.LogDebug($"returning results now:"); + log.LogDebug($"Completed, returning results"); return outputFileName; } catch (System.Exception ex) { + //This is the error when a helper is used on the template but doesn't exist: //Evaluation failed: d //(it might also mean other things wrong with template) diff --git a/server/AyaNova/resource/rpt/stock-report-templates/EXAMPLE API use and meta data.ayrt b/server/AyaNova/resource/rpt/stock-report-templates/EXAMPLE API use and meta data.ayrt index 212e6263..39bf0ba5 100644 --- a/server/AyaNova/resource/rpt/stock-report-templates/EXAMPLE API use and meta data.ayrt +++ b/server/AyaNova/resource/rpt/stock-report-templates/EXAMPLE API use and meta data.ayrt @@ -1 +1 @@ -{"Name":"EXAMPLE API use and meta data","Active":true,"Notes":"","Roles":124927,"ObjectType":2,"Template":"\n\n\n\t

Example: Meta data and API usage

\n\t

See help documentation for details

\n\t\n\t
\n\t\t

ayServerMetaData

\n\t\t{{ ayJSON ayServerMetaData }}\n\t
\n\n\t
\n\t\t

ayClientMetaData

\n\t\t{{ ayJSON ayClientMetaData }}\n\t
\n\n\t
\n\t\t

ayReportMetaData

\n\t\t{{ ayJSON ayReportMetaData }}\n\t
\n\n\n\t
\n\t\t

myData

\n\t\t
(Fetched dynamically from API route enum-list/list/AyaType)
\n\t\t{{ ayJSON myData }}\n\t
\n\n\t
\n\t\t

ayReportData

\n\t\t{{#each ayReportData}}\n\t\t

{{ Name }}

\n\t\t
Notes: {{ Notes }}
\n\t\t{{/each}}\n\t
\n\n\n","Style":".example {\n color: blue;\n}","JsPrerender":"async function ayPrepareData(reportData) {\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\n //Example of using API GET method to fetch data from API server and make it available to the report template\n let route=`${reportData.ayServerMetaData.ayApiUrl}server-info`;\n\n //Put the data into the main report data object so it's available to the template\n reportData.myData={ServerInfo:await ayGetFromAPI(route, reportData.ayClientMetaData.Authorization)};\n\n //Example API POST method to fetch data from api server\n route=`${reportData.ayServerMetaData.ayApiUrl}search`;\n let searchPostData={phrase: \"Fish\"};\n reportData.myData.SearchResults=await ayPostToAPI(route, reportData.ayClientMetaData.Authorization,searchPostData);\n\n return reportData;\n}","JsHelpers":"//Register custom Handlebars helpers here to use in your report script\n//https://handlebarsjs.com/guide/#custom-helpers\nHandlebars.registerHelper('loud', function (aString) {\n return aString.toUpperCase()\n})","RenderType":0} \ No newline at end of file +{"Name":"EXAMPLE API use and meta data","Active":true,"Notes":"","Roles":124927,"ObjectType":2,"Template":"\n\n\n\t

Example: Meta data and API usage

\n\t

See help documentation for details

\n\t\n\t
\n\t\t

ayServerMetaData

\n\t\t{{ ayJSON ayServerMetaData }}\n\t
\n\n\t
\n\t\t

ayClientMetaData

\n\t\t{{ ayJSON ayClientMetaData }}\n\t
\n\n\t
\n\t\t

ayReportMetaData

\n\t\t{{ ayJSON ayReportMetaData }}\n\t
\n\n\n\t
\n\t\t

myData

\n\t\t
(Fetched dynamically from API route enum-list/list/AyaType)
\n\t\t{{ ayJSON myData }}\n\t
\n\n\t
\n\t\t

ayReportData

\n\t\t{{#each ayReportData}}\n\t\t

{{ Name }}

\n\t\t
Notes: {{ Notes }}
\n\t\t{{/each}}\n\t
\n\n\n","Style":".example {\n color: blue;\n}","JsPrerender":"async function ayPrepareData(reportData) {\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\n //Example of using API GET method to fetch data from API server and make it available to the report template\n let route=`${reportData.ayServerMetaData.ayApiUrl}server-info`;\n\n //Put the data into the main report data object so it's available to the template\n reportData.myData={ServerInfo:await ayGetFromAPI(route, reportData.ayClientMetaData.Authorization)};\n\n //Example API POST method to fetch data from api server\n route=`${reportData.ayServerMetaData.ayApiUrl}search`;\n let searchPostData={phrase: \"Fresh\"};\n reportData.myData.SearchResults=await ayPostToAPI(route, searchPostData);\n\n return reportData;\n}","JsHelpers":"//Register custom Handlebars helpers here to use in your report script\n//https://handlebarsjs.com/guide/#custom-helpers\nHandlebars.registerHelper('loud', function (aString) {\n return aString.toUpperCase()\n})","RenderType":0} \ No newline at end of file