A view component
This commit is contained in:
parent
31be2c3c22
commit
e74a81deca
11 changed files with 258 additions and 190 deletions
|
|
@ -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<IActionResult> 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 } );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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<MvcViewOptions>
|
||||
{
|
||||
public MvcViewOptions Value
|
||||
{
|
||||
get
|
||||
{
|
||||
return new MvcViewOptions();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Authorize,Route("Estimate-{id}.pdf")]
|
||||
public async Task<IActionResult> 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<IActionResult> 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");
|
||||
} */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,7 +68,6 @@ namespace Yavsc.Helpers
|
|||
/// <summary>
|
||||
/// Transforms a string of Markdown into HTML.
|
||||
/// </summary>
|
||||
/// <param name="helper">HtmlHelper - Not used, but required to make this an extension method.</param>
|
||||
/// <param name="text">The Markdown that should be transformed.</param>
|
||||
/// <param name="urlBaseLocation">The url Base Location.</param>
|
||||
/// <returns>The HTML representation of the supplied Markdown.</returns>
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
58
Yavsc/ViewComponents/EstimateViewComponent.cs
Normal file
58
Yavsc/ViewComponents/EstimateViewComponent.cs
Normal file
|
|
@ -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<IViewComponentResult> 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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
14
Yavsc/ViewModels/Gen/PdfGenerationViewModel.cs
Normal file
14
Yavsc/ViewModels/Gen/PdfGenerationViewModel.cs
Normal file
|
|
@ -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; }
|
||||
}
|
||||
}
|
||||
|
|
@ -39,6 +39,11 @@
|
|||
<a asp-action="Index">@SR["Back to List"]</a> |
|
||||
@{ var filenametex = $"estimate-{Model.Id}.tex" ;
|
||||
var filenamepdf = $"estimate-{Model.Id}.pdf" ;}
|
||||
<a href="~/do/@filenametex" >Export au format LaTeX</a>
|
||||
<a href="~/do/@filenamepdf" >Export au format Pdf</a>
|
||||
<a href="~/api/pdfestimate/gettex/@Model.Id" >Export au format LaTeX</a> |
|
||||
|
||||
|
||||
<form action="~/api/pdfestimate/gen/@Model.Id" method="GET">
|
||||
<input type="submit" value="Générer le Pdf"/>
|
||||
</form>
|
||||
|
||||
</p>
|
||||
|
|
|
|||
|
|
@ -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}";
|
||||
|
||||
}
|
||||
|
||||
<a href="@uri" >@uri</a>
|
||||
50
Yavsc/Views/Shared/Components/Estimate/Estimate_pdf.cshtml
Normal file
50
Yavsc/Views/Shared/Components/Estimate/Estimate_pdf.cshtml
Normal file
|
|
@ -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
|
||||
<text>Something went wrong ...</text>
|
||||
}
|
||||
|
|
@ -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}
|
||||
|
|
@ -140,5 +140,6 @@
|
|||
"postrestore": "echo after restoring packages",
|
||||
"prepublish": "gulp min",
|
||||
"postpublish": "echo \" . ./contrib/postPublish.sh # to push in prod.\""
|
||||
}
|
||||
},
|
||||
"embed": "Views/**/*.cshtml"
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue