diff --git a/server/AyaNova/Controllers/ReportController.cs b/server/AyaNova/Controllers/ReportController.cs index bdd8924d..5affd3af 100644 --- a/server/AyaNova/Controllers/ReportController.cs +++ b/server/AyaNova/Controllers/ReportController.cs @@ -183,7 +183,7 @@ namespace AyaNova.Api.Controllers //====================================================================================================== - + /// /// Get data from id list in format used by report designer @@ -223,7 +223,7 @@ namespace AyaNova.Api.Controllers // reportData = await biz.GetReportData(reportDataParam.ObjectType, rowIds); // } - var reportData=await biz.GetReportData(reportDataParam); + var reportData = await biz.GetReportData(reportDataParam); if (reportData == null) return BadRequest(new ApiErrorResponse(biz.Errors)); @@ -260,7 +260,7 @@ namespace AyaNova.Api.Controllers } - + // [HttpGet("render-test")] @@ -406,6 +406,114 @@ namespace AyaNova.Api.Controllers } + [HttpPost("post-poc")] + public async Task PostProofOfConcept([FromBody] NameItem nameItem) + { + //https://test.helloayanova.com/api/v8/report/poc + //http://localhost:7575/api/v8/report/poc + + if (!serverState.IsOpen) + return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason)); + + var httpConnectionFeature = HttpContext.Features.Get(); + var API_URL = $"http://127.0.0.1:{httpConnectionFeature.LocalPort}/api/v8/"; + //var localIpAddress = httpConnectionFeature?.LocalIpAddress; + + //todo: validate files are present somehow? + var ReportJSFolderPath = Path.Combine(ServerBootConfig.AYANOVA_CONTENT_ROOT_PATH, "resource", "rpt"); + if (!Directory.Exists(ReportJSFolderPath)) + throw new System.Exception($"E1012: \"reportjs\" folder not found where expected: \"{ReportJSFolderPath}\", installation damaged?"); + + + + //sample CSS + var reportCSS = @" + @page { + margin: 1cm; + } + + @page :first { + margin: 2cm; + } + + .ay-red { + color:red; + } + .ay-blue { + color:blue; + } + "; + + //sample template + //var reportTemplate = "'
{{#with person}}{{firstname}} {{aycaps lastname}}{{/with}}
'"; + var reportTemplate = "'test title " + + "

Test page top

A blue paragraph

{{#with person}}{{firstname}} {{aycaps lastname}}{{/with}}
" + + "

Some markdown

{{{aymarkdown mdtest}}}
'"; + + //data object + + + var aylogo = $"{{small:'{API_URL}logo/small',medium:'{API_URL}logo/medium',large:'{API_URL}logo/large'}}"; + var reportData = "{ person: { firstname: ' First', lastname: '[NAME]' },aylogo:[AYLOGO], mdtest:'| CODE | MEANING |\\n| ----- | ------------------------------ |\\n| E1000 | Could not connect to the database specified in the [connection string](ops-config-db.md). |\\n| E1050 | XXXXXXXX |\\n| E1012 | Missing resource folder. AyaNova was started from the wrong location or was not installed properly. |\\n' }"; + reportData = reportData.Replace("[AYLOGO]", aylogo); + reportData = reportData.Replace("[NAME]", nameItem.Name); + + log.LogInformation($"setting Chrome launchoptions for os:"); + var lo = new LaunchOptions { Headless = true }; + bool isWindows = System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows); + if (!isWindows) + { + log.LogInformation($"IS NOT WINDOWS: setting executable path for chrome"); + lo.ExecutablePath = "/usr/bin/chromium-browser";//this is the default path for docker based alpine dist, but maybe not others, need to make a config setting likely + lo.Args = new string[] { "--no-sandbox" }; + } + else + { + log.LogInformation($"IS WINDOWS: Calling browserFetcher download async now:"); + await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision); + } + log.LogInformation($"Calling browser.launchAsync now:"); + using (var browser = await Puppeteer.LaunchAsync(lo)) + using (var page = await browser.NewPageAsync()) + { + log.LogInformation($"In using for page ops adding scripts and report now:"); + + //Add handlebars JS for compiling and presenting + await page.AddScriptTagAsync(new AddTagOptions() { Path = Path.Combine(ReportJSFolderPath, "ay-hb.js") }); + + //add marked for markdown processing + await page.AddScriptTagAsync(new AddTagOptions() { Path = Path.Combine(ReportJSFolderPath, "ay-md.js") }); + + //test add helpers + await page.AddScriptTagAsync(new AddTagOptions() { Path = Path.Combine(ReportJSFolderPath, "ay-report.js") }); + + + + //execute to add to handlebars + await page.EvaluateExpressionAsync("ayRegisterHelpers();"); + + //compile and run handlebars template + var compileScript = $"Handlebars.compile({reportTemplate})({reportData});"; + var resultHTML = await page.EvaluateExpressionAsync(compileScript); + + //render report as HTML + await page.SetContentAsync(resultHTML); + + //add style (after page or it won't work) + await page.AddStyleTagAsync(new AddTagOptions { Content = reportCSS }); + + //useful for debugging purposes only + //var pagecontent = await page.GetContentAsync(); + + //render to pdf and return + var pdfBuffer = await page.PdfDataAsync(); + log.LogInformation($"returning results now:"); + return new FileContentResult(pdfBuffer, "application/pdf"); + + } + + } + //----------------------------------------- diff --git a/server/AyaNova/biz/ReportBiz.cs b/server/AyaNova/biz/ReportBiz.cs index 31415d8a..4f2fb8c9 100644 --- a/server/AyaNova/biz/ReportBiz.cs +++ b/server/AyaNova/biz/ReportBiz.cs @@ -377,17 +377,7 @@ namespace AyaNova.Biz } } - public class RenderedReport - { - public string MimeType { get; set; } - public byte[] RenderedOutput { get; set; } - public RenderedReport() - { - MimeType = "application/pdf"; - RenderedOutput = null; - } - } - + //////////////////////////////////////////////////////////////////////////////////////////////// //JOB / OPERATIONS diff --git a/server/AyaNova/models/dto/ReportingModels.cs b/server/AyaNova/models/dto/ReportingModels.cs index ee74b041..d4b88a70 100644 --- a/server/AyaNova/models/dto/ReportingModels.cs +++ b/server/AyaNova/models/dto/ReportingModels.cs @@ -1,20 +1,31 @@ using AyaNova.Biz; namespace AyaNova.Models { - public class ObjectReportDataParameter - { - public AyaType ObjectType { get; set; } - public long[] SelectedRowIds { get; set; } - public string DataListKey { get; set; } - public string ListView { get; set; }//optional, if null or empty will use default list view built into DataList + public class ObjectReportDataParameter + { + public AyaType ObjectType { get; set; } + public long[] SelectedRowIds { get; set; } + public string DataListKey { get; set; } + public string ListView { get; set; }//optional, if null or empty will use default list view built into DataList - } + } - public class RenderReportParameter + public class RenderReportParameter + { + public long ReportId { get; set; } + public long[] SelectedRowIds { get; set; } + public string DataListKey { get; set; } + public string ListView { get; set; }//optional, if null or empty will use default list view built into DataList + } + + public class RenderedReport + { + public string MimeType { get; set; } + public byte[] RenderedOutput { get; set; } + public RenderedReport() { - public long ReportId { get; set; } - public long[] SelectedRowIds { get; set; } - public string DataListKey { get; set; } - public string ListView { get; set; }//optional, if null or empty will use default list view built into DataList + MimeType = "application/pdf"; + RenderedOutput = null; } + } }