Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions LearningHub.Nhs.WebUI/Controllers/Api/HierarchyController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,19 @@ public async Task<IActionResult> GetNodeContentsForCatalogueEditor(int nodePathI
return this.Ok(viewModels);
}

/// <summary>
/// Check Catalogue has external reference.
/// </summary>
/// <param name="nodeId">The node id.</param>
/// <returns>The <see cref="IActionResult"/>.</returns>
[HttpGet]
[Route("CheckCatalogueHasExternalReference/{nodeId}")]
public async Task<bool> CheckCatalogueHasExternalReference(int nodeId)
{
var val = await this.hierarchyService.CheckCatalogueHasExternalReference(nodeId);
return val;
}

/// <summary>
/// Gets the contents of a node path (catalogue/folder/course) - i.e. returns a list of subfolders and resources. Only returns the
/// items from the first level down. Doesn't recurse through subfolders.
Expand Down
7 changes: 7 additions & 0 deletions LearningHub.Nhs.WebUI/Interfaces/IHierarchyService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -236,5 +236,12 @@ public interface IHierarchyService
/// <param name="referenceExternalResourceViewModel">The referenceExternalResourceViewModel<see cref="ReferenceExternalResourceViewModel"/>.</param>
/// <returns>IActionResult.</returns>
Task<ApiResponse> HierarchyEditReferenceExternalResource(ReferenceExternalResourceViewModel referenceExternalResourceViewModel);

/// <summary>
/// Check catalogue has external reference.
/// </summary>
/// <param name="nodeId">The nodeId<see cref="int"/>.</param>
/// <returns>The <see cref="Task"/>.</returns>
Task<bool> CheckCatalogueHasExternalReference(int nodeId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export class State {
updatedNode: NodeContentEditorModel = null;
inError: boolean = false;
lastErrorMessage: string = "";
hasExternalReference: boolean = false;
}

const state = new State();
Expand Down Expand Up @@ -51,6 +52,13 @@ function loadNodeContents(state: State) {
state.rootNode.childrenLoaded = false;
state.rootNode.inEdit = state.editMode == EditModeEnum.Structure;
state.rootNode.showInTreeView = false;
}).then(async y => {
await contentStructureData.checkCatalogueHasExternalReference(state.catalogue.nodeId).then(response => {
state.hasExternalReference = response;
})
.catch(e => {
console.log(e);
});
}).then(async y => {
await contentStructureData.getNodeContentsForCatalogueEditor(state.catalogue.rootNodePathId).then(response => {
state.rootNode.children = response;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,9 @@
</a>
<div class="dropdown-menu" aria-labelledby="dropdownNodeItems">
<a class="dropdown-item" v-if="canEditResource" @click="onEditResource">Edit</a>
<a class="dropdown-item" v-if="canMoveResourceUp" @click="onMoveResourceUp">Move up</a>
<a class="dropdown-item" v-if="canMoveResourceDown" @click="onMoveResourceDown">Move down</a>
<a class="dropdown-item" v-if="canMoveResource" @click="onInitiateMoveResource">Move</a>
<a class="dropdown-item" v-if="canMoveResourceUp && !hasExternalCatalogueReference" @click="onMoveResourceUp">Move up</a>
<a class="dropdown-item" v-if="canMoveResourceDown && !hasExternalCatalogueReference" @click="onMoveResourceDown">Move down</a>
<a class="dropdown-item" v-if="canMoveResource && !hasExternalCatalogueReference" @click="onInitiateMoveResource">Move</a>
<a class="dropdown-item" v-if="canDuplicateResource" @click="onDuplicateResource">Duplicate</a>
<a class="dropdown-item" v-if="canDeleteResource" @click="confirmDeleteResource" data-toggle="modal" data-target="#showDeleteConfirm">Delete</a>
</div>
Expand Down Expand Up @@ -248,6 +248,9 @@
}
else return 0;
},
hasExternalCatalogueReference(): boolean {
return this.$store.state.contentStructureState.hasExternalReference;
},
},
mounted() {
Vue.set(this, "isVisible", this.item.showInTreeView);
Expand Down Expand Up @@ -288,7 +291,7 @@
}
}
}

// Load the data.
if (!this.isOpen && (!this.item.childrenLoaded || this.isError)) {
this.isOpen = true;
Expand Down
14 changes: 12 additions & 2 deletions LearningHub.Nhs.WebUI/Scripts/vuesrc/data/contentStructure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,16 @@ const getNodeContentsForCatalogueEditor = async function (nodePathId: number): P
throw e;
});
};

