Skip to content

Commit 163853a

Browse files
authored
Merge pull request #1083 from TechnologyEnhancedLearning/MergeFlaxLilly-RC
Merge flax lilly release changes to RC
2 parents 1f3026d + 169e034 commit 163853a

File tree

12 files changed

+1222
-866
lines changed

12 files changed

+1222
-866
lines changed
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
namespace LearningHub.Nhs.AdminUI.Controllers.Api
2+
{
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Threading.Tasks;
6+
using elfhHub.Nhs.Models.Common;
7+
using elfhHub.Nhs.Models.Enums;
8+
using LearningHub.Nhs.AdminUI.Interfaces;
9+
using Microsoft.AspNetCore.Authorization;
10+
using Microsoft.AspNetCore.Mvc;
11+
using Microsoft.Extensions.Logging;
12+
using Microsoft.Extensions.Options;
13+
14+
/// <summary>
15+
/// The UserController class.
16+
/// </summary>
17+
[Authorize]
18+
[Route("api/[controller]")]
19+
[ApiController]
20+
public class UserController : BaseApiController
21+
{
22+
/// <summary>
23+
/// The elfh user service..
24+
/// </summary>
25+
private IUserService userService;
26+
27+
/// <summary>
28+
/// Initializes a new instance of the <see cref="UserController"/> class.
29+
/// </summary>
30+
/// <param name="userService">The userService<see cref="IUserService"/>.</param>
31+
/// <param name="loginWizardService">loginWizardService.</param>
32+
/// <param name="logger">logger.</param>
33+
/// <param name="settings">Settings.</param>
34+
public UserController(IUserService userService, ILogger<UserController> logger)
35+
: base(logger)
36+
{
37+
this.userService = userService;
38+
}
39+
40+
/// <summary>
41+
/// The SessionTimeout.
42+
/// </summary>
43+
/// <returns>The <see cref="IActionResult"/>.</returns>
44+
[HttpPost("browser-close")]
45+
public IActionResult BrowserClose()
46+
{
47+
// Add browser close to the UserHistory
48+
UserHistoryViewModel userHistory = new UserHistoryViewModel()
49+
{
50+
UserId = this.CurrentUserId,
51+
UserHistoryTypeId = (int)UserHistoryType.Logout,
52+
Detail = @"User browser closed",
53+
};
54+
55+
this.userService.StoreUserHistory(userHistory);
56+
57+
return this.Ok(true);
58+
}
59+
}
60+
}

AdminUI/LearningHub.Nhs.AdminUI/Views/Resource/Details.cshtml

Lines changed: 857 additions & 854 deletions
Large diffs are not rendered by default.

AdminUI/LearningHub.Nhs.AdminUI/Views/Shared/_Layout.cshtml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,14 @@
7878
</environment>
7979
@*<script type="text/javascript" src="~/js/bundle/header.js"></script>*@
8080
<partial name="~/Views/Shared/_ValidationScriptsPartial.cshtml" />
81+
8182
@RenderSection("Scripts", required: false)
83+
<script type="text/javascript" src="~/js/pageunload.js" asp-append-version="true"></script>
84+
<script type="text/javascript">
85+
// Bind the function to the unload event
86+
window.onunload = tellServerBrowserClosed;
87+
88+
</script>
8289
</body>
8390
</html>
8491
<!-- Build number: @settings.Value.BuildNumber -->
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
 // This function will be called when the browser window is closed or unloaded
2+
function tellServerBrowserClosed() {
3+
// Send an asynchronous request to the server when the browser is closed
4+
fetch('/api/user/browser-close', {
5+
method: 'POST',
6+
headers: {
7+
'Content-Type': 'application/json'
8+
},
9+
body: JSON.stringify({ message: 'Browser closed' })
10+
})
11+
.then(response => response.json())
12+
.catch(error => console.error('Error sending data to server:', error));
13+
}

LearningHub.Nhs.WebUI/Configuration/Settings.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,11 @@ public Settings()
196196
/// </summary>
197197
public int PasswordRequestLimit { get; set; }
198198

