Skip to content

Commit 3b73a62

Browse files
committed
Merge branch 'DLS-Release-v1.2.0' into UAT
2 parents 5c53542 + 63521f4 commit 3b73a62

File tree

108 files changed

+4352
-21874
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

108 files changed

+4352
-21874
lines changed

.github/workflows/build-and-deploy-dev.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,4 +138,4 @@ jobs:
138138
{
139139
Remove-Item -LiteralPath 'E:/web/${{env.SitePath}}-PREVIOUS' -Force -Recurse
140140
}
141-
Remove-Item 'E:/web/${{env.SitePath}}/app_offline.htm' -Force
141+
Remove-Item 'E:/web/${{env.SitePath}}/app_offline.htm' -Force

DigitalLearningSolutions.Data/DataServices/FrameworkDataService.cs

Lines changed: 110 additions & 69 deletions
Large diffs are not rendered by default.

DigitalLearningSolutions.Data/Models/Frameworks/FrameworkCompetency.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ public class FrameworkCompetency : BaseSearchableItem
1414
public int AssessmentQuestions { get; set; }
1515
public int CompetencyLearningResourcesCount { get; set; }
1616
public string? FrameworkName { get; set; }
17+
public bool? AlwaysShowDescription { get; set; }
1718

1819
public override string SearchableName
1920
{
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace DigitalLearningSolutions.Data.Models.Frameworks.Import
8+
{
9+
public class BulkCompetency
10+
{
11+
public int? ID { get; set; }
12+
public string? CompetencyGroup { get; set; }
13+
public string? GroupDescription { get; set; }
14+
public string? Competency { get; set; }
15+
public string? CompetencyDescription { get; set; }
16+
public bool? AlwaysShowDescription { get; set; }
17+
public string? FlagsCsv { get; set; }
18+
}
19+
}

DigitalLearningSolutions.Data/Models/Frameworks/Import/CompetencyTableRow.cs

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,69 @@
11
namespace DigitalLearningSolutions.Data.Models.Frameworks.Import
22
{
33
using ClosedXML.Excel;
4-
using System;
5-
using System.Collections.Generic;
6-
using System.Text;
4+
75
public enum RowStatus
86
{
97
NotYetProcessed,
108
Skipped,
11-
CompetencyGroupInserted,
129
CompetencyGroupAndCompetencyInserted,
13-
CompetencyInserted
10+
CompetencyInserted,
11+
CompetencyUpdated,
12+
CompetencyGroupInserted,
13+
CompetencyGroupUpdated,
14+
CompetencyGroupAndCompetencyUpdated,
15+
InvalidAlwaysShowDescription,
16+
InvalidId
1417
}
15-
public class CompetencyTableRow
18+
public class CompetencyTableRow : BulkCompetency
1619
{
1720
public CompetencyTableRow(IXLTable table, IXLRangeRow row)
1821
{
1922
string? FindFieldValue(string name)
2023
{
21-
var colNumber = table.FindColumn(col => col.FirstCell().Value.ToString()?.ToLower() == name).ColumnNumber();
24+
var colNumber = table.FindColumn(col => col.FirstCell().Value.ToString()?.ToLower() == name.ToLower()).ColumnNumber();
2225
return row.Cell(colNumber).GetValue<string?>();
2326
}
2427

2528
RowNumber = row.RowNumber();
26-
CompetencyGroupName = FindFieldValue("competency group");
27-
CompetencyName = FindFieldValue("competency name");
28-
CompetencyDescription = FindFieldValue("competency description");
29+
ID = row.Cell(1).GetValue<int?>();
30+
CompetencyGroup = row.Cell(2).GetValue<string?>();
31+
GroupDescription = row.Cell(3).GetValue<string?>();
32+
Competency = row.Cell(4).GetValue<string?>();
33+
CompetencyDescription = row.Cell(5).GetValue<string?>();
34+
AlwaysShowDescriptionRaw = FindFieldValue("AlwaysShowDescription");
35+
AlwaysShowDescription = bool.TryParse(AlwaysShowDescriptionRaw, out var hasPrn) ? hasPrn : (bool?)null;
36+
FlagsCsv = FindFieldValue("FlagsCSV");
2937
RowStatus = RowStatus.NotYetProcessed;
3038
}
3139
public int RowNumber { get; set; }
32-
public string? CompetencyGroupName { get; set; }
33-
public string? CompetencyName { get; set; }
34-
public string? CompetencyDescription { get; set; }
40+
public int CompetencyOrderNumber { get; set; }
41+
public string? AlwaysShowDescriptionRaw { get; set; }
3542
public ImportCompetenciesResult.ErrorReason? Error { get; set; }
3643
public RowStatus RowStatus { get; set; }
44+
public bool Reordered { get; set; } = false;
3745
public bool Validate()
3846
{
39-
if (string.IsNullOrEmpty(CompetencyName))
47+
if (string.IsNullOrEmpty(Competency))
4048
{
4149
Error = ImportCompetenciesResult.ErrorReason.MissingCompetencyName;
4250
}
43-
else if (CompetencyGroupName?.Length > 255)
51+
else if (CompetencyGroup?.Length > 255)
4452
{
4553
Error = ImportCompetenciesResult.ErrorReason.TooLongCompetencyGroupName;
4654
}
47-
else if (CompetencyName.Length > 500)
55+
else if (Competency.Length > 500)
4856
{
4957
Error = ImportCompetenciesResult.ErrorReason.TooLongCompetencyName;
5058
}
59+
else if (!string.IsNullOrWhiteSpace(AlwaysShowDescriptionRaw) && !bool.TryParse(AlwaysShowDescriptionRaw, out _))
60+
{
61+
Error = ImportCompetenciesResult.ErrorReason.InvalidAlwaysShowDescription;
62+
}
63+
else if (RowStatus == RowStatus.InvalidId)
64+
{
65+
Error = ImportCompetenciesResult.ErrorReason.InvalidId;
66+
}
5167

5268
return !Error.HasValue;
5369
}

DigitalLearningSolutions.Data/Models/Frameworks/Import/ImportCompetenciesResult.cs

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@ public class ImportCompetenciesResult
88
{
99
public enum ErrorReason
1010
{
11+
InvalidId,
1112
MissingCompetencyName,
12-
TooLongCompetencyGroupName,
1313
TooLongCompetencyName,
14-
AlreadyExists
14+
TooLongCompetencyGroupName,
15+
InvalidAlwaysShowDescription
1516
}
1617
public ImportCompetenciesResult() { }
1718

@@ -20,16 +21,39 @@ IReadOnlyCollection<CompetencyTableRow> competencyTableRows
2021
)
2122
{
2223
ProcessedCount = competencyTableRows.Count;
23-
CompetenciesInsertedCount = competencyTableRows.Count(dr => dr.RowStatus == RowStatus.CompetencyInserted | dr.RowStatus == RowStatus.CompetencyGroupAndCompetencyInserted);
24-
CompetencyGroupsInsertedCount = competencyTableRows.Count(dr => dr.RowStatus == RowStatus.CompetencyGroupInserted | dr.RowStatus == RowStatus.CompetencyGroupAndCompetencyInserted);
25-
SkippedCount = competencyTableRows.Count(dr => dr.RowStatus == RowStatus.Skipped);
24+
CompetencyAddedCount = competencyTableRows.Count(dr => dr.RowStatus == RowStatus.CompetencyInserted | dr.RowStatus == RowStatus.CompetencyGroupAndCompetencyInserted);
25+
CompetencyUpdatedCount = competencyTableRows.Count(dr => dr.RowStatus == RowStatus.CompetencyUpdated | dr.RowStatus == RowStatus.CompetencyGroupAndCompetencyUpdated);
26+
GroupAddedCount = competencyTableRows.Count(dr => dr.RowStatus == RowStatus.CompetencyGroupInserted | dr.RowStatus == RowStatus.CompetencyGroupAndCompetencyInserted);
27+
SkippedCount = competencyTableRows.Count(dr => dr.RowStatus == RowStatus.Skipped && dr.Reordered == false);
28+
CompetencyReorderedCount = competencyTableRows.Count(dr => dr.Reordered == true);
2629
Errors = competencyTableRows.Where(dr => dr.Error.HasValue).Select(dr => (dr.RowNumber, dr.Error!.Value));
30+
FlagCount = competencyTableRows
31+
.Where(row => !string.IsNullOrWhiteSpace(row.FlagsCsv))
32+
.SelectMany(static row => row.FlagsCsv.Split(',', StringSplitOptions.RemoveEmptyEntries))
33+
.Count();
34+
DistinctFlagsCount = competencyTableRows
35+
.Where(row => !string.IsNullOrWhiteSpace(row.FlagsCsv))
36+
.SelectMany(row => row.FlagsCsv.Split(',', StringSplitOptions.RemoveEmptyEntries))
37+
.Select(flag => flag.Trim())
38+
.Distinct()
39+
.Count();
40+
CompetencyGroupCount = competencyTableRows
41+
.Where(row => !string.IsNullOrWhiteSpace(row.CompetencyGroup))
42+
.Select(static row => row.CompetencyGroup)
43+
.Distinct()
44+
.Count();
2745
}
2846

2947
public IEnumerable<(int RowNumber, ErrorReason Reason)>? Errors { get; set; }
3048
public int ProcessedCount { get; set; }
31-
public int CompetenciesInsertedCount { get; set; }
32-
public int CompetencyGroupsInsertedCount { get; set; }
49+
public int CompetencyAddedCount { get; set; }
50+
public int CompetencyUpdatedCount { get; set; }
51+
public int CompetencyReorderedCount { get; set; }
52+
public int GroupAddedCount { get; set; }
53+
public int GroupUpdatedCount { get; set; }
3354
public int SkippedCount { get; set; }
55+
public int FlagCount { get; set; }
56+
public int DistinctFlagsCount { get; set; }
57+
public int CompetencyGroupCount { get; set; }
3458
}
3559
}

DigitalLearningSolutions.Web.Tests/Controllers/Frameworks/FrameworkControllerTests.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
using Microsoft.Extensions.Logging;
1313
using NUnit.Framework;
1414
using GDS.MultiPageFormData;
15+
using DigitalLearningSolutions.Data.Utilities;
16+
using Microsoft.AspNetCore.Hosting;
1517

1618
public partial class FrameworkControllerTests
1719
{
@@ -28,6 +30,8 @@ public partial class FrameworkControllerTests
2830
private ILearningHubApiClient learningHubApiClient = null!;
2931
private ISearchSortFilterPaginateService searchSortFilterPaginateService = null!;
3032
private IMultiPageFormService multiPageFormService = null!;
33+
private IClockUtility clockUtility = null!;
34+
private IWebHostEnvironment webHostEnvironment = null!;
3135

3236
[SetUp]
3337
public void SetUp()
@@ -42,7 +46,8 @@ public void SetUp()
4246
learningHubApiClient = A.Fake<ILearningHubApiClient>();
4347
searchSortFilterPaginateService = A.Fake<ISearchSortFilterPaginateService>();
4448
multiPageFormService = A.Fake<IMultiPageFormService>();
45-
49+
clockUtility = A.Fake<ClockUtility>();
50+
webHostEnvironment = A.Fake<IWebHostEnvironment>();
4651
A.CallTo(() => config["CurrentSystemBaseUrl"]).Returns(BaseUrl);
4752

4853
var user = new ClaimsPrincipal(
@@ -65,7 +70,9 @@ public void SetUp()
6570
competencyLearningResourcesService,
6671
learningHubApiClient,
6772
searchSortFilterPaginateService,
68-
multiPageFormService
73+
multiPageFormService,
74+
clockUtility,
75+
webHostEnvironment
6976
)
7077
{
7178
ControllerContext = new ControllerContext { HttpContext = new DefaultHttpContext { User = user } },

DigitalLearningSolutions.Web.Tests/ServiceFilter/RedirectToErrorEmptySessionDataTests.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
using NUnit.Framework;
2323
using GDS.MultiPageFormData;
2424
using GDS.MultiPageFormData.Enums;
25+
using DigitalLearningSolutions.Data.Utilities;
26+
using Microsoft.AspNetCore.Hosting;
2527

2628
public class RedirectToErrorEmptySessionDataTests
2729
{
@@ -41,7 +43,9 @@ public void Setup()
4143
A.Fake<ICompetencyLearningResourcesService>(),
4244
A.Fake<ILearningHubApiClient>(),
4345
A.Fake<ISearchSortFilterPaginateService>(),
44-
A.Fake<IMultiPageFormService>()
46+
A.Fake<IMultiPageFormService>(),
47+
A.Fake<IClockUtility>(),
48+
A.Fake<IWebHostEnvironment>()
4549
)
4650
.WithDefaultContext().WithMockTempData();
4751

DigitalLearningSolutions.Web/Controllers/FrameworksController/Competencies.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ public IActionResult AddEditFrameworkCompetencyGroup(int frameworkId, Competency
7171
(competencyGroupBase.Description), adminId);
7272
return new RedirectResult(Url.Action("ViewFramework", new { tabname = "Structure", frameworkId }) + "#fcgroup-" + frameworkCompetencyGroupId.ToString());
7373
}
74-
var newCompetencyGroupId = frameworkService.InsertCompetencyGroup(competencyGroupBase.Name, SanitizerHelper.SanitizeHtmlData(competencyGroupBase.Description), adminId);
74+
var newCompetencyGroupId = frameworkService.InsertCompetencyGroup(competencyGroupBase.Name, SanitizerHelper.SanitizeHtmlData(competencyGroupBase.Description), adminId, frameworkId);
7575
if (newCompetencyGroupId > 0)
7676
{
7777
var newFrameworkCompetencyGroupId = frameworkService.InsertFrameworkCompetencyGroup(newCompetencyGroupId, frameworkId, adminId);

DigitalLearningSolutions.Web/Controllers/FrameworksController/Frameworks.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -717,6 +717,20 @@ public IActionResult ViewFramework(string tabname, int frameworkId, int? framewo
717717
return View("Developer/Framework", model);
718718
}
719719

720+
[Route("/Framework/{frameworkId}/Structure/PrintLayout")]
721+
public IActionResult PrintLayout(int frameworkId) {
722+
var adminId = GetAdminId();
723+
var detailFramework = frameworkService.GetFrameworkDetailByFrameworkId(frameworkId, adminId);
724+
var routeData = new Dictionary<string, string> { { "frameworkId", detailFramework?.ID.ToString() } };
725+
var model = new FrameworkViewModel()
726+
{
727+
DetailFramework = detailFramework,
728+
};
729+
model.FrameworkCompetencyGroups = frameworkService.GetFrameworkCompetencyGroups(frameworkId).ToList();
730+
model.CompetencyFlags = frameworkService.GetCompetencyFlagsByFrameworkId(frameworkId, null, selected: true);
731+
model.FrameworkCompetencies = frameworkService.GetFrameworkCompetenciesUngrouped(frameworkId);
732+
return View("Developer/FrameworkPrintLayout", model);
733+
}
720734
[ResponseCache(CacheProfileName = "Never")]
721735
public IActionResult InsertFramework()
722736
{

0 commit comments

Comments
 (0)