diff --git a/AdminUI/LearningHub.Nhs.AdminUI/LearningHub.Nhs.AdminUI.csproj b/AdminUI/LearningHub.Nhs.AdminUI/LearningHub.Nhs.AdminUI.csproj
index a0de54f8f..48d14054a 100644
--- a/AdminUI/LearningHub.Nhs.AdminUI/LearningHub.Nhs.AdminUI.csproj
+++ b/AdminUI/LearningHub.Nhs.AdminUI/LearningHub.Nhs.AdminUI.csproj
@@ -83,13 +83,13 @@
-
+
-
+
diff --git a/LearningHub.Nhs.WebUI.AutomatedUiTests/LearningHub.Nhs.WebUI.AutomatedUiTests.csproj b/LearningHub.Nhs.WebUI.AutomatedUiTests/LearningHub.Nhs.WebUI.AutomatedUiTests.csproj
index 1569f9734..838aba189 100644
--- a/LearningHub.Nhs.WebUI.AutomatedUiTests/LearningHub.Nhs.WebUI.AutomatedUiTests.csproj
+++ b/LearningHub.Nhs.WebUI.AutomatedUiTests/LearningHub.Nhs.WebUI.AutomatedUiTests.csproj
@@ -1,4 +1,4 @@
-
+
net8.0
@@ -11,7 +11,9 @@
+
+
diff --git a/LearningHub.Nhs.WebUI/Configuration/MoodleApiConfig.cs b/LearningHub.Nhs.WebUI/Configuration/MoodleApiConfig.cs
new file mode 100644
index 000000000..ec874477e
--- /dev/null
+++ b/LearningHub.Nhs.WebUI/Configuration/MoodleApiConfig.cs
@@ -0,0 +1,33 @@
+namespace LearningHub.Nhs.WebUI.Configuration
+{
+ ///
+ /// The Moodle Settings.
+ ///
+ public class MoodleApiConfig
+ {
+ ///
+ /// Gets or sets the base url for the Moodle service.
+ ///
+ public string BaseUrl { get; set; } = null!;
+
+ ///
+ /// Gets or sets the Web service Rest Format.
+ ///
+ public string MoodleWSRestFormat { get; set; } = null!;
+
+ ///
+ /// Gets or sets the token.
+ ///
+ public string WSToken { get; set; } = null!;
+
+ ///
+ /// Gets or sets the token.
+ ///
+ public string ApiPath { get; set; } = "webservice/rest/server.php";
+
+ ///
+ /// Gets or sets the token.
+ ///
+ public string CoursePath { get; set; } = "course/view.php";
+ }
+}
diff --git a/LearningHub.Nhs.WebUI/Controllers/Api/MyLearningController.cs b/LearningHub.Nhs.WebUI/Controllers/Api/MyLearningController.cs
index bcd13c08a..64b6de28d 100644
--- a/LearningHub.Nhs.WebUI/Controllers/Api/MyLearningController.cs
+++ b/LearningHub.Nhs.WebUI/Controllers/Api/MyLearningController.cs
@@ -44,6 +44,34 @@ public async Task GetActivityDetailed([FromBody] MyLearningRequest
return this.Ok(activity);
}
+ ///
+ /// Gets the detailed activity data.
+ ///
+ /// The request model - filter settings.
+ /// The .
+ [HttpPost]
+ [Route("GetUserRecentMyLearningActivities")]
+ public async Task GetUserRecentMyLearningActivities([FromBody] MyLearningRequestModel requestModel)
+ {
+ var activity = await this.myLearningService.GetUserRecentMyLearningActivities(requestModel);
+
+ return this.Ok(activity);
+ }
+
+ ///
+ /// Gets the detailed activity data.
+ ///
+ /// The request model - filter settings.
+ /// The .
+ [HttpPost]
+ [Route("GetUserLearningHistory")]
+ public async Task GetUserLearningHistory([FromBody] MyLearningRequestModel requestModel)
+ {
+ var activity = await this.myLearningService.GetUserLearningHistory(requestModel);
+
+ return this.Ok(activity);
+ }
+
///
/// Gets the played segment data for the progress modal in My Learning screen.
///
diff --git a/LearningHub.Nhs.WebUI/Controllers/ContributeController.cs b/LearningHub.Nhs.WebUI/Controllers/ContributeController.cs
index fc3b7f76a..27ae615ce 100644
--- a/LearningHub.Nhs.WebUI/Controllers/ContributeController.cs
+++ b/LearningHub.Nhs.WebUI/Controllers/ContributeController.cs
@@ -28,6 +28,7 @@ public class ContributeController : BaseController
private readonly IFileService fileService;
private readonly IResourceService resourceService;
private readonly IUserService userService;
+ private readonly IUserGroupService userGroupService;
///
/// Initializes a new instance of the class.
@@ -37,6 +38,7 @@ public class ContributeController : BaseController
/// Logger.
/// Settings.
/// User service.
+ /// userGroupService.
/// File service.
/// Resource service.
/// Azure media service.
@@ -48,6 +50,7 @@ public ContributeController(
ILogger logger,
IOptions settings,
IUserService userService,
+ IUserGroupService userGroupService,
IFileService fileService,
IResourceService resourceService,
IAzureMediaService azureMediaService,
@@ -58,6 +61,7 @@ public ContributeController(
this.authConfig = authConfig;
this.userService = userService;
+ this.userGroupService = userGroupService;
this.fileService = fileService;
this.resourceService = resourceService;
this.azureMediaService = azureMediaService;
@@ -167,7 +171,8 @@ public async Task CreateVersion(int resourceId)
[Route("my-contributions/{selectedTab}/{catalogueId}/{nodeId}")]
public async Task MyContributions()
{
- if ((this.User.IsInRole("ReadOnly") || this.User.IsInRole("BasicUser")) && !await this.resourceService.UserHasPublishedResourcesAsync())
+ bool catalogueContributionPermission = await this.userGroupService.UserHasCatalogueContributionPermission();
+ if ((this.User.IsInRole("ReadOnly") || this.User.IsInRole("BasicUser")) || (!catalogueContributionPermission && (!await this.resourceService.UserHasPublishedResourcesAsync())))
{
return this.RedirectToAction("AccessDenied", "Home");
}
diff --git a/LearningHub.Nhs.WebUI/Controllers/HomeController.cs b/LearningHub.Nhs.WebUI/Controllers/HomeController.cs
index d5f53c00d..57c170ae6 100644
--- a/LearningHub.Nhs.WebUI/Controllers/HomeController.cs
+++ b/LearningHub.Nhs.WebUI/Controllers/HomeController.cs
@@ -11,6 +11,7 @@ namespace LearningHub.Nhs.WebUI.Controllers
using LearningHub.Nhs.Models.Content;
using LearningHub.Nhs.Models.Enums.Content;
using LearningHub.Nhs.Models.Extensions;
+ using LearningHub.Nhs.Models.Moodle.API;
using LearningHub.Nhs.WebUI.Configuration;
using LearningHub.Nhs.WebUI.Filters;
using LearningHub.Nhs.WebUI.Helpers;
@@ -218,13 +219,12 @@ public async Task Index(string myLearningDashboard = "my-in-progr
var cataloguesTask = this.dashboardService.GetCataloguesAsync(catalogueDashboard, 1);
var userGroupsTask = this.userGroupService.UserHasCatalogueContributionPermission();
- var enrolledCoursesTask = Task.FromResult(new List());
- var enableMoodle = Task.Run(() => this.featureManager.IsEnabledAsync(FeatureFlags.EnableMoodle)).Result;
- this.ViewBag.EnableMoodle = enableMoodle;
- this.ViewBag.ValidMoodleUser = this.CurrentMoodleUserId > 0;
+ var enrolledCoursesTask = Task.FromResult(new List());
+ (bool enableMoodle, int currentMoodleUserId) = await this.GetMoodleFeatureStateAsync();
+
if (enableMoodle && myLearningDashboard == "my-enrolled-courses")
{
- enrolledCoursesTask = this.dashboardService.GetEnrolledCoursesFromMoodleAsync(this.CurrentMoodleUserId, 1);
+ enrolledCoursesTask = this.dashboardService.GetEnrolledCoursesFromMoodleAsync(currentMoodleUserId, 1);
}
await Task.WhenAll(learningTask, resourcesTask, cataloguesTask, userGroupsTask);
@@ -280,9 +280,7 @@ public async Task LoadPage(string dashBoardTray = "my-learning",
Catalogues = new Nhs.Models.Dashboard.DashboardCatalogueResponseViewModel { Type = catalogueDashBoard },
};
- var enableMoodle = Task.Run(() => this.featureManager.IsEnabledAsync(FeatureFlags.EnableMoodle)).Result;
- this.ViewBag.EnableMoodle = enableMoodle;
- this.ViewBag.ValidMoodleUser = this.CurrentMoodleUserId > 0;
+ (bool enableMoodle, int currentMoodleUserId) = await this.GetMoodleFeatureStateAsync();
bool isAjax = this.HttpContext.Request.Headers["X-Requested-With"] == "XMLHttpRequest";
@@ -449,5 +447,28 @@ private async Task GetLandingPageContent(bool preview = fa
return new LandingPageViewModel { PageSectionDetailViewModels = new List(), PageViewModel = new PageViewModel { PageSections = new List { } } };
}
}
+
+ ///
+ /// Asynchronously retrieves the state of the Moodle feature and the current Moodle user ID.
+ ///
+ /// The method checks if the Moodle feature is enabled and retrieves the current Moodle
+ /// user ID. If the user ID is not already set, it attempts to obtain it asynchronously from the dashboard
+ /// service.
+ /// A tuple containing a boolean indicating whether the Moodle feature is enabled and an integer representing
+ /// the current Moodle user ID.
+ private async Task<(bool enableMoodle, int currentMoodleUserId)> GetMoodleFeatureStateAsync()
+ {
+ var enableMoodle = Task.Run(() => this.featureManager.IsEnabledAsync(FeatureFlags.EnableMoodle)).Result;
+ this.ViewBag.EnableMoodle = enableMoodle;
+ int currentMoodleUserId = this.CurrentMoodleUserId;
+
+ if (currentMoodleUserId == 0)
+ {
+ currentMoodleUserId = await this.dashboardService.GetMoodleUserIdAsync(this.CurrentUserId);
+ }
+
+ this.ViewBag.ValidMoodleUser = currentMoodleUserId > 0;
+ return (enableMoodle, currentMoodleUserId);
+ }
}
}
diff --git a/LearningHub.Nhs.WebUI/Controllers/LoginWizardController.cs b/LearningHub.Nhs.WebUI/Controllers/LoginWizardController.cs
index fab43e688..ab0d07dce 100644
--- a/LearningHub.Nhs.WebUI/Controllers/LoginWizardController.cs
+++ b/LearningHub.Nhs.WebUI/Controllers/LoginWizardController.cs
@@ -144,31 +144,7 @@ public async Task Index(string returnUrl)
if (currentStage?.Id == (int)LoginWizardStageEnum.SecurityQuestions)
{
- SecurityQuestionsViewModel securityQuestions = await this.loginWizardService.GetSecurityQuestionsModel(this.CurrentUserId);
-
- while (securityQuestions.UserSecurityQuestions.Count < this.Settings.SecurityQuestionsToAsk)
- {
- securityQuestions.UserSecurityQuestions.Add(new UserSecurityQuestionViewModel());
- }
-
- foreach (var answer in securityQuestions.UserSecurityQuestions)
- {
- if (!string.IsNullOrEmpty(answer.SecurityQuestionAnswerHash))
- {
- answer.SecurityQuestionAnswerHash = "********";
- }
- }
-
- this.TempData.Clear();
- var securityViewModel = new SecurityViewModel()
- {
- SecurityQuestions = securityQuestions.SecurityQuestions,
- UserSecurityQuestions = securityQuestions.UserSecurityQuestions,
- };
-
- await this.multiPageFormService.SetMultiPageFormData(securityViewModel, MultiPageFormDataFeature.EditRegistrationPrompt, this.TempData);
-
- return this.RedirectToAction("SelectSecurityQuestion", new RouteValueDictionary { { "questionIndex", 0 }, { "returnUrl", returnUrl } });
+ return this.RedirectToAction("SelectSecurityQuestions", new { returnUrl });
}
if (currentStage?.Id == (int)LoginWizardStageEnum.JobRole || currentStage?.Id == (int)LoginWizardStageEnum.PlaceOfWork || currentStage?.Id == (int)LoginWizardStageEnum.PersonalDetails)
@@ -213,11 +189,19 @@ await this.multiPageFormService.SetMultiPageFormData(
{
return this.RedirectToAction("AccountInformationNeeded");
}
+ else if (currentStage?.Id == (int)LoginWizardStageEnum.JobRole || currentStage?.Id == (int)LoginWizardStageEnum.PlaceOfWork)
+ {
+ return this.RedirectToAction("MyEmploymentDetails", "MyAccount", new { returnUrl, checkDetails = true });
+ }
else
{
return this.RedirectToAction("Index", "MyAccount", new { returnUrl, checkDetails = true });
}
}
+ else if (currentStage?.Id == (int)LoginWizardStageEnum.JobRole || currentStage?.Id == (int)LoginWizardStageEnum.PlaceOfWork)
+ {
+ return this.RedirectToAction("MyEmploymentDetails", "MyAccount", new { returnUrl, checkDetails = true });
+ }
else
{
return this.RedirectToAction("Index", "MyAccount", new { returnUrl, checkDetails = true });
@@ -585,6 +569,106 @@ public async Task AccountConfirmationPost()
return this.RedirectToAction("Index", new RouteValueDictionary { { "returnUrl", accountModel.WizardReturnUrl } });
}
+ ///
+ /// Action for starting the security question multiPageForm stage of the wizard.
+ ///
+ /// The URL to return to after the login wizard has been completed.
+ /// The .
+ [ResponseCache(CacheProfileName = "Never")]
+ public async Task SelectSecurityQuestions(string returnUrl)
+ {
+ MyAcountSecurityQuestionsViewModel securityViewModel = new MyAcountSecurityQuestionsViewModel();
+ var result = await this.loginWizardService.GetSecurityQuestionsModel(this.CurrentUserId);
+
+ if (result != null)
+ {
+ securityViewModel.FirstSecurityQuestions = SelectListHelper.MapSelectListWithSelection(result.SecurityQuestions, Convert.ToString(securityViewModel.SelectedFirstQuestionId));
+ securityViewModel.SecondSecurityQuestions = SelectListHelper.MapSelectListWithSelection(result.SecurityQuestions, Convert.ToString(securityViewModel.SelectedSecondQuestionId));
+ }
+
+ this.ViewBag.ReturnUrl = returnUrl;
+ return this.View("SecurityQuestionsDetails", securityViewModel);
+ }
+
+ ///
+ /// Action for choosing security questions.
+ ///
+ /// The MyAcountSecurityQuestionsViewModel.
+ /// The URL to return to after the login wizard has been completed.
+ /// The .
+ [HttpPost]
+ [ResponseCache(CacheProfileName = "Never")]
+ public async Task UpdateSecurityQuestionPost(MyAcountSecurityQuestionsViewModel model, string returnUrl)
+ {
+ MyAcountSecurityQuestionsViewModel securityViewModel = new MyAcountSecurityQuestionsViewModel();
+ var result = await this.loginWizardService.GetSecurityQuestionsModel(this.CurrentUserId);
+
+ if (result != null)
+ {
+ securityViewModel.FirstSecurityQuestions = SelectListHelper.MapSelectListWithSelection(result.SecurityQuestions, Convert.ToString(securityViewModel.SelectedFirstQuestionId));
+ securityViewModel.SecondSecurityQuestions = SelectListHelper.MapSelectListWithSelection(result.SecurityQuestions, Convert.ToString(securityViewModel.SelectedSecondQuestionId));
+ }
+
+ if (model != null)
+ {
+ if (model.SelectedFirstQuestionId == model.SelectedSecondQuestionId)
+ {
+ this.ModelState.AddModelError("DuplicateQuestion", CommonValidationErrorMessages.DuplicateQuestion);
+ }
+
+ if (model.SelectedFirstQuestionId > 0 && string.IsNullOrEmpty(model.SecurityFirstQuestionAnswerHash))
+ {
+ this.ModelState.AddModelError(nameof(model.SecurityFirstQuestionAnswerHash), CommonValidationErrorMessages.InvalidSecurityQuestionAnswer);
+ }
+
+ if (model.SelectedSecondQuestionId > 0 && string.IsNullOrEmpty(model.SecuritySecondQuestionAnswerHash))
+ {
+ this.ModelState.AddModelError(nameof(model.SecuritySecondQuestionAnswerHash), CommonValidationErrorMessages.InvalidSecurityQuestionAnswer);
+ }
+
+ if (this.ModelState.IsValid)
+ {
+ var userSecurityQuestions = new List
+ {
+ new UserSecurityQuestionViewModel
+ {
+ SecurityQuestionId = model.SelectedFirstQuestionId,
+ SecurityQuestionAnswerHash = model.SecurityFirstQuestionAnswerHash,
+ UserId = this.CurrentUserId,
+ },
+ new UserSecurityQuestionViewModel
+ {
+ SecurityQuestionId = model.SelectedSecondQuestionId,
+ SecurityQuestionAnswerHash = model.SecuritySecondQuestionAnswerHash,
+ UserId = this.CurrentUserId,
+ },
+ };
+
+ await this.userService.UpdateUserSecurityQuestions(userSecurityQuestions);
+
+ // Mark stage complete.
+ var (cacheExists, loginWizard) = await this.cacheService.TryGetAsync(this.LoginWizardCacheKey);
+
+ if (cacheExists)
+ {
+ await this.CompleteLoginWizardStageAsync(loginWizard, LoginWizardStageEnum.SecurityQuestions);
+ this.TempData.Clear();
+ return this.RedirectToAction("Index", new RouteValueDictionary { { "returnUrl", returnUrl } });
+ }
+
+ this.TempData.Clear();
+ return this.Redirect("/");
+ }
+ else
+ {
+ this.ViewBag.ReturnUrl = returnUrl;
+ return this.View("SecurityQuestionsDetails", securityViewModel);
+ }
+ }
+
+ return this.View("SecurityQuestionsDetails", securityViewModel);
+ }
+
///
/// The complete login wizard stage.
///
diff --git a/LearningHub.Nhs.WebUI/Controllers/MyAccountController.cs b/LearningHub.Nhs.WebUI/Controllers/MyAccountController.cs
index d1dadb902..feebe7124 100644
--- a/LearningHub.Nhs.WebUI/Controllers/MyAccountController.cs
+++ b/LearningHub.Nhs.WebUI/Controllers/MyAccountController.cs
@@ -131,8 +131,308 @@ public async Task Index(string returnUrl = null, bool? checkDetai
}
}
- var userProfileSummary = await this.userService.GetUserProfileSummaryAsync();
- return this.View("Index", userProfileSummary);
+ var userPersonalDetails = await this.userService.GetMyAccountPersonalDetailsAsync();
+ return this.View("Index", userPersonalDetails);
+ }
+
+ ///
+ /// MyEmploymentDetails.
+ ///
+ /// Whether to check account details.
+ /// IActionResult.
+ [HttpGet]
+ [Route("myaccount-employement")]
+ public async Task MyEmploymentDetails(bool? checkDetails = false)
+ {
+ string loginWizardCacheKey = $"{this.CurrentUserId}:LoginWizard";
+ var (cacheExists, loginWizard) = await this.cacheService.TryGetAsync(loginWizardCacheKey);
+
+ if (checkDetails == true || cacheExists)
+ {
+ this.ViewBag.CheckDetails = true;
+
+ var rules = loginWizard.LoginWizardStagesRemaining.SelectMany(l => l.LoginWizardRules.Where(r => r.Required));
+ foreach (var rule in rules)
+ {
+ this.ModelState.AddModelError(string.Empty, rule.Description);
+ }
+
+ if (this.TempData.ContainsKey("IsJobRoleRequired"))
+ {
+ if (this.TempData["IsJobRoleRequired"] != null && (bool)this.TempData["IsJobRoleRequired"] == true)
+ {
+ this.ModelState.AddModelError(string.Empty, CommonValidationErrorMessages.RoleRequired);
+ this.TempData["IsJobRoleRequired"] = null;
+ }
+ }
+ }
+
+ var employmentDetails = await this.userService.GetMyEmploymentDetailsAsync();
+ return this.View("MyEmployment", employmentDetails);
+ }
+
+ ///
+ /// User profile actions.
+ ///
+ /// The redirect back url.
+ /// Whether to check account details.
+ /// IActionResult.
+ [HttpGet]
+ [Route("myaccount-security")]
+ public async Task MyAccountSecurity(string returnUrl = null, bool? checkDetails = false)
+ {
+ var securityDetails = await this.userService.GetMyAccountSecurityDetailsAsync();
+ return this.View("MyAccountSecurity", securityDetails);
+ }
+
+ ///
+ /// ChangePersonalDetails.
+ ///
+ /// ActionResult.
+ [HttpGet]
+ [Route("myaccount/ChangePersonalDetails")]
+ public async Task ChangePersonalDetails()
+ {
+ var userPersonalDetails = await this.userService.GetMyAccountPersonalDetailsAsync();
+ return this.View("ChangePersonalDetails", userPersonalDetails);
+ }
+
+ ///
+ /// To Update first name.
+ ///
+ /// model.
+ /// ActionResult.
+ [HttpPost]
+ public async Task UpdatePersonalDetails(MyAccountPersonalDetailsViewModel model)
+ {
+ if (!this.ModelState.IsValid)
+ {
+ return this.View("ChangePersonalDetails", model);
+ }
+
+ bool isSamePrimaryEmailPendingforValidate = await this.userService.CheckSamePrimaryemailIsPendingToValidate(model.SecondaryEmailAddress);
+ if (isSamePrimaryEmailPendingforValidate)
+ {
+ this.ModelState.AddModelError(string.Empty, CommonValidationErrorMessages.SecondaryEmailShouldNotBeSame);
+ return this.View("ChangePersonalDetails", model);
+ }
+
+ await this.userService.UpdateMyAccountPersonalDetailsAsync(this.CurrentUserId, model);
+ await this.MyAccountUpdatePrimaryEmail(model.PrimaryEmailAddress);
+ this.ViewBag.SuccessMessage = CommonValidationErrorMessages.PersonalDetailsSuccessMessage;
+ this.ViewBag.MyAction = "Index";
+ return this.View("SuccessMessageMyAccount");
+ }
+
+ ///
+ /// ChangeLocation.
+ ///
+ /// model.
+ /// formSubmission.
+ /// ActionResult.
+ [HttpGet]
+ [Route("myaccount/ChangeLocation")]
+ public async Task ChangeLocation([FromQuery] MyAccountLocationViewModel model, bool formSubmission = false)
+ {
+ var userLocationViewModel = await this.userService.GetMyAccountLocationDetailsAsync();
+ var allUKcountries = await this.countryService.GetAllUKCountries();
+ var allnonUKcountries = await this.countryService.GetAllNonUKCountries();
+ var regions = await this.regionService.GetAllAsync();
+
+ List radio = new List();
+ foreach (var country in allUKcountries)
+ {
+ var newradio = new RadiosItemViewModel(country.Id.ToString(), country.Name, false, country.Name);
+ radio.Add(newradio);
+ }
+
+ if (allnonUKcountries.Any(v => v.Id == userLocationViewModel.SelectedCountryId))
+ {
+ userLocationViewModel.SelectedOtherCountryId = userLocationViewModel.SelectedCountryId;
+ userLocationViewModel.SelectedCountryId = 0;
+ }
+
+ userLocationViewModel.Country = radio;
+ userLocationViewModel.OtherCountryOptions = SelectListHelper.MapOptionsToSelectListItems(allnonUKcountries, userLocationViewModel.SelectedOtherCountryId);
+
+ userLocationViewModel.RegionOptions = SelectListHelper.MapOptionsToSelectListItems(regions, userLocationViewModel.SelectedRegionId);
+
+ if (formSubmission)
+ {
+ if (model?.SelectedCountryId == null)
+ {
+ this.ModelState.AddModelError(nameof(model.SelectedCountryId), CommonValidationErrorMessages.CountryRequired);
+ return this.View("MyAccountChangeLocation", userLocationViewModel);
+ }
+ else if (model.SelectedCountryId == 1 && model.SelectedRegionId == null)
+ {
+ userLocationViewModel.HasSelectedRegion = true;
+ this.ModelState.AddModelError(nameof(model.SelectedRegionId), CommonValidationErrorMessages.RegionRequired);
+ return this.View("MyAccountChangeLocation", userLocationViewModel);
+ }
+ else if (model.SelectedCountryId != 1)
+ {
+ model.SelectedRegionId = null;
+ }
+
+ if (model?.SelectedCountryId == 0)
+ {
+ if (model.SelectedOtherCountryId != null && model.SelectedOtherCountryId > 0)
+ {
+ model.SelectedCountryId = model.SelectedOtherCountryId;
+ }
+ else
+ {
+ userLocationViewModel.HasSelectedOtherCountry = true;
+ this.ModelState.AddModelError(nameof(model.SelectedOtherCountryId), CommonValidationErrorMessages.CountryRequired);
+ return this.View("MyAccountChangeLocation", userLocationViewModel);
+ }
+ }
+
+ if (this.ModelState.IsValid)
+ {
+ await this.userService.UpdateMyAccountLocationDetailsAsync(this.CurrentUserId, model);
+ this.ViewBag.SuccessMessage = CommonValidationErrorMessages.LocationDetailsSuccessMessage;
+ this.ViewBag.MyAction = "MyEmploymentDetails";
+ return this.View("SuccessMessageMyAccount");
+ }
+ }
+
+ return this.View("MyAccountChangeLocation", userLocationViewModel);
+ }
+
+ ///
+ /// SecurityQuestionsDetails.
+ ///
+ /// viewModel.
+ /// formSubmission.
+ /// ActionResult.
+ [HttpGet]
+ [Route("myaccount/MyAccountSecurityQuestionsDetails")]
+ public async Task MyAccountSecurityQuestionsDetails([FromQuery] MyAcountSecurityQuestionsViewModel viewModel, bool formSubmission = false)
+ {
+ MyAcountSecurityQuestionsViewModel securityViewModel = new MyAcountSecurityQuestionsViewModel();
+ var result = await this.loginWizardService.GetSecurityQuestionsModel(this.CurrentUserId);
+
+ if (result != null)
+ {
+ if (result.UserSecurityQuestions != null && result.UserSecurityQuestions.Count > 0)
+ {
+ securityViewModel.SelectedFirstQuestionId = result.UserSecurityQuestions[0].SecurityQuestionId;
+ securityViewModel.SelectedSecondQuestionId = result.UserSecurityQuestions.Count > 1 ? result.UserSecurityQuestions[1].SecurityQuestionId : 0;
+ securityViewModel.UserSecurityFirstQuestionId = result.UserSecurityQuestions[0].Id;
+ securityViewModel.UserSecuritySecondQuestionId = result.UserSecurityQuestions.Count > 1 ? result.UserSecurityQuestions[1].Id : 0;
+ }
+
+ securityViewModel.FirstSecurityQuestions = SelectListHelper.MapSelectListWithSelection(result.SecurityQuestions, Convert.ToString(securityViewModel.SelectedFirstQuestionId));
+ securityViewModel.SecondSecurityQuestions = SelectListHelper.MapSelectListWithSelection(result.SecurityQuestions, Convert.ToString(securityViewModel.SelectedSecondQuestionId));
+ }
+
+ if (formSubmission && viewModel != null)
+ {
+ if (viewModel.SelectedFirstQuestionId == viewModel.SelectedSecondQuestionId)
+ {
+ this.ModelState.AddModelError("DuplicateQuestion", CommonValidationErrorMessages.DuplicateQuestion);
+ return this.View("MyAccountSecurityQuestionsDetails", securityViewModel);
+ }
+
+ if (viewModel.SelectedFirstQuestionId > 0 && string.IsNullOrEmpty(viewModel.SecurityFirstQuestionAnswerHash))
+ {
+ this.ModelState.AddModelError(nameof(viewModel.SecurityFirstQuestionAnswerHash), CommonValidationErrorMessages.InvalidSecurityQuestionAnswer);
+ return this.View("MyAccountSecurityQuestionsDetails", securityViewModel);
+ }
+
+ if (viewModel.SelectedSecondQuestionId > 0 && string.IsNullOrEmpty(viewModel.SecuritySecondQuestionAnswerHash))
+ {
+ this.ModelState.AddModelError(nameof(viewModel.SecuritySecondQuestionAnswerHash), CommonValidationErrorMessages.InvalidSecurityQuestionAnswer);
+ return this.View("MyAccountSecurityQuestionsDetails", securityViewModel);
+ }
+
+ if (this.ModelState.IsValid)
+ {
+ var userSecurityQuestions = new List
+ {
+ new UserSecurityQuestionViewModel
+ {
+ Id = securityViewModel.UserSecurityFirstQuestionId,
+ SecurityQuestionId = viewModel.SelectedFirstQuestionId,
+ SecurityQuestionAnswerHash = viewModel.SecurityFirstQuestionAnswerHash,
+ UserId = this.CurrentUserId,
+ },
+ new UserSecurityQuestionViewModel
+ {
+ Id = securityViewModel.UserSecuritySecondQuestionId,
+ SecurityQuestionId = viewModel.SelectedSecondQuestionId,
+ SecurityQuestionAnswerHash = viewModel.SecuritySecondQuestionAnswerHash,
+ UserId = this.CurrentUserId,
+ },
+ };
+
+ await this.userService.UpdateUserSecurityQuestions(userSecurityQuestions);
+
+ this.ViewBag.SuccessMessage = CommonValidationErrorMessages.SecurityQuestionSuccessMessage;
+ this.ViewBag.MyAction = "MyAccountSecurity";
+ return this.View("SuccessMessageMyAccount");
+ }
+ else
+ {
+ return this.View("MyAccountSecurityQuestionsDetails", securityViewModel);
+ }
+ }
+
+ return this.View("MyAccountSecurityQuestionsDetails", securityViewModel);
+ }
+
+ ///
+ /// To update security questions.
+ ///
+ /// model.
+ /// The .
+ [HttpPost]
+ public async Task UpdateMyAccountSecurityQuestions(MyAcountSecurityQuestionsViewModel model)
+ {
+ bool duplicatesExist = false;
+
+ if (model.SelectedFirstQuestionId == model.SelectedSecondQuestionId)
+ {
+ duplicatesExist = true;
+ }
+
+ if (duplicatesExist)
+ {
+ this.ModelState.AddModelError("DuplicateQuestion", CommonValidationErrorMessages.DuplicateQuestion);
+ return this.View("MyAccountSecurityQuestionsDetails", model);
+ }
+
+ if (this.ModelState.IsValid)
+ {
+ var userSecurityQuestions = new List
+ {
+ new UserSecurityQuestionViewModel
+ {
+ Id = model.UserSecurityFirstQuestionId,
+ SecurityQuestionId = model.SelectedFirstQuestionId,
+ SecurityQuestionAnswerHash = model.SecurityFirstQuestionAnswerHash,
+ UserId = this.CurrentUserId,
+ },
+ new UserSecurityQuestionViewModel
+ {
+ Id = model.UserSecuritySecondQuestionId,
+ SecurityQuestionId = model.SelectedSecondQuestionId,
+ SecurityQuestionAnswerHash = model.SecuritySecondQuestionAnswerHash,
+ UserId = this.CurrentUserId,
+ },
+ };
+
+ await this.userService.UpdateUserSecurityQuestions(userSecurityQuestions);
+
+ this.ViewBag.SuccessMessage = CommonValidationErrorMessages.FirstQuestionSuccessMessage;
+ return this.View("SuccessMessage");
+ }
+ else
+ {
+ return this.View("MyAccountSecurityQuestionsDetails", model);
+ }
}
///
@@ -827,8 +1127,7 @@ await this.userService.UpdateUserEmployment(
LocationId = profile.LocationId,
});
- this.ViewBag.SuccessMessage = "Your job details have been changed";
- return this.View("SuccessMessage");
+ return this.RedirectToAction(nameof(this.ChangePrimarySpecialty), new UserPrimarySpecialtyUpdateViewModel { });
}
else
{
@@ -862,6 +1161,9 @@ public async Task ChangePrimarySpecialty([FromQuery] UserPrimaryS
viewModel.PageSize = UserDetailContentPageSize;
viewModel.CurrentPage = viewModel.CurrentPage == 0 ? 1 : viewModel.CurrentPage;
viewModel.OptionalSpecialtyItem = optionalSpecialty.FirstOrDefault(x => x.Name.ToLower() == "not applicable");
+ viewModel.SelectedGradeId = profile.GradeId?.ToString() ?? null;
+ viewModel.SelectedJobRoleId = profile.JobRoleId;
+ viewModel.SelectedMedicalCouncilNo = profile.MedicalCouncilNo;
if (searchSubmission && string.IsNullOrWhiteSpace(viewModel.FilterText))
{
@@ -887,8 +1189,7 @@ await this.userService.UpdateUserEmployment(
LocationId = profile.LocationId,
});
- this.ViewBag.SuccessMessage = "Your primary specialty has been changed";
- return this.View("SuccessMessage");
+ return this.RedirectToAction(nameof(this.ChangeStartDate), new UserStartDateUpdateViewModel { });
}
else
{
@@ -940,8 +1241,7 @@ await this.userService.UpdateUserEmployment(
LocationId = profile.LocationId,
});
- this.ViewBag.SuccessMessage = "Your job start date has been changed";
- return this.View("SuccessMessage");
+ return this.RedirectToAction(nameof(this.ChangeWorkPlace), new UserWorkPlaceUpdateViewModel { });
}
}
else
@@ -977,45 +1277,6 @@ public async Task ChangeWorkPlace([FromQuery] UserWorkPlaceUpdate
return this.View("ChangeWorkPlace", viewModel);
}
- if (formSubmission && viewModel.SelectedWorkPlaceId.HasValue)
- {
- await this.userService.UpdateUserEmployment(
- new elfhHub.Nhs.Models.Entities.UserEmployment
- {
- Id = profile.EmploymentId,
- UserId = profile.Id,
- JobRoleId = profile.JobRoleId,
- MedicalCouncilId = profile.MedicalCouncilId,
- MedicalCouncilNo = profile.MedicalCouncilNo,
- GradeId = profile.GradeId,
- SpecialtyId = profile.SpecialtyId,
- StartDate = profile.JobStartDate,
- LocationId = viewModel.SelectedWorkPlaceId.Value,
- });
-
- var (cacheExists, loginWizard) = await this.cacheService.TryGetAsync(this.LoginWizardCacheKey);
-
- if (cacheExists && loginWizard.LoginWizardStagesRemaining.Any(l => l.Id == (int)LoginWizardStageEnum.PlaceOfWork))
- {
- await this.loginWizardService.SaveLoginWizardStageActivity(LoginWizardStageEnum.PlaceOfWork, this.CurrentUserId);
-
- var stagePlaceOfWork = loginWizard.LoginWizardStages.FirstOrDefault(s => s.Id == (int)LoginWizardStageEnum.PlaceOfWork);
- loginWizard.LoginWizardStagesCompleted.Add(stagePlaceOfWork);
-
- var loginWizardViewModel = new LoginWizardStagesViewModel
- {
- IsFirstLogin = loginWizard.IsFirstLogin,
- LoginWizardStages = loginWizard.LoginWizardStages,
- LoginWizardStagesCompleted = loginWizard.LoginWizardStagesCompleted,
- };
-
- await this.cacheService.SetAsync(this.LoginWizardCacheKey, Newtonsoft.Json.JsonConvert.SerializeObject(loginWizardViewModel));
- }
-
- this.ViewBag.SuccessMessage = "Your place of work has been changed";
- return this.View("SuccessMessage");
- }
-
if (!string.IsNullOrWhiteSpace(viewModel.FilterText))
{
var locations = await this.locationService.GetPagedFilteredAsync(viewModel.FilterText, viewModel.CurrentPage, viewModel.PageSize);
@@ -1024,6 +1285,54 @@ await this.userService.UpdateUserEmployment(
viewModel.HasItems = locations.Item1 > 0;
}
+ if (formSubmission)
+ {
+ if (viewModel.SelectedWorkPlaceId.HasValue)
+ {
+ await this.userService.UpdateUserEmployment(
+ new elfhHub.Nhs.Models.Entities.UserEmployment
+ {
+ Id = profile.EmploymentId,
+ UserId = profile.Id,
+ JobRoleId = profile.JobRoleId,
+ MedicalCouncilId = profile.MedicalCouncilId,
+ MedicalCouncilNo = profile.MedicalCouncilNo,
+ GradeId = profile.GradeId,
+ SpecialtyId = profile.SpecialtyId,
+ StartDate = profile.JobStartDate,
+ LocationId = viewModel.SelectedWorkPlaceId.Value,
+ });
+
+ var (cacheExists, loginWizard) = await this.cacheService.TryGetAsync(this.LoginWizardCacheKey);
+
+ if (cacheExists && loginWizard.LoginWizardStagesRemaining.Any(l => l.Id == (int)LoginWizardStageEnum.PlaceOfWork))
+ {
+ await this.loginWizardService.SaveLoginWizardStageActivity(LoginWizardStageEnum.PlaceOfWork, this.CurrentUserId);
+
+ var stagePlaceOfWork = loginWizard.LoginWizardStages.FirstOrDefault(s => s.Id == (int)LoginWizardStageEnum.PlaceOfWork);
+ loginWizard.LoginWizardStagesCompleted.Add(stagePlaceOfWork);
+
+ var loginWizardViewModel = new LoginWizardStagesViewModel
+ {
+ IsFirstLogin = loginWizard.IsFirstLogin,
+ LoginWizardStages = loginWizard.LoginWizardStages,
+ LoginWizardStagesCompleted = loginWizard.LoginWizardStagesCompleted,
+ };
+
+ await this.cacheService.SetAsync(this.LoginWizardCacheKey, Newtonsoft.Json.JsonConvert.SerializeObject(loginWizardViewModel));
+ }
+
+ this.ViewBag.SuccessMessage = CommonValidationErrorMessages.EmploymentDetailsUpdated;
+ this.ViewBag.MyAction = "MyEmploymentDetails";
+ return this.View("SuccessMessageMyAccount");
+ }
+ else
+ {
+ this.ModelState.AddModelError(nameof(viewModel.SelectedWorkPlaceId), CommonValidationErrorMessages.WorkPlace);
+ return this.View("ChangeWorkPlace", viewModel);
+ }
+ }
+
return this.View("ChangeWorkPlace", viewModel);
}
@@ -1197,5 +1506,49 @@ public async Task CancelEmailChangeValidationToken()
this.ViewBag.SuccessMessage = CommonValidationErrorMessages.EmailCancelMessage;
return this.View("SuccessMessage");
}
+
+ private async Task MyAccountUpdatePrimaryEmail(string primaryEmailAddress)
+ {
+ bool userPrimaryEmailAddressChanged = false;
+ var user = await this.userService.GetUserByUserIdAsync(this.CurrentUserId);
+ if (user != null)
+ {
+ if (!string.IsNullOrEmpty(primaryEmailAddress) && user.EmailAddress.ToLower() != primaryEmailAddress.ToLower())
+ {
+ userPrimaryEmailAddressChanged = true;
+ }
+ }
+
+ if (userPrimaryEmailAddressChanged)
+ {
+ if (await this.userService.DoesEmailAlreadyExist(primaryEmailAddress))
+ {
+ this.ModelState.AddModelError(
+ nameof(primaryEmailAddress),
+ CommonValidationErrorMessages.DuplicateEmailAddress);
+ }
+ else
+ {
+ var isUserRoleUpgrade = await this.userService.ValidateUserRoleUpgradeAsync(user.EmailAddress, primaryEmailAddress);
+ UserRoleUpgrade userRoleUpgradeModel = new UserRoleUpgrade()
+ {
+ UserId = this.CurrentUserId,
+ EmailAddress = primaryEmailAddress,
+ };
+ if (isUserRoleUpgrade)
+ {
+ userRoleUpgradeModel.UserHistoryTypeId = (int)UserHistoryType.UserRoleUpgarde;
+ }
+ else
+ {
+ userRoleUpgradeModel.UserHistoryTypeId = (int)UserHistoryType.UserDetails;
+ }
+
+ await this.userService.GenerateEmailChangeValidationTokenAndSendEmailAsync(primaryEmailAddress, isUserRoleUpgrade);
+ await this.userService.UpdateUserRoleUpgradeAsync();
+ await this.userService.CreateUserRoleUpgradeAsync(userRoleUpgradeModel);
+ }
+ }
+ }
}
}
\ No newline at end of file
diff --git a/LearningHub.Nhs.WebUI/Controllers/MyLearningController.cs b/LearningHub.Nhs.WebUI/Controllers/MyLearningController.cs
index a791bd5d1..46e449dba 100644
--- a/LearningHub.Nhs.WebUI/Controllers/MyLearningController.cs
+++ b/LearningHub.Nhs.WebUI/Controllers/MyLearningController.cs
@@ -31,7 +31,7 @@
[ServiceFilter(typeof(LoginWizardFilter))]
public class MyLearningController : BaseController
{
- private const int MyLearningPageSize = 10;
+ private const int MyLearningPageSize = 5;
private readonly IMyLearningService myLearningService;
private readonly IResourceService resourceService;
private readonly IHierarchyService hierarchyService;
@@ -94,6 +94,181 @@ public static string RenderRazorViewToString(Controller controller, string viewN
}
}
+ ///////
+ /////// Index.
+ ///////
+ /////// learningRequest.
+ /////// The my learning dashboard type.
+ /////// IActionResult.
+ ////[Route("MyLearning")]
+ ////[Route("MyLearning/activity")]
+ ////[HttpGet]
+ ////[HttpPost]
+ ////public async Task Index(MyLearningViewModel learningRequest = null, string myLearningDashboard = null)
+ ////{
+ //// var myLearningRequestModel = new MyLearningRequestModel
+ //// {
+ //// SearchText = learningRequest.SearchText?.Trim(),
+ //// Skip = learningRequest.CurrentPageIndex * MyLearningPageSize,
+ //// Take = MyLearningPageSize,
+ //// TimePeriod = !string.IsNullOrWhiteSpace(learningRequest.TimePeriod) ? learningRequest.TimePeriod : "allDates",
+ //// StartDate = learningRequest.StartDate,
+ //// EndDate = learningRequest.EndDate,
+ //// Weblink = learningRequest.Weblink,
+ //// File = learningRequest.File,
+ //// Video = learningRequest.Video,
+ //// Article = learningRequest.Article,
+ //// Case = learningRequest.Case,
+ //// Image = learningRequest.Image,
+ //// Audio = learningRequest.Audio,
+ //// Elearning = learningRequest.Elearning,
+ //// Html = learningRequest.Html,
+ //// Assessment = learningRequest.Assessment,
+ //// Complete = learningRequest.Complete,
+ //// Incomplete = learningRequest.Incomplete,
+ //// Passed = learningRequest.Passed,
+ //// Failed = learningRequest.Failed,
+ //// Downloaded = learningRequest.Downloaded,
+ //// Viewed = learningRequest.Viewed,
+ //// Launched = learningRequest.Launched,
+ //// CertificateEnabled = learningRequest.CertificateEnabled,
+ //// };
+
+ //// if (myLearningDashboard != null)
+ //// {
+ //// if (myLearningDashboard == "my-in-progress")
+ //// {
+ //// myLearningRequestModel.Incomplete = true;
+ //// myLearningRequestModel.Failed = true;
+ //// }
+ //// else if (myLearningDashboard == "my-recent-completed")
+ //// {
+ //// myLearningRequestModel.Complete = true;
+ //// myLearningRequestModel.Passed = true;
+ //// myLearningRequestModel.Downloaded = true;
+ //// }
+ //// else if (myLearningDashboard == "my-certificates")
+ //// {
+ //// myLearningRequestModel.CertificateEnabled = true;
+ //// myLearningRequestModel.Complete = true;
+ //// myLearningRequestModel.Passed = true;
+ //// myLearningRequestModel.Downloaded = true;
+ //// }
+ //// }
+
+ //// switch (learningRequest.MyLearningFormActionType)
+ //// {
+ //// case MyLearningFormActionTypeEnum.NextPageChange:
+ //// learningRequest.CurrentPageIndex += 1;
+ //// myLearningRequestModel.Skip = learningRequest.CurrentPageIndex * MyLearningPageSize;
+ //// break;
+
+ //// case MyLearningFormActionTypeEnum.PreviousPageChange:
+ //// learningRequest.CurrentPageIndex -= 1;
+ //// myLearningRequestModel.Skip = learningRequest.CurrentPageIndex * MyLearningPageSize;
+ //// break;
+ //// case MyLearningFormActionTypeEnum.BasicSearch:
+
+ //// myLearningRequestModel = new MyLearningRequestModel
+ //// {
+ //// SearchText = learningRequest.SearchText?.Trim(),
+ //// TimePeriod = !string.IsNullOrWhiteSpace(learningRequest.TimePeriod) ? learningRequest.TimePeriod : "allDates",
+ //// Skip = learningRequest.CurrentPageIndex * MyLearningPageSize,
+ //// Take = MyLearningPageSize,
+ //// };
+ //// break;
+
+ //// case MyLearningFormActionTypeEnum.ApplyWeekFilter:
+ //// myLearningRequestModel = new MyLearningRequestModel
+ //// {
+ //// SearchText = learningRequest.SearchText?.Trim(),
+ //// TimePeriod = "thisWeek",
+ //// Skip = learningRequest.CurrentPageIndex * MyLearningPageSize,
+ //// Take = MyLearningPageSize,
+ //// };
+ //// break;
+ //// case MyLearningFormActionTypeEnum.ApplyMonthFilter:
+ //// myLearningRequestModel = new MyLearningRequestModel
+ //// {
+ //// SearchText = learningRequest.SearchText?.Trim(),
+ //// TimePeriod = "thisMonth",
+ //// Skip = learningRequest.CurrentPageIndex * MyLearningPageSize,
+ //// Take = MyLearningPageSize,
+ //// };
+ //// break;
+
+ //// case MyLearningFormActionTypeEnum.ApplyTwelveMonthFilter:
+ //// myLearningRequestModel = new MyLearningRequestModel
+ //// {
+ //// SearchText = learningRequest.SearchText?.Trim(),
+ //// TimePeriod = "last12Months",
+ //// Skip = learningRequest.CurrentPageIndex * MyLearningPageSize,
+ //// Take = MyLearningPageSize,
+ //// };
+ //// break;
+
+ //// case MyLearningFormActionTypeEnum.ApplyMajorFilters:
+ //// if (learningRequest.TimePeriod == "dateRange")
+ //// {
+ //// if (!this.ModelState.IsValid)
+ //// {
+ //// break;
+ //// }
+
+ //// myLearningRequestModel.TimePeriod = learningRequest.TimePeriod;
+ //// myLearningRequestModel.StartDate = learningRequest.GetStartDate().HasValue ? learningRequest.GetStartDate().Value : null;
+ //// myLearningRequestModel.EndDate = learningRequest.GetEndDate().HasValue ? learningRequest.GetEndDate().Value : null;
+ //// }
+
+ //// break;
+
+ //// case MyLearningFormActionTypeEnum.ClearAllFilters:
+
+ //// myLearningRequestModel = new MyLearningRequestModel
+ //// {
+ //// SearchText = learningRequest.SearchText?.Trim(),
+ //// Skip = learningRequest.CurrentPageIndex * MyLearningPageSize,
+ //// TimePeriod = "allDates",
+ //// Take = MyLearningPageSize,
+ //// };
+ //// break;
+ //// }
+
+ //// ////var result = await this.myLearningService.GetUserRecentMyLearningActivities(myLearningRequestModel);
+ //// var result = await this.myLearningService.GetActivityDetailed(myLearningRequestModel);
+ //// var response = new MyLearningViewModel(myLearningRequestModel);
+ //// if (learningRequest.TimePeriod == "dateRange")
+ //// {
+ //// response.StartDay = learningRequest.StartDay;
+ //// response.StartMonth = learningRequest.StartMonth;
+ //// response.StartYear = learningRequest.StartYear;
+ //// response.EndDay = learningRequest.EndDay;
+ //// response.EndMonth = learningRequest.EndMonth;
+ //// response.EndYear = learningRequest.EndYear;
+ //// }
+
+ //// if (result != null)
+ //// {
+ //// response.TotalCount = result.TotalCount;
+ //// response.Activities = result.Activities.Select(entry => new ActivityDetailedItemViewModel(entry)).ToList();
+ //// if (response.Activities.Any())
+ //// {
+ //// foreach (var activity in response.Activities)
+ //// {
+ //// if (!response.MostRecentResources.Contains(activity.ResourceId))
+ //// {
+ //// activity.IsMostRecent = true;
+ //// response.MostRecentResources.Add(activity.ResourceId);
+ //// }
+ //// }
+ //// }
+ //// }
+
+ //// response.MyLearningPaging = new MyLearningPagingModel() { CurrentPage = learningRequest.CurrentPageIndex, PageSize = MyLearningPageSize, TotalItems = response.TotalCount, HasItems = response.TotalCount > 0 };
+ //// this.ViewBag.MyLearningHelpUrl = this.Settings.SupportUrls.MyLearningHelpUrl;
+ //// return this.View(response);
+ ////}
+
///
/// Index.
///
@@ -104,7 +279,7 @@ public static string RenderRazorViewToString(Controller controller, string viewN
[Route("MyLearning/activity")]
[HttpGet]
[HttpPost]
- public async Task Index(MyLearningViewModel learningRequest = null, string myLearningDashboard = null)
+ public async Task Index(MyLearningUserActivitiesViewModel learningRequest = null, string myLearningDashboard = null)
{
var myLearningRequestModel = new MyLearningRequestModel
{
@@ -216,8 +391,6 @@ public async Task Index(MyLearningViewModel learningRequest = nul
}
myLearningRequestModel.TimePeriod = learningRequest.TimePeriod;
- myLearningRequestModel.StartDate = learningRequest.GetStartDate().HasValue ? learningRequest.GetStartDate().Value : null;
- myLearningRequestModel.EndDate = learningRequest.GetEndDate().HasValue ? learningRequest.GetEndDate().Value : null;
}
break;
@@ -234,33 +407,165 @@ public async Task Index(MyLearningViewModel learningRequest = nul
break;
}
- var result = await this.myLearningService.GetActivityDetailed(myLearningRequestModel);
- var response = new MyLearningViewModel(myLearningRequestModel);
- if (learningRequest.TimePeriod == "dateRange")
- {
- response.StartDay = learningRequest.StartDay;
- response.StartMonth = learningRequest.StartMonth;
- response.StartYear = learningRequest.StartYear;
- response.EndDay = learningRequest.EndDay;
- response.EndMonth = learningRequest.EndMonth;
- response.EndYear = learningRequest.EndYear;
- }
+ var result = await this.myLearningService.GetUserRecentMyLearningActivities(myLearningRequestModel);
+ var response = new MyLearningUserActivitiesViewModel(myLearningRequestModel);
if (result != null)
{
response.TotalCount = result.TotalCount;
- response.Activities = result.Activities.Select(entry => new ActivityDetailedItemViewModel(entry)).ToList();
- if (response.Activities.Any())
+ response.Activities = result.Activities;
+ }
+
+ response.MyLearningPaging = new MyLearningPagingModel() { CurrentPage = learningRequest.CurrentPageIndex, PageSize = MyLearningPageSize, TotalItems = response.TotalCount, HasItems = response.TotalCount > 0 };
+ this.ViewBag.MyLearningHelpUrl = this.Settings.SupportUrls.MyLearningHelpUrl;
+ return this.View(response);
+ }
+
+ ///
+ /// Index.
+ ///
+ /// learningRequest.
+ /// The my learning dashboard type.
+ /// IActionResult.
+ [Route("MyLearning/LearningHistory")]
+ [HttpGet]
+ [HttpPost]
+ public async Task LearningHistory(MyLearningUserActivitiesViewModel learningRequest = null, string myLearningDashboard = null)
+ {
+ var myLearningRequestModel = new MyLearningRequestModel
+ {
+ SearchText = learningRequest.SearchText?.Trim(),
+ Skip = learningRequest.CurrentPageIndex * MyLearningPageSize,
+ Take = MyLearningPageSize,
+ TimePeriod = !string.IsNullOrWhiteSpace(learningRequest.TimePeriod) ? learningRequest.TimePeriod : "allDates",
+ StartDate = learningRequest.StartDate,
+ EndDate = learningRequest.EndDate,
+ Weblink = learningRequest.Weblink,
+ File = learningRequest.File,
+ Video = learningRequest.Video,
+ Article = learningRequest.Article,
+ Case = learningRequest.Case,
+ Image = learningRequest.Image,
+ Audio = learningRequest.Audio,
+ Elearning = learningRequest.Elearning,
+ Html = learningRequest.Html,
+ Assessment = learningRequest.Assessment,
+ Complete = learningRequest.Complete,
+ Incomplete = learningRequest.Incomplete,
+ Passed = learningRequest.Passed,
+ Failed = learningRequest.Failed,
+ Downloaded = learningRequest.Downloaded,
+ Viewed = learningRequest.Viewed,
+ Launched = learningRequest.Launched,
+ CertificateEnabled = learningRequest.CertificateEnabled,
+ Courses = learningRequest.Courses,
+ };
+
+ if (myLearningDashboard != null)
+ {
+ if (myLearningDashboard == "my-in-progress")
{
- foreach (var activity in response.Activities)
+ myLearningRequestModel.Incomplete = true;
+ myLearningRequestModel.Failed = true;
+ }
+ else if (myLearningDashboard == "my-recent-completed")
+ {
+ myLearningRequestModel.Complete = true;
+ myLearningRequestModel.Passed = true;
+ myLearningRequestModel.Downloaded = true;
+ }
+ else if (myLearningDashboard == "my-certificates")
+ {
+ myLearningRequestModel.CertificateEnabled = true;
+ myLearningRequestModel.Complete = true;
+ myLearningRequestModel.Passed = true;
+ myLearningRequestModel.Downloaded = true;
+ }
+ }
+
+ switch (learningRequest.MyLearningFormActionType)
+ {
+ case MyLearningFormActionTypeEnum.NextPageChange:
+ learningRequest.CurrentPageIndex += 1;
+ myLearningRequestModel.Skip = learningRequest.CurrentPageIndex * MyLearningPageSize;
+ break;
+
+ case MyLearningFormActionTypeEnum.PreviousPageChange:
+ learningRequest.CurrentPageIndex -= 1;
+ myLearningRequestModel.Skip = learningRequest.CurrentPageIndex * MyLearningPageSize;
+ break;
+ case MyLearningFormActionTypeEnum.BasicSearch:
+
+ myLearningRequestModel = new MyLearningRequestModel
{
- if (!response.MostRecentResources.Contains(activity.ResourceId))
+ SearchText = learningRequest.SearchText?.Trim(),
+ TimePeriod = !string.IsNullOrWhiteSpace(learningRequest.TimePeriod) ? learningRequest.TimePeriod : "allDates",
+ Skip = learningRequest.CurrentPageIndex * MyLearningPageSize,
+ Take = MyLearningPageSize,
+ };
+ break;
+
+ case MyLearningFormActionTypeEnum.ApplyWeekFilter:
+ myLearningRequestModel = new MyLearningRequestModel
+ {
+ SearchText = learningRequest.SearchText?.Trim(),
+ TimePeriod = "thisWeek",
+ Skip = learningRequest.CurrentPageIndex * MyLearningPageSize,
+ Take = MyLearningPageSize,
+ };
+ break;
+ case MyLearningFormActionTypeEnum.ApplyMonthFilter:
+ myLearningRequestModel = new MyLearningRequestModel
+ {
+ SearchText = learningRequest.SearchText?.Trim(),
+ TimePeriod = "thisMonth",
+ Skip = learningRequest.CurrentPageIndex * MyLearningPageSize,
+ Take = MyLearningPageSize,
+ };
+ break;
+
+ case MyLearningFormActionTypeEnum.ApplyTwelveMonthFilter:
+ myLearningRequestModel = new MyLearningRequestModel
+ {
+ SearchText = learningRequest.SearchText?.Trim(),
+ TimePeriod = "last12Months",
+ Skip = learningRequest.CurrentPageIndex * MyLearningPageSize,
+ Take = MyLearningPageSize,
+ };
+ break;
+
+ case MyLearningFormActionTypeEnum.ApplyMajorFilters:
+ if (learningRequest.TimePeriod == "dateRange")
+ {
+ if (!this.ModelState.IsValid)
{
- activity.IsMostRecent = true;
- response.MostRecentResources.Add(activity.ResourceId);
+ break;
}
+
+ myLearningRequestModel.TimePeriod = learningRequest.TimePeriod;
}
- }
+
+ break;
+
+ case MyLearningFormActionTypeEnum.ClearAllFilters:
+
+ myLearningRequestModel = new MyLearningRequestModel
+ {
+ SearchText = learningRequest.SearchText?.Trim(),
+ Skip = learningRequest.CurrentPageIndex * MyLearningPageSize,
+ TimePeriod = "allDates",
+ Take = MyLearningPageSize,
+ };
+ break;
+ }
+
+ var result = await this.myLearningService.GetUserLearningHistory(myLearningRequestModel);
+ var response = new MyLearningUserActivitiesViewModel(myLearningRequestModel);
+
+ if (result != null)
+ {
+ response.TotalCount = result.TotalCount;
+ response.Activities = result.Activities;
}
response.MyLearningPaging = new MyLearningPagingModel() { CurrentPage = learningRequest.CurrentPageIndex, PageSize = MyLearningPageSize, TotalItems = response.TotalCount, HasItems = response.TotalCount > 0 };
@@ -323,6 +628,50 @@ public async Task ExportToPDF(MyLearningRequestModel myLearningRe
return this.View(new Tuple(userDetails, response));
}
+ ///
+ /// Function to export activity report to pdf.
+ ///
+ /// myLearningRequestModel.
+ /// A representing the result of the asynchronous operation.
+ [Route("/MyLearning/DownloadActivities")]
+ [HttpPost]
+ public async Task DownloadActivities(MyLearningRequestModel myLearningRequestModel)
+ {
+ var filter = myLearningRequestModel;
+ filter.Skip = 0;
+ filter.Take = 999;
+ var userDetails = await this.userService.GetCurrentUserBasicDetailsAsync();
+ var response = new MyLearningUserActivitiesViewModel();
+ var result = await this.myLearningService.GetUserLearningHistory(filter);
+ if (result != null)
+ {
+ response.TotalCount = result.TotalCount;
+ response.Activities = result.Activities;
+ }
+
+ Tuple modelData = Tuple.Create(userDetails, response);
+ var renderedViewHTML = RenderRazorViewToString(this, "DownloadActivityRecords", modelData);
+ ReportStatusModel reportStatusModel = new ReportStatusModel();
+ var pdfReportResponse = await this.pdfReportService.PdfReport(renderedViewHTML, userDetails.Id);
+ if (pdfReportResponse != null)
+ {
+ do
+ {
+ reportStatusModel = await this.pdfReportService.PdfReportStatus(pdfReportResponse);
+ }
+ while (reportStatusModel.Id == 1);
+
+ var pdfReportFile = await this.pdfReportService.GetPdfReportFile(pdfReportResponse);
+ if (pdfReportFile != null)
+ {
+ var fileName = "ActivityReport.pdf";
+ return this.File(pdfReportFile, FileHelper.GetContentTypeFromFileName(fileName), fileName);
+ }
+ }
+
+ return this.View(new Tuple(userDetails, response));
+ }
+
///
/// Gets the played segment data for the progress modal in My Learning screen.
///
@@ -387,6 +736,77 @@ public async Task ViewProgress(int resourceId, int resourceRefere
return this.View(vm);
}
+ ///
+ /// Get user certificates.
+ ///
+ /// The certificateRequest.
+ /// A representing the result of the asynchronous operation.
+ [Route("mylearning/certificates")]
+ [HttpGet]
+ [HttpPost]
+ public async Task Certificates(MyLearningUserCertificatesViewModel certificateRequest = null)
+ {
+ var myLearningRequestModel = new MyLearningRequestModel
+ {
+ SearchText = certificateRequest.SearchText?.Trim(),
+ Skip = certificateRequest.CurrentPageIndex * MyLearningPageSize,
+ Take = MyLearningPageSize,
+ File = certificateRequest.File,
+ Video = certificateRequest.Video,
+ Article = certificateRequest.Article,
+ Case = certificateRequest.Case,
+ Image = certificateRequest.Image,
+ Audio = certificateRequest.Audio,
+ Elearning = certificateRequest.Elearning,
+ Html = certificateRequest.Html,
+ Assessment = certificateRequest.Assessment,
+ Courses = certificateRequest.Courses,
+ };
+
+ switch (certificateRequest.MyLearningFormActionType)
+ {
+ case MyLearningFormActionTypeEnum.NextPageChange:
+ certificateRequest.CurrentPageIndex += 1;
+ myLearningRequestModel.Skip = certificateRequest.CurrentPageIndex * MyLearningPageSize;
+ break;
+
+ case MyLearningFormActionTypeEnum.PreviousPageChange:
+ certificateRequest.CurrentPageIndex -= 1;
+ myLearningRequestModel.Skip = certificateRequest.CurrentPageIndex * MyLearningPageSize;
+ break;
+ case MyLearningFormActionTypeEnum.BasicSearch:
+
+ myLearningRequestModel = new MyLearningRequestModel
+ {
+ SearchText = certificateRequest.SearchText?.Trim(),
+ Skip = certificateRequest.CurrentPageIndex * MyLearningPageSize,
+ Take = MyLearningPageSize,
+ };
+ break;
+ case MyLearningFormActionTypeEnum.ClearAllFilters:
+
+ myLearningRequestModel = new MyLearningRequestModel
+ {
+ SearchText = certificateRequest.SearchText?.Trim(),
+ Skip = certificateRequest.CurrentPageIndex * MyLearningPageSize,
+ Take = MyLearningPageSize,
+ };
+ break;
+ }
+
+ var result = await this.myLearningService.GetUserCertificateDetails(myLearningRequestModel);
+ var response = new MyLearningUserCertificatesViewModel(myLearningRequestModel);
+
+ if (result != null)
+ {
+ response.TotalCount = result.TotalCount;
+ response.UserCertificates = result.Certificates;
+ }
+
+ response.MyLearningPaging = new MyLearningPagingModel() { CurrentPage = certificateRequest.CurrentPageIndex, PageSize = MyLearningPageSize, TotalItems = response.TotalCount, HasItems = response.TotalCount > 0 };
+ return this.View(response);
+ }
+
///
/// Gets the certificate details of an activity.
///
@@ -435,6 +855,7 @@ public async Task GetCertificateDetails(int resourceReferenceId,
/// The minorVersion.
/// The userId.
/// The .
+ [HttpGet]
[HttpPost]
[Route("mylearning/downloadcertificate")]
public async Task DownloadCertificate(int resourceReferenceId, int? majorVersion = 0, int? minorVersion = 0, int? userId = 0)
diff --git a/LearningHub.Nhs.WebUI/Helpers/CommonValidationErrorMessages.cs b/LearningHub.Nhs.WebUI/Helpers/CommonValidationErrorMessages.cs
index c9b3aa7bc..440692fae 100644
--- a/LearningHub.Nhs.WebUI/Helpers/CommonValidationErrorMessages.cs
+++ b/LearningHub.Nhs.WebUI/Helpers/CommonValidationErrorMessages.cs
@@ -229,5 +229,30 @@ public static class CommonValidationErrorMessages
/// Message if the validation token expired.
///
public const string EmailChangeValidationTokenInvalidMessage = "We cannot find the page you are looking for";
+
+ ///
+ /// Message if the validation token expired.
+ ///
+ public const string InvalidSecurityQuestionAnswer = "Enter an answer";
+
+ ///
+ /// Message if the validation token expired.
+ ///
+ public const string EmploymentDetailsUpdated = "Your employment details has been changed";
+
+ ///
+ /// security question Success Message.
+ ///
+ public const string SecurityQuestionSuccessMessage = "Your security questions has been changed";
+
+ ///
+ /// location Success Message.
+ ///
+ public const string LocationDetailsSuccessMessage = "Your location details has been changed";
+
+ ///
+ /// location Success Message.
+ ///
+ public const string PersonalDetailsSuccessMessage = "Your personal details has been changed";
}
}
diff --git a/LearningHub.Nhs.WebUI/Helpers/ResourceTypeEnumMoodle.cs b/LearningHub.Nhs.WebUI/Helpers/ResourceTypeEnumMoodle.cs
deleted file mode 100644
index e0601d156..000000000
--- a/LearningHub.Nhs.WebUI/Helpers/ResourceTypeEnumMoodle.cs
+++ /dev/null
@@ -1,82 +0,0 @@
-namespace LearningHub.Nhs.WebUI.Helpers;
-
-///
-/// Represents the types of resources available in Moodle.
-///
-public enum ResourceTypeEnumMoodle
-{
- ///
- /// The undefined resource type.
- ///
- Undefined,
-
- ///
- /// The article resource type.
- ///
- Article,
-
- ///
- /// The audio resource type.
- ///
- Audio,
-
- ///
- /// The embedded resource type.
- ///
- Embedded,
-
- ///
- /// The equipment resource type.
- ///
- Equipment,
-
- ///
- /// The image resource type.
- ///
- Image,
-
- ///
- /// The SCORM resource type.
- ///
- Scorm,
-
- ///
- /// The video resource type.
- ///
- Video,
-
- ///
- /// The web link resource type.
- ///
- WebLink,
-
- ///
- /// The generic file resource type.
- ///
- GenericFile,
-
- ///
- /// The clinical case resource type.
- ///
- Case,
-
- ///
- /// The assessment resource type.
- ///
- Assessment,
-
- ///
- /// The HTML resource type.
- ///
- Html,
-
- ///
- /// The Moodle resource type.
- ///
- Moodle,
-
- ///
- /// The Moodle course resource type.
- ///
- Course,
-}
\ No newline at end of file
diff --git a/LearningHub.Nhs.WebUI/Helpers/SelectListHelper.cs b/LearningHub.Nhs.WebUI/Helpers/SelectListHelper.cs
new file mode 100644
index 000000000..1dcd3f53e
--- /dev/null
+++ b/LearningHub.Nhs.WebUI/Helpers/SelectListHelper.cs
@@ -0,0 +1,35 @@
+namespace LearningHub.Nhs.WebUI.Helpers
+{
+ using System.Collections.Generic;
+ using System.Linq;
+ using elfhHub.Nhs.Models.Common;
+ using Microsoft.AspNetCore.Mvc.Rendering;
+
+ ///
+ /// SelectListHelper.
+ ///
+ public static class SelectListHelper
+ {
+ ///
+ /// MapOptionsToSelectListItems.
+ ///
+ /// options.
+ /// selectedId.
+ /// SelectListItem.
+ public static IEnumerable MapOptionsToSelectListItems(IEnumerable options, int? selectedId = null)
+ {
+ return options.Select(o => new SelectListItem(o.Name, o.Id.ToString(), o.Id == selectedId)).ToList();
+ }
+
+ ///
+ /// MapSelectListWithSelection.
+ ///
+ /// options.
+ /// selectedId.
+ /// SelectListItem.
+ public static IEnumerable MapSelectListWithSelection(IEnumerable options, string selectedId = null)
+ {
+ return options.Select(o => new SelectListItem(o.Text, o.Value, o.Value == selectedId)).ToList();
+ }
+ }
+}
diff --git a/LearningHub.Nhs.WebUI/Helpers/UtilityHelper.cs b/LearningHub.Nhs.WebUI/Helpers/UtilityHelper.cs
index ef71191f9..e1732d5a3 100644
--- a/LearningHub.Nhs.WebUI/Helpers/UtilityHelper.cs
+++ b/LearningHub.Nhs.WebUI/Helpers/UtilityHelper.cs
@@ -30,25 +30,7 @@ public static class UtilityHelper
{ "genericfile", ResourceTypeEnum.GenericFile },
{ "image", ResourceTypeEnum.Image },
{ "html", ResourceTypeEnum.Html },
- };
-
- /// TODO: Remove this method after adding to Moodle resource types to models project.
- ///
- /// Findwise Moodle resource type dictionary.
- ///
- public static readonly Dictionary FindwiseResourceMoodleTypeDict = new Dictionary()
- {
- { "video", ResourceTypeEnumMoodle.Video },
- { "article", ResourceTypeEnumMoodle.Article },
- { "case", ResourceTypeEnumMoodle.Case },
- { "weblink", ResourceTypeEnumMoodle.WebLink },
- { "audio", ResourceTypeEnumMoodle.Audio },
- { "scorm", ResourceTypeEnumMoodle.Scorm },
- { "assessment", ResourceTypeEnumMoodle.Assessment },
- { "genericfile", ResourceTypeEnumMoodle.GenericFile },
- { "image", ResourceTypeEnumMoodle.Image },
- { "html", ResourceTypeEnumMoodle.Html },
- { "moodle", ResourceTypeEnumMoodle.Course },
+ { "moodle", ResourceTypeEnum.Moodle },
};
///
@@ -166,54 +148,6 @@ public static string GetPrettifiedResourceTypeName(ResourceTypeEnum resourceType
}
}
- /// TODO: Remove this method after adding to Moodle resource types to models project.
- ///
- /// Returns a prettified resource type name, suitable for display in the UI. Includes video/audio duration string.
- ///
- /// The resource type.
- /// The media duration in milliseconds.
- /// The resource type name, and duration if applicable.
- public static string GetPrettifiedResourceTypeNameMoodle(ResourceTypeEnumMoodle resourceType, int? durationInMilliseconds = 0)
- {
- switch (resourceType)
- {
- case ResourceTypeEnumMoodle.Assessment:
- return "Assessment";
- case ResourceTypeEnumMoodle.Article:
- return "Article";
- case ResourceTypeEnumMoodle.Audio:
- string durationText = GetDurationText(durationInMilliseconds ?? 0);
- durationText = string.IsNullOrEmpty(durationText) ? string.Empty : " - " + durationText;
- return "Audio" + durationText;
- case ResourceTypeEnumMoodle.Equipment:
- return "Equipment";
- case ResourceTypeEnumMoodle.Image:
- return "Image";
- case ResourceTypeEnumMoodle.Scorm:
- return "elearning";
- case ResourceTypeEnumMoodle.Video:
- durationText = GetDurationText(durationInMilliseconds ?? 0);
- durationText = string.IsNullOrEmpty(durationText) ? string.Empty : " - " + durationText;
- return "Video" + durationText;
- case ResourceTypeEnumMoodle.WebLink:
- return "Web link";
- case ResourceTypeEnumMoodle.GenericFile:
- return "File";
- case ResourceTypeEnumMoodle.Embedded:
- return "Embedded";
- case ResourceTypeEnumMoodle.Case:
- return "Case";
- case ResourceTypeEnumMoodle.Html:
- return "HTML";
- case ResourceTypeEnumMoodle.Moodle:
- return "Course";
- case ResourceTypeEnumMoodle.Course:
- return "Course";
- default:
- return "File";
- }
- }
-
///
/// Returns a prettified resource type name, suitable for display in the UI. Excludes video/audio duration string.
///
@@ -247,6 +181,8 @@ public static string GetPrettifiedResourceTypeName(ResourceTypeEnum resourceType
return "Case";
case ResourceTypeEnum.Html:
return "HTML";
+ case ResourceTypeEnum.Moodle:
+ return "Course";
default:
return "File";
}
diff --git a/LearningHub.Nhs.WebUI/Helpers/ViewActivityHelper.cs b/LearningHub.Nhs.WebUI/Helpers/ViewActivityHelper.cs
index f3bd9259c..44af540da 100644
--- a/LearningHub.Nhs.WebUI/Helpers/ViewActivityHelper.cs
+++ b/LearningHub.Nhs.WebUI/Helpers/ViewActivityHelper.cs
@@ -4,6 +4,7 @@
using System.Collections.Generic;
using System.Linq;
using LearningHub.Nhs.Models.Enums;
+ using LearningHub.Nhs.Models.MyLearning;
using LearningHub.Nhs.WebUI.Models;
///
@@ -71,6 +72,102 @@ public static string GetResourceTypeText(this ActivityDetailedItemViewModel acti
return typeText;
}
+ ///
+ /// Get resource type details.
+ ///
+ /// resourceType.
+ /// The string.
+ public static string GetResourceTypeDesc(ResourceTypeEnum resourceType)
+ {
+ string typeText = string.Empty;
+ switch (resourceType)
+ {
+ case ResourceTypeEnum.Assessment:
+ typeText = "Assessment";
+ break;
+ case ResourceTypeEnum.Article:
+ typeText = "Article";
+ break;
+ case ResourceTypeEnum.Audio:
+ typeText = "Audio";
+ break;
+ case ResourceTypeEnum.GenericFile:
+ typeText = "File";
+ break;
+ case ResourceTypeEnum.Image:
+ typeText = "Image";
+ break;
+ case ResourceTypeEnum.Scorm:
+ typeText = "elearning";
+ break;
+ case ResourceTypeEnum.Video:
+ typeText = "Video";
+ break;
+ case ResourceTypeEnum.WebLink:
+ typeText = "Web link";
+ break;
+ case ResourceTypeEnum.Case:
+ typeText = "Case";
+ break;
+ case ResourceTypeEnum.Html:
+ typeText = "HTML";
+ break;
+ case ResourceTypeEnum.Moodle:
+ typeText = "Course";
+ break;
+ default:
+ typeText = string.Empty;
+ break;
+ }
+
+ return typeText;
+ }
+
+ ///
+ /// GetActivityStatusDisplayText.
+ ///
+ /// The activity.
+ /// The string.
+ public static string GetActivityStatusDisplayText(MyLearningCombinedActivitiesViewModel activity)
+ {
+ if (activity.ActivityStatus == ActivityStatusEnum.Completed || activity.ActivityStatus == ActivityStatusEnum.Passed || activity.ActivityStatus == ActivityStatusEnum.Passed || activity.ActivityStatus == ActivityStatusEnum.Viewed || activity.ActivityStatus == ActivityStatusEnum.Downloaded)
+ {
+ return "Completed";
+ }
+ else
+ {
+ return "InProgress";
+ }
+ }
+
+ ///
+ /// CanDownloadCertificate.
+ ///
+ /// The activityDetailedItemViewModel.
+ /// The bool.
+ public static bool CanCertificateawarded(this MyLearningCombinedActivitiesViewModel activitiesViewModel)
+ {
+ if (activitiesViewModel.CertificateEnabled == true)
+ {
+ if (activitiesViewModel.ResourceType == ResourceTypeEnum.Scorm)
+ {
+ if (GetActivityStatusDisplayText(activitiesViewModel) == "Completed" || GetActivityStatusDisplayText(activitiesViewModel) == "Passed")
+ {
+ return true;
+ }
+ }
+ else
+ {
+ if (GetActivityStatusDisplayText(activitiesViewModel) == "Completed" || GetActivityStatusDisplayText(activitiesViewModel) == "Passed" || GetActivityStatusDisplayText(activitiesViewModel) == "Downloaded")
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
///
/// GetResourceTypeVerb.
///
@@ -340,6 +437,7 @@ public static Dictionary GetActivityParameters(object model)
var routeData = model.GetType().GetProperties().ToDictionary(p => p.Name, p => p.GetValue(model)?.ToString());
routeData.Remove("MostRecentResources");
routeData.Remove("Activities");
+ routeData.Remove("UserCertificates");
routeData.Remove("TotalCount");
routeData.Remove("MyLearningPaging");
routeData.Remove("Skip");
diff --git a/LearningHub.Nhs.WebUI/Interfaces/ICountryService.cs b/LearningHub.Nhs.WebUI/Interfaces/ICountryService.cs
index 8b5fe7542..916159fe7 100644
--- a/LearningHub.Nhs.WebUI/Interfaces/ICountryService.cs
+++ b/LearningHub.Nhs.WebUI/Interfaces/ICountryService.cs
@@ -29,5 +29,17 @@ public interface ICountryService
///
/// A representing the result of the asynchronous operation.
Task> GetAllAsync();
+
+ ///
+ /// The GetAllUKCountries.
+ ///
+ /// A representing the result of the asynchronous operation.
+ Task> GetAllUKCountries();
+
+ ///
+ /// The GetAllNonUKCountries.
+ ///
+ /// A representing the result of the asynchronous operation.
+ Task> GetAllNonUKCountries();
}
}
diff --git a/LearningHub.Nhs.WebUI/Interfaces/IDashboardService.cs b/LearningHub.Nhs.WebUI/Interfaces/IDashboardService.cs
index 9eb8c3266..70a39d2fb 100644
--- a/LearningHub.Nhs.WebUI/Interfaces/IDashboardService.cs
+++ b/LearningHub.Nhs.WebUI/Interfaces/IDashboardService.cs
@@ -3,6 +3,7 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using LearningHub.Nhs.Models.Dashboard;
+ using LearningHub.Nhs.Models.Moodle.API;
using LearningHub.Nhs.WebUI.Models;
///
@@ -47,6 +48,13 @@ public interface IDashboardService
/// The current User Id type.
/// The page Number.
/// A representing the result of the asynchronous operation.
- Task> GetEnrolledCoursesFromMoodleAsync(int currentUserId, int pageNumber);
+ Task> GetEnrolledCoursesFromMoodleAsync(int currentUserId, int pageNumber);
+
+ ///
+ /// GetEnrolledCoursesFromMoodleAsync.
+ ///
+ /// The current User Id type.
+ /// A representing the result of the asynchronous operation.
+ Task GetMoodleUserIdAsync(int currentUserId);
}
}
diff --git a/LearningHub.Nhs.WebUI/Interfaces/IMoodleApiService.cs b/LearningHub.Nhs.WebUI/Interfaces/IMoodleApiService.cs
index d92c01fad..5796c3482 100644
--- a/LearningHub.Nhs.WebUI/Interfaces/IMoodleApiService.cs
+++ b/LearningHub.Nhs.WebUI/Interfaces/IMoodleApiService.cs
@@ -2,29 +2,34 @@
{
using System.Collections.Generic;
using System.Threading.Tasks;
- using LearningHub.Nhs.Models.Dashboard;
- using LearningHub.Nhs.WebUI.Models;
+ using LearningHub.Nhs.Models.Moodle.API;
+ using MoodleCourseCompletionModel = LearningHub.Nhs.Models.Moodle.API.MoodleCourseCompletionModel;
///
/// IMoodleApiService.
///
public interface IMoodleApiService
{
+ ///
+ /// GetMoodleUserIdByUsernameAsync.
+ ///
+ /// The current LH User Id.
+ /// A representing the result of the asynchronous operation.
+ Task GetMoodleUserIdByUsernameAsync(int currentUserId);
+
///
/// GetEnrolledCoursesAsync.
///
/// Moodle user id.
/// pageNumber.
- /// List of MoodleCourseResponseViewModel.
- Task> GetEnrolledCoursesAsync(int currentUserId, int pageNumber);
+ /// List of MoodleCourseResponseModel.
+ Task> GetEnrolledCoursesAsync(int currentUserId, int pageNumber);
///
- /// GetEnrolledCoursesAsync.
+ /// GetCourseUrl.
///
- /// Moodle user id.
- /// Moodle course id.
- /// pageNumber.
- /// List of MoodleCourseResponseViewModel.
- Task GetCourseCompletionAsync(int userId, int courseId, int pageNumber);
+ /// course Id.
+ /// return course URL.
+ string GetCourseUrl(int courseId);
}
}
diff --git a/LearningHub.Nhs.WebUI/Interfaces/IMyLearningService.cs b/LearningHub.Nhs.WebUI/Interfaces/IMyLearningService.cs
index 726f78477..e9b584cc4 100644
--- a/LearningHub.Nhs.WebUI/Interfaces/IMyLearningService.cs
+++ b/LearningHub.Nhs.WebUI/Interfaces/IMyLearningService.cs
@@ -17,6 +17,20 @@ public interface IMyLearningService
/// The .
Task GetActivityDetailed(MyLearningRequestModel requestModel);
+ ///
+ /// Gets the user recent my leraning activities..
+ ///
+ /// The request model.
+ /// The .
+ Task GetUserRecentMyLearningActivities(MyLearningRequestModel requestModel);
+
+ ///
+ /// Gets the user leraning history.
+ ///
+ /// The request model.
+ /// The .
+ Task GetUserLearningHistory(MyLearningRequestModel requestModel);
+
///
/// Gets the played segment data for the progress modal in My Learning screen.
///
@@ -34,5 +48,19 @@ public interface IMyLearningService
/// The userId.
/// The .
Task> GetResourceCertificateDetails(int resourceReferenceId, int? majorVersion = 0, int? minorVersion = 0, int? userId = 0);
+
+ ///
+ /// Gets the user certificates.
+ ///
+ /// The request model.
+ /// The .
+ Task GetUserCertificateDetails(MyLearningRequestModel requestModel);
+
+ ///
+ /// Gets the resource URL for a given resource reference ID.
+ ///
+ /// resourceReferenceId.
+ /// The .
+ string GetResourceUrl(int resourceReferenceId);
}
}
\ No newline at end of file
diff --git a/LearningHub.Nhs.WebUI/Interfaces/IUserService.cs b/LearningHub.Nhs.WebUI/Interfaces/IUserService.cs
index 19ee0a927..4fda81d60 100644
--- a/LearningHub.Nhs.WebUI/Interfaces/IUserService.cs
+++ b/LearningHub.Nhs.WebUI/Interfaces/IUserService.cs
@@ -478,5 +478,45 @@ public interface IUserService
/// the string.
/// base64 string.
string Base64MD5HashDigest(string szString);
+
+ ///
+ /// The get current user profile for My account.
+ ///
+ /// The .
+ Task GetMyAccountPersonalDetailsAsync();
+
+ ///
+ /// Update MyAccount Personal Details Async.
+ ///
+ /// userId.
+ /// MyAccountPersonalDetailsViewModel.
+ /// The .
+ Task UpdateMyAccountPersonalDetailsAsync(int userId, MyAccountPersonalDetailsViewModel model);
+
+ ///
+ /// Get MyEmployment Details Async.
+ ///
+ /// The .
+ Task GetMyEmploymentDetailsAsync();
+
+ ///
+ /// Get MyAccount Security Details Async.
+ ///
+ /// The .
+ Task GetMyAccountSecurityDetailsAsync();
+
+ ///
+ /// Get MyAccount Location Details Async.
+ ///
+ /// The .
+ Task GetMyAccountLocationDetailsAsync();
+
+ ///
+ /// Update MyAccount Location Details Async.
+ ///
+ /// userId.
+ /// MyAccountLocationViewModel.
+ /// The .
+ Task UpdateMyAccountLocationDetailsAsync(int userId, MyAccountLocationViewModel model);
}
}
diff --git a/LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj b/LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj
index dc2cf661d..43c0f9a35 100644
--- a/LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj
+++ b/LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj
@@ -107,13 +107,13 @@
-
+
-
+
diff --git a/LearningHub.Nhs.WebUI/Models/DashboardViewModel.cs b/LearningHub.Nhs.WebUI/Models/DashboardViewModel.cs
index 9ac98c7e0..d7ddeda0c 100644
--- a/LearningHub.Nhs.WebUI/Models/DashboardViewModel.cs
+++ b/LearningHub.Nhs.WebUI/Models/DashboardViewModel.cs
@@ -2,6 +2,7 @@
{
using System.Collections.Generic;
using LearningHub.Nhs.Models.Dashboard;
+ using LearningHub.Nhs.Models.Moodle.API;
///
/// Defines the .
@@ -33,6 +34,6 @@ public DashboardViewModel()
///
/// Gets or sets a list of enrolled courses to be displayed in the dashboard.
///
- public List EnrolledCourses { get; set; }
+ public List EnrolledCourses { get; set; }
}
}
diff --git a/LearningHub.Nhs.WebUI/Models/MoodleCompletionResponseViewModel.cs b/LearningHub.Nhs.WebUI/Models/MoodleCompletionResponseViewModel.cs
deleted file mode 100644
index 1692a32e6..000000000
--- a/LearningHub.Nhs.WebUI/Models/MoodleCompletionResponseViewModel.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-namespace LearningHub.Nhs.WebUI.Models
-{
- ///
- /// MoodleCompletionResponseViewModel.
- ///
- public class MoodleCompletionResponseViewModel
- {
- ///
- /// Gets or sets the completion status.
- ///
- public string Exception { get; set; }
-
- ///
- /// Gets or sets error code.
- ///
- public string Errorcode { get; set; }
-
- ///
- /// Gets or sets Error message.
- ///
- public string Message { get; set; }
-
- ///
- /// Gets or sets Debug info.
- ///
- public string Debuginfo { get; set; }
- }
-}
diff --git a/LearningHub.Nhs.WebUI/Models/MoodleCourseCompletionViewModel.cs b/LearningHub.Nhs.WebUI/Models/MoodleCourseCompletionViewModel.cs
deleted file mode 100644
index 06eb5cb8f..000000000
--- a/LearningHub.Nhs.WebUI/Models/MoodleCourseCompletionViewModel.cs
+++ /dev/null
@@ -1,103 +0,0 @@
-namespace LearningHub.Nhs.WebUI.Models
-{
- using System.Collections.Generic;
-
- ///
- /// MoodleCourseCompletionViewModel.
- ///
- public class MoodleCourseCompletionViewModel
- {
- ///
- /// Gets or sets the completion status.
- ///
- public CompletStatus CompletionStatus { get; set; }
-
- ///
- /// Gets or sets the list of warnings.
- ///
- public List
public GenericListViewModel OptionalSpecialtyItem { get; set; }
+ ///
+ /// Gets or sets the selected job role id.
+ ///
+ public int? SelectedJobRoleId { get; set; }
+
+ ///
+ /// Gets or sets the selected grade id.
+ ///
+ public string SelectedGradeId { get; set; }
+
+ ///
+ /// Gets or sets the selected medical council number.
+ ///
+ public string SelectedMedicalCouncilNo { get; set; }
+
///
/// sets the list of radio specialty.
///
diff --git a/LearningHub.Nhs.WebUI/Models/UserProfile/UserStartDateUpdateViewModel.cs b/LearningHub.Nhs.WebUI/Models/UserProfile/UserStartDateUpdateViewModel.cs
index 8d45071cd..372427781 100644
--- a/LearningHub.Nhs.WebUI/Models/UserProfile/UserStartDateUpdateViewModel.cs
+++ b/LearningHub.Nhs.WebUI/Models/UserProfile/UserStartDateUpdateViewModel.cs
@@ -30,6 +30,16 @@ public class UserStartDateUpdateViewModel : IValidatableObject
///
public int? Year { get; set; }
+ ///////
+ /////// Gets or sets filter text.
+ ///////
+ ////public string FilterText { get; set; }
+
+ ///
+ /// Gets or sets the selected primary specialty id.
+ ///
+ public int? SelectedPrimarySpecialtyId { get; set; }
+
///
/// Gets or sets the GetDate.
///
diff --git a/LearningHub.Nhs.WebUI/Scripts/vuesrc/notification/notification.vue b/LearningHub.Nhs.WebUI/Scripts/vuesrc/notification/notification.vue
index 25ef12656..84fb2eb0c 100644
--- a/LearningHub.Nhs.WebUI/Scripts/vuesrc/notification/notification.vue
+++ b/LearningHub.Nhs.WebUI/Scripts/vuesrc/notification/notification.vue
@@ -1,7 +1,7 @@
-
{{priorityTypeText}}
+
{{priorityTypeText}}