From d3f2f293eb79a315eca5b299c8c71f6d46f2c6ca Mon Sep 17 00:00:00 2001 From: Sam C <156680559+sam-c-dfe@users.noreply.github.com> Date: Tue, 23 Jan 2024 10:57:28 +0000 Subject: [PATCH] Added initial Contentful setup (#2) * Added initial contentful setup and dummy models & views to test the integration * Added a custom renderer for Unordered lists as a POC --- Dfe.EarlyYearsQualification.sln | 7 +++++ ...Dfe.EarlyYearsQualification.Content.csproj | 13 ++++++++ .../Entities/LandingPage.cs | 14 +++++++++ .../Renderers/UnorderedListRenderer.cs | 30 +++++++++++++++++++ .../Services/ContentfulContentService.cs | 26 ++++++++++++++++ .../Services/IContentService.cs | 8 +++++ .../Controllers/HomeController.cs | 20 ++++++++++++- .../Dfe.EarlyYearsQualification.Web.csproj | 8 +++++ .../Models/Content/LandingPageModel.cs | 10 +++++++ .../Program.cs | 6 ++++ .../Views/Home/Content.cshtml | 11 +++++++ .../appsettings.json | 7 +++++ 12 files changed, 159 insertions(+), 1 deletion(-) create mode 100644 src/Dfe.EarlyYearsQualification.Content/Dfe.EarlyYearsQualification.Content.csproj create mode 100644 src/Dfe.EarlyYearsQualification.Content/Entities/LandingPage.cs create mode 100644 src/Dfe.EarlyYearsQualification.Content/Renderers/UnorderedListRenderer.cs create mode 100644 src/Dfe.EarlyYearsQualification.Content/Services/ContentfulContentService.cs create mode 100644 src/Dfe.EarlyYearsQualification.Content/Services/IContentService.cs create mode 100644 src/Dfe.EarlyYearsQualification.Web/Models/Content/LandingPageModel.cs create mode 100644 src/Dfe.EarlyYearsQualification.Web/Views/Home/Content.cshtml diff --git a/Dfe.EarlyYearsQualification.sln b/Dfe.EarlyYearsQualification.sln index 6e00791a..5929c9e5 100644 --- a/Dfe.EarlyYearsQualification.sln +++ b/Dfe.EarlyYearsQualification.sln @@ -11,6 +11,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{CE49B579 EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dfe.EarlyYearsQualification.UnitTests", "tests\Dfe.EarlyYearsQualification.UnitTests\Dfe.EarlyYearsQualification.UnitTests.csproj", "{C989778A-398C-4092-97C4-4BCF5C233918}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dfe.EarlyYearsQualification.Content", "src\Dfe.EarlyYearsQualification.Content\Dfe.EarlyYearsQualification.Content.csproj", "{4DEA254F-34B6-47BA-A61A-83872A42BFD5}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -28,9 +30,14 @@ Global {C989778A-398C-4092-97C4-4BCF5C233918}.Debug|Any CPU.Build.0 = Debug|Any CPU {C989778A-398C-4092-97C4-4BCF5C233918}.Release|Any CPU.ActiveCfg = Release|Any CPU {C989778A-398C-4092-97C4-4BCF5C233918}.Release|Any CPU.Build.0 = Release|Any CPU + {4DEA254F-34B6-47BA-A61A-83872A42BFD5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4DEA254F-34B6-47BA-A61A-83872A42BFD5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4DEA254F-34B6-47BA-A61A-83872A42BFD5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4DEA254F-34B6-47BA-A61A-83872A42BFD5}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {73200EBC-285A-499F-9489-AD3AB7D07D52} = {5ED920E6-E35D-4D6A-8CBE-C76D493EDEE4} {C989778A-398C-4092-97C4-4BCF5C233918} = {CE49B579-76F7-4B4B-B61A-8059FE2F2BAB} + {4DEA254F-34B6-47BA-A61A-83872A42BFD5} = {5ED920E6-E35D-4D6A-8CBE-C76D493EDEE4} EndGlobalSection EndGlobal diff --git a/src/Dfe.EarlyYearsQualification.Content/Dfe.EarlyYearsQualification.Content.csproj b/src/Dfe.EarlyYearsQualification.Content/Dfe.EarlyYearsQualification.Content.csproj new file mode 100644 index 00000000..05682c32 --- /dev/null +++ b/src/Dfe.EarlyYearsQualification.Content/Dfe.EarlyYearsQualification.Content.csproj @@ -0,0 +1,13 @@ + + + + net8.0 + enable + enable + + + + + + + diff --git a/src/Dfe.EarlyYearsQualification.Content/Entities/LandingPage.cs b/src/Dfe.EarlyYearsQualification.Content/Entities/LandingPage.cs new file mode 100644 index 00000000..d3dccb3e --- /dev/null +++ b/src/Dfe.EarlyYearsQualification.Content/Entities/LandingPage.cs @@ -0,0 +1,14 @@ +using Contentful.Core.Models; + +namespace Dfe.EarlyYearsQualification.Content.Entities; + +public class LandingPage +{ + public string Header { get; set; } = string.Empty; + + public Document? ServiceIntroduction { get; set; } + + public string ServiceIntroductionHtml { get; set; } = string.Empty; + + public string StartButtonText { get; set; } = string.Empty; +} diff --git a/src/Dfe.EarlyYearsQualification.Content/Renderers/UnorderedListRenderer.cs b/src/Dfe.EarlyYearsQualification.Content/Renderers/UnorderedListRenderer.cs new file mode 100644 index 00000000..6c8a879f --- /dev/null +++ b/src/Dfe.EarlyYearsQualification.Content/Renderers/UnorderedListRenderer.cs @@ -0,0 +1,30 @@ +using System.Text; +using Contentful.Core.Models; + +namespace Dfe.EarlyYearsQualification.Content.Renderers; + +public class UnorderedListRenderer : IContentRenderer +{ + public int Order { get; set; } + + public Task RenderAsync(IContent content) + { + var list = content as List; + var sb = new StringBuilder(); + sb.Append(""); + return Task.FromResult(sb.ToString()); + } + + public bool SupportsContent(IContent content) + { + return content is List && (content as List)!.NodeType == "unordered-list"; + } +} diff --git a/src/Dfe.EarlyYearsQualification.Content/Services/ContentfulContentService.cs b/src/Dfe.EarlyYearsQualification.Content/Services/ContentfulContentService.cs new file mode 100644 index 00000000..a5959e6a --- /dev/null +++ b/src/Dfe.EarlyYearsQualification.Content/Services/ContentfulContentService.cs @@ -0,0 +1,26 @@ +using Contentful.Core; +using Contentful.Core.Models; +using Dfe.EarlyYearsQualification.Content.Entities; +using Dfe.EarlyYearsQualification.Content.Renderers; + +namespace Dfe.EarlyYearsQualification.Content.Services; + +public class ContentfulContentService : IContentService +{ + private readonly IContentfulClient _contentfulClient; + + public ContentfulContentService(IContentfulClient contentfulClient) + { + _contentfulClient = contentfulClient; + } + + public async Task GetLandingPage() + { + var landingPageEntries = await _contentfulClient.GetEntriesByType("landingPage"); + var landingPageContent = landingPageEntries.First(); + var htmlRenderer = new HtmlRenderer(); + htmlRenderer.AddRenderer(new UnorderedListRenderer() { Order = 10 }); + landingPageContent.ServiceIntroductionHtml = await htmlRenderer.ToHtml(landingPageContent.ServiceIntroduction); + return landingPageContent; + } +} diff --git a/src/Dfe.EarlyYearsQualification.Content/Services/IContentService.cs b/src/Dfe.EarlyYearsQualification.Content/Services/IContentService.cs new file mode 100644 index 00000000..b1a17c3a --- /dev/null +++ b/src/Dfe.EarlyYearsQualification.Content/Services/IContentService.cs @@ -0,0 +1,8 @@ +using Dfe.EarlyYearsQualification.Content.Entities; + +namespace Dfe.EarlyYearsQualification.Content.Services; + +public interface IContentService +{ + Task GetLandingPage(); +} diff --git a/src/Dfe.EarlyYearsQualification.Web/Controllers/HomeController.cs b/src/Dfe.EarlyYearsQualification.Web/Controllers/HomeController.cs index 6dffed65..2b34d9cc 100644 --- a/src/Dfe.EarlyYearsQualification.Web/Controllers/HomeController.cs +++ b/src/Dfe.EarlyYearsQualification.Web/Controllers/HomeController.cs @@ -1,23 +1,41 @@ using System.Diagnostics; using Microsoft.AspNetCore.Mvc; using Dfe.EarlyYearsQualification.Web.Models; +using Dfe.EarlyYearsQualification.Content.Services; +using Dfe.EarlyYearsQualification.Web.Models.Content; namespace Dfe.EarlyYearsQualification.Web.Controllers; public class HomeController : Controller { private readonly ILogger _logger; + private readonly IContentService _contentService; - public HomeController(ILogger logger) + public HomeController(ILogger logger, IContentService contentService) { _logger = logger; + _contentService = contentService; } + [HttpGet] public IActionResult Index() { return View(); } + [HttpGet] + public async Task Content() + { + var landingPageContent = await _contentService.GetLandingPage(); + var model = new LandingPageModel() + { + Header = landingPageContent.Header, + ServiceIntroduction = landingPageContent.ServiceIntroductionHtml, + StartButtonText = landingPageContent.StartButtonText + }; + return View(model); + } + [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] public IActionResult Error() { diff --git a/src/Dfe.EarlyYearsQualification.Web/Dfe.EarlyYearsQualification.Web.csproj b/src/Dfe.EarlyYearsQualification.Web/Dfe.EarlyYearsQualification.Web.csproj index 13d81270..0b8bdec2 100644 --- a/src/Dfe.EarlyYearsQualification.Web/Dfe.EarlyYearsQualification.Web.csproj +++ b/src/Dfe.EarlyYearsQualification.Web/Dfe.EarlyYearsQualification.Web.csproj @@ -6,4 +6,12 @@ enable + + + + + + + + diff --git a/src/Dfe.EarlyYearsQualification.Web/Models/Content/LandingPageModel.cs b/src/Dfe.EarlyYearsQualification.Web/Models/Content/LandingPageModel.cs new file mode 100644 index 00000000..0c51c9cc --- /dev/null +++ b/src/Dfe.EarlyYearsQualification.Web/Models/Content/LandingPageModel.cs @@ -0,0 +1,10 @@ +namespace Dfe.EarlyYearsQualification.Web.Models.Content; + +public class LandingPageModel +{ + public string Header { get; set; } = string.Empty; + + public string ServiceIntroduction { get; set; } = string.Empty; + + public string StartButtonText { get; set; } = string.Empty; +} diff --git a/src/Dfe.EarlyYearsQualification.Web/Program.cs b/src/Dfe.EarlyYearsQualification.Web/Program.cs index 4ac679a0..5950d4f8 100644 --- a/src/Dfe.EarlyYearsQualification.Web/Program.cs +++ b/src/Dfe.EarlyYearsQualification.Web/Program.cs @@ -1,8 +1,14 @@ +using Contentful.AspNetCore; +using Dfe.EarlyYearsQualification.Content.Services; + var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllersWithViews(); +builder.Services.AddContentful(builder.Configuration); +builder.Services.AddTransient(); + var app = builder.Build(); // Configure the HTTP request pipeline. diff --git a/src/Dfe.EarlyYearsQualification.Web/Views/Home/Content.cshtml b/src/Dfe.EarlyYearsQualification.Web/Views/Home/Content.cshtml new file mode 100644 index 00000000..6a04728c --- /dev/null +++ b/src/Dfe.EarlyYearsQualification.Web/Views/Home/Content.cshtml @@ -0,0 +1,11 @@ +@model Dfe.EarlyYearsQualification.Web.Models.Content.LandingPageModel + +@{ + ViewData["Title"] = "Content Page"; +} + +
+

@Model.Header

+ @Html.Raw(Model.ServiceIntroduction) + +
diff --git a/src/Dfe.EarlyYearsQualification.Web/appsettings.json b/src/Dfe.EarlyYearsQualification.Web/appsettings.json index 4d566948..6487b12e 100644 --- a/src/Dfe.EarlyYearsQualification.Web/appsettings.json +++ b/src/Dfe.EarlyYearsQualification.Web/appsettings.json @@ -5,5 +5,12 @@ "Microsoft.AspNetCore": "Warning" } }, + "ContentfulOptions": { + "DeliveryApiKey": "", + "PreviewApiKey": "", + "SpaceId": "", + "UsePreviewApi": false, + "MaxNumberOfRateLimitRetries": 1 + }, "AllowedHosts": "*" }