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("
");
+ foreach (IContent listItem in list!.Content)
+ {
+ var listItemValue = listItem as ListItem;
+ var listItemParagraph = listItemValue!.Content[0] as Paragraph;
+ var listItemText = listItemParagraph!.Content[0] as Text;
+ sb.Append($"
{listItemText!.Value}
");
+ }
+ 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";
+}
+
+