199+
/// <summary>
200+
/// Gets or sets the ConcurrentId.
201+
/// </summary>
202+
public int ConcurrentId { get; set; }
203+
199204
/// <summary>
200205
/// Gets or sets the SupportUrls.
201206
/// </summary>

LearningHub.Nhs.WebUI/Controllers/Api/UserController.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.Collections.Generic;
55
using System.Threading.Tasks;
66
using elfhHub.Nhs.Models.Common;
7+
using elfhHub.Nhs.Models.Enums;
78
using LearningHub.Nhs.WebUI.Configuration;
89
using LearningHub.Nhs.WebUI.Interfaces;
910
using Microsoft.AspNetCore.Authorization;
@@ -62,6 +63,26 @@ public async Task<IActionResult> CurrentProfile()
6263
return this.Ok(await this.userService.GetCurrentUserProfileAsync());
6364
}
6465

66+
/// <summary>
67+
/// The SessionTimeout.
68+
/// </summary>
69+
/// <returns>The <see cref="IActionResult"/>.</returns>
70+
[HttpPost("browser-close")]
71+
public IActionResult BrowserClose()
72+
{
73+
// Add browser close to the UserHistory
74+
UserHistoryViewModel userHistory = new UserHistoryViewModel()
75+
{
76+
UserId = this.CurrentUserId,
77+
UserHistoryTypeId = (int)UserHistoryType.Logout,
78+
Detail = @"User browser closed",
79+
};
80+
81+
this.userService.StoreUserHistory(userHistory);
82+
83+
return this.Ok(true);
84+
}
85+
6586
/// <summary>
6687
/// Get current user's basic details.
6788
/// </summary>

