using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using System.IO; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Authorization; using Microsoft.Extensions.Logging; using AyaNova.Models; using AyaNova.Api.ControllerHelpers; using AyaNova.Biz; using AyaNova.Util; using PuppeteerSharp; namespace AyaNova.Api.Controllers { [ApiController] [ApiVersion("8.0")] [Route("api/v{version:apiVersion}/report")] [Produces("application/json")] [Authorize] public class ReportController : ControllerBase { private readonly AyContext ct; private readonly ILogger log; private readonly ApiServerState serverState; /// /// ctor /// /// /// /// public ReportController(AyContext dbcontext, ILogger logger, ApiServerState apiServerState) { ct = dbcontext; log = logger; serverState = apiServerState; } [HttpGet("render-test")] [AllowAnonymous] public async Task GetTestReport([FromRoute] string test) { if (!serverState.IsOpen) return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason)); string outputFile = FileUtil.NewRandomTempFilesFolderFileName; switch (test) { case "chrome-reddit-to-pdf": //first test, just render a web page to pdf and return it //return PhysicalFile(filePath, mimetype, dbObject.DisplayFileName); outputFile += ".pdf"; //http://www.puppeteersharp.com/api/index.html //https://github.com/hardkoded/puppeteer-sharp await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision); var browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = true }); var page = await browser.NewPageAsync(); await page.GoToAsync("https://github.com/hardkoded/puppeteer-sharp"); await page.PdfAsync(outputFile); return PhysicalFile(outputFile, "application/pdf"); } return NotFound(test); } //--------------------------------------------------------------------- [HttpGet("poc")] [AllowAnonymous] public async Task ProofOfConcept([FromRoute] string url) { if (!serverState.IsOpen) return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason)); var ReportJSFolderPath = Path.Combine(ServerBootConfig.AYANOVA_CONTENT_ROOT_PATH, "resource", "reportjs"); if (!Directory.Exists(ReportJSFolderPath)) throw new System.Exception($"E1012: \"reportjs\" folder not found where expected: \"{ReportJSFolderPath}\", installation damaged?"); var hbspath = Path.Combine(ReportJSFolderPath, "ayhandlebars.js"); if (!System.IO.File.Exists(hbspath)) throw new System.Exception($"E1012: \"ayhandlebars.js\" file not found where expected: \"{hbspath}\", installation damaged?"); await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision); //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 reportData = "{ person: { firstname: 'Tyler', lastname: 'Mott' }, 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' }"; using (var browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = true })) using (var page = await browser.NewPageAsync()) { //Add handlebars JS for compiling and presenting await page.AddScriptTagAsync(new AddTagOptions() { Path = hbspath }); //add marked for markdown processing await page.AddScriptTagAsync(new AddTagOptions() { Path = Path.Combine(ReportJSFolderPath, "marked.js") }); //test add helpers await page.AddScriptTagAsync(new AddTagOptions() { Path = Path.Combine(ReportJSFolderPath, "ay-hb-helpers.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(); return new FileContentResult(pdfBuffer, "application/pdf"); } } //----------------------------------------- //------------ /* NOTES/TODO during testing Need job to automatically erase any temp files older than 5 minutes (or whatever) */ }//eoc }//eons