diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Models/Configuration/AzureBlobSettings.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Models/Configuration/AzureBlobSettings.cs
new file mode 100644
index 000000000..12d6da133
--- /dev/null
+++ b/OpenAPI/LearningHub.Nhs.OpenApi.Models/Configuration/AzureBlobSettings.cs
@@ -0,0 +1,18 @@
+namespace LearningHub.Nhs.OpenApi.Models.Configuration
+{
+ ///
+ /// The AzureBlobSettings.
+ ///
+ public class AzureBlobSettings
+ {
+ ///
+ /// Gets or sets the connectionString.
+ ///
+ public string ConnectionString { get; set; } = null!;
+
+ ///
+ /// Gets or sets the catalogue collection id.
+ ///
+ public string UploadContainer { get; set; } = null!;
+ }
+}
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Models/Configuration/AzureConfig.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Models/Configuration/AzureConfig.cs
new file mode 100644
index 000000000..a63513ff1
--- /dev/null
+++ b/OpenAPI/LearningHub.Nhs.OpenApi.Models/Configuration/AzureConfig.cs
@@ -0,0 +1,13 @@
+namespace LearningHub.Nhs.OpenApi.Models.Configuration
+{
+ ///
+ /// The AzureConfig.
+ ///
+ public class AzureConfig
+ {
+ ///
+ /// Gets or sets the azure blob settings.
+ ///
+ public AzureBlobSettings AzureBlobSettings { get; set; } = null!;
+ }
+}
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Models/Configuration/LearningHubConfig.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Models/Configuration/LearningHubConfig.cs
index 9e2086ee3..c1d37d814 100644
--- a/OpenAPI/LearningHub.Nhs.OpenApi.Models/Configuration/LearningHubConfig.cs
+++ b/OpenAPI/LearningHub.Nhs.OpenApi.Models/Configuration/LearningHubConfig.cs
@@ -14,5 +14,10 @@ public class LearningHubConfig
/// Gets or sets .
///
public string LaunchResourceEndpoint { get; set; } = null!;
+
+ ///
+ /// Gets or sets .
+ ///
+ public string ContentServerUrl { get; set; } = null!;
}
}
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/Hierarchy/ICatalogueNodeVersionRepository.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/Hierarchy/ICatalogueNodeVersionRepository.cs
new file mode 100644
index 000000000..e1137c520
--- /dev/null
+++ b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/Hierarchy/ICatalogueNodeVersionRepository.cs
@@ -0,0 +1,141 @@
+namespace LearningHub.Nhs.OpenApi.Repositories.Interface.Repositories.Hierarchy
+{
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Threading.Tasks;
+ using LearningHub.Nhs.Models.Catalogue;
+ using LearningHub.Nhs.Models.Dashboard;
+ using LearningHub.Nhs.Models.Entities.Hierarchy;
+
+ ///
+ /// The ICatalogueNodeVersionRepository.
+ ///
+ public interface ICatalogueNodeVersionRepository : IGenericRepository
+ {
+ ///
+ /// The get catalogues.
+ ///
+ /// The catalogue ids.
+ /// A representing the result of the asynchronous operation.
+ Task> GetCatalogues(List catalogueIds);
+
+ ///
+ /// The get catalogues.
+ ///
+ /// The .
+ Task> GetPublishedCatalogues();
+
+ ///
+ /// The get catalogues for user.
+ ///
+ /// The userId.
+ /// The .
+ IQueryable GetPublishedCataloguesForUserAsync(int userId);
+
+ ///
+ /// The get basic catalogue.
+ ///
+ /// The catalogueNodeId.
+ /// The .
+ CatalogueNodeVersion GetBasicCatalogue(int catalogueNodeId);
+
+ ///
+ /// The UpdateCatalogueAsync.
+ ///
+ /// The userId.
+ /// The catalogue view model.
+ /// The task.
+ Task UpdateCatalogueAsync(int userId, CatalogueViewModel vm);
+
+ ///
+ /// The UpdateCatalogueOwnerAsync.
+ ///
+ /// The userId.
+ /// The catalogue owner view model.
+ /// The task.
+ Task UpdateCatalogueOwnerAsync(int userId, CatalogueOwnerViewModel vm);
+
+ ///
+ /// The CreateCatalogueAsync.
+ ///
+ /// The userId.
+ /// The catalogue view model.
+ /// The catalogueNodeVersionId.
+ Task CreateCatalogueAsync(int userId, CatalogueViewModel vm);
+
+ ///
+ /// Get Catlogue by reference.
+ ///
+ /// The reference.
+ /// The CatalogueViewModel.
+ Task GetCatalogueAsync(string reference);
+
+ ///
+ /// Get list of Restricted Catalogue AccessRequests for the supplied request.
+ ///
+ /// The restrictedCatalogueAccessRequestsRequestViewModel.
+ /// A RestrictedCatalogueAccessRequestsViewModel.
+ List GetRestrictedCatalogueAccessRequests(RestrictedCatalogueAccessRequestsRequestViewModel restrictedCatalogueAccessRequestsRequestViewModel);
+
+ ///
+ /// Get list of RestrictedCatalogueUsersRequestViewModel for the supplied request.
+ ///
+ /// The restrictedCatalogueUsersRequestViewModel.
+ /// A RestrictedCatalogueUsersViewModel.
+ RestrictedCatalogueUsersViewModel GetRestrictedCatalogueUsers(RestrictedCatalogueUsersRequestViewModel restrictedCatalogueUsersRequestViewModel);
+
+ ///
+ /// The ShowCatalogue.
+ ///
+ /// The UserId.
+ /// The NodeId.
+ /// The Task.
+ Task ShowCatalogue(int userId, int nodeId);
+
+ ///
+ /// Get Restricted Catalogue Summary for the supplied catalogue node id.
+ ///
+ /// The catalogueNodeId.
+ /// A RestrictedCatalogueUsersViewModel.
+ RestrictedCatalogueSummaryViewModel GetRestrictedCatalogueSummary(int catalogueNodeId);
+
+ ///
+ /// Gets catalogues for dashboard based on type.
+ ///
+ /// The dashboard type.
+ /// The page Number.
+ /// The userId.
+ /// Catalogue totals and records.
+ (int TotalCount, List Catalogues) GetCatalogues(string dashboardType, int pageNumber, int userId);
+
+ ///
+ /// Check if a Catalogue with a specific name exists or not.
+ ///
+ /// The catalogue name.
+ /// True if the catalogue exists, otherwise false.
+ Task ExistsAsync(string name);
+
+ ///
+ /// Gets the Node Id for a particular catalogue name.
+ ///
+ /// The catalogue name.
+ /// The catalogue's node id.
+ Task GetNodeIdByCatalogueName(string catalogueName);
+
+ ///
+ /// Gets the catalogues count in alphabet list.
+ ///
+ /// The userId.
+ /// The catalogues alphabet count list.
+ List GetAllCataloguesAlphaCount(int userId);
+
+ ///
+ /// Gets catalogues based on filter character.
+ ///
+ /// The pageSize.
+ /// The filterChar.
+ /// The userId.
+ /// The catalogues.
+ Task> GetAllCataloguesAsync(int pageSize, string filterChar, int userId);
+ }
+}
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/Hierarchy/INodeResourceRepository.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/Hierarchy/INodeResourceRepository.cs
new file mode 100644
index 000000000..dce087b47
--- /dev/null
+++ b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/Hierarchy/INodeResourceRepository.cs
@@ -0,0 +1,53 @@
+namespace LearningHub.Nhs.OpenApi.Repositories.Interface.Repositories.Hierarchy
+{
+ using System.Collections.Generic;
+ using System.Threading.Tasks;
+ using LearningHub.Nhs.Models.Catalogue;
+ using LearningHub.Nhs.Models.Entities.Hierarchy;
+ using LearningHub.Nhs.Models.Enums;
+ using LearningHub.Nhs.Models.Hierarchy;
+
+ ///
+ /// The NodeResourceRepository interface.
+ ///
+ public interface INodeResourceRepository : IGenericRepository
+ {
+ ///
+ /// The get by resource id async.
+ ///
+ /// The resource id.
+ /// The .
+ Task> GetByResourceIdAsync(int resourceId);
+
+ ///
+ /// The get catalogue locations for resource.
+ ///
+ /// The resource id.
+ /// The CatalogueLocationViewModel list.
+ List GetCatalogueLocationsForResource(int resourceId);
+
+ ///
+ /// GetResourcesAsync.
+ ///
+ /// nodeId.
+ /// catalogueOrder.
+ /// offset.
+ /// A representing the result of the asynchronous operation.
+ Task GetResourcesAsync(int nodeId, CatalogueOrder catalogueOrder, int offset);
+
+ ///
+ /// Get All published resources id.
+ ///
+ /// The .
+ Task> GetAllPublishedResourceAsync();
+
+ ///
+ /// Creates or updates the NodeResource record for a draft resource in a node.
+ ///
+ /// The nodeId.
+ /// The resourceId.
+ /// The userId.
+ /// The .
+ Task CreateOrUpdateAsync(int nodeId, int resourceId, int userId);
+ }
+}
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/IBookmarkRepository.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/IBookmarkRepository.cs
new file mode 100644
index 000000000..1244736c5
--- /dev/null
+++ b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/IBookmarkRepository.cs
@@ -0,0 +1,27 @@
+namespace LearningHub.Nhs.Repository.Interface
+{
+ using System.Threading.Tasks;
+ using LearningHub.Nhs.Models.Entities;
+ using LearningHub.Nhs.OpenApi.Repositories.Interface.Repositories;
+
+ ///
+ /// The IRoadmapRepository.
+ ///
+ public interface IBookmarkRepository : IGenericRepository
+ {
+ ///
+ /// The GetById.
+ ///
+ /// The bookmarkId.
+ /// The .
+ Task GetById(int bookmarkId);
+
+ ///
+ /// DeleteFolder.
+ ///
+ /// bookmarkId.
+ /// userId.
+ /// A representing the result of the asynchronous operation.
+ Task DeleteFolder(int bookmarkId, int userId);
+ }
+}
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/IGenericRepository.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/IGenericRepository.cs
new file mode 100644
index 000000000..25969ea32
--- /dev/null
+++ b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/IGenericRepository.cs
@@ -0,0 +1,43 @@
+namespace LearningHub.Nhs.OpenApi.Repositories.Interface.Repositories
+{
+ using System.Linq;
+ using System.Threading.Tasks;
+ using LearningHub.Nhs.Models.Entities;
+
+ ///
+ /// The GenericRepository interface.
+ ///
+ /// Imput type.
+ public interface IGenericRepository
+ where TEntity : EntityBase
+ {
+ ///
+ /// The get all.
+ ///
+ /// The .
+ IQueryable GetAll();
+
+ ///
+ /// The create async.
+ ///
+ /// The user id.
+ /// The entity.
+ /// The .
+ Task CreateAsync(int userId, TEntity entity);
+
+ ///
+ /// The update async.
+ ///
+ /// The user id.
+ /// The entity.
+ /// The .
+ Task UpdateAsync(int userId, TEntity entity);
+
+ ///
+ /// The update.
+ ///
+ /// The user id.
+ /// The entity.
+ void Update(int userId, TEntity entity);
+ }
+}
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/IProviderRepository.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/IProviderRepository.cs
new file mode 100644
index 000000000..2c797be4f
--- /dev/null
+++ b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/IProviderRepository.cs
@@ -0,0 +1,50 @@
+namespace LearningHub.Nhs.OpenApi.Repositories.Interface.Repositories
+{
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Threading.Tasks;
+ using LearningHub.Nhs.Models.Entities;
+ using LearningHub.Nhs.Models.Entities.Resource;
+
+ ///
+ /// The ProviderRepository interface.
+ ///
+ public interface IProviderRepository : IGenericRepository
+ {
+ ///
+ /// The get by id async.
+ ///
+ /// The id.
+ /// The .
+ Task GetByIdAsync(int id);
+
+ ///
+ /// The get by id async.
+ ///
+ /// The id.
+ /// The include children.
+ /// The .
+ Task GetByIdAsync(int id, bool includeChildren);
+
+ ///
+ /// The get by user id async.
+ ///
+ /// The user id.
+ /// The .
+ IQueryable GetProvidersByUserIdAsync(int userId);
+
+ ///
+ /// The get by resource version id async.
+ ///
+ /// The resource version id.
+ /// The .
+ IQueryable GetProvidersByResourceIdAsync(int resourceVersionId);
+
+ ///
+ /// The get by node version id async.
+ ///
+ /// The node version id.
+ /// The .
+ IQueryable GetProvidersByCatalogueIdAsync(int nodeVersionId);
+ }
+}
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/IResourceRepository.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/IResourceRepository.cs
index 52b3dee08..ed16ae016 100644
--- a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/IResourceRepository.cs
+++ b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/IResourceRepository.cs
@@ -15,14 +15,14 @@ public interface IResourceRepository
///
/// .
/// Resources with details.
- public Task> GetResourcesFromIds(IEnumerable resourceIds);
+ Task> GetResourcesFromIds(IEnumerable resourceIds);
///
/// Gets resource references by their original resource reference Ids.
///
/// .
/// Resource references.
- public Task> GetResourceReferencesByOriginalResourceReferenceIds(
+ Task> GetResourceReferencesByOriginalResourceReferenceIds(
IEnumerable originalResourceReferenceIds);
///
@@ -37,6 +37,13 @@ public Task> GetResourceReferencesByOriginalResou
/// GetAchievedCertificatedResourceIds
///
/// .
- public Task> GetAchievedCertificatedResourceIds(int currentUserId);
+ Task> GetAchievedCertificatedResourceIds(int currentUserId);
+
+ ///
+ /// The get by id async.
+ ///
+ /// The id.
+ /// The .
+ Task GetByIdAsync(int id);
}
}
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/IRoleUserGroupRepository.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/IRoleUserGroupRepository.cs
new file mode 100644
index 000000000..7fd1426a1
--- /dev/null
+++ b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/IRoleUserGroupRepository.cs
@@ -0,0 +1,67 @@
+namespace LearningHub.Nhs.OpenApi.Repositories.Interface.Repositories
+{
+ using System.Collections.Generic;
+ using System.Threading.Tasks;
+ using LearningHub.Nhs.Models.Entities;
+ using LearningHub.Nhs.Models.User;
+
+ ///
+ /// The IRoleUserGroupRepository interface.
+ ///
+ public interface IRoleUserGroupRepository : IGenericRepository
+ {
+ ///
+ /// The get by id async.
+ ///
+ /// The id.
+ /// The .
+ Task GetByIdAsync(int id);
+
+ ///
+ /// The get by catalogueNodeId async.
+ ///
+ /// The role id.
+ /// The userGroup id.
+ /// The scope id.
+ /// The .
+ Task GetByRoleIdUserGroupIdScopeIdAsync(int roleId, int userGroupId, int scopeId);
+
+ ///
+ /// The get by role id and catalogue id.
+ ///
+ /// The role id.
+ /// The catalogue node id.
+ /// The .
+ Task> GetByRoleIdCatalogueId(int roleId, int catalogueNodeId);
+
+ ///
+ /// The get by role id and catalogue id that has users.
+ ///
+ /// The role id.
+ /// The catalogue node id.
+ /// The .
+ Task> GetByRoleIdCatalogueIdWithUsers(int roleId, int catalogueNodeId);
+
+ ///
+ /// Get list of RoleUserGroupViewModel for a supplied User Group.
+ ///
+ /// The userGroupId.
+ /// A list of RoleUserGroupViewModel.
+ Task> GetRoleUserGroupViewModelsByUserGroupId(int userGroupId);
+
+ ///
+ /// Get list of RoleUserGroupViewModel for a supplied User Group.
+ ///
+ /// The userGroupId.
+ /// A list of RoleUserGroupViewModel.
+ Task> GetRoleUserGroupViewModelsByUserId(int userId);
+
+ ///
+ /// The get all for search.
+ ///
+ /// The catalogueNodeId.
+ /// The userId.
+ /// The .
+ Task> GetAllforSearch(int catalogueNodeId, int userId);
+ }
+}
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/ITimezoneOffsetManager.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/ITimezoneOffsetManager.cs
new file mode 100644
index 000000000..15f4b8bf1
--- /dev/null
+++ b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/ITimezoneOffsetManager.cs
@@ -0,0 +1,22 @@
+namespace LearningHub.Nhs.OpenApi.Repositories.Interface.Repositories
+{
+ using System;
+
+ ///
+ /// The TimezoneOffsetManager interface.
+ ///
+ public interface ITimezoneOffsetManager
+ {
+ ///
+ /// Gets User Timezone Offset.
+ ///
+ int? UserTimezoneOffset { get; }
+
+ ///
+ /// Converts a UTC DateTimeOffset to the timezone of the current user.
+ ///
+ /// The UTC DateTimeOffset to convert.
+ /// .
+ DateTimeOffset ConvertToUserTimezone(DateTimeOffset utcDate);
+ }
+}
\ No newline at end of file
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/Resources/IBlockCollectionRepository.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/Resources/IBlockCollectionRepository.cs
new file mode 100644
index 000000000..33762762b
--- /dev/null
+++ b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/Resources/IBlockCollectionRepository.cs
@@ -0,0 +1,44 @@
+namespace LearningHub.Nhs.OpenApi.Repositories.Interface.Repositories.Resources
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Threading.Tasks;
+ using LearningHub.Nhs.Models.Entities.Resource.Blocks;
+ using LearningHub.Nhs.Models.Enums;
+
+ ///
+ /// The BlockRepository interface.
+ ///
+ public interface IBlockCollectionRepository : IGenericRepository
+ {
+ ///
+ /// Delete the Block Collection.
+ ///
+ /// The User Id.
+ /// The Block Collection Id.
+ /// The .
+ Task DeleteBlockCollection(int userId, int blockCollectionId);
+
+ ///
+ /// Gets the Block Collection.
+ ///
+ /// The Block Collection Id.
+ /// The .
+ Task GetBlockCollection(int? blockCollectionId);
+
+ ///
+ /// Gets the Question blocks for a particular blockCollectionId.
+ ///
+ /// The Block Collection Id.
+ /// The .
+ Task> GetQuestionBlocks(int blockCollectionId);
+
+ ///
+ /// Gets the Case, AssessmentContent, AssessmentGuidance Block Collections (including child Blocks, TextBlocks, WholeSlideImageBlocks and Files) except that of the provided resource version.
+ ///
+ /// The excluded ResourceVersion Id.
+ /// The resource type.
+ /// The .
+ Task GetResourceBlockCollectionsFileAsync(int excludeResourceVersionId, ResourceTypeEnum resourceTypeEnum);
+ }
+}
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/Resources/ICaseResourceVersionRepository.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/Resources/ICaseResourceVersionRepository.cs
new file mode 100644
index 000000000..af9c600bc
--- /dev/null
+++ b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/Resources/ICaseResourceVersionRepository.cs
@@ -0,0 +1,18 @@
+namespace LearningHub.Nhs.OpenApi.Repositories.Interface.Repositories.Resources
+{
+ using System.Threading.Tasks;
+ using LearningHub.Nhs.Models.Entities.Resource;
+
+ ///
+ /// The CaseResourceVersionRepository interface.
+ ///
+ public interface ICaseResourceVersionRepository : IGenericRepository
+ {
+ ///
+ /// The get by Resource Version Id async.
+ ///
+ /// The Resource Version Id.
+ /// The .
+ Task GetByResourceVersionIdAsync(int resourceVersionId);
+ }
+}
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/Resources/IFileRepository.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/Resources/IFileRepository.cs
new file mode 100644
index 000000000..7baf4ed9d
--- /dev/null
+++ b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/Resources/IFileRepository.cs
@@ -0,0 +1,18 @@
+namespace LearningHub.Nhs.OpenApi.Repositories.Interface.Repositories.Resources
+{
+ using System.Threading.Tasks;
+ using LearningHub.Nhs.Models.Entities.Resource;
+
+ ///
+ /// The FileRepository interface.
+ ///
+ public interface IFileRepository : IGenericRepository
+ {
+ ///
+ /// The get by id async.
+ ///
+ /// The id.
+ /// The .
+ Task GetByIdAsync(int id);
+ }
+}
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/Resources/IFileTypeRepository.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/Resources/IFileTypeRepository.cs
new file mode 100644
index 000000000..33ca0ec23
--- /dev/null
+++ b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/Resources/IFileTypeRepository.cs
@@ -0,0 +1,18 @@
+namespace LearningHub.Nhs.OpenApi.Repositories.Interface.Repositories.Resources
+{
+ using System.Threading.Tasks;
+ using LearningHub.Nhs.Models.Entities.Resource;
+
+ ///
+ /// The FileTypeRepository interface.
+ ///
+ public interface IFileTypeRepository : IGenericRepository
+ {
+ ///
+ /// The get by id async.
+ ///
+ /// The id.
+ /// The .
+ Task GetByIdAsync(int id);
+ }
+}
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/Resources/IGenericFileResourceVersionRepository.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/Resources/IGenericFileResourceVersionRepository.cs
new file mode 100644
index 000000000..e4e449b9d
--- /dev/null
+++ b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/Resources/IGenericFileResourceVersionRepository.cs
@@ -0,0 +1,35 @@
+namespace LearningHub.Nhs.OpenApi.Repositories.Interface.Repositories.Resources
+{
+ using System.Threading.Tasks;
+ using LearningHub.Nhs.Models.Entities.Resource;
+ using LearningHub.Nhs.Models.Resource;
+
+ ///
+ /// The GenericFileResourceVersionRepository interface.
+ ///
+ public interface IGenericFileResourceVersionRepository : IGenericRepository
+ {
+ ///
+ /// The get by id async.
+ ///
+ /// The id.
+ /// The .
+ Task GetByIdAsync(int id);
+
+ ///
+ /// The get by resource version id async.
+ ///
+ /// The id.
+ /// Allows deleted items to be returned.
+ /// The .
+ Task GetByResourceVersionIdAsync(int id, bool includeDeleted = false);
+
+ ///
+ /// The get by resource version id.
+ ///
+ /// The id.
+ /// Allows deleted items to be returned.
+ /// The generic file resource version.
+ GenericFileResourceVersion GetByResourceVersionId(int id, bool includeDeleted = false);
+ }
+}
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/Resources/IHtmlResourceVersionRepository.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/Resources/IHtmlResourceVersionRepository.cs
new file mode 100644
index 000000000..3def3f0b9
--- /dev/null
+++ b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/Resources/IHtmlResourceVersionRepository.cs
@@ -0,0 +1,34 @@
+namespace LearningHub.Nhs.OpenApi.Repositories.Interface.Repositories.Resources
+{
+ using System.Threading.Tasks;
+ using LearningHub.Nhs.Models.Entities.Resource;
+
+ ///
+ /// The GenericFileResourceVersionRepository interface.
+ ///
+ public interface IHtmlResourceVersionRepository : IGenericRepository
+ {
+ ///
+ /// The get by id async.
+ ///
+ /// The id.
+ /// The .
+ Task GetByIdAsync(int id);
+
+ ///
+ /// The get by resource version id async.
+ ///
+ /// The id.
+ /// Allows deleted items to be returned.
+ /// The .
+ Task GetByResourceVersionIdAsync(int id, bool includeDeleted = false);
+
+ ///
+ /// The get by resource version id.
+ ///
+ /// The id.
+ /// Allows deleted items to be returned.
+ /// The html resource version.
+ HtmlResourceVersion GetByResourceVersionId(int id, bool includeDeleted = false);
+ }
+}
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/Resources/IResourceVersionRepository.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/Resources/IResourceVersionRepository.cs
new file mode 100644
index 000000000..b2e296682
--- /dev/null
+++ b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/Resources/IResourceVersionRepository.cs
@@ -0,0 +1,303 @@
+namespace LearningHub.Nhs.OpenApi.Repositories.Interface.Repositories.Resources
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Threading.Tasks;
+ using LearningHub.Nhs.Models.Dashboard;
+ using LearningHub.Nhs.Models.Entities.Resource;
+ using LearningHub.Nhs.Models.Enums;
+ using LearningHub.Nhs.Models.Resource;
+ using LearningHub.Nhs.Models.Resource.ResourceDisplay;
+
+ ///
+ /// The ResourceVersionRepository interface.
+ ///
+ public interface IResourceVersionRepository : IGenericRepository
+ {
+ ///
+ /// The get all admin search.
+ ///
+ /// The userId.
+ /// The .
+ IQueryable GetAllAdminSearch(int userId);
+
+ ///
+ /// The get by id async.
+ ///
+ /// The id.
+ /// The include events.
+ /// The .
+ Task GetByIdAsync(int id, bool includeEvents);
+
+ ///
+ /// The get basic by id async.
+ ///
+ /// The id.
+ /// The .
+ Task GetBasicByIdAsync(int id);
+
+ ///
+ /// The contribution totals.
+ ///
+ /// The user id.
+ /// The catalogue id.
+ /// The MyContributionsTotalsViewModel.
+ MyContributionsTotalsViewModel GetMyContributionTotals(int userId, int catalogueId);
+
+ ///
+ /// Get resource cards.
+ ///
+ /// The include events.
+ /// The .
+ Task> GetResourceCards(bool includeEvents);
+
+ ///
+ /// The get current for resource async.
+ ///
+ /// The resource Id.
+ /// The .
+ Task GetCurrentForResourceAsync(int resourceId);
+
+ ///
+ /// The get current resource for resourceid async.
+ ///
+ /// The resource Id.
+ /// The .
+ Task GetCurrentResourceDetailsAsync(int resourceId);
+
+ ///
+ /// The get resource version details by id async.
+ ///
+ /// The resourceVersionId.
+ /// The .
+ Task GetByResourceVersionByIdAsync(int resourceVersionId);
+
+ ///
+ /// The check dev id already exists in the table async.
+ ///
+ /// The devId.
+ /// The .
+ Task DoesDevIdExistsAync(string devId);
+
+ ///
+ /// The get current published for resource async.
+ ///
+ /// The resource id.
+ /// The .
+ Task GetCurrentPublicationForResourceAsync(int resourceId);
+
+ ///
+ /// The get current for resource reference id async.
+ ///
+ /// The resource reference id.
+ /// The .
+ Task GetCurrentForResourceReferenceIdAsync(int resourceReferenceId);
+
+ ///
+ /// The get current resource for resource reference id async.
+ ///
+ /// The resource reference id.
+ /// The .
+ Task GetCurrentResourceForResourceReferenceIdAsync(int resourceReferenceId);
+
+ ///
+ /// The get current published for resource reference id async.
+ ///
+ /// The resource reference id.
+ /// The .
+ Task GetCurrentPublicationForResourceReferenceIdAsync(int resourceReferenceId);
+
+ ///
+ /// The set resource type.
+ ///
+ /// The resource version id.
+ /// The resource type enum.
+ /// The user id.
+ void SetResourceType(int resourceVersionId, ResourceTypeEnum resourceTypeEnum, int userId);
+
+ ///
+ /// Gets the resource type of a ResourceVersion.
+ ///
+ /// The resourceVersionId.
+ /// The .
+ Task GetResourceType(int resourceVersionId);
+
+ ///
+ /// The publish.
+ ///
+ /// The resource version id.
+ /// The is major revision.
+ /// The notes.
+ /// The publication date. Set to null if not giving the resource a publication date in the past. This parameter is intended for use by the migration tool.
+ /// The user id.
+ /// The publication id.
+ int Publish(int resourceVersionId, bool isMajorRevision, string notes, DateTimeOffset? publicationDate, int userId);
+
+ ///
+ /// The unpublish.
+ ///
+ /// The resource version id.
+ /// The details.
+ /// The user id.
+ void Unpublish(int resourceVersionId, string details, int userId);
+
+ ///
+ /// The revert to draft.
+ ///
+ /// The resource version id.
+ /// The user id.
+ void RevertToDraft(int resourceVersionId, int userId);
+
+ ///
+ /// Delete a resource version.
+ ///
+ /// The resource version id.
+ /// The user id.
+ void Delete(int resourceVersionId, int userId);
+
+ ///
+ /// The get resource versions.
+ ///
+ /// The resource id.
+ /// The .
+ Task> GetResourceVersionsAsync(int resourceId);
+
+ /////
+ ///// The create activity.
+ /////
+ /////
+ ///// The user id.
+ /////
+ /////
+ ///// The resource version id.
+ /////
+ /////
+ ///// The activity status enum.
+ /////
+ /////
+ ///// The activity start.
+ /////
+ /////
+ ///// The activity end.
+ /////
+ ////void CreateActivity(
+ // int userId,
+ // int resourceVersionId,
+ // ActivityStatusEnum activityStatusEnum,
+ // DateTimeOffset activityStart,
+ // DateTimeOffset activityEnd);
+
+ ///
+ /// Check if a user has completed the activity corresponding to the resource version.
+ ///
+ /// The user id.
+ /// The resource version id.
+ /// A boolean.
+ Task HasUserCompletedActivity(int userId, int resourceVersionId);
+
+ ///
+ /// Return whether a version at a specific status currently exists.
+ ///
+ /// The resource id.
+ /// The resource version status id.
+ /// Whether the resource version exists or not.
+ Task DoesVersionExist(int resourceId, VersionStatusEnum draft);
+
+ ///
+ /// Return whether a version at a specific status currently exists.
+ ///
+ /// The resource id.
+ /// The user id.
+ /// Returns the new resource version id.
+ Task CreateNextVersionAsync(int resourceId, int userId);
+
+ ///
+ /// Duplicates a resource version.
+ ///
+ /// The resource id.
+ /// The user id.
+ /// Returns the new resource version id.
+ Task CreateDuplicateVersionAsync(int resourceId, int userId);
+
+ ///
+ /// The publishing.
+ ///
+ /// The resource version id.
+ /// The user id.
+ void Publishing(int resourceVersionId, int userId);
+
+ ///
+ /// "Failed to publish".
+ ///
+ /// The resource version id.
+ /// The user id.
+ void FailedToPublish(int resourceVersionId, int userId);
+
+ ///
+ /// The submit publishing.
+ ///
+ /// The resource version id.
+ /// The user id.
+ void SubmitForPublishing(int resourceVersionId, int userId);
+
+ ///
+ /// Create resource version event.
+ ///
+ /// resourceVersionId.
+ /// resourceVersionEventType.
+ /// details.
+ /// user id.
+ void CreateResourceVersionEvent(int resourceVersionId, ResourceVersionEventTypeEnum resourceVersionEventType, string details, int userId);
+
+ ///
+ /// Get Contributions.
+ ///
+ /// The userId.
+ /// The ResourceContributionsRequestViewModel.
+ /// A list of contributed resources.
+ List GetContributions(int userId, ResourceContributionsRequestViewModel resourceContributionsRequestViewModel);
+
+ ///
+ /// The GetResourceVersionForIdList.
+ ///
+ /// List of resource version ids.
+ /// The resource version list.
+ Task> GetResourceVersionsForSearchSubmission(List resourceVersionIds);
+
+ ///
+ /// Gets resources for dashboard based on type.
+ ///
+ /// The dashboard type.
+ /// The page Number.
+ /// The userId.
+ /// resources.
+ (int resourceCount, List resources) GetResources(string dashboardType, int pageNumber, int userId);
+
+ ///
+ /// Copy the blocks from source to destination.
+ ///
+ /// The user id.
+ /// The source block collection id.
+ /// The destination block collection id.
+ /// The blocks to be duplicated.
+ /// The .
+ Task FractionalDuplication(int userId, int sourceBlockCollectionId, int destinationBlockCollectionId, List blocks);
+
+ ///
+ /// Gets external content details.
+ ///
+ /// resourceVersionId.
+ /// userId.
+ /// A representing the result of the asynchronous operation.
+ Task GetExternalContentDetails(int resourceVersionId, int userId);
+
+ ///
+ /// To update dev id details.
+ ///
+ /// The userId.
+ /// The resourceVersionDevIdViewModel.
+ /// The .
+ Task UpdateDevIdAsync(int userId, ResourceVersionDevIdViewModel resourceVersionDevIdViewModel);
+ }
+}
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/Resources/IScormResourceVersionRepository.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/Resources/IScormResourceVersionRepository.cs
new file mode 100644
index 000000000..2fefbe739
--- /dev/null
+++ b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/Resources/IScormResourceVersionRepository.cs
@@ -0,0 +1,50 @@
+namespace LearningHub.Nhs.OpenApi.Repositories.Interface.Repositories.Resources
+{
+ using System.Collections.Generic;
+ using System.Threading.Tasks;
+ using LearningHub.Nhs.Models.Entities.Resource;
+ using LearningHub.Nhs.Models.Resource;
+
+ ///
+ /// The ScormResourceVersionRepository interface.
+ ///
+ public interface IScormResourceVersionRepository : IGenericRepository
+ {
+ ///
+ /// The get by id async.
+ ///
+ /// The id.
+ /// The .
+ Task GetByIdAsync(int id);
+
+ ///
+ /// The get by resource version id async.
+ ///
+ /// The id.
+ /// The includeDeleted.
+ /// The .
+ Task GetByResourceVersionIdAsync(int id, bool includeDeleted = false);
+
+ ///
+ /// Gets the content details for a particular Learning Hub external reference (guid).
+ ///
+ /// The external reference (guid).
+ /// A ContentServerViewModel.
+ Task GetContentServerDetailsByLHExternalReference(string externalReference);
+
+ ///
+ /// Gets the SCORM content details for a particular historic external URL. These historic URLs have to be supported to
+ /// allow historic ESR links on migrated resources to continue to work.
+ ///
+ /// The external Url.
+ /// A ContentServerViewModel.
+ Task GetScormContentServerDetailsByHistoricExternalUrl(string externalUrl);
+
+ ///
+ /// GetExternalReferenceByResourceId.
+ ///
+ /// Resource id.
+ /// External Reference.
+ Task> GetExternalReferenceByResourceId(int resourceId);
+ }
+}
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/Resources/IWebLinkResourceVersionRepository.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/Resources/IWebLinkResourceVersionRepository.cs
new file mode 100644
index 000000000..7eea30ee3
--- /dev/null
+++ b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/Resources/IWebLinkResourceVersionRepository.cs
@@ -0,0 +1,26 @@
+namespace LearningHub.Nhs.OpenApi.Repositories.Interface.Repositories.Resources
+{
+ using System.Threading.Tasks;
+ using LearningHub.Nhs.Models.Entities.Resource;
+
+ ///
+ /// The WebLinkResourceVersionRepository interface.
+ ///
+ public interface IWebLinkResourceVersionRepository
+ {
+ ///
+ /// The get by resource version id async.
+ ///
+ /// The id.
+ /// The .
+ Task GetByResourceVersionIdAsync(int id);
+
+ ///
+ /// The update async.
+ ///
+ /// The user id.
+ /// The web link resource version.
+ /// The .
+ Task UpdateAsync(int userId, WebLinkResourceVersion webLinkResourceVersion);
+ }
+}
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/EntityFramework/LearningHubDbContext.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/EntityFramework/LearningHubDbContext.cs
index c1ebf721b..be0e6556f 100644
--- a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/EntityFramework/LearningHubDbContext.cs
+++ b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/EntityFramework/LearningHubDbContext.cs
@@ -602,6 +602,32 @@ public LearningHubDbContext(LearningHubDbContextOptions options)
///
public virtual DbSet VideoAsset { get; set; }
+
+ ///
+ /// Gets or sets UserBookmark.
+ ///
+ public virtual DbSet UserBookmark { get; set; }
+
+ ///
+ /// Gets or sets the AllCatalogueAlphabet.
+ ///
+ public virtual DbSet AllCatalogueAlphabetModel { get; set; }
+
+ ///
+ /// Gets or sets the AllCatalogueAlphabet.
+ ///
+ public virtual DbSet AllCatalogueViewModel { get; set; }
+
+ ///
+ /// Gets or sets Provider.
+ ///
+ public virtual DbSet Provider { get; set; }
+
+ ///
+ /// Gets or sets the html resource version.
+ ///
+ public virtual DbSet HtmlResourceVersion { get; set; }
+
///
/// The on model creating.
///
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/Helpers/DateTimeHelper.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/Helpers/DateTimeHelper.cs
new file mode 100644
index 000000000..7133033da
--- /dev/null
+++ b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/Helpers/DateTimeHelper.cs
@@ -0,0 +1,26 @@
+namespace LearningHub.Nhs.OpenApi.Repositories.Helpers
+{
+ using System;
+
+ ///
+ /// Extension methods for DateTime class.
+ ///
+ public static class DateTimeHelper
+ {
+ ///
+ /// Returns the date of the first day of the week, based on the day of week passed in.
+ ///
+ /// The datetime.
+ /// The first day of the week.
+ /// The date of the first day of the week.
+ public static DateTime FirstDateInWeek(this DateTime dt, DayOfWeek weekStartDay)
+ {
+ while (dt.DayOfWeek != weekStartDay)
+ {
+ dt = dt.AddDays(-1);
+ }
+
+ return dt;
+ }
+ }
+}
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/Helpers/TextHelper.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/Helpers/TextHelper.cs
new file mode 100644
index 000000000..e14f17754
--- /dev/null
+++ b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/Helpers/TextHelper.cs
@@ -0,0 +1,37 @@
+namespace LearningHub.Nhs.OpenApi.Repositories.Helpers
+{
+ ///
+ /// The text helper.
+ ///
+ public static class TextHelper
+ {
+ ///
+ /// The Combine Date Components method.
+ ///
+ /// The authoed year.
+ /// The authored month.
+ /// The authored day of month.
+ /// The formatted date.
+ public static string CombineDateComponents(int? authoredYear, int? authoredMonth, int? authoredDayOfMonth)
+ {
+ string returnText = string.Empty;
+ if (authoredYear > 0)
+ {
+ returnText = authoredYear.ToString();
+
+ if (authoredMonth > 0)
+ {
+ string[] monthName = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+ returnText = monthName[(int)authoredMonth - 1] + " " + returnText;
+
+ if (authoredDayOfMonth > 0)
+ {
+ returnText = authoredDayOfMonth.ToString() + " " + returnText;
+ }
+ }
+ }
+
+ return returnText;
+ }
+ }
+}
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/Repositories/BookmarkRepository.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/Repositories/BookmarkRepository.cs
new file mode 100644
index 000000000..375a401b3
--- /dev/null
+++ b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/Repositories/BookmarkRepository.cs
@@ -0,0 +1,57 @@
+namespace LearningHub.Nhs.Repository
+{
+ using System.Linq;
+ using System.Threading.Tasks;
+ using LearningHub.Nhs.Models.Entities;
+ using LearningHub.Nhs.OpenApi.Repositories.EntityFramework;
+ using LearningHub.Nhs.OpenApi.Repositories.Interface.Repositories;
+ using LearningHub.Nhs.OpenApi.Repositories.Repositories;
+ using LearningHub.Nhs.Repository.Interface;
+ using Microsoft.EntityFrameworkCore;
+
+ ///
+ /// The BookmarkRepository.
+ ///
+ public class BookmarkRepository : GenericRepository, IBookmarkRepository
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The dbContext.
+ /// The Timezone offset manager.
+ public BookmarkRepository(LearningHubDbContext dbContext, ITimezoneOffsetManager tzOffsetManager)
+ : base(dbContext, tzOffsetManager)
+ {
+ }
+
+ ///
+ /// The GetById.
+ ///
+ /// The bookmarkId.
+ /// The .
+ public async Task GetById(int bookmarkId)
+ {
+ return await this.DbContext.UserBookmark.SingleAsync(ub => ub.Id == bookmarkId);
+ }
+
+ ///
+ /// DeleteFolder.
+ ///
+ /// bookmarkId.
+ /// userId.
+ /// A representing the result of the asynchronous operation.
+ public async Task DeleteFolder(int bookmarkId, int userId)
+ {
+ var bookmarks = this.DbContext.UserBookmark.Where(ub => ub.Id == bookmarkId || ub.ParentId == bookmarkId);
+
+ foreach (var bookmark in bookmarks)
+ {
+ bookmark.ParentId = null;
+ bookmark.Deleted = true;
+ this.SetAuditFieldsForUpdate(userId, bookmark);
+ }
+
+ await this.DbContext.SaveChangesAsync();
+ }
+ }
+}
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/Repositories/GenericRepository.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/Repositories/GenericRepository.cs
new file mode 100644
index 000000000..cff356d60
--- /dev/null
+++ b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/Repositories/GenericRepository.cs
@@ -0,0 +1,177 @@
+namespace LearningHub.Nhs.OpenApi.Repositories.Repositories
+{
+ using System;
+ using System.Linq;
+ using System.Threading.Tasks;
+ using LearningHub.Nhs.Models.Entities;
+ using LearningHub.Nhs.OpenApi.Repositories.EntityFramework;
+ using LearningHub.Nhs.OpenApi.Repositories.Interface.Repositories;
+ using Microsoft.EntityFrameworkCore;
+
+ ///
+ /// The generic repository.
+ ///
+ /// Input type.
+ public class GenericRepository : IGenericRepository
+ where TEntity : EntityBase
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The db context.
+ /// The Timezone offset manager.
+ public GenericRepository(LearningHubDbContext dbContext, ITimezoneOffsetManager tzOffsetManager)
+ {
+ DbContext = dbContext;
+ TimezoneOffsetManager = tzOffsetManager;
+ }
+
+ ///
+ /// Gets the db context.
+ ///
+ protected LearningHubDbContext DbContext { get; }
+
+ ///
+ /// Gets the TimezoneOffset manager.
+ ///
+ protected ITimezoneOffsetManager TimezoneOffsetManager { get; }
+
+ ///
+ /// The get all.
+ ///
+ /// The .
+ public IQueryable GetAll()
+ {
+ return DbContext.Set().AsNoTracking();
+ }
+
+ ///
+ /// The create async.
+ ///
+ /// The user id.
+ /// The entity.
+ /// The .
+ public virtual async Task CreateAsync(int userId, TEntity entity)
+ {
+ await DbContext.Set().AddAsync(entity);
+ SetAuditFieldsForCreate(userId, entity);
+ try
+ {
+ await DbContext.SaveChangesAsync();
+ }
+ catch (Exception)
+ {
+ throw;
+ }
+
+ DbContext.Entry(entity).State = EntityState.Detached;
+
+ return entity.Id;
+ }
+
+ ///
+ /// The update async.
+ ///
+ /// The user id.
+ /// The entity.
+ /// The .
+ public virtual async Task UpdateAsync(int userId, TEntity entity)
+ {
+ DbContext.Set().Update(entity);
+
+ SetAuditFieldsForUpdate(userId, entity);
+
+ await DbContext.SaveChangesAsync();
+
+ DbContext.Entry(entity).State = EntityState.Detached;
+ }
+
+ ///
+ /// The update.
+ ///
+ /// The user id.
+ /// The entity.
+ public virtual void Update(int userId, TEntity entity)
+ {
+ DbContext.Set().Update(entity);
+
+ SetAuditFieldsForUpdate(userId, entity);
+
+ DbContext.SaveChanges();
+
+ DbContext.Entry(entity).State = EntityState.Detached;
+ }
+
+ ///
+ /// The set audit fields for create.
+ ///
+ /// The user id.
+ /// The entity.
+ public void SetAuditFieldsForCreate(int userId, EntityBase entity)
+ {
+ var amendDate = GetAmendDate();
+
+ entity.Deleted = false;
+ entity.CreateUserId = userId;
+ entity.CreateDate = amendDate;
+ entity.AmendUserId = userId;
+ entity.AmendDate = amendDate;
+ }
+
+ ///
+ /// The set audit fields for create or delete.
+ ///
+ /// The user id.
+ /// The entity.
+ /// Flag used to specify the journey.
+ public void SetAuditFieldsForCreateOrDelete(int userId, EntityBase entity, bool isCreate)
+ {
+ if (isCreate)
+ {
+ SetAuditFieldsForCreate(userId, entity);
+ }
+ else
+ {
+ SetAuditFieldsForDelete(userId, entity);
+ }
+ }
+
+ ///
+ /// The set audit fields for update.
+ ///
+ /// The user id.
+ /// The entity.
+ public void SetAuditFieldsForUpdate(int userId, EntityBase entity)
+ {
+ entity.AmendUserId = userId;
+ entity.AmendDate = GetAmendDate();
+ DbContext.Entry(entity).Property("CreateUserId").IsModified = false;
+ DbContext.Entry(entity).Property("CreateDate").IsModified = false;
+ if (entity.GetType() == typeof(User))
+ {
+ DbContext.Entry(entity).Property("VersionStartTime").IsModified = false;
+ DbContext.Entry(entity).Property("VersionEndTime").IsModified = false;
+ }
+ }
+
+ ///
+ /// The set audit fields for delete.
+ ///
+ /// The user id.
+ /// The entity.
+ public void SetAuditFieldsForDelete(int userId, EntityBase entity)
+ {
+ entity.Deleted = true;
+ entity.AmendUserId = userId;
+ entity.AmendDate = GetAmendDate();
+ DbContext.Entry(entity).Property("CreateUserId").IsModified = false;
+ DbContext.Entry(entity).Property("CreateDate").IsModified = false;
+ }
+
+ private DateTimeOffset GetAmendDate()
+ {
+ var tzOffset = TimezoneOffsetManager.UserTimezoneOffset;
+ return tzOffset.HasValue ? new DateTimeOffset(DateTime.UtcNow.AddMinutes(tzOffset.Value).Ticks, TimeSpan.FromMinutes(tzOffset.Value)) : DateTimeOffset.Now;
+ }
+ }
+}
\ No newline at end of file
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/Repositories/Hierarchy/CatalogueNodeVersionRepository.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/Repositories/Hierarchy/CatalogueNodeVersionRepository.cs
new file mode 100644
index 000000000..ee2dd0f50
--- /dev/null
+++ b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/Repositories/Hierarchy/CatalogueNodeVersionRepository.cs
@@ -0,0 +1,393 @@
+namespace LearningHub.Nhs.OpenApi.Repositories.Repositories.Hierarchy
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Data;
+ using System.Linq;
+ using System.Threading.Tasks;
+ using LearningHub.Nhs.Models.Catalogue;
+ using LearningHub.Nhs.Models.Dashboard;
+ using LearningHub.Nhs.Models.Entities.Hierarchy;
+ using LearningHub.Nhs.Models.Enums;
+ using LearningHub.Nhs.OpenApi.Repositories.EntityFramework;
+ using LearningHub.Nhs.OpenApi.Repositories.Interface.Repositories;
+ using LearningHub.Nhs.OpenApi.Repositories.Interface.Repositories.Hierarchy;
+ using Microsoft.Data.SqlClient;
+ using Microsoft.EntityFrameworkCore;
+
+ ///
+ /// The CatalogueNodeVersionRepository.
+ ///
+ public class CatalogueNodeVersionRepository : GenericRepository, ICatalogueNodeVersionRepository
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The dbContext.
+ /// The Timezone offset manager.
+ public CatalogueNodeVersionRepository(LearningHubDbContext dbContext, ITimezoneOffsetManager tzOffsetManager)
+ : base(dbContext, tzOffsetManager)
+ {
+ }
+
+ ///
+ /// The get basic catalogue.
+ ///
+ /// The catalogueNodeId.
+ /// The .
+ public CatalogueNodeVersion GetBasicCatalogue(int catalogueNodeId)
+ {
+ var catalogue = DbContext.CatalogueNodeVersion.AsNoTracking()
+ .Include(cnv => cnv.NodeVersion.Node)
+ .FirstOrDefault(cnv => cnv.NodeVersion.VersionStatusEnum == VersionStatusEnum.Published
+ && cnv.NodeVersion.NodeId == catalogueNodeId);
+
+ return catalogue;
+ }
+
+ ///
+ /// The get catalogues for id list.
+ ///
+ /// The catalogues ids.
+ /// The .
+ public async Task> GetCatalogues(List catalogueIds)
+ {
+ return await DbContext.CatalogueNodeVersion.AsNoTracking()
+ .Include(r => r.NodeVersion).AsNoTracking()
+ .Include(r => r.NodeVersion.Node).AsNoTracking()
+ .Where(r => !r.Deleted
+ && catalogueIds.Any(catalogueId => catalogueId == r.NodeVersion.NodeId)
+ && r.NodeVersion.Node.CurrentNodeVersionId == r.NodeVersionId
+ && r.NodeVersion.VersionStatusEnum == VersionStatusEnum.Published).ToListAsync();
+ }
+
+ ///
+ /// The get catalogues.
+ ///
+ /// The .
+ public async Task> GetPublishedCatalogues()
+ {
+ return await DbContext.CatalogueNodeVersion.AsNoTracking()
+ .Include(r => r.NodeVersion).AsNoTracking()
+ .Include(r => r.NodeVersion.Node).AsNoTracking()
+ .Where(r => !r.Deleted
+ && r.NodeVersion.Node.CurrentNodeVersionId == r.NodeVersionId
+ && r.NodeVersion.VersionStatusEnum == VersionStatusEnum.Published).ToListAsync();
+ }
+
+ ///
+ /// The get published catalogues for user.
+ ///
+ /// The user id.
+ /// The .
+ public IQueryable GetPublishedCataloguesForUserAsync(int userId)
+ {
+ var communityCatalogue = DbContext.CatalogueNodeVersion.AsNoTracking()
+ .Include(cnv => cnv.NodeVersion.Node)
+ .Where(cnv => cnv.NodeVersion.VersionStatusEnum == VersionStatusEnum.Published
+ && cnv.NodeVersion.NodeId == 1 /* Community Catalogue */);
+
+ var cataloguesForUser = from cnv in DbContext.CatalogueNodeVersion.Include(cnv => cnv.NodeVersion.Node).AsNoTracking()
+ join nv in DbContext.NodeVersion.Where(cnv => cnv.VersionStatusEnum == VersionStatusEnum.Published && !cnv.Deleted) // .Include(nv => nv.Node)
+ on cnv.NodeVersionId equals nv.Id
+ join s in DbContext.Scope.Where(x => !x.Deleted)
+ on nv.NodeId equals s.CatalogueNodeId
+ join rug in DbContext.RoleUserGroup.Where(r => r.RoleId == (int)RoleEnum.Editor && !r.Deleted)
+ on s.Id equals rug.ScopeId
+ join uug in DbContext.UserUserGroup.Where(u => u.UserId == userId && !u.Deleted)
+ on rug.UserGroupId equals uug.UserGroupId
+ join n in DbContext.Node.Where(x => !x.Deleted)
+ on nv.Id equals n.CurrentNodeVersionId
+ select cnv;
+
+ var returnedCatalogues = communityCatalogue.Union(cataloguesForUser).Distinct()
+ .OrderBy(cnv => cnv.NodeVersion.NodeId != 1)
+ .ThenBy(cnv => cnv.Name);
+
+ return returnedCatalogues;
+ }
+
+ ///
+ /// The CreateCatalogueAsync.
+ ///
+ /// The userId.
+ /// The catalogue view model.
+ /// The catalogueNodeVersionId.
+ public async Task CreateCatalogueAsync(int userId, CatalogueViewModel vm)
+ {
+ try
+ {
+ var param0 = new SqlParameter("@p0", SqlDbType.Int) { Value = (int)vm.Status };
+ var param1 = new SqlParameter("@p1", SqlDbType.VarChar) { Value = vm.Name };
+ var param2 = new SqlParameter("@p2", SqlDbType.VarChar) { Value = vm.Url };
+ var param3 = string.IsNullOrEmpty(vm.BadgeUrl)
+ ? new SqlParameter("@p3", SqlDbType.VarChar) { Value = DBNull.Value }
+ : new SqlParameter("@p3", SqlDbType.VarChar) { Value = vm.BadgeUrl };
+ var param4 = string.IsNullOrEmpty(vm.CertificateUrl)
+ ? new SqlParameter("@p4", SqlDbType.VarChar) { Value = DBNull.Value }
+ : new SqlParameter("@p4", SqlDbType.VarChar) { Value = vm.CertificateUrl };
+ var param5 = string.IsNullOrEmpty(vm.CardImageUrl)
+ ? new SqlParameter("@p5", SqlDbType.VarChar) { Value = DBNull.Value }
+ : new SqlParameter("@p5", SqlDbType.VarChar) { Value = vm.CardImageUrl };
+ var param6 = string.IsNullOrEmpty(vm.BannerUrl)
+ ? new SqlParameter("@p6", SqlDbType.VarChar) { Value = DBNull.Value }
+ : new SqlParameter("@p6", SqlDbType.VarChar) { Value = vm.BannerUrl };
+ var param7 = new SqlParameter("@p7", SqlDbType.Int) { Value = (int)vm.ResourceOrder };
+ var param8 = new SqlParameter("@p8", SqlDbType.VarChar) { Value = vm.Description };
+ var param9 = new SqlParameter("@p9", SqlDbType.Int) { Value = userId };
+ var param10 = new SqlParameter("@p10", SqlDbType.Bit) { Value = vm.Hidden };
+ var param11 = new SqlParameter("@p11", SqlDbType.VarChar) { Value = string.Join(",", vm.Keywords) };
+ var param12 = new SqlParameter("@p12", SqlDbType.Bit) { Value = vm.RestrictedAccess };
+ var param13 = new SqlParameter("@p13", SqlDbType.Int) { Value = TimezoneOffsetManager.UserTimezoneOffset ?? (object)DBNull.Value };
+ var param14 = new SqlParameter("@p14", SqlDbType.Int) { Value = vm.CatalogueNodeVersionProvider.ProviderId };
+ var param15 = new SqlParameter("@p15", SqlDbType.Int) { Direction = ParameterDirection.Output };
+
+ await DbContext.Database.ExecuteSqlRawAsync("hierarchy.CatalogueCreate @p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10, @p11, @p12, @p13, @p14, @p15 output", param0, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15);
+
+ int catalogueNodeVersionId = (int)param15.Value;
+
+ return catalogueNodeVersionId;
+ }
+ catch (Exception ex)
+ {
+ throw new Exception(ex.Message);
+ }
+ }
+
+ ///
+ /// The UpdateCatalogueAsync.
+ ///
+ /// The userId.
+ /// The catalogue view model.
+ /// The task.
+ public async Task UpdateCatalogueAsync(int userId, CatalogueViewModel vm)
+ {
+ try
+ {
+ var param0 = new SqlParameter("@p0", SqlDbType.Int) { Value = (int)vm.Status };
+ var param1 = new SqlParameter("@p1", SqlDbType.VarChar) { Value = vm.Name };
+ var param2 = string.IsNullOrEmpty(vm.BadgeUrl)
+ ? new SqlParameter("@p2", SqlDbType.VarChar) { Value = DBNull.Value }
+ : new SqlParameter("@p2", SqlDbType.VarChar) { Value = vm.BadgeUrl };
+ var param3 = string.IsNullOrEmpty(vm.CardImageUrl)
+ ? new SqlParameter("@p3", SqlDbType.VarChar) { Value = DBNull.Value }
+ : new SqlParameter("@p3", SqlDbType.VarChar) { Value = vm.CardImageUrl };
+ var param4 = string.IsNullOrEmpty(vm.BannerUrl)
+ ? new SqlParameter("@p4", SqlDbType.VarChar) { Value = DBNull.Value }
+ : new SqlParameter("@p4", SqlDbType.VarChar) { Value = vm.BannerUrl };
+ var param5 = string.IsNullOrEmpty(vm.CertificateUrl)
+ ? new SqlParameter("@p5", SqlDbType.VarChar) { Value = DBNull.Value }
+ : new SqlParameter("@p5", SqlDbType.VarChar) { Value = vm.CertificateUrl };
+ var param6 = new SqlParameter("@p6", SqlDbType.Int) { Value = (int)vm.ResourceOrder };
+ var param7 = new SqlParameter("@p7", SqlDbType.VarChar) { Value = vm.Description };
+ var param8 = new SqlParameter("@p8", SqlDbType.Int) { Value = userId };
+ var param9 = new SqlParameter("@p9", SqlDbType.VarChar) { Value = string.Join(",", vm.Keywords) };
+ var param10 = new SqlParameter("@p10", SqlDbType.Int) { Value = vm.CatalogueNodeVersionId };
+ var param11 = new SqlParameter("@p11", SqlDbType.Bit) { Value = vm.RestrictedAccess };
+ var param12 = new SqlParameter("@p12", SqlDbType.Int) { Value = TimezoneOffsetManager.UserTimezoneOffset ?? (object)DBNull.Value };
+ var param13 = new SqlParameter("@p13", SqlDbType.Int) { Value = vm.CatalogueNodeVersionProvider.ProviderId };
+
+ await DbContext.Database.ExecuteSqlRawAsync("hierarchy.CatalogueUpdate @p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10, @p11, @p12, @p13", param0, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13);
+ }
+ catch (Exception ex)
+ {
+ throw new Exception(ex.Message);
+ }
+ }
+
+ ///
+ /// The UpdateCatalogueOwnerAsync.
+ ///
+ /// The userId.
+ /// The catalogue owner view model.
+ /// The task.
+ public async Task UpdateCatalogueOwnerAsync(int userId, CatalogueOwnerViewModel vm)
+ {
+ try
+ {
+ var param0 = new SqlParameter("@p0", SqlDbType.VarChar) { Value = vm.OwnerName };
+ var param1 = new SqlParameter("@p1", SqlDbType.VarChar) { Value = vm.OwnerEmailAddress };
+ var param2 = new SqlParameter("@p2", SqlDbType.VarChar) { Value = vm.Notes };
+ var param3 = new SqlParameter("@p3", SqlDbType.Int) { Value = userId };
+ var param4 = new SqlParameter("@p4", SqlDbType.Int) { Value = vm.CatalogueNodeVersionId };
+ var param5 = new SqlParameter("@p5", SqlDbType.Int) { Value = TimezoneOffsetManager.UserTimezoneOffset ?? (object)DBNull.Value };
+
+ await DbContext.Database.ExecuteSqlRawAsync("hierarchy.CatalogueOwnerUpdate @p0, @p1, @p2, @p3, @p4, @p5", param0, param1, param2, param3, param4, param5);
+ }
+ catch (Exception ex)
+ {
+ throw new Exception(ex.Message);
+ }
+ }
+
+ ///
+ /// Get Catlogue by reference.
+ ///
+ /// The reference.
+ /// The CatalogueViewModel.
+ public async Task GetCatalogueAsync(string reference)
+ {
+ return await (from cnv in DbContext.CatalogueNodeVersion.AsNoTracking()
+ join nv in DbContext.NodeVersion.AsNoTracking() on cnv.NodeVersionId equals nv.Id
+ join n in DbContext.Node.AsNoTracking() on cnv.NodeVersionId equals n.CurrentNodeVersionId
+ where cnv.Url != null && cnv.Url.ToLower() == reference.ToLower() && cnv.Deleted == false && nv.VersionStatusEnum == VersionStatusEnum.Published
+ select new CatalogueViewModel
+ {
+ Id = cnv.Id,
+ NodeVersionId = cnv.NodeVersionId,
+ BadgeUrl = cnv.BadgeUrl,
+ BannerUrl = cnv.BannerUrl,
+ CertificateUrl = cnv.CertificateUrl,
+ Name = cnv.Name,
+ Description = cnv.Description,
+ Notes = cnv.Notes,
+ Url = cnv.Url,
+ NodeId = n.Id,
+ CatalogueNodeVersionId = cnv.NodeVersionId,
+ ResourceOrder = cnv.Order,
+ RestrictedAccess = cnv.RestrictedAccess,
+ Hidden = n.Hidden,
+ }).SingleOrDefaultAsync();
+ }
+
+ ///
+ /// Get list of Restricted Catalogue AccessRequests for the supplied request.
+ ///
+ /// The restrictedCatalogueAccessRequestsRequestViewModel.
+ /// A RestrictedCatalogueAccessRequestsViewModel.
+ public List GetRestrictedCatalogueAccessRequests(RestrictedCatalogueAccessRequestsRequestViewModel restrictedCatalogueAccessRequestsRequestViewModel)
+ {
+ var param0 = new SqlParameter("@p0", SqlDbType.Int) { Value = restrictedCatalogueAccessRequestsRequestViewModel.CatalogueNodeId };
+ var param1 = new SqlParameter("@p1", SqlDbType.Bit) { Value = restrictedCatalogueAccessRequestsRequestViewModel.IncludeNew };
+ var param2 = new SqlParameter("@p2", SqlDbType.Bit) { Value = restrictedCatalogueAccessRequestsRequestViewModel.IncludeApproved };
+ var param3 = new SqlParameter("@p3", SqlDbType.Bit) { Value = restrictedCatalogueAccessRequestsRequestViewModel.IncludeDenied };
+
+ var restrictedCatalogueAccessRequests = DbContext.RestrictedCatalogueAccessRequestViewModel.FromSqlRaw("hub.RestrictedCatalogueGetAccessRequests @p0, @p1, @p2, @p3", param0, param1, param2, param3).ToList();
+
+ return restrictedCatalogueAccessRequests;
+ }
+
+ ///
+ /// Get list of Restricted Catalogue Users for the supplied request.
+ ///
+ /// The restrictedCatalogueUsersRequestViewModel.
+ /// A RestrictedCatalogueUsersViewModel.
+ public RestrictedCatalogueUsersViewModel GetRestrictedCatalogueUsers(RestrictedCatalogueUsersRequestViewModel restrictedCatalogueUsersRequestViewModel)
+ {
+ var param0 = new SqlParameter("@p0", SqlDbType.Int) { Value = restrictedCatalogueUsersRequestViewModel.CatalogueNodeId };
+ var param1 = new SqlParameter("@p1", SqlDbType.NVarChar) { Value = string.IsNullOrEmpty(restrictedCatalogueUsersRequestViewModel.EmailAddressFilter) ? string.Empty : restrictedCatalogueUsersRequestViewModel.EmailAddressFilter };
+ var param2 = new SqlParameter("@p2", SqlDbType.Bit) { Value = restrictedCatalogueUsersRequestViewModel.IncludeCatalogueAdmins };
+ var param3 = new SqlParameter("@p3", SqlDbType.Bit) { Value = restrictedCatalogueUsersRequestViewModel.IncludePlatformAdmins };
+ var param4 = new SqlParameter("@p4", SqlDbType.Int) { Value = restrictedCatalogueUsersRequestViewModel.Skip };
+ var param5 = new SqlParameter("@p5", SqlDbType.Int) { Value = restrictedCatalogueUsersRequestViewModel.Take };
+ var param6 = new SqlParameter("@p6", SqlDbType.Int) { Direction = ParameterDirection.Output };
+
+ var restrictedCatalogueUsers = DbContext.RestrictedCatalogueUserViewModel.FromSqlRaw("hub.RestrictedCatalogueGetUsers @p0, @p1, @p2, @p3, @p4, @p5, @p6 output", param0, param1, param2, param3, param4, param5, param6).ToList();
+
+ var vm = new RestrictedCatalogueUsersViewModel();
+ vm.RestrictedCatalogueUsers = restrictedCatalogueUsers;
+ vm.UserCount = (int)param6.Value;
+
+ return vm;
+ }
+
+ ///
+ /// Get Restricted Catalogue Summary for the supplied catalogue node id.
+ ///
+ /// The catalogueNodeId.
+ /// A RestrictedCatalogueUsersViewModel.
+ public RestrictedCatalogueSummaryViewModel GetRestrictedCatalogueSummary(int catalogueNodeId)
+ {
+ var param0 = new SqlParameter("@p0", SqlDbType.Int) { Value = catalogueNodeId };
+
+ var vm = DbContext.RestrictedCatalogueSummaryViewModel.FromSqlRaw("hub.RestrictedCatalogueGetSummary @p0", param0).AsEnumerable().FirstOrDefault();
+
+ return vm;
+ }
+
+ ///
+ /// Gets catalogues for dashboard based on type.
+ ///
+ /// The dashboard type.
+ /// The page Number.
+ /// The userId.
+ /// resources.
+ public (int TotalCount, List Catalogues) GetCatalogues(string dashboardType, int pageNumber, int userId)
+ {
+ var param0 = new SqlParameter("@DashboardType", SqlDbType.NVarChar, 30) { Value = dashboardType };
+ var param1 = new SqlParameter("@UserId", SqlDbType.Int) { Value = userId };
+ var param2 = new SqlParameter("@pageNumber", SqlDbType.Int) { Value = pageNumber };
+ var param3 = new SqlParameter("@TotalRecords", SqlDbType.Int) { Direction = ParameterDirection.Output };
+
+ var dashboardCatalogues = DbContext.DashboardCatalogueDto.FromSqlRaw("[hierarchy].[GetDashboardCatalogues] @DashboardType, @UserId, @pageNumber, @TotalRecords OUTPUT", param0, param1, param2, param3).ToList();
+
+ return (TotalCount: (int)param3.Value, Catalogues: dashboardCatalogues);
+ }
+
+ ///
+ public async Task ShowCatalogue(int userId, int nodeId)
+ {
+ var param0 = new SqlParameter("@NodeId", SqlDbType.Int) { Value = nodeId };
+ var param1 = new SqlParameter("@UserId", SqlDbType.Int) { Value = userId };
+ var param2 = new SqlParameter("@UserTimezoneOffset", SqlDbType.Int) { Value = TimezoneOffsetManager.UserTimezoneOffset ?? (object)DBNull.Value };
+
+ await DbContext.Database.ExecuteSqlRawAsync("[hierarchy].[CatalogueShow] @NodeId, @UserId, @UserTimezoneOffset", param0, param1, param2);
+ }
+
+ ///
+ /// Check if a Catalogue with a specific name exists or not.
+ ///
+ /// The catalogue name.
+ /// True if the catalogue exists, otherwise false.
+ public async Task ExistsAsync(string name)
+ {
+ return await DbContext.CatalogueNodeVersion.AnyAsync(x => x.Name.Equals(name) && !x.Deleted);
+ }
+
+ ///
+ /// Gets the Node Id for a particular catalogue name.
+ ///
+ /// The catalogue name.
+ /// The catalogue's node id.
+ public async Task GetNodeIdByCatalogueName(string catalogueName)
+ {
+ return await (from cnv in DbContext.CatalogueNodeVersion.AsNoTracking()
+ join nv in DbContext.NodeVersion.AsNoTracking() on cnv.NodeVersionId equals nv.Id
+ where cnv.Name == catalogueName && cnv.Deleted == false
+ select nv.NodeId).FirstOrDefaultAsync();
+ }
+
+ ///
+ /// Gets catalogues count based on alphabets.
+ ///
+ /// The userId.
+ /// resources.
+ public List GetAllCataloguesAlphaCount(int userId)
+ {
+ var param0 = new SqlParameter("@userId", SqlDbType.Int) { Value = userId };
+
+ var result = DbContext.AllCatalogueAlphabetModel.FromSqlRaw("[hierarchy].[GetCataloguesCount] @userid", param0)
+ .AsNoTracking().ToList();
+ return result;
+ }
+
+ ///
+ /// Gets catalogues based on filter character.
+ ///
+ /// The pageSize.
+ /// The filterChar.
+ /// The userId.
+ /// resources.
+ public async Task> GetAllCataloguesAsync(int pageSize, string filterChar, int userId)
+ {
+ var param0 = new SqlParameter("@userId", SqlDbType.Int) { Value = userId };
+ var param1 = new SqlParameter("@filterChar", SqlDbType.NVarChar, 10) { Value = filterChar.Trim() };
+ var param2 = new SqlParameter("@OffsetRows", SqlDbType.Int) { Value = 0 };
+ var param3 = new SqlParameter("@fetchRows", SqlDbType.Int) { Value = pageSize };
+
+ var result = await DbContext.AllCatalogueViewModel.FromSqlRaw("[hierarchy].[GetCatalogues] @userId, @filterChar, @OffsetRows, @fetchRows", param0, param1, param2, param3)
+ .AsNoTracking().ToListAsync();
+ return result;
+ }
+ }
+}
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/Repositories/Hierarchy/NodeResourceRepository.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/Repositories/Hierarchy/NodeResourceRepository.cs
new file mode 100644
index 000000000..e881cb3dc
--- /dev/null
+++ b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/Repositories/Hierarchy/NodeResourceRepository.cs
@@ -0,0 +1,161 @@
+namespace LearningHub.Nhs.OpenApi.Repositories.Repositories.Hierarchy
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Data;
+ using System.Linq;
+ using System.Threading.Tasks;
+ using LearningHub.Nhs.Models.Catalogue;
+ using LearningHub.Nhs.Models.Entities.Hierarchy;
+ using LearningHub.Nhs.Models.Enums;
+ using LearningHub.Nhs.Models.Hierarchy;
+ using LearningHub.Nhs.OpenApi.Repositories.EntityFramework;
+ using LearningHub.Nhs.OpenApi.Repositories.Helpers;
+ using LearningHub.Nhs.OpenApi.Repositories.Interface.Repositories;
+ using LearningHub.Nhs.OpenApi.Repositories.Interface.Repositories.Hierarchy;
+ using Microsoft.Data.SqlClient;
+ using Microsoft.EntityFrameworkCore;
+
+ ///
+ /// The node resource repository.
+ ///
+ public class NodeResourceRepository : GenericRepository, INodeResourceRepository
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The db context.
+ /// The Timezone offset manager.
+ public NodeResourceRepository(LearningHubDbContext dbContext, ITimezoneOffsetManager tzOffsetManager)
+ : base(dbContext, tzOffsetManager)
+ {
+ }
+
+ ///
+ /// The get by resource id async.
+ ///
+ /// The resource id.
+ /// The .
+ public async Task> GetByResourceIdAsync(int resourceId)
+ {
+ return await DbContext.NodeResource.AsNoTracking().Where(r => r.ResourceId == resourceId && !r.Deleted)
+ .Include(n => n.Node)
+ .ThenInclude(n => n.NodePaths)
+ .ThenInclude(n => n.NodePathNode)
+ .ThenInclude(n => n.Node)
+ .ToListAsync();
+ }
+
+ ///
+ /// Gets the Id of the node where a resource is currently located (IT1 - one resource is located in one node).
+ ///
+ /// The resource id.
+ /// The node id.
+ public async Task GetNodeIdByResourceId(int resourceId)
+ {
+ return await DbContext.NodeResource.AsNoTracking().Where(r => r.ResourceId == resourceId && !r.Deleted)
+ .Select(x => x.NodeId).SingleAsync();
+ }
+
+ ///
+ /// The get catalogue locations for resource.
+ ///
+ /// The resource id.
+ /// The CatalogueLocationViewModel list.
+ public List GetCatalogueLocationsForResource(int resourceId)
+ {
+ var param0 = new SqlParameter("@p0", SqlDbType.Int) { Value = resourceId };
+
+ var vms = DbContext.CatalogueLocationViewModel.FromSqlRaw("hierarchy.CatalogueLocationsForResource @p0", param0).ToList();
+
+ return vms;
+ }
+
+ ///
+ /// GetResourcesAsync.
+ ///
+ /// nodeId.
+ /// catalogueOrder.
+ /// offset.
+ /// CatalogueResourceViewModel.
+ public async Task GetResourcesAsync(int nodeId, CatalogueOrder catalogueOrder, int offset)
+ {
+ var resourceViewModels = (from nr in DbContext.NodeResource.AsNoTracking()
+ join rr in DbContext.ResourceReference.AsNoTracking() on nr.ResourceId equals rr.ResourceId
+ join np in DbContext.NodePath.AsNoTracking() on rr.NodePathId equals np.Id
+ join r in DbContext.Resource.AsNoTracking() on nr.ResourceId equals r.Id
+ join rv in DbContext.ResourceVersion.AsNoTracking() on r.CurrentResourceVersionId equals rv.Id
+ join grv in DbContext.GenericFileResourceVersion.AsNoTracking() on rv.Id equals grv.ResourceVersionId into genericjoin
+ from grv in genericjoin.DefaultIfEmpty()
+ where nr.NodeId == nodeId && np.NodeId == nodeId && rv.VersionStatusEnum == VersionStatusEnum.Published && rv.Deleted == false && nr.VersionStatusEnum == VersionStatusEnum.Published && nr.Deleted == false
+ select new CatalogueResourceViewModel
+ {
+ Type = r.ResourceTypeEnum.ToString(),
+ ResourceId = nr.ResourceId.ToString(),
+ ResourceVersionId = r.CurrentResourceVersionId.ToString(),
+ ResourceReferenceId = rr.Id.ToString(),
+ Title = rv.Title,
+ Description = rv.Description,
+ AuthoredBy = rv.ResourceVersionAuthor.FirstOrDefault().AuthorName,
+ Organisation = rv.ResourceVersionAuthor.FirstOrDefault().Organisation,
+ CreatedOn = rv.CreateDate.Date,
+ AuthoredDateText = r.ResourceTypeEnum != ResourceTypeEnum.GenericFile ? string.Empty : TextHelper.CombineDateComponents(grv.AuthoredYear, grv.AuthoredMonth, grv.AuthoredDayOfMonth),
+ }).AsQueryable();
+
+ if (resourceViewModels != null)
+ {
+ var totalResources = await resourceViewModels.CountAsync();
+ if (catalogueOrder == CatalogueOrder.AlphabeticalAscending)
+ {
+ resourceViewModels = resourceViewModels.OrderBy(r => r.Title).Take(offset + 10);
+ }
+ else
+ {
+ resourceViewModels = resourceViewModels.OrderByDescending(r => r.CreatedOn).Take(offset + 10);
+ }
+
+ return new CatalogueResourceResponseViewModel
+ {
+ NodeId = nodeId,
+ TotalResources = totalResources,
+ CatalogueResources = resourceViewModels?.ToList(),
+ };
+ }
+
+ return null;
+ }
+
+ ///
+ /// Get All published resources id.
+ ///
+ /// The .
+ public async Task> GetAllPublishedResourceAsync()
+ {
+ return await (from nr in DbContext.NodeResource.AsNoTracking()
+ join rr in DbContext.ResourceReference.AsNoTracking() on nr.ResourceId equals rr.ResourceId
+ join np in DbContext.NodePath.AsNoTracking() on rr.NodePathId equals np.Id
+ join r in DbContext.Resource.AsNoTracking() on nr.ResourceId equals r.Id
+ join rv in DbContext.ResourceVersion.AsNoTracking() on r.CurrentResourceVersionId equals rv.Id
+ where nr.NodeId == np.NodeId && rv.VersionStatusEnum == VersionStatusEnum.Published && nr.VersionStatusEnum == VersionStatusEnum.Published
+ select rr.Id)
+ .ToListAsync();
+ }
+
+ ///
+ /// Creates or updates the NodeResource record for a draft resource in a node.
+ ///
+ /// The nodeId.
+ /// The resourceId.
+ /// The userId.
+ /// The .
+ public async Task CreateOrUpdateAsync(int nodeId, int resourceId, int userId)
+ {
+ var param0 = new SqlParameter("@p0", SqlDbType.Int) { Value = nodeId };
+ var param1 = new SqlParameter("@p1", SqlDbType.Int) { Value = resourceId };
+ var param2 = new SqlParameter("@p2", SqlDbType.Int) { Value = userId };
+ var param3 = new SqlParameter("@p3", SqlDbType.Int) { Value = TimezoneOffsetManager.UserTimezoneOffset ?? (object)DBNull.Value };
+
+ return await DbContext.Database.ExecuteSqlRawAsync("hierarchy.NodeResourceCreateOrUpdate @p0, @p1, @p2, @p3", param0, param1, param2, param3);
+ }
+ }
+}
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/Repositories/MultipleResultSets.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/Repositories/MultipleResultSets.cs
new file mode 100644
index 000000000..9889db659
--- /dev/null
+++ b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/Repositories/MultipleResultSets.cs
@@ -0,0 +1,132 @@
+namespace LearningHub.Nhs.OpenApi.Repositories.Repositories
+{
+ using System;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Data;
+ using System.Data.Common;
+ using System.Linq;
+ using System.Reflection;
+ using Microsoft.Data.SqlClient;
+ using Microsoft.EntityFrameworkCore;
+
+ ///
+ /// MultipleResultSets.
+ ///
+ public static class MultipleResultSets
+ {
+ ///
+ /// MultipleResults extension.
+ ///
+ /// DbContext.
+ /// Store Proc.
+ /// MultipleResultSetWrapper.
+ public static MultipleResultSetWrapper MultipleResults(this DbContext db, SqlCommand command)
+ {
+ return new MultipleResultSetWrapper(db, command);
+ }
+
+ ///
+ /// MultipleResultSetWrapper.
+ ///
+ public class MultipleResultSetWrapper
+ {
+ private readonly DbContext dbContext;
+ private readonly SqlCommand command;
+ private List> resultSets;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// DbContext.
+ /// Store Proc.
+ public MultipleResultSetWrapper(DbContext dbContext, SqlCommand storedProcedure)
+ {
+ this.dbContext = dbContext;
+ command = storedProcedure;
+ resultSets = new List>();
+ }
+
+ ///
+ /// With result.
+ ///
+ /// Type.
+ /// MultipleResultSetWrapper.
+ public MultipleResultSetWrapper With()
+ {
+ resultSets.Add(reader => MapToList(reader));
+
+ return this;
+ }
+
+ ///
+ /// Execute.
+ ///
+ /// IEnumerable list.
+ public List Execute()
+ {
+ var results = new List();
+
+ var connection = dbContext.Database.GetDbConnection();
+
+ if (connection.State != ConnectionState.Open)
+ {
+ connection.Open();
+ }
+
+ command.Connection = (SqlConnection)connection;
+ using (var reader = command.ExecuteReader())
+ {
+ foreach (var resultSet in resultSets)
+ {
+ results.Add(resultSet(reader));
+ reader.NextResult();
+ }
+ }
+
+ return results;
+ }
+
+ ///
+ /// Retrieves the column values from the stored procedure and maps them to 's properties.
+ ///
+ /// Type.
+ /// DbDataReader.
+ /// Array of type.
+ private static List MapToList(DbDataReader dr)
+ {
+ var objList = new List();
+ var props = typeof(T).GetRuntimeProperties().ToList();
+
+ var colMapping = dr.GetColumnSchema()
+ .Where(x => props.Any(y => y.Name.ToLower() == x.ColumnName.ToLower()))
+ .ToDictionary(key => key.ColumnName.ToLower());
+
+ if (dr.HasRows)
+ {
+ while (dr.Read())
+ {
+ T obj = Activator.CreateInstance();
+ foreach (var prop in props)
+ {
+ if (colMapping.ContainsKey(prop.Name.ToLower()))
+ {
+ var column = colMapping[prop.Name.ToLower()];
+
+ if (column?.ColumnOrdinal != null)
+ {
+ var val = dr.GetValue(column.ColumnOrdinal.Value);
+ prop.SetValue(obj, val == DBNull.Value ? null : val);
+ }
+ }
+ }
+
+ objList.Add(obj);
+ }
+ }
+
+ return objList;
+ }
+ }
+ }
+}
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/Repositories/ProviderRepository.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/Repositories/ProviderRepository.cs
new file mode 100644
index 000000000..e81581930
--- /dev/null
+++ b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/Repositories/ProviderRepository.cs
@@ -0,0 +1,91 @@
+namespace LearningHub.Nhs.OpenApi.Repositories.Repositories
+{
+ using System.Data;
+ using System.Linq;
+ using System.Threading.Tasks;
+ using LearningHub.Nhs.Models.Entities;
+ using LearningHub.Nhs.Models.Entities.Hierarchy;
+ using LearningHub.Nhs.Models.Entities.Resource;
+ using LearningHub.Nhs.OpenApi.Repositories.EntityFramework;
+ using LearningHub.Nhs.OpenApi.Repositories.Interface.Repositories;
+ using Microsoft.EntityFrameworkCore;
+
+ ///
+ /// The provider repository.
+ ///
+ public class ProviderRepository : GenericRepository, IProviderRepository
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The db context.
+ /// The Timezone offset manager.
+ public ProviderRepository(LearningHubDbContext dbContext, ITimezoneOffsetManager tzOffsetManager)
+ : base(dbContext, tzOffsetManager)
+ {
+ }
+
+ ///
+ public async Task GetByIdAsync(int id)
+ {
+ return await DbContext.Provider.AsNoTracking().FirstOrDefaultAsync(n => n.Id == id && !n.Deleted);
+ }
+
+ ///
+ public async Task GetByIdAsync(int id, bool includeChildren)
+ {
+ if (includeChildren)
+ {
+ return await DbContext.Provider
+ .Where(r => !r.Deleted)
+ .Include(r => r.UserProvider)
+ .ThenInclude(pr => pr.User)
+ .AsNoTracking()
+ .FirstOrDefaultAsync(n => n.Id == id);
+ }
+ else
+ {
+ return await DbContext.Provider.AsNoTracking().FirstOrDefaultAsync(n => n.Id == id && !n.Deleted);
+ }
+ }
+
+ ///
+ /// The get by user id async.
+ ///
+ /// The user id.
+ /// The .
+ public IQueryable GetProvidersByUserIdAsync(int userId)
+ {
+ return DbContext.Set()
+ .Include(up => up.Provider)
+ .Where(up => up.UserId == userId && !up.Deleted).AsNoTracking()
+ .Select(up => up.Provider);
+ }
+
+ ///
+ /// The get by resource version id async.
+ ///
+ /// The resource version id.
+ /// The .
+ public IQueryable GetProvidersByResourceIdAsync(int resourceVersionId)
+ {
+ return DbContext.Set()
+ .Include(up => up.Provider)
+ .Where(up => up.ResourceVersionId == resourceVersionId && !up.Deleted).AsNoTracking()
+ .Select(up => up.Provider);
+ }
+
+ ///
+ /// The get by node version id async.
+ ///
+ /// The node version id.
+ /// The .
+ public IQueryable GetProvidersByCatalogueIdAsync(int nodeVersionId)
+ {
+ return DbContext.Set()
+ .Include(up => up.Provider)
+ .Where(up => up.CatalogueNodeVersionId == nodeVersionId && !up.Deleted).AsNoTracking()
+ .Select(up => up.Provider);
+ }
+ }
+}
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/Repositories/ResourceRepository.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/Repositories/ResourceRepository.cs
index 79b7a239b..1ba6a10af 100644
--- a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/Repositories/ResourceRepository.cs
+++ b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/Repositories/ResourceRepository.cs
@@ -90,11 +90,11 @@ public async Task> GetAchievedCertificatedResourceIds(int currentUserI
return achievedCertificatedResourceIds;
}
- ///
- ///
- ///
- /// .
- /// A representing the result of the asynchronous operation.
+ //
+ //
+ //
+ // .
+ // A representing the result of the asynchronous operation.
public async Task> GetResourceActivityPerResourceMajorVersion(
IEnumerable? resourceIds, IEnumerable? userIds)
{
@@ -119,5 +119,16 @@ public async Task> GetResourceActivityPerResour
return resourceActivityDTOs;
}
+
+ ///
+ /// The get by id async.
+ ///
+ /// The id.
+ /// The .
+ public async Task GetByIdAsync(int id)
+ {
+ return await this.dbContext.Resource.AsNoTracking().FirstOrDefaultAsync(r => r.Id == id && !r.Deleted);
+ }
+
}
}
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/Repositories/Resources/BlockCollectionRepository.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/Repositories/Resources/BlockCollectionRepository.cs
new file mode 100644
index 000000000..35b7432f1
--- /dev/null
+++ b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/Repositories/Resources/BlockCollectionRepository.cs
@@ -0,0 +1,443 @@
+namespace LearningHub.Nhs.OpenApi.Repositories.Repositories.Resources
+{
+ using System;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Data;
+ using System.Linq;
+ using System.Threading.Tasks;
+ using LearningHub.Nhs.Models.Entities.Resource;
+ using LearningHub.Nhs.Models.Entities.Resource.Blocks;
+ using LearningHub.Nhs.Models.Enums;
+ using LearningHub.Nhs.Models.Resource.Blocks;
+ using LearningHub.Nhs.OpenApi.Repositories.EntityFramework;
+ using LearningHub.Nhs.OpenApi.Repositories.Interface.Repositories;
+ using LearningHub.Nhs.OpenApi.Repositories.Interface.Repositories.Resources;
+ using Microsoft.Data.SqlClient;
+ using Microsoft.EntityFrameworkCore;
+
+ ///
+ /// The block collection repository.
+ ///
+ public class BlockCollectionRepository : GenericRepository, IBlockCollectionRepository
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The db context.
+ /// The Timezone offset manager.
+ public BlockCollectionRepository(LearningHubDbContext dbContext, ITimezoneOffsetManager tzOffsetManager)
+ : base(dbContext, tzOffsetManager)
+ {
+ }
+
+ ///
+ /// The create async.
+ ///
+ /// The user id.
+ /// The block collection.
+ /// The .
+ public override async Task CreateAsync(int userId, BlockCollection blockCollection)
+ {
+ SetAuditFieldsOnChildren(userId, blockCollection, isCreate: true);
+
+ return await base.CreateAsync(userId, blockCollection);
+ }
+
+ ///
+ /// Delete the Block Collection.
+ ///
+ /// The User Id.
+ /// The Block Collection Id.
+ /// The .
+ public async Task DeleteBlockCollection(int userId, int blockCollectionId)
+ {
+ BlockCollection blockCollection = DbContext.BlockCollection
+ .Include(b => b.Blocks)
+ .ThenInclude(b => b.QuestionBlock)
+ .ThenInclude(b => b.Answers)
+ .Include(bc => bc.Blocks)
+ .ThenInclude(b => b.ImageCarouselBlock)
+ .FirstOrDefault(bc => bc.Id == blockCollectionId);
+
+ if (blockCollection == null)
+ {
+ return;
+ }
+
+ var questionBlockCollection = blockCollection.Blocks
+ .Where(b => b.QuestionBlock != null)
+ .SelectMany(b =>
+ {
+ var qb = b.QuestionBlock;
+ return qb.Answers
+ .Where(t => t.BlockCollectionId.HasValue)
+ .Select(a => a.BlockCollectionId.Value)
+ .Concat(new[] { qb.QuestionBlockCollectionId, qb.FeedbackBlockCollectionId });
+ });
+
+ var imageBlockCollection = blockCollection.Blocks
+ .Where(b => b.ImageCarouselBlock != null)
+ .Select(b => b.ImageCarouselBlock.ImageBlockCollectionId);
+
+ var collectionIds = new[] { blockCollectionId }.Concat(imageBlockCollection.Concat(questionBlockCollection));
+
+ foreach (var id in collectionIds)
+ {
+ await DbContext.Database.ExecuteSqlRawAsync("resources.BlockCollectionDelete @p0", new SqlParameter("@p0", SqlDbType.Int) { Value = id });
+ }
+ }
+
+ ///
+ /// Gets the Block Collection (including child Blocks, TextBlocks, WholeSlideImageBlocks and Files).
+ ///
+ /// The Block Collection Id.
+ /// The .
+ public async Task GetBlockCollection(int? blockCollectionId)
+ {
+ if (!blockCollectionId.HasValue)
+ {
+ return null;
+ }
+
+ var command = new SqlCommand
+ {
+ CommandText = "[resources].[BlockCollectionGet]",
+ CommandType = CommandType.StoredProcedure,
+ Parameters = { new SqlParameter("@BlockCollectionId", SqlDbType.Int) { Value = blockCollectionId } },
+ };
+
+ var results = DbContext.MultipleResults(command)
+ .With()
+ .With()
+ .With()
+ .With()
+ .With()
+ .With()
+ .With()
+ .With()
+ .With()
+ .With()
+ .With()
+ .With()
+ .With()
+ .With()
+ .With()
+ .With()
+ .With()
+ .With