Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Update Resource pages to new design #314

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion Childrens-Social-Care-CPD/Contentful/EntityResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ public Type Resolve(string contentTypeId)
"linkCard" => typeof(LinkCard),
"linkListCard" => typeof(LinkListCard),
"pdfFileResource" => typeof(PdfFileResource),
"resource" => typeof(Resource),
"richTextBlock" => typeof(RichTextBlock),
"roleList" => typeof(RoleList),
"sideMenu" => typeof(SideMenu),
Expand Down
13 changes: 13 additions & 0 deletions Childrens-Social-Care-CPD/Contentful/Models/Content.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
using Contentful.Core.Models;
using Newtonsoft.Json;

namespace Childrens_Social_Care_CPD.Contentful.Models;

public static class ContentTypes
{
public const string Resource = "Resource";
}

public class Content : IContent
{
public string Id { get; set; }
public string ContentType { get; set; }
public string Title { get; set; }
public string ContentTitle { get; set; }
public string ContentSubtitle { get; set; }
Expand All @@ -14,4 +21,10 @@ public class Content : IContent
public SideMenu SideMenu { get; set; }
public List<IContent> Items { get; set; }
public RelatedContent RelatedContent { get; set; }

public List<ContentLink> Navigation { get; set; }

[JsonProperty("$metadata")]
public ContentfulMetadata Metadata { get; set; }
public SystemProperties Sys { get; set; }
}
20 changes: 0 additions & 20 deletions Childrens-Social-Care-CPD/Contentful/Models/Resource.cs

This file was deleted.

1 change: 0 additions & 1 deletion Childrens-Social-Care-CPD/Contentful/PartialsFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ public static string GetPartialFor(IContent item)
LinkCard => "_LinkCard",
LinkListCard => "_LinkListCard",
PdfFileResource => "_PdfFileResource",
Resource => "_Resource",
RichTextBlock => "_RichTextBlock",
RoleList => "_RoleList",
SideMenu => "_SideMenu",
Expand Down
17 changes: 9 additions & 8 deletions Childrens-Social-Care-CPD/Controllers/ContentController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,23 +45,24 @@ private async Task<Content> FetchPageContentAsync(string contentId, Cancellation
public async Task<IActionResult> Index(CancellationToken cancellationToken, string pageName = "home", bool preferenceSet = false)
{
pageName = pageName?.TrimEnd('/');
var pageContent = await FetchPageContentAsync(pageName, cancellationToken);
if (pageContent == null)
var content = await FetchPageContentAsync(pageName, cancellationToken);
if (content == null)
{
return NotFound();
}

var contextModel = new ContextModel(
Id: pageContent.Id,
Title: pageContent.Title,
Id: content.Id,
Title: content.Title,
PageName: pageName,
Category: pageContent.Category,
UseContainers: pageContent.SideMenu == null,
Category: content.Category,
UseContainers: content.SideMenu == null,
PreferenceSet: preferenceSet,
BackLink: pageContent.BackLink);
BackLink: content.BackLink);

ViewData["ContextModel"] = contextModel;
ViewData["StateModel"] = new StateModel();
return View(pageContent);

return View(content);
}
}
54 changes: 51 additions & 3 deletions Childrens-Social-Care-CPD/Controllers/ResourcesController.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
using Childrens_Social_Care_CPD.Configuration;
using Childrens_Social_Care_CPD.Contentful.Models;
using Childrens_Social_Care_CPD.Core.Resources;
using Childrens_Social_Care_CPD.DataAccess;
using Childrens_Social_Care_CPD.Models;
using Microsoft.AspNetCore.Mvc;
using Childrens_Social_Care_CPD.Extensions;
using System.Reflection;

namespace Childrens_Social_Care_CPD.Controllers;

Expand All @@ -18,7 +20,7 @@ public class ResourcesQuery
public int Page { get; set; } = 1;
public ResourceSortOrder SortOrder { get; set; }