const checkCatalogueHasExternalReference = async function (nodeId: number): Promise<boolean> {
return await axios.get<boolean>('/api/hierarchy/CheckCatalogueHasExternalReference/' + nodeId + `?timestamp=${new Date().getTime()}`)
.then(response => {
return response.data;
})
.catch(e => {
console.log('CheckCatalogueHasExternalReference:' + e);
throw e;
});
};
const getNodeContentsAdmin = async function (nodePathId: number, readOnly: boolean): Promise<NodeContentAdminModel[]> {
return await axios.get<NodeContentAdminModel[]>('/api/hierarchy/GetNodeContentsAdmin/' + nodePathId + '/' + readOnly + `?timestamp=${new Date().getTime()}`)
.then(response => {
Expand Down Expand Up @@ -464,5 +473,6 @@ export const contentStructureData = {
getReferencableCatalogues,
hierarchyEditReferenceExternalResource,
referenceExternalNode,
removeReferenceNode
removeReferenceNode,
checkCatalogueHasExternalReference
}
29 changes: 29 additions & 0 deletions LearningHub.Nhs.WebUI/Services/HierarchyService.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
namespace LearningHub.Nhs.WebUI.Services
{
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using LearningHub.Nhs.Models.Common;
Expand Down Expand Up @@ -337,5 +338,33 @@ public async Task<ApiResponse> HierarchyEditReferenceExternalResource(ReferenceE
{
return await this.facade.PostAsync<ApiResponse, ReferenceExternalResourceViewModel>("Hierarchy/HierarchyEditReferenceExternalResource", referenceExternalResourceViewModel);
}

/// <summary>
/// Check catalogue has external reference.
/// </summary>
/// <param name="nodeId">nodeId<see cref="Task"/>.</param>
/// <returns>IActionResult.</returns>
public async Task<bool> CheckCatalogueHasExternalReference(int nodeId)
{
var request = $"Hierarchy/CheckCatalogueHasExternalReference/{nodeId}";

var client = await this.LearningHubHttpClient.GetClientAsync();
var response = await client.GetAsync(request).ConfigureAwait(false);
var hasExternalCatalogueReference = false;

if (response.IsSuccessStatusCode)
{
var result = await response.Content.ReadAsStringAsync();
hasExternalCatalogueReference = bool.Parse(result);
}
else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized
||
response.StatusCode == System.Net.HttpStatusCode.Forbidden)
{
throw new Exception("AccessDenied");
}

return hasExternalCatalogueReference;
}
}
}
12 changes: 12 additions & 0 deletions WebAPI/LearningHub.Nhs.API/Controllers/HierarchyController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,18 @@ public async Task<IActionResult> GetNodeContentsForCatalogueEditor(int nodePathI
return this.Ok(await this.hierarchyService.GetNodeContentsForCatalogueEditor(nodePathId));
}

/// <summary>
/// Check Catalogue has external reference.
/// </summary>
/// <param name="nodeId">The node id.</param>
/// <returns>The <see cref="IActionResult"/>.</returns>
[HttpGet]
[Route("checkCatalogueHasExternalReference/{nodeId}")]
public async Task<IActionResult> CheckCatalogueHasExternalReference(int nodeId)
{
return this.Ok(await this.hierarchyService.CheckCatalogueHasExternalReference(nodeId));
}

/// <summary>
/// Gets the contents of a node path (catalogue/folder/course) - i.e. returns a list of subfolders and resources. Only returns the
/// items from the first level down. Doesn't recurse through subfolders.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,7 @@
<Build Include="Stored Procedures\Resources\GetScormContentServerDetailsForLHExternalReference.sql" />
<None Include="Scripts\Post-Deploy\Scripts\Content_Referencing_DataSetup.sql" />
<None Include="Scripts\Pre-Deploy\Scripts\Content Referencing Initialise.sql" />
<Build Include="Stored Procedures\Hierarchy\CheckCatalogueHasExternalReference.sql" />
</ItemGroup>
<ItemGroup>
<None Include="Scripts\Pre-Deploy\Scripts\Card5766_AuthorTableChanges.PreDeployment.sql" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
-------------------------------------------------------------------------------
-- Author Sarathlal
-- Created 29 August 2024
-- Purpose Return if Node has an external reference
--
-- Modification History
--
-- 29-08-2024 SS Initial Revision.

-------------------------------------------------------------------------------
CREATE PROCEDURE [hierarchy].[CheckCatalogueHasExternalReference]
(
@CatalogueNodeId int,
@HasExternalCatalogueReference bit OUTPUT
)
AS

BEGIN
;WITH
cteNode(NodeId, ParentNodeId, PrimaryCatalogueNodeId, InitialNodePath)
AS
(
SELECT
n.Id AS NodeId,
ParentNodeId = NULL,
nv.PrimaryCatalogueNodeId,
CAST(n.Id AS nvarchar(128)) AS InitialNodePath
FROM
hierarchy.NodePath np
INNER JOIN
hierarchy.[Node] n ON np.NodeId = n.Id
INNER JOIN
hierarchy.NodeVersion nv ON n.CurrentNodeVersionId = nv.Id
WHERE
nv.NodeId=@catalogueNodeId
AND nv.VersionStatusId = 2 -- Published
AND np.Deleted = 0
AND n.Deleted = 0
AND nv.Deleted = 0

UNION ALL

SELECT
ChildNodeId AS NodeId,
nl.ParentNodeId,
nv.PrimaryCatalogueNodeId,
CAST(cte.InitialNodePath + '\' + CAST(ChildNodeId AS nvarchar(8)) AS nvarchar(128)) AS InitialNodePath
FROM
hierarchy.NodeLink nl
INNER JOIN
hierarchy.[Node] n ON nl.ChildNodeId = n.Id
INNER JOIN
cteNode cte ON nl.ParentNodeId = cte.NodeId
INNER JOIN
hierarchy.NodeVersion nv ON n.CurrentNodeVersionId = nv.Id
WHERE
n.CurrentNodeVersionId IS NOT NULL
AND nv.VersionStatusId = 2 -- Published
AND n.Deleted = 0
AND nl.Deleted = 0

),

cteResource
AS (
SELECT cte.PrimaryCatalogueNodeId
FROM
cteNode cte
UNION

SELECT
rv.PrimaryCatalogueNodeId AS PrimaryCatalogueNodeId
FROM
hierarchy.NodePath np
INNER JOIN
hierarchy.NodeResource nr ON np.NodeId = nr.NodeId
INNER JOIN
resources.[Resource] r ON nr.ResourceId = r.Id
INNER JOIN
resources.ResourceVersion rv ON rv.resourceId = nr.ResourceId
INNER JOIN
resources.ResourceReference rr ON rr.ResourceId = nr.ResourceId AND rr.NodePathId = np.Id AND rr.Deleted = 0

WHERE
np.CatalogueNodeId = @CatalogueNodeId
and rv.PrimaryCatalogueNodeId <>np.CatalogueNodeId
AND r.CurrentResourceVersionId IS not NULL
AND nr.VersionStatusId=2
AND nr.Deleted = 0
AND r.Deleted = 0
AND rv.Deleted = 0
)
SELECT @HasExternalCatalogueReference=case when count(distinct cte.PrimaryCatalogueNodeId ) > 1 then 1 ELSE 0 END

FROM
cteResource cte
END
GO
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,12 @@ public interface INodeRepository : IGenericRepository<Node>
/// <param name="readOnly">Set to true if read only data set is required.</param>
/// <returns>The <see cref="Task"/>.</returns>
Task<List<NodeContentAdminDto>> GetNodeContentsAdminAsync(int nodeId, bool readOnly);

/// <summary>
/// Check catalogue has external reference.
/// </summary>
/// <param name="nodeId">The node id.</param>
/// <returns>The <see cref="Task"/>.</returns>
Task<bool> CheckCatalogueHasExternalReference(int nodeId);
}
}
17 changes: 17 additions & 0 deletions WebAPI/LearningHub.Nhs.Repository/Hierarchy/NodeRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,23 @@ public async Task<List<NodeContentEditorViewModel>> GetNodeContentsForCatalogueE
return retVal;
}

