Skip to content

Commit ebe8332

Browse files
committed
Refactors view to use summary and begins to add a set optional competencies view
1 parent 1e5d9e2 commit ebe8332

File tree

11 files changed

+289
-48
lines changed

11 files changed

+289
-48
lines changed

DigitalLearningSolutions.Data/DataServices/CompetencyAssessmentDataService.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ string direction
6868
public bool UpdateCompetencyAssessmentFeaturesTaskStatus(int id, bool descriptionStatus, bool providerandCategoryStatus, bool vocabularyStatus,
6969
bool workingGroupStatus, bool AllframeworkCompetenciesStatus);
7070
void UpdateSelfAssessmentFromFramework(int selfAssessmentId, int? frameworkId);
71+
bool UpdateOptionalCompetenciesInAssessment(int selfAssessmentId, int[] selectedStructureIds, int[] groupIds);
7172

7273
//INSERT DATA
7374
int InsertCompetencyAssessment(int adminId, int centreId, string competencyAssessmentName);
@@ -867,5 +868,10 @@ FROM FrameworkCompetencies AS FC
867868
);
868869

869870
}
871+
872+
public bool UpdateOptionalCompetenciesInAssessment(int selfAssessmentId, int[] selectedStructureIds, int[] groupIds)
873+
{
874+
throw new NotImplementedException();
875+
}
870876
}
871877
}

DigitalLearningSolutions.Data/Models/CompetencyAssessments/Competency.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
namespace DigitalLearningSolutions.Data.Models.CompetencyAssessments
1+
using DigitalLearningSolutions.Data.Models.Frameworks;
2+
using System.Collections.Generic;
3+
4+
namespace DigitalLearningSolutions.Data.Models.CompetencyAssessments
25
{
36
public class Competency
47
{
@@ -12,5 +15,6 @@ public class Competency
1215
public string? CompetencyDescription { get; set; }
1316
public bool Optional { get; set; }
1417
public bool GroupOptionalCompetencies { get; set; }
18+
public IEnumerable<CompetencyFlag> CompetencyFlags { get; set; } = [];
1519
}
1620
}

DigitalLearningSolutions.Web/Controllers/CompetencyAssessmentsController/CompetencyAssessments.cs

