diff --git a/src/Microservices/Common/ClassifiedAds.CrossCuttingConcerns/Csv/ICsvReader.cs b/src/Microservices/Common/ClassifiedAds.CrossCuttingConcerns/Csv/ICsvReader.cs index e498900ca..c3e51237e 100644 --- a/src/Microservices/Common/ClassifiedAds.CrossCuttingConcerns/Csv/ICsvReader.cs +++ b/src/Microservices/Common/ClassifiedAds.CrossCuttingConcerns/Csv/ICsvReader.cs @@ -1,9 +1,14 @@ -using System.Collections.Generic; -using System.IO; +using System.IO; +using System.Threading.Tasks; namespace ClassifiedAds.CrossCuttingConcerns.Csv; public interface ICsvReader + where T : ICsvResponse { - IEnumerable Read(Stream stream); + Task ReadAsync(Stream stream); } + +public interface ICsvResponse +{ +} \ No newline at end of file diff --git a/src/Microservices/Common/ClassifiedAds.CrossCuttingConcerns/Csv/ICsvWriter.cs b/src/Microservices/Common/ClassifiedAds.CrossCuttingConcerns/Csv/ICsvWriter.cs index f726a82e4..078ea0dcd 100644 --- a/src/Microservices/Common/ClassifiedAds.CrossCuttingConcerns/Csv/ICsvWriter.cs +++ b/src/Microservices/Common/ClassifiedAds.CrossCuttingConcerns/Csv/ICsvWriter.cs @@ -1,9 +1,14 @@ -using System.Collections.Generic; -using System.IO; +using System.IO; +using System.Threading.Tasks; namespace ClassifiedAds.CrossCuttingConcerns.Csv; public interface ICsvWriter + where T : ICsvRequest { - void Write(IEnumerable collection, Stream stream); + Task WriteAsync(T data, Stream stream); } + +public interface ICsvRequest +{ +} \ No newline at end of file diff --git a/src/Microservices/Common/ClassifiedAds.CrossCuttingConcerns/Excel/IExcelReader.cs b/src/Microservices/Common/ClassifiedAds.CrossCuttingConcerns/Excel/IExcelReader.cs index ee57a30df..71c0934cf 100644 --- a/src/Microservices/Common/ClassifiedAds.CrossCuttingConcerns/Excel/IExcelReader.cs +++ b/src/Microservices/Common/ClassifiedAds.CrossCuttingConcerns/Excel/IExcelReader.cs @@ -1,8 +1,14 @@ using System.IO; +using System.Threading.Tasks; namespace ClassifiedAds.CrossCuttingConcerns.Excel; public interface IExcelReader + where T : IExcelResponse +{ + Task ReadAsync(Stream stream); +} + +public interface IExcelResponse { - T Read(Stream stream); } diff --git a/src/Microservices/Common/ClassifiedAds.CrossCuttingConcerns/Excel/IExcelWriter.cs b/src/Microservices/Common/ClassifiedAds.CrossCuttingConcerns/Excel/IExcelWriter.cs index a42031f4b..536e8ca14 100644 --- a/src/Microservices/Common/ClassifiedAds.CrossCuttingConcerns/Excel/IExcelWriter.cs +++ b/src/Microservices/Common/ClassifiedAds.CrossCuttingConcerns/Excel/IExcelWriter.cs @@ -1,8 +1,14 @@ using System.IO; +using System.Threading.Tasks; namespace ClassifiedAds.CrossCuttingConcerns.Excel; public interface IExcelWriter + where T : IExcelRequest { - void Write(T data, Stream stream); + Task WriteAsync(T data, Stream stream); } + +public interface IExcelRequest +{ +} \ No newline at end of file diff --git a/src/Microservices/Common/ClassifiedAds.CrossCuttingConcerns/Html/IHtmlWriter.cs b/src/Microservices/Common/ClassifiedAds.CrossCuttingConcerns/Html/IHtmlWriter.cs new file mode 100644 index 000000000..9160aa439 --- /dev/null +++ b/src/Microservices/Common/ClassifiedAds.CrossCuttingConcerns/Html/IHtmlWriter.cs @@ -0,0 +1,16 @@ +using System.IO; +using System.Threading.Tasks; + +namespace ClassifiedAds.CrossCuttingConcerns.Html; + +public interface IHtmlWriter + where T : IHtmlRequest +{ + Task WriteAsync(T data, Stream stream); + + Task GetStringAsync(T data); +} + +public interface IHtmlRequest +{ +} \ No newline at end of file diff --git a/src/Microservices/Common/ClassifiedAds.CrossCuttingConcerns/HtmlGenerator/IHtmlGenerator.cs b/src/Microservices/Common/ClassifiedAds.CrossCuttingConcerns/HtmlGenerator/IHtmlGenerator.cs deleted file mode 100644 index 209f4bdef..000000000 --- a/src/Microservices/Common/ClassifiedAds.CrossCuttingConcerns/HtmlGenerator/IHtmlGenerator.cs +++ /dev/null @@ -1,8 +0,0 @@ -using System.Threading.Tasks; - -namespace ClassifiedAds.CrossCuttingConcerns.HtmlGenerator; - -public interface IHtmlGenerator -{ - Task GenerateAsync(string template, object model); -} diff --git a/src/Microservices/Common/ClassifiedAds.CrossCuttingConcerns/Pdf/IPdfWriter.cs b/src/Microservices/Common/ClassifiedAds.CrossCuttingConcerns/Pdf/IPdfWriter.cs new file mode 100644 index 000000000..c0db7bacc --- /dev/null +++ b/src/Microservices/Common/ClassifiedAds.CrossCuttingConcerns/Pdf/IPdfWriter.cs @@ -0,0 +1,16 @@ +using System.IO; +using System.Threading.Tasks; + +namespace ClassifiedAds.CrossCuttingConcerns.Pdf; + +public interface IPdfWriter + where T : IPdfRequest +{ + Task WriteAsync(T data, Stream stream); + + Task GetBytesAsync(T data); +} + +public interface IPdfRequest +{ +} diff --git a/src/Microservices/Common/ClassifiedAds.CrossCuttingConcerns/PdfConverter/IPdfConverter.cs b/src/Microservices/Common/ClassifiedAds.CrossCuttingConcerns/PdfConverter/IPdfConverter.cs deleted file mode 100644 index fc567d15d..000000000 --- a/src/Microservices/Common/ClassifiedAds.CrossCuttingConcerns/PdfConverter/IPdfConverter.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System.IO; -using System.Threading.Tasks; - -namespace ClassifiedAds.CrossCuttingConcerns.PdfConverter; - -public interface IPdfConverter -{ - Stream Convert(string html, PdfOptions pdfOptions = null); - - Task ConvertAsync(string html, PdfOptions pdfOptions = null); -} - -public class PdfOptions -{ - -} diff --git a/src/Microservices/Common/ClassifiedAds.Infrastructure/Csv/CsvReader.cs b/src/Microservices/Common/ClassifiedAds.Infrastructure/Csv/CsvReader.cs deleted file mode 100644 index fac48811c..000000000 --- a/src/Microservices/Common/ClassifiedAds.Infrastructure/Csv/CsvReader.cs +++ /dev/null @@ -1,17 +0,0 @@ -using ClassifiedAds.CrossCuttingConcerns.Csv; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; - -namespace ClassifiedAds.Infrastructure.Csv; - -public class CsvReader : ICsvReader -{ - public IEnumerable Read(Stream stream) - { - using var reader = new StreamReader(stream); - using var csv = new CsvHelper.CsvReader(reader, CultureInfo.InvariantCulture); - return csv.GetRecords().ToList(); - } -} diff --git a/src/Microservices/Common/ClassifiedAds.Infrastructure/Csv/CsvWriter.cs b/src/Microservices/Common/ClassifiedAds.Infrastructure/Csv/CsvWriter.cs deleted file mode 100644 index ca1e0a8c6..000000000 --- a/src/Microservices/Common/ClassifiedAds.Infrastructure/Csv/CsvWriter.cs +++ /dev/null @@ -1,16 +0,0 @@ -using ClassifiedAds.CrossCuttingConcerns.Csv; -using System.Collections.Generic; -using System.Globalization; -using System.IO; - -namespace ClassifiedAds.Infrastructure.Csv; - -public class CsvWriter : ICsvWriter -{ - public void Write(IEnumerable collection, Stream stream) - { - using var writer = new StreamWriter(stream); - using var csv = new CsvHelper.CsvWriter(writer, CultureInfo.InvariantCulture); - csv.WriteRecords(collection); - } -} diff --git a/src/Microservices/Common/ClassifiedAds.Infrastructure/HtmlGenerators/HtmlGeneratorCollectionExtensions.cs b/src/Microservices/Common/ClassifiedAds.Infrastructure/Html/HtmlCollectionExtensions.cs similarity index 51% rename from src/Microservices/Common/ClassifiedAds.Infrastructure/HtmlGenerators/HtmlGeneratorCollectionExtensions.cs rename to src/Microservices/Common/ClassifiedAds.Infrastructure/Html/HtmlCollectionExtensions.cs index 01b5af963..378fd5691 100644 --- a/src/Microservices/Common/ClassifiedAds.Infrastructure/HtmlGenerators/HtmlGeneratorCollectionExtensions.cs +++ b/src/Microservices/Common/ClassifiedAds.Infrastructure/Html/HtmlCollectionExtensions.cs @@ -1,13 +1,11 @@ -using ClassifiedAds.CrossCuttingConcerns.HtmlGenerator; -using ClassifiedAds.Infrastructure.HtmlGenerators; -using RazorLight; +using RazorLight; using System; namespace Microsoft.Extensions.DependencyInjection; -public static class HtmlGeneratorCollectionExtensions +public static class HtmlCollectionExtensions { - public static IServiceCollection AddHtmlGenerator(this IServiceCollection services) + public static IServiceCollection AddHtmlRazorLightEngine(this IServiceCollection services) { var engine = new RazorLightEngineBuilder() .UseFileSystemProject(Environment.CurrentDirectory) @@ -15,7 +13,6 @@ public static IServiceCollection AddHtmlGenerator(this IServiceCollection servic .Build(); services.AddSingleton(engine); - services.AddSingleton(); return services; } diff --git a/src/Microservices/Common/ClassifiedAds.Infrastructure/HtmlGenerators/HtmlGenerator.cs b/src/Microservices/Common/ClassifiedAds.Infrastructure/HtmlGenerators/HtmlGenerator.cs deleted file mode 100644 index cc8d0dd33..000000000 --- a/src/Microservices/Common/ClassifiedAds.Infrastructure/HtmlGenerators/HtmlGenerator.cs +++ /dev/null @@ -1,20 +0,0 @@ -using ClassifiedAds.CrossCuttingConcerns.HtmlGenerator; -using RazorLight; -using System.Threading.Tasks; - -namespace ClassifiedAds.Infrastructure.HtmlGenerators; - -public class HtmlGenerator : IHtmlGenerator -{ - private readonly IRazorLightEngine _razorLightEngine; - - public HtmlGenerator(IRazorLightEngine razorLightEngine) - { - _razorLightEngine = razorLightEngine; - } - - public Task GenerateAsync(string template, object model) - { - return _razorLightEngine.CompileRenderAsync(template, model); - } -} diff --git a/src/Microservices/Common/ClassifiedAds.Infrastructure/PdfConverters/DinkToPdf/DinkToPdfConverterCollectionExtensions.cs b/src/Microservices/Common/ClassifiedAds.Infrastructure/Pdf/DinkToPdf/DinkToPdfCollectionExtensions.cs similarity index 54% rename from src/Microservices/Common/ClassifiedAds.Infrastructure/PdfConverters/DinkToPdf/DinkToPdfConverterCollectionExtensions.cs rename to src/Microservices/Common/ClassifiedAds.Infrastructure/Pdf/DinkToPdf/DinkToPdfCollectionExtensions.cs index 80087ea6c..2fe5c3df3 100644 --- a/src/Microservices/Common/ClassifiedAds.Infrastructure/PdfConverters/DinkToPdf/DinkToPdfConverterCollectionExtensions.cs +++ b/src/Microservices/Common/ClassifiedAds.Infrastructure/Pdf/DinkToPdf/DinkToPdfCollectionExtensions.cs @@ -1,17 +1,13 @@ -using ClassifiedAds.CrossCuttingConcerns.PdfConverter; -using ClassifiedAds.Infrastructure.PdfConverters.DinkToPdf; -using DinkToPdf; +using DinkToPdf; using DinkToPdf.Contracts; namespace Microsoft.Extensions.DependencyInjection; -public static class DinkToPdfConverterCollectionExtensions +public static class DinkToPdfCollectionExtensions { public static IServiceCollection AddDinkToPdfConverter(this IServiceCollection services) { services.AddSingleton(typeof(IConverter), new SynchronizedConverter(new PdfTools())); - services.AddSingleton(); - return services; } } diff --git a/src/Microservices/Common/ClassifiedAds.Infrastructure/PdfConverters/PuppeteerSharp/PuppeteerSharpConverterCollectionExtensions.cs b/src/Microservices/Common/ClassifiedAds.Infrastructure/Pdf/PuppeteerSharp/PuppeteerSharpCollectionExtensions.cs similarity index 52% rename from src/Microservices/Common/ClassifiedAds.Infrastructure/PdfConverters/PuppeteerSharp/PuppeteerSharpConverterCollectionExtensions.cs rename to src/Microservices/Common/ClassifiedAds.Infrastructure/Pdf/PuppeteerSharp/PuppeteerSharpCollectionExtensions.cs index aca01319f..c318ea275 100644 --- a/src/Microservices/Common/ClassifiedAds.Infrastructure/PdfConverters/PuppeteerSharp/PuppeteerSharpConverterCollectionExtensions.cs +++ b/src/Microservices/Common/ClassifiedAds.Infrastructure/Pdf/PuppeteerSharp/PuppeteerSharpCollectionExtensions.cs @@ -1,18 +1,13 @@ -using ClassifiedAds.CrossCuttingConcerns.PdfConverter; -using ClassifiedAds.Infrastructure.PdfConverters.PuppeteerSharp; -using PuppeteerSharp; +using PuppeteerSharp; namespace Microsoft.Extensions.DependencyInjection; -public static class PuppeteerSharpConverterCollectionExtensions +public static class PuppeteerSharpCollectionExtensions { public static IServiceCollection AddPuppeteerSharpPdfConverter(this IServiceCollection services) { var browserFetcher = new BrowserFetcher(); browserFetcher.DownloadAsync().GetAwaiter().GetResult(); - - services.AddSingleton(); - return services; } } diff --git a/src/Microservices/Common/ClassifiedAds.Infrastructure/PdfConverters/PuppeteerSharp/PuppeteerSharpConverter.cs b/src/Microservices/Common/ClassifiedAds.Infrastructure/PdfConverters/PuppeteerSharp/PuppeteerSharpConverter.cs deleted file mode 100644 index fc042a459..000000000 --- a/src/Microservices/Common/ClassifiedAds.Infrastructure/PdfConverters/PuppeteerSharp/PuppeteerSharpConverter.cs +++ /dev/null @@ -1,25 +0,0 @@ -using ClassifiedAds.CrossCuttingConcerns.PdfConverter; -using PuppeteerSharp; -using System.IO; -using System.Threading.Tasks; - -namespace ClassifiedAds.Infrastructure.PdfConverters.PuppeteerSharp; - -public class PuppeteerSharpConverter : IPdfConverter -{ - public Stream Convert(string html, CrossCuttingConcerns.PdfConverter.PdfOptions pdfOptions = null) - { - return ConvertAsync(html, pdfOptions).GetAwaiter().GetResult(); - } - - public async Task ConvertAsync(string html, CrossCuttingConcerns.PdfConverter.PdfOptions pdfOptions = null) - { - await using var browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = true }); - await using var page = await browser.NewPageAsync(); - await page.SetContentAsync(html); - return new MemoryStream(await page.PdfDataAsync(new global::PuppeteerSharp.PdfOptions - { - PrintBackground = true, - })); - } -} diff --git a/src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/ConfigurationModuleServiceCollectionExtensions.cs b/src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/ConfigurationModuleServiceCollectionExtensions.cs index e86458f19..2c742cd46 100644 --- a/src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/ConfigurationModuleServiceCollectionExtensions.cs +++ b/src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/ConfigurationModuleServiceCollectionExtensions.cs @@ -3,12 +3,12 @@ using ClassifiedAds.Services.Configuration.Authorization; using ClassifiedAds.Services.Configuration.ConfigurationOptions; using ClassifiedAds.Services.Configuration.Entities; +using ClassifiedAds.Services.Configuration.Excel; using ClassifiedAds.Services.Configuration.Excel.ClosedXML; using ClassifiedAds.Services.Configuration.Repositories; using Microsoft.AspNetCore.Builder; using Microsoft.EntityFrameworkCore; using System; -using System.Collections.Generic; using System.Reflection; namespace Microsoft.Extensions.DependencyInjection; @@ -30,8 +30,8 @@ public static IServiceCollection AddConfigurationModule(this IServiceCollection services.AddAuthorizationPolicies(Assembly.GetExecutingAssembly(), AuthorizationPolicyNames.GetPolicyNames()); - services.AddScoped>, ConfigurationEntryExcelReader>(); - services.AddScoped>, ConfigurationEntryExcelWriter>(); + services.AddScoped, ImportConfigurationEntriesFromExcelHandler>(); + services.AddScoped, ExportConfigurationEntriesToExcelHandler>(); return services; } diff --git a/src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Controllers/ConfigurationEntriesController.cs b/src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Controllers/ConfigurationEntriesController.cs index 24c6c8011..16335e818 100644 --- a/src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Controllers/ConfigurationEntriesController.cs +++ b/src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Controllers/ConfigurationEntriesController.cs @@ -3,6 +3,7 @@ using ClassifiedAds.Services.Configuration.Authorization; using ClassifiedAds.Services.Configuration.ConfigurationOptions; using ClassifiedAds.Services.Configuration.Entities; +using ClassifiedAds.Services.Configuration.Excel; using ClassifiedAds.Services.Configuration.Models; using CryptographyHelper; using CryptographyHelper.AsymmetricAlgorithms; @@ -29,14 +30,14 @@ public class ConfigurationEntriesController : ControllerBase private readonly Dispatcher _dispatcher; private readonly ILogger _logger; private readonly AppSettings _appSettings; - private readonly IExcelWriter> _configurationEntriesExcelWriter; - private readonly IExcelReader> _configurationEntriesExcelReader; + private readonly IExcelWriter _configurationEntriesExcelWriter; + private readonly IExcelReader _configurationEntriesExcelReader; public ConfigurationEntriesController(Dispatcher dispatcher, ILogger logger, IOptionsSnapshot appSettings, - IExcelWriter> configurationEntriesExcelWriter, - IExcelReader> configurationEntriesExcelReader) + IExcelWriter configurationEntriesExcelWriter, + IExcelReader configurationEntriesExcelReader) { _dispatcher = dispatcher; _logger = logger; @@ -131,17 +132,17 @@ public async Task ExportAsExcel() { var entries = await _dispatcher.DispatchAsync(new GetEntititesQuery()); using var stream = new MemoryStream(); - _configurationEntriesExcelWriter.Write(entries, stream); + await _configurationEntriesExcelWriter.WriteAsync(new ExportConfigurationEntriesToExcel { ConfigurationEntries = entries }, stream); return File(stream.ToArray(), MediaTypeNames.Application.Octet, "ConfigurationEntries.xlsx"); } [HttpPost("ImportExcel")] - public IActionResult ImportExcel([FromForm] UploadFileModel model) + public async Task ImportExcel([FromForm] UploadFileModel model) { using var stream = model.FormFile.OpenReadStream(); - var entries = _configurationEntriesExcelReader.Read(stream); + var entries = await _configurationEntriesExcelReader.ReadAsync(stream); // TODO: import to database - return Ok(entries); + return Ok(entries.ConfigurationEntries); } } diff --git a/src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Excel/ClosedXML/ConfigurationEntryExcelWriter.cs b/src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Excel/ClosedXML/ExportConfigurationEntriesToExcelHandler.cs similarity index 67% rename from src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Excel/ClosedXML/ConfigurationEntryExcelWriter.cs rename to src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Excel/ClosedXML/ExportConfigurationEntriesToExcelHandler.cs index 75b8f2151..39fe73563 100644 --- a/src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Excel/ClosedXML/ConfigurationEntryExcelWriter.cs +++ b/src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Excel/ClosedXML/ExportConfigurationEntriesToExcelHandler.cs @@ -1,14 +1,13 @@ using ClassifiedAds.CrossCuttingConcerns.Excel; -using ClassifiedAds.Services.Configuration.Entities; using ClosedXML.Excel; -using System.Collections.Generic; using System.IO; +using System.Threading.Tasks; namespace ClassifiedAds.Services.Configuration.Excel.ClosedXML; -public class ConfigurationEntryExcelWriter : IExcelWriter> +public class ExportConfigurationEntriesToExcelHandler : IExcelWriter { - public void Write(List data, Stream stream) + public Task WriteAsync(ExportConfigurationEntriesToExcel data, Stream stream) { using var workbook = new XLWorkbook(); var worksheet = workbook.Worksheets.Add("Sheet1"); @@ -18,7 +17,7 @@ public void Write(List data, Stream stream) worksheet.Range("A1:B1").Style.Font.Bold = true; int i = 2; - foreach (var row in data) + foreach (var row in data.ConfigurationEntries) { worksheet.Cell("A" + i).Value = row.Key; worksheet.Cell("B" + i).Value = row.Value; @@ -26,5 +25,7 @@ public void Write(List data, Stream stream) } workbook.SaveAs(stream); + + return Task.CompletedTask; } } diff --git a/src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Excel/ClosedXML/ConfigurationEntryExcelReader.cs b/src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Excel/ClosedXML/ImportConfigurationEntriesFromExcelHandler.cs similarity index 78% rename from src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Excel/ClosedXML/ConfigurationEntryExcelReader.cs rename to src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Excel/ClosedXML/ImportConfigurationEntriesFromExcelHandler.cs index 75ab1de75..511f3b25b 100644 --- a/src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Excel/ClosedXML/ConfigurationEntryExcelReader.cs +++ b/src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Excel/ClosedXML/ImportConfigurationEntriesFromExcelHandler.cs @@ -5,12 +5,22 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Threading.Tasks; namespace ClassifiedAds.Services.Configuration.Excel.ClosedXML; -public class ConfigurationEntryExcelReader : IExcelReader> +public class ImportConfigurationEntriesFromExcelHandler : IExcelReader { - public List Read(Stream stream) + private static Dictionary GetCorrectHeaders() + { + return new Dictionary + { + { "A", "Key" }, + { "B", "Value" }, + }; + } + + public Task ReadAsync(Stream stream) { using var workbook = new XLWorkbook(stream); var worksheet = workbook.Worksheets.First(); @@ -34,15 +44,6 @@ public List Read(Stream stream) rows.Add(row); } - return rows; - } - - private static Dictionary GetCorrectHeaders() - { - return new Dictionary - { - { "A", "Key" }, - { "B", "Value" }, - }; + return Task.FromResult(new ImportConfigurationEntriesFromExcel { ConfigurationEntries = rows }); } } diff --git a/src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Excel/EPPlus/ConfigurationEntryExcelWriter.cs b/src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Excel/EPPlus/ExportConfigurationEntriesToExcelHandler.cs similarity index 66% rename from src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Excel/EPPlus/ConfigurationEntryExcelWriter.cs rename to src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Excel/EPPlus/ExportConfigurationEntriesToExcelHandler.cs index 7ecec561d..215fbf48b 100644 --- a/src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Excel/EPPlus/ConfigurationEntryExcelWriter.cs +++ b/src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Excel/EPPlus/ExportConfigurationEntriesToExcelHandler.cs @@ -1,14 +1,13 @@ using ClassifiedAds.CrossCuttingConcerns.Excel; -using ClassifiedAds.Services.Configuration.Entities; using OfficeOpenXml; -using System.Collections.Generic; using System.IO; +using System.Threading.Tasks; namespace ClassifiedAds.Services.Configuration.Excel.EPPlus; -public class ConfigurationEntryExcelWriter : IExcelWriter> +public class ExportConfigurationEntriesToExcelHandler : IExcelWriter { - public void Write(List data, Stream stream) + public Task WriteAsync(ExportConfigurationEntriesToExcel data, Stream stream) { using var pck = new ExcelPackage(); var worksheet = pck.Workbook.Worksheets.Add("Sheet1"); @@ -18,7 +17,7 @@ public void Write(List data, Stream stream) worksheet.Cells["A1:B1"].Style.Font.Bold = true; int i = 2; - foreach (var row in data) + foreach (var row in data.ConfigurationEntries) { worksheet.Cells["A" + i].Value = row.Key; worksheet.Cells["B" + i].Value = row.Value; @@ -26,5 +25,7 @@ public void Write(List data, Stream stream) } pck.SaveAs(stream); + + return Task.CompletedTask; } } diff --git a/src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Excel/EPPlus/ConfigurationEntryExcelReader.cs b/src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Excel/EPPlus/ImportConfigurationEntriesFromExcelHandler.cs similarity index 78% rename from src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Excel/EPPlus/ConfigurationEntryExcelReader.cs rename to src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Excel/EPPlus/ImportConfigurationEntriesFromExcelHandler.cs index bde3cbad5..89bd23ca0 100644 --- a/src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Excel/EPPlus/ConfigurationEntryExcelReader.cs +++ b/src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Excel/EPPlus/ImportConfigurationEntriesFromExcelHandler.cs @@ -5,12 +5,22 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Threading.Tasks; namespace ClassifiedAds.Services.Configuration.Excel.EPPlus; -public class ConfigurationEntryExcelReader : IExcelReader> +public class ImportConfigurationEntriesFromExcelHandler : IExcelReader { - public List Read(Stream stream) + private static Dictionary GetCorrectHeaders() + { + return new Dictionary + { + { "A", "Key" }, + { "B", "Value" }, + }; + } + + public Task ReadAsync(Stream stream) { using var pck = new ExcelPackage(stream); var worksheet = pck.Workbook.Worksheets.First(); @@ -34,15 +44,6 @@ public List Read(Stream stream) rows.Add(row); } - return rows; - } - - private static Dictionary GetCorrectHeaders() - { - return new Dictionary - { - { "A", "Key" }, - { "B", "Value" }, - }; + return Task.FromResult(new ImportConfigurationEntriesFromExcel { ConfigurationEntries = rows }); } } diff --git a/src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Excel/ExcelDataReader/ConfigurationEntryExcelReader.cs b/src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Excel/ExcelDataReader/ImportConfigurationEntriesFromExcelHandler.cs similarity index 84% rename from src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Excel/ExcelDataReader/ConfigurationEntryExcelReader.cs rename to src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Excel/ExcelDataReader/ImportConfigurationEntriesFromExcelHandler.cs index bb0d62067..495510570 100644 --- a/src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Excel/ExcelDataReader/ConfigurationEntryExcelReader.cs +++ b/src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Excel/ExcelDataReader/ImportConfigurationEntriesFromExcelHandler.cs @@ -1,16 +1,26 @@ using ClassifiedAds.CrossCuttingConcerns.Excel; using ClassifiedAds.CrossCuttingConcerns.Exceptions; -using ClassifiedAds.Domain.Entities; +using ClassifiedAds.Services.Configuration.Entities; using ExcelDataReader; using System; using System.Collections.Generic; using System.IO; +using System.Threading.Tasks; namespace ClassifiedAds.Services.Configuration.Excel.ExcelDataReader; -public class ConfigurationEntryExcelReader : IExcelReader> +public class ImportConfigurationEntriesFromExcelHandler : IExcelReader { - public List Read(Stream stream) + private static Dictionary GetCorrectHeaders() + { + return new Dictionary + { + { 0, "Key" }, + { 1, "Value" }, + }; + } + + public Task ReadAsync(Stream stream) { var rows = new List(); int headerIndex = 0; @@ -63,15 +73,6 @@ public List Read(Stream stream) while (reader.NextResult()); } - return rows; - } - - private static Dictionary GetCorrectHeaders() - { - return new Dictionary - { - { 0, "Key" }, - { 1, "Value" }, - }; + return Task.FromResult(new ImportConfigurationEntriesFromExcel { ConfigurationEntries = rows }); } } diff --git a/src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Excel/ExportConfigurationEntriesToExcel.cs b/src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Excel/ExportConfigurationEntriesToExcel.cs new file mode 100644 index 000000000..969303b9f --- /dev/null +++ b/src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Excel/ExportConfigurationEntriesToExcel.cs @@ -0,0 +1,10 @@ +using ClassifiedAds.CrossCuttingConcerns.Excel; +using ClassifiedAds.Services.Configuration.Entities; +using System.Collections.Generic; + +namespace ClassifiedAds.Services.Configuration.Excel; + +public class ExportConfigurationEntriesToExcel : IExcelRequest +{ + public List ConfigurationEntries { get; set; } +} diff --git a/src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Excel/ImportConfigurationEntriesFromExcel.cs b/src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Excel/ImportConfigurationEntriesFromExcel.cs new file mode 100644 index 000000000..b79c77ccd --- /dev/null +++ b/src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Excel/ImportConfigurationEntriesFromExcel.cs @@ -0,0 +1,10 @@ +using ClassifiedAds.CrossCuttingConcerns.Excel; +using ClassifiedAds.Services.Configuration.Entities; +using System.Collections.Generic; + +namespace ClassifiedAds.Services.Configuration.Excel; + +public class ImportConfigurationEntriesFromExcel : IExcelResponse +{ + public List ConfigurationEntries { get; set; } +} diff --git a/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Csv/ExportProductsToCsv.cs b/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Csv/ExportProductsToCsv.cs new file mode 100644 index 000000000..bb26fb87b --- /dev/null +++ b/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Csv/ExportProductsToCsv.cs @@ -0,0 +1,9 @@ +using ClassifiedAds.CrossCuttingConcerns.Csv; +using System.Collections.Generic; + +namespace ClassifiedAds.Services.Product.Csv; + +public record ExportProductsToCsv : ICsvRequest +{ + public List Products { get; set; } +} diff --git a/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Csv/ExportProductsToCsvHandler.cs b/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Csv/ExportProductsToCsvHandler.cs new file mode 100644 index 000000000..3d2c2831e --- /dev/null +++ b/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Csv/ExportProductsToCsvHandler.cs @@ -0,0 +1,18 @@ +using ClassifiedAds.CrossCuttingConcerns.Csv; +using System.Globalization; +using System.IO; +using System.Threading.Tasks; + +namespace ClassifiedAds.Services.Product.Csv; + +public class ExportProductsToCsvHandler : ICsvWriter +{ + public Task WriteAsync(ExportProductsToCsv data, Stream stream) + { + using var writer = new StreamWriter(stream); + using var csv = new CsvHelper.CsvWriter(writer, CultureInfo.InvariantCulture); + csv.WriteRecords(data.Products); + + return Task.CompletedTask; + } +} diff --git a/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Csv/ImportProductsFromCsv.cs b/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Csv/ImportProductsFromCsv.cs new file mode 100644 index 000000000..3829b213b --- /dev/null +++ b/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Csv/ImportProductsFromCsv.cs @@ -0,0 +1,9 @@ +using ClassifiedAds.CrossCuttingConcerns.Csv; +using System.Collections.Generic; + +namespace ClassifiedAds.Services.Product.Csv; + +public record ImportProductsFromCsv : ICsvResponse +{ + public List Products { get; set; } +} diff --git a/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Csv/ImportProductsFromCsvHandler.cs b/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Csv/ImportProductsFromCsvHandler.cs new file mode 100644 index 000000000..0570c3d82 --- /dev/null +++ b/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Csv/ImportProductsFromCsvHandler.cs @@ -0,0 +1,31 @@ +using ClassifiedAds.CrossCuttingConcerns.Csv; +using CsvHelper.Configuration; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Threading.Tasks; + +namespace ClassifiedAds.Services.Product.Csv; + +public class ImportProductsFromCsvHandler : ICsvReader +{ + public Task ReadAsync(Stream stream) + { + using var reader = new StreamReader(stream); + + var config = new CsvConfiguration(CultureInfo.InvariantCulture) + { + HeaderValidated = null, + MissingFieldFound = null, + }; + + using var csv = new CsvHelper.CsvReader(reader, config); + + var response = new ImportProductsFromCsv + { + Products = csv.GetRecords().ToList(), + }; + + return Task.FromResult(response); + } +} diff --git a/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Endpoints/ExportProductsAsCsvRequest.cs b/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Endpoints/ExportProductsAsCsvRequest.cs index d8d5d6591..baab33423 100644 --- a/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Endpoints/ExportProductsAsCsvRequest.cs +++ b/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Endpoints/ExportProductsAsCsvRequest.cs @@ -1,6 +1,6 @@ using ClassifiedAds.CrossCuttingConcerns.Csv; using ClassifiedAds.Infrastructure.Web.MinimalApis; -using ClassifiedAds.Services.Product.Models; +using ClassifiedAds.Services.Product.Csv; using ClassifiedAds.Services.Product.Queries; using ClassifiedAds.Services.Product.RateLimiterPolicies; using MediatR; @@ -31,12 +31,11 @@ public static void MapEndpoint(IEndpointRouteBuilder builder) } private static async Task HandleAsync(IMediator dispatcher, - ICsvWriter productCsvWriter) + ICsvWriter productCsvWriter) { var products = await dispatcher.Send(new GetProductsQuery()); - var model = products.ToModels(); using var stream = new MemoryStream(); - productCsvWriter.Write(model, stream); + await productCsvWriter.WriteAsync(new ExportProductsToCsv { Products = products }, stream); return Results.File(stream.ToArray(), MediaTypeNames.Application.Octet, "Products.csv"); } } diff --git a/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Endpoints/ExportProductsAsPdfRequest.cs b/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Endpoints/ExportProductsAsPdfRequest.cs index 3fc4e574d..f8032b6a5 100644 --- a/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Endpoints/ExportProductsAsPdfRequest.cs +++ b/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Endpoints/ExportProductsAsPdfRequest.cs @@ -1,7 +1,6 @@ -using ClassifiedAds.CrossCuttingConcerns.HtmlGenerator; -using ClassifiedAds.CrossCuttingConcerns.PdfConverter; +using ClassifiedAds.CrossCuttingConcerns.Pdf; using ClassifiedAds.Infrastructure.Web.MinimalApis; -using ClassifiedAds.Services.Product.Models; +using ClassifiedAds.Services.Product.Pdf; using ClassifiedAds.Services.Product.Queries; using ClassifiedAds.Services.Product.RateLimiterPolicies; using MediatR; @@ -9,9 +8,7 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing; using Microsoft.OpenApi.Models; -using System; using System.Collections.Generic; -using System.IO; using System.Net.Mime; using System.Threading.Tasks; @@ -32,17 +29,11 @@ public static void MapEndpoint(IEndpointRouteBuilder builder) }); } - private static async Task HandleAsync(IMediator dispatcher, - IHtmlGenerator htmlGenerator, - IPdfConverter pdfConverter) + private static async Task HandleAsync(IMediator dispatcher, IPdfWriter pdfWriter) { var products = await dispatcher.Send(new GetProductsQuery()); - var model = products.ToModels(); + var bytes = await pdfWriter.GetBytesAsync(new ExportProductsToPdf { Products = products }); - var template = Path.Combine(Environment.CurrentDirectory, $"Templates/ProductList.cshtml"); - var html = await htmlGenerator.GenerateAsync(template, model); - var pdf = await pdfConverter.ConvertAsync(html); - - return Results.File(pdf, MediaTypeNames.Application.Octet, "Products.pdf"); + return Results.File(bytes, MediaTypeNames.Application.Octet, "Products.pdf"); } } diff --git a/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Endpoints/ImportCsvRequest.cs b/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Endpoints/ImportCsvRequest.cs index d643688c7..f5f506582 100644 --- a/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Endpoints/ImportCsvRequest.cs +++ b/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Endpoints/ImportCsvRequest.cs @@ -1,6 +1,6 @@ using ClassifiedAds.CrossCuttingConcerns.Csv; using ClassifiedAds.Infrastructure.Web.MinimalApis; -using ClassifiedAds.Services.Product.Models; +using ClassifiedAds.Services.Product.Csv; using ClassifiedAds.Services.Product.RateLimiterPolicies; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; @@ -34,12 +34,12 @@ public static void MapEndpoint(IEndpointRouteBuilder builder) .DisableAntiforgery(); } - private static Task HandleAsync(ICsvReader productCsvReader, [FromForm] ImportCsvRequest request) + private static async Task HandleAsync(ICsvReader productCsvReader, [FromForm] ImportCsvRequest request) { using var stream = request.FormFile.OpenReadStream(); - var products = productCsvReader.Read(stream); + var result = await productCsvReader.ReadAsync(stream); // TODO: import to database - return Task.FromResult(Results.Ok(products)); + return Results.Ok(result.Products); } } \ No newline at end of file diff --git a/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Html/ExportProductsToHtml.cs b/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Html/ExportProductsToHtml.cs new file mode 100644 index 000000000..90e18cb10 --- /dev/null +++ b/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Html/ExportProductsToHtml.cs @@ -0,0 +1,9 @@ +using ClassifiedAds.CrossCuttingConcerns.Html; +using System.Collections.Generic; + +namespace ClassifiedAds.Services.Product.Html; + +public record ExportProductsToHtml : IHtmlRequest +{ + public List Products { get; set; } +} diff --git a/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Html/ExportProductsToHtmlHandler.cs b/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Html/ExportProductsToHtmlHandler.cs new file mode 100644 index 000000000..aa4583097 --- /dev/null +++ b/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Html/ExportProductsToHtmlHandler.cs @@ -0,0 +1,31 @@ +using ClassifiedAds.CrossCuttingConcerns.Html; +using RazorLight; +using System; +using System.IO; +using System.Text; +using System.Threading.Tasks; + +namespace ClassifiedAds.Services.Product.Html; + +public class ExportProductsToHtmlHandler : IHtmlWriter +{ + private readonly IRazorLightEngine _razorLightEngine; + + public ExportProductsToHtmlHandler(IRazorLightEngine razorLightEngine) + { + _razorLightEngine = razorLightEngine; + } + + public async Task WriteAsync(ExportProductsToHtml data, Stream stream) + { + using var sw = new StreamWriter(stream, Encoding.UTF8); + await sw.WriteAsync(await GetStringAsync(data)); + } + + public async Task GetStringAsync(ExportProductsToHtml data) + { + var template = Path.Combine(Environment.CurrentDirectory, $"Templates/ProductList.cshtml"); + string html = await _razorLightEngine.CompileRenderAsync(template, data.Products); + return html; + } +} diff --git a/src/Microservices/Common/ClassifiedAds.Infrastructure/PdfConverters/DinkToPdf/DinkToPdfConverter.cs b/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Pdf/DinkToPdf/ExportProductsToPdfHandler.cs similarity index 50% rename from src/Microservices/Common/ClassifiedAds.Infrastructure/PdfConverters/DinkToPdf/DinkToPdfConverter.cs rename to src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Pdf/DinkToPdf/ExportProductsToPdfHandler.cs index a68845a8f..102d9e923 100644 --- a/src/Microservices/Common/ClassifiedAds.Infrastructure/PdfConverters/DinkToPdf/DinkToPdfConverter.cs +++ b/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Pdf/DinkToPdf/ExportProductsToPdfHandler.cs @@ -1,21 +1,25 @@ -using ClassifiedAds.CrossCuttingConcerns.PdfConverter; +using ClassifiedAds.CrossCuttingConcerns.Html; +using ClassifiedAds.CrossCuttingConcerns.Pdf; +using ClassifiedAds.Services.Product.Html; using DinkToPdf; using DinkToPdf.Contracts; using System.IO; using System.Threading.Tasks; -namespace ClassifiedAds.Infrastructure.PdfConverters.DinkToPdf; +namespace ClassifiedAds.Services.Product.Pdf.DinkToPdf; -public class DinkToPdfConverter : IPdfConverter +public class ExportProductsToPdfHandler : IPdfWriter { private readonly IConverter _converter; + private readonly IHtmlWriter _htmlWriter; - public DinkToPdfConverter(IConverter converter) + public ExportProductsToPdfHandler(IConverter converter, IHtmlWriter htmlWriter) { _converter = converter; + _htmlWriter = htmlWriter; } - public Stream Convert(string html, PdfOptions pdfOptions = null) + public async Task GetBytesAsync(ExportProductsToPdf data) { var doc = new HtmlToPdfDocument() { @@ -31,20 +35,20 @@ public Stream Convert(string html, PdfOptions pdfOptions = null) new ObjectSettings() { PagesCount = true, - HtmlContent = html, + HtmlContent = await _htmlWriter.GetStringAsync(new ExportProductsToHtml {Products = data.Products}), WebSettings = { DefaultEncoding = "utf-8", Background = true }, HeaderSettings = { FontSize = 9, Right = "Page [page] of [toPage]", Line = true, Spacing = 2.812 }, }, }, }; - byte[] pdf = _converter.Convert(doc); - - return new MemoryStream(pdf); + var bytes = _converter.Convert(doc); + return bytes; } - public Task ConvertAsync(string html, PdfOptions pdfOptions = null) + public async Task WriteAsync(ExportProductsToPdf data, Stream stream) { - return Task.FromResult(Convert(html, pdfOptions)); + using var sw = new BinaryWriter(stream); + sw.Write(await GetBytesAsync(data)); } } diff --git a/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Pdf/ExportProductsToPdf.cs b/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Pdf/ExportProductsToPdf.cs new file mode 100644 index 000000000..ec1552034 --- /dev/null +++ b/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Pdf/ExportProductsToPdf.cs @@ -0,0 +1,9 @@ +using ClassifiedAds.CrossCuttingConcerns.Pdf; +using System.Collections.Generic; + +namespace ClassifiedAds.Services.Product.Pdf; + +public record ExportProductsToPdf : IPdfRequest +{ + public List Products { get; set; } +} diff --git a/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Pdf/PuppeteerSharp/ExportProductsToPdfHandler.cs b/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Pdf/PuppeteerSharp/ExportProductsToPdfHandler.cs new file mode 100644 index 000000000..a21da362f --- /dev/null +++ b/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Pdf/PuppeteerSharp/ExportProductsToPdfHandler.cs @@ -0,0 +1,39 @@ +using ClassifiedAds.CrossCuttingConcerns.Html; +using ClassifiedAds.CrossCuttingConcerns.Pdf; +using ClassifiedAds.Services.Product.Html; +using PuppeteerSharp; +using System.IO; +using System.Threading.Tasks; + +namespace ClassifiedAds.Services.Product.Pdf.PuppeteerSharp; + +public class ExportProductsToPdfHandler : IPdfWriter +{ + private readonly IHtmlWriter _htmlWriter; + + public ExportProductsToPdfHandler(IHtmlWriter htmlWriter) + { + _htmlWriter = htmlWriter; + } + + public async Task GetBytesAsync(ExportProductsToPdf data) + { + var html = await _htmlWriter.GetStringAsync(new ExportProductsToHtml { Products = data.Products }); + await using var browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = true }); + await using var page = await browser.NewPageAsync(); + await page.SetContentAsync(html); + + var bytes = await page.PdfDataAsync(new PdfOptions + { + PrintBackground = true, + }); + + return bytes; + } + + public async Task WriteAsync(ExportProductsToPdf data, Stream stream) + { + using var sw = new BinaryWriter(stream); + sw.Write(await GetBytesAsync(data)); + } +} diff --git a/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/ProductModuleServiceCollectionExtensions.cs b/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/ProductModuleServiceCollectionExtensions.cs index f8ea203d6..948a2fa90 100644 --- a/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/ProductModuleServiceCollectionExtensions.cs +++ b/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/ProductModuleServiceCollectionExtensions.cs @@ -1,13 +1,18 @@ using ClassifiedAds.CrossCuttingConcerns.Csv; +using ClassifiedAds.CrossCuttingConcerns.Html; +using ClassifiedAds.CrossCuttingConcerns.Pdf; using ClassifiedAds.Domain.Infrastructure.MessageBrokers; using ClassifiedAds.Domain.Repositories; -using ClassifiedAds.Infrastructure.Csv; using ClassifiedAds.Infrastructure.Identity; using ClassifiedAds.Services.Product.Authorization; using ClassifiedAds.Services.Product.ConfigurationOptions; +using ClassifiedAds.Services.Product.Csv; using ClassifiedAds.Services.Product.DTOs; using ClassifiedAds.Services.Product.Entities; using ClassifiedAds.Services.Product.HostedServices; +using ClassifiedAds.Services.Product.Html; +using ClassifiedAds.Services.Product.Pdf; +using ClassifiedAds.Services.Product.Pdf.DinkToPdf; using ClassifiedAds.Services.Product.Repositories; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; @@ -44,8 +49,12 @@ public static IServiceCollection AddProductModule(this IServiceCollection servic services.AddSingleton(); services.AddScoped(); - services.AddScoped(typeof(ICsvReader<>), typeof(CsvReader<>)); - services.AddScoped(typeof(ICsvWriter<>), typeof(CsvWriter<>)); + services.AddScoped, ImportProductsFromCsvHandler>(); + services.AddScoped, ExportProductsToCsvHandler>(); + + services.AddScoped, ExportProductsToHtmlHandler>(); + + services.AddScoped, ExportProductsToPdfHandler>(); services.AddTransient() .AddMessageBusSender(appSettings.MessageBroker); diff --git a/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Program.cs b/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Program.cs index 920a68bb2..76cbc9456 100644 --- a/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Program.cs +++ b/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Program.cs @@ -65,7 +65,7 @@ services.AddDateTimeProvider(); services.AddApplicationServices(); -services.AddHtmlGenerator(); +services.AddHtmlRazorLightEngine(); services.AddDinkToPdfConverter(); services.AddProductModule(appSettings); diff --git a/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Templates/ProductList.cshtml b/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Templates/ProductList.cshtml index 41551aed8..2b4ea0dc9 100644 --- a/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Templates/ProductList.cshtml +++ b/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Templates/ProductList.cshtml @@ -1,4 +1,4 @@ -@model IEnumerable +@model IEnumerable