Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/feature/feedback-banner' into fe…
Browse files Browse the repository at this point in the history
…ature/feedback-banner
  • Loading branch information
jack-coggin committed Aug 15, 2024
2 parents 286c2dd + c682631 commit c4aa7af
Show file tree
Hide file tree
Showing 20 changed files with 676 additions and 173 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
:root {
--govuk-link-color: #1d70b8;
--govuk-black: #0b0c0c;
}

.dfe-vertical-nav__section-item {
list-style-type: none;
font-size: 1rem;
}

.dfe-vertical-nav__link {
display: block;
padding: 7px 30px 8px 10px;
border-left: 4px solid #b1b4b6;
text-decoration: none;
}

.dfe-vertical-nav__link--selected {
border-left: 4px solid var(--govuk-link-color);
background-color: #f3f2f1;
font-weight: bold;
}

.dfe-vertical-nav__link,
.dfe-vertical-nav__link--selected {
color: var(--govuk-link-color);

&:active, &:hover {
background-color: #fd0;
color: var(--govuk-black);
border-left: 4px solid var(--govuk-black);
font-weight: normal;
}
}

.dfe-vertical-nav__theme {
border-top: 1px solid var(--govuk-link-color);
padding-top: 5px;
margin-top: 10px;
margin-left: 0;
}
11 changes: 7 additions & 4 deletions src/Dfe.ContentSupport.Web/Controllers/ContentController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace Dfe.ContentSupport.Web.Controllers;

[Route("/content")]
[AllowAnonymous]
public class ContentController(IContentService contentService)
public class ContentController(IContentService contentService, ILayoutService layoutService)
: Controller
{
public async Task<IActionResult> Home()
Expand All @@ -28,14 +28,17 @@ public async Task<IActionResult> Home()
return View(defaultModel);
}

[HttpGet("{slug}")]
public async Task<IActionResult> Index(string slug, bool isPreview = false)
[HttpGet("{slug}/{page?}")]
public async Task<IActionResult> Index(string slug, string page = "", bool isPreview = false)
{
if (!ModelState.IsValid) return RedirectToAction("error");
if (string.IsNullOrEmpty(slug)) return RedirectToAction("error");

var resp = await contentService.GetContent(slug, isPreview);
if (resp is null) return RedirectToAction("error");

resp = layoutService.GenerateLayout(resp, Request, page);

return View("CsIndex", resp);
}