Lines changed: 69 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using DigitalLearningSolutions.Web.Helpers;
99
using DigitalLearningSolutions.Web.Models.Enums;
1010
using DigitalLearningSolutions.Web.ViewModels.CompetencyAssessments;
11+
using DigitalLearningSolutions.Web.ViewModels.LearningPortal.SelfAssessments;
1112
using GDS.MultiPageFormData.Enums;
1213
using Microsoft.AspNetCore.Mvc;
1314
using Microsoft.AspNetCore.Mvc.Rendering;
@@ -652,7 +653,42 @@ public IActionResult ViewSelectedCompetencies(ViewSelectedCompetenciesFormData m
652653
return RedirectToAction("ManageCompetencyAssessment", new { competencyAssessmentId = model.ID });
653654
}
654655
[HttpGet]
655-
[Route("/CompetencyAssessments/{competencyAssessmentId}/Competencies/Optional")]
656+
[Route("/CompetencyAssessments/{competencyAssessmentId}/Competencies/Optional/Manage")]
657+
public IActionResult ManageOptionalCompetencies(int competencyAssessmentId)
658+
{
659+
var adminId = GetAdminID();
660+
var competencyAssessmentBase = competencyAssessmentService.GetCompetencyAssessmentBaseById(competencyAssessmentId, adminId);
661+
if (competencyAssessmentBase == null)
662+
{
663+
logger.LogWarning($"Failed to load Optional Competencies page for competencyAssessmentId: {competencyAssessmentId} adminId: {adminId}");
664+
return StatusCode(500);
665+
}
666+
if (competencyAssessmentBase.UserRole < 2)
667+
{
668+
return StatusCode(403);
669+
}
670+
var competencies = competencyAssessmentService.GetCompetenciesForCompetencyAssessment(competencyAssessmentId).Where(c => c.Optional == true);
671+
var competencyIds = competencies.Select(c => c.CompetencyID).ToArray();
672+
var competencyFlags = frameworkService.GetSelectedCompetencyFlagsByCompetecyIds(competencyIds);
673+
foreach (var competency in competencies)
674+
competency.CompetencyFlags = competencyFlags.Where(f => f.CompetencyId == competency.CompetencyID);
675+
var competencyAssessmentTaskStatus = competencyAssessmentService.GetCompetencyAssessmentTaskStatus(competencyAssessmentId, null);
676+
var model = new SelectOptionalCompetenciesViewModel(competencyAssessmentBase, competencies, competencyAssessmentTaskStatus.OptionalCompetenciesTaskStatus);
677+
return View(model);
678+
}
679+
[HttpPost]
680+
[Route("/CompetencyAssessments/{competencyAssessmentId}/Competencies/Optional/Manage")]
681+
public IActionResult ManageOptionalCompetencies(ViewSelectedCompetenciesFormData model)
682+
{
683+
if (model.TaskStatus == null)
684+
{
685+
model.TaskStatus = false;
686+
}
687+
competencyAssessmentService.UpdateOptionalCompetenciesTaskStatus(model.ID, model.TaskStatus.Value, null);
688+
return RedirectToAction("ManageCompetencyAssessment", new { competencyAssessmentId = model.ID });
689+
}
690+
[HttpGet]
691+
[Route("/CompetencyAssessments/{competencyAssessmentId}/Competencies/Optional/Select")]
656692
public IActionResult SelectOptionalCompetencies(int competencyAssessmentId)
657693
{
658694
var adminId = GetAdminID();
@@ -667,12 +703,42 @@ public IActionResult SelectOptionalCompetencies(int competencyAssessmentId)
667703
return StatusCode(403);
668704
}
669705
var competencies = competencyAssessmentService.GetCompetenciesForCompetencyAssessment(competencyAssessmentId);
670-
706+
var competencyIds = competencies.Select(c => c.CompetencyID).ToArray();
707+
var competencyFlags = frameworkService.GetSelectedCompetencyFlagsByCompetecyIds(competencyIds);
708+
foreach (var competency in competencies)
709+
competency.CompetencyFlags = competencyFlags.Where(f => f.CompetencyId == competency.CompetencyID);
671710
var competencyAssessmentTaskStatus = competencyAssessmentService.GetCompetencyAssessmentTaskStatus(competencyAssessmentId, null);
672711
var model = new SelectOptionalCompetenciesViewModel(competencyAssessmentBase, competencies, competencyAssessmentTaskStatus.OptionalCompetenciesTaskStatus);
673712
return View(model);
674713
}
675-
714+
[HttpPost]
715+
[Route("/CompetencyAssessments/{competencyAssessmentId}/Competencies/Optional/Select")]
716+
public IActionResult SelectOptionalCompetencies(SelectOptionalCompetenciesFormData model)
717+
{
718+
if (!ModelState.IsValid)
719+
{
720+
var adminId = GetAdminID();
721+
var competencyAssessmentBase = competencyAssessmentService.GetCompetencyAssessmentBaseById(model.ID, adminId);
722+
if (competencyAssessmentBase == null)
723+
{
724+
logger.LogWarning($"Failed to load Optional Competencies page for competencyAssessmentId: {model.ID} adminId: {adminId}");
725+
return StatusCode(500);
726+
}
727+
if (competencyAssessmentBase.UserRole < 2)
728+
{
729+
return StatusCode(403);
730+
}
731+
var competencies = competencyAssessmentService.GetCompetenciesForCompetencyAssessment(model.ID);
732+
var competencyIds = competencies.Select(c => c.CompetencyID).ToArray();
733+
var competencyFlags = frameworkService.GetSelectedCompetencyFlagsByCompetecyIds(competencyIds);
734+
foreach (var competency in competencies)
735+
competency.CompetencyFlags = competencyFlags.Where(f => f.CompetencyId == competency.CompetencyID);
736+
var viewModel = new SelectOptionalCompetenciesViewModel(competencyAssessmentBase, competencies, model.TaskStatus);
737+
return View("SelectOptionalCompetencies", viewModel);
738+
}
739+
competencyAssessmentService.UpdateOptionalCompetenciesInAssessment(model.ID, model.SelectedCompetencyIds ?? [], model.GroupIds ?? []);
740+
return RedirectToAction("ManageCompetencyAssessment", new { competencyAssessmentId = model.ID });
741+
}
676742
[Route("/CompetencyAssessments/Framework/{frameworkId}/{competencyAssessmentId}/Features")]
677743
public IActionResult CompetencyAssessmentFeatures(int competencyAssessmentId, int? frameworkId = null)
678744
{
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
document.addEventListener('DOMContentLoaded', () => {
2+
const groups = document.querySelectorAll<HTMLDivElement>('.nhsuk-checkboxes');
3+
4+
groups.forEach((group) => {
5+
const groupToggle = group.querySelector<HTMLInputElement>('input[name="GroupIds"]');
6+
if (!groupToggle) return;
7+
8+
// All individual competency checkboxes in the group
9+
const childCheckboxes = group.querySelectorAll<HTMLInputElement>(
10+
'input[name="SelectedCompetencyIds"]',
11+
);
12+
13+
const updateState = () => {
14+
const isChecked = groupToggle.checked;
15+
16+
childCheckboxes.forEach((cb) => {
17+
if (isChecked) {
18+
// eslint-disable-next-line no-param-reassign
19+
cb.checked = true; // force selected
20+
// eslint-disable-next-line no-param-reassign
21+
cb.disabled = true; // lock them
22+
} else {
23+
// eslint-disable-next-line no-param-reassign
24+
cb.disabled = false; // re-enable when group is unchecked
25+
// optional: leave cb.checked unchanged
26+
}
27+
});
28+
};
29+
30+
// Run when the group checkbox changes
31+
groupToggle.addEventListener('change', updateState);
32+
33+
// Also run at page load in case some are pre-checked server-side
34+
updateState();
35+
});
36+
});

DigitalLearningSolutions.Web/Services/CompetencyAssessmentService.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ string direction
5757
bool UpdateCompetencyAssessmentFeaturesTaskStatus(int id, bool descriptionStatus, bool providerandCategoryStatus, bool vocabularyStatus,
5858
bool workingGroupStatus, bool AllframeworkCompetenciesStatus);
5959
void UpdateSelfAssessmentFromFramework(int selfAssessmentId, int? frameworkId);
60+
bool UpdateOptionalCompetenciesInAssessment(int selfAssessmentId, int[] selectedStructureIds, int[] groupIds);
6061

6162
//INSERT DATA
6263
int InsertCompetencyAssessment(int adminId, int centreId, string competencyAssessmentName, int? frameworkId);
@@ -290,5 +291,10 @@ public void UpdateSelfAssessmentFromFramework(int selfAssessmentId, int? framewo
290291
{
291292
return competencyAssessmentDataService.GetSelfAssessmentStructure(competencyAssessmentId);
292293
}
294+
295+
public bool UpdateOptionalCompetenciesInAssessment(int selfAssessmentId, int[] selectedStructureIds, int[] groupIds)
296+
{
297+
return competencyAssessmentDataService.UpdateOptionalCompetenciesInAssessment(selfAssessmentId, selectedStructureIds, groupIds);
293298
}
299+
}
294300
}

DigitalLearningSolutions.Web/ViewModels/CompetencyAssessments/SelectOptionalCompetenciesFormData.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ public class SelectOptionalCompetenciesFormData
44
{
55
public int ID { get; set; }
66
public bool? TaskStatus { get; set; }
7+
public int? MinimumOptionalCompetencies { get; set; }
8+
public string? ManageOptionalCompetenciesPrompt { get; set; }
79
public int[] SelectedCompetencyIds { get; set; } = [];
10+
public int[] GroupIds { get; set; } = [];
811
}
912
}

DigitalLearningSolutions.Web/ViewModels/CompetencyAssessments/SelectOptionalCompetenciesViewModel.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@ public SelectOptionalCompetenciesViewModel(CompetencyAssessmentBase competencyAs
1212
ID = competencyAssessmentBase.ID;
1313
TaskStatus = taskStatus;
1414
CompetencyAssessmentName = competencyAssessmentBase.CompetencyAssessmentName;
15+
MinimumOptionalCompetencies = competencyAssessmentBase.MinimumOptionalCompetencies;
16+
ManageOptionalCompetenciesPrompt = competencyAssessmentBase.ManageOptionalCompetenciesPrompt;
1517
UserRole = competencyAssessmentBase.UserRole;
16-
Competencies = competencies.Where(c => c.Optional == true);
18+
CompetencyGroups = competencies.GroupBy(competency => competency.GroupName);
1719
VocabularySingular = FrameworkVocabularyHelper.VocabularySingular(competencyAssessmentBase.Vocabulary);
1820
VocabularyPlural = FrameworkVocabularyHelper.VocabularyPlural(competencyAssessmentBase.Vocabulary);
1921
SelectedCompetencyIds = competencies.Where(c => c.Optional == true).Select(c => c.CompetencyID).ToArray();
@@ -22,6 +24,6 @@ public SelectOptionalCompetenciesViewModel(CompetencyAssessmentBase competencyAs
2224
public int UserRole { get; set; }
2325
public string VocabularySingular { get; set; }
2426
public string VocabularyPlural { get; set; }
25-
public IEnumerable<Competency> Competencies { get; set; }
27+
public IEnumerable<IGrouping<string, Competency>>? CompetencyGroups { get; set; }
2628
}
2729
}