/// <summary>
/// Check catalogue has external reference.
/// </summary>
/// <param name="nodeId">The node path id.</param>
/// <returns>The <see cref="Task"/>.</returns>
public async Task<bool> CheckCatalogueHasExternalReference(int nodeId)
{
var param0 = new SqlParameter("@p0", SqlDbType.Int) { Value = nodeId };
var param1 = new SqlParameter("@p1", SqlDbType.Bit) { Direction = ParameterDirection.Output };
string sql = "hierarchy.CheckCatalogueHasExternalReference @p0, @p1 output";
var sqlParams = new List<SqlParameter>() { param0, param1 };

await this.DbContext.Database.ExecuteSqlRawAsync(sql, sqlParams);

return (bool)param1.Value;
}

/// <summary>
/// Gets the contents of a node path (catalogue/folder/course) - i.e. returns a list of subfolders and resources. Only returns the
/// items from the first level down. Doesn't recurse through subfolders.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -293,5 +293,12 @@ public interface IHierarchyService
/// <param name="nodeId">The nodeId<see cref="int"/>.</param>
/// <returns>The <see cref="List{NodePathViewModel}"/>.</returns>
Task<List<NodePathViewModel>> GetNodePathsForNodeAsync(int nodeId);

/// <summary>
/// Check catalogue has external reference.
/// </summary>
/// <param name="nodeId">The nodeId<see cref="int"/>.</param>
/// <returns>The <see cref="Task"/>.</returns>
Task<bool> CheckCatalogueHasExternalReference(int nodeId);
}
}
13 changes: 13 additions & 0 deletions WebAPI/LearningHub.Nhs.Services/HierarchyService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,19 @@ public async Task<List<NodeContentEditorViewModel>> GetNodeContentsForCatalogueE
return vm;
}

/// <summary>
/// Check catalogue has external reference.
/// </summary>
/// <param name="nodeId">The node path id.</param>
/// <returns>The <see cref="Task"/>.</returns>
public async Task<bool> CheckCatalogueHasExternalReference(int nodeId)
{
// Not cached, retrieve directly from the database.
var vm = await this.nodeRepository.CheckCatalogueHasExternalReference(nodeId);

return vm;
}

/// <summary>
/// Gets the contents of a node path (catalogue/folder/course) - i.e. returns a list of subfolders and resources. Only returns the
/// items from the first level down. Doesn't recurse through subfolders.
Expand Down