Expand All @@ -48,6 +51,6 @@ public IActionResult Privacy()
public IActionResult Error()
{
return View(new ErrorViewModel
{ RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
{ RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public static void InitCsDependencyInjection(this WebApplicationBuilder app)
app.Services.AddTransient<IModelMapper, ModelMapper>();
app.Services.AddTransient<IContentfulService, ContentfulService>();
app.Services.AddTransient<IContentService, ContentService>();
app.Services.AddTransient<ILayoutService, LayoutService>();

app.Services.Configure<CookiePolicyOptions>(options =>
{
Expand Down
4 changes: 4 additions & 0 deletions src/Dfe.ContentSupport.Web/Models/ContentBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,8 @@ namespace Dfe.ContentSupport.Web.Models;
public class ContentBase : ContentType
{
public string InternalName { get; set; } = null!;

public string? Title { get; set; } = null;

public string? Subtitle { get; set; } = null;
}
2 changes: 2 additions & 0 deletions src/Dfe.ContentSupport.Web/Models/Mapped/CsContentItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@ namespace Dfe.ContentSupport.Web.Models.Mapped;
public class CsContentItem
{
public string InternalName { get; set; } = null!;
public string? Title { get; set; } = null;
public string? Subtitle { get; set; } = null;
}
3 changes: 3 additions & 0 deletions src/Dfe.ContentSupport.Web/Models/Mapped/CsPage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@ public class CsPage
public string Slug { get; set; } = null!;
public bool IsSitemap { get; set; }
public bool HasCitation { get; set; }
public bool ShowVerticalNavigation { get; set; }
public bool HasBackToTop { get; set; }
public List<CsContentItem> Content { get; set; } = null!;
public DateTime? CreatedAt { get; init; }
public DateTime? UpdatedAt { get; init; }
public bool HasFeedbackBanner { get; set; }
public List<PageLink>? MenuItems { get; set; }

}
10 changes: 10 additions & 0 deletions src/Dfe.ContentSupport.Web/Models/Mapped/PageLink.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace Dfe.ContentSupport.Web.Models.Mapped
{
public class PageLink
{
public string? Title { get; set; } = null;
public string? Subtitle { get; set; } = null;
public required string Url { get; set; }
public required bool IsActive { get; set; }
}
}
2 changes: 1 addition & 1 deletion src/Dfe.ContentSupport.Web/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public static void Main(string[] args)

app.MapControllerRoute(
name: "slug",
pattern: "{slug}",
pattern: "{slug}/{page?}",
defaults: new { controller = "Content", action = "Index" });


Expand Down
10 changes: 10 additions & 0 deletions src/Dfe.ContentSupport.Web/Services/ILayoutService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using Dfe.ContentSupport.Web.Models.Mapped;

namespace Dfe.ContentSupport.Web.Services
{
public interface ILayoutService
{
CsPage GenerateLayout(CsPage page, HttpRequest request, string pageName);

}
}
85 changes: 85 additions & 0 deletions src/Dfe.ContentSupport.Web/Services/LayoutService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
using Dfe.ContentSupport.Web.Models;
using Dfe.ContentSupport.Web.Models.Mapped;


namespace Dfe.ContentSupport.Web.Services
{
public class LayoutService : ILayoutService
{
public CsPage GenerateLayout(CsPage page, HttpRequest request, string pageName)
{
if (!page.ShowVerticalNavigation) return page;

return new()
{
Heading = GetHeading(page, pageName),
MenuItems = GenerateVerticalNavigation(page, request, pageName),
Content = GetVisiblePageList(page, pageName),
UpdatedAt = page.UpdatedAt,
CreatedAt = page.CreatedAt,
HasCitation = page.HasCitation,
HasBackToTop = page.HasBackToTop,
IsSitemap = page.IsSitemap,
ShowVerticalNavigation = page.ShowVerticalNavigation,
Slug = page.Slug,
};
}


public Heading GetHeading(CsPage page, string pageName)
{
var selectedPage = page.Content.Find(o => o.InternalName == pageName);

if (selectedPage != null)
return new()
{
Title = selectedPage.Title ?? "",
Subtitle = selectedPage.Subtitle ?? ""
};


return new()
{
Title = page.Content[0]?.Title ?? "",
Subtitle = page.Content[0]?.Subtitle ?? ""
};
}


public List<PageLink> GenerateVerticalNavigation(CsPage page, HttpRequest request, string pageName)
{
var baseUrl = GetNavigationUrl(request);

var menuItems = page.Content.Select(o => new PageLink()
{
Title = o.Title ?? "",
Subtitle = o.Subtitle ?? "",
Url = $"{baseUrl}/{o.InternalName}",
IsActive = pageName == o.InternalName
}).ToList();

if (string.IsNullOrEmpty(pageName) && menuItems.Count > 0)
menuItems[0].IsActive = true;

return menuItems;
}


public List<CsContentItem> GetVisiblePageList(CsPage page, string pageName)
{
if (!string.IsNullOrEmpty(pageName))
return page.Content.Where(o => o.InternalName == pageName).ToList();


return page.Content.GetRange(0, 1);
}


public string GetNavigationUrl(HttpRequest request)
{
var splitUrl = request.Path.ToString().Split("/");
return string.Join("/", splitUrl.Take(3));
}

}
}
17 changes: 10 additions & 7 deletions src/Dfe.ContentSupport.Web/Services/ModelMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public CsPage MapToCsPage(ContentSupportPage incoming)
HasBackToTop = incoming.HasBackToTop,
HasFeedbackBanner = incoming.HasFeedbackBanner,
Content = MapEntriesToContent(incoming.Content),
ShowVerticalNavigation = incoming.ShowVerticalNavigation,
CreatedAt = incoming.Sys.CreatedAt,
UpdatedAt = incoming.Sys.UpdatedAt
};
Expand All @@ -41,18 +42,20 @@ private List<CsContentItem> MapEntriesToContent(List<Entry> entries)
public CsContentItem ConvertEntryToContentItem(Entry entry)
{
CsContentItem item = entry.RichText is not null
? MapRichTextContent(entry.RichText)!
: new CsContentItem { InternalName = entry.InternalName };
? MapRichTextContent(entry.RichText, entry)!
: new CsContentItem { InternalName = entry.InternalName, Title = entry.Title, Subtitle = entry.Subtitle };
return item;
}

public RichTextContentItem? MapRichTextContent(ContentItemBase? richText)
public RichTextContentItem? MapRichTextContent(ContentItemBase? richText, Entry entry)
{
if (richText is null) return null;
RichTextContentItem item =
new RichTextContentItem
{
InternalName = richText.InternalName,
InternalName = entry.InternalName,
Title = entry.Title,
Subtitle = entry.Subtitle,
NodeType = ConvertToRichTextNodeType(richText.NodeType),
Content = MapRichTextNodes(richText.Content),
};
Expand All @@ -62,7 +65,7 @@ public CsContentItem ConvertEntryToContentItem(Entry entry)
public List<RichTextContentItem> MapRichTextNodes(List<ContentItem> nodes)
{
return nodes.Select(node => MapContent(node) ?? new RichTextContentItem
{ NodeType = RichTextNodeType.Unknown, InternalName = node.InternalName }).ToList();
{ NodeType = RichTextNodeType.Unknown, InternalName = node.InternalName }).ToList();
}

public RichTextContentItem? MapContent(ContentItem contentItem)
Expand Down Expand Up @@ -102,7 +105,7 @@ public List<RichTextContentItem> MapRichTextNodes(List<ContentItem> nodes)
item = new EmbeddedEntry
{
JumpIdentifier = target.JumpIdentifier,
RichText = MapRichTextContent(target.RichText),
RichText = MapRichTextContent(target.RichText, target),
CustomComponent = GenerateCustomComponent(target)
};
break;
Expand Down Expand Up @@ -155,7 +158,7 @@ private CustomAccordion GenerateCustomAccordion(Target target)
return new CustomAccordion
{
InternalName = target.InternalName,
Body = MapRichTextContent(target.RichText),
Body = MapRichTextContent(target.RichText, target),
SummaryLine = target.SummaryLine,
Title = target.Title,
Accordions = target.Content.Select(GenerateCustomAccordion).ToList()
Expand Down
2 changes: 2 additions & 0 deletions src/Dfe.ContentSupport.Web/ViewModels/ContentSupportPage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,6 @@ public class ContentSupportPage : ContentBase
public bool HasCitation { get; init; }
public bool HasBackToTop { get; init; }
public bool HasFeedbackBanner { get; init; }
public bool ShowVerticalNavigation { get; init; }

}
21 changes: 21 additions & 0 deletions src/Dfe.ContentSupport.Web/Views/Content/CsIndex.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,34 @@
}

<div class="govuk-grid-row">

@if (Model.MenuItems is not null)
{
<div class="govuk-grid-column-one-quarter sticky">
<nav class="dfe-vertical-nav">
<div class="dfe-vertical-nav__section">
<ul class="dfe-vertical-nav__section">
@foreach (var menuItem in Model.MenuItems)
{
<li class="dfe-vertical-nav__section-item">
<a class="dfe-vertical-nav__link @(menuItem.IsActive ? "dfe-vertical-nav__section-item--current" : "")" href="@menuItem.Url">@(string.IsNullOrEmpty(menuItem.Subtitle) ? "" : $"{menuItem.Subtitle} : ") @menuItem.Title </a>
</li>
}
</ul>
</div>
</nav>
</div>
}

<div class="govuk-grid-column-three-quarters">

@foreach (var content in Model.Content)
{
<partial name="_Content" model="@content" />
}
</div>

<div class="govuk-grid-column-full">
@if (Model.HasCitation)
{
<partial name="_Citation" model="Model" />
Expand Down
2 changes: 1 addition & 1 deletion src/Dfe.ContentSupport.Web/Views/Shared/Error.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
{
<p class="govuk-body">
<strong>Request ID:</strong> <code>@Model.RequestId</code>
</p class="govuk-body">
</p>
}

<h3>Development Mode</h3>
Expand Down
Loading

0 comments on commit c4aa7af

Please sign in to comment.