DigitalLearningSolutions.Web/Views/CompetencyAssessments/EditRoleProfileLinks.cshtml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
<ol class="nhsuk-breadcrumb__list">
1616
<li class="nhsuk-breadcrumb__item"><a class="nhsuk-breadcrumb__link trigger-loader" asp-action="ViewCompetencyAssessments" asp-route-tabname="Mine">Competency Assessments</a></li>
1717
<li class="nhsuk-breadcrumb__item"><a class="nhsuk-breadcrumb__link trigger-loader" asp-action="ManageCompetencyAssessment" asp-route-competencyAssessmentId="@Model.ID">Manage Competency Assessment</a></li>
18-
<li class="nhsuk-breadcrumb__item">Introductory text</li>
18+
<li class="nhsuk-breadcrumb__item">Role Profile Links</li>
1919
</ol>
2020
<p class="nhsuk-breadcrumb__back"><a class="nhsuk-breadcrumb__backlink" asp-action="ManageCompetencyAssessment" asp-route-competencyAssessmentId="@Model.ID">Back to competency assessment detail</a></p>
2121
</div>

DigitalLearningSolutions.Web/Views/CompetencyAssessments/ManageCompetencyAssessment.cshtml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
<li class="nhsuk-task-list__item nhsuk-task-list__item--with-link">
5959
<div class="nhsuk-task-list__name-and-hint" aria-describedby="select-frameworks-status">
6060
<a class="nhsuk-link nhsuk-task-list__link" asp-action="SelectFrameworkSources" asp-route-actionName="@(Model.CompetencyAssessmentTaskStatus.FrameworkLinksTaskStatus == null ? "AddFramework" : "Summary" )" asp-route-competencyAssessmentId="@ViewContext.RouteData.Values["competencyAssessmentId"]">
61-
Select competency framework sources
61+
Select (@Model.VocabularySingular) framework sources
6262
</a>
6363
</div>
6464
<div class="nhsuk-task-list__status" id="select-frameworks-status">
@@ -143,7 +143,7 @@
143143
@if (Model.CompetencyAssessmentTaskStatus.SelectCompetenciesTaskStatus == null)
144144
{
145145
<div class="nhsuk-task-list__name-and-hint" aria-describedby="optional-competencies-status">
146-
Identify optional @Model.VocabularyPlural.ToLower()
146+
Manage optional @Model.VocabularyPlural.ToLower()
147147
</div>
148148
<div class="nhsuk-task-list__status nhsuk-task-list__status--cannot-start-yet" id="optional-competencies-status">
149149
Cannot start yet
@@ -152,8 +152,8 @@
152152
else
153153
{
154154
<div class="nhsuk-task-list__name-and-hint" aria-describedby="optional-competencies-status">
155-
<a class="nhsuk-link nhsuk-task-list__link" asp-action="SelectOptionalCompetencies" asp-route-competencyAssessmentId="@ViewContext.RouteData.Values["competencyAssessmentId"]">
156-
Identify optional @Model.VocabularyPlural.ToLower()
155+
<a class="nhsuk-link nhsuk-task-list__link" asp-action="ManageOptionalCompetencies" asp-route-competencyAssessmentId="@ViewContext.RouteData.Values["competencyAssessmentId"]">
156+
Manage optional @Model.VocabularyPlural.ToLower()
157157
</a>
158158
</div>
159159
<div class="nhsuk-task-list__status" id="optional-competencies-status">

0 commit comments

Comments
 (0)