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