public ResourcesQuery()
public ResourcesQuery()
{
Tags = Array.Empty<string>();
}
Expand All @@ -28,12 +30,14 @@ public class ResourcesController : Controller
{
private readonly IFeaturesConfig _featuresConfig;
private readonly IResourcesSearchStrategy _strategy;
private readonly IResourcesRepository _resourcesRepository;

public ResourcesController(IFeaturesConfig featuresConfig, IResourcesSearchStrategy strategy)
public ResourcesController(IFeaturesConfig featuresConfig, IResourcesSearchStrategy strategy, IResourcesRepository resourcesRepository)
{
ArgumentNullException.ThrowIfNull(strategy);
_featuresConfig = featuresConfig;
_strategy = strategy;
_resourcesRepository = resourcesRepository;
}

[Route("resources-learning")]
Expand All @@ -51,4 +55,48 @@ public async Task<IActionResult> Search([FromQuery] ResourcesQuery query, bool p
var viewModel = await _strategy.SearchAsync(query, cancellationToken);
return View(viewModel);
}

[Route("resources-learning/{*pagename:regex(^[[0-9a-z]](\\/?[[0-9a-z\\-]])*\\/?$)}")]
public async Task<IActionResult> Index(string pageName = "home", bool preferenceSet = false, CancellationToken cancellationToken = default)
{
if (!_featuresConfig.IsEnabled(Features.ResourcesAndLearning))
{
return NotFound();
}

pageName = $"resources-learning/{pageName?.TrimEnd('/')}";
(var content, var tags) = await _resourcesRepository.GetByIdAsync(pageName, cancellationToken: cancellationToken);
if (content == null)
{
return NotFound();
}

var properties = new Dictionary<string, string>(tags.ContentCollection.Items.First().ContentfulMetaData.Tags.Where(x => x.Name.StartsWith("Resource:")).Select(x =>
{
var property = x.Name[9..];
var tokens = property.Split('=');
return tokens.Length > 1
? KeyValuePair.Create(tokens[0].Trim(' '), tokens[1].Trim(' '))
: KeyValuePair.Create(property, string.Empty);
}))
{
{ "Published", content.Sys.CreatedAt?.ToString("dd MMMM yyyy") },
{ "Last updated", content.Sys.CreatedAt?.ToString("dd MMMM yyyy") }
};

var contextModel = new ContextModel(
Id: content.Id,
Title: content.Title,
PageName: pageName,
Category: content.Category,
UseContainers: content.SideMenu == null,
PreferenceSet: preferenceSet,
BackLink: content.BackLink);

ViewData["ContextModel"] = contextModel;
ViewData["StateModel"] = new StateModel();
ViewData["Properties"] = properties;

return View("Resource", content);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using Childrens_Social_Care_CPD.Controllers;
using Childrens_Social_Care_CPD.DataAccess;
using Childrens_Social_Care_CPD.Extensions;
using Childrens_Social_Care_CPD.GraphQL.Queries;
using Childrens_Social_Care_CPD.Models;

Expand Down Expand Up @@ -33,7 +32,7 @@ private static IEnumerable<string> SanitiseTags(IEnumerable<string> tags, HashSe

private static Tuple<int, int, int> CalculatePageStats(SearchResourcesByTags.ResponseType searchResults, int page)
{
var totalResults = searchResults?.ResourceCollection?.Total ?? 0;
var totalResults = searchResults?.ContentCollection?.Total ?? 0;
var totalPages = (int)Math.Ceiling((decimal)totalResults / PAGE_SIZE);

return Tuple.Create(totalResults, totalPages, Math.Min(page, totalPages));
Expand Down Expand Up @@ -75,7 +74,7 @@ public async Task<ResourcesListViewModel> SearchAsync(ResourcesQuery query, Canc

return new ResourcesListViewModel(
pageContent,
searchResults?.ResourceCollection,
searchResults?.ContentCollection,
tagInfos,
query.Tags,
(int)query.SortOrder,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ private IEnumerable<string> GetQueryTags(int[] tags)

private static Tuple<int, int, int> CalculatePageStats(SearchResourcesByTags.ResponseType searchResults, int page)
{
var totalResults = searchResults?.ResourceCollection?.Total ?? 0;
var totalResults = searchResults?.ContentCollection?.Total ?? 0;
var totalPages = (int)Math.Ceiling((decimal)totalResults / PAGE_SIZE);

return Tuple.Create(totalResults, totalPages, Math.Min(page, totalPages));
Expand Down Expand Up @@ -84,7 +84,7 @@ public async Task<ResourcesListViewModel> SearchAsync(ResourcesQuery query, Canc

return new ResourcesListViewModel(
pageContent,
searchResults?.ResourceCollection,
searchResults?.ContentCollection,
_tagInfos,
queryTags.Select(x => x.ToString()),
(int)query.SortOrder,
Expand Down
21 changes: 20 additions & 1 deletion Childrens-Social-Care-CPD/DataAccess/ResourcesRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
using Childrens_Social_Care_CPD.GraphQL.Queries;
using Contentful.Core.Search;
using GraphQL.Client.Abstractions.Websocket;
using System.Diagnostics;

namespace Childrens_Social_Care_CPD.DataAccess;

Expand All @@ -15,6 +14,7 @@ public interface IResourcesRepository
Task<Content> FetchRootPageAsync(CancellationToken cancellationToken = default);
Task<SearchResourcesByTags.ResponseType> FindByTagsAsync(IEnumerable<string> tags, int skip, int take, ResourceSortOrder resourceSortOrder, CancellationToken cancellationToken = default);
Task<IEnumerable<TagInfo>> GetSearchTagsAsync();
Task<Tuple<Content, GetContentTags.ResponseType>> GetByIdAsync(string id, int depth = 10, CancellationToken cancellationToken = default);
}

public class ResourcesRepository : IResourcesRepository
Expand Down Expand Up @@ -52,6 +52,25 @@ public Task<Content> FetchRootPageAsync(CancellationToken cancellationToken = de
.ContinueWith(x => x.Result.Data);
}

public async Task<Tuple<Content, GetContentTags.ResponseType>> GetByIdAsync(string id, int depth = 10, CancellationToken cancellationToken = default)
{
var queryBuilder = QueryBuilder<Content>.New
.ContentTypeIs("content")
.Include(depth)
.FieldEquals("fields.id", id);

var tagsTask = _gqlClient
.SendQueryAsync<GetContentTags.ResponseType>(GetContentTags.Query(id, _isPreview), cancellationToken)
.ContinueWith(x => x.Result.Data);

var contentTask = _cpdClient
.GetEntries(queryBuilder, cancellationToken)
.ContinueWith(x => x.Result.FirstOrDefault());

await Task.WhenAll(contentTask, tagsTask);
return Tuple.Create(contentTask.Result, tagsTask.Result);
}

public async Task<IEnumerable<TagInfo>> GetSearchTagsAsync()
{
var allTags = await _cpdClient.GetTags();
Expand Down
78 changes: 78 additions & 0 deletions Childrens-Social-Care-CPD/GraphQL/Queries/GetContentTags.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
using GraphQL;
using System.Text.Json.Serialization;

namespace Childrens_Social_Care_CPD.GraphQL.Queries;

public class GetContentTags
{
public static GraphQLRequest Query(string id, bool preview = false)
{
return new GraphQLRequest
{
Query = @"
query GetContentTags($id: String!, $preview: Boolean) {
contentCollection(where: {
id : $id,
}, preview: $preview) {
total
items {
id
sys {
publishedAt
firstPublishedAt
}
contentfulMetadata {
tags {
id
name
}
}
}
}
}",
OperationName = "GetContentTags",
Variables = new
{
id,
preview,
}
};
}

public class ResponseType
{
[JsonPropertyName("contentCollection")]
public ContentCollection ContentCollection { get; set; }
}

public class ContentCollection
{
[JsonPropertyName("items")]
public ICollection<ContentItem> Items { get; set; }
public int Total { get; set; }
}

public class ContentItem
{
public string Id { get; set; }
public PublishedInfo Sys { get; set; }
public MetaData ContentfulMetaData { get; set; }
}

public class PublishedInfo
{
public DateTime? PublishedAt { get; set; }
public DateTime? FirstPublishedAt { get; set; }
}

public class MetaData
{
public List<Tag> Tags { get; set; }
}

public class Tag
{
public string Id { get; set; }
public string Name { get; set; }
}
}
Loading
Loading