diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 0749deea..1c92a603 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -17,7 +17,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v3 with: - dotnet-version: 7.0.x + dotnet-version: 8.0.x - name: Restore dependencies run: dotnet restore - name: Build diff --git a/.github/workflows/load-testing.yml b/.github/workflows/load-testing.yml index f1b201e6..f0ccefab 100644 --- a/.github/workflows/load-testing.yml +++ b/.github/workflows/load-testing.yml @@ -35,6 +35,7 @@ jobs: TF_VAR_cpd_gf_password: ${{secrets.TF_CPD_GF_PASSWORD}} TF_VAR_cpd_gf_plugins: ${{secrets.TF_VAR_CPD_GF_PLUGINS}} TF_VAR_cpd_gf_image_tag: ${{vars.TF_VAR_CPD_GF_IMAGE_TAG}} + TF_VAR_whitelist_ips: ${{vars.TF_VAR_WHITELIST_IPS}} TF_VAR_vcs_tag: ${{github.event.release.tag_name}} TF_WORKSPACE: Load-Test SITE_URL: https://20.107.65.156/ diff --git a/.github/workflows/terraform-destroy.yml b/.github/workflows/terraform-destroy.yml index e3171cc7..02bb72e2 100644 --- a/.github/workflows/terraform-destroy.yml +++ b/.github/workflows/terraform-destroy.yml @@ -46,6 +46,7 @@ jobs: TF_VAR_cpd_gf_password: ${{secrets.TF_CPD_GF_PASSWORD}} TF_VAR_cpd_gf_plugins: ${{secrets.TF_VAR_CPD_GF_PLUGINS}} TF_VAR_cpd_gf_image_tag: ${{vars.TF_VAR_CPD_GF_IMAGE_TAG}} + TF_VAR_whitelist_ips: ${{vars.TF_VAR_WHITELIST_IPS}} TF_VAR_vcs_tag: ${{github.event.release.tag_name}} TF_WORKSPACE: ${{inputs.workspace}} diff --git a/.github/workflows/terraform-plan.yml b/.github/workflows/terraform-plan.yml index f1cc828e..96aaa23d 100644 --- a/.github/workflows/terraform-plan.yml +++ b/.github/workflows/terraform-plan.yml @@ -49,6 +49,7 @@ jobs: TF_VAR_cpd_gf_password: ${{secrets.TF_CPD_GF_PASSWORD}} TF_VAR_cpd_gf_plugins: ${{secrets.TF_VAR_CPD_GF_PLUGINS}} TF_VAR_cpd_gf_image_tag: ${{vars.TF_VAR_CPD_GF_IMAGE_TAG}} + TF_VAR_whitelist_ips: ${{vars.TF_VAR_WHITELIST_IPS}} TF_VAR_vcs_tag: ${{github.event.release.tag_name}} TF_WORKSPACE: ${{inputs.workspace}} diff --git a/.github/workflows/terraform.yml b/.github/workflows/terraform.yml index cbcdad4a..8ba51cd5 100644 --- a/.github/workflows/terraform.yml +++ b/.github/workflows/terraform.yml @@ -49,6 +49,7 @@ jobs: TF_VAR_cpd_gf_password: ${{secrets.TF_CPD_GF_PASSWORD}} TF_VAR_cpd_gf_plugins: ${{secrets.TF_VAR_CPD_GF_PLUGINS}} TF_VAR_cpd_gf_image_tag: ${{vars.TF_VAR_CPD_GF_IMAGE_TAG}} + TF_VAR_whitelist_ips: ${{vars.TF_VAR_WHITELIST_IPS}} TF_VAR_vcs_tag: ${{github.event.release.tag_name}} TF_WORKSPACE: ${{inputs.workspace}} diff --git a/Childrens-Social-Care-CPD-Tests/AntiforgeryTokenController.cs b/Childrens-Social-Care-CPD-Tests/AntiforgeryTokenController.cs index a380c0c3..28527df1 100644 --- a/Childrens-Social-Care-CPD-Tests/AntiforgeryTokenController.cs +++ b/Childrens-Social-Care-CPD-Tests/AntiforgeryTokenController.cs @@ -42,15 +42,8 @@ public sealed class AntiforgeryTokenController : Controller [Route(GetUrl)] public IActionResult GetAntiforgeryTokens([FromServices] IAntiforgery antiforgery, [FromServices] IOptions options) { - if (antiforgery == null) - { - throw new ArgumentNullException(nameof(antiforgery)); - } - - if (options == null) - { - throw new ArgumentNullException(nameof(options)); - } + ArgumentNullException.ThrowIfNull(antiforgery); + ArgumentNullException.ThrowIfNull(options); AntiforgeryTokenSet tokens = antiforgery.GetTokens(HttpContext); diff --git a/Childrens-Social-Care-CPD-Tests/Childrens-Social-Care-CPD-Tests.csproj b/Childrens-Social-Care-CPD-Tests/Childrens-Social-Care-CPD-Tests.csproj index 1ef312b1..a2b07537 100644 --- a/Childrens-Social-Care-CPD-Tests/Childrens-Social-Care-CPD-Tests.csproj +++ b/Childrens-Social-Care-CPD-Tests/Childrens-Social-Care-CPD-Tests.csproj @@ -1,7 +1,7 @@  - net7.0 + net8.0 Childrens_Social_Care_CPD_Tests disable false diff --git a/Childrens-Social-Care-CPD-Tests/Configuration/ApplicationConfigurationTests.cs b/Childrens-Social-Care-CPD-Tests/Configuration/ApplicationConfigurationTests.cs index e344ec6b..e104d53d 100644 --- a/Childrens-Social-Care-CPD-Tests/Configuration/ApplicationConfigurationTests.cs +++ b/Childrens-Social-Care-CPD-Tests/Configuration/ApplicationConfigurationTests.cs @@ -1,5 +1,6 @@ using Childrens_Social_Care_CPD.Configuration; using Microsoft.Extensions.Configuration; +using NSubstitute.Extensions; using System; using System.Collections.Generic; @@ -15,6 +16,7 @@ public class ApplicationConfigurationTests public void Setup() { _configuration = Substitute.For(); + _configuration.ReturnsForAll((string)null); _sut = new ApplicationConfiguration(_configuration); } @@ -26,7 +28,7 @@ public void Returns_ContentfulGraphqlConnectionString_Value() _configuration["CPD_CONTENTFUL_ENVIRONMENT"].Returns("foo"); // act - var actual = _sut.ContentfulGraphqlConnectionString.Value; + var actual = _sut.ContentfulGraphqlConnectionString; // assert actual.Should().Be($"https://graphql.contentful.com/content/v1/spaces/foo/environments/foo"); @@ -39,7 +41,7 @@ public void Returns_ContentfulPreviewHost_Value() var value = "preview.contentful.com"; // act - var actual = _sut.ContentfulPreviewHost.Value; + var actual = _sut.ContentfulPreviewHost; // assert actual.Should().Be(value); @@ -50,7 +52,11 @@ public void Returns_ContentfulPreviewHost_Value() get { // Set values + yield return ("CPD_AZURE_DATA_PROTECTION_CONTAINER_NAME", (ApplicationConfiguration sut) => sut.AzureDataProtectionContainerName, "foo", "foo"); yield return ("CPD_AZURE_ENVIRONMENT", (ApplicationConfiguration sut) => sut.AzureEnvironment, "foo", "foo"); + yield return ("CPD_AZURE_MANAGED_IDENTITY_ID", (ApplicationConfiguration sut) => sut.AzureManagedIdentityId, "foo", "foo"); + yield return ("CPD_AZURE_STORAGE_ACCOUNT", (ApplicationConfiguration sut) => sut.AzureStorageAccount, "foo", "foo"); + yield return ("CPD_AZURE_STORAGE_ACCOUNT_URI_FORMAT_STRING", (ApplicationConfiguration sut) => sut.AzureStorageAccountUriFormatString, "foo", "foo"); yield return ("CPD_CLARITY", (ApplicationConfiguration sut) => sut.ClarityProjectId, "foo", "foo"); yield return ("CPD_DELIVERY_KEY", (ApplicationConfiguration sut) => sut.ContentfulDeliveryApiKey, "foo", "foo"); yield return ("CPD_CONTENTFUL_ENVIRONMENT", (ApplicationConfiguration sut) => sut.ContentfulEnvironment, "foo", "foo"); @@ -65,22 +71,27 @@ public void Returns_ContentfulPreviewHost_Value() yield return ("CPD_SEARCH_CLIENT_API_KEY", (ApplicationConfiguration sut) => sut.SearchApiKey, "foo", "foo"); yield return ("CPD_SEARCH_ENDPOINT", (ApplicationConfiguration sut) => sut.SearchEndpoint, "foo", "foo"); yield return ("CPD_SEARCH_INDEX_NAME", (ApplicationConfiguration sut) => sut.SearchIndexName, "foo", "foo"); + // Default values - yield return ("CPD_AZURE_ENVIRONMENT", (ApplicationConfiguration sut) => sut.AzureEnvironment, null, ""); - yield return ("CPD_CLARITY", (ApplicationConfiguration sut) => sut.ClarityProjectId, null, ""); - yield return ("CPD_DELIVERY_KEY", (ApplicationConfiguration sut) => sut.ContentfulDeliveryApiKey, null, ""); - yield return ("CPD_CONTENTFUL_ENVIRONMENT", (ApplicationConfiguration sut) => sut.ContentfulEnvironment, null, ""); - yield return ("CPD_PREVIEW_KEY", (ApplicationConfiguration sut) => sut.ContentfulPreviewId, null, ""); - yield return ("CPD_SPACE_ID", (ApplicationConfiguration sut) => sut.ContentfulSpaceId, null, ""); - yield return ("CPD_GOOGLEANALYTICSTAG", (ApplicationConfiguration sut) => sut.GoogleTagManagerKey, null, ""); - yield return ("CPD_INSTRUMENTATION_CONNECTIONSTRING", (ApplicationConfiguration sut) => sut.AppInsightsConnectionString, null, ""); - yield return ("VCS-REF", (ApplicationConfiguration sut) => sut.GitHash, null, ""); - yield return ("VCS-TAG", (ApplicationConfiguration sut) => sut.AppVersion, null, ""); + yield return ("CPD_AZURE_DATA_PROTECTION_CONTAINER_NAME", (ApplicationConfiguration sut) => sut.AzureDataProtectionContainerName, null, null); + yield return ("CPD_AZURE_ENVIRONMENT", (ApplicationConfiguration sut) => sut.AzureEnvironment, null, null); + yield return ("CPD_AZURE_MANAGED_IDENTITY_ID", (ApplicationConfiguration sut) => sut.AzureManagedIdentityId, null, null); + yield return ("CPD_AZURE_STORAGE_ACCOUNT", (ApplicationConfiguration sut) => sut.AzureStorageAccount, null, null); + yield return ("CPD_AZURE_STORAGE_ACCOUNT_URI_FORMAT_STRING", (ApplicationConfiguration sut) => sut.AzureStorageAccountUriFormatString, null, null); + yield return ("CPD_CLARITY", (ApplicationConfiguration sut) => sut.ClarityProjectId, null, null); + yield return ("CPD_DELIVERY_KEY", (ApplicationConfiguration sut) => sut.ContentfulDeliveryApiKey, null, null); + yield return ("CPD_CONTENTFUL_ENVIRONMENT", (ApplicationConfiguration sut) => sut.ContentfulEnvironment, null, null); + yield return ("CPD_PREVIEW_KEY", (ApplicationConfiguration sut) => sut.ContentfulPreviewId, null, null); + yield return ("CPD_SPACE_ID", (ApplicationConfiguration sut) => sut.ContentfulSpaceId, null, null); + yield return ("CPD_GOOGLEANALYTICSTAG", (ApplicationConfiguration sut) => sut.GoogleTagManagerKey, null, null); + yield return ("CPD_INSTRUMENTATION_CONNECTIONSTRING", (ApplicationConfiguration sut) => sut.AppInsightsConnectionString, null, null); + yield return ("VCS-REF", (ApplicationConfiguration sut) => sut.GitHash, null, null); + yield return ("VCS-TAG", (ApplicationConfiguration sut) => sut.AppVersion, null, null); yield return ("CPD_DISABLE_SECURE_COOKIES", (ApplicationConfiguration sut) => sut.DisableSecureCookies, null, false); yield return ("CPD_FEATURE_POLLING_INTERVAL", (ApplicationConfiguration sut) => sut.FeaturePollingInterval, null, 0); - yield return ("CPD_SEARCH_CLIENT_API_KEY", (ApplicationConfiguration sut) => sut.SearchApiKey, null, ""); - yield return ("CPD_SEARCH_ENDPOINT", (ApplicationConfiguration sut) => sut.SearchEndpoint, null, ""); - yield return ("CPD_SEARCH_INDEX_NAME", (ApplicationConfiguration sut) => sut.SearchIndexName, null, ""); + yield return ("CPD_SEARCH_CLIENT_API_KEY", (ApplicationConfiguration sut) => sut.SearchApiKey, null, null); + yield return ("CPD_SEARCH_ENDPOINT", (ApplicationConfiguration sut) => sut.SearchEndpoint, null, null); + yield return ("CPD_SEARCH_INDEX_NAME", (ApplicationConfiguration sut) => sut.SearchIndexName, null, null); } } @@ -89,11 +100,9 @@ public void Returns_AzureEnvironment_Value((string key, Func(); - _applicationConfiguration.AzureEnvironment.Value.Returns(ApplicationEnvironment.Development); + _applicationConfiguration.AzureEnvironment.Returns(ApplicationEnvironment.Development); } [Test] public void Required_Values_Are_Detected() { // arrange - _applicationConfiguration.AppVersion.Returns(new StringConfigSetting(() => "foo")); + _applicationConfiguration.AppVersion.Returns("foo"); // act var sut = new ConfigurationInformation(_applicationConfiguration); @@ -38,7 +35,7 @@ public void Required_Values_Are_Detected() public void Missing_Values_Are_Detected(string value) { // arrange - _applicationConfiguration.AppVersion.Returns(new StringConfigSetting(() => value)); + _applicationConfiguration.AppVersion.Returns(value); // act var sut = new ConfigurationInformation(_applicationConfiguration); @@ -53,7 +50,7 @@ public void Missing_Values_Are_Detected(string value) public void Extraneous_Values_Are_Detected() { // arrange - _applicationConfiguration.ClarityProjectId.Returns(new StringConfigSetting(() => "foo")); + _applicationConfiguration.ClarityProjectId.Returns("foo"); // act var sut = new ConfigurationInformation(_applicationConfiguration); @@ -80,8 +77,8 @@ public void Sensitive_Values_Are_Obfuscated() { // arrange var value = "sensitive value"; - _applicationConfiguration.AzureEnvironment.Returns(new StringConfigSetting(() => ApplicationEnvironment.Production)); - _applicationConfiguration.AppInsightsConnectionString.Returns(new StringConfigSetting(() => value)); + _applicationConfiguration.AzureEnvironment.Returns(ApplicationEnvironment.Production); + _applicationConfiguration.AppInsightsConnectionString.Returns(value); // act var sut = new ConfigurationInformation(_applicationConfiguration); diff --git a/Childrens-Social-Care-CPD-Tests/Configuration/ConfigurationSettingTests.cs b/Childrens-Social-Care-CPD-Tests/Configuration/ConfigurationSettingTests.cs deleted file mode 100644 index c0ea4605..00000000 --- a/Childrens-Social-Care-CPD-Tests/Configuration/ConfigurationSettingTests.cs +++ /dev/null @@ -1,103 +0,0 @@ -using Childrens_Social_Care_CPD.Configuration; -using FluentAssertions; -using NUnit.Framework; - -namespace Childrens_Social_Care_CPD_Tests.Configuration; - -public class ConfigurationSettingTests -{ - [Test] - public void Default_Value_Is_Set() - { - // arrange - var defaultValue = new object(); - - // act - var sut = new ConfigurationSetting(() => " ", x => new object(), defaultValue); - - // assert - sut.Value.Should().Be(defaultValue); - } - - [Test] - public void Value_Calls_Getter() - { - // arrange - var input = "x"; - var value = new object(); - var passedValue = string.Empty; - - // act - var sut = new ConfigurationSetting(() => input, x => { - passedValue = input; - return value; - }); - - // accessing Value causes the parser to be called - sut.Value.Should().NotBeNull(); - - // assert - passedValue.Should().BeEquivalentTo(input); - } - - [Test] - public void Value_Calls_Parser() - { - // arrange - var value = new object(); - - // act - var sut = new ConfigurationSetting(() => "x", x => value); - - // assert - sut.Value.Should().Be(value); - } - - [TestCase(null)] - [TestCase("")] - [TestCase(" ")] - public void IsSet_Returns_False_For_Invalid_Input(string value) - { - // act - var sut = new ConfigurationSetting(() => value, x => new object()); - - // assert - sut.IsSet.Should().BeFalse(); - } - - [Test] - public void IsSet_Returns_True_For_Valid_Input() - { - // act - var sut = new ConfigurationSetting(() => "x", x => new object()); - - // assert - sut.IsSet.Should().BeTrue(); - } - - [Test] - public void ConfigurationSetting_ToString_Returns_Value_Representation() - { - // arrange - var value = new object(); - - // act - var sut = new ConfigurationSetting(() => "x", x => "foo"); - - // assert - sut.ToString().Should().Be("foo"); - } - - [Test] - public void ConfigurationSetting_ToString_Should_Not_Return_Null() - { - // arrange - var value = new object(); - - // act - var sut = new ConfigurationSetting(() => "x", x => null); - - // assert - sut.ToString().Should().Be(string.Empty); - } -} \ No newline at end of file diff --git a/Childrens-Social-Care-CPD-Tests/Configuration/FeaturesConfigBackgroundServiceTests.cs b/Childrens-Social-Care-CPD-Tests/Configuration/Features/FeaturesConfigBackgroundServiceTests.cs similarity index 89% rename from Childrens-Social-Care-CPD-Tests/Configuration/FeaturesConfigBackgroundServiceTests.cs rename to Childrens-Social-Care-CPD-Tests/Configuration/Features/FeaturesConfigBackgroundServiceTests.cs index 29ac884e..a78371c7 100644 --- a/Childrens-Social-Care-CPD-Tests/Configuration/FeaturesConfigBackgroundServiceTests.cs +++ b/Childrens-Social-Care-CPD-Tests/Configuration/Features/FeaturesConfigBackgroundServiceTests.cs @@ -1,10 +1,9 @@ using Childrens_Social_Care_CPD.Configuration; +using Childrens_Social_Care_CPD.Configuration.Features; using Microsoft.Extensions.Logging; -using NSubstitute; -using NUnit.Framework; using System.Threading; using System.Threading.Tasks; -namespace Childrens_Social_Care_CPD_Tests.Configuration; +namespace Childrens_Social_Care_CPD_Tests.Configuration.Features; public class FeaturesConfigBackgroundServiceTests { @@ -26,7 +25,7 @@ public void Setup() public async Task Calls_Updater_At_Specified_Interval(int interval) { // arrange - _applicationConfiguration.FeaturePollingInterval.Value.Returns(interval); + _applicationConfiguration.FeaturePollingInterval.Returns(interval); var featuresConfigBackgroundService = new FeaturesConfigBackgroundService( _logger, _applicationConfiguration, @@ -50,7 +49,7 @@ public async Task Calls_Updater_At_Specified_Interval(int interval) public async Task Returns_If_Interval_Is_Zero() { // arrange - _applicationConfiguration.FeaturePollingInterval.Value.Returns(0); + _applicationConfiguration.FeaturePollingInterval.Returns(0); var featuresConfigBackgroundService = new FeaturesConfigBackgroundService( _logger, _applicationConfiguration, diff --git a/Childrens-Social-Care-CPD-Tests/Configuration/FeaturesConfigTests.cs b/Childrens-Social-Care-CPD-Tests/Configuration/Features/FeaturesConfigTests.cs similarity index 91% rename from Childrens-Social-Care-CPD-Tests/Configuration/FeaturesConfigTests.cs rename to Childrens-Social-Care-CPD-Tests/Configuration/Features/FeaturesConfigTests.cs index 243bc353..06f6f0fc 100644 --- a/Childrens-Social-Care-CPD-Tests/Configuration/FeaturesConfigTests.cs +++ b/Childrens-Social-Care-CPD-Tests/Configuration/Features/FeaturesConfigTests.cs @@ -1,6 +1,4 @@ -using Childrens_Social_Care_CPD.Configuration; -using FluentAssertions; -using NUnit.Framework; +using Childrens_Social_Care_CPD.Configuration.Features; namespace Childrens_Social_Care_CPD_Tests.Configuration; diff --git a/Childrens-Social-Care-CPD-Tests/Configuration/FeaturesConfigUpdaterTests.cs b/Childrens-Social-Care-CPD-Tests/Configuration/Features/FeaturesConfigUpdaterTests.cs similarity index 98% rename from Childrens-Social-Care-CPD-Tests/Configuration/FeaturesConfigUpdaterTests.cs rename to Childrens-Social-Care-CPD-Tests/Configuration/Features/FeaturesConfigUpdaterTests.cs index c21a61a4..d311593f 100644 --- a/Childrens-Social-Care-CPD-Tests/Configuration/FeaturesConfigUpdaterTests.cs +++ b/Childrens-Social-Care-CPD-Tests/Configuration/Features/FeaturesConfigUpdaterTests.cs @@ -10,6 +10,7 @@ using System.Threading.Tasks; using System.Threading; using NSubstitute.ExceptionExtensions; +using Childrens_Social_Care_CPD.Configuration.Features; namespace Childrens_Social_Care_CPD_Tests.Configuration; diff --git a/Childrens-Social-Care-CPD-Tests/ConfigurationHealthCheckTests.cs b/Childrens-Social-Care-CPD-Tests/ConfigurationHealthCheckTests.cs index 1ac8172b..9400ff33 100644 --- a/Childrens-Social-Care-CPD-Tests/ConfigurationHealthCheckTests.cs +++ b/Childrens-Social-Care-CPD-Tests/ConfigurationHealthCheckTests.cs @@ -22,7 +22,7 @@ public async Task Passes_When_All_Values_Set_And_Cookies_Are_Secured() { // arrange _applicationConfiguration.SetAllValid(); - _applicationConfiguration._featurePollingInterval = "0"; + _applicationConfiguration._featurePollingInterval = 0; var sut = new ConfigurationHealthCheck(_logger, _applicationConfiguration); // act @@ -37,7 +37,7 @@ public async Task Fails_When_Disable_Cookies_Is_True() { // arrange _applicationConfiguration.SetAllValid(); - _applicationConfiguration._disableSecureCookies = "true"; + _applicationConfiguration._disableSecureCookies = true; var sut = new ConfigurationHealthCheck(_logger, _applicationConfiguration); // act diff --git a/Childrens-Social-Care-CPD-Tests/Controllers/ApplicationControllerTests.cs b/Childrens-Social-Care-CPD-Tests/Controllers/ApplicationControllerTests.cs index 56be41a4..6ad25b4f 100644 --- a/Childrens-Social-Care-CPD-Tests/Controllers/ApplicationControllerTests.cs +++ b/Childrens-Social-Care-CPD-Tests/Controllers/ApplicationControllerTests.cs @@ -1,15 +1,9 @@ using Childrens_Social_Care_CPD.Configuration; using Childrens_Social_Care_CPD.Controllers; using Childrens_Social_Care_CPD.Models; -using FluentAssertions; -using NSubstitute; -using NUnit.Framework; -using Childrens_Social_Care_CPD_Tests.Configuration; using Microsoft.AspNetCore.Mvc; -using Childrens_Social_Care_CPD.Contentful; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc.ViewFeatures; -using System.Net; using System.Net.Mime; using Microsoft.Extensions.Primitives; @@ -32,7 +26,7 @@ public void ApplicationController_Includes_Contentful_Environment() { // arrange var value = "foo"; - _applicationConfiguration.ContentfulEnvironment.Value.Returns(value); + _applicationConfiguration.ContentfulEnvironment.Returns(value); // act var actual = _controller.AppInfo().Value as ApplicationInfo; @@ -46,7 +40,7 @@ public void ApplicationController_Includes_Azure_Environment() { // arrange var value = "foo"; - _applicationConfiguration.AzureEnvironment.Value.Returns(value); + _applicationConfiguration.AzureEnvironment.Returns(value); // act var actual = _controller.AppInfo().Value as ApplicationInfo; @@ -60,7 +54,7 @@ public void ApplicationController_Includes_Git_Hash() { // arrange var value = "foo"; - _applicationConfiguration.GitHash.Value.Returns(value); + _applicationConfiguration.GitHash.Returns(value); // act var actual = _controller.AppInfo().Value as ApplicationInfo; @@ -74,7 +68,7 @@ public void ApplicationController_Includes_App_Version() { // arrange var value = "foo"; - _applicationConfiguration.AppVersion.Value.Returns(value); + _applicationConfiguration.AppVersion.Returns(value); // act var actual = _controller.AppInfo().Value as ApplicationInfo; diff --git a/Childrens-Social-Care-CPD-Tests/Controllers/CookieController.ServerTests.cs b/Childrens-Social-Care-CPD-Tests/Controllers/CookieController.ServerTests.cs index 38c6756a..4d31b663 100644 --- a/Childrens-Social-Care-CPD-Tests/Controllers/CookieController.ServerTests.cs +++ b/Childrens-Social-Care-CPD-Tests/Controllers/CookieController.ServerTests.cs @@ -33,15 +33,15 @@ public async Task SetPreferences_Sets_Cookie(string consentValue) { // arrange var antiforgeryTokens = await _application.GetAntiforgeryTokensAsync(); - var cookies = new CookieContainerHandler(); + using var cookies = new CookieContainerHandler(); cookies.Container.Add(_application.Server.BaseAddress, new Cookie(antiforgeryTokens.CookieName, antiforgeryTokens.CookieValue)); - var client = _application.CreateDefaultClient(cookies); + using var client = _application.CreateDefaultClient(cookies); - var formContent = new FormUrlEncodedContent(new Dictionary { ["consentValue"] = consentValue }); + using var formContent = new FormUrlEncodedContent(new Dictionary { ["consentValue"] = consentValue }); formContent.Headers.Add(antiforgeryTokens.HeaderName, antiforgeryTokens.RequestToken); // act - var response = await client.PostAsync(SetPrefencesUrl, formContent); + using var response = await client.PostAsync(SetPrefencesUrl, formContent); // assert response.StatusCode.Should().Be(HttpStatusCode.Redirect); @@ -56,15 +56,15 @@ public async Task SetPreferences_Clear_Cookie(string consentValue) { // arrange var antiforgeryTokens = await _application.GetAntiforgeryTokensAsync(); - var cookies = new CookieContainerHandler(); + using var cookies = new CookieContainerHandler(); cookies.Container.Add(_application.Server.BaseAddress, new Cookie(antiforgeryTokens.CookieName, antiforgeryTokens.CookieValue)); - var client = _application.CreateDefaultClient(cookies); + using var client = _application.CreateDefaultClient(cookies); - var formContent = new FormUrlEncodedContent(new Dictionary { ["consentValue"] = consentValue }); + using var formContent = new FormUrlEncodedContent(new Dictionary { ["consentValue"] = consentValue }); formContent.Headers.Add(antiforgeryTokens.HeaderName, antiforgeryTokens.RequestToken); // act - var response = await client.PostAsync(SetPrefencesUrl, formContent); + using var response = await client.PostAsync(SetPrefencesUrl, formContent); // assert response.StatusCode.Should().Be(HttpStatusCode.Redirect); diff --git a/Childrens-Social-Care-CPD-Tests/Controllers/CookieControllerTests.cs b/Childrens-Social-Care-CPD-Tests/Controllers/CookieControllerTests.cs index bd3d8815..842dabbb 100644 --- a/Childrens-Social-Care-CPD-Tests/Controllers/CookieControllerTests.cs +++ b/Childrens-Social-Care-CPD-Tests/Controllers/CookieControllerTests.cs @@ -3,12 +3,9 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc.ViewFeatures; using Microsoft.AspNetCore.Mvc; -using NSubstitute; -using NUnit.Framework; using Childrens_Social_Care_CPD.Contentful.Models; using Contentful.Core.Models; using Contentful.Core.Search; -using FluentAssertions; using System.Collections.Generic; using System.Threading.Tasks; using Childrens_Social_Care_CPD.Models; @@ -64,7 +61,9 @@ public void SetUp() _contentfulClient = Substitute.For(); - _cookieController = new CookieController(_contentfulClient, new CookieHelper(new ApplicationConfiguration(Substitute.For()))) + var configuration = Substitute.For(); + configuration.ReturnsForAll((string)null); + _cookieController = new CookieController(_contentfulClient, new CookieHelper(new ApplicationConfiguration(configuration))) { ControllerContext = controllerContext, TempData = Substitute.For() diff --git a/Childrens-Social-Care-CPD-Tests/Controllers/FeedbackControllerTests.cs b/Childrens-Social-Care-CPD-Tests/Controllers/FeedbackControllerTests.cs index e73c1715..c9671cef 100644 --- a/Childrens-Social-Care-CPD-Tests/Controllers/FeedbackControllerTests.cs +++ b/Childrens-Social-Care-CPD-Tests/Controllers/FeedbackControllerTests.cs @@ -1,4 +1,5 @@ using Childrens_Social_Care_CPD.Configuration; +using Childrens_Social_Care_CPD.Configuration.Features; using Childrens_Social_Care_CPD.Contentful; using Childrens_Social_Care_CPD.Contentful.Models; using Childrens_Social_Care_CPD.Controllers; diff --git a/Childrens-Social-Care-CPD-Tests/Controllers/ResourcesControllerTests.cs b/Childrens-Social-Care-CPD-Tests/Controllers/ResourcesControllerTests.cs index b8885835..77b7704a 100644 --- a/Childrens-Social-Care-CPD-Tests/Controllers/ResourcesControllerTests.cs +++ b/Childrens-Social-Care-CPD-Tests/Controllers/ResourcesControllerTests.cs @@ -1,4 +1,5 @@ using Childrens_Social_Care_CPD.Configuration; +using Childrens_Social_Care_CPD.Configuration.Features; using Childrens_Social_Care_CPD.Contentful.Models; using Childrens_Social_Care_CPD.Controllers; using Childrens_Social_Care_CPD.DataAccess; diff --git a/Childrens-Social-Care-CPD-Tests/Controllers/SearchResourcesControllerTests.cs b/Childrens-Social-Care-CPD-Tests/Controllers/SearchResourcesControllerTests.cs index 73dbcc4d..7e365cfa 100644 --- a/Childrens-Social-Care-CPD-Tests/Controllers/SearchResourcesControllerTests.cs +++ b/Childrens-Social-Care-CPD-Tests/Controllers/SearchResourcesControllerTests.cs @@ -1,4 +1,5 @@ using Childrens_Social_Care_CPD.Configuration; +using Childrens_Social_Care_CPD.Configuration.Features; using Childrens_Social_Care_CPD.Controllers; using Childrens_Social_Care_CPD.Models; using Childrens_Social_Care_CPD.Search; @@ -15,7 +16,6 @@ private class MockSearchResultsVMFactory : ISearchResultsVMFactory public Task GetSearchModel(SearchRequestModel query, int pageSize, string searchRoute, CancellationToken cancellationToken) { return Task.FromResult(new ResourceSearchResultsViewModel( - null, string.Empty, 0,0,0,0,0, null, diff --git a/Childrens-Social-Care-CPD-Tests/CookieHelperTests.cs b/Childrens-Social-Care-CPD-Tests/CookieHelperTests.cs index 04f4dc28..6c458059 100644 --- a/Childrens-Social-Care-CPD-Tests/CookieHelperTests.cs +++ b/Childrens-Social-Care-CPD-Tests/CookieHelperTests.cs @@ -87,7 +87,7 @@ public void GetRequestAnalyticsCookieState(string cookieValue, AnalyticsConsentS public void Disables_Secure_Cookies_On_Config() { // arrange - _applicationConfiguration.DisableSecureCookies.Returns(new BooleanConfigSetting(() => "false")); + _applicationConfiguration.DisableSecureCookies.Returns(false); var httpContext = Substitute.For(); CookieOptions cookieOptions = null; httpContext.Response.Cookies.Append(CookieHelper.ANALYTICSCOOKIENAME, CookieHelper.ANALYTICSCOOKIEACCEPTED, Arg.Do(x => cookieOptions = x)); diff --git a/Childrens-Social-Care-CPD-Tests/DataAccess/ResourcesRepositoryTests.cs b/Childrens-Social-Care-CPD-Tests/DataAccess/ResourcesRepositoryTests.cs index be8a5178..dcc08384 100644 --- a/Childrens-Social-Care-CPD-Tests/DataAccess/ResourcesRepositoryTests.cs +++ b/Childrens-Social-Care-CPD-Tests/DataAccess/ResourcesRepositoryTests.cs @@ -44,8 +44,8 @@ public void Setup() _gqlClient = Substitute.For(); // By default we want the preview flag set to false - _applicationConfiguration.AzureEnvironment.Returns(new StringConfigSetting(() => ApplicationEnvironment.Development)); - _applicationConfiguration.ContentfulEnvironment.Returns(new StringConfigSetting(() => ApplicationEnvironment.Development)); + _applicationConfiguration.AzureEnvironment.Returns(ApplicationEnvironment.Development); + _applicationConfiguration.ContentfulEnvironment.Returns(ApplicationEnvironment.Development); } [Test] @@ -99,7 +99,7 @@ public async Task FindByTagsAsync_Returns_Results() Total = 1, Items = new Collection { - new SearchResourcesByTags.SearchResult() + new() } } }; @@ -176,7 +176,7 @@ public async Task FindByTagsAsync_Preview_Flag_Is_False_By_Default() public async Task FindByTagsAsync_Sets_Preview_Flag() { // arrange - _applicationConfiguration.ContentfulEnvironment.Returns(new StringConfigSetting(() => ApplicationEnvironment.PreProduction)); + _applicationConfiguration.ContentfulEnvironment.Returns(ApplicationEnvironment.PreProduction); var response = Substitute.For>(); response.Data = new SearchResourcesByTags.ResponseType(); @@ -199,8 +199,8 @@ public async Task GetSearchTagsAsync_Strips_Ungrouped_Tags() // arrange var tags = new List { - new ContentTag { Name = "Foo", SystemProperties = new SystemProperties { Id = "foo" } }, - new ContentTag { Name = "Topic: Foo", SystemProperties = new SystemProperties { Id = "topicFoo" } }, + new() { Name = "Foo", SystemProperties = new SystemProperties { Id = "foo" } }, + new() { Name = "Topic: Foo", SystemProperties = new SystemProperties { Id = "topicFoo" } }, }; _contentfulClient.GetTags().Returns(tags); var sut = new ResourcesRepository(_applicationConfiguration, _contentfulClient, _gqlClient); @@ -218,7 +218,7 @@ public async Task GetSearchTagsAsync_Gets_Valid_Tags() // arrange var tags = new List { - new ContentTag { Name = "Topic: Foo", SystemProperties = new SystemProperties { Id = "topicFoo" } }, + new() { Name = "Topic: Foo", SystemProperties = new SystemProperties { Id = "topicFoo" } }, }; _contentfulClient.GetTags().Returns(tags); var sut = new ResourcesRepository(_applicationConfiguration, _contentfulClient, _gqlClient); @@ -237,8 +237,8 @@ public async Task GetSearchTagsAsync_Strips_Unwanted_Grouped_Tags() // arrange var tags = new List { - new ContentTag { Name = "Topic: Foo", SystemProperties = new SystemProperties { Id = "topicFoo" } }, - new ContentTag { Name = "Foo: Foo", SystemProperties = new SystemProperties { Id = "fooFoo" } }, + new() { Name = "Topic: Foo", SystemProperties = new SystemProperties { Id = "topicFoo" } }, + new() { Name = "Foo: Foo", SystemProperties = new SystemProperties { Id = "fooFoo" } }, }; _contentfulClient.GetTags().Returns(tags); var sut = new ResourcesRepository(_applicationConfiguration, _contentfulClient, _gqlClient); @@ -306,7 +306,7 @@ public async Task GetByIdAsync_Preview_Flag_Is_False_By_Default() public async Task GetByIdAsync_Sets_Preview_Flag() { // arrange - _applicationConfiguration.ContentfulEnvironment.Returns(new StringConfigSetting(() => ApplicationEnvironment.PreProduction)); + _applicationConfiguration.ContentfulEnvironment.Returns(ApplicationEnvironment.PreProduction); var collection = new ContentfulCollection { @@ -334,7 +334,7 @@ public async Task GetByIdAsync_Sets_Preview_Flag() public async Task GetByIdAsync_Returns_Data() { // arrange - _applicationConfiguration.ContentfulEnvironment.Returns(new StringConfigSetting(() => ApplicationEnvironment.PreProduction)); + _applicationConfiguration.ContentfulEnvironment.Returns(ApplicationEnvironment.PreProduction); var content = new Content(); var collection = new ContentfulCollection diff --git a/Childrens-Social-Care-CPD-Tests/GlobalUsings.cs b/Childrens-Social-Care-CPD-Tests/GlobalUsings.cs index 972843f1..59ef3c18 100644 --- a/Childrens-Social-Care-CPD-Tests/GlobalUsings.cs +++ b/Childrens-Social-Care-CPD-Tests/GlobalUsings.cs @@ -1,3 +1,4 @@ global using FluentAssertions; global using NSubstitute; +global using NSubstitute.Extensions; global using NUnit.Framework; \ No newline at end of file diff --git a/Childrens-Social-Care-CPD-Tests/MockApplicationConfiguration.cs b/Childrens-Social-Care-CPD-Tests/MockApplicationConfiguration.cs index b6eac0e7..171d01a0 100644 --- a/Childrens-Social-Care-CPD-Tests/MockApplicationConfiguration.cs +++ b/Childrens-Social-Care-CPD-Tests/MockApplicationConfiguration.cs @@ -14,31 +14,40 @@ public class MockApplicationConfiguration : IApplicationConfiguration public string _contentfulPreviewHost = null; public string _contentfulPreviewId = null; public string _contentfulSpaceId = null; - public string _disableSecureCookies = null; - public string _featurePollingInterval = null; + public bool _disableSecureCookies = false; + public int _featurePollingInterval = 0; public string _gitHash = null; public string _googleTagManagerKey = null; public string _searchApiKey = null; public string _searchEndpoint = null; public string _searchIndexName = null; + public string _azureDataProtectionContainerName = null; + public string _azureManagedIdentityId = null; + public string _azureStorageAccount = null; + public string _azureStorageAccountUriFormatString = null; - public IConfigurationSetting AppInsightsConnectionString => new StringConfigSetting(() => _appInsightsConnectionString); - public IConfigurationSetting AppVersion => new StringConfigSetting(() => _appVersion); - public IConfigurationSetting AzureEnvironment => new StringConfigSetting(() => _azureEnvironment); - public IConfigurationSetting ClarityProjectId => new StringConfigSetting(() => _clarityProjectId); - public IConfigurationSetting ContentfulDeliveryApiKey => new StringConfigSetting(() => _contentfulDeliveryApiKey); - public IConfigurationSetting ContentfulEnvironment => new StringConfigSetting(() => _contentfulEnvironment); - public IConfigurationSetting ContentfulGraphqlConnectionString => new StringConfigSetting(() => _contentfulGraphqlConnectionString); - public IConfigurationSetting ContentfulPreviewHost => new StringConfigSetting(() => _contentfulPreviewHost); - public IConfigurationSetting ContentfulPreviewId => new StringConfigSetting(() => _contentfulPreviewId); - public IConfigurationSetting ContentfulSpaceId => new StringConfigSetting(() => _contentfulSpaceId); - public IConfigurationSetting DisableSecureCookies => new BooleanConfigSetting(() => _disableSecureCookies); - public IConfigurationSetting FeaturePollingInterval => new IntegerConfigSetting(() => _featurePollingInterval); - public IConfigurationSetting GitHash => new StringConfigSetting(() => _gitHash); - public IConfigurationSetting GoogleTagManagerKey => new StringConfigSetting(() => _googleTagManagerKey); - public IConfigurationSetting SearchApiKey => new StringConfigSetting(() => _searchApiKey); - public IConfigurationSetting SearchEndpoint => new StringConfigSetting(() => _searchEndpoint); - public IConfigurationSetting SearchIndexName => new StringConfigSetting(() => _searchIndexName); + public string AppInsightsConnectionString => _appInsightsConnectionString; + public string AppVersion => _appVersion; + public string AzureEnvironment => _azureEnvironment; + public string ClarityProjectId => _clarityProjectId; + public string ContentfulDeliveryApiKey => _contentfulDeliveryApiKey; + public string ContentfulEnvironment => _contentfulEnvironment; + public string ContentfulGraphqlConnectionString => _contentfulGraphqlConnectionString; + public string ContentfulPreviewHost => _contentfulPreviewHost; + public string ContentfulPreviewId => _contentfulPreviewId; + public string ContentfulSpaceId => _contentfulSpaceId; + public bool DisableSecureCookies => _disableSecureCookies; + public int FeaturePollingInterval => _featurePollingInterval; + public string GitHash => _gitHash; + public string GoogleTagManagerKey => _googleTagManagerKey; + public string SearchApiKey => _searchApiKey; + public string SearchEndpoint => _searchEndpoint; + public string SearchIndexName => _searchIndexName; + + public string AzureDataProtectionContainerName => _azureDataProtectionContainerName; + public string AzureManagedIdentityId => _azureManagedIdentityId; + public string AzureStorageAccount => _azureStorageAccount; + public string AzureStorageAccountUriFormatString => _azureStorageAccountUriFormatString; public void SetAllValid(string value = "foo") { @@ -52,12 +61,16 @@ public void SetAllValid(string value = "foo") _contentfulPreviewHost = value; _contentfulPreviewId = value; _contentfulSpaceId = value; - _disableSecureCookies = "false"; - _featurePollingInterval = "0"; + _disableSecureCookies = false; + _featurePollingInterval = 0; _gitHash = value; _googleTagManagerKey = value; _searchApiKey = value; _searchEndpoint = value; _searchIndexName = value; + _azureDataProtectionContainerName = value; + _azureManagedIdentityId = value; + _azureStorageAccount = value; + _azureStorageAccountUriFormatString = value; } } diff --git a/Childrens-Social-Care-CPD-Tests/Search/SearchResultsVMFactoryTests.cs b/Childrens-Social-Care-CPD-Tests/Search/SearchResultsVMFactoryTests.cs index cccdd154..6fc9c108 100644 --- a/Childrens-Social-Care-CPD-Tests/Search/SearchResultsVMFactoryTests.cs +++ b/Childrens-Social-Care-CPD-Tests/Search/SearchResultsVMFactoryTests.cs @@ -122,30 +122,6 @@ public async Task GetSearchModel_Model_Should_Receive_SearchResults() result.SearchResults.Should().HaveCount(count); } - [Test] - public async Task GetSearchModel_Model_Should_Receive_PageContent() - { - // arrange - var content = new Content(); - _resourcesRepository.GetSearchTagsAsync(Arg.Any()).Returns(Array.Empty()); - _resourcesRepository.FetchRootPageAsync().Returns(Task.FromResult(content)); - - _searchService.SearchResourcesAsync(Arg.Any()).Returns(GenerateSearchResults(0)); - var request = new SearchRequestModel - { - Term = string.Empty, - Tags = Array.Empty(), - Page = 1, - SortOrder = SortOrder.Relevance - }; - - // act - var result = await _searchResultsVMFactory.GetSearchModel(request, 1, string.Empty, default); - - // assert - result.PageContent.Should().Be(content); - } - [Test] public async Task GetSearchModel_Model_Should_Receive_SearchTerm() { diff --git a/Childrens-Social-Care-CPD-Tests/TagHelpers/CpdPropertiesListTests.cs b/Childrens-Social-Care-CPD-Tests/TagHelpers/CpdPropertiesListTests.cs index 0503a299..c4e2ccf3 100644 --- a/Childrens-Social-Care-CPD-Tests/TagHelpers/CpdPropertiesListTests.cs +++ b/Childrens-Social-Care-CPD-Tests/TagHelpers/CpdPropertiesListTests.cs @@ -113,6 +113,6 @@ public async Task Items_Are_Rendered_As_ListItem() var actual = _tagHelperOutput.AsString(); // assert - actual.Should().Contain("
  • HtmlEncode[[Foo"); + actual.Should().Contain("
  • HtmlEncode[[Foo"); } } \ No newline at end of file diff --git a/Childrens-Social-Care-CPD/Childrens-Social-Care-CPD.csproj b/Childrens-Social-Care-CPD/Childrens-Social-Care-CPD.csproj index 244eee4a..4018ec00 100644 --- a/Childrens-Social-Care-CPD/Childrens-Social-Care-CPD.csproj +++ b/Childrens-Social-Care-CPD/Childrens-Social-Care-CPD.csproj @@ -1,7 +1,7 @@  - net7.0 + net8.0 disable enable Childrens_Social_Care_CPD @@ -14,6 +14,8 @@ + + diff --git a/Childrens-Social-Care-CPD/Configuration/ApplicationConfiguration.cs b/Childrens-Social-Care-CPD/Configuration/ApplicationConfiguration.cs index b5828dc2..adc9367b 100644 --- a/Childrens-Social-Care-CPD/Configuration/ApplicationConfiguration.cs +++ b/Childrens-Social-Care-CPD/Configuration/ApplicationConfiguration.cs @@ -1,43 +1,26 @@ namespace Childrens_Social_Care_CPD.Configuration; -public class ApplicationConfiguration : IApplicationConfiguration +public class ApplicationConfiguration(IConfiguration configuration) : IApplicationConfiguration { - public ApplicationConfiguration(IConfiguration configuration) - { - AppInsightsConnectionString = new StringConfigSetting(() => configuration["CPD_INSTRUMENTATION_CONNECTIONSTRING"]); - AppVersion = new StringConfigSetting(() => configuration["VCS-TAG"]); - AzureEnvironment = new StringConfigSetting(() => configuration["CPD_AZURE_ENVIRONMENT"]); - ClarityProjectId = new StringConfigSetting(() => configuration["CPD_CLARITY"]); - ContentfulDeliveryApiKey = new StringConfigSetting(() => configuration["CPD_DELIVERY_KEY"]); - ContentfulEnvironment = new StringConfigSetting(() => configuration["CPD_CONTENTFUL_ENVIRONMENT"]); - ContentfulGraphqlConnectionString = new StringConfigSetting(() => $"https://graphql.contentful.com/content/v1/spaces/{ContentfulSpaceId.Value}/environments/{ContentfulEnvironment.Value}"); - ContentfulPreviewHost = new StringConfigSetting(() => "preview.contentful.com"); - ContentfulPreviewId = new StringConfigSetting(() => configuration["CPD_PREVIEW_KEY"]); - ContentfulSpaceId = new StringConfigSetting(() => configuration["CPD_SPACE_ID"]); - DisableSecureCookies = new BooleanConfigSetting(() => configuration["CPD_DISABLE_SECURE_COOKIES"], false); - FeaturePollingInterval = new IntegerConfigSetting(() => configuration["CPD_FEATURE_POLLING_INTERVAL"], 0); - GitHash = new StringConfigSetting(() => configuration["VCS-REF"]); - GoogleTagManagerKey = new StringConfigSetting(() => configuration["CPD_GOOGLEANALYTICSTAG"]); - SearchApiKey = new StringConfigSetting(() => configuration["CPD_SEARCH_CLIENT_API_KEY"]); - SearchEndpoint = new StringConfigSetting(() => configuration["CPD_SEARCH_ENDPOINT"]); - SearchIndexName = new StringConfigSetting(() => configuration["CPD_SEARCH_INDEX_NAME"]); - } - - public IConfigurationSetting AppInsightsConnectionString { get; init; } - public IConfigurationSetting AppVersion { get; init; } - public IConfigurationSetting AzureEnvironment { get; init; } - public IConfigurationSetting ClarityProjectId { get; init; } - public IConfigurationSetting ContentfulDeliveryApiKey { get; init; } - public IConfigurationSetting ContentfulEnvironment { get; init; } - public IConfigurationSetting ContentfulGraphqlConnectionString { get; init; } - public IConfigurationSetting ContentfulPreviewHost { get; init; } - public IConfigurationSetting ContentfulPreviewId { get; init; } - public IConfigurationSetting ContentfulSpaceId { get; init; } - public IConfigurationSetting DisableSecureCookies { get; init; } - public IConfigurationSetting FeaturePollingInterval { get; init; } - public IConfigurationSetting GitHash { get; init; } - public IConfigurationSetting GoogleTagManagerKey { get; init; } - public IConfigurationSetting SearchApiKey { get; init; } - public IConfigurationSetting SearchEndpoint { get; init; } - public IConfigurationSetting SearchIndexName { get; init; } + public string AppInsightsConnectionString => configuration["CPD_INSTRUMENTATION_CONNECTIONSTRING"]; + public string AppVersion => configuration["VCS-TAG"]; + public string AzureDataProtectionContainerName => configuration["CPD_AZURE_DATA_PROTECTION_CONTAINER_NAME"]; + public string AzureEnvironment => configuration["CPD_AZURE_ENVIRONMENT"]; + public string AzureManagedIdentityId => configuration["CPD_AZURE_MANAGED_IDENTITY_ID"]; + public string AzureStorageAccount => configuration["CPD_AZURE_STORAGE_ACCOUNT"]; + public string AzureStorageAccountUriFormatString => configuration["CPD_AZURE_STORAGE_ACCOUNT_URI_FORMAT_STRING"]; + public string ClarityProjectId => configuration["CPD_CLARITY"]; + public string ContentfulDeliveryApiKey => configuration["CPD_DELIVERY_KEY"]; + public string ContentfulEnvironment => configuration["CPD_CONTENTFUL_ENVIRONMENT"]; + public string ContentfulGraphqlConnectionString => $"https://graphql.contentful.com/content/v1/spaces/{ContentfulSpaceId}/environments/{ContentfulEnvironment}"; + public string ContentfulPreviewHost => "preview.contentful.com"; + public string ContentfulPreviewId => configuration["CPD_PREVIEW_KEY"]; + public string ContentfulSpaceId => configuration["CPD_SPACE_ID"]; + public bool DisableSecureCookies => bool.TryParse(configuration["CPD_DISABLE_SECURE_COOKIES"], out var result) && result; + public int FeaturePollingInterval => int.TryParse(configuration["CPD_FEATURE_POLLING_INTERVAL"], out var result) ? result : 0; + public string GitHash => configuration["VCS-REF"]; + public string GoogleTagManagerKey => configuration["CPD_GOOGLEANALYTICSTAG"]; + public string SearchApiKey => configuration["CPD_SEARCH_CLIENT_API_KEY"]; + public string SearchEndpoint => configuration["CPD_SEARCH_ENDPOINT"]; + public string SearchIndexName => configuration["CPD_SEARCH_INDEX_NAME"]; } \ No newline at end of file diff --git a/Childrens-Social-Care-CPD/Configuration/ApplicationEnvironment.cs b/Childrens-Social-Care-CPD/Configuration/ApplicationEnvironment.cs index e6fb8553..8d0e60f1 100644 --- a/Childrens-Social-Care-CPD/Configuration/ApplicationEnvironment.cs +++ b/Childrens-Social-Care-CPD/Configuration/ApplicationEnvironment.cs @@ -9,4 +9,5 @@ public static class ApplicationEnvironment public const string PreProduction = "pre-prod"; public const string Production = "prod"; public const string All = "*"; + public const string None = ""; } diff --git a/Childrens-Social-Care-CPD/Configuration/ConfigurationInformation.cs b/Childrens-Social-Care-CPD/Configuration/ConfigurationInformation.cs index cff0b585..e763cfde 100644 --- a/Childrens-Social-Care-CPD/Configuration/ConfigurationInformation.cs +++ b/Childrens-Social-Care-CPD/Configuration/ConfigurationInformation.cs @@ -1,5 +1,4 @@ using System.Collections.ObjectModel; -using System.Reflection; namespace Childrens_Social_Care_CPD.Configuration; @@ -12,7 +11,7 @@ public class ConfigurationInformation public ConfigurationInformation(IApplicationConfiguration applicationConfiguration) { - Environment = applicationConfiguration.AzureEnvironment.Value; + Environment = applicationConfiguration.AzureEnvironment; ExtractInfo(applicationConfiguration); } @@ -70,11 +69,6 @@ private static bool IsSet(object value) return !(string.IsNullOrEmpty(v) || string.IsNullOrWhiteSpace(v)); } - if (value is IConfigurationSetting) - { - return (value as IConfigurationSetting).IsSet; - } - return true; } } \ No newline at end of file diff --git a/Childrens-Social-Care-CPD/Configuration/ConfigurationSetting.cs b/Childrens-Social-Care-CPD/Configuration/ConfigurationSetting.cs deleted file mode 100644 index 1ac8411a..00000000 --- a/Childrens-Social-Care-CPD/Configuration/ConfigurationSetting.cs +++ /dev/null @@ -1,64 +0,0 @@ -namespace Childrens_Social_Care_CPD.Configuration; - -public interface IConfigurationSetting -{ - bool IsSet { get; } -} - -public interface IConfigurationSetting : IConfigurationSetting -{ - T Value { get; } -} - -public class ConfigurationSetting : IConfigurationSetting -{ - private readonly Func _valueGetter; - private readonly Func _valueParser; - private readonly T _defaultValue; - - public ConfigurationSetting(Func valueGetter, Func valueParser, T defaultValue = default) - { - ArgumentNullException.ThrowIfNull(valueGetter); - ArgumentNullException.ThrowIfNull(valueParser); - - _valueGetter = valueGetter; - _valueParser = valueParser; - _defaultValue = defaultValue; - } - - private static bool CheckIfSet(string value) => !(string.IsNullOrEmpty(value) || string.IsNullOrWhiteSpace(value)); - - public T Value - { - get - { - var value = _valueGetter(); - return CheckIfSet(value) ? _valueParser(value) : _defaultValue; - } - } - - public bool IsSet => CheckIfSet(_valueGetter()); - - public override string ToString() - { - return Value?.ToString() ?? string.Empty; - } -} - -internal class BooleanConfigSetting : ConfigurationSetting -{ - public BooleanConfigSetting(Func valueGetter, bool defaultValue = false) : base(valueGetter, bool.Parse, defaultValue) - { } -} - -internal class StringConfigSetting : ConfigurationSetting -{ - public StringConfigSetting(Func valueGetter, string defaultValue = "") : base(valueGetter, x => x, defaultValue) - { } -} - -internal class IntegerConfigSetting : ConfigurationSetting -{ - public IntegerConfigSetting(Func valueGetter, int defaultValue = 0) : base(valueGetter, int.Parse, defaultValue) - { } -} \ No newline at end of file diff --git a/Childrens-Social-Care-CPD/Configuration/ContentfulConfiguration.cs b/Childrens-Social-Care-CPD/Configuration/ContentfulConfiguration.cs index 248628b4..f00c4a95 100644 --- a/Childrens-Social-Care-CPD/Configuration/ContentfulConfiguration.cs +++ b/Childrens-Social-Care-CPD/Configuration/ContentfulConfiguration.cs @@ -1,5 +1,4 @@ -using Contentful.Core.Models.Management; -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; namespace Childrens_Social_Care_CPD.Configuration; @@ -9,23 +8,23 @@ public static class ContentfulConfiguration public static bool IsPreviewEnabled(IApplicationConfiguration applicationConfiguration) { var azureEnvironment = applicationConfiguration.AzureEnvironment; - return azureEnvironment.IsSet - && azureEnvironment.Value != ApplicationEnvironment.LoadTest - && applicationConfiguration.ContentfulEnvironment.Value.ToLower() != azureEnvironment.Value.ToLower(); + return !string.IsNullOrEmpty(azureEnvironment) + && !string.Equals(azureEnvironment, ApplicationEnvironment.LoadTest, StringComparison.OrdinalIgnoreCase) + && !string.Equals(applicationConfiguration.ContentfulEnvironment, azureEnvironment, StringComparison.OrdinalIgnoreCase); } public static ConfigurationManager GetContentfulConfiguration(ConfigurationManager configuration, IApplicationConfiguration applicationConfiguration) { var contentfulEnvironment = applicationConfiguration.ContentfulEnvironment; - configuration["ContentfulOptions:Environment"] = contentfulEnvironment.Value; - configuration["ContentfulOptions:SpaceId"] = applicationConfiguration.ContentfulSpaceId.Value; - configuration["ContentfulOptions:DeliveryApiKey"] = applicationConfiguration.ContentfulDeliveryApiKey.Value; + configuration["ContentfulOptions:Environment"] = contentfulEnvironment; + configuration["ContentfulOptions:SpaceId"] = applicationConfiguration.ContentfulSpaceId; + configuration["ContentfulOptions:DeliveryApiKey"] = applicationConfiguration.ContentfulDeliveryApiKey; if (IsPreviewEnabled(applicationConfiguration)) { - configuration["ContentfulOptions:host"] = applicationConfiguration.ContentfulPreviewHost.Value; + configuration["ContentfulOptions:host"] = applicationConfiguration.ContentfulPreviewHost; configuration["ContentfulOptions:UsePreviewApi"] = "true"; - configuration["ContentfulOptions:PreviewApiKey"] = applicationConfiguration.ContentfulPreviewId.Value; + configuration["ContentfulOptions:PreviewApiKey"] = applicationConfiguration.ContentfulPreviewId; } return configuration; } diff --git a/Childrens-Social-Care-CPD/Configuration/Features.cs b/Childrens-Social-Care-CPD/Configuration/Features/Features.cs similarity index 72% rename from Childrens-Social-Care-CPD/Configuration/Features.cs rename to Childrens-Social-Care-CPD/Configuration/Features/Features.cs index 5599b5e7..3cb3223e 100644 --- a/Childrens-Social-Care-CPD/Configuration/Features.cs +++ b/Childrens-Social-Care-CPD/Configuration/Features/Features.cs @@ -1,4 +1,4 @@ -namespace Childrens_Social_Care_CPD.Configuration; +namespace Childrens_Social_Care_CPD.Configuration.Features; public static class Features { diff --git a/Childrens-Social-Care-CPD/Configuration/FeaturesConfig.cs b/Childrens-Social-Care-CPD/Configuration/Features/FeaturesConfig.cs similarity index 88% rename from Childrens-Social-Care-CPD/Configuration/FeaturesConfig.cs rename to Childrens-Social-Care-CPD/Configuration/Features/FeaturesConfig.cs index fe24e391..cfc010a3 100644 --- a/Childrens-Social-Care-CPD/Configuration/FeaturesConfig.cs +++ b/Childrens-Social-Care-CPD/Configuration/Features/FeaturesConfig.cs @@ -1,6 +1,6 @@ using System.Collections.Concurrent; -namespace Childrens_Social_Care_CPD.Configuration; +namespace Childrens_Social_Care_CPD.Configuration.Features; public sealed class FeaturesConfig : IFeaturesConfig { diff --git a/Childrens-Social-Care-CPD/Configuration/FeaturesConfigBackgroundService.cs b/Childrens-Social-Care-CPD/Configuration/Features/FeaturesConfigBackgroundService.cs similarity index 87% rename from Childrens-Social-Care-CPD/Configuration/FeaturesConfigBackgroundService.cs rename to Childrens-Social-Care-CPD/Configuration/Features/FeaturesConfigBackgroundService.cs index e70e1e54..fa856dd1 100644 --- a/Childrens-Social-Care-CPD/Configuration/FeaturesConfigBackgroundService.cs +++ b/Childrens-Social-Care-CPD/Configuration/Features/FeaturesConfigBackgroundService.cs @@ -1,4 +1,4 @@ -namespace Childrens_Social_Care_CPD.Configuration; +namespace Childrens_Social_Care_CPD.Configuration.Features; public class FeaturesConfigBackgroundService : BackgroundService { @@ -22,13 +22,13 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken) _logger.LogInformation("Background polling task started"); stoppingToken.Register(() => _logger.LogInformation("Background polling task started")); - if (_applicationConfiguration.FeaturePollingInterval.Value == 0) return; + if (_applicationConfiguration.FeaturePollingInterval == 0) return; - var timer = new PeriodicTimer(TimeSpan.FromSeconds(_applicationConfiguration.FeaturePollingInterval.Value)); + var timer = new PeriodicTimer(TimeSpan.FromSeconds(_applicationConfiguration.FeaturePollingInterval)); while (await timer.WaitForNextTickAsync(stoppingToken)) { _logger.LogInformation("Polling at: {utcNow}", DateTime.UtcNow.ToShortTimeString()); await _featureConfigurationUpdater.UpdateFeaturesAsync(stoppingToken); - } + } } } \ No newline at end of file diff --git a/Childrens-Social-Care-CPD/Configuration/FeaturesConfigUpdater.cs b/Childrens-Social-Care-CPD/Configuration/Features/FeaturesConfigUpdater.cs similarity index 97% rename from Childrens-Social-Care-CPD/Configuration/FeaturesConfigUpdater.cs rename to Childrens-Social-Care-CPD/Configuration/Features/FeaturesConfigUpdater.cs index 6ed71383..1299714a 100644 --- a/Childrens-Social-Care-CPD/Configuration/FeaturesConfigUpdater.cs +++ b/Childrens-Social-Care-CPD/Configuration/Features/FeaturesConfigUpdater.cs @@ -3,7 +3,7 @@ using Contentful.Core.Extensions; using Contentful.Core.Search; -namespace Childrens_Social_Care_CPD.Configuration; +namespace Childrens_Social_Care_CPD.Configuration.Features; public class FeaturesConfigUpdater : IFeaturesConfigUpdater { diff --git a/Childrens-Social-Care-CPD/Configuration/IFeaturesConfig.cs b/Childrens-Social-Care-CPD/Configuration/Features/IFeaturesConfig.cs similarity index 69% rename from Childrens-Social-Care-CPD/Configuration/IFeaturesConfig.cs rename to Childrens-Social-Care-CPD/Configuration/Features/IFeaturesConfig.cs index d1871518..b1203ce7 100644 --- a/Childrens-Social-Care-CPD/Configuration/IFeaturesConfig.cs +++ b/Childrens-Social-Care-CPD/Configuration/Features/IFeaturesConfig.cs @@ -1,4 +1,4 @@ -namespace Childrens_Social_Care_CPD.Configuration; +namespace Childrens_Social_Care_CPD.Configuration.Features; public interface IFeaturesConfig { diff --git a/Childrens-Social-Care-CPD/Configuration/IFeaturesConfigUpdater.cs b/Childrens-Social-Care-CPD/Configuration/Features/IFeaturesConfigUpdater.cs similarity index 64% rename from Childrens-Social-Care-CPD/Configuration/IFeaturesConfigUpdater.cs rename to Childrens-Social-Care-CPD/Configuration/Features/IFeaturesConfigUpdater.cs index 763a21f1..435d6ae8 100644 --- a/Childrens-Social-Care-CPD/Configuration/IFeaturesConfigUpdater.cs +++ b/Childrens-Social-Care-CPD/Configuration/Features/IFeaturesConfigUpdater.cs @@ -1,4 +1,4 @@ -namespace Childrens_Social_Care_CPD.Configuration; +namespace Childrens_Social_Care_CPD.Configuration.Features; public interface IFeaturesConfigUpdater { diff --git a/Childrens-Social-Care-CPD/Configuration/IApplicationConfiguration.cs b/Childrens-Social-Care-CPD/Configuration/IApplicationConfiguration.cs index 89740900..4b0afcdb 100644 --- a/Childrens-Social-Care-CPD/Configuration/IApplicationConfiguration.cs +++ b/Childrens-Social-Care-CPD/Configuration/IApplicationConfiguration.cs @@ -5,55 +5,67 @@ namespace Childrens_Social_Care_CPD.Configuration; public interface IApplicationConfiguration { [RequiredForEnvironment(ApplicationEnvironment.All, Hidden = false)] - IConfigurationSetting AppInsightsConnectionString { get; } + string AppInsightsConnectionString { get; } [RequiredForEnvironment(ApplicationEnvironment.All, Hidden = false, Obfuscate = false)] - IConfigurationSetting AppVersion { get; } + string AppVersion { get; } [RequiredForEnvironment(ApplicationEnvironment.All, Hidden = false, Obfuscate = false)] - IConfigurationSetting AzureEnvironment { get; } + string AzureDataProtectionContainerName { get; } + + [RequiredForEnvironment(ApplicationEnvironment.All, Hidden = false, Obfuscate = false)] + string AzureEnvironment { get; } + + [RequiredForEnvironment(ApplicationEnvironment.All, Hidden = false)] + string AzureManagedIdentityId { get; } + + [RequiredForEnvironment(ApplicationEnvironment.All, Hidden = false)] + string AzureStorageAccount { get; } + + [RequiredForEnvironment(ApplicationEnvironment.All, Hidden = false, Obfuscate = false)] + string AzureStorageAccountUriFormatString { get; } [RequiredForEnvironment(ApplicationEnvironment.Production, Hidden = false)] - IConfigurationSetting ClarityProjectId { get; } + string ClarityProjectId { get; } [RequiredForEnvironment(ApplicationEnvironment.All, Hidden = false)] - IConfigurationSetting ContentfulDeliveryApiKey { get; } + string ContentfulDeliveryApiKey { get; } [RequiredForEnvironment(ApplicationEnvironment.All, Hidden = false, Obfuscate = false)] - IConfigurationSetting ContentfulEnvironment { get; } + string ContentfulEnvironment { get; } [RequiredForEnvironment(ApplicationEnvironment.All, Hidden = false)] - IConfigurationSetting ContentfulGraphqlConnectionString { get; } + string ContentfulGraphqlConnectionString { get; } [RequiredForEnvironment(ApplicationEnvironment.PreProduction, Hidden = false)] - IConfigurationSetting ContentfulPreviewHost { get; } + string ContentfulPreviewHost { get; } [RequiredForEnvironment(ApplicationEnvironment.PreProduction, Hidden = false)] - IConfigurationSetting ContentfulPreviewId { get; } + string ContentfulPreviewId { get; } [RequiredForEnvironment(ApplicationEnvironment.All, Hidden = false)] - IConfigurationSetting ContentfulSpaceId { get; } + string ContentfulSpaceId { get; } [DefaultValue(false)] [RequiredForEnvironment(ApplicationEnvironment.Integration, Hidden = false, Obfuscate = false)] - IConfigurationSetting DisableSecureCookies { get; } + bool DisableSecureCookies { get; } [DefaultValue(0)] [RequiredForEnvironment(ApplicationEnvironment.All, Hidden = false, Obfuscate = false)] - IConfigurationSetting FeaturePollingInterval { get; } + int FeaturePollingInterval { get; } [RequiredForEnvironment(ApplicationEnvironment.All, Hidden = false, Obfuscate = false)] - IConfigurationSetting GitHash { get; } + string GitHash { get; } [RequiredForEnvironment(ApplicationEnvironment.All, Hidden = false)] - IConfigurationSetting GoogleTagManagerKey { get; } + string GoogleTagManagerKey { get; } - //[RequiredForEnvironment(ApplicationEnvironment.None, Hidden = false)] - IConfigurationSetting SearchApiKey { get; } + [RequiredForEnvironment(ApplicationEnvironment.None, Hidden = false)] // TODO: when released, set the env to ALL + string SearchApiKey { get; } - //[RequiredForEnvironment(ApplicationEnvironment.All, Hidden = false)] - IConfigurationSetting SearchEndpoint { get; } + [RequiredForEnvironment(ApplicationEnvironment.None, Hidden = false)] // TODO: when released, set the env to ALL + string SearchEndpoint { get; } - //[RequiredForEnvironment(ApplicationEnvironment.All, Hidden = false, Obfuscate = false)] - IConfigurationSetting SearchIndexName { get; } + [RequiredForEnvironment(ApplicationEnvironment.None, Hidden = false, Obfuscate = false)] // TODO: when released, set the env to ALL + string SearchIndexName { get; } } diff --git a/Childrens-Social-Care-CPD/ConfigurationHealthCheck.cs b/Childrens-Social-Care-CPD/ConfigurationHealthCheck.cs index 85ea8498..0b4d6e5e 100644 --- a/Childrens-Social-Care-CPD/ConfigurationHealthCheck.cs +++ b/Childrens-Social-Care-CPD/ConfigurationHealthCheck.cs @@ -3,35 +3,26 @@ namespace Childrens_Social_Care_CPD; -public class ConfigurationHealthCheck : IHealthCheck +public class ConfigurationHealthCheck(ILogger logger, IApplicationConfiguration applicationConfiguration) : IHealthCheck { - private readonly ILogger _logger; - private readonly IApplicationConfiguration _applicationConfiguration; - - public ConfigurationHealthCheck(ILogger logger, IApplicationConfiguration applicationConfiguration) - { - _logger = logger; - _applicationConfiguration = applicationConfiguration; - } - public Task CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default) { - var configurationInformation = new ConfigurationInformation(_applicationConfiguration); + var configurationInformation = new ConfigurationInformation(applicationConfiguration); var healthy = true; foreach (var item in configurationInformation.ConfigurationInfo) { if (item.Required && !item.IsSet) { - _logger.LogError("Configuration setting {propertyName} does not have a value", item.Name); + logger.LogError("Configuration setting {propertyName} does not have a value", item.Name); healthy = false; } } // Specific check as this is super important. - if (_applicationConfiguration.DisableSecureCookies.Value) + if (applicationConfiguration.DisableSecureCookies) { - _logger.LogError("DisableSecureCookies should not be enabled for standard environments"); + logger.LogError("DisableSecureCookies should not be enabled for standard environments"); healthy = false; } diff --git a/Childrens-Social-Care-CPD/Contentful/Renderers/ContentLinkRenderer.cs b/Childrens-Social-Care-CPD/Contentful/Renderers/ContentLinkRenderer.cs index 1d2eb344..9684b898 100644 --- a/Childrens-Social-Care-CPD/Contentful/Renderers/ContentLinkRenderer.cs +++ b/Childrens-Social-Care-CPD/Contentful/Renderers/ContentLinkRenderer.cs @@ -9,13 +9,8 @@ interface IContentLinkContext string Path { get; } } -internal class ContentLinkRenderer : IRendererWithOptions +internal class ContentLinkRenderer(IContentLinkContext contentLinkContext) : IRendererWithOptions { - private readonly IContentLinkContext _context; - public ContentLinkRenderer(IContentLinkContext contentLinkContext) - { - _context = contentLinkContext; - } public IHtmlContent Render(ContentLink item, RendererOptions options = null) { var tagBuilder = new TagBuilder("a"); @@ -33,7 +28,7 @@ string s when s.StartsWith('/') => s, { tagBuilder.AddCssClass(options.Css); } - tagBuilder.Attributes.Add("data-track-label", _context.Path); + tagBuilder.Attributes.Add("data-track-label", contentLinkContext.Path); tagBuilder.InnerHtml.Append(item.Name); return tagBuilder; } diff --git a/Childrens-Social-Care-CPD/Contentful/Renderers/HeadingsRenderer.cs b/Childrens-Social-Care-CPD/Contentful/Renderers/HeadingsRenderer.cs index a7a9b6d4..a585fd0a 100644 --- a/Childrens-Social-Care-CPD/Contentful/Renderers/HeadingsRenderer.cs +++ b/Childrens-Social-Care-CPD/Contentful/Renderers/HeadingsRenderer.cs @@ -5,20 +5,9 @@ namespace Childrens_Social_Care_CPD.Contentful.Renderers; -internal class HeadingRendererBase +internal class HeadingRendererBase(IRenderer textRenderer, IRenderer hyperlinkRenderer, IRenderer contentLinkRenderer) { - private readonly IRenderer _textRenderer; - private readonly IRenderer _hyperlinkRenderer; - private readonly IRenderer _contentLinkRenderer; - - public HeadingRendererBase(IRenderer textRenderer, IRenderer hyperlinkRenderer, IRenderer contentLinkRenderer) - { - _textRenderer = textRenderer; - _hyperlinkRenderer = hyperlinkRenderer; - _contentLinkRenderer = contentLinkRenderer; - } - - protected IHtmlContent HeadingToHtml(string tag, IHeading heading) + protected TagBuilder HeadingToHtml(string tag, IHeading heading) { var h = new TagBuilder(tag); foreach (var content in heading.Content) @@ -33,15 +22,15 @@ protected IHtmlContent HeadingToHtml(string tag, IHeading heading) { switch (entryStructureData.Target) { - case ContentLink contentLink: h.InnerHtml.AppendHtml(_contentLinkRenderer.Render(contentLink)); break; + case ContentLink contentLink: h.InnerHtml.AppendHtml(contentLinkRenderer.Render(contentLink)); break; } break; } } break; } - case Text text: h.InnerHtml.AppendHtml(_textRenderer.Render(text)); break; - case Hyperlink hyperlink: h.InnerHtml.AppendHtml(_hyperlinkRenderer.Render(hyperlink)); break; + case Text text: h.InnerHtml.AppendHtml(textRenderer.Render(text)); break; + case Hyperlink hyperlink: h.InnerHtml.AppendHtml(hyperlinkRenderer.Render(hyperlink)); break; } } @@ -49,66 +38,48 @@ protected IHtmlContent HeadingToHtml(string tag, IHeading heading) } } -internal class Heading1Renderer : HeadingRendererBase, IRenderer +internal class Heading1Renderer(IRenderer textRenderer, IRenderer hyperlinkRenderer, IRenderer contentLinkRenderer) : HeadingRendererBase(textRenderer, hyperlinkRenderer, contentLinkRenderer), IRenderer { - public Heading1Renderer(IRenderer textRenderer, IRenderer hyperlinkRenderer, IRenderer contentLinkRenderer) : base(textRenderer, hyperlinkRenderer, contentLinkRenderer) - { } - public IHtmlContent Render(Heading1 item) { return HeadingToHtml("h1", item); } } -internal class Heading2Renderer : HeadingRendererBase, IRenderer +internal class Heading2Renderer(IRenderer textRenderer, IRenderer hyperlinkRenderer, IRenderer contentLinkRenderer) : HeadingRendererBase(textRenderer, hyperlinkRenderer, contentLinkRenderer), IRenderer { - public Heading2Renderer(IRenderer textRenderer, IRenderer hyperlinkRenderer, IRenderer contentLinkRenderer) : base(textRenderer, hyperlinkRenderer, contentLinkRenderer) - { } - public IHtmlContent Render(Heading2 item) { return HeadingToHtml("h2", item); } } -internal class Heading3Renderer : HeadingRendererBase, IRenderer +internal class Heading3Renderer(IRenderer textRenderer, IRenderer hyperlinkRenderer, IRenderer contentLinkRenderer) : HeadingRendererBase(textRenderer, hyperlinkRenderer, contentLinkRenderer), IRenderer { - public Heading3Renderer(IRenderer textRenderer, IRenderer hyperlinkRenderer, IRenderer contentLinkRenderer) : base(textRenderer, hyperlinkRenderer, contentLinkRenderer) - { } - public IHtmlContent Render(Heading3 item) { return HeadingToHtml("h3", item); } } -internal class Heading4Renderer : HeadingRendererBase, IRenderer +internal class Heading4Renderer(IRenderer textRenderer, IRenderer hyperlinkRenderer, IRenderer contentLinkRenderer) : HeadingRendererBase(textRenderer, hyperlinkRenderer, contentLinkRenderer), IRenderer { - public Heading4Renderer(IRenderer textRenderer, IRenderer hyperlinkRenderer, IRenderer contentLinkRenderer) : base(textRenderer, hyperlinkRenderer, contentLinkRenderer) - { } - public IHtmlContent Render(Heading4 item) { return HeadingToHtml("h4", item); } } -internal class Heading5Renderer : HeadingRendererBase, IRenderer +internal class Heading5Renderer(IRenderer textRenderer, IRenderer hyperlinkRenderer, IRenderer contentLinkRenderer) : HeadingRendererBase(textRenderer, hyperlinkRenderer, contentLinkRenderer), IRenderer { - public Heading5Renderer(IRenderer textRenderer, IRenderer hyperlinkRenderer, IRenderer contentLinkRenderer) : base(textRenderer, hyperlinkRenderer, contentLinkRenderer) - { } - public IHtmlContent Render(Heading5 item) { return HeadingToHtml("h5", item); } } -internal class Heading6Renderer : HeadingRendererBase, IRenderer +internal class Heading6Renderer(IRenderer textRenderer, IRenderer hyperlinkRenderer, IRenderer contentLinkRenderer) : HeadingRendererBase(textRenderer, hyperlinkRenderer, contentLinkRenderer), IRenderer { - public Heading6Renderer(IRenderer textRenderer, IRenderer hyperlinkRenderer, IRenderer contentLinkRenderer) : base(textRenderer, hyperlinkRenderer, contentLinkRenderer) - { } - public IHtmlContent Render(Heading6 item) { return HeadingToHtml("h6", item); diff --git a/Childrens-Social-Care-CPD/Contentful/Renderers/ImageCardRenderer.cs b/Childrens-Social-Care-CPD/Contentful/Renderers/ImageCardRenderer.cs index 2de421cf..395ff1f8 100644 --- a/Childrens-Social-Care-CPD/Contentful/Renderers/ImageCardRenderer.cs +++ b/Childrens-Social-Care-CPD/Contentful/Renderers/ImageCardRenderer.cs @@ -4,15 +4,8 @@ namespace Childrens_Social_Care_CPD.Contentful.Renderers; -internal class QuoteRenderer : IRenderer +internal class QuoteRenderer(IRenderer paragraphRenderer) : IRenderer { - private readonly IRenderer _paragraphRenderer; - - public QuoteRenderer(IRenderer paragraphRenderer) - { - _paragraphRenderer = paragraphRenderer; - } - public IHtmlContent Render(Quote item) { var div = new TagBuilder("div"); @@ -20,10 +13,9 @@ public IHtmlContent Render(Quote item) foreach (var content in item.Content) { - var paragraph = content as Paragraph; - if (paragraph != null) + if (content is Paragraph paragraph) { - div.InnerHtml.AppendHtml(_paragraphRenderer.Render(paragraph)); + div.InnerHtml.AppendHtml(paragraphRenderer.Render(paragraph)); } } diff --git a/Childrens-Social-Care-CPD/Contentful/Renderers/InlineAreaOfPracticeListRenderer.cs b/Childrens-Social-Care-CPD/Contentful/Renderers/InlineAreaOfPracticeListRenderer.cs index 6ce28c91..38746d94 100644 --- a/Childrens-Social-Care-CPD/Contentful/Renderers/InlineAreaOfPracticeListRenderer.cs +++ b/Childrens-Social-Care-CPD/Contentful/Renderers/InlineAreaOfPracticeListRenderer.cs @@ -4,15 +4,8 @@ namespace Childrens_Social_Care_CPD.Contentful.Renderers; -internal class InlineAreaOfPracticeListRenderer : IRenderer +internal class InlineAreaOfPracticeListRenderer(IRenderer contentLinkRenderer) : IRenderer { - private readonly IRenderer _contentLinkRenderer; - - public InlineAreaOfPracticeListRenderer(IRenderer contentLinkRenderer) - { - _contentLinkRenderer = contentLinkRenderer; - } - public IHtmlContent Render(AreaOfPracticeList item) { if (item.Areas.Count == 0) @@ -34,14 +27,14 @@ public IHtmlContent Render(AreaOfPracticeList item) return htmlContentBuilder; } - private static IHtmlContent NoAreasOfpractice() + private static TagBuilder NoAreasOfpractice() { var span = new TagBuilder("span"); span.InnerHtml.Append("No Areas Of practice Available"); return span; } - private IHtmlContent AreaOfPracticeTitle(string id, AreaOfPractice areaOfPractice) + private TagBuilder AreaOfPracticeTitle(string id, AreaOfPractice areaOfPractice) { var div = new TagBuilder("div"); div.AddCssClass("govuk-heading-s govuk-!-margin-bottom-1"); @@ -53,13 +46,13 @@ private IHtmlContent AreaOfPracticeTitle(string id, AreaOfPractice areaOfPractic Uri = id }; - heading2.InnerHtml.AppendHtml(_contentLinkRenderer.Render(contentLink)); + heading2.InnerHtml.AppendHtml(contentLinkRenderer.Render(contentLink)); div.InnerHtml.AppendHtml(heading2); return div; } - private static IHtmlContent AreaOfPracticeSummary(AreaOfPractice areaOfPractice) + private static HtmlContentBuilder AreaOfPracticeSummary(AreaOfPractice areaOfPractice) { var htmlContentBuilder = new HtmlContentBuilder(); var p = new TagBuilder("p"); diff --git a/Childrens-Social-Care-CPD/Contentful/Renderers/InlineRoleListRenderer.cs b/Childrens-Social-Care-CPD/Contentful/Renderers/InlineRoleListRenderer.cs index 826f5627..e516185c 100644 --- a/Childrens-Social-Care-CPD/Contentful/Renderers/InlineRoleListRenderer.cs +++ b/Childrens-Social-Care-CPD/Contentful/Renderers/InlineRoleListRenderer.cs @@ -4,15 +4,8 @@ namespace Childrens_Social_Care_CPD.Contentful.Renderers; -internal class InlineRoleListRenderer : IRenderer +internal class InlineRoleListRenderer(IRenderer contentLinkRenderer) : IRenderer { - private readonly IRenderer _contentLinkRenderer; - - public InlineRoleListRenderer(IRenderer contentLinkRenderer) - { - _contentLinkRenderer = contentLinkRenderer; - } - public IHtmlContent Render(RoleList item) { if (item.Roles.Count == 0) @@ -24,8 +17,7 @@ public IHtmlContent Render(RoleList item) foreach (var contentItem in item.Roles) { - var detailedRole = contentItem.Items.Find(x => typeof(DetailedRole) == x.GetType()) as DetailedRole; - if (detailedRole == null) continue; + if (contentItem.Items.Find(x => typeof(DetailedRole) == x.GetType()) is not DetailedRole detailedRole) continue; htmlContentBuilder.AppendHtml(RoleTitle(contentItem.Id, detailedRole)); htmlContentBuilder.AppendHtml(RoleSummary(detailedRole)); @@ -34,14 +26,14 @@ public IHtmlContent Render(RoleList item) return htmlContentBuilder; } - private static IHtmlContent NoRoles() + private static TagBuilder NoRoles() { var span = new TagBuilder("span"); span.InnerHtml.Append("No Roles Available"); return span; } - private IHtmlContent RoleTitle(string id, DetailedRole detailedRole) + private TagBuilder RoleTitle(string id, DetailedRole detailedRole) { var div = new TagBuilder("div"); div.AddCssClass("govuk-heading-s govuk-!-margin-bottom-1"); @@ -53,13 +45,13 @@ private IHtmlContent RoleTitle(string id, DetailedRole detailedRole) Uri = id }; - heading3.InnerHtml.AppendHtml(_contentLinkRenderer.Render(contentLink)); + heading3.InnerHtml.AppendHtml(contentLinkRenderer.Render(contentLink)); div.InnerHtml.AppendHtml(heading3); return div; } - private static IHtmlContent RoleSummary(DetailedRole detailedRole) + private static HtmlContentBuilder RoleSummary(DetailedRole detailedRole) { var htmlContentBuilder = new HtmlContentBuilder(); var p = new TagBuilder("p"); diff --git a/Childrens-Social-Care-CPD/Contentful/Renderers/ListRenderer.cs b/Childrens-Social-Care-CPD/Contentful/Renderers/ListRenderer.cs index 3424c8ab..14b77c62 100644 --- a/Childrens-Social-Care-CPD/Contentful/Renderers/ListRenderer.cs +++ b/Childrens-Social-Care-CPD/Contentful/Renderers/ListRenderer.cs @@ -5,17 +5,8 @@ namespace Childrens_Social_Care_CPD.Contentful.Renderers; -public class ListRenderer : IRenderer +public class ListRenderer(IRenderer textRenderer, IRenderer hyperlinkRenderer) : IRenderer { - private readonly IRenderer _textRenderer; - private readonly IRenderer _hyperlinkRenderer; - - public ListRenderer(IRenderer textRenderer, IRenderer hyperlinkRenderer) - { - _textRenderer = textRenderer; - _hyperlinkRenderer = hyperlinkRenderer; - } - public IHtmlContent Render(List item) { if (item.Content.Count == 0) @@ -28,8 +19,7 @@ public IHtmlContent Render(List item) foreach (var listItem in item.Content.OfType()) { - var paragraph = listItem.Content[0] as Paragraph; - if (paragraph == null) continue; + if (listItem.Content[0] is not Paragraph paragraph) continue; var li = new TagBuilder("li"); foreach (var content in paragraph.Content) @@ -38,12 +28,12 @@ public IHtmlContent Render(List item) { case Text text: { - li.InnerHtml.AppendHtml(_textRenderer.Render(text)); + li.InnerHtml.AppendHtml(textRenderer.Render(text)); break; } case Hyperlink hyperlink: { - li.InnerHtml.AppendHtml(_hyperlinkRenderer.Render(hyperlink)); + li.InnerHtml.AppendHtml(hyperlinkRenderer.Render(hyperlink)); break; } } diff --git a/Childrens-Social-Care-CPD/Contentful/Renderers/ParagraphRenderer.cs b/Childrens-Social-Care-CPD/Contentful/Renderers/ParagraphRenderer.cs index e3d9666d..b7f33508 100644 --- a/Childrens-Social-Care-CPD/Contentful/Renderers/ParagraphRenderer.cs +++ b/Childrens-Social-Care-CPD/Contentful/Renderers/ParagraphRenderer.cs @@ -5,24 +5,8 @@ namespace Childrens_Social_Care_CPD.Contentful.Renderers; -internal class ParagraphRenderer : IRenderer +internal class ParagraphRenderer(IRenderer textRenderer, IRenderer roleListRenderer, IRenderer hyperlinkRenderer, IRenderer contentLinkRenderer, IRenderer areaOfPracticeListRenderer) : IRenderer { - private readonly IRenderer _textRenderer; - private readonly IRenderer _roleListRenderer; - private readonly IRenderer _hyperlinkRenderer; - private readonly IRenderer _contentLinkRenderer; - private readonly IRenderer _areaOfPracticeList; - - - public ParagraphRenderer(IRenderer textRenderer, IRenderer roleListRenderer, IRenderer hyperlinkRenderer, IRenderer contentLinkRenderer, IRenderer areaOfPracticeList) - { - _textRenderer = textRenderer; - _roleListRenderer = roleListRenderer; - _hyperlinkRenderer = hyperlinkRenderer; - _contentLinkRenderer = contentLinkRenderer; - _areaOfPracticeList = areaOfPracticeList; - } - public IHtmlContent Render(Paragraph item) { var p = new TagBuilder("p"); @@ -32,18 +16,18 @@ public IHtmlContent Render(Paragraph item) { switch (content) { - case Text text: p.InnerHtml.AppendHtml(_textRenderer.Render(text)); break; + case Text text: p.InnerHtml.AppendHtml(textRenderer.Render(text)); break; case EntryStructure entryStructure: { switch (entryStructure.Data.Target) { - case ContentLink contentLink: p.InnerHtml.AppendHtml(_contentLinkRenderer.Render(contentLink)); break; - case RoleList roleList: p.InnerHtml.AppendHtml(_roleListRenderer.Render(roleList)); break; - case AreaOfPracticeList areaOfPracticeList: p.InnerHtml.AppendHtml(_areaOfPracticeList.Render(areaOfPracticeList)); break; + case ContentLink contentLink: p.InnerHtml.AppendHtml(contentLinkRenderer.Render(contentLink)); break; + case RoleList roleList: p.InnerHtml.AppendHtml(roleListRenderer.Render(roleList)); break; + case AreaOfPracticeList areaOfPracticeList: p.InnerHtml.AppendHtml(areaOfPracticeListRenderer.Render(areaOfPracticeList)); break; } break; } - case Hyperlink hyperlink: p.InnerHtml.AppendHtml(_hyperlinkRenderer.Render(hyperlink)); break; + case Hyperlink hyperlink: p.InnerHtml.AppendHtml(hyperlinkRenderer.Render(hyperlink)); break; } } diff --git a/Childrens-Social-Care-CPD/Contentful/Renderers/RelatedContentRenderer.cs b/Childrens-Social-Care-CPD/Contentful/Renderers/RelatedContentRenderer.cs index c1484b7a..d058065d 100644 --- a/Childrens-Social-Care-CPD/Contentful/Renderers/RelatedContentRenderer.cs +++ b/Childrens-Social-Care-CPD/Contentful/Renderers/RelatedContentRenderer.cs @@ -4,15 +4,8 @@ namespace Childrens_Social_Care_CPD.Contentful.Renderers; -public class RelatedContentRenderer : IRenderer +public class RelatedContentRenderer(IRenderer contentLinkRenderer) : IRenderer { - private readonly IRenderer _contentLinkRenderer; - - public RelatedContentRenderer(IRenderer contentLinkRenderer) - { - _contentLinkRenderer = contentLinkRenderer; - } - public IHtmlContent Render(RelatedContent item) { if (item == null) return null; @@ -41,7 +34,7 @@ public IHtmlContent Render(RelatedContent item) return rowDiv; } - private static IHtmlContent RenderHeading() + private static TagBuilder RenderHeading() { var h2 = new TagBuilder("h2"); h2.AddCssClass("govuk-heading-s"); @@ -50,7 +43,7 @@ private static IHtmlContent RenderHeading() return h2; } - private IHtmlContent RenderNav(RelatedContent relatedContent) + private TagBuilder RenderNav(RelatedContent relatedContent) { var nav = new TagBuilder("nav"); nav.Attributes.Add("role", "navigation"); @@ -62,7 +55,7 @@ private IHtmlContent RenderNav(RelatedContent relatedContent) foreach(var contentLink in relatedContent) { var li = new TagBuilder("li"); - li.InnerHtml.AppendHtml(_contentLinkRenderer.Render(contentLink)); + li.InnerHtml.AppendHtml(contentLinkRenderer.Render(contentLink)); ul.InnerHtml.AppendHtml(li); } diff --git a/Childrens-Social-Care-CPD/Contentful/Renderers/TableCellRenderer.cs b/Childrens-Social-Care-CPD/Contentful/Renderers/TableCellRenderer.cs index 52e313a4..ff8b5c72 100644 --- a/Childrens-Social-Care-CPD/Contentful/Renderers/TableCellRenderer.cs +++ b/Childrens-Social-Care-CPD/Contentful/Renderers/TableCellRenderer.cs @@ -4,15 +4,8 @@ namespace Childrens_Social_Care_CPD.Contentful.Renderers; -internal class TableCellRenderer : IRenderer +internal class TableCellRenderer(IRenderer paragraphRenderer) : IRenderer { - private readonly IRenderer _paragraphRenderer; - - public TableCellRenderer(IRenderer paragraphRenderer) - { - _paragraphRenderer = paragraphRenderer; - } - public IHtmlContent Render(TableCell item) { var td = new TagBuilder("td"); @@ -22,7 +15,7 @@ public IHtmlContent Render(TableCell item) { switch (content) { - case Paragraph paragraph: td.InnerHtml.AppendHtml(_paragraphRenderer.Render(paragraph)); break; + case Paragraph paragraph: td.InnerHtml.AppendHtml(paragraphRenderer.Render(paragraph)); break; } } diff --git a/Childrens-Social-Care-CPD/Contentful/Renderers/TableHeaderRenderer.cs b/Childrens-Social-Care-CPD/Contentful/Renderers/TableHeaderRenderer.cs index f5b27b9e..ca4d1ce0 100644 --- a/Childrens-Social-Care-CPD/Contentful/Renderers/TableHeaderRenderer.cs +++ b/Childrens-Social-Care-CPD/Contentful/Renderers/TableHeaderRenderer.cs @@ -4,17 +4,8 @@ namespace Childrens_Social_Care_CPD.Contentful.Renderers; -internal class TableHeaderRenderer : IRenderer +internal class TableHeaderRenderer(IRenderer textRenderer, IRenderer hyperlinkRenderer) : IRenderer { - private readonly IRenderer _textRenderer; - private readonly IRenderer _hyperlinkRenderer; - - public TableHeaderRenderer(IRenderer textRenderer, IRenderer hyperlinkRenderer) - { - _textRenderer = textRenderer; - _hyperlinkRenderer = hyperlinkRenderer; - } - public IHtmlContent Render(TableHeader item) { var th = new TagBuilder("th"); @@ -31,8 +22,8 @@ public IHtmlContent Render(TableHeader item) { switch (pContent) { - case Text text: th.InnerHtml.AppendHtml(_textRenderer.Render(text)); break; - case Hyperlink hyperlink: th.InnerHtml.AppendHtml(_hyperlinkRenderer.Render(hyperlink)); break; + case Text text: th.InnerHtml.AppendHtml(textRenderer.Render(text)); break; + case Hyperlink hyperlink: th.InnerHtml.AppendHtml(hyperlinkRenderer.Render(hyperlink)); break; } } break; diff --git a/Childrens-Social-Care-CPD/Contentful/Renderers/TableRenderer.cs b/Childrens-Social-Care-CPD/Contentful/Renderers/TableRenderer.cs index cfa010e2..cf56b9b1 100644 --- a/Childrens-Social-Care-CPD/Contentful/Renderers/TableRenderer.cs +++ b/Childrens-Social-Care-CPD/Contentful/Renderers/TableRenderer.cs @@ -4,17 +4,8 @@ namespace Childrens_Social_Care_CPD.Contentful.Renderers; -internal class TableRenderer : IRenderer +internal class TableRenderer(IRenderer tableHeaderRenderer, IRenderer tableCellRenderer) : IRenderer
    { - private readonly IRenderer _tableHeaderRenderer; - private readonly IRenderer _tableCellRenderer; - - public TableRenderer(IRenderer tableHeaderRenderer, IRenderer tableCellRenderer) - { - _tableHeaderRenderer = tableHeaderRenderer; - _tableCellRenderer = tableCellRenderer; - } - public IHtmlContent Render(Table item) { var table = new TagBuilder("table"); @@ -32,7 +23,7 @@ public IHtmlContent Render(Table item) foreach (TableHeader tableHeader in headerRow.Content.OfType()) { - tr.InnerHtml.AppendHtml(_tableHeaderRenderer.Render(tableHeader)); + tr.InnerHtml.AppendHtml(tableHeaderRenderer.Render(tableHeader)); } thead.InnerHtml.AppendHtml(tr); @@ -50,7 +41,7 @@ public IHtmlContent Render(Table item) foreach (TableCell tableCell in row.Content.OfType()) { - tr.InnerHtml.AppendHtml(_tableCellRenderer.Render(tableCell)); + tr.InnerHtml.AppendHtml(tableCellRenderer.Render(tableCell)); } tbody.InnerHtml.AppendHtml(tr); diff --git a/Childrens-Social-Care-CPD/Contentful/Renderers/TextRenderer.cs b/Childrens-Social-Care-CPD/Contentful/Renderers/TextRenderer.cs index e13f3997..511df025 100644 --- a/Childrens-Social-Care-CPD/Contentful/Renderers/TextRenderer.cs +++ b/Childrens-Social-Care-CPD/Contentful/Renderers/TextRenderer.cs @@ -19,7 +19,7 @@ public IHtmlContent Render(Text item) htmlContentBuilder.Append(parts[index]); htmlContentBuilder.AppendHtml("
    "); } - htmlContentBuilder.Append(parts[parts.Length - 1]); + htmlContentBuilder.Append(parts[^1]); IHtmlContent htmlContent = htmlContentBuilder; foreach (var mark in item.Marks) @@ -38,7 +38,7 @@ public IHtmlContent Render(Text item) return htmlContent; } - private static IHtmlContent EncaseInTag(IHtmlContent htmlContent, string tag) + private static TagBuilder EncaseInTag(IHtmlContent htmlContent, string tag) { var tagBuilder = new TagBuilder(tag); tagBuilder.InnerHtml.SetHtmlContent(htmlContent); diff --git a/Childrens-Social-Care-CPD/Controllers/ApplicationController.cs b/Childrens-Social-Care-CPD/Controllers/ApplicationController.cs index 53fa658b..309224c2 100644 --- a/Childrens-Social-Care-CPD/Controllers/ApplicationController.cs +++ b/Childrens-Social-Care-CPD/Controllers/ApplicationController.cs @@ -5,25 +5,18 @@ namespace Childrens_Social_Care_CPD.Controllers; -public class ApplicationController : Controller +public class ApplicationController(IApplicationConfiguration applicationConfiguration) : Controller { - private readonly IApplicationConfiguration _applicationConfiguration; - - public ApplicationController(IApplicationConfiguration applicationConfiguration) - { - _applicationConfiguration = applicationConfiguration; - } - [HttpGet] [Route("CPD/AppInfo")] public JsonResult AppInfo() { var applicationInfo = new ApplicationInfo() { - Environment = _applicationConfiguration.AzureEnvironment.Value, - ContentfulEnvironment = _applicationConfiguration.ContentfulEnvironment.Value, - GitShortHash = _applicationConfiguration.GitHash.Value, - Version = _applicationConfiguration.AppVersion.Value, + Environment = applicationConfiguration.AzureEnvironment, + ContentfulEnvironment = applicationConfiguration.ContentfulEnvironment, + GitShortHash = applicationConfiguration.GitHash, + Version = applicationConfiguration.AppVersion, }; return Json(applicationInfo); @@ -33,7 +26,7 @@ public JsonResult AppInfo() [Route("application/configuration")] public IActionResult Configuration() { - var configurationInformation = new ConfigurationInformation(_applicationConfiguration); + var configurationInformation = new ConfigurationInformation(applicationConfiguration); if (Request.Headers.Accept == MediaTypeNames.Application.Json) { diff --git a/Childrens-Social-Care-CPD/Controllers/ContentController.cs b/Childrens-Social-Care-CPD/Controllers/ContentController.cs index 6c6b732c..136cb811 100644 --- a/Childrens-Social-Care-CPD/Controllers/ContentController.cs +++ b/Childrens-Social-Care-CPD/Controllers/ContentController.cs @@ -6,15 +6,8 @@ namespace Childrens_Social_Care_CPD.Controllers; -public class ContentController : Controller +public class ContentController(ICpdContentfulClient cpdClient) : Controller { - private readonly ICpdContentfulClient _cpdClient; - - public ContentController(ICpdContentfulClient cpdClient) - { - _cpdClient = cpdClient; - } - private async Task FetchPageContentAsync(string contentId, CancellationToken cancellationToken) { var queryBuilder = QueryBuilder.New @@ -22,7 +15,7 @@ private async Task FetchPageContentAsync(string contentId, Cancellation .FieldEquals("fields.id", contentId) .Include(10); - var result = await _cpdClient.GetEntries(queryBuilder, cancellationToken); + var result = await cpdClient.GetEntries(queryBuilder, cancellationToken); return result?.FirstOrDefault(); } @@ -41,7 +34,7 @@ private async Task FetchPageContentAsync(string contentId, Cancellation <= Etc. */ - [Route("/{*pagename:regex(^[[0-9a-z]](\\/?[[0-9a-z\\-]])*\\/?$)}")] + [Route("/{*pagename:regex(^[[0-9a-z]]+[[0-9a-z\\/\\-]]*$)}")] public async Task Index(string pageName = "home", bool preferenceSet = false, bool fs = false, CancellationToken cancellationToken = default) { pageName = pageName?.TrimEnd('/'); diff --git a/Childrens-Social-Care-CPD/Controllers/CookieController.cs b/Childrens-Social-Care-CPD/Controllers/CookieController.cs index c1e74233..138cebaf 100644 --- a/Childrens-Social-Care-CPD/Controllers/CookieController.cs +++ b/Childrens-Social-Care-CPD/Controllers/CookieController.cs @@ -7,25 +7,17 @@ namespace Childrens_Social_Care_CPD.Controllers; -public class CookieController : Controller +public class CookieController(ICpdContentfulClient cpdClient, ICookieHelper cookieHelper) : Controller { - private readonly ICpdContentfulClient _cpdClient; - private readonly ICookieHelper _cookieHelper; private const string _pageName = "cookies"; - public CookieController(ICpdContentfulClient cpdClient, ICookieHelper cookieHelper) - { - _cpdClient = cpdClient; - _cookieHelper = cookieHelper; - } - [HttpPost] [ValidateAntiForgeryToken] [Route("/cookies/setpreferences")] public IActionResult SetPreferences(string consentValue, string sourcePage = null, bool fromCookies = false) { var consentState = AnalyticsConsentStateHelper.Parse(consentValue); - _cookieHelper.SetResponseAnalyticsCookieState(HttpContext, consentState); + cookieHelper.SetResponseAnalyticsCookieState(HttpContext, consentState); if (fromCookies) { @@ -47,7 +39,7 @@ public async Task Cookies(CancellationToken cancellationToken, st .FieldEquals("fields.id", _pageName) .Include(10); - var result = await _cpdClient.GetEntries(queryBuilder, cancellationToken); + var result = await cpdClient.GetEntries(queryBuilder, cancellationToken); var pageContent = result.FirstOrDefault(); if (pageContent == null) @@ -60,7 +52,7 @@ public async Task Cookies(CancellationToken cancellationToken, st sourcePage = "home"; } - var consentState = _cookieHelper.GetRequestAnalyticsCookieState(HttpContext); + var consentState = cookieHelper.GetRequestAnalyticsCookieState(HttpContext); var contextModel = new ContextModel(pageContent.Id, pageContent.Title, _pageName, pageContent.Category, true, preferenceSet, true); ViewData["ContextModel"] = contextModel; diff --git a/Childrens-Social-Care-CPD/Controllers/FeedbackController.cs b/Childrens-Social-Care-CPD/Controllers/FeedbackController.cs index f25a9dff..77943d5a 100644 --- a/Childrens-Social-Care-CPD/Controllers/FeedbackController.cs +++ b/Childrens-Social-Care-CPD/Controllers/FeedbackController.cs @@ -1,4 +1,4 @@ -using Childrens_Social_Care_CPD.Configuration; +using Childrens_Social_Care_CPD.Configuration.Features; using Childrens_Social_Care_CPD.Contentful; using Childrens_Social_Care_CPD.Contentful.Models; using Contentful.Core.Search; @@ -45,7 +45,7 @@ private static bool IsModelValid(FeedbackModel model, out string pageId) pageId = pageId.Trim('/'); if (pageId.Length > 512 - || model.Comments?.Length > 500 + || model.Comments?.Length > 400 || !Regex.IsMatch(pageId, @"^[0-9a-z](\/?[0-9a-z\-])*\/?$", RegexOptions.Compiled, TimeSpan.FromSeconds(1))) { return false; diff --git a/Childrens-Social-Care-CPD/Controllers/ResourcesController.cs b/Childrens-Social-Care-CPD/Controllers/ResourcesController.cs index c0e8b06a..d38e39f9 100644 --- a/Childrens-Social-Care-CPD/Controllers/ResourcesController.cs +++ b/Childrens-Social-Care-CPD/Controllers/ResourcesController.cs @@ -1,4 +1,5 @@ using Childrens_Social_Care_CPD.Configuration; +using Childrens_Social_Care_CPD.Configuration.Features; using Childrens_Social_Care_CPD.Contentful.Models; using Childrens_Social_Care_CPD.DataAccess; using Childrens_Social_Care_CPD.GraphQL.Queries; @@ -7,17 +8,8 @@ namespace Childrens_Social_Care_CPD.Controllers; -public class ResourcesController : Controller +public class ResourcesController(IFeaturesConfig featuresConfig, IResourcesRepository resourcesRepository) : Controller { - private readonly IFeaturesConfig _featuresConfig; - private readonly IResourcesRepository _resourcesRepository; - - public ResourcesController(IFeaturesConfig featuresConfig, IResourcesRepository resourcesRepository) - { - _featuresConfig = featuresConfig; - _resourcesRepository = resourcesRepository; - } - private static Dictionary GetProperties(GetContentTags.ResponseType tags, Content content) { var properties = new Dictionary() @@ -49,16 +41,16 @@ void AddProperty(string key, string prefix) return properties; } - [Route("resources-learning/{*pagename:regex(^[[0-9a-z]](\\/?[[0-9a-z\\-]])*\\/?$)}")] + [Route("resources-learning/{*pagename:regex(^[[0-9a-z]]+[[0-9a-z\\/\\-]]*$)}")] public async Task Index(string pageName = "home", bool preferenceSet = false, bool fs = false, CancellationToken cancellationToken = default) { - if (!_featuresConfig.IsEnabled(Features.ResourcesAndLearning)) + if (!featuresConfig.IsEnabled(Features.ResourcesAndLearning)) { return NotFound(); } pageName = $"resources-learning/{pageName?.TrimEnd('/')}"; - (var content, var tags) = await _resourcesRepository.GetByIdAsync(pageName, cancellationToken: cancellationToken); + (var content, var tags) = await resourcesRepository.GetByIdAsync(pageName, cancellationToken: cancellationToken); if (content == null) { return NotFound(); diff --git a/Childrens-Social-Care-CPD/Controllers/SearchResourcesController.cs b/Childrens-Social-Care-CPD/Controllers/SearchResourcesController.cs index e71b33ce..200e3aac 100644 --- a/Childrens-Social-Care-CPD/Controllers/SearchResourcesController.cs +++ b/Childrens-Social-Care-CPD/Controllers/SearchResourcesController.cs @@ -1,4 +1,5 @@ using Childrens_Social_Care_CPD.Configuration; +using Childrens_Social_Care_CPD.Configuration.Features; using Childrens_Social_Care_CPD.Models; using Childrens_Social_Care_CPD.Search; using Microsoft.AspNetCore.Mvc; diff --git a/Childrens-Social-Care-CPD/CookieHelper.cs b/Childrens-Social-Care-CPD/CookieHelper.cs index f8b53748..17a10858 100644 --- a/Childrens-Social-Care-CPD/CookieHelper.cs +++ b/Childrens-Social-Care-CPD/CookieHelper.cs @@ -23,7 +23,7 @@ public void SetResponseAnalyticsCookieState(HttpContext httpContext, AnalyticsCo HttpOnly = true, SameSite = SameSiteMode.Strict, IsEssential = true, - Secure = !_applicationConfiguration.DisableSecureCookies.Value + Secure = !_applicationConfiguration.DisableSecureCookies }; switch (state) diff --git a/Childrens-Social-Care-CPD/DataAccess/ResourcesRepository.cs b/Childrens-Social-Care-CPD/DataAccess/ResourcesRepository.cs index 2aeb3417..1f779978 100644 --- a/Childrens-Social-Care-CPD/DataAccess/ResourcesRepository.cs +++ b/Childrens-Social-Care-CPD/DataAccess/ResourcesRepository.cs @@ -25,6 +25,7 @@ public interface IResourcesRepository public class ResourcesRepository : IResourcesRepository { private static readonly string[] _tagPrefixes = new string[] { "Topic", "Resource provider", "Format", "Career stage" }; + private static readonly string[] _carrerStageOrder = new string[] { "careerStagePractitioner", "careerStageExperiencedPractitioner", "careerStageManager", "careerStageSeniorManager", "careerStageSeniorLeader" }; private readonly ICpdContentfulClient _cpdClient; private readonly IGraphQLWebSocketClient _gqlClient; private readonly bool _isPreview; @@ -93,12 +94,21 @@ public async Task> GetSearchTagsAsync(CancellationToken can foreach (var category in _tagPrefixes) { - list.AddRange( - tags + var sortedtags = tags .Where(x => x.Key == category) .Select(x => new TagInfo(x.Key, x.Value.Name[(x.Value.Name.IndexOf(':') + 1)..], x.Value.SystemProperties.Id)) - .OrderBy(x => x.TagName) - ); + .OrderBy(x => x.TagName); + + switch (category) + { + //reorder career stage tags + case "Career stage": + list.AddRange(sortedtags.OrderBy(x => Array.IndexOf(_carrerStageOrder, x.TagName))); + break; + default: + list.AddRange(sortedtags); + break; + } } return list; diff --git a/Childrens-Social-Care-CPD/Dockerfile b/Childrens-Social-Care-CPD/Dockerfile index 970ff45b..854e6e6e 100644 --- a/Childrens-Social-Care-CPD/Dockerfile +++ b/Childrens-Social-Care-CPD/Dockerfile @@ -1,11 +1,11 @@ #See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging. -FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base WORKDIR /app EXPOSE 80 EXPOSE 443 -FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build WORKDIR /src COPY ["Childrens-Social-Care-CPD.csproj", "."] RUN dotnet restore "./Childrens-Social-Care-CPD.csproj" diff --git a/Childrens-Social-Care-CPD/Models/ResourceSearchResultsViewModel.cs b/Childrens-Social-Care-CPD/Models/ResourceSearchResultsViewModel.cs index 31118a2f..f414aa27 100644 --- a/Childrens-Social-Care-CPD/Models/ResourceSearchResultsViewModel.cs +++ b/Childrens-Social-Care-CPD/Models/ResourceSearchResultsViewModel.cs @@ -1,5 +1,4 @@ using Azure.Search.Documents.Models; -using Childrens_Social_Care_CPD.Contentful.Models; using Childrens_Social_Care_CPD.Search; using System.Diagnostics.CodeAnalysis; @@ -7,7 +6,6 @@ namespace Childrens_Social_Care_CPD.Models; [ExcludeFromCodeCoverage] public record ResourceSearchResultsViewModel( - Content PageContent, string SearchTerm, long TotalCount, long TotalPages, diff --git a/Childrens-Social-Care-CPD/Program.cs b/Childrens-Social-Care-CPD/Program.cs index 27f0cd3f..4becf642 100644 --- a/Childrens-Social-Care-CPD/Program.cs +++ b/Childrens-Social-Care-CPD/Program.cs @@ -1,10 +1,10 @@ using Childrens_Social_Care_CPD; -using Childrens_Social_Care_CPD.Configuration; +using Childrens_Social_Care_CPD.Configuration.Features; using System.Diagnostics.CodeAnalysis; var builder = WebApplication.CreateBuilder(args); builder.AddDependencies(); -builder.AddFeatures(); +await builder.AddFeatures(); var app = builder.Build(); @@ -26,7 +26,6 @@ pattern: "{controller=Content}/{action=Index}"); app.MapHealthChecks("application/status"); - app.Run(); [ExcludeFromCodeCoverage] diff --git a/Childrens-Social-Care-CPD/Search/SearchResultsVMFactory.cs b/Childrens-Social-Care-CPD/Search/SearchResultsVMFactory.cs index 69e14bfc..82bebbf7 100644 --- a/Childrens-Social-Care-CPD/Search/SearchResultsVMFactory.cs +++ b/Childrens-Social-Care-CPD/Search/SearchResultsVMFactory.cs @@ -3,7 +3,7 @@ using Childrens_Social_Care_CPD.Models; using System.Collections.ObjectModel; using System.Net; -using System.Text.Encodings.Web; +using System.Text; namespace Childrens_Social_Care_CPD.Search; @@ -25,7 +25,7 @@ public SearchResultsVMFactory(ISearchService searchService, IResourcesRepository _resourcesRepository = resourcesRepository; } - private static IReadOnlyDictionary GetFacetedTags(IEnumerable tagInfos, IDictionary> facets) + private static ReadOnlyDictionary GetFacetedTags(IEnumerable tagInfos, IDictionary> facets) { facets.TryGetValue("Tags", out var tagFacets); if (tagFacets == null) @@ -41,26 +41,27 @@ private static IReadOnlyDictionary GetFacetedTags(IEnumera private static string AppendUrlParameter(string name, string param, bool additive = true) { - return string.IsNullOrEmpty(param) - ? string.Empty - : $"{(additive ? '&' : string.Empty)}{name}={WebUtility.UrlEncode(param)}"; + if (string.IsNullOrEmpty(name)) return string.Empty; + + return $"{(additive ? '&' : string.Empty)}{name}={WebUtility.UrlEncode(param)}"; } private static string GetPagingFormatString(string searchTerm, IEnumerable tags, SortOrder sortOrder, string routeName) { - var result = $"/{routeName}?{SearchRequestPropertyNames.Page}={{0}}"; - + var sb = new StringBuilder($"/{routeName}?{SearchRequestPropertyNames.Page}={{0}}"); if (sortOrder != SortOrder.UpdatedLatest) { - result += AppendUrlParameter(SearchRequestPropertyNames.SortOrder, ((int)sortOrder).ToString()); + sb.Append(AppendUrlParameter(SearchRequestPropertyNames.SortOrder, ((int)sortOrder).ToString())); } - result += AppendUrlParameter(SearchRequestPropertyNames.Term, searchTerm); + + sb.Append(AppendUrlParameter(SearchRequestPropertyNames.Term, searchTerm)); + foreach (var tag in tags) { - result += AppendUrlParameter(SearchRequestPropertyNames.Tags, tag); + sb.Append(AppendUrlParameter(SearchRequestPropertyNames.Tags, tag)); } - - return result; + + return sb.ToString(); } private static string GetClearFiltersUri(SearchRequestModel request, string routeName) @@ -98,9 +99,6 @@ private static KeywordSearchQuery GetQuery(SearchRequestModel request, IEnumerab public async Task GetSearchModel(SearchRequestModel request, int pageSize, string routeName, CancellationToken cancellationToken) { - // Kick off our page content query - var rootPageTask = _resourcesRepository.FetchRootPageAsync(cancellationToken); - // Get the available tags and validate the ones we've been given var tagInfos = await _resourcesRepository.GetSearchTagsAsync(cancellationToken); var validTags = request.Tags?.Where(x => tagInfos.Any(y => y.TagName == x)) ?? Array.Empty(); @@ -112,11 +110,7 @@ public async Task GetSearchModel(SearchRequestMo var searchResults = await _searchService.SearchResourcesAsync(query); var facetedTags = GetFacetedTags(tagInfos, searchResults.SearchResults.Facets); - // Wait for the page content query to complete - var pageContent = await rootPageTask; - return new ResourceSearchResultsViewModel( - pageContent, query.Keyword, searchResults.TotalCount, searchResults.TotalPages, diff --git a/Childrens-Social-Care-CPD/TagHelpers/CpdPropertiesList.cs b/Childrens-Social-Care-CPD/TagHelpers/CpdPropertiesList.cs index 89848b26..7b3fad14 100644 --- a/Childrens-Social-Care-CPD/TagHelpers/CpdPropertiesList.cs +++ b/Childrens-Social-Care-CPD/TagHelpers/CpdPropertiesList.cs @@ -29,12 +29,8 @@ public override void Process(TagHelperContext context, TagHelperOutput output) foreach (var item in Items) { - var span = new TagBuilder("span"); - span.AddCssClass("govuk-!-font-size-16"); - span.InnerHtml.Append($"{item.Key}: {item.Value}"); - var li = new TagBuilder("li"); - li.InnerHtml.AppendHtml(span); + li.InnerHtml.Append($"{item.Key}: {item.Value}"); output.Content.AppendHtml(li); } diff --git a/Childrens-Social-Care-CPD/TagHelpers/CpdResourceNav.cs b/Childrens-Social-Care-CPD/TagHelpers/CpdResourceNav.cs index 8b7ef6e0..dba545a5 100644 --- a/Childrens-Social-Care-CPD/TagHelpers/CpdResourceNav.cs +++ b/Childrens-Social-Care-CPD/TagHelpers/CpdResourceNav.cs @@ -41,7 +41,7 @@ public override void Process(TagHelperContext context, TagHelperOutput output) output.Content.AppendHtml(RenderNavigation(Navigation, Selected)); } - private static IHtmlContent RenderNavigation(IList navigation, string selected) + private static TagBuilder RenderNavigation(IList navigation, string selected) { var ol = new TagBuilder("ol"); ol.AddCssClass("gem-c-contents-list__list"); diff --git a/Childrens-Social-Care-CPD/TagHelpers/CpdResourcePageNav.cs b/Childrens-Social-Care-CPD/TagHelpers/CpdResourcePageNav.cs index 0580f1e8..72d78d97 100644 --- a/Childrens-Social-Care-CPD/TagHelpers/CpdResourcePageNav.cs +++ b/Childrens-Social-Care-CPD/TagHelpers/CpdResourcePageNav.cs @@ -49,7 +49,7 @@ public override void Process(TagHelperContext context, TagHelperOutput output) } } - private static IHtmlContent RenderNext(ContentLink contentLink) + private static TagBuilder RenderNext(ContentLink contentLink) { var span1 = new TagBuilder("span"); span1.AddCssClass("govuk-pagination__link-title"); @@ -81,7 +81,7 @@ private static IHtmlContent RenderNext(ContentLink contentLink) return div; } - private static IHtmlContent RenderPrevious(ContentLink contentLink) + private static TagBuilder RenderPrevious(ContentLink contentLink) { var span1 = new TagBuilder("span"); span1.AddCssClass("govuk-pagination__link-title"); @@ -113,7 +113,7 @@ private static IHtmlContent RenderPrevious(ContentLink contentLink) return div; } - private static IHtmlContent ArrowRight() + private static TagBuilder ArrowRight() { var path = new TagBuilder("path"); path.Attributes.Add("d", "m8.107-0.0078125-1.4136 1.414 4.2926 4.293h-12.986v2h12.896l-4.1855 3.9766 1.377 1.4492 6.7441-6.4062-6.7246-6.7266z"); @@ -132,7 +132,7 @@ private static IHtmlContent ArrowRight() return svg; } - private static IHtmlContent ArrowLeft() + private static TagBuilder ArrowLeft() { var path = new TagBuilder("path"); path.Attributes.Add("d", "m6.5938-0.0078125-6.7266 6.7266 6.7441 6.4062 1.377-1.449-4.1856-3.9768h12.896v-2h-12.984l4.2931-4.293-1.414-1.414z"); diff --git a/Childrens-Social-Care-CPD/TagHelpers/GdsFilterCategoryTagHelper.cs b/Childrens-Social-Care-CPD/TagHelpers/GdsFilterCategoryTagHelper.cs index 29bd582e..1ff0d238 100644 --- a/Childrens-Social-Care-CPD/TagHelpers/GdsFilterCategoryTagHelper.cs +++ b/Childrens-Social-Care-CPD/TagHelpers/GdsFilterCategoryTagHelper.cs @@ -31,7 +31,7 @@ public override async Task ProcessAsync(TagHelperContext context, TagHelperOutpu output.Content.AppendHtml(RenderCategoryBody(Index, content)); } - private static IHtmlContent RenderCategoryHeader(int index, string categoryTitle) + private static TagBuilder RenderCategoryHeader(int index, string categoryTitle) { var headerSpan = new TagBuilder("span"); headerSpan.AddCssClass("govuk-accordion__section-button"); @@ -48,7 +48,7 @@ private static IHtmlContent RenderCategoryHeader(int index, string categoryTitle return div; } - private static IHtmlContent RenderCategoryBody(int index, IHtmlContent content) + private TagBuilder RenderCategoryBody(int index, IHtmlContent content) { var fieldsetDiv = new TagBuilder("div"); fieldsetDiv.AddCssClass("govuk-checkboxes"); @@ -56,8 +56,15 @@ private static IHtmlContent RenderCategoryBody(int index, IHtmlContent content) fieldsetDiv.InnerHtml.AppendHtml(content); + var legend = new TagBuilder("legend"); + legend.AddCssClass("govuk-fieldset__legend"); + legend.AddCssClass("govuk-visually-hidden"); + legend.InnerHtml.Append(Title); + var fieldset = new TagBuilder("fieldset"); fieldset.AddCssClass("govuk-fieldset"); + + fieldset.InnerHtml.AppendHtml(legend); fieldset.InnerHtml.AppendHtml(fieldsetDiv); var contentDiv = new TagBuilder("div"); diff --git a/Childrens-Social-Care-CPD/TagHelpers/GdsFilterHelper.cs b/Childrens-Social-Care-CPD/TagHelpers/GdsFilterHelper.cs index 958a744c..b1b4bb75 100644 --- a/Childrens-Social-Care-CPD/TagHelpers/GdsFilterHelper.cs +++ b/Childrens-Social-Care-CPD/TagHelpers/GdsFilterHelper.cs @@ -24,7 +24,7 @@ public override async Task ProcessAsync(TagHelperContext context, TagHelperOutpu output.Content.AppendHtml(RenderBody(content)); } - private static IHtmlContent RenderBody(IHtmlContent content) + private static TagBuilder RenderBody(IHtmlContent content) { var button = new TagBuilder("button"); button.AddCssClass("govuk-button"); @@ -49,7 +49,7 @@ private static IHtmlContent RenderBody(IHtmlContent content) return div; } - private static IHtmlContent RenderHeader() + private static TagBuilder RenderHeader() { var h2 = new TagBuilder("h2"); h2.AddCssClass("govuk-heading-m"); diff --git a/Childrens-Social-Care-CPD/TagHelpers/GovUkPaginationTagHelper.cs b/Childrens-Social-Care-CPD/TagHelpers/GovUkPaginationTagHelper.cs index 0a6c480e..b640e3f8 100644 --- a/Childrens-Social-Care-CPD/TagHelpers/GovUkPaginationTagHelper.cs +++ b/Childrens-Social-Care-CPD/TagHelpers/GovUkPaginationTagHelper.cs @@ -44,7 +44,7 @@ public override void Process(TagHelperContext context, TagHelperOutput output) } } - private static IHtmlContent GeneratesPagesPages(long pageCount, long currentPage, string formatString) + private static TagBuilder GeneratesPagesPages(long pageCount, long currentPage, string formatString) { var ul = new TagBuilder("ul"); ul.AddCssClass("govuk-pagination__list"); @@ -69,7 +69,7 @@ private static IHtmlContent GeneratesPagesPages(long pageCount, long currentPage return ul; } - private static IHtmlContent GenerateEllipses() + private static TagBuilder GenerateEllipses() { var li = new TagBuilder("li"); li.AddCssClass("govuk-pagination__item govuk-pagination__item--ellipses"); @@ -77,7 +77,7 @@ private static IHtmlContent GenerateEllipses() return li; } - private static IHtmlContent GeneratePageNumber(int pageNumber, string href, bool isCurrent) + private static TagBuilder GeneratePageNumber(int pageNumber, string href, bool isCurrent) { var listItem = new TagBuilder("li"); listItem.AddCssClass("govuk-pagination__item"); @@ -100,7 +100,7 @@ private static IHtmlContent GeneratePageNumber(int pageNumber, string href, bool return listItem; } - public IHtmlContent GeneratePreviousButton(string href) + public TagBuilder GeneratePreviousButton(string href) { var path = new TagBuilder("path"); path.Attributes.Add("d", "m6.5938-0.0078125-6.7266 6.7266 6.7441 6.4062 1.377-1.449-4.1856-3.9768h12.896v-2h-12.984l4.2931-4.293-1.414-1.414z"); @@ -132,7 +132,7 @@ public IHtmlContent GeneratePreviousButton(string href) return div; } - public IHtmlContent GenerateNextButton(string href) + public TagBuilder GenerateNextButton(string href) { var path = new TagBuilder("path"); path.Attributes.Add("d", "m8.107-0.0078125-1.4136 1.414 4.2926 4.293h-12.986v2h12.896l-4.1855 3.9766 1.377 1.4492 6.7441-6.4062-6.7246-6.7266z"); diff --git a/Childrens-Social-Care-CPD/Views/Resources/Resource.cshtml b/Childrens-Social-Care-CPD/Views/Resources/Resource.cshtml index 3dc58519..68027e97 100644 --- a/Childrens-Social-Care-CPD/Views/Resources/Resource.cshtml +++ b/Childrens-Social-Care-CPD/Views/Resources/Resource.cshtml @@ -1,7 +1,7 @@ -@using Childrens_Social_Care_CPD.Configuration -@using Childrens_Social_Care_CPD.Contentful.Models; +@using Childrens_Social_Care_CPD.Contentful.Models; @using Childrens_Social_Care_CPD.Contentful.Renderers; @using Contentful.Core.Models; +@using Childrens_Social_Care_CPD.Configuration.Features; @model Content; @@ -35,7 +35,6 @@ } - @@ -44,27 +43,51 @@
    + + @if (featuresConfig.IsEnabled(Features.FeedbackControl)) + { +

    + Give feedback about this page +

    + }
    -@if (featuresConfig.IsEnabled(Features.FeedbackControl)) -{ - -} -
    - +@if (featuresConfig.IsEnabled(Features.FeedbackControl)) +{ +
    + +
    +} + @_relatedContentRenderer.Render(Model.RelatedContent) @section Scripts { - @if (ViewData.TryGetValue("StateModel", out var stateModel) && ((StateModel)stateModel).IncludeMediaPlayer) + @if (featuresConfig.IsEnabled(Features.FeedbackControl)) { - - + } +} + +@if (ViewData.TryGetValue("StateModel", out var stateModel) && ((StateModel)stateModel).IncludeMediaPlayer) +{ + Html.RequireScriptUrl("~/javascript/mediaelement-and-player.min.js"); + Html.RequireScriptUrl("~/javascript/mediaelement-configuration.js"); } \ No newline at end of file diff --git a/Childrens-Social-Care-CPD/Views/SearchResources/SearchResources.cshtml b/Childrens-Social-Care-CPD/Views/SearchResources/SearchResources.cshtml index 751fa5ea..70e5f2da 100644 --- a/Childrens-Social-Care-CPD/Views/SearchResources/SearchResources.cshtml +++ b/Childrens-Social-Care-CPD/Views/SearchResources/SearchResources.cshtml @@ -1,4 +1,4 @@ -@using Childrens_Social_Care_CPD.Configuration +@using Childrens_Social_Care_CPD.Configuration.Features @using Childrens_Social_Care_CPD.Controllers @using Childrens_Social_Care_CPD.Models @using Microsoft.AspNetCore.Html @@ -7,19 +7,25 @@ @inject IFeaturesConfig featuresConfig -@section PageBanner { - -} - -
    +@using (@Html.BeginForm("SearchResources", "SearchResources", null, FormMethod.Get, false, new { id = "searchForm" })) +{ +
    +
    +
    +
    +

    Resources and learning

    + +
    +
    +
    +
    - @using (@Html.BeginForm("SearchResources", "SearchResources", null, FormMethod.Get, false, null)) - { +
    @* Filter column *@

    Results

    -

    We found @Model.TotalCount results

    +

    We found @Model.TotalCount results

    @if (Model.SelectedTags.Any()) { @@ -28,32 +34,33 @@ } - - @{ - var groups = Model.FacetedTags.GroupBy(x => x.Key.Category); - var index = 1; // gov uk js requires starting at 1 for this control - foreach (var group in groups) - { - - @foreach (var kvp in group) - { - var isChecked = Model.SelectedTags.Contains(kvp.Key.TagName); - var count = kvp.Value?.Count ?? 0; - - @kvp.Key.DisplayName (@count) - - } - - index++; +
    + + @{ + var groups = Model.FacetedTags.GroupBy(x => x.Key.Category); + var index = 1; // gov uk js requires starting at 1 for this control + foreach (var group in groups) + { + + @foreach (var kvp in group) + { + var isChecked = Model.SelectedTags.Contains(kvp.Key.TagName); + var count = kvp.Value?.Count ?? 0; + + @kvp.Key.DisplayName (@count) + + } + + index++; + } } - } - - + +
    +
    @* Results column *@
    - @if (Model.TotalPages == 0) { @@ -64,9 +71,9 @@ }
    - } -
    +
    +} -@section Scripts { - +@{ + Html.RequireScriptUrl("~/javascript/pages/search.js"); } \ No newline at end of file diff --git a/Childrens-Social-Care-CPD/Views/SearchResources/_SearchResults.cshtml b/Childrens-Social-Care-CPD/Views/SearchResources/_SearchResults.cshtml index 7bb7a57b..0f6e0f1e 100644 --- a/Childrens-Social-Care-CPD/Views/SearchResources/_SearchResults.cshtml +++ b/Childrens-Social-Care-CPD/Views/SearchResources/_SearchResults.cshtml @@ -20,7 +20,7 @@
    - + -
    +
    + +
    Use this form to provide feedback about this page. If you have more general feedback about this website, please use this feedback form.
    -
    +
    Did you find this page useful? -
    - +
    - + @@ -66,31 +66,39 @@
    -
    -
    @{ - Html.RequireScriptUrl("~/javascript/feedback.js"); + Html.RequireScriptUrl("~/javascript/components/feedback.js"); } \ No newline at end of file diff --git a/Childrens-Social-Care-CPD/Views/Shared/_Footer.cshtml b/Childrens-Social-Care-CPD/Views/Shared/_Footer.cshtml index 966ae358..12ccd471 100644 --- a/Childrens-Social-Care-CPD/Views/Shared/_Footer.cshtml +++ b/Childrens-Social-Care-CPD/Views/Shared/_Footer.cshtml @@ -33,6 +33,11 @@ Terms and conditions +