-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #505 from DFE-Digital/edit-contacts-ui
Create Edit contacts UI and hide behind feature flag
- Loading branch information
Showing
25 changed files
with
627 additions
and
98 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
25 changes: 25 additions & 0 deletions
25
DfE.FindInformationAcademiesTrusts/Pages/Shared/_ErrorSummary.cshtml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
@model Microsoft.AspNetCore.Mvc.RazorPages.PageModel | ||
|
||
@if (!Model.ModelState.IsValid) | ||
{ | ||
<div class="govuk-error-summary" aria-labelledby="error-summary-title" tabindex="-1" data-module="govuk-error-summary"> | ||
<div role="alert"> | ||
<h2 class="govuk-error-summary__title" id="error-summary-title"> | ||
There is a problem | ||
</h2> | ||
<div class="govuk-error-summary__body"> | ||
<ul class="govuk-list govuk-error-summary__list" data-testid="error-summary"> | ||
@foreach (var (key, modelState) in Model.ModelState) | ||
{ | ||
@foreach (var error in modelState.Errors) | ||
{ | ||
<li> | ||
<a href="#@key" data-testid="error-link-@key">@error.ErrorMessage</a> | ||
</li> | ||
} | ||
} | ||
</ul> | ||
</div> | ||
</div> | ||
</div> | ||
} |
158 changes: 93 additions & 65 deletions
158
DfE.FindInformationAcademiesTrusts/Pages/Trusts/Contacts.cshtml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,99 +1,127 @@ | ||
@page | ||
@using DfE.FindInformationAcademiesTrusts.Configuration | ||
@using DfE.FindInformationAcademiesTrusts.Data | ||
@model ContactsModel | ||
|
||
@{ | ||
Layout = "_TrustLayout"; | ||
} | ||
|
||
<section class="govuk-!-margin-top-8 govuk-!-margin-bottom-9"> | ||
<div class="govuk-summary-card"> | ||
<section class="govuk-!-margin-bottom-9"> | ||
<h2 class="govuk-heading-m"> | ||
Contacts at DfE | ||
</h2> | ||
<feature name="@FeatureFlags.EditContactsUI"> | ||
@if (!string.IsNullOrWhiteSpace(TempData["ContactUpdatedMessage"] as string)) | ||
{ | ||
<div class="govuk-notification-banner govuk-notification-banner--success" role="alert" aria-labelledby="govuk-notification-banner-title" data-module="govuk-notification-banner"> | ||
<div class="govuk-notification-banner__header"> | ||
<h2 class="govuk-notification-banner__title" id="govuk-notification-banner-title"> | ||
Success | ||
</h2> | ||
</div> | ||
<div class="govuk-notification-banner__content"> | ||
<h3 class="govuk-notification-banner__heading"> | ||
@TempData["ContactUpdatedMessage"] | ||
</h3> | ||
</div> | ||
</div> | ||
} | ||
</feature> | ||
<div class="govuk-summary-card" data-testid="trust-relationship-manager"> | ||
<div class="govuk-summary-card__title-wrapper"> | ||
<h2 class="govuk-summary-card__title">DfE contacts</h2> | ||
</div> | ||
<div class="govuk-summary-card__content"> | ||
<dl class="govuk-summary-list"> | ||
<div class="govuk-summary-list__row" data-testid="trust-relationship-manager"> | ||
<dt class="govuk-summary-list__key"> | ||
Trust relationship manager | ||
</dt> | ||
@{ DisplayContact(Model.TrustRelationshipManager); } | ||
<h3 class="govuk-summary-card__title"> | ||
Trust relationship manager | ||
</h3> | ||
<feature name="@FeatureFlags.EditContactsUI"> | ||
<div class="govuk-summary-card__actions"> | ||
<a class="govuk-link" asp-page="/Trusts/Contacts/EditTrustRelationshipManager" asp-route-uid="@Model.Uid">Change<span class="govuk-visually-hidden"> details of this contact (Trust relationship manager)</span></a> | ||
</div> | ||
<div class="govuk-summary-list__row" data-testid="sfso-lead"> | ||
<dt class="govuk-summary-list__key"> | ||
SFSO (Schools financial support and oversight) lead | ||
</dt> | ||
@{ DisplayContact(Model.SfsoLead); } | ||
</feature> | ||
</div> | ||
@{ DisplayContact(Model.TrustRelationshipManager); } | ||
</div> | ||
<div class="govuk-summary-card" data-testid="sfso-lead"> | ||
<div class="govuk-summary-card__title-wrapper"> | ||
<h3 class="govuk-summary-card__title"> | ||
SFSO (Schools financial support and oversight) lead | ||
</h3> | ||
<feature name="@FeatureFlags.EditContactsUI"> | ||
<div class="govuk-summary-card__actions"> | ||
<a class="govuk-link" asp-page="/Trusts/Contacts/EditSfsoLead" asp-route-uid="@Model.Uid">Change<span class="govuk-visually-hidden"> details of this contact (SFSO Lead)</span></a> | ||
</div> | ||
</dl> | ||
</feature> | ||
</div> | ||
@{ DisplayContact(Model.SfsoLead); } | ||
</div> | ||
</section> | ||
|
||
<section class="govuk-!-margin-top-8 govuk-!-margin-bottom-9"> | ||
<div class="govuk-summary-card"> | ||
<h2 class="govuk-heading-m"> | ||
Contacts at the trust | ||
</h2> | ||
<div class="govuk-summary-card" data-testid="accounting-officer"> | ||
<div class="govuk-summary-card__title-wrapper"> | ||
<h2 class="govuk-summary-card__title">Trust contacts</h2> | ||
<h3 class="govuk-summary-card__title"> | ||
Accounting officer | ||
</h3> | ||
</div> | ||
<div class="govuk-summary-card__content"> | ||
<dl class="govuk-summary-list"> | ||
<div class="govuk-summary-list__row" data-testid="accounting-officer"> | ||
<dt class="govuk-summary-list__key"> | ||
Accounting officer | ||
</dt> | ||
@{ DisplayContact(Model.AccountingOfficer); } | ||
</div> | ||
<div class="govuk-summary-list__row" data-testid="chair-of-trustees"> | ||
<dt class="govuk-summary-list__key"> | ||
Chair of trustees | ||
</dt> | ||
@{ DisplayContact(Model.ChairOfTrustees); } | ||
</div> | ||
<div class="govuk-summary-list__row" data-testid="chief-financial-officer"> | ||
<dt class="govuk-summary-list__key"> | ||
Chief financial officer | ||
</dt> | ||
@{ DisplayContact(Model.ChiefFinancialOfficer); } | ||
</div> | ||
|
||
</dl> | ||
@{ DisplayContact(Model.AccountingOfficer); } | ||
</div> | ||
<div class="govuk-summary-card" data-testid="chair-of-trustees"> | ||
<div class="govuk-summary-card__title-wrapper"> | ||
<h3 class="govuk-summary-card__title"> | ||
Chair of trustees | ||
</h3> | ||
</div> | ||
@{ DisplayContact(Model.ChairOfTrustees); } | ||
</div> | ||
<div class="govuk-summary-card" data-testid="chief-financial-officer"> | ||
<div class="govuk-summary-card__title-wrapper"> | ||
<h3 class="govuk-summary-card__title"> | ||
Chief financial officer | ||
</h3> | ||
</div> | ||
@{ DisplayContact(Model.ChiefFinancialOfficer); } | ||
</div> | ||
</section> | ||
|
||
@functions { | ||
|
||
private void DisplayContact(Person? contactToDisplay) | ||
{ | ||
<dd class="govuk-summary-list__value"> | ||
|
||
@if (contactToDisplay is null) | ||
{ | ||
<p class="govuk-body">@ContactsModel.ContactInformationNotAvailableMessage</p> | ||
} | ||
else | ||
{ | ||
@if (!string.IsNullOrWhiteSpace(contactToDisplay.FullName)) | ||
{ | ||
<p class="govuk-body" data-testid="contact-name">@contactToDisplay.FullName</p> | ||
} | ||
else | ||
{ | ||
<p class="govuk-body">@ContactsModel.ContactNameNotAvailableMessage</p> | ||
} | ||
|
||
<p class="govuk-body"> | ||
@if (contactToDisplay.Email is not null) | ||
<div class="govuk-summary-card__content"> | ||
<dl class="govuk-summary-list"> | ||
<div class="govuk-summary-list__row"> | ||
<dt class="govuk-summary-list__key"> | ||
Name | ||
</dt> | ||
@if (!string.IsNullOrWhiteSpace(contactToDisplay?.FullName)) | ||
{ | ||
<dd class="govuk-summary-list__value" data-testid="contact-name">@contactToDisplay.FullName</dd> | ||
} | ||
else | ||
{ | ||
<dd class="govuk-summary-list__value" data-testid="contact-name">@ContactsModel.ContactNameNotAvailableMessage</dd> | ||
} | ||
</div> | ||
<div class="govuk-summary-list__row"> | ||
<dt class="govuk-summary-list__key"> | ||
Email address | ||
</dt> | ||
@if (contactToDisplay?.Email is not null) | ||
{ | ||
<a class="govuk-link" href="mailto:@contactToDisplay.Email" rel="noopener" target="_blank" data-testid="contact-email">@contactToDisplay.Email</a> | ||
<dd class="govuk-summary-list__value"> | ||
<a class="govuk-link" href="mailto:@contactToDisplay.Email" rel="noopener" target="_blank" data-testid="contact-email">@contactToDisplay.Email</a> | ||
</dd> | ||
} | ||
else | ||
{ | ||
<a class="govuk-body">@ContactsModel.ContactEmailNotAvailableMessage</a> | ||
<dd class="govuk-summary-list__value" data-testid="contact-email">@ContactsModel.ContactEmailNotAvailableMessage</dd> | ||
} | ||
</p> | ||
} | ||
</dd> | ||
</div> | ||
</dl> | ||
</div> | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
69 changes: 69 additions & 0 deletions
69
DfE.FindInformationAcademiesTrusts/Pages/Trusts/Contacts/EditContactModel.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
using System.ComponentModel.DataAnnotations; | ||
using DfE.FindInformationAcademiesTrusts.Data; | ||
using DfE.FindInformationAcademiesTrusts.Services.DataSource; | ||
using DfE.FindInformationAcademiesTrusts.Services.Trust; | ||
using Microsoft.AspNetCore.Mvc; | ||
using Microsoft.AspNetCore.Mvc.ModelBinding; | ||
|
||
namespace DfE.FindInformationAcademiesTrusts.Pages.Trusts.Contacts; | ||
|
||
public abstract class EditContactModel( | ||
ITrustProvider trustProvider, | ||
IDataSourceService dataSourceService, | ||
ITrustService trustService, | ||
ILogger<EditContactModel> logger, | ||
string roleText) | ||
: TrustsAreaModel(trustProvider, dataSourceService, trustService, | ||
logger, $"Edit {roleText}") | ||
{ | ||
public const string NameField = "Name"; | ||
public const string EmailField = "Email"; | ||
|
||
[BindProperty] [BindRequired] public string? Name { get; set; } | ||
|
||
[BindProperty] | ||
[BindRequired] | ||
[EmailAddress(ErrorMessage = "Enter an email address in the correct format, like [email protected]")] | ||
[RegularExpression(".*@education.gov.uk$", ErrorMessage = "Enter a DfE email address ending in @education.gov.uk")] | ||
public string? Email { get; set; } | ||
|
||
[TempData] public string ContactUpdatedMessage { get; set; } = string.Empty; | ||
|
||
private string RoleText { get; init; } = roleText; | ||
|
||
public async Task<IActionResult> OnPostAsync() | ||
{ | ||
if (!ModelState.IsValid) | ||
{ | ||
return await base.OnGetAsync(); | ||
} | ||
|
||
ContactUpdatedMessage = $"Changes made to the {RoleText} were successfully updated."; | ||
return RedirectToPage("/Trusts/Contacts", new { Uid }); | ||
} | ||
|
||
public string GetErrorClass(string key) | ||
{ | ||
return ModelState.ContainsKey(key) && ModelState[key]!.Errors.Any() ? "govuk-form-group--error" : string.Empty; | ||
} | ||
|
||
public string GenerateErrorAriaDescribedBy(string key) | ||
{ | ||
return string.Join(" ", GetErrorList(key).Select(value => $"error-{key}-{value.index}")); | ||
} | ||
|
||
public (int index, string errorMessage)[] GetErrorList(string key) | ||
{ | ||
if (ModelState.ContainsKey(key)) | ||
{ | ||
return ModelState[key]!.Errors.Select((error, index) => (index, error.ErrorMessage)).ToArray(); | ||
} | ||
|
||
return []; | ||
} | ||
|
||
public string GeneratePageTitle() | ||
{ | ||
return $"{(ModelState.IsValid ? string.Empty : "Error: ")}{PageTitle ?? PageName} - {TrustSummary.Name}"; | ||
} | ||
} |
9 changes: 9 additions & 0 deletions
9
DfE.FindInformationAcademiesTrusts/Pages/Trusts/Contacts/EditSfsoLead.cshtml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
@page | ||
@model EditSfsoLeadModel | ||
|
||
@{ | ||
Layout = "_Layout"; | ||
ViewData["Title"] = Model.GeneratePageTitle(); | ||
} | ||
|
||
<partial name="_EditContactsForm" model="@Model"/> |
31 changes: 31 additions & 0 deletions
31
DfE.FindInformationAcademiesTrusts/Pages/Trusts/Contacts/EditSfsoLead.cshtml.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
using DfE.FindInformationAcademiesTrusts.Configuration; | ||
using DfE.FindInformationAcademiesTrusts.Data; | ||
using DfE.FindInformationAcademiesTrusts.Services.DataSource; | ||
using DfE.FindInformationAcademiesTrusts.Services.Trust; | ||
using Microsoft.AspNetCore.Mvc; | ||
using Microsoft.FeatureManagement.Mvc; | ||
|
||
namespace DfE.FindInformationAcademiesTrusts.Pages.Trusts.Contacts; | ||
|
||
[FeatureGate(FeatureFlags.EditContactsUI)] | ||
public class EditSfsoLeadModel( | ||
ITrustProvider trustProvider, | ||
IDataSourceService dataSourceService, | ||
ILogger<EditSfsoLeadModel> logger, | ||
ITrustService trustService) | ||
: EditContactModel(trustProvider, dataSourceService, trustService, | ||
logger, "SFSO (Schools financial support and oversight) lead") | ||
{ | ||
public override async Task<IActionResult> OnGetAsync() | ||
{ | ||
var pageResult = await base.OnGetAsync(); | ||
|
||
if (pageResult.GetType() == typeof(NotFoundResult)) return pageResult; | ||
|
||
var contacts = await TrustService.GetTrustContactsAsync(Uid); | ||
|
||
Email = contacts.SfsoLead?.Email; | ||
Name = contacts.SfsoLead?.FullName; | ||
return pageResult; | ||
} | ||
} |
9 changes: 9 additions & 0 deletions
9
DfE.FindInformationAcademiesTrusts/Pages/Trusts/Contacts/EditTrustRelationshipManager.cshtml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
@page | ||
@model EditTrustRelationshipManagerModel | ||
|
||
@{ | ||
Layout = "_Layout"; | ||
ViewData["Title"] = Model.GeneratePageTitle(); | ||
} | ||
|
||
<partial name="_EditContactsForm" model="@Model"/> |
Oops, something went wrong.