diff --git a/DigitalLearningSolutions.Data.Migrations/202501280929_CreateCompetencyAssessmentTables.cs b/DigitalLearningSolutions.Data.Migrations/202501280929_CreateCompetencyAssessmentTables.cs new file mode 100644 index 0000000000..3ad9669e2c --- /dev/null +++ b/DigitalLearningSolutions.Data.Migrations/202501280929_CreateCompetencyAssessmentTables.cs @@ -0,0 +1,57 @@ +namespace DigitalLearningSolutions.Data.Migrations +{ + using FluentMigrator; + using FluentMigrator.SqlServer; + [Migration(202501280929)] + public class CreateCompetencyAssessmentTables : Migration + { + public override void Up() + { + Create.Table("SelfAssessmentFrameworks") + .WithColumn("ID").AsInt32().NotNullable().PrimaryKey().Identity() + .WithColumn("SelfAssessmentId").AsInt32().NotNullable().ForeignKey("SelfAssessments", "ID") + .WithColumn("FrameworkId").AsInt32().NotNullable().ForeignKey("Frameworks", "ID") + .WithColumn("CreatedDate").AsDateTime().NotNullable().WithDefault(SystemMethods.CurrentDateTime) + .WithColumn("CreatedByAdminId").AsInt32().NotNullable().ForeignKey("AdminAccounts", "ID") + .WithColumn("RemovedDate").AsDateTime().Nullable() + .WithColumn("RemovedByAdminId").AsInt32().Nullable().ForeignKey("AdminAccounts", "ID") + .WithColumn("AmendedDate").AsDateTime().Nullable() + .WithColumn("AmendedByAdminId").AsInt32().Nullable().ForeignKey("AdminAccounts", "ID"); + Create.Table("SelfAssessmentTaskStatus") + .WithColumn("ID").AsInt32().NotNullable().PrimaryKey().Identity() + .WithColumn("SelfAssessmentId").AsInt32().NotNullable().ForeignKey("SelfAssessments", "ID").Unique() + .WithColumn("IntroductoryTextTaskStatus").AsBoolean().Nullable() + .WithColumn("BrandingTaskStatus").AsBoolean().Nullable() + .WithColumn("VocabularyTaskStatus").AsBoolean().Nullable() + .WithColumn("WorkingGroupTaskStatus").AsBoolean().Nullable() + .WithColumn("NationalRoleProfileTaskStatus").AsBoolean().Nullable() + .WithColumn("FrameworkLinksTaskStatus").AsBoolean().Nullable() + .WithColumn("SelectCompetenciesTaskStatus").AsBoolean().Nullable() + .WithColumn("OptionalCompetenciesTaskStatus").AsBoolean().Nullable() + .WithColumn("RoleRequirementsTaskStatus").AsBoolean().Nullable() + .WithColumn("SupervisorRolesTaskStatus").AsBoolean().Nullable() + .WithColumn("SelfAssessmentOptionsTaskStatus").AsBoolean().Nullable() + .WithColumn("ReviewTaskStatus").AsBoolean().Nullable(); + Alter.Table("SelfAssessments").AlterColumn("Description").AsString(int.MaxValue).Nullable(); + Execute.Sql($@"INSERT INTO SelfAssessmentFrameworks (SelfAssessmentId, FrameworkId, CreatedByAdminId) + SELECT sa.ID, fc.FrameworkID, sa.CreatedByAdminID + FROM SelfAssessments AS sa INNER JOIN + SelfAssessmentStructure AS sas ON sa.ID = sas.SelfAssessmentID INNER JOIN + FrameworkCompetencies AS fc ON sas.CompetencyID = fc.CompetencyID + GROUP BY sa.ID, fc.FrameworkID, sa.CreatedByAdminID + "); + Execute.Sql($@"INSERT INTO SelfAssessmentTaskStatus (SelfAssessmentId, IntroductoryTextTaskStatus, BrandingTaskStatus, VocabularyTaskStatus, WorkingGroupTaskStatus, NationalRoleProfileTaskStatus, FrameworkLinksTaskStatus, SelectCompetenciesTaskStatus, OptionalCompetenciesTaskStatus, RoleRequirementsTaskStatus, SupervisorRolesTaskStatus, SelfAssessmentOptionsTaskStatus) + SELECT ID, 1,1,1,1,1,1,1,1,1,1,1 + FROM SelfAssessments AS sa + "); + } + + public override void Down() + { + Delete.Table("SelfAssessmentFrameworks"); + Delete.Table("SelfAssessmentTaskStatus"); + Alter.Table("SelfAssessments").AlterColumn("Description").AsString(int.MaxValue).NotNullable(); + } + + } +} diff --git a/DigitalLearningSolutions.Data.Migrations/202503111500_AddLastAccessedColumn.cs b/DigitalLearningSolutions.Data.Migrations/202503111500_AddLastAccessedColumn.cs new file mode 100644 index 0000000000..95a0eb6020 --- /dev/null +++ b/DigitalLearningSolutions.Data.Migrations/202503111500_AddLastAccessedColumn.cs @@ -0,0 +1,26 @@ +namespace DigitalLearningSolutions.Data.Migrations +{ + using FluentMigrator; + + [Migration(202503111500)] + public class AddLastAccessedColumn : Migration + { + public override void Up() + { + Alter.Table("Users").AddColumn("LastAccessed").AsDateTime().Nullable(); + Alter.Table("DelegateAccounts").AddColumn("LastAccessed").AsDateTime().Nullable(); + Alter.Table("AdminAccounts").AddColumn("LastAccessed").AsDateTime().Nullable(); + + Execute.Sql("UPDATE u SET LastAccessed = (SELECT MAX(s.LoginTime) FROM DelegateAccounts da JOIN Sessions s ON da.ID = s.CandidateId WHERE da.UserID = u.ID) FROM users u;"); + Execute.Sql("UPDATE da SET LastAccessed = (SELECT MAX(s.LoginTime) FROM Sessions s WHERE s.CandidateId = da.ID) FROM DelegateAccounts da;"); + Execute.Sql("UPDATE da SET LastAccessed = (SELECT ca.LastAccessed FROM CandidateAssessments ca WHERE ca.ID = da.ID) FROM DelegateAccounts da where da.LastAccessed IS NULL;"); + Execute.Sql("UPDATE AA SET LastAccessed = (SELECT MAX(AdS.LoginTime) FROM AdminSessions AdS WHERE AdS.AdminID = AA.ID) FROM AdminAccounts AA;"); + } + public override void Down() + { + Delete.Column("LastAccessed").FromTable("Users"); + Delete.Column("LastAccessed").FromTable("DelegateAccounts"); + Delete.Column("LastAccessed").FromTable("AdminAccounts"); + } + } +} diff --git a/DigitalLearningSolutions.Data.Migrations/2025041161520_Alter_SendExpiredTBCReminders_AppendCourseName.cs b/DigitalLearningSolutions.Data.Migrations/2025041161520_Alter_SendExpiredTBCReminders_AppendCourseName.cs new file mode 100644 index 0000000000..02bcb19b10 --- /dev/null +++ b/DigitalLearningSolutions.Data.Migrations/2025041161520_Alter_SendExpiredTBCReminders_AppendCourseName.cs @@ -0,0 +1,19 @@ + + +namespace DigitalLearningSolutions.Data.Migrations +{ + using FluentMigrator; + + [Migration(2025041161520)] + public class Alter_SendExpiredTBCReminders_AppendCourseName : Migration + { + public override void Up() + { + Execute.Sql(Properties.Resources.TD_5514_Alter_SendExpiredTBCReminders_Up); + } + public override void Down() + { + Execute.Sql(Properties.Resources.TD_5514_Alter_SendExpiredTBCReminders_Down); + } + } +} diff --git a/DigitalLearningSolutions.Data.Migrations/202504241517_AddFieldIsPrimaryToSelfAssessmentFrameworksTable.cs b/DigitalLearningSolutions.Data.Migrations/202504241517_AddFieldIsPrimaryToSelfAssessmentFrameworksTable.cs new file mode 100644 index 0000000000..fe1e096135 --- /dev/null +++ b/DigitalLearningSolutions.Data.Migrations/202504241517_AddFieldIsPrimaryToSelfAssessmentFrameworksTable.cs @@ -0,0 +1,12 @@ +namespace DigitalLearningSolutions.Data.Migrations +{ + using FluentMigrator; + [Migration(202504241517)] + public class AddFieldIsPrimaryToSelfAssessmentFrameworksTable : AutoReversingMigration + { + public override void Up() + { + Alter.Table("SelfAssessmentFrameworks").AddColumn("IsPrimary").AsBoolean().NotNullable().WithDefaultValue(1); + } + } +} diff --git a/DigitalLearningSolutions.Data.Migrations/202504281045_Alter_ReorderFrameworkCompetency.cs b/DigitalLearningSolutions.Data.Migrations/202504281045_Alter_ReorderFrameworkCompetency.cs new file mode 100644 index 0000000000..2759e056ac --- /dev/null +++ b/DigitalLearningSolutions.Data.Migrations/202504281045_Alter_ReorderFrameworkCompetency.cs @@ -0,0 +1,19 @@ + + +namespace DigitalLearningSolutions.Data.Migrations +{ + using FluentMigrator; + + [Migration(202504281045)] + public class Alter_ReorderFrameworkCompetency : Migration + { + public override void Up() + { + Execute.Sql(Properties.Resources.TD_5447_Alter_ReorderFrameworkCompetency_Up); + } + public override void Down() + { + Execute.Sql(Properties.Resources.TD_5447_Alter_ReorderFrameworkCompetency_Down); + } + } +} diff --git a/DigitalLearningSolutions.Data.Migrations/202504281115_UpdateFrameworkCompetenciesOrdering.cs b/DigitalLearningSolutions.Data.Migrations/202504281115_UpdateFrameworkCompetenciesOrdering.cs new file mode 100644 index 0000000000..e64cdd3f6f --- /dev/null +++ b/DigitalLearningSolutions.Data.Migrations/202504281115_UpdateFrameworkCompetenciesOrdering.cs @@ -0,0 +1,21 @@ +namespace DigitalLearningSolutions.Data.Migrations +{ + using FluentMigrator; + [Migration(202504281115)] + public class UpdateFrameworkCompetenciesOrdering : ForwardOnlyMigration + { + public override void Up() + { + Execute.Sql(@"WITH Ranked AS ( +    SELECT ID, +            ROW_NUMBER() OVER (PARTITION BY FrameworkID ORDER BY SysStartTime) AS NewOrder +    FROM FrameworkCompetencies + Where FrameworkCompetencyGroupID is null + ) + UPDATE fc + SET fc.Ordering = r.NewOrder + FROM FrameworkCompetencies fc + JOIN Ranked r ON fc.ID = r.ID;"); + } + } +} diff --git a/DigitalLearningSolutions.Data.Migrations/202504290900_UpdateNotifications.cs b/DigitalLearningSolutions.Data.Migrations/202504290900_UpdateNotifications.cs new file mode 100644 index 0000000000..a662824279 --- /dev/null +++ b/DigitalLearningSolutions.Data.Migrations/202504290900_UpdateNotifications.cs @@ -0,0 +1,14 @@ +namespace DigitalLearningSolutions.Data.Migrations +{ + using FluentMigrator; + + [Migration(202504290900)] + public class UpdateNotifications : ForwardOnlyMigration + { + public override void Up() + { + Execute.Sql(@$"UPDATE Notifications SET NotificationName = 'Completed course follow-up feedback requests' where NotificationID = 13"); + } + + } +} diff --git a/DigitalLearningSolutions.Data.Migrations/Properties/Resources.Designer.cs b/DigitalLearningSolutions.Data.Migrations/Properties/Resources.Designer.cs index 1b4edf4c6f..f5949119d4 100644 --- a/DigitalLearningSolutions.Data.Migrations/Properties/Resources.Designer.cs +++ b/DigitalLearningSolutions.Data.Migrations/Properties/Resources.Designer.cs @@ -2436,6 +2436,94 @@ internal static string TD_5412_Alter_SendExpiredTBCReminders_Up { } } + /// + /// Looks up a localized string similar to /****** Object: StoredProcedure [dbo].[ReorderFrameworkCompetency] Script Date: 24/04/2025 09:23:17 ******/ + ///SET ANSI_NULLS ON + ///GO + /// + ///SET QUOTED_IDENTIFIER ON + ///GO + /// + ///-- ============================================= + ///-- Author: Kevin Whittaker + ///-- Create date: 04/01/2021 + ///-- Description: Reorders the FrameworkCompetencies in a given FrameworkCompetencyGroup - moving the given competency up or down. + ///-- ============================================= + ///ALTER PROCEDURE [dbo].[ReorderFrameworkCompetency] + /// [rest of string was truncated]";. + /// + internal static string TD_5447_Alter_ReorderFrameworkCompetency_Down { + get { + return ResourceManager.GetString("TD_5447_Alter_ReorderFrameworkCompetency_Down", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to /****** Object: StoredProcedure [dbo].[ReorderFrameworkCompetency] Script Date: 24/04/2025 09:23:17 ******/ + ///SET ANSI_NULLS ON + ///GO + /// + ///SET QUOTED_IDENTIFIER ON + ///GO + /// + ///-- ============================================= + ///-- Author: Kevin Whittaker + ///-- Create date: 04/01/2021 + ///-- Description: Reorders the FrameworkCompetencies in a given FrameworkCompetencyGroup - moving the given competency up or down. + ///-- ============================================= + ///ALTER PROCEDURE [dbo].[ReorderFrameworkCompetency] + /// [rest of string was truncated]";. + /// + internal static string TD_5447_Alter_ReorderFrameworkCompetency_Up { + get { + return ResourceManager.GetString("TD_5447_Alter_ReorderFrameworkCompetency_Up", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to /****** Object: StoredProcedure [dbo].[SendExpiredTBCReminders] Script Date: 16/04/2025 10:50:12 ******/ + ///SET ANSI_NULLS ON + ///GO + /// + ///SET QUOTED_IDENTIFIER ON + ///GO + /// + ///-- ============================================= + ///-- Author: Kevin Whittaker + ///-- Create date: 17/08/2018 + ///-- Description: Uses DB mail to send reminders to delegates on courses with a TBC date within 1 month. + ///-- ============================================= + ///ALTER PROCEDURE [dbo].[SendExpiredTBCReminders] + /// -- Add the parameters for the stor [rest of string was truncated]";. + /// + internal static string TD_5514_Alter_SendExpiredTBCReminders_Down { + get { + return ResourceManager.GetString("TD_5514_Alter_SendExpiredTBCReminders_Down", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to /****** Object: StoredProcedure [dbo].[SendExpiredTBCReminders] Script Date: 16/04/2025 10:50:12 ******/ + ///SET ANSI_NULLS ON + ///GO + /// + ///SET QUOTED_IDENTIFIER ON + ///GO + /// + ///-- ============================================= + ///-- Author: Kevin Whittaker + ///-- Create date: 17/08/2018 + ///-- Description: Uses DB mail to send reminders to delegates on courses with a TBC date within 1 month. + ///-- ============================================= + ///ALTER PROCEDURE [dbo].[SendExpiredTBCReminders] + /// -- Add the parameters for the stor [rest of string was truncated]";. + /// + internal static string TD_5514_Alter_SendExpiredTBCReminders_Up { + get { + return ResourceManager.GetString("TD_5514_Alter_SendExpiredTBCReminders_Up", resourceCulture); + } + } + /// /// Looks up a localized string similar to /****** Object: StoredProcedure [dbo].[GetActiveAvailableCustomisationsForCentreFiltered_V6] Script Date: 29/09/2022 19:11:04 ******/ ///SET ANSI_NULLS ON diff --git a/DigitalLearningSolutions.Data.Migrations/Properties/Resources.resx b/DigitalLearningSolutions.Data.Migrations/Properties/Resources.resx index a951c296c9..c0b77842ad 100644 --- a/DigitalLearningSolutions.Data.Migrations/Properties/Resources.resx +++ b/DigitalLearningSolutions.Data.Migrations/Properties/Resources.resx @@ -475,4 +475,16 @@ ..\Scripts\TD-5412-Alter_SendExpiredTBCReminders_Up.sql;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-16 + + ..\Scripts\TD-5514-Alter_SendExpiredTBCReminders_Down.sql;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-16 + + + ..\Scripts\TD-5514-Alter_SendExpiredTBCReminders_Up.sql;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-16 + + + ..\Scripts\TD-5447-Alter_ReorderFrameworkCompetency_Down.sql;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-16 + + + ..\Scripts\TD-5447-Alter_ReorderFrameworkCompetency_Up.sql;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-16 + \ No newline at end of file diff --git a/DigitalLearningSolutions.Data.Migrations/Scripts/TD-5447-Alter_ReorderFrameworkCompetency_Down.sql b/DigitalLearningSolutions.Data.Migrations/Scripts/TD-5447-Alter_ReorderFrameworkCompetency_Down.sql new file mode 100644 index 0000000000..56bac72b67 Binary files /dev/null and b/DigitalLearningSolutions.Data.Migrations/Scripts/TD-5447-Alter_ReorderFrameworkCompetency_Down.sql differ diff --git a/DigitalLearningSolutions.Data.Migrations/Scripts/TD-5447-Alter_ReorderFrameworkCompetency_Up.sql b/DigitalLearningSolutions.Data.Migrations/Scripts/TD-5447-Alter_ReorderFrameworkCompetency_Up.sql new file mode 100644 index 0000000000..bd170f6b9e Binary files /dev/null and b/DigitalLearningSolutions.Data.Migrations/Scripts/TD-5447-Alter_ReorderFrameworkCompetency_Up.sql differ diff --git a/DigitalLearningSolutions.Data.Migrations/Scripts/TD-5514-Alter_SendExpiredTBCReminders_Down.sql b/DigitalLearningSolutions.Data.Migrations/Scripts/TD-5514-Alter_SendExpiredTBCReminders_Down.sql new file mode 100644 index 0000000000..f80def01d5 Binary files /dev/null and b/DigitalLearningSolutions.Data.Migrations/Scripts/TD-5514-Alter_SendExpiredTBCReminders_Down.sql differ diff --git a/DigitalLearningSolutions.Data.Migrations/Scripts/TD-5514-Alter_SendExpiredTBCReminders_Up.sql b/DigitalLearningSolutions.Data.Migrations/Scripts/TD-5514-Alter_SendExpiredTBCReminders_Up.sql new file mode 100644 index 0000000000..448ba42946 Binary files /dev/null and b/DigitalLearningSolutions.Data.Migrations/Scripts/TD-5514-Alter_SendExpiredTBCReminders_Up.sql differ diff --git a/DigitalLearningSolutions.Data/DataServices/CompetencyAssessmentDataService.cs b/DigitalLearningSolutions.Data/DataServices/CompetencyAssessmentDataService.cs new file mode 100644 index 0000000000..2f597dc696 --- /dev/null +++ b/DigitalLearningSolutions.Data/DataServices/CompetencyAssessmentDataService.cs @@ -0,0 +1,636 @@ +namespace DigitalLearningSolutions.Data.DataServices +{ + using System; + using System.Collections.Generic; + using System.Data; + using System.Linq; + using Dapper; + using DigitalLearningSolutions.Data.Models.Common; + using DigitalLearningSolutions.Data.Models.CompetencyAssessments; + using DigitalLearningSolutions.Data.Models.Frameworks; + using DocumentFormat.OpenXml.Wordprocessing; + using Microsoft.Extensions.Logging; + + public interface ICompetencyAssessmentDataService + { + //GET DATA + IEnumerable GetAllCompetencyAssessments(int adminId); + + IEnumerable GetCompetencyAssessmentsForAdminId(int adminId); + + CompetencyAssessmentBase? GetCompetencyAssessmentBaseById(int competencyAssessmentId, int adminId); + + CompetencyAssessmentBase? GetCompetencyAssessmentBaseByName(string competencyAssessmentName, int adminId); + CompetencyAssessment? GetCompetencyAssessmentById(int competencyAssessmentId, int adminId); + IEnumerable GetNRPProfessionalGroups(); + IEnumerable GetNRPSubGroups(int? nRPProfessionalGroupID); + IEnumerable GetNRPRoles(int? nRPSubGroupID); + + CompetencyAssessmentTaskStatus GetOrInsertAndReturnAssessmentTaskStatus(int assessmentId, bool frameworkBased); + + int[] GetLinkedFrameworkIds (int assessmentId); + + int? GetPrimaryLinkedFrameworkId(int assessmentId); + + int GetCompetencyCountByFrameworkId(int assessmentId, int frameworkId); + + //UPDATE DATA + bool UpdateCompetencyAssessmentName(int competencyAssessmentId, int adminId, string competencyAssessmentName); + + bool UpdateCompetencyRoleProfileLinks(int competencyAssessmentId, int adminId, int? professionalGroupId, int? subGroupId, int? roleId); + bool UpdateCompetencyAssessmentBranding( + int competencyAssessmentId, + int adminId, + int brandId, + int categoryId + ); + bool UpdateCompetencyAssessmentVocabulary(int competencyAssessmentId, int adminId, string vocabulary); + bool UpdateCompetencyAssessmentDescription(int competencyAssessmentId, int adminId, string competencyAssessmentDescription); + bool UpdateIntroductoryTextTaskStatus(int assessmentId, bool taskStatus); + bool UpdateBrandingTaskStatus(int assessmentId, bool taskStatus); + bool UpdateVocabularyTaskStatus(int assessmentId, bool taskStatus); + bool UpdateRoleProfileLinksTaskStatus(int assessmentId, bool taskStatus); + bool UpdateFrameworkLinksTaskStatus(int assessmentId, bool taskStatus, bool? previousStatus); + bool RemoveSelfAssessmentFramework(int assessmentId, int frameworkId, int adminId); + bool UpdateSelectCompetenciesTaskStatus(int assessmentId, bool taskStatus, bool? previousStatus); + bool UpdateOptionalCompetenciesTaskStatus(int assessmentId, bool taskStatus, bool? previousStatus); + bool UpdateRoleRequirementsTaskStatus(int assessmentId, bool taskStatus, bool? previousStatus); + + //INSERT DATA + int InsertCompetencyAssessment(int adminId, int centreId, string competencyAssessmentName); + bool InsertSelfAssessmentFramework(int adminId, int selfAssessmentId, int frameworkId); + + //DELETE DATA + bool RemoveFrameworkCompetenciesFromAssessment(int competencyAssessmentId, int frameworkId); + + } + + public class CompetencyAssessmentDataService : ICompetencyAssessmentDataService + { + private const string SelfAssessmentBaseFields = @"sa.ID, sa.Name AS CompetencyAssessmentName, sa.Description, sa.BrandID, + sa.ParentSelfAssessmentID, + sa.[National], sa.[Public], sa.CreatedByAdminID AS OwnerAdminID, + sa.NRPProfessionalGroupID, + sa.NRPSubGroupID, + sa.NRPRoleID, + sa.PublishStatusID, sa.Vocabulary, CASE WHEN sa.CreatedByAdminID = @adminId THEN 3 WHEN sac.CanModify = 1 THEN 2 WHEN sac.CanModify = 0 THEN 1 ELSE 0 END AS UserRole"; + + private const string SelfAssessmentFields = + @", sa.CategoryID, sa.CreatedDate, + (SELECT BrandName + FROM Brands + WHERE (BrandID = sa.BrandID)) AS Brand, + (SELECT CategoryName + FROM CourseCategories + WHERE (CourseCategoryID = sa.CategoryID)) AS Category, + (SELECT [Name] + FROM SelfAssessments AS sa2 + WHERE (ID = sa.ParentSelfAssessmentID)) AS ParentSelfAssessment, + (SELECT Forename + ' ' + Surname + (CASE WHEN Active = 1 THEN '' ELSE ' (Inactive)' END) AS Expr1 + FROM AdminUsers + WHERE (AdminID = sa.CreatedByAdminID)) AS Owner, + sa.Archived, + sa.LastEdit, + STUFF(( + SELECT + ', ' + f.FrameworkName + FROM + SelfAssessmentFrameworks saf2 + INNER JOIN Frameworks f ON f.ID = saf2.FrameworkId + WHERE + saf2.SelfAssessmentId = sa.ID + FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 2, '' + ) AS LinkedFrameworks, + (SELECT ProfessionalGroup + FROM NRPProfessionalGroups + WHERE (ID = sa.NRPProfessionalGroupID)) AS NRPProfessionalGroup, + (SELECT SubGroup + FROM NRPSubGroups + WHERE (ID = sa.NRPSubGroupID)) AS NRPSubGroup, + (SELECT RoleProfile + FROM NRPRoles + WHERE (ID = sa.NRPRoleID)) AS NRPRole, sar.ID AS SelfAssessmentReviewID"; + + private const string SelfAssessmentBaseTables = + @"SelfAssessments AS sa LEFT OUTER JOIN + SelfAssessmentCollaborators AS sac ON sac.SelfAssessmentID = sa.ID AND sac.AdminID = @adminId"; + + private const string SelfAssessmentTables = + @" LEFT OUTER JOIN + SelfAssessmentReviews AS sar ON sac.ID = sar.SelfAssessmentCollaboratorID AND sar.Archived IS NULL AND sar.ReviewComplete IS NULL"; + + private readonly IDbConnection connection; + private readonly ILogger logger; + + public CompetencyAssessmentDataService(IDbConnection connection, ILogger logger) + { + this.connection = connection; + this.logger = logger; + } + + public IEnumerable GetAllCompetencyAssessments(int adminId) + { + return connection.Query( + $@"SELECT {SelfAssessmentBaseFields} {SelfAssessmentFields} + FROM {SelfAssessmentBaseTables} {SelfAssessmentTables}", + new { adminId } + ); + } + + public IEnumerable GetCompetencyAssessmentsForAdminId(int adminId) + { + return connection.Query( + $@"SELECT {SelfAssessmentBaseFields} {SelfAssessmentFields} + FROM {SelfAssessmentBaseTables} {SelfAssessmentTables} + WHERE (sa.CreatedByAdminID = @adminId) OR + (@adminId IN + (SELECT AdminID + FROM SelfAssessmentCollaborators + WHERE (SelfAssessmentID = sa.ID)))", + new { adminId } + ); + } + + public CompetencyAssessmentBase? GetCompetencyAssessmentBaseById(int competencyAssessmentId, int adminId) + { + return connection.Query( + $@"SELECT {SelfAssessmentBaseFields} + FROM {SelfAssessmentBaseTables} + WHERE (sa.ID = @competencyAssessmentId)", + new { competencyAssessmentId, adminId } + ).FirstOrDefault(); + } + + public int InsertCompetencyAssessment(int adminId, int centreId, string competencyAssessmentName) + { + if ((competencyAssessmentName.Length == 0) | (adminId < 1)) + { + logger.LogWarning( + $"Not inserting competency assessmente as it failed server side validation. AdminId: {adminId}, competencyAssessmentName: {competencyAssessmentName}" + ); + return -1; + } + var result = connection.ExecuteScalar( + @"SELECT COUNT(*) FROM SelfAssessments WHERE [Name] = @competencyAssessmentName", + new { competencyAssessmentName } + ); + int existingSelfAssessments = Convert.ToInt32(result); + if (existingSelfAssessments > 0) + { + return -1; + } + var assessmentId = connection.QuerySingle( + @"INSERT INTO SelfAssessments ([Name], CreatedByCentreID, CreatedByAdminID) + OUTPUT INSERTED.Id + VALUES (@competencyAssessmentName, @centreId, @adminId)" + , + new { competencyAssessmentName, centreId, adminId } + ); + return assessmentId; + } + public bool UpdateCompetencyAssessmentName(int competencyAssessmentId, int adminId, string competencyAssessmentName) + { + if ((competencyAssessmentName.Length == 0) | (adminId < 1) | (competencyAssessmentId < 1)) + { + logger.LogWarning( + $"Not updating role profile name as it failed server side validation. AdminId: {adminId}, competencyAssessmentName: {competencyAssessmentName}, competencyAssessmentId: {competencyAssessmentId}" + ); + return false; + } + var result = connection.ExecuteScalar( + @"SELECT COUNT(*) FROM SelfAssessments WHERE [Name] = @competencyAssessmentName AND ID <> @competencyAssessmentId", + new { competencyAssessmentName, competencyAssessmentId } + ); + int existingSelfAssessments = Convert.ToInt32(result); + if (existingSelfAssessments > 0) + { + return false; + } + + var numberOfAffectedRows = connection.Execute( + @"UPDATE SelfAssessments SET [Name] = @competencyAssessmentName, UpdatedByAdminID = @adminId + WHERE ID = @competencyAssessmentId", + new { competencyAssessmentName, adminId, competencyAssessmentId } + ); + if (numberOfAffectedRows < 1) + { + logger.LogWarning( + "Not updating role profile name as db update failed. " + + $"SelfAssessmentName: {competencyAssessmentName}, admin id: {adminId}, competencyAssessmentId: {competencyAssessmentId}" + ); + return false; + } + + return true; + } + + public IEnumerable GetNRPProfessionalGroups() + { + return connection.Query( + @"SELECT ID, ProfessionalGroup, Active + FROM NRPProfessionalGroups + WHERE (Active = 1) + ORDER BY ProfessionalGroup" + ); + } + + public CompetencyAssessmentBase? GetCompetencyAssessmentBaseByName(string competencyAssessmentName, int adminId) + { + return connection.Query( + $@"SELECT {SelfAssessmentBaseFields} + FROM {SelfAssessmentBaseTables} + WHERE (sa.Name = @competencyAssessmentName)", + new { competencyAssessmentName, adminId } + ).FirstOrDefault(); + } + + public bool UpdateCompetencyRoleProfileLinks(int competencyAssessmentId, int adminId, int? professionalGroupId, int? subGroupId, int? roleId) + { + var result = connection.ExecuteScalar( + @"SELECT COUNT(*) FROM SelfAssessments WHERE ID = @competencyAssessmentId AND NRPProfessionalGroupID = @professionalGroupId AND NRPSubGroupID = @subGroupId AND NRPRoleID = @roleId", + new { competencyAssessmentId, professionalGroupId, subGroupId, roleId } + ); + int sameCount = Convert.ToInt32(result); + if (sameCount > 0) + { + //same so don't update: + return false; + } + + //needs updating: + var numberOfAffectedRows = connection.Execute( + @"UPDATE SelfAssessments SET NRPProfessionalGroupID = @professionalGroupId, NRPSubGroupID = @subGroupId, NRPRoleID = @roleId, UpdatedByAdminID = @adminId + WHERE ID = @competencyAssessmentId", + new { adminId, competencyAssessmentId, professionalGroupId, subGroupId, roleId } + ); + if (numberOfAffectedRows > 0) + { + return true; + } + + return false; + } + public bool UpdateCompetencyAssessmentBranding( + int competencyAssessmentId, + int adminId, + int brandId, + int categoryId + ) + { + if ((competencyAssessmentId < 1) | (brandId < 1) | (categoryId < 1) | (adminId < 1)) + { + logger.LogWarning( + $"Not updating competency assessment as it failed server side validation. competencyAssessmentId: {competencyAssessmentId}, brandId: {brandId}, categoryId: {categoryId}, AdminId: {adminId}" + ); + return false; + } + + var numberOfAffectedRows = connection.Execute( + @"UPDATE SelfAssessments SET BrandID = @brandId, CategoryID = @categoryId, UpdatedByAdminID = @adminId + WHERE ID = @competencyAssessmentId", + new { brandId, categoryId, adminId, competencyAssessmentId } + ); + if (numberOfAffectedRows < 1) + { + logger.LogWarning( + "Not updating competency assessment branding as db update failed. " + + $"frameworkId: {competencyAssessmentId}, brandId: {brandId}, categoryId: {categoryId}, AdminId: {adminId}" + ); + return false; + } + + return true; + } + + public bool UpdateCompetencyAssessmentDescription(int competencyAssessmentId, int adminId, string competencyAssessmentDescription) + { + var numberOfAffectedRows = connection.Execute( + @"UPDATE SelfAssessments SET Description = @competencyAssessmentDescription, UpdatedByAdminID = @adminId + WHERE ID = @competencyAssessmentId", + new { adminId, competencyAssessmentId, competencyAssessmentDescription } + ); + if (numberOfAffectedRows < 1) + { + logger.LogWarning( + "Not updating competency assessment Description as db update failed. " + + $"frameworkId: {competencyAssessmentId}, competencyAssessmentDescription: {competencyAssessmentDescription}, AdminId: {adminId}" + ); + return false; + } + return true; + } + + public bool UpdateCompetencyAssessmentVocabulary(int competencyAssessmentId, int adminId, string vocabulary) + { + var numberOfAffectedRows = connection.Execute( + @"UPDATE SelfAssessments SET Vocabulary = @vocabulary, UpdatedByAdminID = @adminId + WHERE ID = @competencyAssessmentId", + new { adminId, competencyAssessmentId, vocabulary } + ); + if (numberOfAffectedRows < 1) + { + logger.LogWarning( + "Not updating competency assessment vocabulary as db update failed. " + + $"frameworkId: {competencyAssessmentId}, vocabulary: {vocabulary}, AdminId: {adminId}" + ); + return false; + } + return true; + } + + public bool InsertSelfAssessmentFramework(int adminId, int selfAssessmentId, int frameworkId) + { + bool isPrimary = Convert.ToInt32(connection.ExecuteScalar( + @"SELECT Count(1) FROM SelfAssessmentFrameworks + WHERE SelfAssessmentId = @selfAssessmentId AND IsPrimary = 1", new { selfAssessmentId })) == 0; + + var numberOfAffectedRows = connection.Execute( + @"INSERT INTO SelfAssessmentFrameworks (SelfAssessmentId, FrameworkId, CreatedByAdminId, IsPrimary) + SELECT @selfAssessmentId, @frameworkId, @adminId, @isPrimary + WHERE NOT EXISTS (SELECT 1 FROM SelfAssessmentFrameworks WHERE SelfAssessmentId = @selfAssessmentId AND FrameworkId = @frameworkId)" + , + new { adminId, selfAssessmentId, frameworkId, isPrimary } + ); + if (numberOfAffectedRows < 1) + { + numberOfAffectedRows = connection.Execute( + @"UPDATE SelfAssessmentFrameworks + SET RemovedDate = NULL, RemovedByAdminId = NULL, AmendedByAdminId = @adminId + WHERE SelfAssessmentId = @selfAssessmentId AND FrameworkId = @frameworkId" + , + new { adminId, selfAssessmentId, frameworkId } + ); + } + if (numberOfAffectedRows < 1) + { + logger.LogWarning( + "Not inserting SelfAssessmentFrameworks record as db insert failed. " + + $"selfAssessmentId: {selfAssessmentId}, frameworkId: {frameworkId}, AdminId: {adminId}" + ); + return false; + } + + return true; + } + + public CompetencyAssessmentTaskStatus GetOrInsertAndReturnAssessmentTaskStatus(int assessmentId, bool frameworkBased) + { + bool? frameworkItemBool = frameworkBased ? false : null; + connection.Execute( + @"INSERT INTO SelfAssessmentTaskStatus (SelfAssessmentId, IntroductoryTextTaskStatus, BrandingTaskStatus, VocabularyTaskStatus, FrameworkLinksTaskStatus) + SELECT @assessmentId, @frameworkItemBool, @frameworkItemBool, @frameworkItemBool, @frameworkItemBool + WHERE NOT EXISTS (SELECT 1 FROM SelfAssessmentTaskStatus WHERE SelfAssessmentId = @assessmentId)", new { assessmentId, frameworkItemBool }); + return connection.Query( + $@"SELECT * + FROM SelfAssessmentTaskStatus + WHERE (SelfAssessmentId = @assessmentId)", + new { assessmentId } + ).Single(); + + } + public bool UpdateIntroductoryTextTaskStatus(int assessmentId, bool taskStatus) + { + var numberOfAffectedRows = connection.Execute( + @"UPDATE SelfAssessmentTaskStatus SET IntroductoryTextTaskStatus = @taskStatus + WHERE SelfAssessmentId = @assessmentId", + new { assessmentId, taskStatus } + ); + if (numberOfAffectedRows < 1) + { + logger.LogWarning( + "Not updating IntroductoryTextTaskStatus as db update failed. " + + $"assessmentId: {assessmentId}, taskStatus: {taskStatus}" + ); + return false; + } + return true; + } + + public CompetencyAssessment? GetCompetencyAssessmentById(int competencyAssessmentId, int adminId) + { + return connection.Query( + $@"SELECT {SelfAssessmentBaseFields} {SelfAssessmentFields} + FROM {SelfAssessmentBaseTables} {SelfAssessmentTables} + WHERE (sa.ID = @competencyAssessmentId)", + new { competencyAssessmentId, adminId } + ).FirstOrDefault(); + } + + public bool UpdateBrandingTaskStatus(int assessmentId, bool taskStatus) + { + var numberOfAffectedRows = connection.Execute( + @"UPDATE SelfAssessmentTaskStatus SET BrandingTaskStatus = @taskStatus + WHERE SelfAssessmentId = @assessmentId", + new { assessmentId, taskStatus } + ); + if (numberOfAffectedRows < 1) + { + logger.LogWarning( + "Not updating BrandingTaskStatus as db update failed. " + + $"assessmentId: {assessmentId}, taskStatus: {taskStatus}" + ); + return false; + } + return true; + } + + public bool UpdateVocabularyTaskStatus(int assessmentId, bool taskStatus) + { + var numberOfAffectedRows = connection.Execute( + @"UPDATE SelfAssessmentTaskStatus SET VocabularyTaskStatus = @taskStatus + WHERE SelfAssessmentId = @assessmentId", + new { assessmentId, taskStatus } + ); + if (numberOfAffectedRows < 1) + { + logger.LogWarning( + "Not updating VocabularyTaskStatus as db update failed. " + + $"assessmentId: {assessmentId}, taskStatus: {taskStatus}" + ); + return false; + } + return true; + } + + public IEnumerable GetNRPSubGroups(int? nRPProfessionalGroupID) + { + return connection.Query( + @"SELECT ID, SubGroup, Active + FROM NRPSubGroups + WHERE (Active = 1) AND (NRPProfessionalGroupID = @nRPProfessionalGroupID) + ORDER BY SubGroup", new { nRPProfessionalGroupID } + ); + } + + public IEnumerable GetNRPRoles(int? nRPSubGroupID) + { + return connection.Query( + @"SELECT ID, RoleProfile AS ProfileName, Active + FROM NRPRoles + WHERE (Active = 1) AND (NRPSubGroupID = @nRPSubGroupID) + ORDER BY RoleProfile", new { nRPSubGroupID } + ); + } + + public bool UpdateRoleProfileLinksTaskStatus(int assessmentId, bool taskStatus) + { + var numberOfAffectedRows = connection.Execute( + @"UPDATE SelfAssessmentTaskStatus SET NationalRoleProfileTaskStatus = @taskStatus + WHERE SelfAssessmentId = @assessmentId", + new { assessmentId, taskStatus } + ); + if (numberOfAffectedRows < 1) + { + logger.LogWarning( + "Not updating NationalRoleProfileTaskStatus as db update failed. " + + $"assessmentId: {assessmentId}, taskStatus: {taskStatus}" + ); + return false; + } + return true; + } + + public int[] GetLinkedFrameworkIds(int assessmentId) + { + return [.. connection.Query( + @"SELECT FrameworkId + FROM SelfAssessmentFrameworks + WHERE (SelfAssessmentId = @assessmentId) AND (RemovedDate IS NULL) AND (IsPrimary = 0) + ORDER BY ID", + new { assessmentId } + )]; + } + + public bool RemoveSelfAssessmentFramework(int assessmentId, int frameworkId, int adminId) + { + var numberOfAffectedRows = connection.Execute( + @"UPDATE SelfAssessmentFrameworks SET RemovedDate = @removedDate, RemovedByAdminId = @adminId + WHERE SelfAssessmentId = @assessmentId AND FrameworkId = @frameworkId", + new { removedDate = DateTime.Now, assessmentId, frameworkId, adminId } + ); + if (numberOfAffectedRows < 1) + { + logger.LogWarning( + "Not updating SelfAssessmentFrameworks as db update failed. " + + $"assessmentId: {assessmentId}, frameworkId: {frameworkId}, adminId: {adminId}" + ); + return false; + } + return true; + } + + public int? GetPrimaryLinkedFrameworkId(int assessmentId) + { + return connection.QuerySingleOrDefault( + @"SELECT TOP(1) FrameworkId + FROM SelfAssessmentFrameworks + WHERE (SelfAssessmentId = @assessmentId) AND (RemovedDate IS NULL) AND (IsPrimary = 1) + ORDER BY ID DESC", + new { assessmentId } + ); + } + + public bool UpdateFrameworkLinksTaskStatus(int assessmentId, bool taskStatus, bool? previousStatus) + { + var numberOfAffectedRows = connection.Execute( + @"UPDATE SelfAssessmentTaskStatus SET FrameworkLinksTaskStatus = @taskStatus + WHERE SelfAssessmentId = @assessmentId AND (@previousStatus IS NULL OR FrameworkLinksTaskStatus = @previousStatus)", + new { assessmentId, taskStatus, previousStatus } + ); + if (numberOfAffectedRows < 1) + { + logger.LogWarning( + "Not updating FrameworkLinksTaskStatus as db update failed. " + + $"assessmentId: {assessmentId}, taskStatus: {taskStatus}" + ); + return false; + } + return true; + } + + public int GetCompetencyCountByFrameworkId(int assessmentId, int frameworkId) + { + return connection.ExecuteScalar( + @"SELECT COUNT(sas.CompetencyID) AS Competencies + FROM SelfAssessmentStructure AS sas INNER JOIN + FrameworkCompetencies AS fc ON sas.CompetencyID = fc.CompetencyID INNER JOIN + SelfAssessmentFrameworks AS saf ON fc.FrameworkID = saf.FrameworkId AND sas.SelfAssessmentID = saf.SelfAssessmentId + WHERE (saf.SelfAssessmentId = @assessmentId) AND (saf.FrameworkId = @frameworkId)", + new { assessmentId, frameworkId } + ); + } + + public bool RemoveFrameworkCompetenciesFromAssessment(int competencyAssessmentId, int frameworkId) + { + var numberOfAffectedRows = connection.Execute( + @"DELETE FROM SelfAssessmentStructure + FROM SelfAssessmentStructure INNER JOIN + FrameworkCompetencies AS fc ON SelfAssessmentStructure.CompetencyID = fc.CompetencyID INNER JOIN + SelfAssessmentFrameworks AS saf ON fc.FrameworkID = saf.FrameworkId AND SelfAssessmentStructure.SelfAssessmentID = saf.SelfAssessmentId + WHERE (saf.SelfAssessmentId = @competencyAssessmentId) AND (saf.FrameworkId = @frameworkId)", + new { competencyAssessmentId, frameworkId } + ); + if (numberOfAffectedRows < 1) + { + logger.LogWarning( + "Not removing competencies linked to source framework as db update failed. " + + $"assessmentId: {competencyAssessmentId}, taskStatus: {frameworkId}" + ); + return false; + } + return true; + } + + public bool UpdateSelectCompetenciesTaskStatus(int assessmentId, bool taskStatus, bool? previousStatus) + { + var numberOfAffectedRows = connection.Execute( + @"UPDATE SelfAssessmentTaskStatus SET SelectCompetenciesTaskStatus = @taskStatus + WHERE SelfAssessmentId = @assessmentId AND (@previousStatus IS NULL OR SelectCompetenciesTaskStatus = @previousStatus)", + new { assessmentId, taskStatus, previousStatus } + ); + if (numberOfAffectedRows < 1) + { + logger.LogWarning( + "Not updating SelectCompetenciesTaskStatus as db update failed. " + + $"assessmentId: {assessmentId}, taskStatus: {taskStatus}" + ); + return false; + } + return true; + } + public bool UpdateOptionalCompetenciesTaskStatus(int assessmentId, bool taskStatus, bool? previousStatus) + { + var numberOfAffectedRows = connection.Execute( + @"UPDATE SelfAssessmentTaskStatus SET OptionalCompetenciesTaskStatus = @taskStatus + WHERE SelfAssessmentId = @assessmentId AND (@previousStatus IS NULL OR OptionalCompetenciesTaskStatus = @previousStatus)", + new { assessmentId, taskStatus, previousStatus } + ); + if (numberOfAffectedRows < 1) + { + logger.LogWarning( + "Not updating OptionalCompetenciesTaskStatus as db update failed. " + + $"assessmentId: {assessmentId}, taskStatus: {taskStatus}" + ); + return false; + } + return true; + } + public bool UpdateRoleRequirementsTaskStatus(int assessmentId, bool taskStatus, bool? previousStatus) + { + var numberOfAffectedRows = connection.Execute( + @"UPDATE SelfAssessmentTaskStatus SET RoleRequirementsTaskStatus = @taskStatus + WHERE SelfAssessmentId = @assessmentId AND (@previousStatus IS NULL OR RoleRequirementsTaskStatus = @previousStatus)", + new { assessmentId, taskStatus, previousStatus } + ); + if (numberOfAffectedRows < 1) + { + logger.LogWarning( + "Not updating RoleRequirementsTaskStatus as db update failed. " + + $"assessmentId: {assessmentId}, taskStatus: {taskStatus}" + ); + return false; + } + return true; + } + } +} diff --git a/DigitalLearningSolutions.Data/DataServices/CompetencyLearningResourcesDataService.cs b/DigitalLearningSolutions.Data/DataServices/CompetencyLearningResourcesDataService.cs index 323188bf45..f00b2b1a71 100644 --- a/DigitalLearningSolutions.Data/DataServices/CompetencyLearningResourcesDataService.cs +++ b/DigitalLearningSolutions.Data/DataServices/CompetencyLearningResourcesDataService.cs @@ -14,6 +14,7 @@ public interface ICompetencyLearningResourcesDataService IEnumerable GetCompetencyResourceAssessmentQuestionParameters(IEnumerable competencyLearningResourceIds); int AddCompetencyLearningResource(int resourceRefID, string originalResourceName, string description, string resourceType, string link, string catalogue, decimal rating, int competencyID, int adminId); + IEnumerable GetActiveCompetencyLearningResourcesByCompetencyIdAndReferenceId(int competencyId, int referenceId); } public class CompetencyLearningResourcesDataService : ICompetencyLearningResourcesDataService @@ -120,5 +121,20 @@ FROM CompetencyResourceAssessmentQuestionParameters new { competencyLearningResourceIds } ); } + public IEnumerable GetActiveCompetencyLearningResourcesByCompetencyIdAndReferenceId(int competencyId, int referenceId) + { + return connection.Query( + @"SELECT + clr.ID, + clr.CompetencyID, + clr.LearningResourceReferenceID, + clr.AdminID, + lrr.ResourceRefID AS LearningHubResourceReferenceId + FROM CompetencyLearningResources AS clr + INNER JOIN LearningResourceReferences AS lrr ON lrr.ID = clr.LearningResourceReferenceID + WHERE CompetencyID = @competencyId AND ResourceRefID = @referenceId AND clr.RemovedDate IS NULL", + new { competencyId, referenceId } + ); + } } } diff --git a/DigitalLearningSolutions.Data/DataServices/FrameworkDataService.cs b/DigitalLearningSolutions.Data/DataServices/FrameworkDataService.cs index 3bdf62f412..43c0d4374b 100644 --- a/DigitalLearningSolutions.Data/DataServices/FrameworkDataService.cs +++ b/DigitalLearningSolutions.Data/DataServices/FrameworkDataService.cs @@ -252,9 +252,9 @@ string direction void RemoveCustomFlag(int flagId); void RemoveCollaboratorFromFramework(int frameworkId, int id); - void DeleteFrameworkCompetencyGroup(int frameworkCompetencyGroupId, int competencyGroupId, int adminId); + void DeleteFrameworkCompetencyGroup(int frameworkCompetencyGroupId, int competencyGroupId, int frameworkId, int adminId); - void DeleteFrameworkCompetency(int frameworkCompetencyId, int adminId); + void DeleteFrameworkCompetency(int frameworkCompetencyId, int? frameworkCompetencyGroupId, int frameworkId, int adminId); void DeleteFrameworkDefaultQuestion( int frameworkId, @@ -277,17 +277,39 @@ public class FrameworkDataService : IFrameworkDataService OwnerAdminID, (SELECT Forename + ' ' + Surname + (CASE WHEN Active = 1 THEN '' ELSE ' (Inactive)' END) AS Expr1 FROM AdminUsers WHERE (AdminID = FW.OwnerAdminID)) AS Owner, BrandID, - CategoryID, + FW.CategoryID, TopicID, CreatedDate, PublishStatusID, UpdatedByAdminID, (SELECT Forename + ' ' + Surname + (CASE WHEN Active = 1 THEN '' ELSE ' (Inactive)' END) AS Expr1 FROM AdminUsers AS AdminUsers_1 WHERE (AdminID = FW.UpdatedByAdminID)) AS UpdatedBy, - CASE WHEN FW.OwnerAdminID = @adminId THEN 3 WHEN fwc.CanModify = 1 THEN 2 WHEN fwc.CanModify = 0 THEN 1 ELSE 0 END AS UserRole, - fwr.ID AS FrameworkReviewID"; + CASE + WHEN (aa.UserID = (SELECT UserID FROM AdminAccounts WHERE ID = @adminId)) THEN 3 + WHEN (fwc.CanModify = 1) OR + (SELECT COUNT(*) + FROM FrameworkCollaborators fc + JOIN AdminAccounts aa1 ON fc.AdminID = aa1.ID + WHERE fc.FrameworkID = fw.ID + AND fc.CanModify = 1 AND fc.IsDeleted = 0 + AND aa1.UserID = (SELECT aa2.UserID FROM AdminAccounts aa2 WHERE aa2.ID = @adminId)) > 0 THEN 2 + WHEN (fwc.CanModify = 0) OR + (SELECT COUNT(*) + FROM FrameworkCollaborators fc + JOIN AdminAccounts aa3 ON fc.AdminID = aa3.ID + WHERE fc.FrameworkID = fw.ID + AND fc.CanModify = 0 AND fc.IsDeleted = 0 + AND aa3.UserID = (SELECT aa4.UserID FROM AdminAccounts aa4 WHERE aa4.ID = @adminId)) > 0 THEN 1 + ELSE 0 + END AS UserRole, + (SELECT fwr.ID + FROM FrameworkCollaborators fc + INNER JOIN AdminAccounts aa3 ON fc.AdminID = aa3.ID + LEFT OUTER JOIN FrameworkReviews AS fwr ON fc.ID = fwr.FrameworkCollaboratorID AND fwr.Archived IS NULL AND fwr.ReviewComplete IS NULL + WHERE fc.FrameworkID = fw.ID AND fc.IsDeleted = 0 + AND aa3.UserID = (SELECT aa4.UserID FROM AdminAccounts aa4 WHERE aa4.ID = @adminId)) AS FrameworkReviewID"; private const string BrandedFrameworkFields = - @",(SELECT BrandName + @", FW.Description, FW.FrameworkConfig AS Vocabulary, (SELECT BrandName FROM Brands WHERE (BrandID = FW.BrandID)) AS Brand, (SELECT CategoryName @@ -304,9 +326,8 @@ FROM CourseTopics private const string FlagFields = @"fl.ID AS FlagId, fl.FrameworkId, fl.FlagName, fl.FlagGroup, fl.FlagTagClass"; private const string FrameworkTables = - @"Frameworks AS FW LEFT OUTER JOIN - FrameworkCollaborators AS fwc ON fwc.FrameworkID = FW.ID AND fwc.AdminID = @adminId AND COALESCE(IsDeleted, 0) = 0 - LEFT OUTER JOIN FrameworkReviews AS fwr ON fwc.ID = fwr.FrameworkCollaboratorID AND fwr.Archived IS NULL AND fwr.ReviewComplete IS NULL"; + @"Frameworks AS FW INNER JOIN AdminAccounts AS aa ON aa.ID = fw.OwnerAdminID + LEFT OUTER JOIN FrameworkCollaborators AS fwc ON fwc.FrameworkID = FW.ID AND fwc.AdminID = @adminId AND COALESCE(IsDeleted, 0) = 0 "; private const string AssessmentQuestionFields = @"SELECT AQ.ID, AQ.Question, AQ.MinValue, AQ.MaxValue, AQ.AssessmentQuestionInputTypeID, AQI.InputTypeName, AQ.AddedByAdminId, CASE WHEN AQ.AddedByAdminId = @adminId THEN 1 ELSE 0 END AS UserIsOwner, AQ.CommentsPrompt, AQ.CommentsHint"; @@ -680,9 +701,11 @@ public int InsertFrameworkCompetency( var numberOfAffectedRows = connection.Execute( @"INSERT INTO FrameworkCompetencies ([CompetencyID], FrameworkCompetencyGroupID, UpdatedByAdminID, Ordering, FrameworkID) VALUES (@competencyId, @frameworkCompetencyGroupID, @adminId, COALESCE - ((SELECT MAX(Ordering) AS OrderNum - FROM [FrameworkCompetencies] - WHERE ([FrameworkCompetencyGroupID] = @frameworkCompetencyGroupID)), 0)+1, @frameworkId)", + ((SELECT MAX(Ordering) AS OrderNum + FROM [FrameworkCompetencies] + WHERE ((@frameworkCompetencyGroupID IS NULL AND FrameworkCompetencyGroupID IS NULL) OR + (@frameworkCompetencyGroupID IS NOT NULL AND FrameworkCompetencyGroupID = @frameworkCompetencyGroupID)) AND + FrameworkID = @frameworkId ), 0)+1, @frameworkId)", new { competencyId, frameworkCompetencyGroupID, adminId, frameworkId } ); if (numberOfAffectedRows < 1) @@ -707,7 +730,7 @@ FROM [FrameworkCompetencies] new { competencyId, frameworkCompetencyGroupID } ); } - if(addDefaultQuestions) + if (addDefaultQuestions) { AddDefaultQuestionsToCompetency(competencyId, frameworkId); } @@ -1033,7 +1056,7 @@ int adminId { var numberOfAffectedRows = connection.Execute( @"UPDATE CompetencyGroups SET Name = @name, UpdatedByAdminID = @adminId, Description = @description - WHERE ID = @competencyGroupId AND (Name <> @name OR Description <> @description)", + WHERE ID = @competencyGroupId AND (Name <> @name OR ISNULL(Description, '') <> ISNULL(@description, ''))", new { name, adminId, competencyGroupId, description } ); if (numberOfAffectedRows < 1) @@ -1134,7 +1157,7 @@ public void MoveFrameworkCompetency(int frameworkCompetencyId, bool singleStep, ); } - public void DeleteFrameworkCompetencyGroup(int frameworkCompetencyGroupId, int competencyGroupId, int adminId) + public void DeleteFrameworkCompetencyGroup(int frameworkCompetencyGroupId, int competencyGroupId, int frameworkId, int adminId) { if ((frameworkCompetencyGroupId < 1) | (adminId < 1)) { @@ -1165,7 +1188,23 @@ public void DeleteFrameworkCompetencyGroup(int frameworkCompetencyGroupId, int c new { frameworkCompetencyGroupId } ); - if (numberOfAffectedRows < 1) + if (numberOfAffectedRows > 0) + { + connection.Execute( + @"WITH Ranked AS ( +    SELECT ID, +            ROW_NUMBER() OVER (PARTITION BY FrameworkID ORDER BY Ordering) AS NewOrder +    FROM FrameworkCompetencyGroups + Where FrameworkID = @frameworkID + ) + UPDATE fcg + SET fcg.Ordering = r.NewOrder + FROM FrameworkCompetencyGroups fcg + JOIN Ranked r ON fcg.ID = r.ID;", + new { frameworkId } + ); + } + else { logger.LogWarning( "Not deleting framework competency group as db update failed. " + @@ -1210,7 +1249,7 @@ public void DeleteFrameworkCompetencyGroup(int frameworkCompetencyGroupId, int c } } - public void DeleteFrameworkCompetency(int frameworkCompetencyId, int adminId) + public void DeleteFrameworkCompetency(int frameworkCompetencyId, int? frameworkCompetencyGroupId, int frameworkId, int adminId) { var competencyId = connection.QuerySingle( @"SELECT CompetencyID FROM FrameworkCompetencies WHERE ID = @frameworkCompetencyId", @@ -1234,7 +1273,24 @@ public void DeleteFrameworkCompetency(int frameworkCompetencyId, int adminId) @"DELETE FROM FrameworkCompetencies WHERE ID = @frameworkCompetencyId", new { frameworkCompetencyId } ); - if (numberOfAffectedRows < 1) + if (numberOfAffectedRows > 0) + { + connection.Execute( + @"WITH Ranked AS ( +    SELECT ID, +            ROW_NUMBER() OVER (PARTITION BY FrameworkID ORDER BY Ordering) AS NewOrder +    FROM FrameworkCompetencies + Where (FrameworkCompetencyGroupID = @frameworkCompetencyGroupID) OR (FrameworkCompetencyGroupID IS NULL AND @frameworkCompetencyGroupID IS NULL) AND + FrameworkID = @frameworkID + ) + UPDATE fc + SET fc.Ordering = r.NewOrder + FROM FrameworkCompetencies fc + JOIN Ranked r ON fc.ID = r.ID;", + new { frameworkCompetencyGroupId, frameworkId } + ); + } + else { logger.LogWarning( "Not deleting framework competency as db update failed. " + @@ -1838,9 +1894,20 @@ FROM Competencies AS C INNER JOIN public int GetAdminUserRoleForFrameworkId(int adminId, int frameworkId) { return connection.QuerySingle( - @"SELECT CASE WHEN FW.OwnerAdminID = @adminId THEN 3 WHEN COALESCE (fwc.CanModify, 0) = 1 THEN 2 WHEN COALESCE (fwc.CanModify, 0) = 0 THEN 1 ELSE 0 END AS UserRole - FROM Frameworks AS FW LEFT OUTER JOIN - FrameworkCollaborators AS fwc ON fwc.FrameworkID = FW.ID AND fwc.AdminID = @adminId AND fwc.IsDeleted = 0 + @"SELECT CASE + WHEN (aa.UserID = (SELECT UserID FROM AdminAccounts WHERE ID = @adminId)) THEN 3 + WHEN (fwc.CanModify = 1) OR + (SELECT COUNT(*) + FROM FrameworkCollaborators fc + JOIN AdminAccounts aa1 ON fc.AdminID = aa1.ID + WHERE fc.FrameworkID = fw.ID + AND fc.CanModify = 1 AND fc.IsDeleted = 0 + AND aa1.UserID = (SELECT aa2.UserID FROM AdminAccounts aa2 WHERE aa2.ID = @adminId)) > 0 THEN 2 + WHEN fwc.CanModify = 0 THEN 1 ELSE 0 + END AS UserRole + FROM Frameworks AS FW INNER JOIN + AdminAccounts AS aa ON aa.ID = fw.OwnerAdminID LEFT OUTER JOIN + FrameworkCollaborators AS fwc ON fwc.FrameworkID = FW.ID AND fwc.AdminID = @adminId AND fwc.IsDeleted = 0 WHERE (FW.ID = @frameworkId)", new { adminId, frameworkId } ); @@ -2064,10 +2131,13 @@ FROM FrameworkReviews AS FR INNER JOIN { return connection.Query( @"SELECT FR.ID, FR.FrameworkID, FR.FrameworkCollaboratorID, FC.UserEmail, CAST(CASE WHEN FC.AdminID IS NULL THEN 0 ELSE 1 END AS bit) AS IsRegistered, FR.ReviewRequested, FR.ReviewComplete, FR.SignedOff, FR.FrameworkCommentID, FC1.Comments AS Comment, FR.SignOffRequired - FROM FrameworkReviews AS FR INNER JOIN - FrameworkCollaborators AS FC ON FR.FrameworkCollaboratorID = FC.ID LEFT OUTER JOIN - FrameworkComments AS FC1 ON FR.FrameworkCommentID = FC1.ID - WHERE FR.ID = @reviewId AND FR.FrameworkID = @frameworkId AND FC.AdminID = @adminId AND FR.Archived IS NULL AND IsDeleted = 0", + FROM FrameworkReviews AS FR INNER JOIN + FrameworkCollaborators AS FC ON FR.FrameworkCollaboratorID = FC.ID INNER JOIN + AdminAccounts AS aa ON aa.ID = FC.AdminID LEFT OUTER JOIN + FrameworkComments AS FC1 ON FR.FrameworkCommentID = FC1.ID + WHERE FR.ID = @reviewId AND FR.FrameworkID = @frameworkId AND + aa.UserID = (SELECT aa1.UserID FROM AdminAccounts aa1 WHERE aa1.ID = @adminId) AND + FR.Archived IS NULL AND IsDeleted = 0", new { frameworkId, adminId, reviewId } ).FirstOrDefault(); } @@ -2190,7 +2260,7 @@ public void ArchiveReviewRequest(int reviewId) FROM FrameworkCollaborators WHERE (FrameworkID = FW.ID) AND (IsDeleted=0)))) AS MyFrameworksCount, - (SELECT COUNT(*) FROM SelfAssessments) AS RoleProfileCount, + (SELECT COUNT(*) FROM SelfAssessments) AS CompetencyAssessmentCount, (SELECT COUNT(*) FROM SelfAssessments AS RP LEFT OUTER JOIN SelfAssessmentCollaborators AS RPC ON RPC.SelfAssessmentID = RP.ID AND RPC.AdminID = @adminId @@ -2198,7 +2268,7 @@ FROM FrameworkCollaborators (@adminId IN (SELECT AdminID FROM SelfAssessmentCollaborators - WHERE (SelfAssessmentID = RP.ID)))) AS MyRoleProfileCount", + WHERE (SelfAssessmentID = RP.ID)))) AS MyCompetencyAssessmentCount", new { adminId } ).FirstOrDefault(); } @@ -2208,7 +2278,7 @@ public IEnumerable GetDashboardToDoItems(int adminId) return connection.Query( @"SELECT FW.ID AS FrameworkID, - 0 AS RoleProfileID, + 0 AS SelfAssessmentID, FW.FrameworkName AS ItemName, AU.Forename + ' ' + AU.Surname + (CASE WHEN AU.Active = 1 THEN '' ELSE ' (Inactive)' END) AS RequestorName, FWR.SignOffRequired, @@ -2220,8 +2290,8 @@ FROM FrameworkReviews AS FWR WHERE (FWC.AdminID = @adminId) AND (FWR.ReviewComplete IS NULL) AND (FWR.Archived IS NULL) UNION ALL SELECT - 0 AS SelfAssessmentID, - RP.ID AS SelfAssessmentID, + 0 AS FrameworkID, + RP.ID AS CompetencyAssessmentID, RP.Name AS ItemName, AU.Forename + ' ' + AU.Surname + (CASE WHEN AU.Active = 1 THEN '' ELSE ' (Inactive)' END) AS RequestorName, RPR.SignOffRequired, diff --git a/DigitalLearningSolutions.Data/DataServices/LoginDataService.cs b/DigitalLearningSolutions.Data/DataServices/LoginDataService.cs new file mode 100644 index 0000000000..109d5a9273 --- /dev/null +++ b/DigitalLearningSolutions.Data/DataServices/LoginDataService.cs @@ -0,0 +1,63 @@ +namespace DigitalLearningSolutions.Data.DataServices +{ + using Dapper; + using System.Data; + + public interface ILoginDataService + { + void UpdateLastAccessedForUsersTable(int Id); + + void UpdateLastAccessedForDelegatesAccountsTable(int Id); + + void UpdateLastAccessedForAdminAccountsTable(int Id); + } + + public class LoginDataService : ILoginDataService + { + private readonly IDbConnection connection; + + public LoginDataService(IDbConnection connection) + { + this.connection = connection; + } + + public void UpdateLastAccessedForUsersTable(int Id) + { + connection.Execute( + @"UPDATE Users SET + LastAccessed = GetUtcDate() + WHERE ID = @Id", + new + { + Id + } + ); + } + + public void UpdateLastAccessedForDelegatesAccountsTable(int Id) + { + connection.Execute( + @"UPDATE DelegateAccounts SET + LastAccessed = GetUtcDate() + WHERE ID = @Id", + new + { + Id + } + ); + } + + public void UpdateLastAccessedForAdminAccountsTable(int Id) + { + connection.Execute( + @"UPDATE AdminAccounts SET + LastAccessed = GetUtcDate() + WHERE ID = @Id", + new + { + Id + } + ); + } + } +} diff --git a/DigitalLearningSolutions.Data/DataServices/RoleProfileDataService.cs b/DigitalLearningSolutions.Data/DataServices/RoleProfileDataService.cs deleted file mode 100644 index 7e37d4ff03..0000000000 --- a/DigitalLearningSolutions.Data/DataServices/RoleProfileDataService.cs +++ /dev/null @@ -1,197 +0,0 @@ -namespace DigitalLearningSolutions.Data.DataServices -{ - using System.Collections.Generic; - using System.Data; - using System.Linq; - using Dapper; - using DigitalLearningSolutions.Data.Models.RoleProfiles; - using Microsoft.Extensions.Logging; - - public interface IRoleProfileDataService - { - //GET DATA - IEnumerable GetAllRoleProfiles(int adminId); - - IEnumerable GetRoleProfilesForAdminId(int adminId); - - RoleProfileBase? GetRoleProfileBaseById(int roleProfileId, int adminId); - - RoleProfileBase? GetRoleProfileByName(string roleProfileName, int adminId); - - IEnumerable GetNRPProfessionalGroups(); - - //UPDATE DATA - bool UpdateRoleProfileName(int roleProfileId, int adminId, string roleProfileName); - - bool UpdateRoleProfileProfessionalGroup(int roleProfileId, int adminId, int? nrpProfessionalGroupID); - //INSERT DATA - - //DELETE DATA - } - - public class RoleProfileDataService : IRoleProfileDataService - { - private const string SelfAssessmentBaseFields = @"rp.ID, rp.Name AS RoleProfileName, rp.Description, rp.BrandID, - rp.ParentSelfAssessmentID, - rp.[National], rp.[Public], rp.CreatedByAdminID AS OwnerAdminID, - rp.NRPProfessionalGroupID, - rp.NRPSubGroupID, - rp.NRPRoleID, - rp.PublishStatusID, CASE WHEN rp.CreatedByAdminID = @adminId THEN 3 WHEN rpc.CanModify = 1 THEN 2 WHEN rpc.CanModify = 0 THEN 1 ELSE 0 END AS UserRole"; - - private const string SelfAssessmentFields = - @", rp.CreatedDate, - (SELECT BrandName - FROM Brands - WHERE (BrandID = rp.BrandID)) AS Brand, - (SELECT [Name] - FROM SelfAssessments AS rp2 - WHERE (ID = rp.ParentSelfAssessmentID)) AS ParentSelfAssessment, - (SELECT Forename + ' ' + Surname + (CASE WHEN Active = 1 THEN '' ELSE ' (Inactive)' END) AS Expr1 - FROM AdminUsers - WHERE (AdminID = rp.CreatedByAdminID)) AS Owner, - rp.Archived, - rp.LastEdit, - (SELECT ProfessionalGroup - FROM NRPProfessionalGroups - WHERE (ID = rp.NRPProfessionalGroupID)) AS NRPProfessionalGroup, - (SELECT SubGroup - FROM NRPSubGroups - WHERE (ID = rp.NRPSubGroupID)) AS NRPSubGroup, - (SELECT RoleProfile - FROM NRPRoles - WHERE (ID = rp.NRPRoleID)) AS NRPRole, rpr.ID AS SelfAssessmentReviewID"; - - private const string SelfAssessmentBaseTables = - @"SelfAssessments AS rp LEFT OUTER JOIN - SelfAssessmentCollaborators AS rpc ON rpc.SelfAssessmentID = rp.ID AND rpc.AdminID = @adminId"; - - private const string SelfAssessmentTables = - @" LEFT OUTER JOIN - SelfAssessmentReviews AS rpr ON rpc.ID = rpr.SelfAssessmentCollaboratorID AND rpr.Archived IS NULL AND rpr.ReviewComplete IS NULL"; - - private readonly IDbConnection connection; - private readonly ILogger logger; - - public RoleProfileDataService(IDbConnection connection, ILogger logger) - { - this.connection = connection; - this.logger = logger; - } - - public IEnumerable GetAllRoleProfiles(int adminId) - { - return connection.Query( - $@"SELECT {SelfAssessmentBaseFields} {SelfAssessmentFields} - FROM {SelfAssessmentBaseTables} {SelfAssessmentTables}", - new { adminId } - ); - } - - public IEnumerable GetRoleProfilesForAdminId(int adminId) - { - return connection.Query( - $@"SELECT {SelfAssessmentBaseFields} {SelfAssessmentFields} - FROM {SelfAssessmentBaseTables} {SelfAssessmentTables} - WHERE (rp.CreatedByAdminID = @adminId) OR - (@adminId IN - (SELECT AdminID - FROM SelfAssessmentCollaborators - WHERE (SelfAssessmentID = rp.ID)))", - new { adminId } - ); - } - - public RoleProfileBase? GetRoleProfileBaseById(int roleProfileId, int adminId) - { - return connection.Query( - $@"SELECT {SelfAssessmentBaseFields} - FROM {SelfAssessmentBaseTables} - WHERE (rp.ID = @roleProfileId)", - new { roleProfileId, adminId } - ).FirstOrDefault(); - } - - public bool UpdateRoleProfileName(int roleProfileId, int adminId, string roleProfileName) - { - if ((roleProfileName.Length == 0) | (adminId < 1) | (roleProfileId < 1)) - { - logger.LogWarning( - $"Not updating role profile name as it failed server side validation. AdminId: {adminId}, roleProfileName: {roleProfileName}, roleProfileId: {roleProfileId}" - ); - return false; - } - - var existingSelfAssessments = (int)connection.ExecuteScalar( - @"SELECT COUNT(*) FROM SelfAssessments WHERE [Name] = @roleProfileName AND ID <> @roleProfileId", - new { roleProfileName, roleProfileId } - ); - if (existingSelfAssessments > 0) - { - return false; - } - - var numberOfAffectedRows = connection.Execute( - @"UPDATE SelfAssessments SET [Name] = @roleProfileName, UpdatedByAdminID = @adminId - WHERE ID = @roleProfileId", - new { roleProfileName, adminId, roleProfileId } - ); - if (numberOfAffectedRows < 1) - { - logger.LogWarning( - "Not updating role profile name as db update failed. " + - $"SelfAssessmentName: {roleProfileName}, admin id: {adminId}, roleProfileId: {roleProfileId}" - ); - return false; - } - - return true; - } - - public IEnumerable GetNRPProfessionalGroups() - { - return connection.Query( - @"SELECT ID, ProfessionalGroup, Active - FROM NRPProfessionalGroups - WHERE (Active = 1) - ORDER BY ProfessionalGroup" - ); - } - - public RoleProfileBase? GetRoleProfileByName(string roleProfileName, int adminId) - { - return connection.Query( - $@"SELECT {SelfAssessmentBaseFields} - FROM {SelfAssessmentBaseTables} - WHERE (rp.Name = @roleProfileName)", - new { roleProfileName, adminId } - ).FirstOrDefault(); - } - - public bool UpdateRoleProfileProfessionalGroup(int roleProfileId, int adminId, int? nrpProfessionalGroupID) - { - var sameCount = (int)connection.ExecuteScalar( - @"SELECT COUNT(*) FROM RoleProfiles WHERE ID = @roleProfileId AND NRPProfessionalGroupID = @nrpProfessionalGroupID", - new { roleProfileId, nrpProfessionalGroupID } - ); - if (sameCount > 0) - { - //same so don't update: - return false; - } - - //needs updating: - var numberOfAffectedRows = connection.Execute( - @"UPDATE SelfAssessments SET NRPProfessionalGroupID = @nrpProfessionalGroupID, NRPSubGroupID = NULL, NRPRoleID = NULL, UpdatedByAdminID = @adminId - WHERE ID = @roleProfileId", - new { nrpProfessionalGroupID, adminId, roleProfileId } - ); - if (numberOfAffectedRows > 0) - { - return true; - } - - return false; - } - } -} diff --git a/DigitalLearningSolutions.Data/DataServices/SelfAssessmentDataService/SelfAsssessmentReportDataService.cs b/DigitalLearningSolutions.Data/DataServices/SelfAssessmentDataService/SelfAsssessmentReportDataService.cs index 50168d4e64..0bd5d38f37 100644 --- a/DigitalLearningSolutions.Data/DataServices/SelfAssessmentDataService/SelfAsssessmentReportDataService.cs +++ b/DigitalLearningSolutions.Data/DataServices/SelfAssessmentDataService/SelfAsssessmentReportDataService.cs @@ -1,135 +1,139 @@ -namespace DigitalLearningSolutions.Data.DataServices.SelfAssessmentDataService -{ - using Dapper; - using DigitalLearningSolutions.Data.Models.SelfAssessments.Export; - using DigitalLearningSolutions.Data.Models.SelfAssessments; - using Microsoft.Extensions.Logging; - using System.Collections.Generic; - using System.Data; - - public interface ISelfAssessmentReportDataService - { - IEnumerable GetSelfAssessmentsForReportList(int centreId, int? categoryId); - IEnumerable GetSelfAssessmentReportDataForCentre(int centreId, int selfAssessmentId); - } - public partial class SelfAssessmentReportDataService : ISelfAssessmentReportDataService - { - private readonly IDbConnection connection; - private readonly ILogger logger; - - public SelfAssessmentReportDataService(IDbConnection connection, ILogger logger) - { - this.connection = connection; - this.logger = logger; - } - - public IEnumerable GetSelfAssessmentsForReportList(int centreId, int? categoryId) - { - return connection.Query( - @"SELECT csa.SelfAssessmentID AS Id, sa.Name, - (SELECT COUNT (DISTINCT da.UserID) AS Learners - FROM CandidateAssessments AS ca1 INNER JOIN - DelegateAccounts AS da ON ca1.DelegateUserID = da.UserID - WHERE (da.CentreID = @centreId) AND (ca1.RemovedDate IS NULL) AND (ca1.SelfAssessmentID = csa.SelfAssessmentID) AND ca1.NonReportable=0) AS LearnerCount - FROM CentreSelfAssessments AS csa INNER JOIN - SelfAssessments AS sa ON csa.SelfAssessmentID = sa.ID - WHERE (csa.CentreID = @centreId) AND (sa.CategoryID = @categoryId) AND (sa.SupervisorResultsReview = 1) AND (sa.ArchivedDate IS NULL) OR - (csa.CentreID = @centreId) AND (sa.CategoryID = @categoryId) AND (sa.ArchivedDate IS NULL) AND (sa.SupervisorSelfAssessmentReview = 1) OR - (csa.CentreID = @centreId) AND (sa.SupervisorResultsReview = 1) AND (sa.ArchivedDate IS NULL) AND (@categoryId = 0) OR - (csa.CentreID = @centreId) AND (sa.ArchivedDate IS NULL) AND (sa.SupervisorSelfAssessmentReview = 1) AND (@categoryId = 0) - ORDER BY sa.Name", - new { centreId, categoryId = categoryId ??= 0 } - ); - } - - public IEnumerable GetSelfAssessmentReportDataForCentre(int centreId, int selfAssessmentId) - { - return connection.Query( - @"WITH LatestAssessmentResults AS - ( - SELECT s.DelegateUserID - , CASE WHEN COALESCE (rr.LevelRAG, 0) = 3 THEN s.ID ELSE NULL END AS SelfAssessed - , CASE WHEN sv.Verified IS NOT NULL AND sv.SignedOff = 1 AND COALESCE (rr.LevelRAG, 0) = 3 THEN s.ID ELSE NULL END AS Confirmed - , CASE WHEN sas.Optional = 1 THEN s.CompetencyID ELSE NULL END AS Optional - FROM SelfAssessmentResults AS s LEFT OUTER JOIN - SelfAssessmentStructure AS sas ON sas.SelfAssessmentID = @selfAssessmentId AND s.CompetencyID = sas.CompetencyID LEFT OUTER JOIN - SelfAssessmentResultSupervisorVerifications AS sv ON s.ID = sv.SelfAssessmentResultId AND sv.Superceded = 0 LEFT OUTER JOIN - CompetencyAssessmentQuestionRoleRequirements AS rr ON s.CompetencyID = rr.CompetencyID AND s.AssessmentQuestionID = rr.AssessmentQuestionID AND sas.SelfAssessmentID = rr.SelfAssessmentID AND s.Result = rr.LevelValue - WHERE (sas.SelfAssessmentID = @selfAssessmentId) - ) - SELECT - sa.Name AS SelfAssessment - , u.LastName + ', ' + u.FirstName AS Learner - , da.Active AS LearnerActive - , u.ProfessionalRegistrationNumber AS PRN - , jg.JobGroupName AS JobGroup - , CASE WHEN c.CustomField1PromptID = 10 THEN da.Answer1 WHEN c.CustomField2PromptID = 10 THEN da.Answer2 WHEN c.CustomField3PromptID = 10 THEN da.Answer3 WHEN c.CustomField4PromptID = 10 THEN da.Answer4 WHEN c.CustomField5PromptID = 10 THEN da.Answer5 WHEN c.CustomField6PromptID = 10 THEN da.Answer6 ELSE '' END AS 'ProgrammeCourse' - , CASE WHEN c.CustomField1PromptID = 4 THEN da.Answer1 WHEN c.CustomField2PromptID = 4 THEN da.Answer2 WHEN c.CustomField3PromptID = 4 THEN da.Answer3 WHEN c.CustomField4PromptID = 4 THEN da.Answer4 WHEN c.CustomField5PromptID = 4 THEN da.Answer5 WHEN c.CustomField6PromptID = 4 THEN da.Answer6 ELSE '' END AS 'Organisation' - , CASE WHEN c.CustomField1PromptID = 1 THEN da.Answer1 WHEN c.CustomField2PromptID = 1 THEN da.Answer2 WHEN c.CustomField3PromptID = 1 THEN da.Answer3 WHEN c.CustomField4PromptID = 1 THEN da.Answer4 WHEN c.CustomField5PromptID = 1 THEN da.Answer5 WHEN c.CustomField6PromptID = 1 THEN da.Answer6 ELSE '' END AS 'DepartmentTeam' - , dbo.GetOtherCentresForSelfAssessment(da.UserID, @SelfAssessmentID, c.CentreID) AS OtherCentres - , CASE - WHEN aa.ID IS NULL THEN 'Learner' - WHEN aa.IsCentreManager = 1 THEN 'Centre Manager' - WHEN aa.IsCentreAdmin = 1 AND aa.IsCentreManager = 0 THEN 'Centre Admin' - WHEN aa.IsSupervisor = 1 THEN 'Supervisor' - WHEN aa.IsNominatedSupervisor = 1 THEN 'Nominated supervisor' - END AS DLSRole - , da.DateRegistered AS Registered - , ca.StartedDate AS Started - , ca.LastAccessed - , COALESCE(COUNT(DISTINCT LAR.Optional), NULL) AS [OptionalProficienciesAssessed] - , COALESCE(COUNT(DISTINCT LAR.SelfAssessed), NULL) AS [SelfAssessedAchieved] - , COALESCE(COUNT(DISTINCT LAR.Confirmed), NULL) AS [ConfirmedResults] - , max(casv.Requested) AS SignOffRequested - , max(1*casv.SignedOff) AS SignOffAchieved - , min(casv.Verified) AS ReviewedDate - FROM - CandidateAssessments AS ca INNER JOIN - DelegateAccounts AS da ON ca.DelegateUserID = da.UserID and da.CentreID = @centreId INNER JOIN - Users as u ON u.ID = da.UserID INNER JOIN - SelfAssessments AS sa INNER JOIN - CentreSelfAssessments AS csa ON sa.ID = csa.SelfAssessmentID INNER JOIN - Centres AS c ON csa.CentreID = c.CentreID ON da.CentreID = c.CentreID AND ca.SelfAssessmentID = sa.ID INNER JOIN - JobGroups AS jg ON u.JobGroupID = jg.JobGroupID LEFT OUTER JOIN - AdminAccounts AS aa ON da.UserID = aa.UserID AND aa.CentreID = da.CentreID AND aa.Active = 1 LEFT OUTER JOIN - CandidateAssessmentSupervisors AS cas ON ca.ID = cas.CandidateAssessmentID left JOIN - CandidateAssessmentSupervisorVerifications AS casv ON casv.CandidateAssessmentSupervisorID = cas.ID LEFT JOIN - SupervisorDelegates AS sd ON cas.SupervisorDelegateId = sd.ID - LEFT OUTER JOIN LatestAssessmentResults AS LAR ON LAR.DelegateUserID = ca.DelegateUserID - WHERE - (sa.ID = @SelfAssessmentID) AND (sa.ArchivedDate IS NULL) AND (c.Active = 1) AND (ca.RemovedDate IS NULL AND ca.NonReportable = 0) - Group by sa.Name - , u.LastName + ', ' + u.FirstName - , da.Active - , u.ProfessionalRegistrationNumber - , c.CustomField1PromptID - , c.CustomField2PromptID - , c.CustomField3PromptID - , c.CustomField4PromptID - , c.CustomField5PromptID - , c.CustomField6PromptID - , c.CentreID - , jg.JobGroupName - , da.ID - , da.Answer1 - , da.Answer2 - , da.Answer3 - , da.Answer4 - , da.Answer5 - , da.Answer6 - , da.DateRegistered - , da.UserID - , aa.ID - , aa.IsCentreManager - , aa.IsCentreAdmin - , aa.IsSupervisor - , aa.IsNominatedSupervisor - , ca.StartedDate - , ca.LastAccessed - ORDER BY - SelfAssessment, u.LastName + ', ' + u.FirstName", - new { centreId, selfAssessmentId } - ); - } - } -} +namespace DigitalLearningSolutions.Data.DataServices.SelfAssessmentDataService +{ + using Dapper; + using DigitalLearningSolutions.Data.Models.SelfAssessments.Export; + using DigitalLearningSolutions.Data.Models.SelfAssessments; + using Microsoft.Extensions.Logging; + using System.Collections.Generic; + using System.Data; + using ClosedXML.Excel; + + public interface ISelfAssessmentReportDataService + { + IEnumerable GetSelfAssessmentsForReportList(int centreId, int? categoryId); + IEnumerable GetSelfAssessmentReportDataForCentre(int centreId, int selfAssessmentId); + } + public partial class SelfAssessmentReportDataService : ISelfAssessmentReportDataService + { + private readonly IDbConnection connection; + private readonly ILogger logger; + + public SelfAssessmentReportDataService(IDbConnection connection, ILogger logger) + { + this.connection = connection; + this.logger = logger; + } + + public IEnumerable GetSelfAssessmentsForReportList(int centreId, int? categoryId) + { + return connection.Query( + @"SELECT csa.SelfAssessmentID AS Id, sa.Name, + (SELECT COUNT (DISTINCT da.UserID) AS Learners + FROM CandidateAssessments AS ca1 INNER JOIN + DelegateAccounts AS da ON ca1.DelegateUserID = da.UserID + WHERE (da.CentreID = @centreId) AND (ca1.RemovedDate IS NULL) AND (ca1.SelfAssessmentID = csa.SelfAssessmentID) AND ca1.NonReportable=0) AS LearnerCount + FROM CentreSelfAssessments AS csa INNER JOIN + SelfAssessments AS sa ON csa.SelfAssessmentID = sa.ID + WHERE (csa.CentreID = @centreId) AND (sa.CategoryID = @categoryId) AND (sa.SupervisorResultsReview = 1) AND (sa.ArchivedDate IS NULL) OR + (csa.CentreID = @centreId) AND (sa.CategoryID = @categoryId) AND (sa.ArchivedDate IS NULL) AND (sa.SupervisorSelfAssessmentReview = 1) OR + (csa.CentreID = @centreId) AND (sa.SupervisorResultsReview = 1) AND (sa.ArchivedDate IS NULL) AND (@categoryId = 0) OR + (csa.CentreID = @centreId) AND (sa.ArchivedDate IS NULL) AND (sa.SupervisorSelfAssessmentReview = 1) AND (@categoryId = 0) + ORDER BY sa.Name", + new { centreId, categoryId = categoryId ??= 0 } + ); + } + + public IEnumerable GetSelfAssessmentReportDataForCentre(int centreId, int selfAssessmentId) + { + return connection.Query( + @"WITH LatestAssessmentResults AS + ( + SELECT s.DelegateUserID + , CASE WHEN COALESCE (rr.LevelRAG, 0) = 3 THEN s.ID ELSE NULL END AS SelfAssessed + , CASE WHEN sv.Verified IS NOT NULL AND sv.SignedOff = 1 AND COALESCE (rr.LevelRAG, 0) = 3 THEN s.ID ELSE NULL END AS Confirmed + , CASE WHEN sas.Optional = 1 THEN s.CompetencyID ELSE NULL END AS Optional + FROM SelfAssessmentResults AS s LEFT OUTER JOIN + SelfAssessmentStructure AS sas ON sas.SelfAssessmentID = @selfAssessmentId AND s.CompetencyID = sas.CompetencyID LEFT OUTER JOIN + SelfAssessmentResultSupervisorVerifications AS sv ON s.ID = sv.SelfAssessmentResultId AND sv.Superceded = 0 LEFT OUTER JOIN + CompetencyAssessmentQuestionRoleRequirements AS rr ON s.CompetencyID = rr.CompetencyID AND s.AssessmentQuestionID = rr.AssessmentQuestionID AND sas.SelfAssessmentID = rr.SelfAssessmentID AND s.Result = rr.LevelValue + WHERE (sas.SelfAssessmentID = @selfAssessmentId) + ) + SELECT + sa.Name AS SelfAssessment + , u.LastName + ', ' + u.FirstName AS Learner + , da.Active AS LearnerActive + , u.ProfessionalRegistrationNumber AS PRN + , jg.JobGroupName AS JobGroup + , da.Answer1 AS RegistrationAnswer1 + , da.Answer2 AS RegistrationAnswer2 + , da.Answer3 AS RegistrationAnswer3 + , da.Answer4 AS RegistrationAnswer4 + , da.Answer5 AS RegistrationAnswer5 + , da.Answer6 AS RegistrationAnswer6 + , dbo.GetOtherCentresForSelfAssessment(da.UserID, @SelfAssessmentID, c.CentreID) AS OtherCentres + , CASE + WHEN aa.ID IS NULL THEN 'Learner' + WHEN aa.IsCentreManager = 1 THEN 'Centre Manager' + WHEN aa.IsCentreAdmin = 1 AND aa.IsCentreManager = 0 THEN 'Centre Admin' + WHEN aa.IsSupervisor = 1 THEN 'Supervisor' + WHEN aa.IsNominatedSupervisor = 1 THEN 'Nominated supervisor' + END AS DLSRole + , da.DateRegistered AS Registered + , ca.StartedDate AS Started + , ca.LastAccessed + , COALESCE(COUNT(DISTINCT LAR.Optional), NULL) AS [OptionalProficienciesAssessed] + , COALESCE(COUNT(DISTINCT LAR.SelfAssessed), NULL) AS [SelfAssessedAchieved] + , COALESCE(COUNT(DISTINCT LAR.Confirmed), NULL) AS [ConfirmedResults] + , max(casv.Requested) AS SignOffRequested + , max(1*casv.SignedOff) AS SignOffAchieved + , min(casv.Verified) AS ReviewedDate + FROM + CandidateAssessments AS ca INNER JOIN + DelegateAccounts AS da ON ca.DelegateUserID = da.UserID and da.CentreID = @centreId INNER JOIN + Users as u ON u.ID = da.UserID INNER JOIN + SelfAssessments AS sa INNER JOIN + CentreSelfAssessments AS csa ON sa.ID = csa.SelfAssessmentID INNER JOIN + Centres AS c ON csa.CentreID = c.CentreID ON da.CentreID = c.CentreID AND ca.SelfAssessmentID = sa.ID INNER JOIN + JobGroups AS jg ON u.JobGroupID = jg.JobGroupID LEFT OUTER JOIN + AdminAccounts AS aa ON da.UserID = aa.UserID AND aa.CentreID = da.CentreID AND aa.Active = 1 LEFT OUTER JOIN + CandidateAssessmentSupervisors AS cas ON ca.ID = cas.CandidateAssessmentID left JOIN + CandidateAssessmentSupervisorVerifications AS casv ON casv.CandidateAssessmentSupervisorID = cas.ID LEFT JOIN + SupervisorDelegates AS sd ON cas.SupervisorDelegateId = sd.ID + LEFT OUTER JOIN LatestAssessmentResults AS LAR ON LAR.DelegateUserID = ca.DelegateUserID + WHERE + (sa.ID = @SelfAssessmentID) AND (sa.ArchivedDate IS NULL) AND (c.Active = 1) AND (ca.RemovedDate IS NULL AND ca.NonReportable = 0) + Group by sa.Name + , u.LastName + ', ' + u.FirstName + , da.Active + , u.ProfessionalRegistrationNumber + , c.CustomField1PromptID + , c.CustomField2PromptID + , c.CustomField3PromptID + , c.CustomField4PromptID + , c.CustomField5PromptID + , c.CustomField6PromptID + , c.CentreID + , jg.JobGroupName + , da.ID + , da.Answer1 + , da.Answer2 + , da.Answer3 + , da.Answer4 + , da.Answer5 + , da.Answer6 + , da.DateRegistered + , da.UserID + , aa.ID + , aa.IsCentreManager + , aa.IsCentreAdmin + , aa.IsSupervisor + , aa.IsNominatedSupervisor + , ca.StartedDate + , ca.LastAccessed + ORDER BY + SelfAssessment, u.LastName + ', ' + u.FirstName", + new { centreId, selfAssessmentId } + ); + } + } +} diff --git a/DigitalLearningSolutions.Data/DataServices/SupervisorDataService.cs b/DigitalLearningSolutions.Data/DataServices/SupervisorDataService.cs index 2cfd546720..d1289107ec 100644 --- a/DigitalLearningSolutions.Data/DataServices/SupervisorDataService.cs +++ b/DigitalLearningSolutions.Data/DataServices/SupervisorDataService.cs @@ -1,7 +1,7 @@ namespace DigitalLearningSolutions.Data.DataServices { using Dapper; - using DigitalLearningSolutions.Data.Models.RoleProfiles; + using DigitalLearningSolutions.Data.Models.CompetencyAssessments; using DigitalLearningSolutions.Data.Models.SelfAssessments; using DigitalLearningSolutions.Data.Models.Supervisor; using Microsoft.Extensions.Logging; @@ -23,8 +23,8 @@ public interface ISupervisorDataService IEnumerable GetSupervisorDashboardToDoItemsForRequestedSignOffs(int adminId); IEnumerable GetSupervisorDashboardToDoItemsForRequestedReviews(int adminId); DelegateSelfAssessment? GetSelfAssessmentBaseByCandidateAssessmentId(int candidateAssessmentId, int? adminIdCategoryId); - IEnumerable GetAvailableRoleProfilesForDelegate(int candidateId, int centreId, int? categoryId); - RoleProfile? GetRoleProfileById(int selfAssessmentId); + IEnumerable GetAvailableCompetencyAssessmentsForDelegate(int candidateId, int centreId, int? categoryId); + CompetencyAssessment? GetCompetencyAssessmentById(int selfAssessmentId); IEnumerable GetSupervisorRolesForSelfAssessment(int selfAssessmentId); IEnumerable GetSupervisorRolesBySelfAssessmentIdForSupervisor(int selfAssessmentId); IEnumerable GetDelegateNominatableSupervisorRolesForSelfAssessment(int selfAssessmentId); @@ -583,7 +583,7 @@ public bool RemoveSupervisorDelegateById(int supervisorDelegateId, int delegateU public IEnumerable GetSelfAssessmentsForSupervisorDelegateId(int supervisorDelegateId, int? adminIdCategoryId) { return connection.Query( - @$"SELECT {delegateSelfAssessmentFields}, COALESCE(ca.LastAccessed, ca.StartedDate) AS LastAccessed, ca.CompleteByDate, ca.LaunchCount, ca.CompletedDate, r.RoleProfile, sg.SubGroup, pg.ProfessionalGroup,CONVERT(BIT, IIF(cas.CandidateAssessmentID IS NULL, 0, 1)) AS IsAssignedToSupervisor,ca.DelegateUserID, + @$"SELECT {delegateSelfAssessmentFields}, COALESCE(ca.LastAccessed, ca.StartedDate) AS LastAccessed, ca.CompleteByDate, ca.LaunchCount, ca.CompletedDate, r.CompetencyAssessment, sg.SubGroup, pg.ProfessionalGroup,CONVERT(BIT, IIF(cas.CandidateAssessmentID IS NULL, 0, 1)) AS IsAssignedToSupervisor,ca.DelegateUserID, (SELECT COUNT(*) AS Expr1 FROM CandidateAssessmentSupervisorVerifications AS casv WHERE (CandidateAssessmentSupervisorID = cas.ID) AND (Requested IS NOT NULL) AND (Verified IS NULL)) AS SignOffRequested, @@ -772,10 +772,10 @@ public int RemoveSelfAssessmentResultSupervisorVerificationById(int id) } return numberOfAffectedRows; } - public IEnumerable GetAvailableRoleProfilesForDelegate(int delegateUserId, int centreId, int? categoryId) + public IEnumerable GetAvailableCompetencyAssessmentsForDelegate(int delegateUserId, int centreId, int? categoryId) { - return connection.Query( - $@"SELECT rp.ID, rp.Name AS RoleProfileName, rp.Description, rp.BrandID, rp.ParentSelfAssessmentID, rp.[National], rp.[Public], rp.CreatedByAdminID AS OwnerAdminID, rp.NRPProfessionalGroupID, rp.NRPSubGroupID, rp.NRPRoleID, rp.PublishStatusID, 0 AS UserRole, rp.CreatedDate, + return connection.Query( + $@"SELECT rp.ID, rp.Name AS CompetencyAssessmentName, rp.Description, rp.BrandID, rp.ParentSelfAssessmentID, rp.[National], rp.[Public], rp.CreatedByAdminID AS OwnerAdminID, rp.NRPProfessionalGroupID, rp.NRPSubGroupID, rp.NRPRoleID, rp.PublishStatusID, 0 AS UserRole, rp.CreatedDate, (SELECT BrandName FROM Brands WHERE (BrandID = rp.BrandID)) AS Brand, '' AS ParentSelfAssessment, '' AS Owner, rp.Archived, rp.LastEdit, @@ -785,7 +785,7 @@ FROM NRPProfessionalGroups (SELECT SubGroup FROM NRPSubGroups WHERE (ID = rp.NRPSubGroupID)) AS NRPSubGroup, - (SELECT RoleProfile + (SELECT CompetencyAssessment FROM NRPRoles WHERE (ID = rp.NRPRoleID)) AS NRPRole, 0 AS SelfAssessmentReviewID FROM SelfAssessments AS rp INNER JOIN @@ -800,10 +800,10 @@ FROM CandidateAssessments AS CA ); } - public RoleProfile? GetRoleProfileById(int selfAssessmentId) + public CompetencyAssessment? GetCompetencyAssessmentById(int selfAssessmentId) { - return connection.Query( - $@"SELECT ID, Name AS RoleProfileName, Description, BrandID, ParentSelfAssessmentID, [National], [Public], CreatedByAdminID AS OwnerAdminID, NRPProfessionalGroupID, NRPSubGroupID, NRPRoleID, PublishStatusID, 0 AS UserRole, CreatedDate, + return connection.Query( + $@"SELECT ID, Name AS CompetencyAssessmentName, Description, BrandID, ParentSelfAssessmentID, [National], [Public], CreatedByAdminID AS OwnerAdminID, NRPProfessionalGroupID, NRPSubGroupID, NRPRoleID, PublishStatusID, 0 AS UserRole, CreatedDate, (SELECT BrandName FROM Brands WHERE (BrandID = rp.BrandID)) AS Brand, @@ -815,7 +815,7 @@ FROM NRPProfessionalGroups (SELECT SubGroup FROM NRPSubGroups WHERE (ID = rp.NRPSubGroupID)) AS NRPSubGroup, - (SELECT RoleProfile + (SELECT CompetencyAssessment FROM NRPRoles WHERE (ID = rp.NRPRoleID)) AS NRPRole, 0 AS SelfAssessmentReviewID FROM SelfAssessments AS rp @@ -1146,7 +1146,7 @@ FROM CandidateAssessmentSupervisors { return connection.Query( @"SELECT ca.ID, ca.SelfAssessmentID, sa.Name AS RoleName, sa.ReviewerCommentsLabel, COALESCE (sasr.SelfAssessmentReview, 1) AS SelfAssessmentReview, COALESCE (sasr.ResultsReview, 1) AS SupervisorResultsReview, COALESCE (sasr.RoleName, 'Supervisor') AS SupervisorRoleTitle, ca.StartedDate, - ca.LastAccessed, ca.CompleteByDate, ca.LaunchCount, ca.CompletedDate, npg.ProfessionalGroup, nsg.SubGroup, nr.RoleProfile, casv.ID AS CandidateAssessmentSupervisorVerificationId, + ca.LastAccessed, ca.CompleteByDate, ca.LaunchCount, ca.CompletedDate, npg.ProfessionalGroup, nsg.SubGroup, nr.CompetencyAssessment, casv.ID AS CandidateAssessmentSupervisorVerificationId, (SELECT COUNT(sas1.CompetencyID) AS CompetencyAssessmentQuestionCount FROM SelfAssessmentStructure AS sas1 INNER JOIN CandidateAssessments AS ca1 ON sas1.SelfAssessmentID = ca1.SelfAssessmentID INNER JOIN diff --git a/DigitalLearningSolutions.Data/DataServices/UserDataService/AdminUserDataService.cs b/DigitalLearningSolutions.Data/DataServices/UserDataService/AdminUserDataService.cs index d93094c97b..9f293ad394 100644 --- a/DigitalLearningSolutions.Data/DataServices/UserDataService/AdminUserDataService.cs +++ b/DigitalLearningSolutions.Data/DataServices/UserDataService/AdminUserDataService.cs @@ -105,6 +105,7 @@ FROM AdminAccounts AS aa aa.IsSupervisor, aa.IsTrainer, aa.CategoryID, + aa.LastAccessed, CASE WHEN aa.CategoryID IS NULL THEN 'All' ELSE cc.CategoryName @@ -369,7 +370,7 @@ public IEnumerable GetAdminAccountsByUserId(int userId) } string BaseSelectQuery = $@"SELECT aa.ID, aa.UserID, aa.CentreID, aa.Active, aa.IsCentreAdmin, aa.IsReportsViewer, aa.IsSuperAdmin, aa.IsCentreManager, - aa.IsContentManager, aa.IsContentCreator, aa.IsSupervisor, aa.IsTrainer, aa.CategoryID, aa.IsFrameworkDeveloper, aa.IsFrameworkContributor,aa.ImportOnly, + aa.LastAccessed, aa.IsContentManager, aa.IsContentCreator, aa.IsSupervisor, aa.IsTrainer, aa.CategoryID, aa.IsFrameworkDeveloper, aa.IsFrameworkContributor,aa.ImportOnly, aa.IsWorkforceManager, aa.IsWorkforceContributor, aa.IsLocalWorkforceManager, aa.IsNominatedSupervisor, u.ID, u.PrimaryEmail, u.FirstName, u.LastName, u.Active, u.FailedLoginCount, c.CentreID, c.CentreName, diff --git a/DigitalLearningSolutions.Data/DataServices/UserDataService/DelegateUserCardDataService.cs b/DigitalLearningSolutions.Data/DataServices/UserDataService/DelegateUserCardDataService.cs index 8e2a424ed5..f2068623a9 100644 --- a/DigitalLearningSolutions.Data/DataServices/UserDataService/DelegateUserCardDataService.cs +++ b/DigitalLearningSolutions.Data/DataServices/UserDataService/DelegateUserCardDataService.cs @@ -87,6 +87,7 @@ FROM DelegateAccounts AS da c.CentreName, da.CentreID, da.DateRegistered, + da.LastAccessed, da.RegistrationConfirmationHash, c.Active AS CentreActive, COALESCE(ucd.Email, u.PrimaryEmail) AS EmailAddress, @@ -124,6 +125,7 @@ FROM AdminAccounts aa c.CentreName, da.CentreID, da.DateRegistered, + da.LastAccessed, da.RegistrationConfirmationHash, c.Active AS CentreActive, COALESCE(ucd.Email, u.PrimaryEmail) AS EmailAddress, @@ -350,6 +352,8 @@ public List GetDelegateUserCardsForExportByCentreId(String sea if (sortBy == "SearchableName") orderBy = " ORDER BY LTRIM(LastName) " + sortDirection + ", LTRIM(FirstName) "; + else if(sortBy == "LastAccessed") + orderBy = " ORDER BY LastAccessed " + sortDirection; else orderBy = " ORDER BY DateRegistered " + sortDirection; diff --git a/DigitalLearningSolutions.Data/DataServices/UserDataService/UserDataService.cs b/DigitalLearningSolutions.Data/DataServices/UserDataService/UserDataService.cs index aba887ccf5..178e2f62dc 100644 --- a/DigitalLearningSolutions.Data/DataServices/UserDataService/UserDataService.cs +++ b/DigitalLearningSolutions.Data/DataServices/UserDataService/UserDataService.cs @@ -308,6 +308,7 @@ public partial class UserDataService : IUserDataService u.ProfessionalRegistrationNumber, u.ProfileImage, u.Active, + u.LastAccessed, u.ResetPasswordID, u.TermsAgreed, u.FailedLoginCount, @@ -619,6 +620,7 @@ public void UpdateUserDetailsAccount(string firstName, string lastName, string p ce.CentreName, ce.Active AS CentreActive, da.DateRegistered, + da.LastAccessed, da.CandidateNumber, da.Approved, da.SelfReg, diff --git a/DigitalLearningSolutions.Data/Enums/NavMenuTab.cs b/DigitalLearningSolutions.Data/Enums/NavMenuTab.cs index a0d60c8399..7691f565e9 100644 --- a/DigitalLearningSolutions.Data/Enums/NavMenuTab.cs +++ b/DigitalLearningSolutions.Data/Enums/NavMenuTab.cs @@ -91,9 +91,9 @@ public class NavMenuTab : Enumeration nameof(Frameworks) ); - public static readonly NavMenuTab RolesProfiles = new NavMenuTab( + public static readonly NavMenuTab CompetencyAssessments = new NavMenuTab( 17, - nameof(RolesProfiles) + nameof(CompetencyAssessments) ); public static readonly NavMenuTab LogOut = new NavMenuTab( diff --git a/DigitalLearningSolutions.Data/Helpers/GenericSortingHelper.cs b/DigitalLearningSolutions.Data/Helpers/GenericSortingHelper.cs index 7f4380d941..0165d19655 100644 --- a/DigitalLearningSolutions.Data/Helpers/GenericSortingHelper.cs +++ b/DigitalLearningSolutions.Data/Helpers/GenericSortingHelper.cs @@ -250,6 +250,9 @@ public static class DelegateSortByOptions public static readonly (string DisplayText, string PropertyName) Name = ("Name", nameof(DelegateUserCard.SearchableName)); + public static readonly (string DisplayText, string PropertyName) LastAccessed = + ("Last accessed date", nameof(DelegateUserCard.LastAccessed)); + public static readonly (string DisplayText, string PropertyName) RegistrationDate = ("Registration Date", nameof(DelegateUserCard.DateRegistered)); } diff --git a/DigitalLearningSolutions.Data/Models/RoleProfiles/RoleProfile.cs b/DigitalLearningSolutions.Data/Models/CompetencyAssessments/CompetencyAssessment.cs similarity index 59% rename from DigitalLearningSolutions.Data/Models/RoleProfiles/RoleProfile.cs rename to DigitalLearningSolutions.Data/Models/CompetencyAssessments/CompetencyAssessment.cs index ec1970fc92..c5db0ca4be 100644 --- a/DigitalLearningSolutions.Data/Models/RoleProfiles/RoleProfile.cs +++ b/DigitalLearningSolutions.Data/Models/CompetencyAssessments/CompetencyAssessment.cs @@ -1,8 +1,7 @@ -namespace DigitalLearningSolutions.Data.Models.RoleProfiles +namespace DigitalLearningSolutions.Data.Models.CompetencyAssessments { using System; - using System.ComponentModel.DataAnnotations; - public class RoleProfile : RoleProfileBase + public class CompetencyAssessment : CompetencyAssessmentBase { public DateTime CreatedDate { get; set; } public string? Brand @@ -10,15 +9,22 @@ public string? Brand get => brand; set => brand = GetValidOrNull(value); } - public string? ParentRoleProfile { get; set; } + public string? Category + { + get => category; + set => category = GetValidOrNull(value); + } + public string? ParentCompetencyAssessment { get; set; } public string? Owner { get; set; } public DateTime? Archived { get; set; } public DateTime LastEdit { get; set; } + public string? LinkedFrameworks { get; set; } public string? NRPProfessionalGroup { get; set; } public string? NRPSubGroup { get; set; } public string? NRPRole { get; set; } - public int? RoleProfileReviewID { get; set; } + public int? CompetencyAssessmentReviewID { get; set; } private string? brand; + private string? category; private static string? GetValidOrNull(string? toValidate) { return toValidate != null && toValidate.ToLower() == "undefined" ? null : toValidate; diff --git a/DigitalLearningSolutions.Data/Models/RoleProfiles/RoleProfileBase.cs b/DigitalLearningSolutions.Data/Models/CompetencyAssessments/CompetencyAssessmentBase.cs similarity index 64% rename from DigitalLearningSolutions.Data/Models/RoleProfiles/RoleProfileBase.cs rename to DigitalLearningSolutions.Data/Models/CompetencyAssessments/CompetencyAssessmentBase.cs index 1c843fae46..5fa9080ae3 100644 --- a/DigitalLearningSolutions.Data/Models/RoleProfiles/RoleProfileBase.cs +++ b/DigitalLearningSolutions.Data/Models/CompetencyAssessments/CompetencyAssessmentBase.cs @@ -1,16 +1,16 @@ -namespace DigitalLearningSolutions.Data.Models.RoleProfiles +namespace DigitalLearningSolutions.Data.Models.CompetencyAssessments { - using System; using System.ComponentModel.DataAnnotations; - public class RoleProfileBase + public class CompetencyAssessmentBase { public int ID { get; set; } [StringLength(255, MinimumLength = 3)] [Required] - public string RoleProfileName { get; set; } = string.Empty; + public string CompetencyAssessmentName { get; set; } = string.Empty; public string? Description { get; set; } public int BrandID { get; set; } - public int? ParentRoleProfileID { get; set; } + public int CategoryID { get; set; } + public int? ParentCompetencyAssessmentID { get; set; } public bool National { get; set; } public bool Public { get; set; } public int OwnerAdminID { get; set; } @@ -19,6 +19,8 @@ public class RoleProfileBase public int? NRPRoleID { get; set; } public int PublishStatusID { get; set; } public int UserRole { get; set; } + public string? Vocabulary { get; set; } } } + diff --git a/DigitalLearningSolutions.Data/Models/CompetencyAssessments/CompetencyAssessmentTaskStatus.cs b/DigitalLearningSolutions.Data/Models/CompetencyAssessments/CompetencyAssessmentTaskStatus.cs new file mode 100644 index 0000000000..654220f151 --- /dev/null +++ b/DigitalLearningSolutions.Data/Models/CompetencyAssessments/CompetencyAssessmentTaskStatus.cs @@ -0,0 +1,20 @@ +namespace DigitalLearningSolutions.Data.Models.CompetencyAssessments +{ + public class CompetencyAssessmentTaskStatus + { + public int Id { get; set; } + public bool? IntroductoryTextTaskStatus { get; set; } + public bool? BrandingTaskStatus { get; set; } + public bool? VocabularyTaskStatus { get; set; } + public bool? WorkingGroupTaskStatus { get; set; } + public bool? NationalRoleProfileTaskStatus { get; set; } + public bool? FrameworkLinksTaskStatus { get; set; } + public bool? SelectCompetenciesTaskStatus { get; set; } + public bool? OptionalCompetenciesTaskStatus { get; set; } + public bool? RoleRequirementsTaskStatus { get; set; } + public bool? SupervisorRolesTaskStatus { get; set; } + public bool? SelfAssessmentOptionsTaskStatus { get; set; } + public bool? ReviewTaskStatus { get; set; } + + } +} diff --git a/DigitalLearningSolutions.Data/Models/RoleProfiles/NRPProfessionalGroups.cs b/DigitalLearningSolutions.Data/Models/CompetencyAssessments/NRPProfessionalGroups.cs similarity index 81% rename from DigitalLearningSolutions.Data/Models/RoleProfiles/NRPProfessionalGroups.cs rename to DigitalLearningSolutions.Data/Models/CompetencyAssessments/NRPProfessionalGroups.cs index de1f9e4588..bdc4f6942a 100644 --- a/DigitalLearningSolutions.Data/Models/RoleProfiles/NRPProfessionalGroups.cs +++ b/DigitalLearningSolutions.Data/Models/CompetencyAssessments/NRPProfessionalGroups.cs @@ -1,4 +1,4 @@ -namespace DigitalLearningSolutions.Data.Models.RoleProfiles +namespace DigitalLearningSolutions.Data.Models.CompetencyAssessments { using System.ComponentModel.DataAnnotations; public class NRPProfessionalGroups @@ -10,3 +10,4 @@ public class NRPProfessionalGroups public bool Active { get; set; } } } + diff --git a/DigitalLearningSolutions.Data/Models/RoleProfiles/NRPRoles.cs b/DigitalLearningSolutions.Data/Models/CompetencyAssessments/NRPRoles.cs similarity index 67% rename from DigitalLearningSolutions.Data/Models/RoleProfiles/NRPRoles.cs rename to DigitalLearningSolutions.Data/Models/CompetencyAssessments/NRPRoles.cs index f404bfb243..22cba2ada8 100644 --- a/DigitalLearningSolutions.Data/Models/RoleProfiles/NRPRoles.cs +++ b/DigitalLearningSolutions.Data/Models/CompetencyAssessments/NRPRoles.cs @@ -1,4 +1,4 @@ -namespace DigitalLearningSolutions.Data.Models.RoleProfiles +namespace DigitalLearningSolutions.Data.Models.CompetencyAssessments { using System.ComponentModel.DataAnnotations; public class NRPRoles @@ -7,7 +7,7 @@ public class NRPRoles public int NRPSubGroupID { get; set; } [StringLength(255, MinimumLength = 3)] [Required] - public string RoleProfile { get; set; } = string.Empty; + public string ProfileName { get; set; } = string.Empty; public bool Active { get; set; } } } diff --git a/DigitalLearningSolutions.Data/Models/RoleProfiles/NRPSubGroups.cs b/DigitalLearningSolutions.Data/Models/CompetencyAssessments/NRPSubGroups.cs similarity index 71% rename from DigitalLearningSolutions.Data/Models/RoleProfiles/NRPSubGroups.cs rename to DigitalLearningSolutions.Data/Models/CompetencyAssessments/NRPSubGroups.cs index 6d43b936a2..f100a6b2e2 100644 --- a/DigitalLearningSolutions.Data/Models/RoleProfiles/NRPSubGroups.cs +++ b/DigitalLearningSolutions.Data/Models/CompetencyAssessments/NRPSubGroups.cs @@ -1,10 +1,9 @@ -namespace DigitalLearningSolutions.Data.Models.RoleProfiles +namespace DigitalLearningSolutions.Data.Models.CompetencyAssessments { using System.ComponentModel.DataAnnotations; public class NRPSubGroups { public int ID { get; set; } - public int NRPProfessionalGroupID { get; set; } [StringLength(255, MinimumLength = 3)] [Required] public string SubGroup { get; set; } = string.Empty; diff --git a/DigitalLearningSolutions.Data/Models/Frameworks/BrandedFramework.cs b/DigitalLearningSolutions.Data/Models/Frameworks/BrandedFramework.cs index f49b526831..5ba38617ac 100644 --- a/DigitalLearningSolutions.Data/Models/Frameworks/BrandedFramework.cs +++ b/DigitalLearningSolutions.Data/Models/Frameworks/BrandedFramework.cs @@ -2,6 +2,8 @@ { public class BrandedFramework : BaseFramework { + public string? Description { get; set; } + public string? Vocabulary { get; set; } public string? Brand { get => brand; diff --git a/DigitalLearningSolutions.Data/Models/Frameworks/DashboardData.cs b/DigitalLearningSolutions.Data/Models/Frameworks/DashboardData.cs index f5d28bd284..207e61079c 100644 --- a/DigitalLearningSolutions.Data/Models/Frameworks/DashboardData.cs +++ b/DigitalLearningSolutions.Data/Models/Frameworks/DashboardData.cs @@ -4,7 +4,7 @@ public class DashboardData { public int FrameworksCount { get; set; } public int MyFrameworksCount { get; set; } - public int RoleProfileCount { get; set; } - public int MyRoleProfileCount { get; set; } + public int CompetencyAssessmentCount { get; set; } + public int MyCompetencyAssessmentCount { get; set; } } } diff --git a/DigitalLearningSolutions.Data/Models/Frameworks/DashboardToDoItem.cs b/DigitalLearningSolutions.Data/Models/Frameworks/DashboardToDoItem.cs index 96ee4e8326..dc7e6b0386 100644 --- a/DigitalLearningSolutions.Data/Models/Frameworks/DashboardToDoItem.cs +++ b/DigitalLearningSolutions.Data/Models/Frameworks/DashboardToDoItem.cs @@ -4,7 +4,7 @@ public class DashboardToDoItem { public int? FrameworkID { get; set; } - public int? RoleProfileID { get; set; } + public int? CompetencyAssessmentID { get; set; } public string ItemName { get; set; } = string.Empty; public string RequestorName { get; set; } = string.Empty; public bool SignOffRequired { get; set; } diff --git a/DigitalLearningSolutions.Data/Models/SelfAssessments/Export/SelfAssessmentReportData.cs b/DigitalLearningSolutions.Data/Models/SelfAssessments/Export/SelfAssessmentReportData.cs index 27c3d31bc7..847162bf47 100644 --- a/DigitalLearningSolutions.Data/Models/SelfAssessments/Export/SelfAssessmentReportData.cs +++ b/DigitalLearningSolutions.Data/Models/SelfAssessments/Export/SelfAssessmentReportData.cs @@ -1,26 +1,41 @@ -namespace DigitalLearningSolutions.Data.Models.SelfAssessments.Export -{ - using System; - public class SelfAssessmentReportData - { - public string? SelfAssessment { get; set; } - public string? Learner { get; set; } - public bool LearnerActive { get; set; } - public string? PRN { get; set; } - public string? JobGroup { get; set; } - public string? ProgrammeCourse { get; set; } - public string? Organisation { get; set; } - public string? DepartmentTeam { get; set; } - public string? OtherCentres { get; set; } - public string? DLSRole { get; set; } - public DateTime? Registered { get; set; } - public DateTime? Started { get; set; } - public DateTime? LastAccessed { get; set; } - public int? OptionalProficienciesAssessed { get; set; } - public int? SelfAssessedAchieved { get; set; } - public int? ConfirmedResults { get; set; } - public DateTime? SignOffRequested { get; set; } - public bool SignOffAchieved { get; set; } - public DateTime? ReviewedDate { get; set; } - } -} +namespace DigitalLearningSolutions.Data.Models.SelfAssessments.Export +{ + using System; + public class SelfAssessmentReportData + { + public string? SelfAssessment { get; set; } + public string? Learner { get; set; } + public bool LearnerActive { get; set; } + public string? PRN { get; set; } + public string? JobGroup { get; set; } + public string? RegistrationAnswer1 { get; set; } + public string? RegistrationAnswer2 { get; set; } + public string? RegistrationAnswer3 { get; set; } + public string? RegistrationAnswer4 { get; set; } + public string? RegistrationAnswer5 { get; set; } + public string? RegistrationAnswer6 { get; set; } + public string? OtherCentres { get; set; } + public string? DLSRole { get; set; } + public DateTime? Registered { get; set; } + public DateTime? Started { get; set; } + public DateTime? LastAccessed { get; set; } + public int? OptionalProficienciesAssessed { get; set; } + public int? SelfAssessedAchieved { get; set; } + public int? ConfirmedResults { get; set; } + public DateTime? SignOffRequested { get; set; } + public bool SignOffAchieved { get; set; } + public DateTime? ReviewedDate { get; set; } + + // we need this for iteration across the registration answers from Delegate Accounts which match the custom fields of Centres. + public string?[] CentreRegistrationPrompts => + new[] + { + RegistrationAnswer1, + RegistrationAnswer2, + RegistrationAnswer3, + RegistrationAnswer4, + RegistrationAnswer5, + RegistrationAnswer6, + }; + } +} diff --git a/DigitalLearningSolutions.Data/Models/SessionData/CompetencyAssessments/SessionNewCompetencyAssessment.cs b/DigitalLearningSolutions.Data/Models/SessionData/CompetencyAssessments/SessionNewCompetencyAssessment.cs new file mode 100644 index 0000000000..b8d572404f --- /dev/null +++ b/DigitalLearningSolutions.Data/Models/SessionData/CompetencyAssessments/SessionNewCompetencyAssessment.cs @@ -0,0 +1,15 @@ +namespace DigitalLearningSolutions.Data.Models.SessionData.CompetencyAssessments +{ + using System; + using DigitalLearningSolutions.Data.Models.CompetencyAssessments; + public class SessionNewCompetencyAssessment + { + public SessionNewCompetencyAssessment() + { + Id = new Guid(); + CompetencyAssessmentBase = new CompetencyAssessmentBase(); + } + public Guid Id { get; set; } + public CompetencyAssessmentBase CompetencyAssessmentBase { get; set; } + } +} diff --git a/DigitalLearningSolutions.Data/Models/SessionData/RoleProfiles/SessionNewRoleProfile.cs b/DigitalLearningSolutions.Data/Models/SessionData/RoleProfiles/SessionNewRoleProfile.cs deleted file mode 100644 index 617c8ebb64..0000000000 --- a/DigitalLearningSolutions.Data/Models/SessionData/RoleProfiles/SessionNewRoleProfile.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace DigitalLearningSolutions.Data.Models.SessionData.RoleProfiles -{ - using System; - using DigitalLearningSolutions.Data.Models.RoleProfiles; - public class SessionNewRoleProfile - { - public SessionNewRoleProfile() - { - Id = new Guid(); - RoleProfileBase = new RoleProfileBase(); - } - public Guid Id { get; set; } - public RoleProfileBase RoleProfileBase { get; set; } - } -} diff --git a/DigitalLearningSolutions.Data/Models/SessionData/Supervisor/SessionEnrolOnRoleProfile.cs b/DigitalLearningSolutions.Data/Models/SessionData/Supervisor/SessionEnrolOnCompetencyAssessment.cs similarity index 84% rename from DigitalLearningSolutions.Data/Models/SessionData/Supervisor/SessionEnrolOnRoleProfile.cs rename to DigitalLearningSolutions.Data/Models/SessionData/Supervisor/SessionEnrolOnCompetencyAssessment.cs index 29b7b1b261..1fd5fee129 100644 --- a/DigitalLearningSolutions.Data/Models/SessionData/Supervisor/SessionEnrolOnRoleProfile.cs +++ b/DigitalLearningSolutions.Data/Models/SessionData/Supervisor/SessionEnrolOnCompetencyAssessment.cs @@ -1,7 +1,7 @@ namespace DigitalLearningSolutions.Data.Models.SessionData.Supervisor { using System; - public class SessionEnrolOnRoleProfile + public class SessionEnrolOnCompetencyAssessment { public int? SelfAssessmentID { get; set; } public DateTime? CompleteByDate { get; set; } diff --git a/DigitalLearningSolutions.Data/Models/SuperAdmin/SuperAdminDelegateAccount.cs b/DigitalLearningSolutions.Data/Models/SuperAdmin/SuperAdminDelegateAccount.cs index a18268f104..aac978b35a 100644 --- a/DigitalLearningSolutions.Data/Models/SuperAdmin/SuperAdminDelegateAccount.cs +++ b/DigitalLearningSolutions.Data/Models/SuperAdmin/SuperAdminDelegateAccount.cs @@ -19,6 +19,7 @@ public SuperAdminDelegateAccount(DelegateEntity delegateEntity) LearningHubAuthId = delegateEntity.UserAccount.LearningHubAuthId; RegistrationConfirmationHash = delegateEntity.DelegateAccount.RegistrationConfirmationHash; DateRegistered = delegateEntity.DelegateAccount.DateRegistered; + LastAccessed = delegateEntity.DelegateAccount.LastAccessed; SelfReg = delegateEntity.DelegateAccount.SelfReg; Active = delegateEntity.DelegateAccount.Active; EmailVerified = delegateEntity.UserAccount.EmailVerified; diff --git a/DigitalLearningSolutions.Data/Models/Supervisor/DelegateSelfAssessment.cs b/DigitalLearningSolutions.Data/Models/Supervisor/DelegateSelfAssessment.cs index 69da5a36fd..212089f305 100644 --- a/DigitalLearningSolutions.Data/Models/Supervisor/DelegateSelfAssessment.cs +++ b/DigitalLearningSolutions.Data/Models/Supervisor/DelegateSelfAssessment.cs @@ -22,7 +22,7 @@ public class DelegateSelfAssessment public string? DescriptionLabel { get; set; } public string? ReviewerCommentsLabel { get; set; } public string? SubGroup { get; set; } - public string? RoleProfile { get; set; } + public string? CompetencyAssessment { get; set; } public int SignOffRequested { get; set; } public int ResultsVerificationRequests { get; set; } public bool IsSupervisorResultsReviewed { get; set; } diff --git a/DigitalLearningSolutions.Data/Models/User/AdminAccount.cs b/DigitalLearningSolutions.Data/Models/User/AdminAccount.cs index eaff1da52f..51a109785b 100644 --- a/DigitalLearningSolutions.Data/Models/User/AdminAccount.cs +++ b/DigitalLearningSolutions.Data/Models/User/AdminAccount.cs @@ -1,5 +1,7 @@ namespace DigitalLearningSolutions.Data.Models.User { + using System; + public class AdminAccount { public int Id { get; set; } @@ -26,6 +28,7 @@ public class AdminAccount public bool IsWorkforceContributor { get; set; } public bool IsLocalWorkforceManager { get; set; } public bool IsNominatedSupervisor { get; set; } + public DateTime? LastAccessed { get; set; } public bool IsCmsAdministrator => ImportOnly && IsContentManager; public bool IsCmsManager => IsContentManager && !ImportOnly; diff --git a/DigitalLearningSolutions.Data/Models/User/AdminEntity.cs b/DigitalLearningSolutions.Data/Models/User/AdminEntity.cs index e070aca124..a9b71e5143 100644 --- a/DigitalLearningSolutions.Data/Models/User/AdminEntity.cs +++ b/DigitalLearningSolutions.Data/Models/User/AdminEntity.cs @@ -3,6 +3,7 @@ using DigitalLearningSolutions.Data.Helpers; using DigitalLearningSolutions.Data.Models.Centres; using DigitalLearningSolutions.Data.Models.SearchSortFilterPaginate; + using System; public class AdminEntity : BaseSearchableItem { @@ -72,6 +73,7 @@ public override string SearchableName public bool IsSuperAdmin => AdminAccount.IsSuperAdmin; public bool IsReportsViewer => AdminAccount.IsReportsViewer; public bool IsActive => AdminAccount.Active; + public DateTime? LastAccessed => AdminAccount.LastAccessed; } } diff --git a/DigitalLearningSolutions.Data/Models/User/DelegateAccount.cs b/DigitalLearningSolutions.Data/Models/User/DelegateAccount.cs index 3f720e350b..66d458fd13 100644 --- a/DigitalLearningSolutions.Data/Models/User/DelegateAccount.cs +++ b/DigitalLearningSolutions.Data/Models/User/DelegateAccount.cs @@ -12,6 +12,7 @@ public class DelegateAccount public bool CentreActive { get; set; } public string CandidateNumber { get; set; } = string.Empty; public DateTime DateRegistered { get; set; } + public DateTime? LastAccessed { get; set; } public string? Answer1 { get; set; } public string? Answer2 { get; set; } public string? Answer3 { get; set; } diff --git a/DigitalLearningSolutions.Data/Models/User/DelegateUser.cs b/DigitalLearningSolutions.Data/Models/User/DelegateUser.cs index 7033b8d13f..f007b355b1 100644 --- a/DigitalLearningSolutions.Data/Models/User/DelegateUser.cs +++ b/DigitalLearningSolutions.Data/Models/User/DelegateUser.cs @@ -9,6 +9,7 @@ public class DelegateUser : User public int UserId { get; set; } public string CandidateNumber { get; set; } = string.Empty; public DateTime? DateRegistered { get; set; } + public DateTime? LastAccessed { get; set; } public int JobGroupId { get; set; } public string? JobGroupName { get; set; } public string? Answer1 { get; set; } diff --git a/DigitalLearningSolutions.Data/Models/User/DelegateUserCard.cs b/DigitalLearningSolutions.Data/Models/User/DelegateUserCard.cs index ed04402308..1e9caf4e9d 100644 --- a/DigitalLearningSolutions.Data/Models/User/DelegateUserCard.cs +++ b/DigitalLearningSolutions.Data/Models/User/DelegateUserCard.cs @@ -23,6 +23,7 @@ public DelegateUserCard(DelegateEntity delegateEntity) Password = delegateEntity.UserAccount.PasswordHash; CandidateNumber = delegateEntity.DelegateAccount.CandidateNumber; DateRegistered = delegateEntity.DelegateAccount.DateRegistered; + LastAccessed = delegateEntity.DelegateAccount.LastAccessed; JobGroupId = delegateEntity.UserAccount.JobGroupId; JobGroupName = delegateEntity.UserAccount.JobGroupName; Answer1 = delegateEntity.DelegateAccount.Answer1; diff --git a/DigitalLearningSolutions.Data/Models/User/UserAccount.cs b/DigitalLearningSolutions.Data/Models/User/UserAccount.cs index 4e1c975bf1..6afca34e14 100644 --- a/DigitalLearningSolutions.Data/Models/User/UserAccount.cs +++ b/DigitalLearningSolutions.Data/Models/User/UserAccount.cs @@ -14,6 +14,7 @@ public class UserAccount public string? ProfessionalRegistrationNumber { get; set; } public byte[]? ProfileImage { get; set; } public bool Active { get; set; } + public DateTime? LastAccessed { get; set; } public int? ResetPasswordId { get; set; } public DateTime? TermsAgreed { get; set; } public int FailedLoginCount { get; set; } diff --git a/DigitalLearningSolutions.Web.Tests/Services/LoginServiceTests.cs b/DigitalLearningSolutions.Web.Tests/Services/LoginServiceTests.cs index f8dad9821e..a77c38f7b8 100644 --- a/DigitalLearningSolutions.Web.Tests/Services/LoginServiceTests.cs +++ b/DigitalLearningSolutions.Web.Tests/Services/LoginServiceTests.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; + using DigitalLearningSolutions.Data.DataServices; using DigitalLearningSolutions.Data.Enums; using DigitalLearningSolutions.Data.Helpers; using DigitalLearningSolutions.Data.Models; @@ -32,6 +33,7 @@ private static readonly (string?, List<(int centreId, string centreName, string private LoginService loginService = null!; private IUserService userService = null!; private IUserVerificationService userVerificationService = null!; + private ILoginDataService loginDataService = null!; [SetUp] public void Setup() @@ -39,7 +41,7 @@ public void Setup() userVerificationService = A.Fake(x => x.Strict()); userService = A.Fake(x => x.Strict()); - loginService = new LoginService(userService, userVerificationService); + loginService = new LoginService(userService, userVerificationService, loginDataService); } [Test] diff --git a/DigitalLearningSolutions.Web.Tests/TestHelpers/SupervisorTagTestHelper.cs b/DigitalLearningSolutions.Web.Tests/TestHelpers/SupervisorTagTestHelper.cs index e55cc5fe1a..ba437edd2d 100644 --- a/DigitalLearningSolutions.Web.Tests/TestHelpers/SupervisorTagTestHelper.cs +++ b/DigitalLearningSolutions.Web.Tests/TestHelpers/SupervisorTagTestHelper.cs @@ -101,7 +101,7 @@ public static DelegateSelfAssessment CreateDefaultDelegateSelfAssessment( string? descriptionLabel = null, string? reviewerCommentsLabel = null, string? subGroup = null, - string? roleProfile = null, + string? competencyAssessment = null, int signOffRequested =1, int resultsVerificationRequests =1, bool isSupervisorResultsReviewed =false, @@ -116,7 +116,7 @@ public static DelegateSelfAssessment CreateDefaultDelegateSelfAssessment( ResultsVerificationRequests = resultsVerificationRequests, ReviewerCommentsLabel = reviewerCommentsLabel, SubGroup = subGroup, - RoleProfile = roleProfile, + CompetencyAssessment = competencyAssessment, SignOffRequested = signOffRequested, SupervisorResultsReview = supervisorResultsReview, SupervisorSelfAssessmentReview= supervisorSelfAssessmentReview, diff --git a/DigitalLearningSolutions.Web/Controllers/CompetencyAssessmentsController/CompetencyAssessments.cs b/DigitalLearningSolutions.Web/Controllers/CompetencyAssessmentsController/CompetencyAssessments.cs new file mode 100644 index 0000000000..0d8d3ec490 --- /dev/null +++ b/DigitalLearningSolutions.Web/Controllers/CompetencyAssessmentsController/CompetencyAssessments.cs @@ -0,0 +1,485 @@ +namespace DigitalLearningSolutions.Web.Controllers.CompetencyAssessmentsController +{ + using DigitalLearningSolutions.Data.Models.CompetencyAssessments; + using DigitalLearningSolutions.Web.ViewModels.CompetencyAssessments; + using Microsoft.AspNetCore.Mvc; + using Microsoft.Extensions.Logging; + using System.Collections.Generic; + using DigitalLearningSolutions.Data.Enums; + using DigitalLearningSolutions.Web.Attributes; + using DigitalLearningSolutions.Web.Models.Enums; + using DigitalLearningSolutions.Web.Helpers; + using System.Linq; + using AspNetCoreGeneratedDocument; + using Microsoft.AspNetCore.Mvc.Rendering; + using DigitalLearningSolutions.Data.Models.Centres; + using DigitalLearningSolutions.Data.Models.Frameworks; + using Microsoft.CodeAnalysis.CSharp.Syntax; + using DigitalLearningSolutions.Data.Models.Courses; + using DigitalLearningSolutions.Web.Services; + using DigitalLearningSolutions.Web.ViewModels.TrackingSystem.Delegates.GroupCourses; + + public partial class CompetencyAssessmentsController + { + [Route("/CompetencyAssessments/View/{tabname}/{page=1:int}")] + [SetSelectedTab(nameof(NavMenuTab.CompetencyAssessments))] + public IActionResult ViewCompetencyAssessments(string tabname, string? searchString = null, + string sortBy = CompetencyAssessmentSortByOptionTexts.CompetencyAssessmentName, + string sortDirection = BaseCompetencyAssessmentsPageViewModel.AscendingText, + int page = 1 + ) + { + var adminId = GetAdminID(); + var isWorkforceManager = GetIsWorkforceManager() | GetIsFrameworkDeveloper(); + var isWorkforceContributor = GetIsWorkforceContributor() | GetIsFrameworkContributor(); + IEnumerable competencyAssessments; + if (tabname == "All") + { + competencyAssessments = competencyAssessmentService.GetAllCompetencyAssessments(adminId); + } + else + { + if (!isWorkforceContributor && !isWorkforceManager) + { + return RedirectToAction("ViewCompetencyAssessments", "CompetencyAssessments", new { tabname = "All" }); + } + competencyAssessments = competencyAssessmentService.GetCompetencyAssessmentsForAdminId(adminId); + } + if (competencyAssessments == null) + { + logger.LogWarning($"Attempt to display competency assessments for admin {adminId} returned null."); + return StatusCode(403); + } + MyCompetencyAssessmentsViewModel myCompetencyAssessments; + AllCompetencyAssessmentsViewModel allCompetencyAssessments; + if (tabname == "Mine") + { + myCompetencyAssessments = new MyCompetencyAssessmentsViewModel( + competencyAssessments, + searchString, + sortBy, + sortDirection, + page, + isWorkforceManager); + allCompetencyAssessments = new AllCompetencyAssessmentsViewModel( + new List(), + searchString, + sortBy, + sortDirection, + page + ); + } + else + { + allCompetencyAssessments = new AllCompetencyAssessmentsViewModel( + competencyAssessments, + searchString, + sortBy, + sortDirection, + page); + myCompetencyAssessments = new MyCompetencyAssessmentsViewModel( + new List(), + searchString, + sortBy, + sortDirection, + page, + isWorkforceManager + ); + } + + var currentTab = tabname == "All" ? CompetencyAssessmentsTab.AllCompetencyAssessments : CompetencyAssessmentsTab.MyCompetencyAssessments; + CompetencyAssessmentsViewModel? model = new CompetencyAssessmentsViewModel( + isWorkforceManager, + isWorkforceContributor, + allCompetencyAssessments, + myCompetencyAssessments, + currentTab + ); + return View("Index", model); + } + + [Route("/CompetencyAssessments/{actionName}/Name/{competencyAssessmentId}")] + [Route("/CompetencyAssessments/Framework/{frameworkId}/{actionName}/Name")] + [Route("/CompetencyAssessments/{actionName}/Name")] + [SetSelectedTab(nameof(NavMenuTab.CompetencyAssessments))] + public IActionResult CompetencyAssessmentName(string actionName, int competencyAssessmentId = 0, int? frameworkId = null) + { + var adminId = GetAdminID(); + var competencyAssessmentBase = new CompetencyAssessmentBase(); + if (competencyAssessmentId > 0) + { + competencyAssessmentBase = competencyAssessmentService.GetCompetencyAssessmentBaseById(competencyAssessmentId, adminId); + if (competencyAssessmentBase == null) + { + logger.LogWarning($"Failed to load name page for competencyAssessmentId: {competencyAssessmentId} adminId: {adminId}"); + return StatusCode(500); + } + if (competencyAssessmentBase.UserRole < 2) + { + return StatusCode(403); + } + } + else if (frameworkId != null) + { + var framework = frameworkService.GetBaseFrameworkByFrameworkId((int)frameworkId, adminId); + if (framework != null) + { + competencyAssessmentBase.CompetencyAssessmentName = framework.FrameworkName; + } + } + return View("Name", competencyAssessmentBase); + } + + [HttpPost] + [Route("/CompetencyAssessments/{actionName}/Name/{competencyAssessmentId}")] + [Route("/CompetencyAssessments/Framework/{frameworkId}/{actionName}/Name")] + [Route("/CompetencyAssessments/{actionName}/Name")] + [SetSelectedTab(nameof(NavMenuTab.CompetencyAssessments))] + public IActionResult SaveProfileName(CompetencyAssessmentBase competencyAssessmentBase, string actionName, int competencyAssessmentId = 0, int? frameworkId = null) + { + if (!ModelState.IsValid) + { + ModelState.Remove(nameof(CompetencyAssessmentBase.CompetencyAssessmentName)); + ModelState.AddModelError(nameof(CompetencyAssessmentBase.CompetencyAssessmentName), "Please enter a valid competency assessment name (between 3 and 255 characters)"); + return View("Name", competencyAssessmentBase); + } + else + { + var userCentreId = (int)GetCentreId(); + var adminId = GetAdminID(); + if (actionName == "New") + { + var sameItems = competencyAssessmentService.GetCompetencyAssessmentBaseByName(competencyAssessmentBase.CompetencyAssessmentName, GetAdminID()); + if (sameItems != null) + { + ModelState.Remove(nameof(CompetencyAssessmentBase.CompetencyAssessmentName)); + ModelState.AddModelError(nameof(CompetencyAssessmentBase.CompetencyAssessmentName), "Another competency assessment exists with that name. Please choose a different name."); + return View("Name", competencyAssessmentBase); + } + competencyAssessmentId = competencyAssessmentService.InsertCompetencyAssessment(adminId, userCentreId, competencyAssessmentBase.CompetencyAssessmentName, frameworkId); + } + else + { + + var isUpdated = competencyAssessmentService.UpdateCompetencyAssessmentName(competencyAssessmentBase.ID, adminId, competencyAssessmentBase.CompetencyAssessmentName); + if (!isUpdated) + { + ModelState.AddModelError(nameof(CompetencyAssessmentBase.CompetencyAssessmentName), "Another competency assessment exists with that name. Please choose a different name."); + return View("Name", competencyAssessmentBase); + } + } + return RedirectToAction("ManageCompetencyAssessment", new { competencyAssessmentId, frameworkId }); + } + } + [Route("/CompetencyAssessments/Framework/{frameworkId}/{competencyAssessmentId}/Manage")] + [Route("/CompetencyAssessments/{competencyAssessmentId}/Manage")] + public IActionResult ManageCompetencyAssessment(int competencyAssessmentId, int? frameworkId = null) + { + var adminId = GetAdminID(); + var competencyAssessmentBase = competencyAssessmentService.GetCompetencyAssessmentBaseById(competencyAssessmentId, adminId); + if (competencyAssessmentBase == null) + { + logger.LogWarning($"Failed to load name page for competencyAssessmentId: {competencyAssessmentId} adminId: {adminId}"); + return StatusCode(500); + } + if (competencyAssessmentBase.UserRole < 2) + { + return StatusCode(403); + } + var competencyAssessmentTaskStatus = competencyAssessmentService.GetCompetencyAssessmentTaskStatus(competencyAssessmentId, frameworkId); + var model = new ManageCompetencyAssessmentViewModel(competencyAssessmentBase, competencyAssessmentTaskStatus); + return View("ManageCompetencyAssessment", model); + } + + [Route("/CompetencyAssessments/{competencyAssessmentId}/NationalRoleProfileLinks/{actionName}")] + [SetSelectedTab(nameof(NavMenuTab.CompetencyAssessments))] + public IActionResult EditRoleProfileLinks(int competencyAssessmentId = 0, string actionName = "EditGroup") + { + var adminId = GetAdminID(); + CompetencyAssessmentBase? competencyAssessmentBase; + if (competencyAssessmentId > 0) + { + competencyAssessmentBase = competencyAssessmentService.GetCompetencyAssessmentBaseById(competencyAssessmentId, adminId); + if (competencyAssessmentBase == null) + { + logger.LogWarning($"Failed to load Professional Group page for competencyAssessmentId: {competencyAssessmentId} adminId: {adminId}"); + return StatusCode(500); + } + if (competencyAssessmentBase.UserRole < 2) + { + return StatusCode(403); + } + } + else + { + competencyAssessmentBase = competencyAssessmentService.GetCompetencyAssessmentBaseById(competencyAssessmentId, adminId); + } + var professionalGroups = competencyAssessmentService.GetNRPProfessionalGroups(); + var subGroups = competencyAssessmentService.GetNRPSubGroups(competencyAssessmentBase.NRPProfessionalGroupID); + var roles = competencyAssessmentService.GetNRPRoles(competencyAssessmentBase.NRPSubGroupID); + var competencyAssessmentTaskStatus = competencyAssessmentService.GetCompetencyAssessmentTaskStatus(competencyAssessmentId, null); + var model = new EditRoleProfileLinksViewModel(competencyAssessmentBase, professionalGroups, subGroups, roles, actionName, competencyAssessmentTaskStatus.NationalRoleProfileTaskStatus); + return View(model); + } + + [HttpPost] + [Route("/CompetencyAssessments/{competencyAssessmentId}/NationalRoleProfileLinks/{actionName}")] + public IActionResult EditRoleProfileLinks(EditRoleProfileLinksViewModel model, string actionName, int competencyAssessmentId = 0) + { + var adminId = GetAdminID(); + var competencyAssessmentBase = competencyAssessmentService.GetCompetencyAssessmentBaseById(competencyAssessmentId, adminId); + competencyAssessmentService.UpdateRoleProfileLinksTaskStatus(model.ID, model.TaskStatus ?? false); + if (competencyAssessmentBase == null) + { + logger.LogWarning($"Failed to submit role links page for competencyAssessmentId: {competencyAssessmentId} adminId: {adminId}"); + return StatusCode(500); + } + if (competencyAssessmentBase.UserRole < 2) + { + return StatusCode(403); + } + if (competencyAssessmentBase.NRPProfessionalGroupID != model.ProfessionalGroupId) + { + model.SubGroupId = null; + model.RoleId = null; + } + if (competencyAssessmentBase.NRPSubGroupID != model.SubGroupId) + { + model.RoleId = null; + } + var isUpdated = competencyAssessmentService.UpdateCompetencyRoleProfileLinks(model.ID, adminId, model.ProfessionalGroupId, model.SubGroupId, model.RoleId); + if (model.ActionName == "EditGroup") + { + if (model.ProfessionalGroupId == null) + { + return RedirectToAction("EditRoleProfileLinks", new { actionName = "Summary", competencyAssessmentId }); + } + else + { + return RedirectToAction("EditRoleProfileLinks", new { actionName = "EditSubGroup", competencyAssessmentId }); + } + } + else if (model.ActionName == "EditSubGroup") + { + if (model.SubGroupId == null) + { + return RedirectToAction("EditRoleProfileLinks", new { actionName = "Summary", competencyAssessmentId }); + } + else + { + return RedirectToAction("EditRoleProfileLinks", new { actionName = "EditRole", competencyAssessmentId }); + } + } + else if (model.ActionName == "EditRole") + { + return RedirectToAction("EditRoleProfileLinks", new { actionName = "Summary", competencyAssessmentId }); + } + else + { + return RedirectToAction("ManageCompetencyAssessment", new { competencyAssessmentId }); + } + } + + [Route("/CompetencyAssessments/SubGroup/{actionName}/{competencyAssessmentId}")] + [Route("/CompetencyAssessments/SubGroup/{actionName}")] + [SetSelectedTab(nameof(NavMenuTab.CompetencyAssessments))] + public IActionResult CompetencyAssessmentSubGroup(string actionName, int competencyAssessmentId = 0) + { + return View("SubGroup"); + } + + [Route("/CompetencyAssessments/{competencyAssessmentId}/Description/")] + public IActionResult EditDescription(int competencyAssessmentId) + { + var adminId = GetAdminID(); + CompetencyAssessmentBase? competencyAssessmentBase = competencyAssessmentService.GetCompetencyAssessmentBaseById(competencyAssessmentId, adminId); + if (competencyAssessmentBase == null) + { + logger.LogWarning($"Failed to load description page for competencyAssessmentId: {competencyAssessmentId} adminId: {adminId}"); + return StatusCode(500); + } + if (competencyAssessmentBase.UserRole < 2) + { + return StatusCode(403); + } + var competencyAssessmentTaskStatus = competencyAssessmentService.GetCompetencyAssessmentTaskStatus(competencyAssessmentId, null); + var model = new EditDescriptionViewModel(competencyAssessmentBase, competencyAssessmentTaskStatus.IntroductoryTextTaskStatus); + return View(model); + } + [HttpPost] + [Route("/CompetencyAssessments/{competencyAssessmentId}/Description/")] + public IActionResult SaveDescription(EditDescriptionViewModel model) + { + if (!ModelState.IsValid) + { + return View("EditDescription", model); + } + var adminId = GetAdminID(); + var isUpdated = competencyAssessmentService.UpdateCompetencyAssessmentDescription(model.ID, adminId, SanitizerHelper.SanitizeHtmlData(model.Description)); + competencyAssessmentService.UpdateIntroductoryTextTaskStatus(model.ID, model.TaskStatus ?? false); + return RedirectToAction("ManageCompetencyAssessment", new { competencyAssessmentId = model.ID }); + } + [Route("/CompetencyAssessments/{competencyAssessmentId}/Branding/")] + public IActionResult EditBranding(int competencyAssessmentId) + { + var centreId = GetCentreId(); + var adminId = GetAdminID(); + var brandsList = commonService.GetBrandListForCentre((int)centreId).Select(b => new { b.BrandID, b.BrandName }).ToList(); + var categoryList = commonService.GetCategoryListForCentre((int)centreId).Select(c => new { c.CourseCategoryID, c.CategoryName }).ToList(); + var brandSelectList = new SelectList(brandsList, "BrandID", "BrandName"); + var categorySelectList = new SelectList(categoryList, "CourseCategoryID", "CategoryName"); + var competencyAssessment = competencyAssessmentService.GetCompetencyAssessmentById(competencyAssessmentId, adminId); + var competencyAssessmentTaskStatus = competencyAssessmentService.GetCompetencyAssessmentTaskStatus(competencyAssessmentId, null); + var model = new EditBrandingViewModel(competencyAssessment, brandSelectList, categorySelectList, competencyAssessmentTaskStatus.BrandingTaskStatus); + return View(model); + } + [HttpPost] + [Route("/CompetencyAssessments/{competencyAssessmentId}/Branding/")] + public IActionResult EditBranding(EditBrandingViewModel model) + { + var adminId = GetAdminID(); + var centreId = GetCentreId(); + if (!ModelState.IsValid) + { + var brandsList = commonService.GetBrandListForCentre((int)centreId).Select(b => new { b.BrandID, b.BrandName }).ToList(); + var categoryList = commonService.GetCategoryListForCentre((int)centreId).Select(c => new { c.CourseCategoryID, c.CategoryName }).ToList(); + var brandSelectList = new SelectList(brandsList, "BrandID", "BrandName"); + var categorySelectList = new SelectList(categoryList, "CourseCategoryID", "CategoryName"); + model.BrandSelectList = brandSelectList; + model.CategorySelectList = categorySelectList; + return View("EditBranding", model); + } + if (model.BrandID == 0) + { + model.BrandID = commonService.InsertBrandAndReturnId(model.Brand, (int)centreId); + } + if (model.CategoryID == 0) + { + model.CategoryID = commonService.InsertCategoryAndReturnId(model.Category, (int)centreId); + } + var isUpdated = competencyAssessmentService.UpdateCompetencyAssessmentBranding(model.ID, adminId, model.BrandID, model.CategoryID); + competencyAssessmentService.UpdateBrandingTaskStatus(model.ID, model.TaskStatus ?? false); + return RedirectToAction("ManageCompetencyAssessment", new { competencyAssessmentId = model.ID }); + } + [Route("/CompetencyAssessments/{competencyAssessmentId}/Vocabulary/")] + public IActionResult EditVocabulary(int competencyAssessmentId) + { + var adminId = GetAdminID(); + CompetencyAssessmentBase? competencyAssessmentBase = competencyAssessmentService.GetCompetencyAssessmentBaseById(competencyAssessmentId, adminId); + if (competencyAssessmentBase == null) + { + logger.LogWarning($"Failed to load Vocabulary page for competencyAssessmentId: {competencyAssessmentId} adminId: {adminId}"); + return StatusCode(500); + } + if (competencyAssessmentBase.UserRole < 2) + { + return StatusCode(403); + } + var competencyAssessmentTaskStatus = competencyAssessmentService.GetCompetencyAssessmentTaskStatus(competencyAssessmentId, null); + var model = new EditVocabularyViewModel(competencyAssessmentBase, competencyAssessmentTaskStatus.VocabularyTaskStatus); + return View(model); + } + [HttpPost] + [Route("/CompetencyAssessments/{competencyAssessmentId}/Vocabulary/")] + public IActionResult SaveVocabulary(EditVocabularyViewModel model) + { + if (!ModelState.IsValid) + { + return View("EditVocabulary", model); + } + var adminId = GetAdminID(); + var isUpdated = competencyAssessmentService.UpdateCompetencyAssessmentVocabulary(model.ID, adminId, model.Vocabulary); + competencyAssessmentService.UpdateVocabularyTaskStatus(model.ID, model.TaskStatus ?? false); + return RedirectToAction("ManageCompetencyAssessment", new { competencyAssessmentId = model.ID }); + } + [Route("/CompetencyAssessments/{competencyAssessmentId}/Frameworks/{actionName}")] + public IActionResult SelectFrameworkSources(int competencyAssessmentId, string actionName) + { + var adminId = GetAdminID(); + var frameworks = frameworkService.GetAllFrameworks(adminId); + var competencyAssessmentBase = competencyAssessmentService.GetCompetencyAssessmentBaseById(competencyAssessmentId, adminId); + if (competencyAssessmentBase == null) + { + logger.LogWarning($"Failed to load Vocabulary page for competencyAssessmentId: {competencyAssessmentId} adminId: {adminId}"); + return StatusCode(500); + } + if (competencyAssessmentBase.UserRole < 2) + { + return StatusCode(403); + } + var primaryFrameworkId = competencyAssessmentService.GetPrimaryLinkedFrameworkId(competencyAssessmentId); + var additionalFrameworks = competencyAssessmentService.GetLinkedFrameworkIds(competencyAssessmentId); + var competencyAssessmentTaskStatus = competencyAssessmentService.GetCompetencyAssessmentTaskStatus(competencyAssessmentId, null); + var model = new SelectFrameworkSourcesViewModel(competencyAssessmentBase, frameworks, additionalFrameworks, primaryFrameworkId, competencyAssessmentTaskStatus.FrameworkLinksTaskStatus, actionName); + return View(model); + } + [HttpPost] + [Route("/CompetencyAssessments/{competencyAssessmentId}/Frameworks/{actionName}")] + public IActionResult SelectFrameworkSources(SelectFrameworkSourcesFormData model, string actionName) + { + var adminId = GetAdminID(); + var competencyAssessmentId = model.CompetencyAssessmentId; + if (!ModelState.IsValid) + { + + var frameworks = frameworkService.GetAllFrameworks(adminId); + var competencyAssessmentBase = competencyAssessmentService.GetCompetencyAssessmentBaseById(competencyAssessmentId, adminId); + if (competencyAssessmentBase == null) + { + logger.LogWarning($"Failed to load Vocabulary page for competencyAssessmentId: {competencyAssessmentId} adminId: {adminId}"); + return StatusCode(500); + } + if (competencyAssessmentBase.UserRole < 2) + { + return StatusCode(403); + } + var primaryFrameworkId = competencyAssessmentService.GetPrimaryLinkedFrameworkId(competencyAssessmentId); + var additionalFrameworks = competencyAssessmentService.GetLinkedFrameworkIds(competencyAssessmentId); + var viewModel = new SelectFrameworkSourcesViewModel(competencyAssessmentBase, frameworks, additionalFrameworks, primaryFrameworkId, model.TaskStatus, model.ActionName); + return View("SelectFrameworkSources", viewModel); + } + if (actionName == "AddFramework") + { + competencyAssessmentService.InsertSelfAssessmentFramework(adminId, competencyAssessmentId, model.FrameworkId); + return RedirectToAction("SelectFrameworkSources", new { competencyAssessmentId, actionName = "Summary" }); + } + else + { + competencyAssessmentService.UpdateFrameworkLinksTaskStatus(model.CompetencyAssessmentId, model.TaskStatus ?? false, null); + return RedirectToAction("ManageCompetencyAssessment", new { competencyAssessmentId = model.CompetencyAssessmentId }); + } + } + [Route("/CompetencyAssessments/{competencyAssessmentId}/Frameworks/{frameworkId}/Remove")] + public IActionResult RemoveFramework(int frameworkId, int competencyAssessmentId) + { + var frameworkCompetencyCount = competencyAssessmentService.GetCompetencyCountByFrameworkId(competencyAssessmentId, frameworkId); + if (frameworkCompetencyCount > 0) + { + var adminId = GetAdminID(); + var competencyAssessmentBase = competencyAssessmentService.GetCompetencyAssessmentBaseById(competencyAssessmentId, adminId); + var framework = frameworkService.GetFrameworkDetailByFrameworkId(frameworkId, adminId); + var model = new ConfirmRemoveFrameworkSourceViewModel(competencyAssessmentBase, framework, frameworkCompetencyCount); + return View("ConfirmRemoveFrameworkSource", model); + } + else + { + var adminId = GetAdminID(); + competencyAssessmentService.RemoveSelfAssessmentFramework(competencyAssessmentId, frameworkId, adminId); + } + return RedirectToAction("SelectFrameworkSources", new { competencyAssessmentId, actionName = "Summary" }); + } + [HttpPost] + [Route("/CompetencyAssessments/{competencyAssessmentId}/Frameworks/{frameworkId}/Remove")] + public IActionResult RemoveFramework(ConfirmRemoveFrameworkSourceViewModel model) + { + if (!ModelState.IsValid) + { + return View("ConfirmRemoveFrameworkSource", model); + } + var adminId = GetAdminID(); + competencyAssessmentService.RemoveFrameworkCompetenciesFromAssessment(model.CompetencyAssessmentId, model.FrameworkId); + competencyAssessmentService.RemoveSelfAssessmentFramework(model.CompetencyAssessmentId, model.FrameworkId, adminId); + return RedirectToAction("SelectFrameworkSources", new { model.CompetencyAssessmentId, actionName = "Summary" }); + } + } +} diff --git a/DigitalLearningSolutions.Web/Controllers/RoleProfilesController/RoleProfilesController.cs b/DigitalLearningSolutions.Web/Controllers/CompetencyAssessmentsController/CompetencyAssessmentsController.cs similarity index 58% rename from DigitalLearningSolutions.Web/Controllers/RoleProfilesController/RoleProfilesController.cs rename to DigitalLearningSolutions.Web/Controllers/CompetencyAssessmentsController/CompetencyAssessmentsController.cs index 9a3173289f..c057b43776 100644 --- a/DigitalLearningSolutions.Web/Controllers/RoleProfilesController/RoleProfilesController.cs +++ b/DigitalLearningSolutions.Web/Controllers/CompetencyAssessmentsController/CompetencyAssessmentsController.cs @@ -1,54 +1,67 @@ -namespace DigitalLearningSolutions.Web.Controllers.RoleProfilesController -{ - using DigitalLearningSolutions.Web.Helpers; - using DigitalLearningSolutions.Web.Services; - using Microsoft.AspNetCore.Authorization; - using Microsoft.AspNetCore.Mvc; - using Microsoft.Extensions.Configuration; - using Microsoft.Extensions.Logging; - - [Authorize(Policy = CustomPolicies.UserFrameworksAdminOnly)] - public partial class RoleProfilesController : Controller - { - private readonly IRoleProfileService roleProfileService; - private readonly ICommonService commonService; - private readonly IFrameworkNotificationService frameworkNotificationService; - private readonly ILogger logger; - private readonly IConfiguration config; - public RoleProfilesController( - IRoleProfileService roleProfileService, - ICommonService commonService, - IFrameworkNotificationService frameworkNotificationService, - ILogger logger, - IConfiguration config) - { - this.roleProfileService = roleProfileService; - this.commonService = commonService; - this.frameworkNotificationService = frameworkNotificationService; - this.logger = logger; - this.config = config; - } - public IActionResult Index() - { - return View(); - } - private int? GetCentreId() - { - return User.GetCustomClaimAsInt(CustomClaimTypes.UserCentreId); - } - private int GetAdminID() - { - return User.GetCustomClaimAsRequiredInt(CustomClaimTypes.UserAdminId); - } - private bool GetIsWorkforceManager() - { - var isWorkforceManager = User.GetCustomClaimAsBool(CustomClaimTypes.IsWorkforceManager); - return isWorkforceManager != null && (bool)isWorkforceManager; - } - private bool GetIsWorkforceContributor() - { - var isWorkforceContributor = User.GetCustomClaimAsBool(CustomClaimTypes.IsWorkforceContributor); - return isWorkforceContributor != null && (bool)isWorkforceContributor; - } - } -} +namespace DigitalLearningSolutions.Web.Controllers.CompetencyAssessmentsController +{ + using DigitalLearningSolutions.Web.Helpers; + using DigitalLearningSolutions.Web.Services; + using Microsoft.AspNetCore.Authorization; + using Microsoft.AspNetCore.Mvc; + using Microsoft.Extensions.Configuration; + using Microsoft.Extensions.Logging; + + [Authorize(Policy = CustomPolicies.UserFrameworksAdminOnly)] + public partial class CompetencyAssessmentsController : Controller + { + private readonly ICompetencyAssessmentService competencyAssessmentService; + private readonly IFrameworkService frameworkService; + private readonly ICommonService commonService; + private readonly IFrameworkNotificationService frameworkNotificationService; + private readonly ILogger logger; + private readonly IConfiguration config; + public CompetencyAssessmentsController( + ICompetencyAssessmentService competencyAssessmentService, + IFrameworkService frameworkService, + ICommonService commonService, + IFrameworkNotificationService frameworkNotificationService, + ILogger logger, + IConfiguration config) + { + this.competencyAssessmentService = competencyAssessmentService; + this.frameworkService = frameworkService; + this.commonService = commonService; + this.frameworkNotificationService = frameworkNotificationService; + this.logger = logger; + this.config = config; + } + public IActionResult Index() + { + return View(); + } + private int? GetCentreId() + { + return User.GetCustomClaimAsInt(CustomClaimTypes.UserCentreId); + } + private int GetAdminID() + { + return User.GetCustomClaimAsRequiredInt(CustomClaimTypes.UserAdminId); + } + private bool GetIsWorkforceManager() + { + var isWorkforceManager = User.GetCustomClaimAsBool(CustomClaimTypes.IsWorkforceManager); + return isWorkforceManager != null && (bool)isWorkforceManager; + } + private bool GetIsWorkforceContributor() + { + var isWorkforceContributor = User.GetCustomClaimAsBool(CustomClaimTypes.IsWorkforceContributor); + return isWorkforceContributor != null && (bool)isWorkforceContributor; + } + private bool GetIsFrameworkDeveloper() + { + var isFrameworkDeveloper = User.GetCustomClaimAsBool(CustomClaimTypes.IsFrameworkDeveloper); + return isFrameworkDeveloper != null && (bool)isFrameworkDeveloper; + } + private bool GetIsFrameworkContributor() + { + var isFrameworkContributor = User.GetCustomClaimAsBool(CustomClaimTypes.IsFrameworkContributor); + return isFrameworkContributor != null && (bool)isFrameworkContributor; + } + } +} diff --git a/DigitalLearningSolutions.Web/Controllers/FrameworksController/AssessmentQuestions.cs b/DigitalLearningSolutions.Web/Controllers/FrameworksController/AssessmentQuestions.cs index f4ffce91d1..519c8881bd 100644 --- a/DigitalLearningSolutions.Web/Controllers/FrameworksController/AssessmentQuestions.cs +++ b/DigitalLearningSolutions.Web/Controllers/FrameworksController/AssessmentQuestions.cs @@ -456,6 +456,7 @@ public IActionResult EditAssessmentQuestionOptions(AssessmentQuestionDetail asse return RedirectToAction("EditAssessmentQuestionOptions", "Frameworks", new { frameworkId, assessmentQuestionId, frameworkCompetencyId }); } assessmentQuestionDetail.ScoringInstructions = SanitizerHelper.SanitizeHtmlData(assessmentQuestionDetail.ScoringInstructions); + if (string.IsNullOrWhiteSpace(StringHelper.StripHtmlTags(assessmentQuestionDetail?.ScoringInstructions))) { assessmentQuestionDetail.ScoringInstructions = null; } SessionAssessmentQuestion sessionAssessmentQuestion = multiPageFormService .GetMultiPageFormData(MultiPageFormDataFeature.EditAssessmentQuestion, TempData) .GetAwaiter() diff --git a/DigitalLearningSolutions.Web/Controllers/FrameworksController/Competencies.cs b/DigitalLearningSolutions.Web/Controllers/FrameworksController/Competencies.cs index 6afd88f86a..9a849c4168 100644 --- a/DigitalLearningSolutions.Web/Controllers/FrameworksController/Competencies.cs +++ b/DigitalLearningSolutions.Web/Controllers/FrameworksController/Competencies.cs @@ -65,6 +65,7 @@ public IActionResult AddEditFrameworkCompetencyGroup(int frameworkId, Competency var adminId = GetAdminId(); var userRole = frameworkService.GetAdminUserRoleForFrameworkId(adminId, frameworkId); if (userRole < 2) return StatusCode(403); + if (string.IsNullOrWhiteSpace(StringHelper.StripHtmlTags(competencyGroupBase?.Description))) { competencyGroupBase.Description = null; } if (competencyGroupBase.ID > 0) { frameworkService.UpdateFrameworkCompetencyGroup(frameworkCompetencyGroupId, competencyGroupBase.CompetencyGroupID, competencyGroupBase.Name, SanitizerHelper.SanitizeHtmlData @@ -102,7 +103,7 @@ public IActionResult DeleteFrameworkCompetencyGroup(int frameworkId, int compete var adminId = GetAdminId(); - frameworkService.DeleteFrameworkCompetencyGroup(frameworkCompetencyGroupId, competencyGroupId, adminId); + frameworkService.DeleteFrameworkCompetencyGroup(frameworkCompetencyGroupId, competencyGroupId, frameworkId, adminId); return new RedirectResult(Url.Action("ViewFramework", new { tabname = "Structure", frameworkId, frameworkCompetencyGroupId })); } @@ -141,7 +142,7 @@ public IActionResult AddEditFrameworkCompetency(int frameworkId, FrameworkCompet frameworkCompetency.Description?.Trim(); var description = HttpUtility.HtmlDecode(HttpUtility.HtmlDecode(frameworkCompetency.Description)); var detailFramework = frameworkService.GetDetailFrameworkByFrameworkId(frameworkId, GetAdminId()); - if (string.IsNullOrWhiteSpace(description)) { frameworkCompetency.Description = null; } + if (string.IsNullOrWhiteSpace(StringHelper.StripHtmlTags(description))) { frameworkCompetency.Description = null; } if (!ModelState.IsValid) { ModelState.Remove(nameof(FrameworkCompetency.Name)); @@ -158,6 +159,7 @@ public IActionResult AddEditFrameworkCompetency(int frameworkId, FrameworkCompet FrameworkCompetency = frameworkCompetency, CompetencyFlags = competencyFlags }; + ModelState.Remove("SearchableName"); return View("Developer/Competency", model); } var adminId = GetAdminId(); @@ -235,7 +237,7 @@ public IActionResult DeleteFrameworkCompetency(int frameworkId, int frameworkCom { var userRole = frameworkService.GetAdminUserRoleForFrameworkId(GetAdminId(), frameworkId); if (userRole < 2) return StatusCode(403); - frameworkService.DeleteFrameworkCompetency(frameworkCompetencyId, GetAdminId()); + frameworkService.DeleteFrameworkCompetency(frameworkCompetencyId, frameworkCompetencyGroupId, frameworkId, GetAdminId()); return frameworkCompetencyGroupId != null ? new RedirectResult(Url.Action("ViewFramework", new { tabname = "Structure", frameworkId, frameworkCompetencyGroupId }) + "#fcgroup-" + frameworkCompetencyGroupId.ToString()) : new RedirectResult(Url.Action("ViewFramework", new { tabname = "Structure", frameworkId }) + "#fc-ungrouped"); } [Route("/Frameworks/{frameworkId}/Competency/{frameworkCompetencyGroupId:int=0}/{frameworkCompetencyId}/Preview/")] diff --git a/DigitalLearningSolutions.Web/Controllers/FrameworksController/Frameworks.cs b/DigitalLearningSolutions.Web/Controllers/FrameworksController/Frameworks.cs index 2cdda2862c..fc9e8eb335 100644 --- a/DigitalLearningSolutions.Web/Controllers/FrameworksController/Frameworks.cs +++ b/DigitalLearningSolutions.Web/Controllers/FrameworksController/Frameworks.cs @@ -136,18 +136,18 @@ public IActionResult StartNewFrameworkSession() MultiPageFormDataFeature.AddNewFramework, TempData ); - return RedirectToAction("CreateNewFramework", "Frameworks", new { actionname = "New" }); + return RedirectToAction("CreateNewFramework", "Frameworks", new { actionName = "New" }); } - [Route("/Frameworks/Name/{actionname}/{frameworkId}")] - [Route("/Frameworks/Name/{actionname}")] + [Route("/Frameworks/Name/{actionName}/{frameworkId}")] + [Route("/Frameworks/Name/{actionName}")] [SetSelectedTab(nameof(NavMenuTab.Frameworks))] [ResponseCache(CacheProfileName = "Never")] [TypeFilter( typeof(RedirectToErrorEmptySessionData), Arguments = new object[] { nameof(MultiPageFormDataFeature.AddNewFramework) } )] - public IActionResult CreateNewFramework(string actionname, int frameworkId = 0) + public IActionResult CreateNewFramework(string actionName, int frameworkId = 0) { var adminId = GetAdminId(); DetailFramework? detailFramework; @@ -173,15 +173,15 @@ public IActionResult CreateNewFramework(string actionname, int frameworkId = 0) return View("Developer/Name", detailFramework); } [HttpPost] - [Route("/Frameworks/Name/{actionname}/{frameworkId}")] - [Route("/Frameworks/Name/{actionname}")] + [Route("/Frameworks/Name/{actionName}/{frameworkId}")] + [Route("/Frameworks/Name/{actionName}")] [SetSelectedTab(nameof(NavMenuTab.Frameworks))] [ResponseCache(CacheProfileName = "Never")] [TypeFilter( typeof(RedirectToErrorEmptySessionData), Arguments = new object[] { nameof(MultiPageFormDataFeature.AddNewFramework) } )] - public IActionResult CreateNewFramework(DetailFramework detailFramework, string actionname, int frameworkId = 0) + public IActionResult CreateNewFramework(DetailFramework detailFramework, string actionName, int frameworkId = 0) { if (!ModelState.IsValid) { @@ -189,7 +189,7 @@ public IActionResult CreateNewFramework(DetailFramework detailFramework, string ModelState.AddModelError(nameof(BaseFramework.FrameworkName), "Please enter a valid framework name (between 3 and 255 characters)"); return View("Developer/Name", detailFramework); } - if (actionname == "New") + if (actionName == "New") { SessionNewFramework sessionNewFramework = multiPageFormService.GetMultiPageFormData(MultiPageFormDataFeature.AddNewFramework, TempData).GetAwaiter().GetResult(); sessionNewFramework.DetailFramework = detailFramework; @@ -198,7 +198,7 @@ public IActionResult CreateNewFramework(DetailFramework detailFramework, string MultiPageFormDataFeature.AddNewFramework, TempData ); - return RedirectToAction("SetNewFrameworkName", new { frameworkname = detailFramework.FrameworkName, actionname }); + return RedirectToAction("SetNewFrameworkName", new { frameworkname = detailFramework.FrameworkName, actionName }); } var adminId = GetAdminId(); var isUpdated = frameworkService.UpdateFrameworkName(detailFramework.ID, adminId, detailFramework.FrameworkName); @@ -207,10 +207,10 @@ public IActionResult CreateNewFramework(DetailFramework detailFramework, string return View("Developer/Name", detailFramework); } - [Route("/Frameworks/Similar/{actionname}")] - public IActionResult SetNewFrameworkName(string frameworkname, string actionname) + [Route("/Frameworks/Similar/{actionName}")] + public IActionResult SetNewFrameworkName(string frameworkname, string actionName) { - if (actionname == "New") + if (actionName == "New") { var sessionNewFramework = multiPageFormService.GetMultiPageFormData(MultiPageFormDataFeature.AddNewFramework, TempData).GetAwaiter().GetResult(); multiPageFormService.SetMultiPageFormData( @@ -241,14 +241,14 @@ public IActionResult SetNewFrameworkName(string frameworkname, string actionname }; return View("Developer/Similar", model); } - return RedirectToAction("SaveNewFramework", "Frameworks", new { frameworkname, actionname }); + return RedirectToAction("SaveNewFramework", "Frameworks", new { frameworkname, actionName }); } - public IActionResult SaveNewFramework(string frameworkname, string actionname) + public IActionResult SaveNewFramework(string frameworkname, string actionName) { //var framework = frameworkService.CreateFramework(frameworkname, GetAdminID()); //need to create framework and move to next step. - if (actionname != "New") + if (actionName != "New") { return StatusCode(500); } @@ -258,23 +258,23 @@ public IActionResult SaveNewFramework(string frameworkname, string actionname) MultiPageFormDataFeature.AddNewFramework, TempData ); - return RedirectToAction("FrameworkDescription", "Frameworks", new { actionname }); + return RedirectToAction("FrameworkDescription", "Frameworks", new { actionName }); } - [Route("/Frameworks/Description/{actionname}/")] - [Route("/Frameworks/Description/{actionname}/{frameworkId}/")] + [Route("/Frameworks/Description/{actionName}/")] + [Route("/Frameworks/Description/{actionName}/{frameworkId}/")] [SetSelectedTab(nameof(NavMenuTab.Frameworks))] [ResponseCache(CacheProfileName = "Never")] [TypeFilter( typeof(RedirectToErrorEmptySessionData), Arguments = new object[] { nameof(MultiPageFormDataFeature.AddNewFramework) } )] - public IActionResult FrameworkDescription(string actionname, int frameworkId = 0) + public IActionResult FrameworkDescription(string actionName, int frameworkId = 0) { var adminId = GetAdminId(); var centreId = GetCentreId(); DetailFramework? framework; - if (actionname == "New") + if (actionName == "New") { var sessionNewFramework = multiPageFormService.GetMultiPageFormData(MultiPageFormDataFeature.AddNewFramework, TempData).GetAwaiter().GetResult(); framework = sessionNewFramework.DetailFramework; @@ -298,16 +298,16 @@ public IActionResult FrameworkDescription(string actionname, int frameworkId = 0 } [HttpPost] - [Route("/Frameworks/Description/{actionname}/")] - [Route("/Frameworks/Description/{actionname}/{frameworkId}/")] + [Route("/Frameworks/Description/{actionName}/")] + [Route("/Frameworks/Description/{actionName}/{frameworkId}/")] [ResponseCache(CacheProfileName = "Never")] [TypeFilter( typeof(RedirectToErrorEmptySessionData), Arguments = new object[] { nameof(MultiPageFormDataFeature.AddNewFramework) } )] - public IActionResult FrameworkDescription(DetailFramework detailFramework, string actionname, int frameworkId = 0) + public IActionResult FrameworkDescription(DetailFramework detailFramework, string actionName, int frameworkId = 0) { - if (actionname == "New") + if (actionName == "New") { var sessionNewFramework = multiPageFormService.GetMultiPageFormData(MultiPageFormDataFeature.AddNewFramework, TempData).GetAwaiter().GetResult(); sessionNewFramework.DetailFramework = detailFramework; @@ -316,7 +316,7 @@ public IActionResult FrameworkDescription(DetailFramework detailFramework, strin MultiPageFormDataFeature.AddNewFramework, TempData ); - return RedirectToAction("FrameworkType", "Frameworks", new { actionname }); + return RedirectToAction("FrameworkType", "Frameworks", new { actionName }); } detailFramework.Description = SanitizerHelper.SanitizeHtmlData(detailFramework.Description); frameworkService.UpdateFrameworkDescription(frameworkId, GetAdminId(), detailFramework.Description); @@ -324,20 +324,20 @@ public IActionResult FrameworkDescription(DetailFramework detailFramework, strin } - [Route("/Frameworks/Type/{actionname}/")] - [Route("/Frameworks/Type/{actionname}/{frameworkId}/")] + [Route("/Frameworks/Type/{actionName}/")] + [Route("/Frameworks/Type/{actionName}/{frameworkId}/")] [SetSelectedTab(nameof(NavMenuTab.Frameworks))] [ResponseCache(CacheProfileName = "Never")] [TypeFilter( typeof(RedirectToErrorEmptySessionData), Arguments = new object[] { nameof(MultiPageFormDataFeature.AddNewFramework) } )] - public IActionResult FrameworkType(string actionname, int frameworkId = 0) + public IActionResult FrameworkType(string actionName, int frameworkId = 0) { var adminId = GetAdminId(); var centreId = GetCentreId(); DetailFramework? framework; - if (actionname == "New") + if (actionName == "New") { var sessionNewFramework = multiPageFormService.GetMultiPageFormData(MultiPageFormDataFeature.AddNewFramework, TempData).GetAwaiter().GetResult(); framework = sessionNewFramework.DetailFramework; @@ -361,16 +361,16 @@ public IActionResult FrameworkType(string actionname, int frameworkId = 0) } [HttpPost] - [Route("/Frameworks/Type/{actionname}/")] - [Route("/Frameworks/Type/{actionname}/{frameworkId}/")] + [Route("/Frameworks/Type/{actionName}/")] + [Route("/Frameworks/Type/{actionName}/{frameworkId}/")] [ResponseCache(CacheProfileName = "Never")] [TypeFilter( typeof(RedirectToErrorEmptySessionData), Arguments = new object[] { nameof(MultiPageFormDataFeature.AddNewFramework) } )] - public IActionResult FrameworkType(DetailFramework detailFramework, string actionname, int frameworkId = 0) + public IActionResult FrameworkType(DetailFramework detailFramework, string actionName, int frameworkId = 0) { - if (actionname == "New") + if (actionName == "New") { var sessionNewFramework = multiPageFormService.GetMultiPageFormData(MultiPageFormDataFeature.AddNewFramework, TempData).GetAwaiter().GetResult(); sessionNewFramework.DetailFramework = detailFramework; @@ -379,26 +379,26 @@ public IActionResult FrameworkType(DetailFramework detailFramework, string actio MultiPageFormDataFeature.AddNewFramework, TempData ); - return RedirectToAction("SetNewFrameworkBrand", "Frameworks", new { actionname }); + return RedirectToAction("SetNewFrameworkBrand", "Frameworks", new { actionName }); } frameworkService.UpdateFrameworkConfig(frameworkId, GetAdminId(), detailFramework.FrameworkConfig); return RedirectToAction("ViewFramework", new { tabname = "Details", frameworkId }); } - [Route("/Frameworks/Categorise/{actionname}/")] - [Route("/Frameworks/Categorise/{actionname}/{frameworkId}/")] + [Route("/Frameworks/Categorise/{actionName}/")] + [Route("/Frameworks/Categorise/{actionName}/{frameworkId}/")] [SetSelectedTab(nameof(NavMenuTab.Frameworks))] [ResponseCache(CacheProfileName = "Never")] [TypeFilter( typeof(RedirectToErrorEmptySessionData), Arguments = new object[] { nameof(MultiPageFormDataFeature.AddNewFramework) } )] - public IActionResult SetNewFrameworkBrand(string actionname, int frameworkId = 0) + public IActionResult SetNewFrameworkBrand(string actionName, int frameworkId = 0) { var adminId = GetAdminId(); var centreId = GetCentreId(); DetailFramework? framework; - if (actionname == "New") + if (actionName == "New") { if (TempData[MultiPageFormDataFeature.AddNewFramework.TempDataKey] == null) { @@ -443,13 +443,13 @@ public IActionResult SetNewFrameworkBrand(string actionname, int frameworkId = 0 } [HttpPost] - [Route("/Frameworks/Categorise/{actionname}/")] - [Route("/Frameworks/Categorise/{actionname}/{frameworkId}/")] - public IActionResult SetNewFrameworkBrand(DetailFramework? detailFramework, string actionname, int frameworkId = 0) + [Route("/Frameworks/Categorise/{actionName}/")] + [Route("/Frameworks/Categorise/{actionName}/{frameworkId}/")] + public IActionResult SetNewFrameworkBrand(DetailFramework? detailFramework, string actionName, int frameworkId = 0) { var adminId = GetAdminId(); var centreId = GetCentreId(); - if (actionname != "New" && frameworkId > 0) + if (actionName != "New" && frameworkId > 0) { detailFramework = InsertBrandingCategoryTopicIfRequired(detailFramework); if (detailFramework == null) return RedirectToAction("SetNewFrameworkBrand", "Frameworks", new { frameworkId }); @@ -577,30 +577,49 @@ public IActionResult RemoveFrameworkFlag(RemoveCustomFlagConfirmationViewModel m } [HttpPost] - [Route("/Frameworks/Flags/{actionname}/{frameworkId}/{flagId}")] - public IActionResult EditFrameworkFlag(CustomFlagViewModel model, int frameworkId, string actionname, int flagId) + [Route("/Frameworks/Flags/{actionName}/{frameworkId}/{flagId}")] + public IActionResult EditFrameworkFlag(CustomFlagViewModel model, int frameworkId, string actionName, int flagId) { if (ModelState.IsValid) { - if (actionname == "Edit") + var flags = frameworkService.GetCustomFlagsByFrameworkId(frameworkId, null) + .Where(fn => fn.FlagName?.Trim().ToLower() == model.FlagName?.Trim().ToLower()).ToList(); + + bool nameExists = flags.Any(x => x.FlagName?.Trim().ToLower() == model.FlagName?.Trim().ToLower()); + bool idExists = flags.Any(x => x.FlagId == flagId); + + if (actionName == "Edit") { - frameworkService.UpdateFrameworkCustomFlag(frameworkId, model.Id, model.FlagName, model.FlagGroup, model.FlagTagClass); + if (nameExists && !idExists) + { + ModelState.AddModelError(nameof(model.FlagName), "A custom flag already exists."); + return View("Developer/EditCustomFlag", model); + } + else + frameworkService.UpdateFrameworkCustomFlag(frameworkId, model.Id, model.FlagName?.Trim(), model.FlagGroup?.Trim(), model.FlagTagClass); } else { - frameworkService.AddCustomFlagToFramework(frameworkId, model.FlagName, model.FlagGroup, model.FlagTagClass); + if (nameExists) + { + ModelState.AddModelError(nameof(model.FlagName), "A custom flag already exists."); + return View("Developer/EditCustomFlag", model); + } + else + frameworkService.AddCustomFlagToFramework(frameworkId, model.FlagName?.Trim(), model.FlagGroup?.Trim(), model.FlagTagClass); } + return RedirectToAction("EditFrameworkFlags", "Frameworks", new { frameworkId }); } return View("Developer/EditCustomFlag", model); } [HttpGet] - [Route("/Frameworks/Flags/{actionname:regex(Edit|New)}/{frameworkId}/{flagId}")] - public IActionResult EditFrameworkFlag(int frameworkId, string actionname, int flagId) + [Route("/Frameworks/Flags/{actionName:regex(Edit|New)}/{frameworkId}/{flagId}")] + public IActionResult EditFrameworkFlag(int frameworkId, string actionName, int flagId) { var model = new CustomFlagViewModel(); - if (actionname == "Edit") + if (actionName == "Edit") { var flag = frameworkService.GetCustomFlagsByFrameworkId(frameworkId, (int?)flagId).FirstOrDefault(); model = new CustomFlagViewModel() @@ -614,9 +633,9 @@ public IActionResult EditFrameworkFlag(int frameworkId, string actionname, int f return View("Developer/EditCustomFlag", model); } - [Route("/Frameworks/Collaborators/{actionname}/{frameworkId}/")] + [Route("/Frameworks/Collaborators/{actionName}/{frameworkId}/")] [ResponseCache(CacheProfileName = "Never")] - public IActionResult AddCollaborators(string actionname, int frameworkId, bool error = false) + public IActionResult AddCollaborators(string actionName, int frameworkId, bool error = false) { var adminId = GetAdminId(); var collaborators = frameworkService.GetCollaboratorsForFrameworkId(frameworkId); @@ -638,15 +657,15 @@ public IActionResult AddCollaborators(string actionname, int frameworkId, bool e } [HttpPost] - [Route("/Frameworks/Collaborators/{actionname}/{frameworkId}/")] - public IActionResult AddCollaborator(string actionname, string userEmail, bool canModify, int frameworkId) + [Route("/Frameworks/Collaborators/{actionName}/{frameworkId}/")] + public IActionResult AddCollaborator(string actionName, string userEmail, bool canModify, int frameworkId) { int? centreID = GetCentreId(); var collaboratorId = frameworkService.AddCollaboratorToFramework(frameworkId, userEmail, canModify, centreID); if (collaboratorId > 0) { frameworkNotificationService.SendFrameworkCollaboratorInvite(collaboratorId, GetAdminId()); - return RedirectToAction("AddCollaborators", "Frameworks", new { frameworkId, actionname }); + return RedirectToAction("AddCollaborators", "Frameworks", new { frameworkId, actionName }); } else { @@ -671,15 +690,15 @@ public IActionResult AddCollaborator(string actionname, string userEmail, bool c { TempData["FrameworkError"] = "User not added,Kindly try again;"; } - return RedirectToAction("AddCollaborators", "Frameworks", new { frameworkId, actionname }); + return RedirectToAction("AddCollaborators", "Frameworks", new { frameworkId, actionName }); } } - public IActionResult RemoveCollaborator(int frameworkId, string actionname, int id) + public IActionResult RemoveCollaborator(int frameworkId, string actionName, int id) { frameworkService.RemoveCollaboratorFromFramework(frameworkId, id); - return RedirectToAction("AddCollaborators", "Frameworks", new { frameworkId, actionname }); + return RedirectToAction("AddCollaborators", "Frameworks", new { frameworkId, actionName }); } [Route("/Framework/{frameworkId}/{tabname}/{frameworkCompetencyGroupId}/{frameworkCompetencyId}")] @@ -752,7 +771,7 @@ public IActionResult InsertFramework() detailFramework.Description = SanitizerHelper.SanitizeHtmlData(detailFramework.Description); var newFramework = frameworkService.CreateFramework(detailFramework, adminId); TempData.Clear(); - return RedirectToAction("AddCollaborators", "Frameworks", new { actionname = "New", frameworkId = newFramework.ID }); + return RedirectToAction("AddCollaborators", "Frameworks", new { actionName = "New", frameworkId = newFramework.ID }); } } } diff --git a/DigitalLearningSolutions.Web/Controllers/FrameworksController/ImportCompetencies.cs b/DigitalLearningSolutions.Web/Controllers/FrameworksController/ImportCompetencies.cs index 9a49cffa85..e272f6da1e 100644 --- a/DigitalLearningSolutions.Web/Controllers/FrameworksController/ImportCompetencies.cs +++ b/DigitalLearningSolutions.Web/Controllers/FrameworksController/ImportCompetencies.cs @@ -246,6 +246,7 @@ public IActionResult AddQuestionsToWhichCompetencies(int AddAssessmentQuestionsO [Route("/Framework/{frameworkId}/{tabname}/Import/Summary")] public IActionResult ImportSummary() { + if (!TempData.Any()) return RedirectToAction("StatusCode", "LearningSolutions", new { code = 410 }); var data = GetBulkUploadData(); var model = new ImportSummaryViewModel(data); return View("Developer/Import/ImportSummary", model); diff --git a/DigitalLearningSolutions.Web/Controllers/FrameworksController/Review.cs b/DigitalLearningSolutions.Web/Controllers/FrameworksController/Review.cs index 16c2665150..e9a5304e65 100644 --- a/DigitalLearningSolutions.Web/Controllers/FrameworksController/Review.cs +++ b/DigitalLearningSolutions.Web/Controllers/FrameworksController/Review.cs @@ -63,6 +63,7 @@ public IActionResult LoadReview(int frameworkId, int reviewId) { var adminId = GetAdminId(); var framework = frameworkService.GetBaseFrameworkByFrameworkId(frameworkId, adminId); + if (framework.FrameworkReviewID == 0 || framework.FrameworkReviewID == null) return RedirectToAction("StatusCode", "LearningSolutions", new { code = 410 }); if (framework == null) return StatusCode(404); if (framework.UserRole < 1) return StatusCode(403); var frameworkName = framework.FrameworkName; @@ -81,6 +82,8 @@ public IActionResult LoadReview(int frameworkId, int reviewId) public IActionResult SubmitFrameworkReview(int frameworkId, int reviewId, string? comment, bool signedOff) { var adminId = GetAdminId(); + var framework = frameworkService.GetBaseFrameworkByFrameworkId(frameworkId, adminId); + if (framework.FrameworkReviewID == 0 || framework.FrameworkReviewID == null) return RedirectToAction("StatusCode", "LearningSolutions", new { code = 410 }); int? commentId = null; if (!string.IsNullOrWhiteSpace(comment)) commentId = frameworkService.InsertComment(frameworkId, adminId, comment, null); frameworkService.SubmitFrameworkReview(frameworkId, reviewId, signedOff, commentId); diff --git a/DigitalLearningSolutions.Web/Controllers/FrameworksController/Signposting.cs b/DigitalLearningSolutions.Web/Controllers/FrameworksController/Signposting.cs index 9acf3bd6c9..d994dee7a9 100644 --- a/DigitalLearningSolutions.Web/Controllers/FrameworksController/Signposting.cs +++ b/DigitalLearningSolutions.Web/Controllers/FrameworksController/Signposting.cs @@ -107,6 +107,13 @@ public IActionResult ConfirmAddCompetencyLearningResourceSummary(CompetencyResou { var frameworkCompetency = frameworkService.GetFrameworkCompetencyById(model.FrameworkCompetencyId.Value); string plainTextDescription = DisplayStringHelper.RemoveMarkup(model.Description); + var competencyLearningResource = competencyLearningResourcesService.GetActiveCompetencyLearningResourcesByCompetencyIdAndReferenceId(frameworkCompetency.CompetencyID, model.ReferenceId); + if (competencyLearningResource.Any()) + { + ModelState.Clear(); + ModelState.AddModelError("LearningResourceExists", "This learning resource is already signposted to the selected competency."); + return View("Developer/AddCompetencyLearningResourceSummary", model); + } int competencyLearningResourceId = competencyLearningResourcesService.AddCompetencyLearningResource(model.ReferenceId, model.ResourceName, plainTextDescription, model.ResourceType, model.Link, model.SelectedCatalogue, model.Rating.Value, frameworkCompetency.CompetencyID, GetAdminId()); return RedirectToAction("StartSignpostingParametersSession", "Frameworks", new { model.FrameworkId, model.FrameworkCompetencyId, model.FrameworkCompetencyGroupId, competencyLearningResourceId }); } diff --git a/DigitalLearningSolutions.Web/Controllers/LoginController.cs b/DigitalLearningSolutions.Web/Controllers/LoginController.cs index 20280e18a8..80984a593b 100644 --- a/DigitalLearningSolutions.Web/Controllers/LoginController.cs +++ b/DigitalLearningSolutions.Web/Controllers/LoginController.cs @@ -82,6 +82,14 @@ public async Task Index(LoginViewModel model, string timeZone = " var loginResult = loginService.AttemptLogin(model.Username!.Trim(), model.Password!); + if (loginResult.LoginAttemptResult == LoginAttemptResult.LogIntoSingleCentre || + loginResult.LoginAttemptResult == LoginAttemptResult.ChooseACentre || + loginResult.LoginAttemptResult == LoginAttemptResult.UnverifiedEmail) + { + loginService.UpdateLastAccessedForUsersTable(loginResult.UserEntity.UserAccount.Id); + } + + switch (loginResult.LoginAttemptResult) { case LoginAttemptResult.InvalidCredentials: @@ -219,11 +227,17 @@ int centreIdToLogInto IsPersistent = rememberMe, IssuedUtc = clockUtility.UtcNow, }; + var centreAccountSet = userEntity?.GetCentreAccountSet(centreIdToLogInto); - var adminAccount = userEntity!.GetCentreAccountSet(centreIdToLogInto)?.AdminAccount; + if (centreAccountSet?.DelegateAccount?.Id != null) + { + loginService.UpdateLastAccessedForDelegatesAccountsTable(centreAccountSet.DelegateAccount.Id); + } + var adminAccount = centreAccountSet?.AdminAccount; if (adminAccount?.Active == true) { + loginService.UpdateLastAccessedForAdminAccountsTable(adminAccount.Id); sessionService.StartAdminSession(adminAccount.Id); } diff --git a/DigitalLearningSolutions.Web/Controllers/RoleProfilesController/RoleProfiles.cs b/DigitalLearningSolutions.Web/Controllers/RoleProfilesController/RoleProfiles.cs deleted file mode 100644 index dfcae3b8ef..0000000000 --- a/DigitalLearningSolutions.Web/Controllers/RoleProfilesController/RoleProfiles.cs +++ /dev/null @@ -1,306 +0,0 @@ -namespace DigitalLearningSolutions.Web.Controllers.RoleProfilesController -{ - using DigitalLearningSolutions.Data.Models.RoleProfiles; - using DigitalLearningSolutions.Web.ViewModels.RoleProfiles; - using Microsoft.AspNetCore.Mvc; - using Microsoft.Extensions.Logging; - using DigitalLearningSolutions.Web.Extensions; - using DigitalLearningSolutions.Data.Models.SessionData.RoleProfiles; - using Microsoft.AspNetCore.Http; - using System; - using System.Collections.Generic; - using DigitalLearningSolutions.Data.Enums; - using DigitalLearningSolutions.Web.Attributes; - using DigitalLearningSolutions.Web.Models.Enums; - - public partial class RoleProfilesController - { - private const string CookieName = "DLSFrameworkService"; - [Route("/RoleProfiles/View/{tabname}/{page=1:int}")] - [SetSelectedTab(nameof(NavMenuTab.RolesProfiles))] - public IActionResult ViewRoleProfiles(string tabname, string? searchString = null, - string sortBy = RoleProfileSortByOptionTexts.RoleProfileName, - string sortDirection = BaseRoleProfilesPageViewModel.AscendingText, - int page = 1 - ) - { - var adminId = GetAdminID(); - var isWorkforceManager = GetIsWorkforceManager(); - var isWorkforceContributor = GetIsWorkforceContributor(); - IEnumerable roleProfiles; - if (tabname == "All") - { - roleProfiles = roleProfileService.GetAllRoleProfiles(adminId); - } - else - { - if (!isWorkforceContributor && !isWorkforceManager) - { - return RedirectToAction("ViewRoleProfiles", "RoleProfiles", new { tabname = "All" }); - } - roleProfiles = roleProfileService.GetRoleProfilesForAdminId(adminId); - } - if (roleProfiles == null) - { - logger.LogWarning($"Attempt to display role profiles for admin {adminId} returned null."); - return StatusCode(403); - } - MyRoleProfilesViewModel myRoleProfiles; - AllRoleProfilesViewModel allRoleProfiles; - if (tabname == "Mine") - { - myRoleProfiles = new MyRoleProfilesViewModel( - roleProfiles, - searchString, - sortBy, - sortDirection, - page, - isWorkforceManager); - allRoleProfiles = new AllRoleProfilesViewModel( - new List(), - searchString, - sortBy, - sortDirection, - page - ); - } - else - { - allRoleProfiles = new AllRoleProfilesViewModel( - roleProfiles, - searchString, - sortBy, - sortDirection, - page); - myRoleProfiles = new MyRoleProfilesViewModel( - new List(), - searchString, - sortBy, - sortDirection, - page, - isWorkforceManager - ); - } - - var currentTab = tabname == "All" ? RoleProfilesTab.AllRoleProfiles : RoleProfilesTab.MyRoleProfiles; - RoleProfilesViewModel? model = new RoleProfilesViewModel( - isWorkforceManager, - isWorkforceContributor, - allRoleProfiles, - myRoleProfiles, - currentTab - ); - return View("Index", model); - } - public IActionResult StartNewRoleProfileSession() - { - var adminId = GetAdminID(); - TempData.Clear(); - var sessionNewRoleProfile = new SessionNewRoleProfile(); - if (!Request.Cookies.ContainsKey(CookieName)) - { - var id = Guid.NewGuid(); - - Response.Cookies.Append( - CookieName, - id.ToString(), - new CookieOptions - { - Expires = DateTimeOffset.UtcNow.AddDays(30) - }); - - sessionNewRoleProfile.Id = id; - } - else - { - if (Request.Cookies.TryGetValue(CookieName, out string idString)) - { - sessionNewRoleProfile.Id = Guid.Parse(idString); - } - else - { - var id = Guid.NewGuid(); - - Response.Cookies.Append( - CookieName, - id.ToString(), - new CookieOptions - { - Expires = DateTimeOffset.UtcNow.AddDays(30) - }); - sessionNewRoleProfile.Id = id; - } - } - RoleProfileBase roleProfileBase = new RoleProfileBase() - { - BrandID = 6, - OwnerAdminID = adminId, - National = true, - Public = true, - PublishStatusID = 1, - UserRole = 3 - }; - sessionNewRoleProfile.RoleProfileBase = roleProfileBase; - TempData.Set(sessionNewRoleProfile); - return RedirectToAction("RoleProfileName", "RoleProfiles", new { actionname = "New" }); - } - - [Route("/RoleProfiles/Name/{actionname}/{roleProfileId}")] - [Route("/RoleProfiles/Name/{actionname}")] - [SetSelectedTab(nameof(NavMenuTab.RolesProfiles))] - public IActionResult RoleProfileName(string actionname, int roleProfileId = 0) - { - var adminId = GetAdminID(); - RoleProfileBase? roleProfileBase; - if (roleProfileId > 0) - { - roleProfileBase = roleProfileService.GetRoleProfileBaseById(roleProfileId, adminId); - if (roleProfileBase == null) - { - logger.LogWarning($"Failed to load name page for roleProfileId: {roleProfileId} adminId: {adminId}"); - return StatusCode(500); - } - if (roleProfileBase.UserRole < 2) - { - return StatusCode(403); - } - } - else - { - SessionNewRoleProfile sessionNewRoleProfile = TempData.Peek(); - TempData.Set(sessionNewRoleProfile); - roleProfileBase = sessionNewRoleProfile.RoleProfileBase; - TempData.Set(sessionNewRoleProfile); - } - return View("Name", roleProfileBase); - } - - [HttpPost] - [Route("/RoleProfiles/Name/{actionname}/{roleProfileId}")] - [Route("/RoleProfiles/Name/{actionname}")] - [SetSelectedTab(nameof(NavMenuTab.RolesProfiles))] - public IActionResult SaveProfileName(RoleProfileBase roleProfileBase, string actionname, int roleProfileId = 0) - { - if (!ModelState.IsValid) - { - ModelState.Remove(nameof(RoleProfileBase.RoleProfileName)); - ModelState.AddModelError(nameof(RoleProfileBase.RoleProfileName), "Please enter a valid role profile name (between 3 and 255 characters)"); - // do something - return View("Name", roleProfileBase); - } - else - { - if (actionname == "New") - { - var sameItems = roleProfileService.GetRoleProfileByName(roleProfileBase.RoleProfileName, GetAdminID()); - if (sameItems != null) - { - ModelState.Remove(nameof(RoleProfileBase.RoleProfileName)); - ModelState.AddModelError(nameof(RoleProfileBase.RoleProfileName), "Another role profile exists with that name. Please choose a different name."); - // do something - return View("Name", roleProfileBase); - } - SessionNewRoleProfile sessionNewRoleProfile = TempData.Peek(); - sessionNewRoleProfile.RoleProfileBase = roleProfileBase; - TempData.Set(sessionNewRoleProfile); - return RedirectToAction("RoleProfileProfessionalGroup", "RoleProfiles", new { actionname }); - } - else - { - var adminId = GetAdminID(); - var isUpdated = roleProfileService.UpdateRoleProfileName(roleProfileBase.ID, adminId, roleProfileBase.RoleProfileName); - if (isUpdated) - { - return RedirectToAction("ViewRoleProfile", new { tabname = "Details", roleProfileId }); - } - else - { - ModelState.AddModelError(nameof(RoleProfileBase.RoleProfileName), "Another role profile exists with that name. Please choose a different name."); - // do something - return View("Name", roleProfileBase); - } - } - - } - } - - [Route("/RoleProfiles/ProfessionalGroup/{actionname}/{roleProfileId}")] - [Route("/RoleProfiles/ProfessionalGroup/{actionname}")] - [SetSelectedTab(nameof(NavMenuTab.RolesProfiles))] - public IActionResult RoleProfileProfessionalGroup(string actionname, int roleProfileId = 0) - { - var adminId = GetAdminID(); - RoleProfileBase? roleProfileBase; - if (roleProfileId > 0) - { - roleProfileBase = roleProfileService.GetRoleProfileBaseById(roleProfileId, adminId); - if (roleProfileBase == null) - { - logger.LogWarning($"Failed to load Professional Group page for roleProfileId: {roleProfileId} adminId: {adminId}"); - return StatusCode(500); - } - if (roleProfileBase.UserRole < 2) - { - return StatusCode(403); - } - } - else - { - SessionNewRoleProfile sessionNewRoleProfile = TempData.Peek(); - TempData.Set(sessionNewRoleProfile); - roleProfileBase = sessionNewRoleProfile.RoleProfileBase; - TempData.Set(sessionNewRoleProfile); - } - var professionalGroups = roleProfileService.GetNRPProfessionalGroups(); - var model = new ProfessionalGroupViewModel() - { - NRPProfessionalGroups = professionalGroups, - RoleProfileBase = roleProfileBase - }; - return View("ProfessionalGroup", model); - } - - [HttpPost] - [Route("/RoleProfiles/ProfessionalGroup/{actionname}/{roleProfileId}")] - [Route("/RoleProfiles/ProfessionalGroup/{actionname}")] - [SetSelectedTab(nameof(NavMenuTab.RolesProfiles))] - public IActionResult SaveProfessionalGroup(RoleProfileBase roleProfileBase, string actionname, int roleProfileId = 0) - { - if (roleProfileBase.NRPProfessionalGroupID == null) - { - ModelState.Remove(nameof(RoleProfileBase.NRPProfessionalGroupID)); - ModelState.AddModelError(nameof(RoleProfileBase.NRPProfessionalGroupID), "Please choose a professional group" + (roleProfileId == 0 ? "or Skip this step" : "") + "."); - // do something - return View("Name", roleProfileBase); - } - if (actionname == "New") - { - SessionNewRoleProfile sessionNewRoleProfile = TempData.Peek(); - sessionNewRoleProfile.RoleProfileBase = roleProfileBase; - TempData.Set(sessionNewRoleProfile); - return RedirectToAction("RoleProfileSubGroup", "RoleProfiles", new { actionname }); - } - else - { - var adminId = GetAdminID(); - var isUpdated = roleProfileService.UpdateRoleProfileProfessionalGroup(roleProfileBase.ID, adminId, roleProfileBase.NRPProfessionalGroupID); - if (isUpdated) - { - return RedirectToAction("RoleProfileSubGroup", "RoleProfiles", new { actionname, roleProfileId }); - } - else - { - return RedirectToAction("ViewRoleProfile", new { tabname = "Details", roleProfileId }); - } - } - } - - [Route("/RoleProfiles/SubGroup/{actionname}/{roleProfileId}")] - [Route("/RoleProfiles/SubGroup/{actionname}")] - [SetSelectedTab(nameof(NavMenuTab.RolesProfiles))] - public IActionResult RoleProfileSubGroup(string actionname, int roleProfileId = 0) - { - return View("SubGroup"); - } - } -} diff --git a/DigitalLearningSolutions.Web/Controllers/SupervisorController/Supervisor.cs b/DigitalLearningSolutions.Web/Controllers/SupervisorController/Supervisor.cs index 3d22fb71fb..21b555391c 100644 --- a/DigitalLearningSolutions.Web/Controllers/SupervisorController/Supervisor.cs +++ b/DigitalLearningSolutions.Web/Controllers/SupervisorController/Supervisor.cs @@ -699,9 +699,9 @@ public IActionResult StartEnrolDelegateOnProfileAssessment(int supervisorDelegat { TempData.Clear(); - var sessionEnrolOnRoleProfile = new SessionEnrolOnRoleProfile(); + var sessionEnrolOnCompetencyAssessment = new SessionEnrolOnCompetencyAssessment(); multiPageFormService.SetMultiPageFormData( - sessionEnrolOnRoleProfile, + sessionEnrolOnCompetencyAssessment, MultiPageFormDataFeature.EnrolDelegateOnProfileAssessment, TempData ); @@ -719,12 +719,12 @@ public IActionResult StartEnrolDelegateOnProfileAssessment(int supervisorDelegat )] public IActionResult EnrolDelegateOnProfileAssessment(int supervisorDelegateId) { - var sessionEnrolOnRoleProfile = multiPageFormService.GetMultiPageFormData( + var sessionEnrolOnCompetencyAssessment = multiPageFormService.GetMultiPageFormData( MultiPageFormDataFeature.EnrolDelegateOnProfileAssessment, TempData ).GetAwaiter().GetResult(); multiPageFormService.SetMultiPageFormData( - sessionEnrolOnRoleProfile, + sessionEnrolOnCompetencyAssessment, MultiPageFormDataFeature.EnrolDelegateOnProfileAssessment, TempData ); @@ -732,25 +732,25 @@ public IActionResult EnrolDelegateOnProfileAssessment(int supervisorDelegateId) var supervisorDelegate = supervisorService.GetSupervisorDelegateDetailsById(supervisorDelegateId, GetAdminId(), 0); - var roleProfiles = supervisorService.GetAvailableRoleProfilesForDelegate( + var competencyAssessments = supervisorService.GetAvailableCompetencyAssessmentsForDelegate( (int)supervisorDelegate.DelegateUserID, GetCentreId(), loggedInAdmin.CategoryId ); var model = new EnrolDelegateOnProfileAssessmentViewModel() { - SessionEnrolOnRoleProfile = sessionEnrolOnRoleProfile, + SessionEnrolOnCompetencyAssessment = sessionEnrolOnCompetencyAssessment, SupervisorDelegateDetail = supervisorDelegate, - RoleProfiles = roleProfiles + CompetencyAssessments = competencyAssessments }; return View("EnrolDelegateOnProfileAssessment", model); } [HttpPost] [Route("/Supervisor/Staff/{supervisorDelegateId}/ProfileAssessment/Enrol/Profile")] - public IActionResult EnrolSetRoleProfile(int supervisorDelegateId, int selfAssessmentID) + public IActionResult EnrolSetCompetencyAssessment(int supervisorDelegateId, int selfAssessmentID) { - var sessionEnrolOnRoleProfile = multiPageFormService.GetMultiPageFormData( + var sessionEnrolOnCompetencyAssessment = multiPageFormService.GetMultiPageFormData( MultiPageFormDataFeature.EnrolDelegateOnProfileAssessment, TempData ).GetAwaiter().GetResult(); @@ -761,29 +761,29 @@ public IActionResult EnrolSetRoleProfile(int supervisorDelegateId, int selfAsses { ModelState.AddModelError("selfAssessmentId", "You must select a self assessment"); multiPageFormService.SetMultiPageFormData( - sessionEnrolOnRoleProfile, + sessionEnrolOnCompetencyAssessment, MultiPageFormDataFeature.EnrolDelegateOnProfileAssessment, TempData ); var supervisorDelegate = supervisorService.GetSupervisorDelegateDetailsById(supervisorDelegateId, GetAdminId(), 0); - var roleProfiles = supervisorService.GetAvailableRoleProfilesForDelegate( + var competencyAssessments = supervisorService.GetAvailableCompetencyAssessmentsForDelegate( (int)supervisorDelegate.DelegateUserID, GetCentreId(), loggedInAdmin.CategoryId ); var model = new EnrolDelegateOnProfileAssessmentViewModel() { - SessionEnrolOnRoleProfile = sessionEnrolOnRoleProfile, + SessionEnrolOnCompetencyAssessment = sessionEnrolOnCompetencyAssessment, SupervisorDelegateDetail = supervisorDelegate, - RoleProfiles = roleProfiles + CompetencyAssessments = competencyAssessments }; return View("EnrolDelegateOnProfileAssessment", model); } - sessionEnrolOnRoleProfile.SelfAssessmentID = selfAssessmentID; + sessionEnrolOnCompetencyAssessment.SelfAssessmentID = selfAssessmentID; multiPageFormService.SetMultiPageFormData( - sessionEnrolOnRoleProfile, + sessionEnrolOnCompetencyAssessment, MultiPageFormDataFeature.EnrolDelegateOnProfileAssessment, TempData ); @@ -802,23 +802,23 @@ public IActionResult EnrolSetRoleProfile(int supervisorDelegateId, int selfAsses )] public IActionResult EnrolDelegateCompleteBy(int supervisorDelegateId, int? day, int? month, int? year) { - var sessionEnrolOnRoleProfile = multiPageFormService.GetMultiPageFormData( + var sessionEnrolOnCompetencyAssessment = multiPageFormService.GetMultiPageFormData( MultiPageFormDataFeature.EnrolDelegateOnProfileAssessment, TempData ).GetAwaiter().GetResult(); multiPageFormService.SetMultiPageFormData( - sessionEnrolOnRoleProfile, + sessionEnrolOnCompetencyAssessment, MultiPageFormDataFeature.EnrolDelegateOnProfileAssessment, TempData ); var supervisorDelegate = supervisorService.GetSupervisorDelegateDetailsById(supervisorDelegateId, GetAdminId(), 0); - var roleProfile = supervisorService.GetRoleProfileById((int)sessionEnrolOnRoleProfile.SelfAssessmentID); + var competencyAssessment = supervisorService.GetCompetencyAssessmentById((int)sessionEnrolOnCompetencyAssessment.SelfAssessmentID); var model = new EnrolDelegateSetCompletByDateViewModel() { SupervisorDelegateDetail = supervisorDelegate, - RoleProfile = roleProfile, - CompleteByDate = sessionEnrolOnRoleProfile.CompleteByDate + CompetencyAssessment = competencyAssessment, + CompleteByDate = sessionEnrolOnCompetencyAssessment.CompleteByDate }; if (day != null && month != null && year != null) { @@ -835,7 +835,7 @@ public IActionResult EnrolDelegateSetCompleteBy(int supervisorDelegateId, int da TempData["completeByDate"] = day; TempData["completeByMonth"] = month; TempData["completeByYear"] = year; - var sessionEnrolOnRoleProfile = multiPageFormService.GetMultiPageFormData(MultiPageFormDataFeature.EnrolDelegateOnProfileAssessment, TempData).GetAwaiter().GetResult(); + var sessionEnrolOnCompetencyAssessment = multiPageFormService.GetMultiPageFormData(MultiPageFormDataFeature.EnrolDelegateOnProfileAssessment, TempData).GetAwaiter().GetResult(); if (day != 0 | month != 0 | year != 0) { var validationResult = OldDateValidator.ValidateDate(day, month, year); @@ -846,9 +846,9 @@ public IActionResult EnrolDelegateSetCompleteBy(int supervisorDelegateId, int da else { var completeByDate = new DateTime(year, month, day); - sessionEnrolOnRoleProfile.CompleteByDate = completeByDate; + sessionEnrolOnCompetencyAssessment.CompleteByDate = completeByDate; multiPageFormService.SetMultiPageFormData( - sessionEnrolOnRoleProfile, + sessionEnrolOnCompetencyAssessment, MultiPageFormDataFeature.EnrolDelegateOnProfileAssessment, TempData ); @@ -856,7 +856,7 @@ public IActionResult EnrolDelegateSetCompleteBy(int supervisorDelegateId, int da } var supervisorRoles = - supervisorService.GetSupervisorRolesBySelfAssessmentIdForSupervisor(sessionEnrolOnRoleProfile.SelfAssessmentID.Value); + supervisorService.GetSupervisorRolesBySelfAssessmentIdForSupervisor(sessionEnrolOnCompetencyAssessment.SelfAssessmentID.Value); if (supervisorRoles.Count() > 1) { TempData["navigatedFrom"] = "EnrolDelegateSupervisorRole"; @@ -868,9 +868,9 @@ public IActionResult EnrolDelegateSetCompleteBy(int supervisorDelegateId, int da } else if (supervisorRoles.Count() == 1) { - sessionEnrolOnRoleProfile.SelfAssessmentSupervisorRoleId = supervisorRoles.First().ID; + sessionEnrolOnCompetencyAssessment.SelfAssessmentSupervisorRoleId = supervisorRoles.First().ID; multiPageFormService.SetMultiPageFormData( - sessionEnrolOnRoleProfile, + sessionEnrolOnCompetencyAssessment, MultiPageFormDataFeature.EnrolDelegateOnProfileAssessment, TempData ); @@ -891,21 +891,21 @@ public IActionResult EnrolDelegateSetCompleteBy(int supervisorDelegateId, int da )] public IActionResult EnrolDelegateSupervisorRole(int supervisorDelegateId) { - var sessionEnrolOnRoleProfile = multiPageFormService.GetMultiPageFormData(MultiPageFormDataFeature.EnrolDelegateOnProfileAssessment, TempData).GetAwaiter().GetResult(); + var sessionEnrolOnCompetencyAssessment = multiPageFormService.GetMultiPageFormData(MultiPageFormDataFeature.EnrolDelegateOnProfileAssessment, TempData).GetAwaiter().GetResult(); multiPageFormService.SetMultiPageFormData( - sessionEnrolOnRoleProfile, + sessionEnrolOnCompetencyAssessment, MultiPageFormDataFeature.EnrolDelegateOnProfileAssessment, TempData ); var supervisorDelegate = supervisorService.GetSupervisorDelegateDetailsById(supervisorDelegateId, GetAdminId(), 0); - var roleProfile = supervisorService.GetRoleProfileById((int)sessionEnrolOnRoleProfile.SelfAssessmentID); - var supervisorRoles = supervisorService.GetSupervisorRolesForSelfAssessment(sessionEnrolOnRoleProfile.SelfAssessmentID.Value); + var competencyAssessment = supervisorService.GetCompetencyAssessmentById((int)sessionEnrolOnCompetencyAssessment.SelfAssessmentID); + var supervisorRoles = supervisorService.GetSupervisorRolesForSelfAssessment(sessionEnrolOnCompetencyAssessment.SelfAssessmentID.Value); var model = new EnrolDelegateSupervisorRoleViewModel() { SupervisorDelegateDetail = supervisorDelegate, - RoleProfile = roleProfile, - SelfAssessmentSupervisorRoleId = sessionEnrolOnRoleProfile.SelfAssessmentSupervisorRoleId, + CompetencyAssessment = competencyAssessment, + SelfAssessmentSupervisorRoleId = sessionEnrolOnCompetencyAssessment.SelfAssessmentSupervisorRoleId, SelfAssessmentSupervisorRoles = supervisorRoles }; ViewBag.completeByDate = TempData["completeByDate"]; @@ -922,24 +922,24 @@ public IActionResult EnrolDelegateSetSupervisorRole( int selfAssessmentSupervisorRoleId ) { - var sessionEnrolOnRoleProfile = multiPageFormService.GetMultiPageFormData(MultiPageFormDataFeature.EnrolDelegateOnProfileAssessment, TempData).GetAwaiter().GetResult(); + var sessionEnrolOnCompetencyAssessment = multiPageFormService.GetMultiPageFormData(MultiPageFormDataFeature.EnrolDelegateOnProfileAssessment, TempData).GetAwaiter().GetResult(); if (!ModelState.IsValid) { ModelState.ClearErrorsForAllFieldsExcept("SelfAssessmentSupervisorRoleId"); var supervisorDelegate = supervisorService.GetSupervisorDelegateDetailsById(supervisorDelegateId, GetAdminId(), 0); - var roleProfile = supervisorService.GetRoleProfileById((int)sessionEnrolOnRoleProfile.SelfAssessmentID); + var competencyAssessment = supervisorService.GetCompetencyAssessmentById((int)sessionEnrolOnCompetencyAssessment.SelfAssessmentID); var supervisorRoles = - supervisorService.GetSupervisorRolesForSelfAssessment(sessionEnrolOnRoleProfile.SelfAssessmentID.Value); + supervisorService.GetSupervisorRolesForSelfAssessment(sessionEnrolOnCompetencyAssessment.SelfAssessmentID.Value); model.SupervisorDelegateDetail = supervisorDelegate; - model.RoleProfile = roleProfile; + model.CompetencyAssessment = competencyAssessment; model.SelfAssessmentSupervisorRoles = supervisorRoles; return View("EnrolDelegateSupervisorRole", model); } - sessionEnrolOnRoleProfile.SelfAssessmentSupervisorRoleId = selfAssessmentSupervisorRoleId; + sessionEnrolOnCompetencyAssessment.SelfAssessmentSupervisorRoleId = selfAssessmentSupervisorRoleId; multiPageFormService.SetMultiPageFormData( - sessionEnrolOnRoleProfile, + sessionEnrolOnCompetencyAssessment, MultiPageFormDataFeature.EnrolDelegateOnProfileAssessment, TempData ); @@ -958,32 +958,32 @@ int selfAssessmentSupervisorRoleId )] public IActionResult EnrolDelegateSummary(int supervisorDelegateId) { - var sessionEnrolOnRoleProfile = multiPageFormService.GetMultiPageFormData(MultiPageFormDataFeature.EnrolDelegateOnProfileAssessment, TempData).GetAwaiter().GetResult(); + var sessionEnrolOnCompetencyAssessment = multiPageFormService.GetMultiPageFormData(MultiPageFormDataFeature.EnrolDelegateOnProfileAssessment, TempData).GetAwaiter().GetResult(); multiPageFormService.SetMultiPageFormData( - sessionEnrolOnRoleProfile, + sessionEnrolOnCompetencyAssessment, MultiPageFormDataFeature.EnrolDelegateOnProfileAssessment, TempData ); var supervisorDelegate = supervisorService.GetSupervisorDelegateDetailsById(supervisorDelegateId, GetAdminId(), 0); - var roleProfile = supervisorService.GetRoleProfileById((int)sessionEnrolOnRoleProfile.SelfAssessmentID); - var supervisorRoleName = (sessionEnrolOnRoleProfile.SelfAssessmentSupervisorRoleId == null + var competencyAssessment = supervisorService.GetCompetencyAssessmentById((int)sessionEnrolOnCompetencyAssessment.SelfAssessmentID); + var supervisorRoleName = (sessionEnrolOnCompetencyAssessment.SelfAssessmentSupervisorRoleId == null ? "Supervisor" : supervisorService - .GetSupervisorRoleById(sessionEnrolOnRoleProfile.SelfAssessmentSupervisorRoleId.Value).RoleName); - var supervisorRoleCount = (sessionEnrolOnRoleProfile.SelfAssessmentSupervisorRoleId == null + .GetSupervisorRoleById(sessionEnrolOnCompetencyAssessment.SelfAssessmentSupervisorRoleId.Value).RoleName); + var supervisorRoleCount = (sessionEnrolOnCompetencyAssessment.SelfAssessmentSupervisorRoleId == null ? 0 : supervisorService - .GetSupervisorRolesForSelfAssessment(sessionEnrolOnRoleProfile.SelfAssessmentID.Value).Count()); - var allowSupervisorRoleSelection = (sessionEnrolOnRoleProfile.SelfAssessmentSupervisorRoleId == null + .GetSupervisorRolesForSelfAssessment(sessionEnrolOnCompetencyAssessment.SelfAssessmentID.Value).Count()); + var allowSupervisorRoleSelection = (sessionEnrolOnCompetencyAssessment.SelfAssessmentSupervisorRoleId == null ? false : supervisorService - .GetSupervisorRolesForSelfAssessment(sessionEnrolOnRoleProfile.SelfAssessmentID.Value).FirstOrDefault().AllowSupervisorRoleSelection); + .GetSupervisorRolesForSelfAssessment(sessionEnrolOnCompetencyAssessment.SelfAssessmentID.Value).FirstOrDefault().AllowSupervisorRoleSelection); var model = new EnrolDelegateSummaryViewModel() { SupervisorDelegateDetail = supervisorDelegate, - RoleProfile = roleProfile, + CompetencyAssessment = competencyAssessment, SupervisorRoleName = supervisorRoleName, - CompleteByDate = sessionEnrolOnRoleProfile.CompleteByDate, + CompleteByDate = sessionEnrolOnCompetencyAssessment.CompleteByDate, SupervisorRoleCount = supervisorRoleCount, AllowSupervisorRoleSelection = allowSupervisorRoleSelection }; @@ -996,10 +996,10 @@ public IActionResult EnrolDelegateSummary(int supervisorDelegateId) public IActionResult EnrolDelegateConfirm(int delegateUserId, int supervisorDelegateId) { - var sessionEnrolOnRoleProfile = multiPageFormService.GetMultiPageFormData(MultiPageFormDataFeature.EnrolDelegateOnProfileAssessment, TempData).GetAwaiter().GetResult(); - var selfAssessmentId = sessionEnrolOnRoleProfile.SelfAssessmentID; - var completeByDate = sessionEnrolOnRoleProfile.CompleteByDate; - var selfAssessmentSupervisorRoleId = sessionEnrolOnRoleProfile.SelfAssessmentSupervisorRoleId; + var sessionEnrolOnCompetencyAssessment = multiPageFormService.GetMultiPageFormData(MultiPageFormDataFeature.EnrolDelegateOnProfileAssessment, TempData).GetAwaiter().GetResult(); + var selfAssessmentId = sessionEnrolOnCompetencyAssessment.SelfAssessmentID; + var completeByDate = sessionEnrolOnCompetencyAssessment.CompleteByDate; + var selfAssessmentSupervisorRoleId = sessionEnrolOnCompetencyAssessment.SelfAssessmentSupervisorRoleId; var loggedInUserId = User.GetUserId(); var candidateAssessmentId = supervisorService.EnrolDelegateOnAssessment( delegateUserId, @@ -1031,7 +1031,7 @@ public IActionResult QuickAddSupervisor(int selfAssessmentId, int supervisorDele { var supervisorDelegate = supervisorService.GetSupervisorDelegateDetailsById(supervisorDelegateId, GetAdminId(), 0); - var roleProfile = supervisorService.GetRoleProfileById(selfAssessmentId); + var competencyAssessment = supervisorService.GetCompetencyAssessmentById(selfAssessmentId); var supervisorRoles = supervisorService.GetSupervisorRolesBySelfAssessmentIdForSupervisor(selfAssessmentId); if (supervisorRoles.Any() && supervisorRoles.Count() > 1) @@ -1039,7 +1039,7 @@ public IActionResult QuickAddSupervisor(int selfAssessmentId, int supervisorDele var model = new EnrolDelegateSupervisorRoleViewModel() { SupervisorDelegateDetail = supervisorDelegate, - RoleProfile = roleProfile, + CompetencyAssessment = competencyAssessment, SelfAssessmentSupervisorRoleId = null, SelfAssessmentSupervisorRoles = supervisorRoles }; @@ -1059,25 +1059,25 @@ public IActionResult QuickAddSupervisor(int selfAssessmentId, int supervisorDele } } - var sessionEnrolOnRoleProfile = new SessionEnrolOnRoleProfile() + var sessionEnrolOnCompetencyAssessment = new SessionEnrolOnCompetencyAssessment() { SelfAssessmentID = supervisorRoles.FirstOrDefault() != null ? supervisorRoles.FirstOrDefault().SelfAssessmentID : selfAssessmentId, SelfAssessmentSupervisorRoleId = supervisorRoles.FirstOrDefault() != null ? supervisorRoles.FirstOrDefault().ID : 0 }; multiPageFormService.SetMultiPageFormData( - sessionEnrolOnRoleProfile, + sessionEnrolOnCompetencyAssessment, MultiPageFormDataFeature.EnrolDelegateOnProfileAssessment, TempData ); var supervisorRoleName = supervisorRoles.FirstOrDefault() != null ? supervisorRoles.FirstOrDefault().RoleName : ""; var model = new EnrolDelegateSummaryViewModel { - RoleProfile = roleProfile, + CompetencyAssessment = competencyAssessment, SupervisorDelegateDetail = supervisorDelegate, SupervisorRoleName = supervisorRoleName }; - return View("SelectDelegateSupervisorRoleSummary", new Tuple(model, sessionEnrolOnRoleProfile.SelfAssessmentSupervisorRoleId)); + return View("SelectDelegateSupervisorRoleSummary", new Tuple(model, sessionEnrolOnCompetencyAssessment.SelfAssessmentSupervisorRoleId)); } @@ -1087,7 +1087,7 @@ public IActionResult QuickAddSupervisor(int selfAssessmentId, int supervisorDele [HttpPost] public IActionResult QuickAddSupervisor(EnrolDelegateSupervisorRoleViewModel supervisorRole, int selfAssessmentId, int supervisorDelegateId, int delegateUserId) { - var roleProfile = supervisorService.GetRoleProfileById(selfAssessmentId); + var competencyAssessment = supervisorService.GetCompetencyAssessmentById(selfAssessmentId); var supervisorDelegate = supervisorService.GetSupervisorDelegateDetailsById(supervisorDelegateId, GetAdminId(), 0); if (supervisorRole.SelfAssessmentSupervisorRoleId == null) @@ -1096,7 +1096,7 @@ public IActionResult QuickAddSupervisor(EnrolDelegateSupervisorRoleViewModel sup var model = new EnrolDelegateSupervisorRoleViewModel() { SupervisorDelegateDetail = supervisorDelegate, - RoleProfile = roleProfile, + CompetencyAssessment = competencyAssessment, SelfAssessmentSupervisorRoleId = null, SelfAssessmentSupervisorRoles = supervisorRoles }; @@ -1107,7 +1107,7 @@ public IActionResult QuickAddSupervisor(EnrolDelegateSupervisorRoleViewModel sup var model = new EnrolDelegateSummaryViewModel { - RoleProfile = roleProfile, + CompetencyAssessment = competencyAssessment, SupervisorDelegateDetail = supervisorDelegate, SupervisorRoleName = supervisorRole.SelfAssessmentSupervisorRoleId == null ? "Supervisor" : supervisorService.GetSupervisorRoleById((int)supervisorRole.SelfAssessmentSupervisorRoleId).RoleName, @@ -1126,12 +1126,12 @@ public IActionResult QuickAddSupervisorConfirm(int? selfAssessmentSupervisorRole var supervisorDelegate = supervisorService.GetSupervisorDelegateDetailsById(supervisorDelegateId, GetAdminId(), 0); if (!selfAssessmentSupervisorRoleId.HasValue) { - var roleProfile = supervisorService.GetRoleProfileById(selfAssessmentId); + var competencyAssessment = supervisorService.GetCompetencyAssessmentById(selfAssessmentId); var supervisorRoles = supervisorService.GetSupervisorRolesForSelfAssessment(selfAssessmentId); var model = new EnrolDelegateSupervisorRoleViewModel() { SupervisorDelegateDetail = supervisorDelegate, - RoleProfile = roleProfile, + CompetencyAssessment = competencyAssessment, SelfAssessmentSupervisorRoleId = null, SelfAssessmentSupervisorRoles = supervisorRoles }; diff --git a/DigitalLearningSolutions.Web/Helpers/DisplayStringHelper.cs b/DigitalLearningSolutions.Web/Helpers/DisplayStringHelper.cs index 5014a2d93c..9f6e6a571b 100644 --- a/DigitalLearningSolutions.Web/Helpers/DisplayStringHelper.cs +++ b/DigitalLearningSolutions.Web/Helpers/DisplayStringHelper.cs @@ -71,6 +71,21 @@ public static string GetPluralitySuffix(int number) { return number == 1 ? string.Empty : "s"; } + public static string PluraliseStringIfRequired(string input, int number) + { + if (number == 1) + { + return input; + } + else if (input.EndsWith("y")) + { + return input.Substring(0, input.Length - 1) + "ies"; + } + else + { + return input + "s"; + } + } public static string? ReplaceNonAlphaNumericSpaceChars(string? input, string replacement) { diff --git a/DigitalLearningSolutions.Web/Helpers/SearchHelper.cs b/DigitalLearningSolutions.Web/Helpers/SearchHelper.cs index 381be134dd..9b3dc5acf8 100644 --- a/DigitalLearningSolutions.Web/Helpers/SearchHelper.cs +++ b/DigitalLearningSolutions.Web/Helpers/SearchHelper.cs @@ -6,7 +6,7 @@ using System.Linq; using System.Text; using DigitalLearningSolutions.Data.Helpers; - using DigitalLearningSolutions.Data.Models.RoleProfiles; + using DigitalLearningSolutions.Data.Models.CompetencyAssessments; using FuzzySharp; using FuzzySharp.SimilarityRatio; using FuzzySharp.SimilarityRatio.Scorer.StrategySensitive; @@ -29,8 +29,8 @@ public static class SearchHelper "profile", "job", "role", }; - public static IEnumerable FilterRoleProfiles( - IEnumerable roleProfiles, + public static IEnumerable FilterCompetencyAssessments( + IEnumerable competencyAssessments, string? searchString, int minMatchScore, bool stripStopWords @@ -38,7 +38,7 @@ bool stripStopWords { if (searchString == null) { - return roleProfiles; + return competencyAssessments; } if (stripStopWords) @@ -46,16 +46,16 @@ bool stripStopWords searchString = CleanSearchedWords(searchString); } - var query = new RoleProfile + var query = new CompetencyAssessment { - RoleProfileName = searchString.ToLower(), + CompetencyAssessmentName = searchString.ToLower(), }; if (stripStopWords) { var results = Process.ExtractSorted( query, - roleProfiles, - roleProfile => roleProfile.RoleProfileName.ToLower(), + competencyAssessments, + competencyAssessment => competencyAssessment.CompetencyAssessmentName.ToLower(), ScorerCache.Get(), minMatchScore ); @@ -65,8 +65,8 @@ bool stripStopWords { var results = Process.ExtractSorted( query, - roleProfiles, - roleProfile => roleProfile.RoleProfileName.ToLower(), + competencyAssessments, + competencyAssessment => competencyAssessment.CompetencyAssessmentName.ToLower(), ScorerCache.Get(), minMatchScore ); diff --git a/DigitalLearningSolutions.Web/Helpers/SortingHelper.cs b/DigitalLearningSolutions.Web/Helpers/SortingHelper.cs index e630a9ea9b..2a4cd083b8 100644 --- a/DigitalLearningSolutions.Web/Helpers/SortingHelper.cs +++ b/DigitalLearningSolutions.Web/Helpers/SortingHelper.cs @@ -3,8 +3,8 @@ using System.Collections.Generic; using System.Linq; using DigitalLearningSolutions.Data.Helpers; - using DigitalLearningSolutions.Data.Models.RoleProfiles; - using DigitalLearningSolutions.Web.ViewModels.RoleProfiles; + using DigitalLearningSolutions.Data.Models.CompetencyAssessments; + using DigitalLearningSolutions.Web.ViewModels.CompetencyAssessments; /// /// This is the older version of the SortingHelper. For future search/sort implementations we should @@ -13,36 +13,36 @@ /// public static class SortingHelper { - public static IEnumerable SortRoleProfileItems( - IEnumerable roleProfiles, + public static IEnumerable SortCompetencyAssessmentItems( + IEnumerable competencyAssessments, string sortBy, string sortDirection ) { return sortBy switch { - RoleProfileSortByOptionTexts.RoleProfileName => sortDirection == BaseRoleProfilesPageViewModel.DescendingText - ? roleProfiles.OrderByDescending(roleProfile => roleProfile.RoleProfileName) - : roleProfiles.OrderBy(roleProfile => roleProfile.RoleProfileName), - RoleProfileSortByOptionTexts.RoleProfileOwner => sortDirection == BaseRoleProfilesPageViewModel.DescendingText - ? roleProfiles.OrderByDescending(roleProfile => roleProfile.Owner) - : roleProfiles.OrderBy(roleProfile => roleProfile.Owner), - RoleProfileSortByOptionTexts.RoleProfileCreatedDate => sortDirection == BaseRoleProfilesPageViewModel.DescendingText - ? roleProfiles.OrderByDescending(roleProfile => roleProfile.CreatedDate) - : roleProfiles.OrderBy(roleProfile => roleProfile.CreatedDate), - RoleProfileSortByOptionTexts.RoleProfilePublishStatus => sortDirection == BaseRoleProfilesPageViewModel.DescendingText - ? roleProfiles.OrderByDescending(roleProfile => roleProfile.PublishStatusID) - : roleProfiles.OrderBy(roleProfile => roleProfile.PublishStatusID), - RoleProfileSortByOptionTexts.RoleProfileBrand => sortDirection == BaseRoleProfilesPageViewModel.DescendingText - ? roleProfiles.OrderByDescending(roleProfile => roleProfile.Brand) - : roleProfiles.OrderBy(roleProfile => roleProfile.Brand), - RoleProfileSortByOptionTexts.RoleProfileNationalRoleProfile => sortDirection == BaseRoleProfilesPageViewModel.DescendingText - ? roleProfiles.OrderByDescending(roleProfile => roleProfile.NRPRole) - : roleProfiles.OrderBy(roleProfile => roleProfile.NRPRole), - RoleProfileSortByOptionTexts.RoleProfileNationalRoleGroup => sortDirection == BaseRoleProfilesPageViewModel.DescendingText - ? roleProfiles.OrderByDescending(roleProfile => roleProfile.NRPProfessionalGroup) - : roleProfiles.OrderBy(roleProfile => roleProfile.NRPProfessionalGroup), - _ => roleProfiles + CompetencyAssessmentSortByOptionTexts.CompetencyAssessmentName => sortDirection == BaseCompetencyAssessmentsPageViewModel.DescendingText + ? competencyAssessments.OrderByDescending(competencyAssessment => competencyAssessment.CompetencyAssessmentName) + : competencyAssessments.OrderBy(competencyAssessment => competencyAssessment.CompetencyAssessmentName), + CompetencyAssessmentSortByOptionTexts.CompetencyAssessmentOwner => sortDirection == BaseCompetencyAssessmentsPageViewModel.DescendingText + ? competencyAssessments.OrderByDescending(competencyAssessment => competencyAssessment.Owner) + : competencyAssessments.OrderBy(competencyAssessment => competencyAssessment.Owner), + CompetencyAssessmentSortByOptionTexts.CompetencyAssessmentCreatedDate => sortDirection == BaseCompetencyAssessmentsPageViewModel.DescendingText + ? competencyAssessments.OrderByDescending(competencyAssessment => competencyAssessment.CreatedDate) + : competencyAssessments.OrderBy(competencyAssessment => competencyAssessment.CreatedDate), + CompetencyAssessmentSortByOptionTexts.CompetencyAssessmentPublishStatus => sortDirection == BaseCompetencyAssessmentsPageViewModel.DescendingText + ? competencyAssessments.OrderByDescending(competencyAssessment => competencyAssessment.PublishStatusID) + : competencyAssessments.OrderBy(competencyAssessment => competencyAssessment.PublishStatusID), + CompetencyAssessmentSortByOptionTexts.CompetencyAssessmentBrand => sortDirection == BaseCompetencyAssessmentsPageViewModel.DescendingText + ? competencyAssessments.OrderByDescending(competencyAssessment => competencyAssessment.Brand) + : competencyAssessments.OrderBy(competencyAssessment => competencyAssessment.Brand), + CompetencyAssessmentSortByOptionTexts.CompetencyAssessmentNationalCompetencyAssessment => sortDirection == BaseCompetencyAssessmentsPageViewModel.DescendingText + ? competencyAssessments.OrderByDescending(competencyAssessment => competencyAssessment.NRPRole) + : competencyAssessments.OrderBy(competencyAssessment => competencyAssessment.NRPRole), + CompetencyAssessmentSortByOptionTexts.CompetencyAssessmentNationalRoleGroup => sortDirection == BaseCompetencyAssessmentsPageViewModel.DescendingText + ? competencyAssessments.OrderByDescending(competencyAssessment => competencyAssessment.NRPProfessionalGroup) + : competencyAssessments.OrderBy(competencyAssessment => competencyAssessment.NRPProfessionalGroup), + _ => competencyAssessments }; } } diff --git a/DigitalLearningSolutions.Web/Models/Enums/CompetencyAssessmentsTab.cs b/DigitalLearningSolutions.Web/Models/Enums/CompetencyAssessmentsTab.cs new file mode 100644 index 0000000000..c77a640c7e --- /dev/null +++ b/DigitalLearningSolutions.Web/Models/Enums/CompetencyAssessmentsTab.cs @@ -0,0 +1,39 @@ +namespace DigitalLearningSolutions.Web.Models.Enums +{ + using System.Collections.Generic; + + public class CompetencyAssessmentsTab : BaseTabEnumeration + { + public static CompetencyAssessmentsTab MyCompetencyAssessments = new CompetencyAssessmentsTab( + 1, + nameof(MyCompetencyAssessments), + "CompetencyAssessments", + "ViewCompetencyAssessments", + "My Competency Assessments", + new Dictionary { { "tabName", "Mine" } } + ); + + public static CompetencyAssessmentsTab AllCompetencyAssessments = new CompetencyAssessmentsTab( + 2, + nameof(AllCompetencyAssessments), + "CompetencyAssessments", + "ViewCompetencyAssessments", + "All Competency Assessments", + new Dictionary { { "tabName", "All" } } + ); + + private CompetencyAssessmentsTab( + int id, + string name, + string controller, + string action, + string linkText, + Dictionary staticRouteData + ) : base(id, name, controller, action, linkText, staticRouteData) { } + + public override IEnumerable GetAllTabs() + { + return GetAll(); + } + } +} diff --git a/DigitalLearningSolutions.Web/Models/Enums/RoleProfilesTab.cs b/DigitalLearningSolutions.Web/Models/Enums/RoleProfilesTab.cs deleted file mode 100644 index 3d599ce5d0..0000000000 --- a/DigitalLearningSolutions.Web/Models/Enums/RoleProfilesTab.cs +++ /dev/null @@ -1,39 +0,0 @@ -namespace DigitalLearningSolutions.Web.Models.Enums -{ - using System.Collections.Generic; - - public class RoleProfilesTab : BaseTabEnumeration - { - public static RoleProfilesTab MyRoleProfiles = new RoleProfilesTab( - 1, - nameof(MyRoleProfiles), - "RoleProfiles", - "ViewRoleProfiles", - "My Role Profiles", - new Dictionary { { "tabName", "Mine" } } - ); - - public static RoleProfilesTab AllRoleProfiles = new RoleProfilesTab( - 2, - nameof(AllRoleProfiles), - "RoleProfiles", - "ViewRoleProfiles", - "All Role Profiles", - new Dictionary { { "tabName", "All" } } - ); - - private RoleProfilesTab( - int id, - string name, - string controller, - string action, - string linkText, - Dictionary staticRouteData - ) : base(id, name, controller, action, linkText, staticRouteData) { } - - public override IEnumerable GetAllTabs() - { - return GetAll(); - } - } -} diff --git a/DigitalLearningSolutions.Web/Scripts/frameworks/htmleditor.ts b/DigitalLearningSolutions.Web/Scripts/frameworks/htmleditor.ts index 129697c0af..3952d26df3 100644 --- a/DigitalLearningSolutions.Web/Scripts/frameworks/htmleditor.ts +++ b/DigitalLearningSolutions.Web/Scripts/frameworks/htmleditor.ts @@ -70,14 +70,19 @@ if (jodited === false) { const clean = DOMPurify.sanitize(editor.editor.innerHTML); editor.editor.innerHTML = clean; }); + + document.addEventListener('DOMContentLoaded', () => { + removeWaveErrors(); + removeDevToolsIssues(); + }); + + // ** Start* for jodit editor error (display red outline, focus on summary error text click) **** const textarea = document.querySelector('.nhsuk-textarea.html-editor.nhsuk-input--error') as HTMLTextAreaElement | null; if (textarea) { const editorDiv = document.querySelector('.jodit-container.jodit.jodit_theme_default.jodit-wysiwyg_mode') as HTMLDivElement | null; editorDiv?.classList.add('jodit-container', 'jodit', 'jodit_theme_default', 'jodit-wysiwyg_mode', 'jodit-error'); } - const summary = document.querySelector('.nhsuk-list.nhsuk-error-summary__list') as HTMLDivElement | null; - if (summary) { summary.addEventListener('click', (e: Event) => { if (textarea) { @@ -96,5 +101,70 @@ if (jodited === false) { } }); } + // ** End* for jodit editor error (display red outline, focus on summary error text click) **** + } +} + +function removeWaveErrors() { + const input = Array.from(document.querySelectorAll('input[tab-index="-1"]')) + .find((el) => el.style.width === '0px' && el.style.height === '0px' + && el.style.position === 'absolute' && el.style.visibility === 'hidden'); + + if (input) { + input.setAttribute('aria-label', 'Hidden input for accessibility'); + input.setAttribute('title', 'HiddenInput'); + } + + const observer = new MutationObserver((mutations, obs) => { + const textarea = document.querySelector('.ace_text-input') as HTMLTextAreaElement | null; + if (textarea) { + textarea.setAttribute('aria-label', 'ace_text-input'); + obs.disconnect(); + } + }); + observer.observe(document.body, { + childList: true, + subtree: true, + }); +} +function removeDevToolsIssues() { + // set role = 'list' to toolbar + const toolbarbox = document.querySelector('.jodit-toolbar__box') as HTMLElement | null; + if (toolbarbox) { + toolbarbox.setAttribute('role', 'list'); + } + // set role = 'list' to statusbar + const statusbar = document.querySelector('.jodit-xpath') as HTMLElement | null; + if (statusbar) { + statusbar.setAttribute('role', 'list'); } + document.querySelectorAll('.jodit-toolbar-button__trigger').forEach((el) => { + el.removeAttribute('role'); + }); + // observer to detect role='trigger' and remove role + const observer = new MutationObserver(() => { + document.querySelectorAll('.jodit-toolbar-button__trigger').forEach((el) => { + el.removeAttribute('role'); + }); + }); + const target = document.querySelector('.jodit-toolbar__box'); + if (target) { + observer.observe(target, { subtree: true, childList: true }); + } + + // observer to detect iframe and set title + const observer2 = new MutationObserver(() => { + const hiddenIframe = Array.from(document.querySelectorAll('iframe')).find((iframe) => { + const rect = iframe.getBoundingClientRect(); + return rect.width === 0 && rect.height === 0 && (iframe.src === 'about:blank' || iframe.getAttribute('src') === 'about:blank'); + }); + if (hiddenIframe) { + hiddenIframe.setAttribute('title', 'Hidden iframe'); + observer2.disconnect(); // Stop observing once found + } + }); + observer2.observe(document.body, { + childList: true, + subtree: true, + }); } diff --git a/DigitalLearningSolutions.Web/ServiceFilter/RedirectToErrorEmptySessionData.cs b/DigitalLearningSolutions.Web/ServiceFilter/RedirectToErrorEmptySessionData.cs index 1a50a20ae6..ef5a5e36a0 100644 --- a/DigitalLearningSolutions.Web/ServiceFilter/RedirectToErrorEmptySessionData.cs +++ b/DigitalLearningSolutions.Web/ServiceFilter/RedirectToErrorEmptySessionData.cs @@ -34,7 +34,7 @@ public void OnActionExecuting(ActionExecutingContext context) return; } - if (context.ActionArguments.ContainsKey("actionname") && context.ActionArguments["actionname"].ToString() == "Edit") + if (context.ActionArguments.ContainsKey("actionName") && context.ActionArguments["actionName"].ToString() == "Edit") { return; } diff --git a/DigitalLearningSolutions.Web/Services/CompetencyAssessmentService.cs b/DigitalLearningSolutions.Web/Services/CompetencyAssessmentService.cs new file mode 100644 index 0000000000..80bb557030 --- /dev/null +++ b/DigitalLearningSolutions.Web/Services/CompetencyAssessmentService.cs @@ -0,0 +1,222 @@ +using DigitalLearningSolutions.Data.DataServices; +using DigitalLearningSolutions.Data.Models.Common; +using DigitalLearningSolutions.Data.Models.CompetencyAssessments; +using DocumentFormat.OpenXml.EMMA; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace DigitalLearningSolutions.Web.Services +{ + public interface ICompetencyAssessmentService + { + //GET DATA + IEnumerable GetAllCompetencyAssessments(int adminId); + + IEnumerable GetCompetencyAssessmentsForAdminId(int adminId); + + CompetencyAssessmentBase? GetCompetencyAssessmentBaseById(int competencyAssessmentId, int adminId); + + CompetencyAssessmentBase? GetCompetencyAssessmentBaseByName(string competencyAssessmentName, int adminId); + CompetencyAssessment? GetCompetencyAssessmentById(int competencyAssessmentId, int adminId); + + IEnumerable GetNRPProfessionalGroups(); + IEnumerable GetNRPSubGroups(int? nRPProfessionalGroupID); + IEnumerable GetNRPRoles(int? nRPSubGroupID); + + CompetencyAssessmentTaskStatus GetCompetencyAssessmentTaskStatus(int assessmentId, int? frameworkId); + int[] GetLinkedFrameworkIds(int assessmentId); + int? GetPrimaryLinkedFrameworkId(int assessmentId); + + bool RemoveSelfAssessmentFramework(int assessmentId, int frameworkId, int adminId); + + //UPDATE DATA + bool UpdateCompetencyAssessmentName(int competencyAssessmentId, int adminId, string competencyAssessmentName); + bool UpdateCompetencyRoleProfileLinks(int competencyAssessmentId, int adminId, int? professionalGroupId, int? subGroupId, int? roleId); + bool UpdateIntroductoryTextTaskStatus(int assessmentId, bool taskStatus); + bool UpdateCompetencyAssessmentDescription(int assessmentId, int adminId, string description); + bool UpdateCompetencyAssessmentBranding(int assessmentId, int adminId, int brandID, int categoryID); + bool UpdateBrandingTaskStatus(int assessmentId, bool taskStatus); + bool UpdateCompetencyAssessmentVocabulary(int assessmentId, int adminId, string vocabulary); + bool UpdateVocabularyTaskStatus(int assessmentId, bool taskStatus); + bool UpdateRoleProfileLinksTaskStatus(int assessmentId, bool taskStatus); + bool UpdateFrameworkLinksTaskStatus(int assessmentId, bool taskStatus, bool? previousStatus); + bool UpdateSelectCompetenciesTaskStatus(int competencyAssessmentId, bool taskStatus, bool? previousStatus); + bool UpdateOptionalCompetenciesTaskStatus(int assessmentId, bool taskStatus, bool? previousStatus); + bool UpdateRoleRequirementsTaskStatus(int assessmentId, bool taskStatus, bool? previousStatus); + + //INSERT DATA + int InsertCompetencyAssessment(int adminId, int centreId, string competencyAssessmentName, int? frameworkId); + bool InsertSelfAssessmentFramework(int adminId, int assessmentId, int frameworkId); + int GetCompetencyCountByFrameworkId(int competencyAssessmentId, int frameworkId); + + //DELETE DATA + bool RemoveFrameworkCompetenciesFromAssessment(int competencyAssessmentId, int frameworkId); + + } + public class CompetencyAssessmentService : ICompetencyAssessmentService + { + private readonly ICompetencyAssessmentDataService competencyAssessmentDataService; + private readonly IFrameworkDataService frameworkDataService; + public CompetencyAssessmentService(ICompetencyAssessmentDataService competencyAssessmentDataService, IFrameworkDataService frameworkDataService) + { + this.competencyAssessmentDataService = competencyAssessmentDataService; + this.frameworkDataService = frameworkDataService; + } + public IEnumerable GetAllCompetencyAssessments(int adminId) + { + return competencyAssessmentDataService.GetAllCompetencyAssessments(adminId); + } + + public IEnumerable GetNRPProfessionalGroups() + { + return competencyAssessmentDataService.GetNRPProfessionalGroups(); + } + + public CompetencyAssessmentBase? GetCompetencyAssessmentBaseById(int competencyAssessmentId, int adminId) + { + return competencyAssessmentDataService.GetCompetencyAssessmentBaseById(competencyAssessmentId, adminId); + } + + public CompetencyAssessmentBase? GetCompetencyAssessmentBaseByName(string competencyAssessmentName, int adminId) + { + return competencyAssessmentDataService.GetCompetencyAssessmentBaseByName(competencyAssessmentName, adminId); + } + + public IEnumerable GetCompetencyAssessmentsForAdminId(int adminId) + { + return competencyAssessmentDataService.GetCompetencyAssessmentsForAdminId(adminId); + } + public int InsertCompetencyAssessment(int adminId, int centreId, string competencyAssessmentName, int? frameworkId) + { + var assessmentId = competencyAssessmentDataService.InsertCompetencyAssessment(adminId, centreId, competencyAssessmentName); + if (assessmentId > 0 && frameworkId != null) + { + var framework = frameworkDataService.GetBrandedFrameworkByFrameworkId((int)frameworkId, adminId); + if (framework != null) + { + competencyAssessmentDataService.InsertSelfAssessmentFramework(adminId, assessmentId, framework.ID); + competencyAssessmentDataService.UpdateCompetencyAssessmentDescription(adminId, assessmentId, framework.Description); + competencyAssessmentDataService.UpdateCompetencyAssessmentBranding(assessmentId, adminId, (int)framework.BrandID, (int)framework.CategoryID); + competencyAssessmentDataService.UpdateCompetencyAssessmentVocabulary(assessmentId, adminId, framework.Vocabulary); + } + } + return assessmentId; + } + + public bool UpdateCompetencyAssessmentName(int competencyAssessmentId, int adminId, string competencyAssessmentName) + { + return competencyAssessmentDataService.UpdateCompetencyAssessmentName(competencyAssessmentId, adminId, competencyAssessmentName); + } + + public bool UpdateCompetencyRoleProfileLinks(int competencyAssessmentId, int adminId, int? professionalGroupId, int? subGroupId, int? roleId) + { + return competencyAssessmentDataService.UpdateCompetencyRoleProfileLinks(competencyAssessmentId, adminId, professionalGroupId, subGroupId, roleId); + } + public CompetencyAssessmentTaskStatus GetCompetencyAssessmentTaskStatus(int assessmentId, int? frameworkId) + { + return competencyAssessmentDataService.GetOrInsertAndReturnAssessmentTaskStatus(assessmentId, (frameworkId != null)); + } + public bool UpdateCompetencyAssessmentDescription(int competencyAssessmentId, int adminId, string description) + { + return competencyAssessmentDataService.UpdateCompetencyAssessmentDescription(competencyAssessmentId, adminId, description); + } + public bool UpdateIntroductoryTextTaskStatus(int assessmentId, bool taskStatus) + { + return competencyAssessmentDataService.UpdateIntroductoryTextTaskStatus(assessmentId, taskStatus); + } + + public CompetencyAssessment? GetCompetencyAssessmentById(int competencyAssessmentId, int adminId) + { + return competencyAssessmentDataService.GetCompetencyAssessmentById(competencyAssessmentId, adminId); + } + + public bool UpdateCompetencyAssessmentBranding(int assessmentId, int adminId, int brandID, int categoryID) + { + return competencyAssessmentDataService.UpdateCompetencyAssessmentBranding(assessmentId, adminId, brandID, categoryID); + } + + public bool UpdateBrandingTaskStatus(int assessmentId, bool taskStatus) + { + return competencyAssessmentDataService.UpdateBrandingTaskStatus(assessmentId, taskStatus); + } + + bool ICompetencyAssessmentService.UpdateCompetencyAssessmentVocabulary(int assessmentId, int adminId, string vocabulary) + { + return competencyAssessmentDataService.UpdateCompetencyAssessmentVocabulary(assessmentId, adminId, vocabulary); + } + + bool ICompetencyAssessmentService.UpdateVocabularyTaskStatus(int assessmentId, bool taskStatus) + { + return competencyAssessmentDataService.UpdateVocabularyTaskStatus(assessmentId, taskStatus); + } + + public IEnumerable GetNRPSubGroups(int? nRPProfessionalGroupID) + { + return competencyAssessmentDataService.GetNRPSubGroups(nRPProfessionalGroupID); + } + + public IEnumerable GetNRPRoles(int? nRPSubGroupID) + { + return competencyAssessmentDataService.GetNRPRoles(nRPSubGroupID); + } + + public bool UpdateRoleProfileLinksTaskStatus(int assessmentId, bool taskStatus) + { + return competencyAssessmentDataService.UpdateRoleProfileLinksTaskStatus(assessmentId, taskStatus); + } + + public int[] GetLinkedFrameworkIds(int assessmentId) + { + return competencyAssessmentDataService.GetLinkedFrameworkIds(assessmentId); + } + + public bool InsertSelfAssessmentFramework(int adminId, int assessmentId, int frameworkId) + { + return competencyAssessmentDataService.InsertSelfAssessmentFramework(adminId, assessmentId, frameworkId); + } + + public bool UpdateFrameworkLinksTaskStatus(int assessmentId, bool taskStatus, bool? previousStatus) + { + return competencyAssessmentDataService.UpdateFrameworkLinksTaskStatus(assessmentId, taskStatus, previousStatus); + } + + public int? GetPrimaryLinkedFrameworkId(int assessmentId) + { + return competencyAssessmentDataService.GetPrimaryLinkedFrameworkId(assessmentId); + } + + public bool RemoveSelfAssessmentFramework(int assessmentId, int frameworkId, int adminId) + { + UpdateFrameworkLinksTaskStatus(assessmentId, false, true); + return competencyAssessmentDataService.RemoveSelfAssessmentFramework(assessmentId, frameworkId, adminId); + } + + public int GetCompetencyCountByFrameworkId(int competencyAssessmentId, int frameworkId) + { + return competencyAssessmentDataService.GetCompetencyCountByFrameworkId(competencyAssessmentId, frameworkId); + } + + public bool RemoveFrameworkCompetenciesFromAssessment(int competencyAssessmentId, int frameworkId) + { + UpdateSelectCompetenciesTaskStatus(competencyAssessmentId, false, true); + UpdateOptionalCompetenciesTaskStatus(competencyAssessmentId, false, true); + UpdateRoleRequirementsTaskStatus(competencyAssessmentId, false, true); + return competencyAssessmentDataService.RemoveFrameworkCompetenciesFromAssessment(competencyAssessmentId, frameworkId); + } + + public bool UpdateSelectCompetenciesTaskStatus(int assessmentId, bool taskStatus, bool? previousStatus) + { + return competencyAssessmentDataService.UpdateSelectCompetenciesTaskStatus(assessmentId, taskStatus, previousStatus); + } + + public bool UpdateOptionalCompetenciesTaskStatus(int assessmentId, bool taskStatus, bool? previousStatus) + { + return competencyAssessmentDataService.UpdateOptionalCompetenciesTaskStatus(assessmentId, taskStatus, previousStatus); + } + + public bool UpdateRoleRequirementsTaskStatus(int assessmentId, bool taskStatus, bool? previousStatus) + { + return competencyAssessmentDataService.UpdateRoleRequirementsTaskStatus(assessmentId, taskStatus, previousStatus); + } + } +} diff --git a/DigitalLearningSolutions.Web/Services/CompetencyLearningResourcesService.cs b/DigitalLearningSolutions.Web/Services/CompetencyLearningResourcesService.cs index 3f9a8b295c..525d3e87e0 100644 --- a/DigitalLearningSolutions.Web/Services/CompetencyLearningResourcesService.cs +++ b/DigitalLearningSolutions.Web/Services/CompetencyLearningResourcesService.cs @@ -13,6 +13,7 @@ public interface ICompetencyLearningResourcesService IEnumerable GetCompetencyResourceAssessmentQuestionParameters(IEnumerable competencyLearningResourceIds); int AddCompetencyLearningResource(int resourceRefID, string originalResourceName, string description, string resourceType, string link, string catalogue, decimal rating, int competencyID, int adminId); + IEnumerable GetActiveCompetencyLearningResourcesByCompetencyIdAndReferenceId(int competencyId, int referenceId); } public class CompetencyLearningResourcesService : ICompetencyLearningResourcesService { @@ -40,5 +41,9 @@ public IEnumerable GetCompetencyR { return competencyLearningResourcesDataService.GetCompetencyResourceAssessmentQuestionParameters(competencyLearningResourceIds); } + public IEnumerable GetActiveCompetencyLearningResourcesByCompetencyIdAndReferenceId(int competencyId, int referenceId) + { + return competencyLearningResourcesDataService.GetActiveCompetencyLearningResourcesByCompetencyIdAndReferenceId(competencyId, referenceId); + } } } diff --git a/DigitalLearningSolutions.Web/Services/DelegateDownloadFileService.cs b/DigitalLearningSolutions.Web/Services/DelegateDownloadFileService.cs index 7274173d88..f0bba93403 100644 --- a/DigitalLearningSolutions.Web/Services/DelegateDownloadFileService.cs +++ b/DigitalLearningSolutions.Web/Services/DelegateDownloadFileService.cs @@ -39,6 +39,7 @@ public class DelegateDownloadFileService : IDelegateDownloadFileService private const string ProfessionalRegistrationNumber = "Professional Registration Number"; private const string JobGroup = "Job group"; private const string RegisteredDate = "Registered"; + private const string LastAccessed = "Last Accessed Date"; private const string RegistrationComplete = "Registration complete"; private const string Active = "Active"; private const string Approved = "Approved"; @@ -333,6 +334,7 @@ DataTable dataTable new DataColumn(ProfessionalRegistrationNumber), new DataColumn(JobGroup), new DataColumn(RegisteredDate), + new DataColumn(LastAccessed), } ); @@ -374,7 +376,7 @@ CentreRegistrationPrompts registrationPrompts ); row[JobGroup] = delegateRecord.JobGroupName; row[RegisteredDate] = delegateRecord.DateRegistered?.Date; - + row[LastAccessed] = delegateRecord.LastAccessed?.Date; var delegateAnswers = delegateRecord.GetRegistrationFieldAnswers(); foreach (var prompt in registrationPrompts.CustomPrompts) @@ -402,7 +404,7 @@ CentreRegistrationPrompts registrationPrompts private static void FormatAllDelegateWorksheetColumns(IXLWorkbook workbook, DataTable dataTable) { ClosedXmlHelper.FormatWorksheetColumn(workbook, dataTable, RegisteredDate, XLDataType.DateTime); - + ClosedXmlHelper.FormatWorksheetColumn(workbook, dataTable, LastAccessed, XLDataType.DateTime); var boolColumns = new[] { RegistrationComplete, Active, Approved, IsAdmin }; foreach (var columnName in boolColumns) { diff --git a/DigitalLearningSolutions.Web/Services/FrameworkNotificationService.cs b/DigitalLearningSolutions.Web/Services/FrameworkNotificationService.cs index 092f38c15d..d0cfdb0a0f 100644 --- a/DigitalLearningSolutions.Web/Services/FrameworkNotificationService.cs +++ b/DigitalLearningSolutions.Web/Services/FrameworkNotificationService.cs @@ -34,7 +34,7 @@ public class FrameworkNotificationService : IFrameworkNotificationService private readonly IConfigDataService configDataService; private readonly IEmailService emailService; private readonly IFrameworkService frameworkService; - private readonly IRoleProfileService roleProfileService; + private readonly ICompetencyAssessmentService competencyAssessmentService; private readonly ISupervisorService supervisorService; private readonly ISelfAssessmentDataService selfAssessmentDataService; private readonly ICentresDataService centresDataService; @@ -42,7 +42,7 @@ public FrameworkNotificationService( IFrameworkService frameworkService, IConfigDataService configDataService, IEmailService emailService, - IRoleProfileService roleProfileService, + ICompetencyAssessmentService competencyAssessmentService, ISupervisorService supervisorService, ISelfAssessmentDataService selfAssessmentDataService, ICentresDataService centresDataService @@ -51,7 +51,7 @@ ICentresDataService centresDataService this.frameworkService = frameworkService; this.configDataService = configDataService; this.emailService = emailService; - this.roleProfileService = roleProfileService; + this.competencyAssessmentService = competencyAssessmentService; this.supervisorService = supervisorService; this.selfAssessmentDataService = selfAssessmentDataService; this.centresDataService = centresDataService; @@ -221,8 +221,8 @@ public void SendSupervisorDelegateInvite(int supervisorDelegateId, int adminId, builder.TextBody = $@"Dear colleague, You have been invited to register to access the NHS England, Digital Learning Solutions platform as a supervised delegate by {supervisorDelegate.SupervisorName} ({supervisorDelegate.SupervisorEmail}) ({centreName}). To register, visit {dlsUrlBuilder.Uri.ToString()}. - Registering using this link will confirm your acceptance of the invite. Your supervisor will then be able to assign role profile assessments and view and validate your self assessment results."; - builder.HtmlBody = $@"

Dear colleague,

You have been invited to register to access the NHS England, Digital Learning Solutions platform as a supervised delegate by {supervisorDelegate.SupervisorName} ({centreName}).

Click here to register and confirm your acceptance of the invite.

Your supervisor will then be able to assign role profile assessments and view and validate your self assessment results.

"; + Registering using this link will confirm your acceptance of the invite. Your supervisor will then be able to assign competency assessments and view and validate your self assessment results."; + builder.HtmlBody = $@"

Dear colleague,

You have been invited to register to access the NHS England, Digital Learning Solutions platform as a supervised delegate by {supervisorDelegate.SupervisorName} ({centreName}).

Click here to register and confirm your acceptance of the invite.

Your supervisor will then be able to assign competency assessments and view and validate your self assessment results.

"; emailService.SendEmail(new Email(emailSubjectLine, builder, supervisorDelegate.DelegateEmail)); } } @@ -240,7 +240,7 @@ public void SendSupervisorDelegateConfirmed(int supervisorDelegateId, int adminI You are already registered as a delegate at the supervisor's DLS centre so they can now assign competency self assessments and view and validate your self assessment results. If this looks like a mistake, please contact {supervisorDelegate.SupervisorName} ({supervisorDelegate.SupervisorEmail}) ({centreName}) directly to correct."; - builder.HtmlBody = $@"

Dear {supervisorDelegate.FirstName}

{supervisorDelegate.SupervisorName} ({centreName}) has accepted your request to be your supervisor for profile asessment activities in the NHS England, Digital Learning Solutions platform.

Click here to access your role profile assessments.

"; + builder.HtmlBody = $@"

Dear {supervisorDelegate.FirstName}

{supervisorDelegate.SupervisorName} ({centreName}) has accepted your request to be your supervisor for profile asessment activities in the NHS England, Digital Learning Solutions platform.

Click here to access your competency assessments.

"; string toEmail = (@adminId == 0 ? supervisorDelegate.DelegateEmail : supervisorDelegate.SupervisorEmail); emailService.SendEmail(new Email(emailSubjectLine, builder, toEmail)); } @@ -410,8 +410,8 @@ public void SendSupervisorDelegateReminder(int supervisorDelegateId, int adminId builder.TextBody = $@"Dear colleague, This is a reminder to to register to access the NHS England, Digital Learning Solutions platform as a supervised delegate by {supervisorDelegate.SupervisorName} ({supervisorDelegate.SupervisorEmail}) ({centreName}). To register, visit {dlsUrlBuilder.Uri.ToString()}. - Your supervisor will then be able to assign role profile assessments and view and validate your self assessment results."; - builder.HtmlBody = $@"

Dear colleague,

This is a reminder to register to access the NHS England, Digital Learning Solutions platform as a supervised delegate by {supervisorDelegate.SupervisorName} ({centreName}).

Click here to register.

Your supervisor will then be able to assign role profile assessments and view and validate your self assessment results.

"; + Your supervisor will then be able to assign competency assessments and view and validate your self assessment results."; + builder.HtmlBody = $@"

Dear colleague,

This is a reminder to register to access the NHS England, Digital Learning Solutions platform as a supervised delegate by {supervisorDelegate.SupervisorName} ({centreName}).

Click here to register.

Your supervisor will then be able to assign competency assessments and view and validate your self assessment results.

"; emailService.SendEmail(new Email(emailSubjectLine, builder, supervisorDelegate.DelegateEmail)); } } diff --git a/DigitalLearningSolutions.Web/Services/FrameworkService.cs b/DigitalLearningSolutions.Web/Services/FrameworkService.cs index b407be417f..6e2c1790e9 100644 --- a/DigitalLearningSolutions.Web/Services/FrameworkService.cs +++ b/DigitalLearningSolutions.Web/Services/FrameworkService.cs @@ -247,9 +247,9 @@ string direction void RemoveCustomFlag(int flagId); void RemoveCollaboratorFromFramework(int frameworkId, int id); - void DeleteFrameworkCompetencyGroup(int frameworkCompetencyGroupId, int competencyGroupId, int adminId); + void DeleteFrameworkCompetencyGroup(int frameworkCompetencyGroupId, int competencyGroupId, int frameworkId, int adminId); - void DeleteFrameworkCompetency(int frameworkCompetencyId, int adminId); + void DeleteFrameworkCompetency(int frameworkCompetencyId, int? frameworkCompetencyGroupId, int frameworkId, int adminId); void DeleteFrameworkDefaultQuestion( int frameworkId, @@ -316,14 +316,14 @@ public void DeleteCompetencyLearningResource(int competencyLearningResourceId, i frameworkDataService.DeleteCompetencyLearningResource(competencyLearningResourceId, adminId); } - public void DeleteFrameworkCompetency(int frameworkCompetencyId, int adminId) + public void DeleteFrameworkCompetency(int frameworkCompetencyId, int? frameworkCompetencyGroupId, int frameworkId, int adminId) { - frameworkDataService.DeleteFrameworkCompetency(frameworkCompetencyId, adminId); + frameworkDataService.DeleteFrameworkCompetency(frameworkCompetencyId, frameworkCompetencyGroupId, frameworkId, adminId); } - public void DeleteFrameworkCompetencyGroup(int frameworkCompetencyGroupId, int competencyGroupId, int adminId) + public void DeleteFrameworkCompetencyGroup(int frameworkCompetencyGroupId, int competencyGroupId, int frameworkId, int adminId) { - frameworkDataService.DeleteFrameworkCompetencyGroup(frameworkCompetencyGroupId, competencyGroupId, adminId); + frameworkDataService.DeleteFrameworkCompetencyGroup(frameworkCompetencyGroupId, competencyGroupId, frameworkId, adminId); } public void DeleteFrameworkDefaultQuestion(int frameworkId, int assessmentQuestionId, int adminId, bool deleteFromExisting) diff --git a/DigitalLearningSolutions.Web/Services/ImportCompetenciesFromFileService.cs b/DigitalLearningSolutions.Web/Services/ImportCompetenciesFromFileService.cs index dcb388f3ae..6d773ffd02 100644 --- a/DigitalLearningSolutions.Web/Services/ImportCompetenciesFromFileService.cs +++ b/DigitalLearningSolutions.Web/Services/ImportCompetenciesFromFileService.cs @@ -206,7 +206,6 @@ CompetencyTableRow competencyRow else { frameworkCompetencyGroupId = frameworkService.GetFrameworkCompetencyGroupId(frameworkId, newCompetencyGroupId); - var isUpdated = frameworkService.UpdateFrameworkCompetencyGroup((int)frameworkCompetencyGroupId, newCompetencyGroupId, competencyRow.CompetencyGroup, competencyRow.GroupDescription, adminId); competencyRow.RowStatus = RowStatus.CompetencyGroupUpdated; } @@ -262,7 +261,7 @@ CompetencyTableRow competencyRow { foreach (var frameworkFlag in frameworkFlags) { - if (frameworkFlag.FlagName == flag) + if (frameworkFlag.FlagName?.Trim().ToLower() == flag?.Trim().ToLower()) { flagId = frameworkFlag.FlagId; break; @@ -271,7 +270,7 @@ CompetencyTableRow competencyRow } if (flagId == 0) { - flagId = frameworkService.AddCustomFlagToFramework(frameworkId, flag, "Flag", "nhsuk-tag--white"); + flagId = frameworkService.AddCustomFlagToFramework(frameworkId, flag?.Trim(), "Flag", "nhsuk-tag--white"); } flagIds.Add(flagId); } diff --git a/DigitalLearningSolutions.Web/Services/LoginService.cs b/DigitalLearningSolutions.Web/Services/LoginService.cs index 35d8cc7a16..dc52aca0b5 100644 --- a/DigitalLearningSolutions.Web/Services/LoginService.cs +++ b/DigitalLearningSolutions.Web/Services/LoginService.cs @@ -5,10 +5,12 @@ using System.Linq; using System.Security.Claims; using System.Threading.Tasks; + using DigitalLearningSolutions.Data.DataServices; using DigitalLearningSolutions.Data.Enums; using DigitalLearningSolutions.Data.Helpers; using DigitalLearningSolutions.Data.Models; using DigitalLearningSolutions.Data.Models.User; + using DigitalLearningSolutions.Data.Utilities; using DigitalLearningSolutions.Data.ViewModels; using DigitalLearningSolutions.Web.Helpers; using Microsoft.AspNetCore.Authentication; @@ -28,6 +30,12 @@ List idsOfCentresWithUnverifiedEmails bool CentreEmailIsVerified(int userId, int centreIdIfLoggingIntoSingleCentre); + void UpdateLastAccessedForUsersTable(int Id); + + void UpdateLastAccessedForDelegatesAccountsTable(int Id); + + void UpdateLastAccessedForAdminAccountsTable(int Id); + Task HandleLoginResult( LoginResult loginResult, TicketReceivedContext context, @@ -41,11 +49,28 @@ public class LoginService : ILoginService { private readonly IUserService userService; private readonly IUserVerificationService userVerificationService; + private readonly ILoginDataService loginDataService; - public LoginService(IUserService userService, IUserVerificationService userVerificationService) + public LoginService(IUserService userService, IUserVerificationService userVerificationService, ILoginDataService loginDataService) { this.userService = userService; this.userVerificationService = userVerificationService; + this.loginDataService = loginDataService; + } + + public void UpdateLastAccessedForUsersTable(int Id) + { + loginDataService.UpdateLastAccessedForUsersTable(Id); + } + + public void UpdateLastAccessedForDelegatesAccountsTable(int Id) + { + loginDataService.UpdateLastAccessedForDelegatesAccountsTable(Id); + } + + public void UpdateLastAccessedForAdminAccountsTable(int Id) + { + loginDataService.UpdateLastAccessedForAdminAccountsTable(Id); } public LoginResult AttemptLogin(string username, string password) diff --git a/DigitalLearningSolutions.Web/Services/RoleProfileService.cs b/DigitalLearningSolutions.Web/Services/RoleProfileService.cs deleted file mode 100644 index 7983b2afa4..0000000000 --- a/DigitalLearningSolutions.Web/Services/RoleProfileService.cs +++ /dev/null @@ -1,68 +0,0 @@ -using DigitalLearningSolutions.Data.DataServices; -using DigitalLearningSolutions.Data.Models.RoleProfiles; -using System.Collections.Generic; - -namespace DigitalLearningSolutions.Web.Services -{ - public interface IRoleProfileService - { - //GET DATA - IEnumerable GetAllRoleProfiles(int adminId); - - IEnumerable GetRoleProfilesForAdminId(int adminId); - - RoleProfileBase? GetRoleProfileBaseById(int roleProfileId, int adminId); - - RoleProfileBase? GetRoleProfileByName(string roleProfileName, int adminId); - - IEnumerable GetNRPProfessionalGroups(); - - //UPDATE DATA - bool UpdateRoleProfileName(int roleProfileId, int adminId, string roleProfileName); - - bool UpdateRoleProfileProfessionalGroup(int roleProfileId, int adminId, int? nrpProfessionalGroupID); - - } - public class RoleProfileService : IRoleProfileService - { - private readonly IRoleProfileDataService roleProfileDataService; - public RoleProfileService(IRoleProfileDataService roleProfileDataService) - { - this.roleProfileDataService = roleProfileDataService; - } - public IEnumerable GetAllRoleProfiles(int adminId) - { - return roleProfileDataService.GetAllRoleProfiles(adminId); - } - - public IEnumerable GetNRPProfessionalGroups() - { - return roleProfileDataService.GetNRPProfessionalGroups(); - } - - public RoleProfileBase? GetRoleProfileBaseById(int roleProfileId, int adminId) - { - return roleProfileDataService.GetRoleProfileBaseById(roleProfileId, adminId); - } - - public RoleProfileBase? GetRoleProfileByName(string roleProfileName, int adminId) - { - return roleProfileDataService.GetRoleProfileByName(roleProfileName, adminId); - } - - public IEnumerable GetRoleProfilesForAdminId(int adminId) - { - return roleProfileDataService.GetRoleProfilesForAdminId(adminId); - } - - public bool UpdateRoleProfileName(int roleProfileId, int adminId, string roleProfileName) - { - return roleProfileDataService.UpdateRoleProfileName(roleProfileId, adminId, roleProfileName); - } - - public bool UpdateRoleProfileProfessionalGroup(int roleProfileId, int adminId, int? nrpProfessionalGroupID) - { - return roleProfileDataService.UpdateRoleProfileProfessionalGroup(roleProfileId, adminId, nrpProfessionalGroupID); - } - } -} diff --git a/DigitalLearningSolutions.Web/Services/SelfAssessmentReportService.cs b/DigitalLearningSolutions.Web/Services/SelfAssessmentReportService.cs index 18b6c46cdc..33c7c71160 100644 --- a/DigitalLearningSolutions.Web/Services/SelfAssessmentReportService.cs +++ b/DigitalLearningSolutions.Web/Services/SelfAssessmentReportService.cs @@ -1,129 +1,261 @@ -namespace DigitalLearningSolutions.Data.Services -{ - using ClosedXML.Excel; - using DigitalLearningSolutions.Data.DataServices.SelfAssessmentDataService; - using DigitalLearningSolutions.Data.Models.Email; - using DigitalLearningSolutions.Data.Models.SelfAssessments; - using System; - using System.Collections.Generic; - using System.IO; - using System.Linq; - - public interface ISelfAssessmentReportService - { - byte[] GetSelfAssessmentExcelExportForCentre(int centreId, int selfAssessmentId); - byte[] GetDigitalCapabilityExcelExportForCentre(int centreId); - IEnumerable GetSelfAssessmentsForReportList(int centreId, int? categoryId); - } - public class SelfAssessmentReportService : ISelfAssessmentReportService - { - private readonly IDCSAReportDataService dcsaReportDataService; - private readonly ISelfAssessmentReportDataService selfAssessmentReportDataService; - public SelfAssessmentReportService( - IDCSAReportDataService dcsaReportDataService, - ISelfAssessmentReportDataService selfAssessmentReportDataService - ) - { - this.dcsaReportDataService = dcsaReportDataService; - this.selfAssessmentReportDataService = selfAssessmentReportDataService; - } - private static void AddSheetToWorkbook(IXLWorkbook workbook, string sheetName, IEnumerable? dataObjects) - { - var sheet = workbook.Worksheets.Add(sheetName); - var table = sheet.Cell(1, 1).InsertTable(dataObjects); - table.Theme = XLTableTheme.TableStyleLight9; - sheet.Columns().AdjustToContents(); - } - - public IEnumerable GetSelfAssessmentsForReportList(int centreId, int? categoryId) - { - return selfAssessmentReportDataService.GetSelfAssessmentsForReportList(centreId, categoryId); - } - - public byte[] GetSelfAssessmentExcelExportForCentre(int centreId, int selfAssessmentId) - { - var selfAssessmentReportData = selfAssessmentReportDataService.GetSelfAssessmentReportDataForCentre(centreId, selfAssessmentId); - var reportData = selfAssessmentReportData.Select( - x => new - { - x.SelfAssessment, - x.Learner, - x.LearnerActive, - x.PRN, - x.JobGroup, - x.ProgrammeCourse, - x.Organisation, - x.DepartmentTeam, - x.OtherCentres, - x.DLSRole, - x.Registered, - x.Started, - x.LastAccessed, - x.OptionalProficienciesAssessed, - x.SelfAssessedAchieved, - x.ConfirmedResults, - x.SignOffRequested, - x.SignOffAchieved, - x.ReviewedDate - } - ); - using var workbook = new XLWorkbook(); - AddSheetToWorkbook(workbook, "SelfAssessmentLearners", reportData); - using var stream = new MemoryStream(); - workbook.SaveAs(stream); - return stream.ToArray(); - } - public byte[] GetDigitalCapabilityExcelExportForCentre(int centreId) - { - var delegateCompletionStatus = dcsaReportDataService.GetDelegateCompletionStatusForCentre(centreId); - var outcomeSummary = dcsaReportDataService.GetOutcomeSummaryForCentre(centreId); - var summary = delegateCompletionStatus.Select( - x => new - { - x.EnrolledMonth, - x.EnrolledYear, - x.FirstName, - x.LastName, - Email = (Guid.TryParse(x.Email, out _) ? string.Empty : x.Email), - x.CentreField1, - x.CentreField2, - x.CentreField3, - x.Status - } - ); - var details = outcomeSummary.Select( - x => new - { - x.EnrolledMonth, - x.EnrolledYear, - x.JobGroup, - x.CentreField1, - x.CentreField2, - x.CentreField3, - x.Status, - x.LearningLaunched, - x.LearningCompleted, - x.DataInformationAndContentConfidence, - x.DataInformationAndContentRelevance, - x.TeachinglearningAndSelfDevelopmentConfidence, - x.TeachinglearningAndSelfDevelopmentRelevance, - x.CommunicationCollaborationAndParticipationConfidence, - x.CommunicationCollaborationAndParticipationRelevance, - x.TechnicalProficiencyConfidence, - x.TechnicalProficiencyRelevance, - x.CreationInnovationAndResearchConfidence, - x.CreationInnovationAndResearchRelevance, - x.DigitalIdentityWellbeingSafetyAndSecurityConfidence, - x.DigitalIdentityWellbeingSafetyAndSecurityRelevance - } - ); - using var workbook = new XLWorkbook(); - AddSheetToWorkbook(workbook, "Delegate Completion Status", summary); - AddSheetToWorkbook(workbook, "Assessment Outcome Summary", outcomeSummary); - using var stream = new MemoryStream(); - workbook.SaveAs(stream); - return stream.ToArray(); - } - } - -} +namespace DigitalLearningSolutions.Data.Services +{ + using ClosedXML.Excel; + using DigitalLearningSolutions.Data.DataServices.SelfAssessmentDataService; + using DigitalLearningSolutions.Data.Models.CustomPrompts; + using DigitalLearningSolutions.Data.Models.SelfAssessments; + using DigitalLearningSolutions.Data.Models.SelfAssessments.Export; + using DigitalLearningSolutions.Web.Services; + using System; + using System.Collections.Generic; + using System.Data; + using System.IO; + using System.Linq; + + public interface ISelfAssessmentReportService + { + byte[] GetSelfAssessmentExcelExportForCentre(int centreId, int selfAssessmentId); + byte[] GetDigitalCapabilityExcelExportForCentre(int centreId); + IEnumerable GetSelfAssessmentsForReportList(int centreId, int? categoryId); + } + public class SelfAssessmentReportService : ISelfAssessmentReportService + { + private const string SelfAssessment = "SelfAssessment"; + private const string Learner = "Leaner"; + private const string LearnerActive = "LearnerActive"; + private const string PRN = "PRN"; + private const string JobGroup = "JobGroup"; + private const string OtherCentres = "OtherCentres"; + private const string DLSRole = "DLSRole"; + private const string Registered = "Registered"; + private const string Started = "Started"; + private const string LastAccessed = "LastAccessed"; + private const string OptionalProficienciesAssessed = "OptionalProficienciesAssessed"; + private const string SelfAssessedAchieved = "SelfAssessedAchieved"; + private const string ConfirmedResults = "ConfirmedResults"; + private const string SignOffRequested = "SignOffRequested"; + private const string SignOffAchieved = "SignOffAchieved"; + private const string ReviewedDate = "ReviewedDate"; + + private readonly IDCSAReportDataService dcsaReportDataService; + private readonly ISelfAssessmentReportDataService selfAssessmentReportDataService; + private readonly ICentreRegistrationPromptsService registrationPromptsService; + public SelfAssessmentReportService( + IDCSAReportDataService dcsaReportDataService, + ISelfAssessmentReportDataService selfAssessmentReportDataService, + ICentreRegistrationPromptsService registrationPromptsService + ) + { + this.dcsaReportDataService = dcsaReportDataService; + this.selfAssessmentReportDataService = selfAssessmentReportDataService; + this.registrationPromptsService = registrationPromptsService; + } + private static void AddSheetToWorkbook(IXLWorkbook workbook, string sheetName, IEnumerable? dataObjects) + { + var sheet = workbook.Worksheets.Add(sheetName); + var table = sheet.Cell(1, 1).InsertTable(dataObjects); + table.Theme = XLTableTheme.TableStyleLight9; + sheet.Columns().AdjustToContents(); + } + + public IEnumerable GetSelfAssessmentsForReportList(int centreId, int? categoryId) + { + return selfAssessmentReportDataService.GetSelfAssessmentsForReportList(centreId, categoryId); + } + + public byte[] GetSelfAssessmentExcelExportForCentre(int centreId, int selfAssessmentId) + { + using var workbook = new XLWorkbook(); + var selfAssessmentReportData = selfAssessmentReportDataService.GetSelfAssessmentReportDataForCentre(centreId, selfAssessmentId); + PopulateSelfAssessmentSheetForCentre(workbook, centreId, selfAssessmentReportData); + using var stream = new MemoryStream(); + workbook.SaveAs(stream); + return stream.ToArray(); + } + public byte[] GetDigitalCapabilityExcelExportForCentre(int centreId) + { + var delegateCompletionStatus = dcsaReportDataService.GetDelegateCompletionStatusForCentre(centreId); + var outcomeSummary = dcsaReportDataService.GetOutcomeSummaryForCentre(centreId); + var summary = delegateCompletionStatus.Select( + x => new + { + x.EnrolledMonth, + x.EnrolledYear, + x.FirstName, + x.LastName, + Email = (Guid.TryParse(x.Email, out _) ? string.Empty : x.Email), + x.CentreField1, + x.CentreField2, + x.CentreField3, + x.Status + } + ); + var details = outcomeSummary.Select( + x => new + { + x.EnrolledMonth, + x.EnrolledYear, + x.JobGroup, + x.CentreField1, + x.CentreField2, + x.CentreField3, + x.Status, + x.LearningLaunched, + x.LearningCompleted, + x.DataInformationAndContentConfidence, + x.DataInformationAndContentRelevance, + x.TeachinglearningAndSelfDevelopmentConfidence, + x.TeachinglearningAndSelfDevelopmentRelevance, + x.CommunicationCollaborationAndParticipationConfidence, + x.CommunicationCollaborationAndParticipationRelevance, + x.TechnicalProficiencyConfidence, + x.TechnicalProficiencyRelevance, + x.CreationInnovationAndResearchConfidence, + x.CreationInnovationAndResearchRelevance, + x.DigitalIdentityWellbeingSafetyAndSecurityConfidence, + x.DigitalIdentityWellbeingSafetyAndSecurityRelevance + } + ); + using var workbook = new XLWorkbook(); + AddSheetToWorkbook(workbook, "Delegate Completion Status", summary); + AddSheetToWorkbook(workbook, "Assessment Outcome Summary", outcomeSummary); + using var stream = new MemoryStream(); + workbook.SaveAs(stream); + return stream.ToArray(); + } + + private void PopulateSelfAssessmentSheetForCentre(IXLWorkbook workbook, int centreId, IEnumerable selfAssessmentReportData) + { + var sheet = workbook.Worksheets.Add("SelfAssessmentLearners"); + // Set sheet to have outlining expand buttons at the top of the expanded section. + sheet.Outline.SummaryVLocation = XLOutlineSummaryVLocation.Top; + var customRegistrationPrompts = + registrationPromptsService.GetCentreRegistrationPromptsByCentreId(centreId); + var dataTable = new DataTable(); + + // did this to sequqence the element into a new form based on the order below + var reportData = selfAssessmentReportData.Select( + x => new + { + x.SelfAssessment, + x.Learner, + x.LearnerActive, + x.PRN, + x.JobGroup, + x.OtherCentres, + x.DLSRole, + x.Registered, + x.Started, + x.LastAccessed, + x.OptionalProficienciesAssessed, + x.SelfAssessedAchieved, + x.ConfirmedResults, + x.SignOffRequested, + x.SignOffAchieved, + x.ReviewedDate + } + ); + + // set the common header table for the excel sheet + SetUpCommonTableColumnsForSelfAssessment(customRegistrationPrompts, dataTable); + + // insert the header table into the sheet starting at the first position + var headerTable = sheet.Cell(1, 1).InsertTable(dataTable); + + foreach (var report in selfAssessmentReportData) + { + //iterate and add every record from the query to the datatable + AddSelfAssessmentReportToSheet(sheet, dataTable, customRegistrationPrompts, report); + } + + var insertedDataRange = sheet.Cell(GetNextEmptyRowNumber(sheet), 1).InsertData(dataTable.Rows); + if (dataTable.Rows.Count > 0) + { + sheet.Rows(insertedDataRange.FirstRow().RowNumber(), insertedDataRange.LastRow().RowNumber()) + .Group(true); + } + + //format the sheet rows and content + sheet.Rows().Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center; + headerTable.Theme = XLTableTheme.TableStyleLight9; + + sheet.Columns().AdjustToContents(); + } + + private static void SetUpCommonTableColumnsForSelfAssessment(CentreRegistrationPrompts centreRegistrationPrompts, DataTable dataTable) + { + dataTable.Columns.AddRange( + new[] {new DataColumn(SelfAssessment), new DataColumn(Learner), new DataColumn(LearnerActive), new DataColumn(PRN), + new DataColumn(JobGroup)} + ); + foreach (var prompt in centreRegistrationPrompts.CustomPrompts) + { + dataTable.Columns.Add( + !dataTable.Columns.Contains(prompt.PromptText) + ? prompt.PromptText + : $"{prompt.PromptText} (Prompt {prompt.RegistrationField.Id})" + ); + } + + dataTable.Columns.AddRange( + new[] + { + new DataColumn(OtherCentres), + new DataColumn(DLSRole), + new DataColumn(Registered), + new DataColumn(Started), + new DataColumn(LastAccessed), + new DataColumn(OptionalProficienciesAssessed), + new DataColumn(SelfAssessedAchieved), + new DataColumn(ConfirmedResults), + new DataColumn(SignOffRequested), + new DataColumn(SignOffAchieved), + new DataColumn(ReviewedDate) + } + ); + } + + private static void AddSelfAssessmentReportToSheet(IXLWorksheet sheet, DataTable dataTable, CentreRegistrationPrompts centreRegistrationPrompts, + SelfAssessmentReportData report) + { + var row = dataTable.NewRow(); + row[SelfAssessment] = report.SelfAssessment; + row[Learner] = report.Learner; + row[LearnerActive] = report.LearnerActive; + row[PRN] = report.PRN; + row[JobGroup] = report.JobGroup; + + // map the individual registration fields with the centre registration custom prompts + foreach (var prompt in centreRegistrationPrompts.CustomPrompts) + { + if (dataTable.Columns.Contains($"{prompt.PromptText} (Prompt {prompt.RegistrationField.Id})")) + { + row[$"{prompt.PromptText} (Prompt {prompt.RegistrationField.Id})"] = + report.CentreRegistrationPrompts[prompt.RegistrationField.Id - 1]; + } + else + { + row[prompt.PromptText] = + report.CentreRegistrationPrompts[prompt.RegistrationField.Id - 1]; + } + } + row[OtherCentres] = report.OtherCentres; + row[DLSRole] = report.DLSRole; + row[Registered] = report.Registered?.ToString("dd/MM/yyyy"); + row[Started] = report.Started?.ToString("dd/MM/yyyy"); + row[LastAccessed] = report.LastAccessed?.ToString("dd/MM/yyyy"); + row[OptionalProficienciesAssessed] = report.OptionalProficienciesAssessed; + row[SelfAssessedAchieved] = report.SelfAssessedAchieved; + row[ConfirmedResults] = report.ConfirmedResults; + row[SignOffRequested] = report.SignOffRequested?.ToString("dd/MM/yyyy"); + row[SignOffAchieved] = report.SignOffAchieved ? "Yes" : "No"; + row[ReviewedDate] = report.ReviewedDate?.ToString("dd/MM/yyyy"); + dataTable.Rows.Add(row); + } + + private static int GetNextEmptyRowNumber(IXLWorksheet sheet) + { + return sheet.LastRowUsed().RowNumber() + 1; + } + } +} diff --git a/DigitalLearningSolutions.Web/Services/SupervisorService.cs b/DigitalLearningSolutions.Web/Services/SupervisorService.cs index 8cd8d2e16e..5a6dd5685f 100644 --- a/DigitalLearningSolutions.Web/Services/SupervisorService.cs +++ b/DigitalLearningSolutions.Web/Services/SupervisorService.cs @@ -1,5 +1,5 @@ using DigitalLearningSolutions.Data.DataServices; -using DigitalLearningSolutions.Data.Models.RoleProfiles; +using DigitalLearningSolutions.Data.Models.CompetencyAssessments; using DigitalLearningSolutions.Data.Models.SelfAssessments; using DigitalLearningSolutions.Data.Models.Supervisor; using System; @@ -20,8 +20,8 @@ public interface ISupervisorService IEnumerable GetSupervisorDashboardToDoItemsForRequestedSignOffs(int adminId); IEnumerable GetSupervisorDashboardToDoItemsForRequestedReviews(int adminId); DelegateSelfAssessment? GetSelfAssessmentBaseByCandidateAssessmentId(int candidateAssessmentId, int? adminIdCategoryId); - IEnumerable GetAvailableRoleProfilesForDelegate(int candidateId, int centreId, int? categoryId); - RoleProfile? GetRoleProfileById(int selfAssessmentId); + IEnumerable GetAvailableCompetencyAssessmentsForDelegate(int candidateId, int centreId, int? categoryId); + CompetencyAssessment? GetCompetencyAssessmentById(int selfAssessmentId); IEnumerable GetSupervisorRolesForSelfAssessment(int selfAssessmentId); IEnumerable GetSupervisorRolesBySelfAssessmentIdForSupervisor(int selfAssessmentId); IEnumerable GetDelegateNominatableSupervisorRolesForSelfAssessment(int selfAssessmentId); @@ -80,9 +80,9 @@ public int EnrolDelegateOnAssessment(int delegateUserId, int supervisorDelegateI return supervisorDataService.EnrolDelegateOnAssessment(delegateUserId, supervisorDelegateId, selfAssessmentId, completeByDate, selfAssessmentSupervisorRoleId, adminId, centreId, isLoggedInUser); } - public IEnumerable GetAvailableRoleProfilesForDelegate(int candidateId, int centreId, int? categoryId) + public IEnumerable GetAvailableCompetencyAssessmentsForDelegate(int candidateId, int centreId, int? categoryId) { - return supervisorDataService.GetAvailableRoleProfilesForDelegate(candidateId, centreId, categoryId); + return supervisorDataService.GetAvailableCompetencyAssessmentsForDelegate(candidateId, centreId, categoryId); } public CandidateAssessmentSupervisor? GetCandidateAssessmentSupervisor(int candidateAssessmentID, int supervisorDelegateId, int selfAssessmentSupervisorRoleId) @@ -110,9 +110,9 @@ public IEnumerable GetDelegateNominatableSuperviso return supervisorDataService.GetDelegateNominatableSupervisorRolesForSelfAssessment(selfAssessmentId); } - public RoleProfile? GetRoleProfileById(int selfAssessmentId) + public CompetencyAssessment? GetCompetencyAssessmentById(int selfAssessmentId) { - return supervisorDataService.GetRoleProfileById(selfAssessmentId); + return supervisorDataService.GetCompetencyAssessmentById(selfAssessmentId); } public DelegateSelfAssessment? GetSelfAssessmentBaseByCandidateAssessmentId(int candidateAssessmentId, int? adminIdCategoryId) diff --git a/DigitalLearningSolutions.Web/Startup.cs b/DigitalLearningSolutions.Web/Startup.cs index bdc34b4d79..09340c861d 100644 --- a/DigitalLearningSolutions.Web/Startup.cs +++ b/DigitalLearningSolutions.Web/Startup.cs @@ -434,7 +434,7 @@ private static void RegisterServices(IServiceCollection services) services.AddScoped(); services.AddScoped(); services.AddScoped(); - services.AddScoped(); + services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); @@ -507,7 +507,7 @@ private static void RegisterDataServices(IServiceCollection services) services.AddScoped(); services.AddScoped(); services.AddScoped(); - services.AddScoped(); + services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); @@ -534,6 +534,7 @@ private static void RegisterDataServices(IServiceCollection services) services.AddScoped(); services.AddScoped(); services.AddScoped(); + services.AddScoped(); } private static void RegisterHelpers(IServiceCollection services) diff --git a/DigitalLearningSolutions.Web/Styles/jodit.scss b/DigitalLearningSolutions.Web/Styles/jodit.scss index 076a7f0053..416099e8f7 100644 --- a/DigitalLearningSolutions.Web/Styles/jodit.scss +++ b/DigitalLearningSolutions.Web/Styles/jodit.scss @@ -4,3 +4,6 @@ border: 2px solid red !important; border-radius: 4px; } +.jodit-placeholder { + display: none !important; +} diff --git a/DigitalLearningSolutions.Web/Styles/trackingSystem/delegates/courseDelegates.scss b/DigitalLearningSolutions.Web/Styles/trackingSystem/delegates/courseDelegates.scss index 3f796924e8..47fb8f20d5 100644 --- a/DigitalLearningSolutions.Web/Styles/trackingSystem/delegates/courseDelegates.scss +++ b/DigitalLearningSolutions.Web/Styles/trackingSystem/delegates/courseDelegates.scss @@ -26,3 +26,31 @@ } } } + +.nhsuk-expander[open] details.nhsuk-details[open] .nhsuk-details__summary-text::before { + display: block; + width: 0; + height: 0; + border-style: solid; + border-color: transparent; + clip-path: polygon(0% 0%, 50% 100%, 100% 0%); + border-width: 12.124px 7px 0 7px; + border-top-color: inherit; +} + +.nhsuk-details[open] .nhsuk-details .nhsuk-details__summary-text::before { + bottom: 0; + content: ""; + left: 0; + margin: auto; + position: absolute; + top: 0; + display: block; + width: 0; + height: 0; + border-style: solid; + border-color: transparent; + clip-path: polygon(0% 0%, 100% 50%, 0% 100%); + border-width: 7px 0 7px 12.124px; + border-left-color: inherit; +} diff --git a/DigitalLearningSolutions.Web/ViewComponents/DlsFooterBannerTextViewComponent.cs b/DigitalLearningSolutions.Web/ViewComponents/DlsFooterBannerTextViewComponent.cs new file mode 100644 index 0000000000..bf484f426e --- /dev/null +++ b/DigitalLearningSolutions.Web/ViewComponents/DlsFooterBannerTextViewComponent.cs @@ -0,0 +1,34 @@ +using System.Security.Claims; +using DigitalLearningSolutions.Data.DataServices; +using DigitalLearningSolutions.Web.Helpers; +using Microsoft.AspNetCore.Mvc; +using DigitalLearningSolutions.Web.ViewModels.Common.ViewComponents; +using DigitalLearningSolutions.Web.Services; +using System; +using System.Threading.Tasks; + +namespace DigitalLearningSolutions.Web.ViewComponents +{ + public class DlsFooterBannerTextViewComponent : ViewComponent + { + private readonly ICentresService centresService; + + public DlsFooterBannerTextViewComponent(ICentresService centresService) + { + this.centresService = centresService; + } + + public IViewComponentResult Invoke() + { + var centreId = ((ClaimsPrincipal)User).GetCustomClaimAsInt(CustomClaimTypes.UserCentreId); + if (centreId == null) + { + return View(new DlsFooterBannerTextViewModel(null)); + } + + var bannerText = centresService.GetBannerText(Convert.ToInt32(centreId)); + var model = new DlsFooterBannerTextViewModel(bannerText); + return View(model); + } + } +} diff --git a/DigitalLearningSolutions.Web/ViewModels/Common/ViewComponents/DlsFooterBannerTextViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/Common/ViewComponents/DlsFooterBannerTextViewModel.cs new file mode 100644 index 0000000000..3a0fdcdd92 --- /dev/null +++ b/DigitalLearningSolutions.Web/ViewModels/Common/ViewComponents/DlsFooterBannerTextViewModel.cs @@ -0,0 +1,13 @@ +namespace DigitalLearningSolutions.Web.ViewModels.Common.ViewComponents +{ + public class DlsFooterBannerTextViewModel + { + public readonly string? BannerText; + + public DlsFooterBannerTextViewModel(string bannerText) + { + BannerText = bannerText; + } + + } +} diff --git a/DigitalLearningSolutions.Web/ViewModels/CompetencyAssessments/AllCompetencyAssessmentsViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/CompetencyAssessments/AllCompetencyAssessmentsViewModel.cs new file mode 100644 index 0000000000..a858706127 --- /dev/null +++ b/DigitalLearningSolutions.Web/ViewModels/CompetencyAssessments/AllCompetencyAssessmentsViewModel.cs @@ -0,0 +1,42 @@ +namespace DigitalLearningSolutions.Web.ViewModels.CompetencyAssessments +{ + using System.Collections.Generic; + using System.Linq; + using DigitalLearningSolutions.Data.Models.CompetencyAssessments; + using DigitalLearningSolutions.Web.Helpers; + using Microsoft.AspNetCore.Mvc.Rendering; + public class AllCompetencyAssessmentsViewModel : BaseCompetencyAssessmentsPageViewModel + { + public readonly IEnumerable CompetencyAssessments; + public readonly bool IsWorkforceManager; + public override SelectList CompetencyAssessmentSortByOptions { get; } = new SelectList(new[] + { + CompetencyAssessmentSortByOptionTexts.CompetencyAssessmentName, + CompetencyAssessmentSortByOptionTexts.CompetencyAssessmentOwner, + CompetencyAssessmentSortByOptionTexts.CompetencyAssessmentCreatedDate, + CompetencyAssessmentSortByOptionTexts.CompetencyAssessmentPublishStatus, + CompetencyAssessmentSortByOptionTexts.CompetencyAssessmentBrand, + CompetencyAssessmentSortByOptionTexts.CompetencyAssessmentNationalRoleGroup, + CompetencyAssessmentSortByOptionTexts.CompetencyAssessmentNationalCompetencyAssessment + }); + public AllCompetencyAssessmentsViewModel( + IEnumerable competencyAssessments, + string? searchString, + string sortBy, + string sortDirection, + int page + ) : base(searchString, sortBy, sortDirection, page) + { + var sortedItems = SortingHelper.SortCompetencyAssessmentItems( + competencyAssessments, + sortBy, + sortDirection + ); + var filteredItems = SearchHelper.FilterCompetencyAssessments(sortedItems, SearchString, 60, false).ToList(); + MatchingSearchResults = filteredItems.Count; + SetTotalPages(); + CompetencyAssessments = PaginateItems(filteredItems).Cast(); + } + } +} + diff --git a/DigitalLearningSolutions.Web/ViewModels/RoleProfiles/BaseRoleProfileViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/CompetencyAssessments/BaseCompetencyAssessmentsPageViewModel.cs similarity index 61% rename from DigitalLearningSolutions.Web/ViewModels/RoleProfiles/BaseRoleProfileViewModel.cs rename to DigitalLearningSolutions.Web/ViewModels/CompetencyAssessments/BaseCompetencyAssessmentsPageViewModel.cs index 0b5fa8d753..01a65ba1ca 100644 --- a/DigitalLearningSolutions.Web/ViewModels/RoleProfiles/BaseRoleProfileViewModel.cs +++ b/DigitalLearningSolutions.Web/ViewModels/CompetencyAssessments/BaseCompetencyAssessmentsPageViewModel.cs @@ -1,71 +1,71 @@ -namespace DigitalLearningSolutions.Web.ViewModels.RoleProfiles -{ - using System; - using System.Collections.Generic; - using System.Linq; - using DigitalLearningSolutions.Data.Models.RoleProfiles; - using Microsoft.AspNetCore.Mvc; - using Microsoft.AspNetCore.Mvc.Rendering; - - public abstract class BaseRoleProfilesPageViewModel - { - [BindProperty] public string SortDirection { get; set; } - [BindProperty] public string SortBy { get; set; } - public int Page { get; protected set; } - public int TotalPages { get; protected set; } - public int MatchingSearchResults; - public abstract SelectList RoleProfileSortByOptions { get; } - - public const string DescendingText = "Descending"; - public const string AscendingText = "Ascending"; - - private const int ItemsPerPage = 12; - - public readonly string? SearchString; - - protected BaseRoleProfilesPageViewModel( - string? searchString, - string sortBy, - string sortDirection, - int page - ) - { - SortBy = sortBy; - SortDirection = sortDirection; - SearchString = searchString; - Page = page; - } - protected IEnumerable PaginateItems(IList items) - { - if (items.Count > ItemsPerPage) - { - items = items.Skip(OffsetFromPageNumber(Page)).Take(ItemsPerPage).ToList(); - } - - return items; - } - protected void SetTotalPages() - { - TotalPages = (int)Math.Ceiling(MatchingSearchResults / (double)ItemsPerPage); - if (Page < 1 || Page > TotalPages) - { - Page = 1; - } - } - - private int OffsetFromPageNumber(int pageNumber) => - (pageNumber - 1) * ItemsPerPage; - } - - public static class RoleProfileSortByOptionTexts - { - public const string - RoleProfileName = "Profile Name", - RoleProfileOwner = "Owner", - RoleProfileCreatedDate = "Created Date", - RoleProfilePublishStatus = "Publish Status", - RoleProfileBrand = "Brand", - RoleProfileNationalRoleGroup = "National Job Group", - RoleProfileNationalRoleProfile = "National Job Profile"; - } -} +namespace DigitalLearningSolutions.Web.ViewModels.CompetencyAssessments +{ + using System; + using System.Collections.Generic; + using System.Linq; + using DigitalLearningSolutions.Data.Models.CompetencyAssessments; + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.Rendering; + + public abstract class BaseCompetencyAssessmentsPageViewModel + { + [BindProperty] public string SortDirection { get; set; } + [BindProperty] public string SortBy { get; set; } + public int Page { get; protected set; } + public int TotalPages { get; protected set; } + public int MatchingSearchResults; + public abstract SelectList CompetencyAssessmentSortByOptions { get; } + + public const string DescendingText = "Descending"; + public const string AscendingText = "Ascending"; + + private const int ItemsPerPage = 12; + + public readonly string? SearchString; + + protected BaseCompetencyAssessmentsPageViewModel( + string? searchString, + string sortBy, + string sortDirection, + int page + ) + { + SortBy = sortBy; + SortDirection = sortDirection; + SearchString = searchString; + Page = page; + } + protected IEnumerable PaginateItems(IList items) + { + if (items.Count > ItemsPerPage) + { + items = items.Skip(OffsetFromPageNumber(Page)).Take(ItemsPerPage).ToList(); + } + + return items; + } + protected void SetTotalPages() + { + TotalPages = (int)Math.Ceiling(MatchingSearchResults / (double)ItemsPerPage); + if (Page < 1 || Page > TotalPages) + { + Page = 1; + } + } + + private int OffsetFromPageNumber(int pageNumber) => + (pageNumber - 1) * ItemsPerPage; + } + + public static class CompetencyAssessmentSortByOptionTexts + { + public const string + CompetencyAssessmentName = "Competency Assessment", + CompetencyAssessmentOwner = "Owner", + CompetencyAssessmentCreatedDate = "Created Date", + CompetencyAssessmentPublishStatus = "Publish Status", + CompetencyAssessmentBrand = "Brand", + CompetencyAssessmentNationalRoleGroup = "National Job Group", + CompetencyAssessmentNationalCompetencyAssessment = "National Job Profile"; + } +} diff --git a/DigitalLearningSolutions.Web/ViewModels/CompetencyAssessments/CompetencyAssessmentsViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/CompetencyAssessments/CompetencyAssessmentsViewModel.cs new file mode 100644 index 0000000000..f091a7dd76 --- /dev/null +++ b/DigitalLearningSolutions.Web/ViewModels/CompetencyAssessments/CompetencyAssessmentsViewModel.cs @@ -0,0 +1,29 @@ +namespace DigitalLearningSolutions.Web.ViewModels.CompetencyAssessments +{ + using DigitalLearningSolutions.Web.Models.Enums; + using DigitalLearningSolutions.Web.ViewModels.Common; + + public class CompetencyAssessmentsViewModel + { + public CompetencyAssessmentsViewModel( + bool isWorkforceManager, + bool isWorkforceContributor, + AllCompetencyAssessmentsViewModel allCompetencyAssessments, + MyCompetencyAssessmentsViewModel myCompetencyAssessments, + CompetencyAssessmentsTab currentTab + ) + { + IsWorkforceManager = isWorkforceManager; + IsWorkforceContributor = isWorkforceContributor; + MyCompetencyAssessmentsViewModel = myCompetencyAssessments; + AllCompetencyAssessmentsViewModel = allCompetencyAssessments; + TabNavLinks = new TabsNavViewModel(currentTab); + } + + public bool IsWorkforceManager { get; set; } + public bool IsWorkforceContributor { get; set; } + public MyCompetencyAssessmentsViewModel MyCompetencyAssessmentsViewModel { get; set; } + public AllCompetencyAssessmentsViewModel AllCompetencyAssessmentsViewModel { get; set; } + public TabsNavViewModel TabNavLinks { get; set; } + } +} diff --git a/DigitalLearningSolutions.Web/ViewModels/CompetencyAssessments/ConfirmRemoveFrameworkSourceViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/CompetencyAssessments/ConfirmRemoveFrameworkSourceViewModel.cs new file mode 100644 index 0000000000..1a4e78cc79 --- /dev/null +++ b/DigitalLearningSolutions.Web/ViewModels/CompetencyAssessments/ConfirmRemoveFrameworkSourceViewModel.cs @@ -0,0 +1,29 @@ +using DigitalLearningSolutions.Data.Models.CompetencyAssessments; +using DigitalLearningSolutions.Data.Models.Frameworks; +using DigitalLearningSolutions.Web.Attributes; + +namespace DigitalLearningSolutions.Web.ViewModels.CompetencyAssessments +{ + public class ConfirmRemoveFrameworkSourceViewModel + { + public ConfirmRemoveFrameworkSourceViewModel() { } + public ConfirmRemoveFrameworkSourceViewModel(CompetencyAssessmentBase competencyAssessmentBase, DetailFramework framework, int competencyCount) + { + CompetencyAssessmentId = competencyAssessmentBase.ID; + CompetencyCount = competencyCount; + AssessmentName = competencyAssessmentBase.CompetencyAssessmentName; + FrameworkName = framework.FrameworkName; + FrameworkId = framework.ID; + Vocabulary = competencyAssessmentBase.Vocabulary; + } + public int CompetencyAssessmentId { get; set; } + public string? AssessmentName { get; set; } + public string? FrameworkName { get; set; } + public int FrameworkId { get; set; } + public int CompetencyCount { get; set; } + public string? Vocabulary { get; set; } + [BooleanMustBeTrue(ErrorMessage = "You must confirm that you wish to remove this framework")] + public bool Confirm { get; set; } + + } +} diff --git a/DigitalLearningSolutions.Web/ViewModels/CompetencyAssessments/EditBrandingViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/CompetencyAssessments/EditBrandingViewModel.cs new file mode 100644 index 0000000000..b9b671c7d1 --- /dev/null +++ b/DigitalLearningSolutions.Web/ViewModels/CompetencyAssessments/EditBrandingViewModel.cs @@ -0,0 +1,33 @@ +using DigitalLearningSolutions.Data.Models.CompetencyAssessments; +using Microsoft.AspNetCore.Mvc.Rendering; + +namespace DigitalLearningSolutions.Web.ViewModels.CompetencyAssessments +{ + public class EditBrandingViewModel + { + public EditBrandingViewModel() { } + public EditBrandingViewModel(CompetencyAssessment competencyAssessment, SelectList brandSelectList, SelectList categorySelectList, bool? taskStatus) + { + ID = competencyAssessment.ID; + CompetencyAssessmentName = competencyAssessment.CompetencyAssessmentName; + BrandID = competencyAssessment.BrandID; + CategoryID = competencyAssessment.CategoryID; + Brand = competencyAssessment.Brand; + Category = competencyAssessment.Category; + UserRole = competencyAssessment.UserRole; + BrandSelectList = brandSelectList; + CategorySelectList = categorySelectList; + TaskStatus = taskStatus; + } + public int ID { get; set; } + public string CompetencyAssessmentName { get; set; } + public int BrandID { get; set; } + public int CategoryID { get; set; } + public string? Brand { get; set; } + public string? Category { get; set; } + public int UserRole { get; set; } + public bool? TaskStatus { get; set; } + public SelectList? BrandSelectList { get; set; } + public SelectList? CategorySelectList { get; set; } + } +} diff --git a/DigitalLearningSolutions.Web/ViewModels/CompetencyAssessments/EditDescriptionViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/CompetencyAssessments/EditDescriptionViewModel.cs new file mode 100644 index 0000000000..fcb36e370f --- /dev/null +++ b/DigitalLearningSolutions.Web/ViewModels/CompetencyAssessments/EditDescriptionViewModel.cs @@ -0,0 +1,22 @@ +using DigitalLearningSolutions.Data.Models.CompetencyAssessments; + +namespace DigitalLearningSolutions.Web.ViewModels.CompetencyAssessments +{ + public class EditDescriptionViewModel + { + public EditDescriptionViewModel() { } + public EditDescriptionViewModel(CompetencyAssessmentBase competencyAssessmentBase, bool? taskStatus) + { + ID = competencyAssessmentBase.ID; + CompetencyAssessmentName = competencyAssessmentBase.CompetencyAssessmentName; + Description = competencyAssessmentBase.Description; + UserRole = competencyAssessmentBase.UserRole; + TaskStatus = taskStatus; + } + public int ID { get; set; } + public string CompetencyAssessmentName { get; set; } = string.Empty; + public string? Description { get; set; } + public int UserRole { get; set; } + public bool? TaskStatus { get; set; } + } +} diff --git a/DigitalLearningSolutions.Web/ViewModels/CompetencyAssessments/EditRoleProfileLinksViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/CompetencyAssessments/EditRoleProfileLinksViewModel.cs new file mode 100644 index 0000000000..54ddd177b5 --- /dev/null +++ b/DigitalLearningSolutions.Web/ViewModels/CompetencyAssessments/EditRoleProfileLinksViewModel.cs @@ -0,0 +1,43 @@ +namespace DigitalLearningSolutions.Web.ViewModels.CompetencyAssessments +{ + using DigitalLearningSolutions.Data.Models.CompetencyAssessments; + using Humanizer; + using System.Collections.Generic; + using System.Linq; + + public class EditRoleProfileLinksViewModel + { + public EditRoleProfileLinksViewModel() { } + public EditRoleProfileLinksViewModel(CompetencyAssessmentBase competencyAssessmentBase, IEnumerable professionalGroups, IEnumerable subGroups, IEnumerable roles, string actionName, bool? taskStatus) + { + ID = competencyAssessmentBase.ID; + CompetencyAssessmentName = competencyAssessmentBase.CompetencyAssessmentName; + ProfessionalGroupId = competencyAssessmentBase.NRPProfessionalGroupID; + SubGroupId = competencyAssessmentBase.NRPSubGroupID; + RoleId = competencyAssessmentBase.NRPRoleID; + UserRole = competencyAssessmentBase.UserRole; + TaskStatus = taskStatus; + ProfessionalGroups = professionalGroups; + SubGroups = subGroups; + Roles = roles; + ActionName = actionName; + RoleName = Roles.FirstOrDefault(r => r.ID == RoleId)?.ProfileName ?? "Don't link assessment to a role."; + SubGroupName = SubGroups.FirstOrDefault(s => s.ID == SubGroupId)?.SubGroup ?? "Don't link assessment to a sub group."; + GroupName = ProfessionalGroups.FirstOrDefault(p => p.ID == ProfessionalGroupId)?.ProfessionalGroup ?? "Don't link assessment to a professional group."; + } + public IEnumerable ProfessionalGroups { get; set; } + public IEnumerable SubGroups { get; set; } + public IEnumerable Roles { get; set; } + public int ID { get; set; } + public string CompetencyAssessmentName { get; set; } + public string ActionName { get; set; } + public int? ProfessionalGroupId { get; set; } + public int? SubGroupId { get; set; } + public int? RoleId { get; set; } + public int UserRole { get; set; } + public bool? TaskStatus { get; set; } + public string? GroupName { get; set; } + public string? SubGroupName { get; set; } + public string? RoleName { get; set; } + } +} diff --git a/DigitalLearningSolutions.Web/ViewModels/CompetencyAssessments/EditVocabularyViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/CompetencyAssessments/EditVocabularyViewModel.cs new file mode 100644 index 0000000000..c68c90f85e --- /dev/null +++ b/DigitalLearningSolutions.Web/ViewModels/CompetencyAssessments/EditVocabularyViewModel.cs @@ -0,0 +1,24 @@ +using DigitalLearningSolutions.Data.Models.CompetencyAssessments; +using System.ComponentModel.DataAnnotations; + +namespace DigitalLearningSolutions.Web.ViewModels.CompetencyAssessments +{ + public class EditVocabularyViewModel + { + public EditVocabularyViewModel() { } + public EditVocabularyViewModel(CompetencyAssessmentBase competencyAssessmentBase, bool? taskStatus) + { + ID = competencyAssessmentBase.ID; + CompetencyAssessmentName = competencyAssessmentBase.CompetencyAssessmentName; + Vocabulary = competencyAssessmentBase.Vocabulary; + UserRole = competencyAssessmentBase.UserRole; + TaskStatus = taskStatus; + } + public int ID { get; set; } + public string CompetencyAssessmentName { get; set; } = string.Empty; + [Required(ErrorMessage = "Select a vocabulary option")] + public string Vocabulary { get; set; } + public int UserRole { get; set; } + public bool? TaskStatus { get; set; } + } +} diff --git a/DigitalLearningSolutions.Web/ViewModels/CompetencyAssessments/ManageCompetencyAssessmentViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/CompetencyAssessments/ManageCompetencyAssessmentViewModel.cs new file mode 100644 index 0000000000..a4a3f41115 --- /dev/null +++ b/DigitalLearningSolutions.Web/ViewModels/CompetencyAssessments/ManageCompetencyAssessmentViewModel.cs @@ -0,0 +1,24 @@ +using DigitalLearningSolutions.Data.Models.CompetencyAssessments; + +namespace DigitalLearningSolutions.Web.ViewModels.CompetencyAssessments +{ + public class ManageCompetencyAssessmentViewModel + { + public ManageCompetencyAssessmentViewModel( + CompetencyAssessmentBase competencyAssessmentBase, + CompetencyAssessmentTaskStatus competencyAssessmentTaskStatus + ) + { + CompetencyAssessmentName = competencyAssessmentBase.CompetencyAssessmentName; + PublishStatusID = competencyAssessmentBase.PublishStatusID; + UserRole = competencyAssessmentBase.UserRole; + CompetencyAssessmentTaskStatus = competencyAssessmentTaskStatus; + Vocabulary = competencyAssessmentBase.Vocabulary; + } + public string CompetencyAssessmentName { get; set; } + public int PublishStatusID { get; set; } + public int UserRole { get; set; } + public string? Vocabulary { get; set; } + public CompetencyAssessmentTaskStatus CompetencyAssessmentTaskStatus { get; set; } + } +} diff --git a/DigitalLearningSolutions.Web/ViewModels/CompetencyAssessments/MyCompetencyAssessmentsViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/CompetencyAssessments/MyCompetencyAssessmentsViewModel.cs new file mode 100644 index 0000000000..ec2cf74500 --- /dev/null +++ b/DigitalLearningSolutions.Web/ViewModels/CompetencyAssessments/MyCompetencyAssessmentsViewModel.cs @@ -0,0 +1,43 @@ +namespace DigitalLearningSolutions.Web.ViewModels.CompetencyAssessments +{ + using System.Collections.Generic; + using System.Linq; + using DigitalLearningSolutions.Data.Models.CompetencyAssessments; + using DigitalLearningSolutions.Web.Helpers; + using Microsoft.AspNetCore.Mvc.Rendering; + + public class MyCompetencyAssessmentsViewModel : BaseCompetencyAssessmentsPageViewModel + { + public readonly IEnumerable CompetencyAssessments; + public readonly bool IsWorkforceManager; + + public override SelectList CompetencyAssessmentSortByOptions { get; } = new SelectList(new[] + { + CompetencyAssessmentSortByOptionTexts.CompetencyAssessmentName, + CompetencyAssessmentSortByOptionTexts.CompetencyAssessmentOwner, + CompetencyAssessmentSortByOptionTexts.CompetencyAssessmentCreatedDate, + CompetencyAssessmentSortByOptionTexts.CompetencyAssessmentPublishStatus + }); + + public MyCompetencyAssessmentsViewModel( + IEnumerable competencyAssessments, // Renamed parameter to avoid shadowing + string? searchString, + string sortBy, + string sortDirection, + int page, + bool isWorkforceManager + ) : base(searchString, sortBy, sortDirection, page) + { + var sortedItems = SortingHelper.SortCompetencyAssessmentItems( + competencyAssessments, + sortBy, + sortDirection + ); + var filteredItems = SearchHelper.FilterCompetencyAssessments(sortedItems, SearchString, 60, false).ToList(); + MatchingSearchResults = filteredItems.Count; + SetTotalPages(); + CompetencyAssessments = PaginateItems(filteredItems).Cast(); // Assign to the field + IsWorkforceManager = isWorkforceManager; + } + } +} diff --git a/DigitalLearningSolutions.Web/ViewModels/CompetencyAssessments/SelectFrameworkSourcesFormData.cs b/DigitalLearningSolutions.Web/ViewModels/CompetencyAssessments/SelectFrameworkSourcesFormData.cs new file mode 100644 index 0000000000..846a0fb2dd --- /dev/null +++ b/DigitalLearningSolutions.Web/ViewModels/CompetencyAssessments/SelectFrameworkSourcesFormData.cs @@ -0,0 +1,12 @@ +namespace DigitalLearningSolutions.Web.ViewModels.CompetencyAssessments +{ + using System.ComponentModel.DataAnnotations; + public class SelectFrameworkSourcesFormData + { + [Required] + public int FrameworkId { get; set; } + public int CompetencyAssessmentId { get; set; } + public bool? TaskStatus { get; set; } + public string? ActionName { get; set; } + } +} diff --git a/DigitalLearningSolutions.Web/ViewModels/CompetencyAssessments/SelectFrameworkSourcesViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/CompetencyAssessments/SelectFrameworkSourcesViewModel.cs new file mode 100644 index 0000000000..8d1adea226 --- /dev/null +++ b/DigitalLearningSolutions.Web/ViewModels/CompetencyAssessments/SelectFrameworkSourcesViewModel.cs @@ -0,0 +1,40 @@ +using DigitalLearningSolutions.Data.Models.CompetencyAssessments; +using DigitalLearningSolutions.Data.Models.Frameworks; +using System.Collections.Generic; +using System.Linq; + +namespace DigitalLearningSolutions.Web.ViewModels.CompetencyAssessments +{ + public class SelectFrameworkSourcesViewModel : SelectFrameworkSourcesFormData + { + public SelectFrameworkSourcesViewModel() { } + public SelectFrameworkSourcesViewModel(CompetencyAssessmentBase competencyAssessmentBase, IEnumerable frameworks, int[] additionalFrameworksIds, int? primaryFramework, bool? taskStatus, string actionName) + { + ID = competencyAssessmentBase.ID; + CompetencyAssessmentName = competencyAssessmentBase.CompetencyAssessmentName; + UserRole = competencyAssessmentBase.UserRole; + TaskStatus = taskStatus; + PrimaryFramework = frameworks.FirstOrDefault(f => f.ID == primaryFramework); + var excludedIds = new HashSet(additionalFrameworksIds); + if (primaryFramework.HasValue) + { + excludedIds.Add(primaryFramework.Value); + } + Frameworks = [.. frameworks + .Where(f => !excludedIds.Contains(f.ID)) + .OrderBy(f => f.FrameworkName)]; + AdditionalFrameworks = [.. additionalFrameworksIds.Select(id => frameworks.First(f => f.ID == id))]; + ActionName = actionName; + } + public IEnumerable Frameworks { get; set; } + public IEnumerable AdditionalFrameworks { get; set; } + public BrandedFramework? PrimaryFramework { get; set; } + public IEnumerable Roles { get; set; } + public int ID { get; set; } + public string CompetencyAssessmentName { get; set; } + public int UserRole { get; set; } + public string? GroupName { get; set; } + public string? SubGroupName { get; set; } + public string? RoleName { get; set; } + } +} diff --git a/DigitalLearningSolutions.Web/ViewModels/RoleProfiles/AllRoleProfilesViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/RoleProfiles/AllRoleProfilesViewModel.cs deleted file mode 100644 index bad699149f..0000000000 --- a/DigitalLearningSolutions.Web/ViewModels/RoleProfiles/AllRoleProfilesViewModel.cs +++ /dev/null @@ -1,42 +0,0 @@ -namespace DigitalLearningSolutions.Web.ViewModels.RoleProfiles -{ - using System.Collections.Generic; - using System.Linq; - using DigitalLearningSolutions.Data.Models.RoleProfiles; - using DigitalLearningSolutions.Web.Helpers; - using Microsoft.AspNetCore.Mvc.Rendering; - public class AllRoleProfilesViewModel : BaseRoleProfilesPageViewModel - { - public readonly IEnumerable RoleProfiles; - public readonly bool IsWorkforceManager; - public override SelectList RoleProfileSortByOptions { get; } = new SelectList(new[] - { - RoleProfileSortByOptionTexts.RoleProfileName, - RoleProfileSortByOptionTexts.RoleProfileOwner, - RoleProfileSortByOptionTexts.RoleProfileCreatedDate, - RoleProfileSortByOptionTexts.RoleProfilePublishStatus, - RoleProfileSortByOptionTexts.RoleProfileBrand, - RoleProfileSortByOptionTexts.RoleProfileNationalRoleGroup, - RoleProfileSortByOptionTexts.RoleProfileNationalRoleProfile - }); - public AllRoleProfilesViewModel( - IEnumerable roleProfiles, - string? searchString, - string sortBy, - string sortDirection, - int page - ) : base(searchString, sortBy, sortDirection, page) - { - var sortedItems = SortingHelper.SortRoleProfileItems( - roleProfiles, - sortBy, - sortDirection - ); - var filteredItems = SearchHelper.FilterRoleProfiles(sortedItems, SearchString, 60, false).ToList(); - MatchingSearchResults = filteredItems.Count; - SetTotalPages(); - var paginatedItems = PaginateItems(filteredItems); - RoleProfiles = paginatedItems.Cast(); - } - } -} diff --git a/DigitalLearningSolutions.Web/ViewModels/RoleProfiles/MyRoleProfilesViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/RoleProfiles/MyRoleProfilesViewModel.cs deleted file mode 100644 index 7657922974..0000000000 --- a/DigitalLearningSolutions.Web/ViewModels/RoleProfiles/MyRoleProfilesViewModel.cs +++ /dev/null @@ -1,41 +0,0 @@ -namespace DigitalLearningSolutions.Web.ViewModels.RoleProfiles -{ - using System.Collections.Generic; - using System.Linq; - using DigitalLearningSolutions.Data.Models.RoleProfiles; - using DigitalLearningSolutions.Web.Helpers; - using Microsoft.AspNetCore.Mvc.Rendering; - public class MyRoleProfilesViewModel : BaseRoleProfilesPageViewModel - { - public readonly IEnumerable RoleProfiles; - public readonly bool IsWorkforceManager; - public override SelectList RoleProfileSortByOptions { get; } = new SelectList(new[] - { - RoleProfileSortByOptionTexts.RoleProfileName, - RoleProfileSortByOptionTexts.RoleProfileOwner, - RoleProfileSortByOptionTexts.RoleProfileCreatedDate, - RoleProfileSortByOptionTexts.RoleProfilePublishStatus - }); - public MyRoleProfilesViewModel( - IEnumerable roleProfiles, - string? searchString, - string sortBy, - string sortDirection, - int page, - bool isWorkforceManager - ) : base(searchString, sortBy, sortDirection, page) - { - var sortedItems = SortingHelper.SortRoleProfileItems( - roleProfiles, - sortBy, - sortDirection - ); - var filteredItems = SearchHelper.FilterRoleProfiles(sortedItems, SearchString, 60, false).ToList(); - MatchingSearchResults = filteredItems.Count; - SetTotalPages(); - var paginatedItems = PaginateItems(filteredItems); - RoleProfiles = paginatedItems.Cast(); - IsWorkforceManager = isWorkforceManager; - } - } -} diff --git a/DigitalLearningSolutions.Web/ViewModels/RoleProfiles/ProfessionalGroupViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/RoleProfiles/ProfessionalGroupViewModel.cs deleted file mode 100644 index 67701b8d15..0000000000 --- a/DigitalLearningSolutions.Web/ViewModels/RoleProfiles/ProfessionalGroupViewModel.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace DigitalLearningSolutions.Web.ViewModels.RoleProfiles -{ - using DigitalLearningSolutions.Data.Models.RoleProfiles; - using System.Collections.Generic; - - public class ProfessionalGroupViewModel - { - public IEnumerable NRPProfessionalGroups { get; set; } - public RoleProfileBase RoleProfileBase { get; set; } - } -} diff --git a/DigitalLearningSolutions.Web/ViewModels/RoleProfiles/RoleProfilesViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/RoleProfiles/RoleProfilesViewModel.cs deleted file mode 100644 index 9154eeee6b..0000000000 --- a/DigitalLearningSolutions.Web/ViewModels/RoleProfiles/RoleProfilesViewModel.cs +++ /dev/null @@ -1,29 +0,0 @@ -namespace DigitalLearningSolutions.Web.ViewModels.RoleProfiles -{ - using DigitalLearningSolutions.Web.Models.Enums; - using DigitalLearningSolutions.Web.ViewModels.Common; - - public class RoleProfilesViewModel - { - public RoleProfilesViewModel( - bool isWorkforceManager, - bool isWorkforceContributor, - AllRoleProfilesViewModel allRoleProfiles, - MyRoleProfilesViewModel myRoleProfiles, - RoleProfilesTab currentTab - ) - { - IsWorkforceManager = isWorkforceManager; - IsWorkforceContributor = isWorkforceContributor; - MyRoleProfilesViewModel = myRoleProfiles; - AllRoleProfilesViewModel = allRoleProfiles; - TabNavLinks = new TabsNavViewModel(currentTab); - } - - public bool IsWorkforceManager { get; set; } - public bool IsWorkforceContributor { get; set; } - public MyRoleProfilesViewModel MyRoleProfilesViewModel { get; set; } - public AllRoleProfilesViewModel AllRoleProfilesViewModel { get; set; } - public TabsNavViewModel TabNavLinks { get; set; } - } -} diff --git a/DigitalLearningSolutions.Web/ViewModels/SuperAdmin/Administrators/SearchableAdminAccountsViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/SuperAdmin/Administrators/SearchableAdminAccountsViewModel.cs index 0afcfe7498..88f5ea2889 100644 --- a/DigitalLearningSolutions.Web/ViewModels/SuperAdmin/Administrators/SearchableAdminAccountsViewModel.cs +++ b/DigitalLearningSolutions.Web/ViewModels/SuperAdmin/Administrators/SearchableAdminAccountsViewModel.cs @@ -5,7 +5,7 @@ using DigitalLearningSolutions.Data.Models.User; using DigitalLearningSolutions.Web.Helpers; using DigitalLearningSolutions.Web.ViewModels.Common.SearchablePage; - + using DateHelper = Helpers.DateHelper; public class SearchableAdminAccountsViewModel : BaseFilterableViewModel { public readonly bool CanShowDeleteAdminButton; @@ -28,7 +28,10 @@ ReturnPageQuery returnPageQuery IsLocked = admin.UserAccount?.FailedLoginCount >= AuthHelper.FailedLoginThreshold; IsAdminActive = admin.AdminAccount.Active; IsUserActive = admin.UserAccount.Active; - + if (admin.LastAccessed.HasValue) + { + LastAccessed = admin.LastAccessed.Value.ToString(DateHelper.StandardDateFormat); + } CanShowDeactivateAdminButton = IsAdminActive && admin.AdminIdReferenceCount > 0; CanShowDeleteAdminButton = admin.AdminIdReferenceCount == 0; @@ -47,6 +50,7 @@ ReturnPageQuery returnPageQuery public bool IsLocked { get; set; } public bool IsAdminActive { get; set; } public bool IsUserActive { get; set; } + public string? LastAccessed { get; set; } public ReturnPageQuery ReturnPageQuery { get; set; } } } diff --git a/DigitalLearningSolutions.Web/ViewModels/SuperAdmin/Delegates/SearchableDelegatesViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/SuperAdmin/Delegates/SearchableDelegatesViewModel.cs index 8ea0ed22e5..a615461e73 100644 --- a/DigitalLearningSolutions.Web/ViewModels/SuperAdmin/Delegates/SearchableDelegatesViewModel.cs +++ b/DigitalLearningSolutions.Web/ViewModels/SuperAdmin/Delegates/SearchableDelegatesViewModel.cs @@ -28,6 +28,7 @@ ReturnPageQuery returnPageQuery LearningHubID = delegates.LearningHubAuthId; AccountClaimed = delegates.RegistrationConfirmationHash; DateRegistered = delegates.DateRegistered?.ToString(Data.Helpers.DateHelper.StandardDateFormat); + LastAccessed = delegates.LastAccessed?.ToString(Data.Helpers.DateHelper.StandardDateFormat); SelRegistered = delegates.SelfReg; IsDelegateActive = delegates.Active; IsCentreEmailVerified = delegates.CentreEmailVerified == null ? false : true; @@ -52,6 +53,7 @@ ReturnPageQuery returnPageQuery public bool IsLocked { get; set; } public string AccountClaimed { get; set; } public string? DateRegistered { get; set; } + public string? LastAccessed { get; set; } public bool SelRegistered { get; set; } public bool IsDelegateActive { get; set; } public bool IsUserActive { get; set; } diff --git a/DigitalLearningSolutions.Web/ViewModels/SuperAdmin/Users/SearchableUserAccountViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/SuperAdmin/Users/SearchableUserAccountViewModel.cs index 5b1e7e63ac..263e008165 100644 --- a/DigitalLearningSolutions.Web/ViewModels/SuperAdmin/Users/SearchableUserAccountViewModel.cs +++ b/DigitalLearningSolutions.Web/ViewModels/SuperAdmin/Users/SearchableUserAccountViewModel.cs @@ -27,6 +27,10 @@ ReturnPageQuery returnPageQuery ProfessionalRegistrationNumber = user.UserAccount.ProfessionalRegistrationNumber; LearningHubAuthId = user.UserAccount.LearningHubAuthId; ReturnPageQuery = returnPageQuery; + if (user.UserAccount.LastAccessed.HasValue) + { + LastAccessed = user.UserAccount.LastAccessed.Value.ToString(DateHelper.StandardDateFormat); + } } public int Id { get; set; } @@ -51,6 +55,7 @@ ReturnPageQuery returnPageQuery public int? LearningHubAuthId { get; set; } + public string? LastAccessed { get; set; } public ReturnPageQuery ReturnPageQuery { get; set; } } } diff --git a/DigitalLearningSolutions.Web/ViewModels/Supervisor/EnrolDelegateOnProfileAssessmentViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/Supervisor/EnrolDelegateOnProfileAssessmentViewModel.cs index ed6e40e583..1b70330bbe 100644 --- a/DigitalLearningSolutions.Web/ViewModels/Supervisor/EnrolDelegateOnProfileAssessmentViewModel.cs +++ b/DigitalLearningSolutions.Web/ViewModels/Supervisor/EnrolDelegateOnProfileAssessmentViewModel.cs @@ -1,13 +1,13 @@ namespace DigitalLearningSolutions.Web.ViewModels.Supervisor { - using DigitalLearningSolutions.Data.Models.RoleProfiles; + using DigitalLearningSolutions.Data.Models.CompetencyAssessments; using DigitalLearningSolutions.Data.Models.SessionData.Supervisor; using DigitalLearningSolutions.Data.Models.Supervisor; using System.Collections.Generic; public class EnrolDelegateOnProfileAssessmentViewModel { - public SessionEnrolOnRoleProfile SessionEnrolOnRoleProfile { get; set; } + public SessionEnrolOnCompetencyAssessment SessionEnrolOnCompetencyAssessment { get; set; } public SupervisorDelegateDetail SupervisorDelegateDetail { get; set; } - public IEnumerable RoleProfiles { get; set; } + public IEnumerable CompetencyAssessments { get; set; } } } diff --git a/DigitalLearningSolutions.Web/ViewModels/Supervisor/EnrolDelegateSetCompletByDateViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/Supervisor/EnrolDelegateSetCompletByDateViewModel.cs index cac66da25f..e8582ca012 100644 --- a/DigitalLearningSolutions.Web/ViewModels/Supervisor/EnrolDelegateSetCompletByDateViewModel.cs +++ b/DigitalLearningSolutions.Web/ViewModels/Supervisor/EnrolDelegateSetCompletByDateViewModel.cs @@ -1,6 +1,6 @@ namespace DigitalLearningSolutions.Web.ViewModels.Supervisor { - using DigitalLearningSolutions.Data.Models.RoleProfiles; + using DigitalLearningSolutions.Data.Models.CompetencyAssessments; using DigitalLearningSolutions.Data.Models.Supervisor; using DigitalLearningSolutions.Web.Helpers; using System; @@ -8,7 +8,7 @@ public class EnrolDelegateSetCompletByDateViewModel { public SupervisorDelegateDetail SupervisorDelegateDetail { get; set; } - public RoleProfile RoleProfile { get; set; } + public CompetencyAssessment CompetencyAssessment { get; set; } public DateTime? CompleteByDate { get; set; } public OldDateValidator.ValidationResult? CompleteByValidationResult { get; set; } } diff --git a/DigitalLearningSolutions.Web/ViewModels/Supervisor/EnrolDelegateSummaryViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/Supervisor/EnrolDelegateSummaryViewModel.cs index ec238061e8..ad66e71ac8 100644 --- a/DigitalLearningSolutions.Web/ViewModels/Supervisor/EnrolDelegateSummaryViewModel.cs +++ b/DigitalLearningSolutions.Web/ViewModels/Supervisor/EnrolDelegateSummaryViewModel.cs @@ -1,13 +1,13 @@ namespace DigitalLearningSolutions.Web.ViewModels.Supervisor { - using DigitalLearningSolutions.Data.Models.RoleProfiles; + using DigitalLearningSolutions.Data.Models.CompetencyAssessments; using DigitalLearningSolutions.Data.Models.Supervisor; using System; public class EnrolDelegateSummaryViewModel { public SupervisorDelegateDetail SupervisorDelegateDetail { get; set; } - public RoleProfile RoleProfile { get; set; } + public CompetencyAssessment CompetencyAssessment { get; set; } public DateTime? CompleteByDate { get; set; } public string SupervisorRoleName { get; set; } public int SupervisorRoleCount { get; set; } diff --git a/DigitalLearningSolutions.Web/ViewModels/Supervisor/EnrolDelegateSupervisorRoleViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/Supervisor/EnrolDelegateSupervisorRoleViewModel.cs index 0c988b9457..4b15b66edf 100644 --- a/DigitalLearningSolutions.Web/ViewModels/Supervisor/EnrolDelegateSupervisorRoleViewModel.cs +++ b/DigitalLearningSolutions.Web/ViewModels/Supervisor/EnrolDelegateSupervisorRoleViewModel.cs @@ -1,6 +1,6 @@ namespace DigitalLearningSolutions.Web.ViewModels.Supervisor { - using DigitalLearningSolutions.Data.Models.RoleProfiles; + using DigitalLearningSolutions.Data.Models.CompetencyAssessments; using DigitalLearningSolutions.Data.Models.Supervisor; using System; using System.Collections.Generic; @@ -9,7 +9,7 @@ public class EnrolDelegateSupervisorRoleViewModel { public SupervisorDelegateDetail? SupervisorDelegateDetail { get; set; } - public RoleProfile? RoleProfile { get; set; } + public CompetencyAssessment? CompetencyAssessment { get; set; } [Required(ErrorMessage = "Please choose a supervisor role")] public int? SelfAssessmentSupervisorRoleId { get; set; } public IEnumerable? SelfAssessmentSupervisorRoles { get; set; } diff --git a/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Centre/Administrator/SearchableAdminViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Centre/Administrator/SearchableAdminViewModel.cs index 7e4ab30b47..c3da68c395 100644 --- a/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Centre/Administrator/SearchableAdminViewModel.cs +++ b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Centre/Administrator/SearchableAdminViewModel.cs @@ -5,6 +5,8 @@ using DigitalLearningSolutions.Data.Models.User; using DigitalLearningSolutions.Web.Helpers; using DigitalLearningSolutions.Web.ViewModels.Common.SearchablePage; + using System; + using DateHelper = Helpers.DateHelper; public class SearchableAdminViewModel : BaseFilterableViewModel { @@ -23,6 +25,10 @@ ReturnPageQuery returnPageQuery EmailAddress = admin.EmailForCentreNotifications; IsLocked = admin.UserAccount.FailedLoginCount >= AuthHelper.FailedLoginThreshold; IsActive = admin.AdminAccount.Active; + if (admin.LastAccessed.HasValue) + { + LastAccessed = admin.LastAccessed.Value.ToString(DateHelper.StandardDateFormat); + } CanShowDeactivateAdminButton = UserPermissionsHelper.LoggedInAdminCanDeactivateUser(admin.AdminAccount, loggedInAdminAccount); @@ -46,6 +52,8 @@ ReturnPageQuery returnPageQuery public bool IsActive { get; set; } + public string? LastAccessed { get; set; } + public ReturnPageQuery ReturnPageQuery { get; set; } } } diff --git a/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/AllDelegates/AllDelegatesViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/AllDelegates/AllDelegatesViewModel.cs index 63a027e4d4..f6a8141dcc 100644 --- a/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/AllDelegates/AllDelegatesViewModel.cs +++ b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/AllDelegates/AllDelegatesViewModel.cs @@ -44,6 +44,7 @@ IEnumerable availableFilters public override IEnumerable<(string, string)> SortOptions { get; } = new[] { DelegateSortByOptions.Name, + DelegateSortByOptions.LastAccessed, DelegateSortByOptions.RegistrationDate, }; diff --git a/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/Shared/DelegateInfoViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/Shared/DelegateInfoViewModel.cs index 504fd4b454..814e488ac9 100644 --- a/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/Shared/DelegateInfoViewModel.cs +++ b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/Shared/DelegateInfoViewModel.cs @@ -41,6 +41,10 @@ IEnumerable delegateRegistrationPrompts { RegistrationDate = delegateUser.DateRegistered.Value.ToString(DateHelper.StandardDateFormat); } + if (delegateUser.LastAccessed.HasValue) + { + LastAccessed = delegateUser.LastAccessed.Value.ToString(DateHelper.StandardDateFormat); + } DelegateRegistrationPrompts = delegateRegistrationPrompts; RegistrationConfirmationHash = delegateUser.RegistrationConfirmationHash; @@ -61,6 +65,7 @@ IEnumerable delegateRegistrationPrompts public int JobGroupId { get; set; } public string? JobGroup { get; set; } public string? RegistrationDate { get; set; } + public string? LastAccessed { get; set; } public string ProfessionalRegistrationNumber { get; set; } public string? RegistrationConfirmationHash { get; set; } diff --git a/DigitalLearningSolutions.Web/Views/RoleProfiles/RoleProfile.cshtml b/DigitalLearningSolutions.Web/Views/CompetencyAssessments/CompetencyAssessment.cshtml similarity index 100% rename from DigitalLearningSolutions.Web/Views/RoleProfiles/RoleProfile.cshtml rename to DigitalLearningSolutions.Web/Views/CompetencyAssessments/CompetencyAssessment.cshtml diff --git a/DigitalLearningSolutions.Web/Views/CompetencyAssessments/ConfirmRemoveFrameworkSource.cshtml b/DigitalLearningSolutions.Web/Views/CompetencyAssessments/ConfirmRemoveFrameworkSource.cshtml new file mode 100644 index 0000000000..a20a786820 --- /dev/null +++ b/DigitalLearningSolutions.Web/Views/CompetencyAssessments/ConfirmRemoveFrameworkSource.cshtml @@ -0,0 +1,51 @@ +@using DigitalLearningSolutions.Web.Helpers +@using DigitalLearningSolutions.Web.ViewModels.CompetencyAssessments +@model ConfirmRemoveFrameworkSourceViewModel; +@{ + var errorHasOccurred = !ViewData.ModelState.IsValid; + ViewData["Title"] = "Competency Assessments - Remove source framework"; +} +
+
+ @if (errorHasOccurred) + { + + } + +

Remove framework source from @Model.AssessmentName

+
+
+ + + +
+
+
+ + + + + + +

+ This competency assessment has @Model.CompetencyCount @DisplayStringHelper.PluraliseStringIfRequired(@Model.Vocabulary.ToLower(), Model.CompetencyCount) + associated with it from the framework @Model.FrameworkName. Removing this + framework source will remove the @DisplayStringHelper.PluraliseStringIfRequired(@Model.Vocabulary.ToLower(), Model.CompetencyCount) from the assessment. +

+ + + + + + +
+
diff --git a/DigitalLearningSolutions.Web/Views/CompetencyAssessments/EditBranding.cshtml b/DigitalLearningSolutions.Web/Views/CompetencyAssessments/EditBranding.cshtml new file mode 100644 index 0000000000..f69c53f94e --- /dev/null +++ b/DigitalLearningSolutions.Web/Views/CompetencyAssessments/EditBranding.cshtml @@ -0,0 +1,82 @@ +@using DigitalLearningSolutions.Web.ViewModels.CompetencyAssessments +@model EditBrandingViewModel +@{ + ViewData["Title"] = "Assessment Branding"; + ViewData["Application"] = "Framework Service"; + ViewData["HeaderPathName"] = "Framework Service"; +} + +@section NavMenuItems { + +} +@section NavBreadcrumbs { + +} + +

Edit @Model.CompetencyAssessmentName provider and category

+

This will be visible to users when they browse assessments. It wiull help them to identify where the assessment is from and what it contains.

+
+ @if (!ViewData.ModelState.IsValid) + { + + } + + + +
+ + +
+
+ + + +
+ + +
+
+ + + + + + + + + + + +@section scripts { + +} diff --git a/DigitalLearningSolutions.Web/Views/CompetencyAssessments/EditDescription.cshtml b/DigitalLearningSolutions.Web/Views/CompetencyAssessments/EditDescription.cshtml new file mode 100644 index 0000000000..6cab75b552 --- /dev/null +++ b/DigitalLearningSolutions.Web/Views/CompetencyAssessments/EditDescription.cshtml @@ -0,0 +1,62 @@ +@using DigitalLearningSolutions.Web.ViewModels.CompetencyAssessments +@model EditDescriptionViewModel; +@{ + ViewData["Title"] = "Edit Introductory Text"; + ViewData["Application"] = "Framework Service"; +} + + +@section NavMenuItems { + +} + +@section NavBreadcrumbs { + +} + +

Edit @Model.CompetencyAssessmentName introductory text

+
+ @if (!ViewData.ModelState.IsValid) + { + + } + + + + + + + + + + + + +@section scripts { + +} diff --git a/DigitalLearningSolutions.Web/Views/CompetencyAssessments/EditRoleProfileLinks.cshtml b/DigitalLearningSolutions.Web/Views/CompetencyAssessments/EditRoleProfileLinks.cshtml new file mode 100644 index 0000000000..96e78ce8d9 --- /dev/null +++ b/DigitalLearningSolutions.Web/Views/CompetencyAssessments/EditRoleProfileLinks.cshtml @@ -0,0 +1,259 @@ +@using DigitalLearningSolutions.Web.ViewModels.CompetencyAssessments; +@model EditRoleProfileLinksViewModel; +@{ + ViewData["Title"] = "Edit National Role Profile Links"; + ViewData["Application"] = "Framework Service"; +} + +@section NavMenuItems { + +} + +@section NavBreadcrumbs { + +} + +

Edit @Model.CompetencyAssessmentName national NHS role profile links

+@if (Model.TaskStatus != null | Model.ActionName != "EditGroup") +{ +
+ +
+
+ Professional group +
+
+ @Model.GroupName +
+
+ + Change professional group link + +
+
+ @if (Model.ProfessionalGroupId != null && Model.ActionName != "EditSubGroup") + { +
+
+ Sub group +
+
+ @Model.SubGroupName +
+
+ + Change sub group link + +
+
+ } + @if (Model.SubGroupId != null && Model.ActionName == "Summary") + { +
+
+ Role +
+
+ @Model.RoleName +
+
+ + Change role profile link + +
+
+ } +
+} +@if (Model.ActionName == "EditGroup") +{ +
+ @if (!ViewData.ModelState.IsValid) + { + + } + +
+ +

+ Choose the NHS national role profile professional group to associate with this assessment. +

+
+ +
+ @foreach (var professionalGroup in Model.ProfessionalGroups) + { +
+ + +
+ } +
+ +
+ + +
+
+
+
+ + + + + + + + + + + + + +} +else if (Model.ActionName == "EditSubGroup" && Model.ProfessionalGroupId != null) +{ +
+ @if (!ViewData.ModelState.IsValid) + { + + } + +
+ +

+ Choose the role sub group to associate with this assessment. +

+
+ +
+ @foreach (var subGroup in Model.SubGroups) + { +
+ + +
+ } +
+ +
+ + +
+
+
+
+ + + + + + + + + + + + +} +else if (Model.ActionName == "EditRole" && Model.SubGroupId != null) +{ +
+ @if (!ViewData.ModelState.IsValid) + { + + } + +
+ +

+ Choose the role to associate with this assessment. +

+
+ +
+ @foreach (var role in Model.Roles) + { +
+ + +
+ } +
+ +
+ + +
+
+
+
+ + + + + + + + + + + + +} +else if (Model.ActionName == "Summary") +{ +
+ + + + + + + + + + + + + + +
+} + diff --git a/DigitalLearningSolutions.Web/Views/CompetencyAssessments/EditVocabulary.cshtml b/DigitalLearningSolutions.Web/Views/CompetencyAssessments/EditVocabulary.cshtml new file mode 100644 index 0000000000..3b32db2a58 --- /dev/null +++ b/DigitalLearningSolutions.Web/Views/CompetencyAssessments/EditVocabulary.cshtml @@ -0,0 +1,98 @@ +@using DigitalLearningSolutions.Web.ViewModels.CompetencyAssessments +@model EditVocabularyViewModel +@{ + ViewData["Title"] = "Assessment Branding"; + ViewData["Application"] = "Framework Service"; + ViewData["HeaderPathName"] = "Framework Service"; +} + +@section NavMenuItems { + +} +@section NavBreadcrumbs { + +} + +

Edit @Model.CompetencyAssessmentName vocabulary

+
+ @if (!ViewData.ModelState.IsValid) + { + + } + +
+ +

+ Choose assessment vocabulary - the name given to the building blocks of your assessment. +

+
+
+
+ + +
+ The attributes (skills, knowledge and behaviours) which individuals bring to the workplace. +
+
+ +
+ + +
+ Defined standards of performance, focused on the outputs of work and observable performance. +
+
+
+ + +
+ The knowledge and skills that registered nurses must demonstrate when caring for people of all ages and across all care settings. +
+
+
+ + +
+ The same as capability | capabilities.
+ The term capabilities is recommended to make a clear distinction from competences. +
+
+
+
+ +
+ + + + + + + + + diff --git a/DigitalLearningSolutions.Web/Views/RoleProfiles/Index.cshtml b/DigitalLearningSolutions.Web/Views/CompetencyAssessments/Index.cshtml similarity index 65% rename from DigitalLearningSolutions.Web/Views/RoleProfiles/Index.cshtml rename to DigitalLearningSolutions.Web/Views/CompetencyAssessments/Index.cshtml index 89477e0ff7..0c6f91d80a 100644 --- a/DigitalLearningSolutions.Web/Views/RoleProfiles/Index.cshtml +++ b/DigitalLearningSolutions.Web/Views/CompetencyAssessments/Index.cshtml @@ -1,8 +1,8 @@ -@using DigitalLearningSolutions.Web.ViewModels.RoleProfiles -@model RoleProfilesViewModel +@using DigitalLearningSolutions.Web.ViewModels.CompetencyAssessments +@model CompetencyAssessmentsViewModel @{ - ViewData["Title"] = (string)ViewContext.RouteData.Values["tabname"] == "Mine" ? "My Role Profiles" : "All Role Profiles"; + ViewData["Title"] = (string)ViewContext.RouteData.Values["tabname"] == "Mine" ? "My Competency Assessments" : "All Competency Assessments"; ViewData["Application"] = "Framework Service"; } @@ -13,7 +13,7 @@ @@ -26,11 +26,11 @@
@if ((string)ViewContext.RouteData.Values["tabname"] == "Mine") { - + } else if ((string)ViewContext.RouteData.Values["tabname"] == "All") { - + }
diff --git a/DigitalLearningSolutions.Web/Views/CompetencyAssessments/ManageCompetencyAssessment.cshtml b/DigitalLearningSolutions.Web/Views/CompetencyAssessments/ManageCompetencyAssessment.cshtml new file mode 100644 index 0000000000..70b5bbdc71 --- /dev/null +++ b/DigitalLearningSolutions.Web/Views/CompetencyAssessments/ManageCompetencyAssessment.cshtml @@ -0,0 +1,244 @@ +@using DigitalLearningSolutions.Web.ViewModels.CompetencyAssessments +@model ManageCompetencyAssessmentViewModel +@{ + ViewData["Title"] = Model.PublishStatusID == 3 ? "Manage" : "Create" + " competency assessment"; + ViewData["Application"] = "Framework Service"; +} + +@section NavMenuItems { + +} +@section NavBreadcrumbs { + +} + +

@ViewData["Title"]

+ +
+
+ +
+
+ Assessment name +
+
+ @Model.CompetencyAssessmentName +
+
+ + Change assessment name + +
+
+
+
+ Publish status +
+
+ + @(Model.PublishStatusID == 1 ? "Draft" : Model.PublishStatusID == 2 ? "In review" : "Published") + +
+
+
+ + +
diff --git a/DigitalLearningSolutions.Web/Views/CompetencyAssessments/Name.cshtml b/DigitalLearningSolutions.Web/Views/CompetencyAssessments/Name.cshtml new file mode 100644 index 0000000000..69feaf3825 --- /dev/null +++ b/DigitalLearningSolutions.Web/Views/CompetencyAssessments/Name.cshtml @@ -0,0 +1,109 @@ +@using DigitalLearningSolutions.Data.Models.CompetencyAssessments; +@model CompetencyAssessmentBase; +@{ + ViewData["Title"] = "New Competency Assessments"; + ViewData["Application"] = "Framework Service"; +} + +@section NavMenuItems { + +} + @if ((string)ViewContext.RouteData.Values["actionname"] == "New") +{ + @section NavBreadcrumbs { + + } +} +else +{ + @section NavBreadcrumbs { + + } +} +@if ((string)ViewContext.RouteData.Values["actionName"] == "New") +{ +

Create a new competency assessment

+} +else +{ +

Edit competency assessment name

+} +
+ @if (!ViewData.ModelState.IsValid) + { + + } + + +
+ Choose a title that identifies scope of capabilities covered and/or the roles or levels the assessment targets. +
+ + +
+ + + + + + + + + + + + + + @if ((string)ViewContext.RouteData.Values["actionName"] == "New") + { + + + } + else + { + @if (Model.PublishStatusID == 3) + { + + } + + + } + + diff --git a/DigitalLearningSolutions.Web/Views/CompetencyAssessments/SelectFrameworkSources.cshtml b/DigitalLearningSolutions.Web/Views/CompetencyAssessments/SelectFrameworkSources.cshtml new file mode 100644 index 0000000000..35496950f2 --- /dev/null +++ b/DigitalLearningSolutions.Web/Views/CompetencyAssessments/SelectFrameworkSources.cshtml @@ -0,0 +1,114 @@ +@using DigitalLearningSolutions.Web.ViewModels.CompetencyAssessments +@model SelectFrameworkSourcesViewModel; +@{ + ViewData["Title"] = "Select Framework Sources"; + ViewData["Application"] = "Framework Service"; +} + + +@section NavMenuItems { + +} + +@section NavBreadcrumbs { + +} + +

Select framework sources for @Model.CompetencyAssessmentName

+
+ @if (Model.PrimaryFramework != null) + { +
+
+ Primary framework +
+
+ @Model.PrimaryFramework.FrameworkName +
+
+ + Remove @Model.PrimaryFramework.FrameworkName + +
+
+ } + @if (Model.AdditionalFrameworks.Count() > 0) + { + for (int i = 0; i < Model.AdditionalFrameworks.Count(); i++) + { +
+
+ Additional framework @i +
+
+ @Model.AdditionalFrameworks.ElementAt(i).FrameworkName +
+
+ + Remove @Model.AdditionalFrameworks.ElementAt(i).FrameworkName + +
+
+ } + } +
+@if (Model.ActionName == "AddFramework") +{ +
+
+
+ +

Add a framework source

+
+
+ @foreach (var framework in Model.Frameworks) + { +
+ + +
+ } +
+
+
+ + + +
+} +@if (Model.ActionName == "Summary") +{ + + Add framework + +
+ + + + + + + +
+} + diff --git a/DigitalLearningSolutions.Web/Views/CompetencyAssessments/Shared/_AssessmentsGrid.cshtml b/DigitalLearningSolutions.Web/Views/CompetencyAssessments/Shared/_AssessmentsGrid.cshtml new file mode 100644 index 0000000000..c9c5deba92 --- /dev/null +++ b/DigitalLearningSolutions.Web/Views/CompetencyAssessments/Shared/_AssessmentsGrid.cshtml @@ -0,0 +1,85 @@ +@using DigitalLearningSolutions.Data.Models.CompetencyAssessments; +@model IEnumerable; + + + + + + + + + + + + + + @foreach (var competencyAssessment in Model) + { + + + + + + + + + } + +
+ Frameworks +
+ Competency Assessment + + Framework Links + + Created + + Status + + Owner + + Actions +
+ Competency Assessment + + @competencyAssessment.Brand + + / + + @competencyAssessment.CompetencyAssessmentName + + + Framework links + + @competencyAssessment.LinkedFrameworks + + + Created + + @competencyAssessment.CreatedDate.ToShortDateString() + + + Status + + + + + Owner + + @competencyAssessment.Owner + + + Actions + @if (competencyAssessment.UserRole > 1) + { + + Manage + + } + else + { + + View + + } +
diff --git a/DigitalLearningSolutions.Web/Views/RoleProfiles/Shared/_RoleProfilesSearchAndSort.cshtml b/DigitalLearningSolutions.Web/Views/CompetencyAssessments/Shared/_CompetencyAssessmentsSearchAndSort.cshtml similarity index 66% rename from DigitalLearningSolutions.Web/Views/RoleProfiles/Shared/_RoleProfilesSearchAndSort.cshtml rename to DigitalLearningSolutions.Web/Views/CompetencyAssessments/Shared/_CompetencyAssessmentsSearchAndSort.cshtml index d6aa3c18d1..c3e030727f 100644 --- a/DigitalLearningSolutions.Web/Views/RoleProfiles/Shared/_RoleProfilesSearchAndSort.cshtml +++ b/DigitalLearningSolutions.Web/Views/CompetencyAssessments/Shared/_CompetencyAssessmentsSearchAndSort.cshtml @@ -1,11 +1,11 @@ -@using DigitalLearningSolutions.Web.ViewModels.RoleProfiles -@model BaseRoleProfilesPageViewModel - -
-
- -
-
- -
-
+@using DigitalLearningSolutions.Web.ViewModels.CompetencyAssessments +@model BaseCompetencyAssessmentsPageViewModel + +
+
+ +
+
+ +
+
diff --git a/DigitalLearningSolutions.Web/Views/RoleProfiles/Shared/_PageSearch.cshtml b/DigitalLearningSolutions.Web/Views/CompetencyAssessments/Shared/_PageSearch.cshtml similarity index 87% rename from DigitalLearningSolutions.Web/Views/RoleProfiles/Shared/_PageSearch.cshtml rename to DigitalLearningSolutions.Web/Views/CompetencyAssessments/Shared/_PageSearch.cshtml index 6edb778960..ab254994c8 100644 --- a/DigitalLearningSolutions.Web/Views/RoleProfiles/Shared/_PageSearch.cshtml +++ b/DigitalLearningSolutions.Web/Views/CompetencyAssessments/Shared/_PageSearch.cshtml @@ -1,13 +1,13 @@ -@using DigitalLearningSolutions.Web.ViewModels.RoleProfiles -@model BaseRoleProfilesPageViewModel - - +@using DigitalLearningSolutions.Web.ViewModels.CompetencyAssessments +@model BaseCompetencyAssessmentsPageViewModel + + diff --git a/DigitalLearningSolutions.Web/Views/RoleProfiles/Shared/_PageSort.cshtml b/DigitalLearningSolutions.Web/Views/CompetencyAssessments/Shared/_PageSort.cshtml similarity index 80% rename from DigitalLearningSolutions.Web/Views/RoleProfiles/Shared/_PageSort.cshtml rename to DigitalLearningSolutions.Web/Views/CompetencyAssessments/Shared/_PageSort.cshtml index a8b403f8d2..a13027eeb5 100644 --- a/DigitalLearningSolutions.Web/Views/RoleProfiles/Shared/_PageSort.cshtml +++ b/DigitalLearningSolutions.Web/Views/CompetencyAssessments/Shared/_PageSort.cshtml @@ -1,26 +1,26 @@ -@using DigitalLearningSolutions.Web.ViewModels.RoleProfiles -@model BaseRoleProfilesPageViewModel - - -
- - -
- - - -
-
+@using DigitalLearningSolutions.Web.ViewModels.CompetencyAssessments +@model BaseCompetencyAssessmentsPageViewModel + + +
+ + +
+ + + +
+
diff --git a/DigitalLearningSolutions.Web/Views/RoleProfiles/Shared/_Pagination.cshtml b/DigitalLearningSolutions.Web/Views/CompetencyAssessments/Shared/_Pagination.cshtml similarity index 94% rename from DigitalLearningSolutions.Web/Views/RoleProfiles/Shared/_Pagination.cshtml rename to DigitalLearningSolutions.Web/Views/CompetencyAssessments/Shared/_Pagination.cshtml index 3f43b6aee8..012e103877 100644 --- a/DigitalLearningSolutions.Web/Views/RoleProfiles/Shared/_Pagination.cshtml +++ b/DigitalLearningSolutions.Web/Views/CompetencyAssessments/Shared/_Pagination.cshtml @@ -1,5 +1,5 @@ -@using DigitalLearningSolutions.Web.ViewModels.RoleProfiles -@model BaseRoleProfilesPageViewModel +@using DigitalLearningSolutions.Web.ViewModels.CompetencyAssessments +@model BaseCompetencyAssessmentsPageViewModel