v1.3.0 Restructure Saxonite workspace and upgrade to .NET 10 (#1)
Move Saxonite’s projects into a dedicated `Workspace` folder and align the solution with .NET 10 and the current Common workspace. Update encryption integration, test project structure and coverage, and repository guidance and upgrade notes. - Relocate application and library projects while retaining Git rename history. - Split tests into Admin, Online, and Shared projects; add representative behavioral and serialization tests. - Update Common integration, application version, and repository documentation. Application version: 1.3.0 Reviewed-on: #1 Co-authored-by: andy <andy@sarand.com>
This commit was merged in pull request #1.
This commit is contained in:
+187
@@ -0,0 +1,187 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Dbas;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using Sarand.Net.Standard.Dbas.Data;
|
||||
using Saxonite.Net.Core.Web.Admin.Models;
|
||||
using Saxonite.Net.Standard.Base.App;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
{
|
||||
//=======================================================================
|
||||
// Home Controller - Ajax - Application Stats
|
||||
//=======================================================================
|
||||
partial class HomeController
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Application Stats data.
|
||||
private class ApplicationStatsData
|
||||
{
|
||||
public class UserStatsData
|
||||
{
|
||||
public String Caption { get; set; }
|
||||
public AjaxResponse_Data.ItemLabelValue Awaiting { get; set; }
|
||||
public String UsersLink { get; set; }
|
||||
public String AwaitingLink { get; set; }
|
||||
public List<AjaxResponse_Data.ItemLabelValue> OnlineStats { get; set; }
|
||||
public String OnlineLink { get; set; }
|
||||
}
|
||||
public UserStatsData User { get; } = new UserStatsData();
|
||||
public class OrganisationStatsData
|
||||
{
|
||||
public String Caption { get; set; }
|
||||
public AjaxResponse_Data.ItemLabelValue Awaiting { get; set; }
|
||||
public String OrganisationsLink { get; set; }
|
||||
public String AwaitingLink { get; set; }
|
||||
}
|
||||
public OrganisationStatsData Organisation { get; } = new OrganisationStatsData();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Get Application Stats ajax request.
|
||||
//-------------------------------------------------------------------
|
||||
private class AjaxResponse_ApplicationStats : AjaxResponse_Data
|
||||
{
|
||||
// Construction.
|
||||
public AjaxResponse_ApplicationStats(SaxModel_Admin model) : base(model) { }
|
||||
// Table list.
|
||||
public ApplicationStatsData Stats { get; } = new ApplicationStatsData();
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
[HttpPost]
|
||||
[Route("Home/Ajax/GetApplicationStats")]
|
||||
public IActionResult Ajax_GetApplicationStats(Model_Sport model)
|
||||
{
|
||||
String messageTitle = Localiser["home.caption.application"];
|
||||
AjaxResponse_ApplicationStats responseData = new AjaxResponse_ApplicationStats(model);
|
||||
|
||||
// Validate session.
|
||||
if (!ValidUserSession)
|
||||
return GetAjaxResult_InvalidSession(responseData);
|
||||
|
||||
// Captions.
|
||||
responseData.Stats.User.Caption = Localiser["user.caption.users"];
|
||||
responseData.Stats.Organisation.Caption = Localiser["caption.organisations"];
|
||||
|
||||
// Core Database connection.
|
||||
ISacsDatabase db = Internals.CoreDatabase;
|
||||
|
||||
// Query to count items awaiting activation.
|
||||
Dictionary<String, int> tableRowCounts = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
|
||||
List<String> query = new List<string>()
|
||||
{
|
||||
// User accounts.
|
||||
"SELECT",
|
||||
"ItemType = '" + DbQuery.FormatForCondition(nameof(Sax.DataItemType.UserAccount)) + "',",
|
||||
"ItemCount = Count(*)",
|
||||
"FROM UserAccount ua",
|
||||
"WHERE ua.Status = 'AWA'",
|
||||
// Organisations.
|
||||
"UNION SELECT",
|
||||
"ItemType = '" + DbQuery.FormatForCondition(nameof(Sax.DataItemType.Organisation)) + "',",
|
||||
"ItemCount = Count(*)",
|
||||
"FROM Organisation org",
|
||||
"WHERE org.Status = 'AWA'",
|
||||
};
|
||||
using (DbResultSet dbResultSet = DbResultSet_DataReader.ExecuteQuery(db, query.Concat("\n")))
|
||||
{
|
||||
while (dbResultSet != null && dbResultSet.NextRecord())
|
||||
{
|
||||
NamedValue.Map values = dbResultSet.GetRecordValues();
|
||||
Sax.DataItemType itemType = EnumUtil.ParseEnum(values.GetValue("ItemType").ToString(), Sax.DataItemType.Unknown);
|
||||
int itemCount = (int)values.GetValue("ItemCount").AsLong();
|
||||
switch (itemType)
|
||||
{
|
||||
case Sax.DataItemType.UserAccount:
|
||||
responseData.Stats.User.Awaiting = new AjaxResponse_Data.ItemLabelValue() { Label = Localiser["label.awaiting.activation"], Value = itemCount.ToString() };
|
||||
responseData.Stats.User.UsersLink = Url.Action("", "User").TrimStart('/');
|
||||
responseData.Stats.User.AwaitingLink = Url.Action("", "User", new RouteValueDictionary() { { "sta", "Await" } }).TrimStart('/');
|
||||
break;
|
||||
case Sax.DataItemType.Organisation:
|
||||
responseData.Stats.Organisation.Awaiting = new AjaxResponse_Data.ItemLabelValue() { Label = Localiser["label.awaiting.activation"], Value = itemCount.ToString() };
|
||||
responseData.Stats.Organisation.OrganisationsLink = Url.Action("", "Organisation").TrimStart('/');
|
||||
responseData.Stats.Organisation.AwaitingLink = Url.Action("", "Organisation", new RouteValueDictionary() { { "sta", "Await" } }).TrimStart('/');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Query to count users online.
|
||||
DateTime today = DateTime.Today;
|
||||
DateTime now = DateTime.Now;
|
||||
const String online5Mins = "Online5Mins";
|
||||
const String online15Mins = "Online15Mins";
|
||||
const String online30Mins = "Online30Mins";
|
||||
const String online60Mins = "Online60Mins";
|
||||
const String onlineToday = "OnlineToday";
|
||||
const String onlineWeek = "OnlineWeek";
|
||||
const String onlineMonth = "OnlineMonth";
|
||||
query = new List<string>()
|
||||
{
|
||||
// Users Online last 5 mins.
|
||||
"Select '" + online5Mins + "' ItemType, (Select Count(*) From UserOnline Where OnlineAt>=" + DbQuery.FormatDateTimeForCondition(now.AddMinutes(-5)) + ") ItemCount ",
|
||||
"Union Select '" + online15Mins + "' ItemType, (Select Count(*) From UserOnline Where OnlineAt>=" + DbQuery.FormatDateTimeForCondition(now.AddMinutes(-15)) + ") ItemCount ",
|
||||
"Union Select '" + online30Mins + "' ItemType, (Select Count(*) From UserOnline Where OnlineAt>=" + DbQuery.FormatDateTimeForCondition(now.AddMinutes(-30)) + ") ItemCount ",
|
||||
"Union Select '" + online60Mins + "' ItemType, (Select Count(*) From UserOnline Where OnlineAt>=" + DbQuery.FormatDateTimeForCondition(now.AddMinutes(-60)) + ") ItemCount ",
|
||||
"Union Select '" + onlineToday + "' ItemType, (Select Count(*) From UserOnline Where OnlineAt>=" + DbQuery.FormatDateForCondition(today) + ") ItemCount ",
|
||||
"Union Select '" + onlineWeek + "' ItemType, (Select Count(*) From UserOnline Where OnlineAt>=" + DbQuery.FormatDateForCondition(DateUtil.StartOfWorkingWeek(today)) + ") ItemCount ",
|
||||
"Union Select '" + onlineMonth + "' ItemType, (Select Count(*) From UserOnline Where OnlineAt>=" + DbQuery.FormatDateForCondition(DateUtil.StartOfMonth(today)) + ") ItemCount ",
|
||||
};
|
||||
using (DbResultSet dbResultSet = DbResultSet_DataReader.ExecuteQuery(db, query.Concat("\n")))
|
||||
{
|
||||
while (dbResultSet != null && dbResultSet.NextRecord())
|
||||
{
|
||||
if (responseData.Stats.User.OnlineStats == null)
|
||||
responseData.Stats.User.OnlineStats = new List<AjaxResponse_Data.ItemLabelValue>();
|
||||
NamedValue.Map values = dbResultSet.GetRecordValues();
|
||||
String itemType = values.GetValue("ItemType").ToString();
|
||||
int itemCount = (int)values.GetValue("ItemCount").AsLong();
|
||||
switch (itemType)
|
||||
{
|
||||
case online5Mins:
|
||||
if (itemCount > 0)
|
||||
responseData.Stats.User.OnlineStats.Add(new AjaxResponse_Data.ItemLabelValue() { Label = Localiser["label.online.last5Mins"], Value = itemCount.ToString() });
|
||||
break;
|
||||
case online15Mins:
|
||||
if (itemCount > 0)
|
||||
responseData.Stats.User.OnlineStats.Add(new AjaxResponse_Data.ItemLabelValue() { Label = Localiser["label.online.last15Mins"], Value = itemCount.ToString() });
|
||||
break;
|
||||
case online30Mins:
|
||||
if (itemCount > 0)
|
||||
responseData.Stats.User.OnlineStats.Add(new AjaxResponse_Data.ItemLabelValue() { Label = Localiser["label.online.last30Mins"], Value = itemCount.ToString() });
|
||||
break;
|
||||
case online60Mins:
|
||||
if (itemCount > 0)
|
||||
responseData.Stats.User.OnlineStats.Add(new AjaxResponse_Data.ItemLabelValue() { Label = Localiser["label.online.last60Mins"], Value = itemCount.ToString() });
|
||||
break;
|
||||
case onlineToday:
|
||||
if (itemCount > 0)
|
||||
responseData.Stats.User.OnlineStats.Add(new AjaxResponse_Data.ItemLabelValue() { Label = Localiser["label.online.today"], Value = itemCount.ToString() });
|
||||
break;
|
||||
case onlineWeek:
|
||||
if (itemCount > 0)
|
||||
responseData.Stats.User.OnlineStats.Add(new AjaxResponse_Data.ItemLabelValue() { Label = Localiser["label.online.thisWeek"], Value = itemCount.ToString() });
|
||||
break;
|
||||
case onlineMonth:
|
||||
if (itemCount > 0)
|
||||
responseData.Stats.User.OnlineStats.Add(new AjaxResponse_Data.ItemLabelValue() { Label = Localiser["label.online.thisMonth"], Value = itemCount.ToString() });
|
||||
break;
|
||||
}
|
||||
responseData.Stats.User.OnlineLink = Url.Action("", "UsersOnline", new RouteValueDictionary() { }).TrimStart('/');
|
||||
}
|
||||
}
|
||||
|
||||
// Complete response.
|
||||
responseData.Success = true;
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
Reference in New Issue
Block a user