diff --git a/Yavsc/ApiControllers/PdfEstimateController.cs b/Yavsc/ApiControllers/PdfEstimateController.cs index 08428c38..3ace640d 100644 --- a/Yavsc/ApiControllers/PdfEstimateController.cs +++ b/Yavsc/ApiControllers/PdfEstimateController.cs @@ -1,19 +1,66 @@ -using System; using System.IO; -using System.Security.Claims; using Microsoft.AspNet.Authorization; using Microsoft.AspNet.Mvc; +using System.Threading.Tasks; +using System.Web.Routing; +using Microsoft.AspNet.Mvc.ViewComponents; +using Microsoft.AspNet.Razor; namespace Yavsc.ApiControllers { + using Models; + [Route("api/pdfestimate"), Authorize] public class PdfEstimateController : Controller { - [HttpGet("{id}", Name = "Get")] + ApplicationDbContext dbContext; + DefaultViewComponentHelper helper; + IViewComponentDescriptorCollectionProvider provider; + IViewComponentInvokerFactory factory; + RazorEngineHost host; + RazorTemplateEngine engine; + IViewComponentSelector selector; + + + public PdfEstimateController( + IViewComponentDescriptorCollectionProvider provider, + IViewComponentSelector selector, + IViewComponentInvokerFactory factory, + ApplicationDbContext context) + { + + this.selector = selector; + this.provider = provider; + this.factory = factory; + helper = new DefaultViewComponentHelper(provider, selector, factory); + dbContext = context; + + var language = new CSharpRazorCodeLanguage(); + host = new RazorEngineHost(language) + { + DefaultBaseClass = "RazorPage", + DefaultClassName = "Estimate", + DefaultNamespace = "Yavsc", + }; + + // Everyone needs the System namespace, right? + host.NamespaceImports.Add("System"); + engine = new RazorTemplateEngine(host); + + + /* + GeneratorResults razorResult = + engine.GenerateCode( + + ) */ + } + + + [HttpGet("get/{id}", Name = "Get"), Authorize] public IActionResult Get(long id) { var filename = $"estimate-{id}.pdf"; - + var cd = new System.Net.Mime.ContentDisposition { // for example foo.bak @@ -23,15 +70,43 @@ namespace Yavsc.ApiControllers // the browser to try to show the file inline Inline = false, }; - - FileInfo fi = new FileInfo(Path.Combine(Startup.UserBillsDirName,filename)); - - FileStreamResult result = null; - var s = fi.OpenRead(); - - result = File(s,"application/x-pdf",filename); - - return result; + + FileInfo fi = new FileInfo(Path.Combine(Startup.UserBillsDirName, filename)); + if (!fi.Exists) return Ok(new { Error = "Not generated" }); + return File(fi.OpenRead(), "application/x-pdf", filename); ; + } + + [HttpGet("GetComponents", Name = "GetComponents")] + public IActionResult GetComponents() + { + return Ok(provider); + } + + [HttpGet("estimate-{id}.tex", Name = "GetTex"), Authorize] + public IActionResult GetTex(long id) + { + Response.ContentType = "text/x-tex"; + + return ViewComponent("Estimate",new object[] { id, false }); + } + + [HttpGet("gen/{id}")] + public async Task GeneratePdf(long id) + { + /* + + using (TextWriter wr = new StringWriter()) { + ViewComponentContext ctx = new ViewComponentContext( + selector.SelectComponent("Estimate"), new object[]{id}, + new ViewContext(), + wr + ); + + } + + */ + + return ViewComponent("Estimate",new object[] { id, true } ); } } } \ No newline at end of file diff --git a/Yavsc/Controllers/FrontOfficeController.cs b/Yavsc/Controllers/FrontOfficeController.cs index 8eed5407..e3a0959f 100644 --- a/Yavsc/Controllers/FrontOfficeController.cs +++ b/Yavsc/Controllers/FrontOfficeController.cs @@ -8,16 +8,6 @@ using Microsoft.Extensions.Logging; using Yavsc.Models.Booking; using Yavsc.Helpers; using System; -using System.IO; -using System.Diagnostics; -using System.Text; -using Microsoft.AspNet.Mvc.ViewFeatures; -using Microsoft.AspNet.Razor; -using Microsoft.AspNet.Mvc.ViewEngines; -using Microsoft.AspNet.Mvc.Rendering; -using Microsoft.Extensions.OptionsModel; -using System.Threading.Tasks; -using System.Security.Claims; namespace Yavsc.Controllers { @@ -111,23 +101,11 @@ namespace Yavsc.Controllers return View("Estimate.tex", estimate); } - class TeOtions : IOptions - { - public MvcViewOptions Value - { - get - { - return new MvcViewOptions(); - } - } - } - [Authorize,Route("Estimate-{id}.pdf")] - public async Task EstimatePdf(long id) + public IActionResult EstimatePdf(long id) { ViewBag.TempDir = Startup.SiteSetup.TempDir; ViewBag.BillsDir = Startup.UserBillsDirName; - var estimate = _context.Estimates.Include(x => x.Query) .Include(x => x.Query.Client) .Include(x => x.Query.PerformerProfile) @@ -136,102 +114,7 @@ namespace Yavsc.Controllers .Include(e => e.Bill).FirstOrDefault(x => x.Id == id); if (estimate==null) throw new Exception("No data"); - return View("Estimate.pdf",estimate); - /* - await result.ExecuteResultAsync(ActionContext); - var cd = new System.Net.Mime.ContentDisposition - { - // for example foo.bak - FileName = $"estimate-{id}.pdf", - - // always prompt the user for downloading, set to true if you want - // the browser to try to show the file inline - Inline = false, - }; - Response.Headers.Add("Content-Disposition", cd.ToString()); - return File((Byte[])ViewData["Pdf"], "application/x-pdf"); */ } - /* - - [Produces("application/x-pdf"), Authorize, Route("testimate-{id}.pdf")] - public async Task BadEstimatePdf(long id) - { - - var tempDir = Startup.SiteSetup.TempDir; - - string name = $"tmpestimtex-{id}"; - string fullname = new FileInfo( - System.IO.Path.Combine(tempDir, name)).FullName; - var writer = new System.IO.StringWriter(); - try - { - using (StringWriter sw = new StringWriter()) - { - Microsoft.AspNet.Mvc.ViewEngines.CompositeViewEngine ve = new CompositeViewEngine( - new TeOtions {} - ); - - ViewEngineResult viewResult = ve.FindPartialView(ActionContext, $"estimate-{id}.tex"); - ViewContext viewContext = new ViewContext(); // ActionContext, viewResult.View, ViewData, TempData, sw); - await viewResult.View.RenderAsync(viewContext); - } - } catch (Exception ex) - { - - } - - - - - FileInfo fo = new FileInfo(fullname + ".pdf"); - if (!fi.Exists) - { - throw new Exception("Source write failed"); - } - using (Process p = new Process()) - { - p.StartInfo.WorkingDirectory = tempDir; - p.StartInfo = new ProcessStartInfo(); - p.StartInfo.UseShellExecute = false; - p.StartInfo.FileName = "/usr/bin/texi2pdf"; - p.StartInfo.Arguments = $"--batch --build-dir=."; - - p.Start(); - - using (p.StandardInput) - { - - } - p.WaitForExit(); - if (p.ExitCode != 0) - { - throw new Exception("Pdf generation failed with exit code:" + p.ExitCode); - } - } - byte[] pdf = null; - if (fo.Exists) - { - using (StreamReader sr = new StreamReader(fo.FullName)) - { - pdf = System.IO.File.ReadAllBytes(fo.FullName); - } - fo.Delete(); - } - fi.Delete(); - - - var cd = new System.Net.Mime.ContentDisposition - { - // for example foo.bak - FileName = $"estimate-{id}.pdf", - - // always prompt the user for downloading, set to true if you want - // the browser to try to show the file inline - Inline = false, - }; - Response.Headers.Add("Content-Disposition", cd.ToString()); - return File(pdf, "application/x-pdf"); - } */ } -} \ No newline at end of file +} diff --git a/Yavsc/Helpers/TagHelpers.cs b/Yavsc/Helpers/TagHelpers.cs index fca20b37..974cbaa7 100644 --- a/Yavsc/Helpers/TagHelpers.cs +++ b/Yavsc/Helpers/TagHelpers.cs @@ -68,7 +68,6 @@ namespace Yavsc.Helpers /// /// Transforms a string of Markdown into HTML. /// - /// HtmlHelper - Not used, but required to make this an extension method. /// The Markdown that should be transformed. /// The url Base Location. /// The HTML representation of the supplied Markdown. diff --git a/Yavsc/Helpers/TeXHelpers.cs b/Yavsc/Helpers/TeXHelpers.cs index 2157520a..0c1d82e9 100644 --- a/Yavsc/Helpers/TeXHelpers.cs +++ b/Yavsc/Helpers/TeXHelpers.cs @@ -1,4 +1,12 @@ +using System; +using System.IO; using System.Linq; +using Microsoft.AspNet.Http; +using Microsoft.AspNet.Mvc; +using Microsoft.AspNet.Mvc.ModelBinding; +using Microsoft.AspNet.Mvc.Rendering; +using Microsoft.AspNet.Mvc.ViewEngines; +using Microsoft.AspNet.Mvc.ViewFeatures; namespace Yavsc.Helpers { @@ -11,5 +19,32 @@ namespace Yavsc.Helpers return string.Join(separator, items); } + public static string RenderViewToString( + this Controller controller, IViewEngine engine, + IHttpContextAccessor httpContextAccessor, + string viewName, object model) +{ + using (var sw = new StringWriter()) + { + if (engine == null) + throw new InvalidOperationException("no engine"); + + // try to find the specified view + controller.TryValidateModel(model); + ViewEngineResult viewResult = engine.FindPartialView(controller.ActionContext, viewName); + // create the associated context + ViewContext viewContext = new ViewContext(); + viewContext.ActionDescriptor = controller.ActionContext.ActionDescriptor; + viewContext.HttpContext = controller.ActionContext.HttpContext; + viewContext.TempData = controller.TempData; + viewContext.View = viewResult.View; + viewContext.Writer = sw; + + // write the render view with the given context to the stringwriter + viewResult.View.RenderAsync(viewContext); + viewResult.EnsureSuccessful(); + return sw.GetStringBuilder().ToString(); + } +} } } \ No newline at end of file diff --git a/Yavsc/ViewComponents/EstimateViewComponent.cs b/Yavsc/ViewComponents/EstimateViewComponent.cs new file mode 100644 index 00000000..720bc2f1 --- /dev/null +++ b/Yavsc/ViewComponents/EstimateViewComponent.cs @@ -0,0 +1,58 @@ +using System; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNet.Mvc; +using Microsoft.Data.Entity; +using Yavsc.Models; +using Yavsc.Models.Billing; +using Yavsc.ViewModels.Gen; + +namespace Yavsc.ViewComponents +{ + public class EstimateViewComponent : ViewComponent + { + ApplicationDbContext dbContext; + public EstimateViewComponent(ApplicationDbContext dbContext) + { + this.dbContext = dbContext; + } + public async Task InvokeAsync(long id, bool toPdf = false) + { + Estimate estimate = + dbContext.Estimates.Include(x => x.Query) + .Include(x => x.Query.Client) + .Include(x => x.Query.PerformerProfile) + .Include(x => x.Query.PerformerProfile.OrganizationAddress) + .Include(x => x.Query.PerformerProfile.Performer) + .Include(e => e.Bill).FirstOrDefault(x => x.Id == id); + if (estimate == null) + throw new Exception("No data"); + if (toPdf) + { + string tex = null; + var oldWriter = ViewComponentContext.ViewContext.Writer; + + using (var writer = new StringWriter()) + { + this.ViewComponentContext.ViewContext.Writer = writer; + + var resultTex = View("Estimate_tex", estimate); + resultTex.Execute(this.ViewComponentContext); + tex = writer.ToString(); + + } + ViewComponentContext.ViewContext.Writer = oldWriter; + + return this.View("Estimate_pdf", + new PdfGenerationViewModel{ + TeXSource = tex, + DestDir = Startup.UserBillsDirName, + BaseFileName = $"estimate-{id}" + } ); + } + return this.View("Estimate_tex", estimate); + } + + } +} \ No newline at end of file diff --git a/Yavsc/ViewModels/Gen/PdfGenerationViewModel.cs b/Yavsc/ViewModels/Gen/PdfGenerationViewModel.cs new file mode 100644 index 00000000..6c193de4 --- /dev/null +++ b/Yavsc/ViewModels/Gen/PdfGenerationViewModel.cs @@ -0,0 +1,14 @@ +using System.ComponentModel.DataAnnotations; + +namespace Yavsc.ViewModels.Gen +{ + public class PdfGenerationViewModel + { + [Required] + public string TeXSource { get; set; } + [Required] + public string BaseFileName { get; set; } + [Required] + public string DestDir { get; set; } + } +} \ No newline at end of file diff --git a/Yavsc/Views/Estimate/Details.cshtml b/Yavsc/Views/Estimate/Details.cshtml index 87afc47b..696398ab 100644 --- a/Yavsc/Views/Estimate/Details.cshtml +++ b/Yavsc/Views/Estimate/Details.cshtml @@ -39,6 +39,11 @@ @SR["Back to List"] | @{ var filenametex = $"estimate-{Model.Id}.tex" ; var filenamepdf = $"estimate-{Model.Id}.pdf" ;} - Export au format LaTeX - Export au format Pdf + Export au format LaTeX | + + +
+ +
+

diff --git a/Yavsc/Views/FrontOffice/Estimate.pdf.cshtml b/Yavsc/Views/FrontOffice/Estimate.pdf.cshtml deleted file mode 100644 index aefd3826..00000000 --- a/Yavsc/Views/FrontOffice/Estimate.pdf.cshtml +++ /dev/null @@ -1,51 +0,0 @@ -@using System.Reflection; -@using System.IO; -@using Microsoft.Extensions.WebEncoders; -@using System.Diagnostics; -@using System.Text; -@using Yavsc.Formatters; -@model Estimate -@{ - if (ViewBag.TempDir==null) { throw new InvalidOperationException(); } - - ViewBag.Pdf = ""; - ViewBag.TeX = ""; - var writer = new System.IO.StringWriter(); - var content = await Html.PartialAsync("Estimate.tex", Model ); - content.WriteTo(writer, new TexEncoder()); - var contentStr = writer.ToString(); - string name = $"estimate-{Model.Id}"; - string fullname = new FileInfo( - System.IO.Path.Combine(ViewBag.TempDir,name)).FullName; - string ofullname = new FileInfo( - System.IO.Path.Combine(ViewBag.BillsDir,name)).FullName; - - FileInfo fi = new FileInfo(fullname + ".tex"); - FileInfo fo = new FileInfo(ofullname + ".pdf"); - using (StreamWriter sw = new StreamWriter (fi.FullName)) - { - sw.Write (contentStr); - } - if (!fi.Exists) - { - throw new Exception ("Source write failed"); - } - using (Process p = new Process ()) { - p.StartInfo.WorkingDirectory = ViewBag.TempDir; - p.StartInfo = new ProcessStartInfo (); - p.StartInfo.UseShellExecute = false; - p.StartInfo.FileName = "/usr/bin/texi2pdf"; - p.StartInfo.Arguments = $"--batch --build-dir=. -o {fo.FullName} {fi.FullName}"; - p.Start (); - p.WaitForExit (); - if (p.ExitCode != 0) { - throw new Exception ("Pdf generation failed with exit code:" + p.ExitCode); - } - } - ViewBag.Success = fo.Exists; - fi.Delete(); - var uri = $"~/api/pdfestimate/{Model.Id}"; - -} - -@uri \ No newline at end of file diff --git a/Yavsc/Views/Shared/Components/Estimate/Estimate_pdf.cshtml b/Yavsc/Views/Shared/Components/Estimate/Estimate_pdf.cshtml new file mode 100644 index 00000000..08664810 --- /dev/null +++ b/Yavsc/Views/Shared/Components/Estimate/Estimate_pdf.cshtml @@ -0,0 +1,50 @@ +@using System.Reflection +@using System.IO +@using Microsoft.Extensions.WebEncoders +@using System.Diagnostics +@using System.Text +@using Yavsc.Formatters +@model Yavsc.ViewModels.Gen.PdfGenerationViewModel +@{ + string errorMsg = null; + var billdir = Model.DestDir; + var tempdir = Startup.SiteSetup.TempDir; + string name = Model.BaseFileName; + string fullname = new FileInfo( + System.IO.Path.Combine(tempdir,name)).FullName; + string ofullname = new FileInfo( + System.IO.Path.Combine(billdir,name)).FullName; + + FileInfo fi = new FileInfo(fullname + ".tex"); + FileInfo fo = new FileInfo(ofullname + ".pdf"); + using (StreamWriter sw = new StreamWriter (fi.FullName)) + { + sw.Write (Model.TeXSource); + } + if (!fi.Exists) + { + errorMsg = "Source write failed"; + } + else { + using (Process p = new Process ()) { + p.StartInfo.WorkingDirectory = tempdir; + p.StartInfo = new ProcessStartInfo (); + p.StartInfo.UseShellExecute = false; + p.StartInfo.FileName = "/usr/bin/texi2pdf"; + p.StartInfo.Arguments = $"--batch --build-dir=. -o {fo.FullName} {fi.FullName}"; + p.Start (); + p.WaitForExit (); + if (p.ExitCode != 0) { + errorMsg = $"Pdf generation failed with exit code: {p.ExitCode}"; + } + } + fi.Delete(); + } + ViewBag.GenSuccess = fo.Exists; +} +@if (ViewBag.GenSuccess) { + @($"{name}.pdf") +} else { + @errorMsg + Something went wrong ... +} \ No newline at end of file diff --git a/Yavsc/Views/FrontOffice/Estimate.tex.cshtml b/Yavsc/Views/Shared/Components/Estimate/Estimate_tex.cshtml similarity index 99% rename from Yavsc/Views/FrontOffice/Estimate.tex.cshtml rename to Yavsc/Views/Shared/Components/Estimate/Estimate_tex.cshtml index 5b807102..142f19cf 100644 --- a/Yavsc/Views/FrontOffice/Estimate.tex.cshtml +++ b/Yavsc/Views/Shared/Components/Estimate/Estimate_tex.cshtml @@ -1,6 +1,6 @@ -@model Estimate @using Yavsc.Helpers @using System.Globalization +@model Estimate @{ Layout = null; var pro = Model.Query.PerformerProfile; @@ -10,8 +10,7 @@ var proaddr = Model.Query?.PerformerProfile.OrganizationAddress.Address; var proaddrn = (proaddr!=null) ? proaddr.NewLinesWith("\\\\\n") : null ; var proaddrm = (proaddr!=null) ? proaddr.NewLinesWith(" - ") : null ; -} -\documentclass[french,11pt]{article} +}\documentclass[french,11pt]{article} \usepackage{eurosym} \usepackage{babel} \usepackage[T1]{fontenc} diff --git a/Yavsc/project.json b/Yavsc/project.json index e8fd7ef1..96bcff9c 100755 --- a/Yavsc/project.json +++ b/Yavsc/project.json @@ -140,5 +140,6 @@ "postrestore": "echo after restoring packages", "prepublish": "gulp min", "postpublish": "echo \" . ./contrib/postPublish.sh # to push in prod.\"" - } + }, + "embed": "Views/**/*.cshtml" } \ No newline at end of file