LearningHub.Nhs.WebUI/Controllers/HomeController.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ namespace LearningHub.Nhs.WebUI.Controllers
77
using System.Net.Http;
88
using System.Threading.Tasks;
99
using elfhHub.Nhs.Models.Common;
10+
using elfhHub.Nhs.Models.Enums;
1011
using LearningHub.Nhs.Models.Content;
1112
using LearningHub.Nhs.Models.Enums.Content;
1213
using LearningHub.Nhs.Models.Extensions;
@@ -205,6 +206,7 @@ public async Task<IActionResult> Index(string myLearningDashboard = "my-in-progr
205206
{
206207
if (this.User?.Identity.IsAuthenticated == true)
207208
{
209+
this.Settings.ConcurrentId = this.CurrentUserId;
208210
this.Logger.LogInformation("User is authenticated: User is {fullname} and userId is: {lhuserid}", this.User.Identity.GetCurrentName(), this.User.Identity.GetCurrentUserId());
209211
if (this.User.IsInRole("Administrator") || this.User.IsInRole("BlueUser") || this.User.IsInRole("ReadOnly") || this.User.IsInRole("BasicUser"))
210212
{
@@ -374,11 +376,41 @@ public IActionResult SessionTimeout(string returnUrl = "/")
374376
return this.Redirect(returnUrl);
375377
}
376378

379+
// Add successful logout to the UserHistory
380+
UserHistoryViewModel userHistory = new UserHistoryViewModel()
381+
{
382+
UserId = this.Settings.ConcurrentId,
383+
UserHistoryTypeId = (int)UserHistoryType.Logout,
384+
Detail = @"User session time out",
385+
};
386+
387+
this.userService.StoreUserHistory(userHistory);
388+
377389
this.ViewBag.AuthTimeout = this.authConfig.AuthTimeout;
378390
this.ViewBag.ReturnUrl = returnUrl;
391+
379392
return this.View();
380393
}
381394

395+
/// <summary>
396+
/// The SessionTimeout.
397+
/// </summary>
398+
/// <returns>The <see cref="IActionResult"/>.</returns>
399+
[HttpPost("browser-close")]
400+
public IActionResult BrowserClose()
401+
{
402+
// Add browser close to the UserHistory
403+
UserHistoryViewModel userHistory = new UserHistoryViewModel()
404+
{
405+
UserId = this.CurrentUserId,
406+
UserHistoryTypeId = (int)UserHistoryType.Logout,
407+
Detail = @"User browser closed",
408+
};
409+
410+
this.userService.StoreUserHistory(userHistory);
411+
return this.Ok(true);
412+
}
413+
382414
/// <summary>
383415
/// The SitemapXml.
384416
/// </summary>

LearningHub.Nhs.WebUI/Views/Shared/Tenant/LearningHub/_Layout.cshtml

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -133,19 +133,19 @@
133133
@if (!ViewData["DisableValidation"]?.Equals(true) ?? true)
134134
{
135135
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.5/jquery.validate.min.js"
136-
asp-fallback-src="~/lib/jquery-validation/dist/jquery.validate.min.js"
137-
asp-fallback-test="window.jQuery && window.jQuery.validator"
138-
asp-suppress-fallback-integrity="true"
139-
crossorigin="anonymous"
140-
integrity="sha512-rstIgDs0xPgmG6RX1Aba4KV5cWJbAMcvRCVmglpam9SoHZiUCyQVDdH2LPlxoHtrv17XWblE/V/PP+Tr04hbtA==">
136+
asp-fallback-src="~/lib/jquery-validation/dist/jquery.validate.min.js"
137+
asp-fallback-test="window.jQuery && window.jQuery.validator"
138+
asp-suppress-fallback-integrity="true"
139+
crossorigin="anonymous"
140+
integrity="sha512-rstIgDs0xPgmG6RX1Aba4KV5cWJbAMcvRCVmglpam9SoHZiUCyQVDdH2LPlxoHtrv17XWblE/V/PP+Tr04hbtA==">
141141
</script>
142142
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validation-unobtrusive/4.0.0/jquery.validate.unobtrusive.min.js"
143-
asp-fallback-src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"
144-
asp-fallback-test="window.jQuery && window.jQuery.validator && window.jQuery.validator.unobtrusive"
145-
asp-suppress-fallback-integrity="true"
146-
crossorigin="anonymous"
147-
integrity="sha512-xq+Vm8jC94ynOikewaQXMEkJIOBp7iArs3IhFWSWdRT3Pq8wFz46p+ZDFAR7kHnSFf+zUv52B3prRYnbDRdgog==">
148-
</script>
143+
asp-fallback-src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"
144+
asp-fallback-test="window.jQuery && window.jQuery.validator && window.jQuery.validator.unobtrusive"
145+
asp-suppress-fallback-integrity="true"
146+
crossorigin="anonymous"
147+
integrity="sha512-xq+Vm8jC94ynOikewaQXMEkJIOBp7iArs3IhFWSWdRT3Pq8wFz46p+ZDFAR7kHnSFf+zUv52B3prRYnbDRdgog==">
148+
</script>
149149
}
150150
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js" asp-append-version="true"></script>
151151
<script type="text/javascript" src="~/js/jquery.matchHeight.min.js" asp-append-version="true"></script>
@@ -161,6 +161,13 @@
161161
@RenderSection("Scripts", required: false)
162162

163163
<script type="text/javascript" src="~/js/mkplayer-ui-custom.js" asp-append-version="true"></script>
164+
<script type="text/javascript" src="~/js/pageunload.js" asp-append-version="true"></script>
165+
166+
<script type="text/javascript">
167+
// Bind the function to the unload event
168+
window.onunload = tellServerBrowserClosed;
169+
170+
</script>
164171

165172
</body>
166173
</html>

LearningHub.Nhs.WebUI/appsettings.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
"Restricted": false,
4040
"PasswordRequestLimitingPeriod": 1, // minutes
4141
"PasswordRequestLimit": 2,
42+
"ConcurrentId": 0,
4243
"AzureBlobSettings": {
4344
"ConnectionString": "",
4445
"UploadContainer": ""
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
 // This function will be called when the browser window is closed or unloaded
2+
function tellServerBrowserClosed() {
3+
// Send an asynchronous request to the server when the browser is closed
4+
fetch('/api/user/browser-close', {
5+
method: 'POST',
6+
headers: {
7+
'Content-Type': 'application/json'
8+
},
9+
body: JSON.stringify({ message: 'Browser closed' })
10+
})
11+
.then(response => response.json())
12+
.catch(error => console.error('Error sending data to server:', error));
13+
}

0 commit comments

Comments
 (0)