v1.2.11.2
This commit is contained in:
+8
-2
@@ -1,7 +1,7 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.31019.35
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.7.34202.233
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SaxoniteCoreWebAdmin", "SaxoniteCoreWebAdmin\SaxoniteCoreWebAdmin.csproj", "{F646283D-F7C2-42DD-AB1E-E741455664BD}"
|
||||
EndProject
|
||||
@@ -32,6 +32,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution files", "Solution
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SaxoniteCoreUnitTestsOnline", "SaxoniteCoreUnitTestsOnline\SaxoniteCoreUnitTestsOnline.csproj", "{303BA8E9-1B95-41AD-9F51-32037A22C908}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SacsStandardProc", "..\..\Common-VS\Workspace\SacsStandardProc\SacsStandardProc.csproj", "{E012B3D3-CF4D-4C2E-ABC6-9E3A3DAE03C5}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -86,6 +88,10 @@ Global
|
||||
{303BA8E9-1B95-41AD-9F51-32037A22C908}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{303BA8E9-1B95-41AD-9F51-32037A22C908}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{303BA8E9-1B95-41AD-9F51-32037A22C908}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E012B3D3-CF4D-4C2E-ABC6-9E3A3DAE03C5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E012B3D3-CF4D-4C2E-ABC6-9E3A3DAE03C5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E012B3D3-CF4D-4C2E-ABC6-9E3A3DAE03C5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E012B3D3-CF4D-4C2E-ABC6-9E3A3DAE03C5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
|
||||
@@ -10,10 +10,13 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
|
||||
<PackageReference Include="Moq" Version="4.18.4" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="2.1.0" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="2.1.0" />
|
||||
<PackageReference Include="coverlet.collector" Version="1.2.0" />
|
||||
<PackageReference Include="Moq" Version="4.20.70" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="3.2.1" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="3.2.1" />
|
||||
<PackageReference Include="coverlet.collector" Version="1.3.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
|
||||
@@ -10,10 +10,13 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
|
||||
<PackageReference Include="Moq" Version="4.18.4" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="2.1.0" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="2.1.0" />
|
||||
<PackageReference Include="coverlet.collector" Version="1.2.0" />
|
||||
<PackageReference Include="Moq" Version="4.20.70" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="3.2.1" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="3.2.1" />
|
||||
<PackageReference Include="coverlet.collector" Version="1.3.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -121,7 +121,7 @@ namespace Saxonite.Net.Core.UnitTests.Web.Online.App
|
||||
Assert.AreEqual(userRoles.Count, sessionDataDeserialised.User.Roles.Count);
|
||||
foreach (var userRoleDeserialised in sessionDataDeserialised.User.Roles)
|
||||
{
|
||||
Assert.AreNotEqual(0, userRoleDeserialised.Role);
|
||||
Assert.AreNotEqual(0, (int)userRoleDeserialised.Role);
|
||||
}
|
||||
|
||||
// User configuration.
|
||||
|
||||
@@ -41,13 +41,23 @@ namespace Saxonite.Net.Core.Web.Base.App
|
||||
protected SaxApplication_Web()
|
||||
{
|
||||
WebApp = this;
|
||||
System_Web = new SaxSystem_Web();
|
||||
}
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
WebApp = null;
|
||||
System_Web = null;
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
public override SaxSystem System { get { return System_Web; } }
|
||||
public SaxSystem_Web System_Web { get; protected set; }
|
||||
// Globals.
|
||||
public static SaxApplication_Web WebApp { get; private set; }
|
||||
public override SaxSystem System { get { return System_Web; } }
|
||||
public SaxSystem_Web System_Web { get; private set; }
|
||||
// Application instance.
|
||||
public override Sax.InstanceType InstanceType { get { return instanceType; } }
|
||||
public override String EnvironmentName { get { return environmentName; } }
|
||||
@@ -57,7 +67,6 @@ namespace Saxonite.Net.Core.Web.Base.App
|
||||
public abstract String SessionCookieName { get; }
|
||||
public virtual SaxSessionContext SessionContext { get; protected set; }
|
||||
public abstract SaxAppConfig AppConfig { get; }
|
||||
public override SaxConsoleHelper ConsoleHelper { get { return ConsoleHelper_Web; } }
|
||||
public SaxConsoleHelper_Web ConsoleHelper_Web { get; protected set; }
|
||||
public override IDatabaseInfo CreateDbInfo(SaxSessionContext sessionContext, Sax.Database databaseType) { return new DbDataItem.DatabaseInfo(GetDatabase(sessionContext, databaseType)); }
|
||||
// Configuration.
|
||||
|
||||
@@ -113,7 +113,7 @@ namespace Saxonite.Net.Core.Web.Base.App
|
||||
opts => { opts.ResourcesPath = resourcesPath; })
|
||||
.AddDataAnnotationsLocalization()
|
||||
// Ignore null values during object serisliation.
|
||||
.AddJsonOptions(options => { options.JsonSerializerOptions.IgnoreNullValues = true; });
|
||||
.AddJsonOptions(options => { options.JsonSerializerOptions.DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull; });
|
||||
|
||||
// Configure localisation middleware.
|
||||
config.services.Configure<RequestLocalizationOptions>
|
||||
|
||||
@@ -13,6 +13,10 @@ namespace Saxonite.Net.Core.Web.Base.Consoles
|
||||
protected SaxConsoleHelper_Web()
|
||||
{
|
||||
}
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
using Sacs.Web.Components;
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
@@ -34,7 +35,7 @@ using System.Web;
|
||||
namespace Saxonite.Net.Core.Web.Base.Controllers
|
||||
{
|
||||
//=======================================================================
|
||||
public abstract class SaxController_Base : Controller
|
||||
public abstract class SaxController_Base : SaController
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
@@ -44,7 +45,6 @@ namespace Saxonite.Net.Core.Web.Base.Controllers
|
||||
// Protected construction.
|
||||
protected SaxController_Base(SaxLocaliser localiser)
|
||||
{
|
||||
CreatedAt = DateTime.Now;
|
||||
Localiser = localiser;
|
||||
|
||||
// Initialise console (debug) logging listener.
|
||||
@@ -62,43 +62,14 @@ namespace Saxonite.Net.Core.Web.Base.Controllers
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
public DateTime CreatedAt { get; }
|
||||
public bool DebugMode { get; } = SacsSystem.DebugMode;
|
||||
protected SaxApplication_Web App { get { return SaxApplication_Web.WebApp; } }
|
||||
public SaxAppConfig AppConfig { get { return App.AppConfig; } }
|
||||
public SaxSessionContext SessionContext { get { return App.SessionContext; } }
|
||||
public SaxLocaliser Localiser { get; }
|
||||
/// <summary>
|
||||
/// Indicate whether session data should be stored by action.
|
||||
/// <para>Any action that might modify the session data must store it.</para>
|
||||
/// <para>Some actions such as scoring a password's complexity don't need to.</para>
|
||||
/// </summary>
|
||||
public virtual bool StoreSessionData { get; protected set; } = true;
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Culture.
|
||||
private CultureInfo sessionCulture;
|
||||
private CultureInfo RequestCulture { get { return Request.HttpContext.Features.Get<IRequestCultureFeature>().RequestCulture.Culture ?? CultureInfo.InvariantCulture; } }
|
||||
public CultureInfo SessionCulture
|
||||
{
|
||||
get
|
||||
{
|
||||
if (sessionCulture == null)
|
||||
{
|
||||
sessionCulture = RequestCulture;
|
||||
// ToDo Adjust culture if needed.
|
||||
}
|
||||
return sessionCulture;
|
||||
}
|
||||
}
|
||||
private string LanguageIso2
|
||||
{
|
||||
get
|
||||
{
|
||||
var feature = HttpContext.Features.Get<IRequestCultureFeature>();
|
||||
return feature.RequestCulture.UICulture.TwoLetterISOLanguageName.ToLower();
|
||||
}
|
||||
}
|
||||
// Globals.
|
||||
protected SaxConsoleHelper ConsoleHelper { get { return SaxGlobals.ConsoleHelper; } }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Business components.
|
||||
@@ -138,36 +109,6 @@ namespace Saxonite.Net.Core.Web.Base.Controllers
|
||||
public SaEmailConfig EmailConfig { get { return App.EmailConfig; } }
|
||||
public SaxEmailConsole EmailConsole { get { return Internals.EmailConsole; } }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Redirection locations.
|
||||
//-------------------------------------------------------------------
|
||||
public static readonly String ParamName_SessionExpired = "SessionExpired";
|
||||
public enum RedirectLocation
|
||||
{
|
||||
WebAppBase,
|
||||
WebAppHome,
|
||||
WebAppHome_SessionExpired,
|
||||
}
|
||||
public String GetRedirectLocation(RedirectLocation redirectLocation)
|
||||
{
|
||||
string protocol = Request.Scheme;
|
||||
var parameters = new RouteValueDictionary();
|
||||
String homeAction = Url.Action("Index", "Home", parameters, protocol);
|
||||
switch (redirectLocation)
|
||||
{
|
||||
case RedirectLocation.WebAppBase:
|
||||
return Regex.Replace(homeAction, "\\/$", "") + "/";
|
||||
case RedirectLocation.WebAppHome:
|
||||
return homeAction;
|
||||
case RedirectLocation.WebAppHome_SessionExpired:
|
||||
// Set the session expired parameter so that the page can report it.
|
||||
// NB Paramater must have a value to be included in the URL query string.
|
||||
parameters.Add(ParamName_SessionExpired, "1");
|
||||
return homeAction;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Action execution events.
|
||||
//-------------------------------------------------------------------
|
||||
@@ -212,7 +153,6 @@ namespace Saxonite.Net.Core.Web.Base.Controllers
|
||||
Response.Headers.Add(HeaderNames.Expires, "0");
|
||||
}
|
||||
|
||||
|
||||
base.OnActionExecuted(filterContext);
|
||||
}
|
||||
|
||||
@@ -244,78 +184,22 @@ namespace Saxonite.Net.Core.Web.Base.Controllers
|
||||
//private static String Base64IV_RequestPassword_Generated_Online { get; } = SacsEncryptionHelper.InitSymmetricEncryptionIV(Base64Key_RequestPassword_Online);
|
||||
protected static String Base64IV_RequestPassword_Online { get; } = "1VAWYTW6d72n/6HDNhbqow==";
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
public static String EncryptParameters(NameValueCollection parameters, String base64IV, String base64Key)
|
||||
{
|
||||
String fn = nameof(ControllerBase) + ".EncryptParameters";
|
||||
try
|
||||
{
|
||||
// Copy the list of parameters and sort the keys.
|
||||
NameValueCollection parametersToEncrypt = new NameValueCollection(parameters);
|
||||
String[] paramKeys = parametersToEncrypt.AllKeys;
|
||||
Array.Sort(paramKeys);
|
||||
|
||||
// Serialise parameters as if in a URL query string - so that they can be deserialised in DecryptParameters() below.
|
||||
// Start with a random length parameter name at start of list to obscure the encryption.
|
||||
string queryString = SacsRandomHelper.getRandomLengthNumber(4) + "&";
|
||||
queryString += String.Join("&", paramKeys.Select(a => a + "=" + HttpUtility.UrlEncode(parametersToEncrypt[a])));
|
||||
|
||||
// Encrypt data.
|
||||
String encrypted = SacsEncryptionHelper.Encrypt(queryString, base64IV, base64Key);
|
||||
//if (SacsSystem.DebugMode) SaLogger.Debug(fn + "\n\tData: " + queryString + " \n\tEncrypted: " + encrypted);
|
||||
return encrypted;
|
||||
}
|
||||
catch (Exception exc) { SaLogger.Warn(fn + " " + ExceptionUtil.GetErrorStateMessage(exc)); }
|
||||
return "";
|
||||
}
|
||||
public static NameValueCollection DecryptParameters(String encrypted, String base64IV, String base64Key)
|
||||
{
|
||||
String fn = nameof(ControllerBase) + ".DecryptParameters";
|
||||
try
|
||||
{
|
||||
String queryString = SacsEncryptionHelper.Decrypt(encrypted, base64IV, base64Key);
|
||||
//if (SacsSystem.DebugMode) SaLogger.Debug(fn + " \n\tEncrypted: " + encrypted + "\n\tData: " + queryString);
|
||||
return HttpUtility.ParseQueryString(queryString);
|
||||
}
|
||||
catch (Exception exc) { SaLogger.Warn(fn + " " + ExceptionUtil.GetErrorStateMessage(exc)); }
|
||||
return new NameValueCollection();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Cookies.
|
||||
//-------------------------------------------------------------------
|
||||
/// <summary>Retrieve the value from the named request cookie.</summary>
|
||||
public String GetRequestCookie(String key)
|
||||
{
|
||||
if (Request.Cookies.ContainsKey(key))
|
||||
return Request.Cookies[key];
|
||||
return null;
|
||||
}
|
||||
/// <summary>Set the value against the named response cookie.</summary>
|
||||
public void SetResponseCookie(string key, string value, DateTime? expiresAt = null, bool isEssential = false)
|
||||
{
|
||||
CookieOptions options = new CookieOptions();
|
||||
options.HttpOnly = true;
|
||||
options.Secure = true;
|
||||
options.SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Strict;
|
||||
if (expiresAt.HasValue)
|
||||
options.Expires = expiresAt;
|
||||
if (isEssential)
|
||||
options.IsEssential = true;
|
||||
Response.Cookies.Append(key, value, options);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Session.
|
||||
//-------------------------------------------------------------------
|
||||
private bool UserActiveRecorded { get; set; } = false;
|
||||
public bool ValidUserSession
|
||||
{
|
||||
get
|
||||
{
|
||||
if (SessionData == null || !SessionData.ValidUserSession) return false;
|
||||
SaxSessionDataConsole sessionDataConsole = SessionDataConsole;
|
||||
if (sessionDataConsole != null)
|
||||
if (sessionDataConsole != null && !UserActiveRecorded)
|
||||
{
|
||||
// Record the user as active once per request.
|
||||
sessionDataConsole.RecordUserActive(SessionUserAccountId, CreatedAt);
|
||||
UserActiveRecorded = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -403,240 +287,6 @@ namespace Saxonite.Net.Core.Web.Base.Controllers
|
||||
}
|
||||
protected abstract SaxSessionData DeserializeSessionData(String sessionDataJson);
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Ajax actions.
|
||||
//-------------------------------------------------------------------
|
||||
protected static readonly Encoding ajaxResponseEncoding = Encoding.UTF8;
|
||||
protected IActionResult GetAjaxResult_GoHome(AjaxResponse_Base responseData)
|
||||
{
|
||||
responseData.SetGoHome();
|
||||
return Json(responseData);
|
||||
}
|
||||
protected IActionResult GetAjaxResult_InvalidSession(AjaxResponse_Base responseData)
|
||||
{
|
||||
responseData.SetGoHome();
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Response data.
|
||||
// Null values are ignored by JSON serialisation.
|
||||
// - See Saxonite.Net.Core.Web.Base.App.SaxStartup.ConfigureServices()
|
||||
// - Ref. config.services.AddMvc(...).AddJsonOptions(options => { options.JsonSerializerOptions.IgnoreNullValues = true; });
|
||||
//-------------------------------------------------------------------
|
||||
// Base response data - for simple responses.
|
||||
public class AjaxResponse_Base
|
||||
{
|
||||
// Response status.
|
||||
public bool? Success { get; set; } = null;
|
||||
public bool? Error { get; set; } = null;
|
||||
public bool? SessionExpired { get; protected set; } = null;
|
||||
public bool? GoHome { get; protected set; } = null;
|
||||
public AjaxResponse_Base SetSessionExpired(String title, String text)
|
||||
{
|
||||
SessionExpired = true;
|
||||
return SetMessage(title, text);
|
||||
}
|
||||
public AjaxResponse_Base SetGoHome()
|
||||
{
|
||||
GoHome = true;
|
||||
return this;
|
||||
}
|
||||
public AjaxResponse_Base SetGoHome(String title, String text)
|
||||
{
|
||||
GoHome = true;
|
||||
return SetMessage(title, text);
|
||||
}
|
||||
// Message - displays alert popup.
|
||||
public class MessageData
|
||||
{
|
||||
public String Title { get; set; }
|
||||
public String Text { get; set; }
|
||||
}
|
||||
public MessageData Message { get; private set; }
|
||||
public AjaxResponse_Base SetMessage(String title, String text)
|
||||
{
|
||||
if (!StringUtil.IsEmpty(text))
|
||||
Message = new MessageData() { Title = title, Text = text };
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
public class AjaxResponse_Data : AjaxResponse_Base
|
||||
{
|
||||
//---------------------------------------------------------------
|
||||
// Construction.
|
||||
protected AjaxResponse_Data(SaxModel_Base model)
|
||||
{
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
/// <summary>Item data - Common properties for data items.</summary>
|
||||
public class ItemData_Base
|
||||
{
|
||||
// Common item properties.
|
||||
public String Id { get; set; }
|
||||
public String Notes { get; set; }
|
||||
public String StatusCode { get; set; }
|
||||
public String StatusDesc { get; set; }
|
||||
// Flags for common status values.
|
||||
// Return true or null so that property is not serialised when false.
|
||||
public bool? Awaiting { get { return StatusCode.EqualsCI(SacsSystem.GetStatusCode(SaStatus.Awaiting)) ? true : (bool?)null; } }
|
||||
public bool? Active { get { return StatusCode.EqualsCI(SacsSystem.GetStatusCode(SaStatus.Active)) ? true : (bool?)null; } }
|
||||
public bool? Inactive { get { return StatusCode.EqualsCI(SacsSystem.GetStatusCode(SaStatus.Inactive)) ? true : (bool?)null; } }
|
||||
public bool? Deleted { get { return StatusCode.EqualsCI(SacsSystem.GetStatusCode(SaStatus.Deleted)) ? true : (bool?)null; } }
|
||||
/// <summary>Created on date - YYYYMMDD</summary>
|
||||
public String CreatedOn { get; set; }
|
||||
/// <summary>Created on date - formatted per locale</summary>
|
||||
public String CreatedOnFmt { get; set; }
|
||||
/// <summary>Updated on date - YYYYMMDD</summary>
|
||||
public String UpdatedOn { get; set; }
|
||||
/// <summary>Updated on date - formatted per locale</summary>
|
||||
public String UpdatedOnFmt { get; set; }
|
||||
}
|
||||
/// <summary>Contact Method properties.</summary>
|
||||
public class ContactMethodData
|
||||
{
|
||||
public String Method { get; set; }
|
||||
public String MethodCaption { get; set; }
|
||||
public String Value { get; set; }
|
||||
}
|
||||
/// <summary>Address properties.</summary>
|
||||
public class AddressData : ItemData_Base
|
||||
{
|
||||
public String Line1 { get; set; }
|
||||
public String Line2 { get; set; }
|
||||
public String Line3 { get; set; }
|
||||
public String Town { get; set; }
|
||||
public String RegionIdProvince { get; set; }
|
||||
public String RegionNameProvince { get; set; }
|
||||
public String RegionIdCountry { get; set; }
|
||||
public String RegionNameCountry { get; set; }
|
||||
public String PostalCode { get; set; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Item data with label and value.
|
||||
/// </summary>
|
||||
public class ItemLabelValue
|
||||
{
|
||||
public String Label { get; set; }
|
||||
public String Value { get; set; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Item data with just Id and name.
|
||||
/// <para>- Id is String to allow for obfuscated values.</para>
|
||||
/// </summary>
|
||||
public class ItemIdName
|
||||
{
|
||||
public String Id { get; set; }
|
||||
public String Name { get; set; }
|
||||
}
|
||||
/// <summary>Item code and desc values.</summary>
|
||||
public class ItemCodeDesc
|
||||
{
|
||||
public String Code { get; set; }
|
||||
public String Desc { get; set; }
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Form data.
|
||||
public class FormControlValue
|
||||
{
|
||||
public FormControlValue(String controlName, String value, String error)
|
||||
{
|
||||
ControlName = controlName;
|
||||
Value = value;
|
||||
Error = error;
|
||||
}
|
||||
public String ControlName { get; }
|
||||
public String Value { get; set; }
|
||||
public String Error { get; set; }
|
||||
}
|
||||
private readonly Dictionary<String, FormControlValue> controlValues = new Dictionary<String, FormControlValue>();
|
||||
public List<FormControlValue> ControlValues { get { return controlValues.Count > 0 ? controlValues.Values.ToList() : null; } }
|
||||
public void SetControlValue(String controlName, String value, String error = null)
|
||||
{
|
||||
if (controlValues.ContainsKey(controlName))
|
||||
{
|
||||
// Modify existing entry in the list.
|
||||
FormControlValue controlValue = controlValues[controlName];
|
||||
if (value != null) controlValue.Value = value;
|
||||
if (error != null) controlValue.Error = error;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add new control to list.
|
||||
controlValues.Add(controlName, new FormControlValue(controlName, value, error));
|
||||
}
|
||||
}
|
||||
/// <summary>Assign the error to the control by name and return this response data.</summary>
|
||||
public AjaxResponse_Data SetControlError(String controlName, String error)
|
||||
{
|
||||
return SetControlError(controlName, error, this);
|
||||
}
|
||||
/// <summary>
|
||||
/// Assign the error to the control by name and return the specified value.
|
||||
/// <para>- Allows alternative return values to be specified (eg. 'false') to avoid separate return statement in calling routine.</para>
|
||||
/// </summary>
|
||||
public T SetControlError<T>(String controlName, String error, T returnValue)
|
||||
{
|
||||
SetControlValue(controlName, null, error);
|
||||
return returnValue;
|
||||
}
|
||||
public bool HasControlErrors()
|
||||
{
|
||||
foreach (FormControlValue controlValue in controlValues.Values)
|
||||
{
|
||||
if (!StringUtil.IsEmpty(controlValue.Error)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Notification - briefly displays after response received.
|
||||
public class NotificationData
|
||||
{
|
||||
public String Title { get; set; }
|
||||
public String Message { get; set; }
|
||||
}
|
||||
public NotificationData Notification { get; private set; }
|
||||
public AjaxResponse_Data SetNotification(String title, String message)
|
||||
{
|
||||
Notification = new NotificationData() { Title = title, Message = message };
|
||||
return this;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Paged data.
|
||||
public class PagingData
|
||||
{
|
||||
public PagingData(SaxModel_Base model) :
|
||||
this(model.Paging.PageNo, model.Paging.PageLength, model.Paging.ItemCount, model.Paging.ItemTotal)
|
||||
{ }
|
||||
public PagingData(uint pageNo, ushort pageLength, ushort itemCount, ulong itemTotal)
|
||||
{
|
||||
PageNo = pageNo;
|
||||
PageLength = pageLength;
|
||||
ItemCount = itemCount;
|
||||
ItemTotal = itemTotal;
|
||||
}
|
||||
public bool Paged { get { return (PageNo > 0 && PageLength > 0 && ItemTotal > PageLength); } }
|
||||
public uint PageNo { get; } = 0;
|
||||
public ushort PageLength { get; } = 0;
|
||||
public uint PageCount { get { return (PageLength > 0 ? (uint)Math.Ceiling((decimal)ItemTotal / PageLength) : 0); } }
|
||||
public ushort ItemCount { get; } = 0;
|
||||
public ulong ItemTotal { get; } = 0;
|
||||
}
|
||||
public PagingData Paging { get; private set; }
|
||||
public void SetPaging(SaxModel_Base model)
|
||||
{
|
||||
Paging = new PagingData(model);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace Saxonite.Net.Core.Web.Base.Middleware
|
||||
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
|
||||
{
|
||||
// NoOp task to avoid compiler warning.
|
||||
await Task.Yield();
|
||||
await Task.CompletedTask;
|
||||
Context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
|
||||
return AuthenticateResult.NoResult();
|
||||
}
|
||||
|
||||
@@ -55,7 +55,6 @@ namespace Saxonite.Net.Core.Web.Base.Middleware
|
||||
/// </summary>
|
||||
protected override void SetProperty(ModelBindingContext bindingContext, string modelName, ModelMetadata propertyMetadata, ModelBindingResult result)
|
||||
{
|
||||
string fn = GetType().Name + ".SetProperty";
|
||||
//if (SaxSystem.DebugMode) Logger.Debug(fn + " Form property " + modelName + ": '" + result.Model.ToString() + ".");
|
||||
object originalValue = result.Model;
|
||||
// Exclude properties that retain leading/trailing whitespace.
|
||||
@@ -91,8 +90,8 @@ namespace Saxonite.Net.Core.Web.Base.Middleware
|
||||
result = ModelBindingResult.Success(value);
|
||||
}
|
||||
}
|
||||
if (result.Model != null && SaxSystem.DebugMode)
|
||||
SaLogger.Debug(fn + " Form property " + modelName + ": '" + result.Model.ToString() + "'." + (originalValue != null && !originalValue.Equals(result.Model) ? " Original value: '" + originalValue.ToString() + "'" : ""));
|
||||
if (result.Model != null && !result.Model.ToString().Equals(result.Model.GetType().FullName) && SaxSystem.DebugMode)
|
||||
SaLogger.Debug(SysUtil.Fn + " Form property " + modelName + ": '" + result.Model.ToString() + "'." + (originalValue != null && !originalValue.Equals(result.Model) ? " Original value: '" + originalValue.ToString() + "'" : ""));
|
||||
base.SetProperty(bindingContext, modelName, propertyMetadata, result);
|
||||
}
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace Saxonite.Net.Core.Web.Base.Middleware
|
||||
catch (Exception exc)
|
||||
{
|
||||
SaLogger.Warn(fn + " " + ExceptionUtil.GetLogMessage(exc));
|
||||
throw exc;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Microsoft.AspNetCore.Html;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using Sacs.Web.Components;
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
@@ -22,14 +23,11 @@ using static Saxonite.Net.Standard.Base.App.Sax;
|
||||
namespace Saxonite.Net.Core.Web.Base.Models
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaxModel_Base
|
||||
public class SaxModel_Base : SaModel
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
private SaxInternals internals;
|
||||
private readonly List<String> infoMessages = new List<string>();
|
||||
private readonly List<String> warningMessages = new List<string>();
|
||||
private readonly List<String> errorMessages = new List<string>();
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Protected construction.
|
||||
@@ -45,7 +43,6 @@ namespace Saxonite.Net.Core.Web.Base.Models
|
||||
protected SaxSystem_Web System { get { return App.System_Web; } }
|
||||
public String SessionCookieName { get { return App.SessionCookieName; } }
|
||||
public SaxLocaliser Localiser { get; }
|
||||
public bool DebugMode { get { return SaxSystem.DebugMode; } }
|
||||
// Session properties.
|
||||
public SaxSessionData SessionData { get; set; }
|
||||
public SaxSessionContext SessionContext { get { return SessionData?.SessionContext ?? App.SessionContext; } }
|
||||
@@ -56,25 +53,7 @@ namespace Saxonite.Net.Core.Web.Base.Models
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Page configuration.
|
||||
public bool OK { get { return !HasMessages(); } }
|
||||
public virtual bool ProhibitCache { get; set; } = true;
|
||||
public String PageCaption { get; set; }
|
||||
public String InstanceVersion { get { return !StringUtil.IsEmpty(App.AppConfig.Instance) ? App.AppConfig.Instance + " v" + Sax.Version.GetFullVersion() : "v" + Sax.Version.GetAppVersion(); } }
|
||||
public bool IncludeGoogleAnalytics { get; set; } = false;
|
||||
// Views can be registered to avoid multiple inclusions in a page.
|
||||
private HashSet<String> registeredViews = new HashSet<String>(StringComparer.OrdinalIgnoreCase);
|
||||
/// <summary>
|
||||
/// Views can be registered to avoid multiple inclusions in a page.
|
||||
/// <para>Only generate view content if this method returns true.</para>
|
||||
/// </summary>
|
||||
public bool RegisterView(String viewName)
|
||||
{
|
||||
#if DEBUG
|
||||
if (registeredViews.Contains(viewName))
|
||||
SaLogger.Warn(this.GetType().Name + ".RegisterView View already registered: " + viewName);
|
||||
#endif
|
||||
return registeredViews.Add(viewName);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Business components.
|
||||
@@ -156,33 +135,6 @@ namespace Saxonite.Net.Core.Web.Base.Models
|
||||
return new SelectList(items, "Code", "Desc");
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Version parameter for includes.
|
||||
public String HrefVersion
|
||||
{
|
||||
get
|
||||
{
|
||||
DateTime versionDate = SaxSystem.AssemblyBuildAt;
|
||||
if (!DateUtil.IsValid(versionDate) || SaxSystem.DebugMode)
|
||||
versionDate = DateTime.Now;
|
||||
return DateUtil.Format(versionDate, "yyyyMMdd" /*+ (SacsSystem.Debug ? "HHmm" : "")*/);
|
||||
}
|
||||
}
|
||||
// Additional includes.
|
||||
public HashSet<String> AdditionalFiles_CSS { get; set; } = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
public HashSet<String> AdditionalFiles_JS { get; set; } = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Redirection locations.
|
||||
public class RedirectLocationData
|
||||
{
|
||||
// Properties populated in Controller_Base.OnActionExecuted.
|
||||
public String Base { get; internal set; }
|
||||
public String Home { get; internal set; }
|
||||
public String Home_SessionExpired { get; internal set; }
|
||||
}
|
||||
public RedirectLocationData RedirectLocation { get; } = new RedirectLocationData();
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Link URLs.
|
||||
public class LinksData
|
||||
@@ -204,42 +156,6 @@ namespace Saxonite.Net.Core.Web.Base.Models
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Paging properties.
|
||||
public class DataPaging
|
||||
{
|
||||
private DbQuery.Paging paging { get; } = new DbQuery.Paging();
|
||||
public void PopulatePagingTo(DbQuery.Paging resultsPaging)
|
||||
{
|
||||
resultsPaging.PageLength = paging.PageLength;
|
||||
resultsPaging.PageNo = paging.PageNo;
|
||||
}
|
||||
public bool IsPaged { get { return paging.Paged; } }
|
||||
public uint PageNo { get { return paging.PageNo; } set { paging.PageNo = value; } }
|
||||
public String PageNoValue { get { return paging.PageNo.ToString(); } set { paging.PageNo = (uint)StringUtil.ToInt(value); } }
|
||||
public ushort PageLength { get { return paging.PageLength; } set { paging.PageLength = value; } }
|
||||
public String PageLengthValue { get { return paging.PageLength.ToString(); } set { paging.PageLength = (ushort)StringUtil.ToShort(value); } }
|
||||
public uint PageCount { get { return (PageLength > 0 ? (uint)Math.Ceiling((decimal)ItemTotal / paging.PageLength) : 0); } }
|
||||
public ushort ItemCount { get; set; }
|
||||
private ulong itemTotal = 0;
|
||||
public ulong ItemTotal
|
||||
{
|
||||
get { return itemTotal; }
|
||||
set
|
||||
{
|
||||
itemTotal = value;
|
||||
// Check whether the total number of items is less than the current page and reduce page no if needed.
|
||||
if (IsPaged && (PageNo - 1) * PageLength > itemTotal)
|
||||
PageNo = (uint)((itemTotal - 1) / PageLength + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
public DataPaging Paging { get; } = new DataPaging();
|
||||
public void PopulatePagingTo(DbQuery.Paging resultsPaging)
|
||||
{
|
||||
Paging.PopulatePagingTo(resultsPaging);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Form control value max length.
|
||||
@@ -487,35 +403,6 @@ namespace Saxonite.Net.Core.Web.Base.Models
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Messages.
|
||||
//-------------------------------------------------------------------
|
||||
public bool HasMessages()
|
||||
{
|
||||
return infoMessages.Count > 0 || warningMessages.Count > 0 || errorMessages.Count > 0;
|
||||
}
|
||||
public List<String> InfoMessages { get { return new List<string>(infoMessages); } }
|
||||
public List<String> WarningMessages { get { return new List<string>(warningMessages); } }
|
||||
public List<String> ErrorMessages { get { return new List<string>(errorMessages); } }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Form messages.
|
||||
public void AddInfoMessage(String message)
|
||||
{
|
||||
if (StringUtil.IsEmpty(StringUtil.TrimAll(message))) return;
|
||||
infoMessages.Add(message);
|
||||
}
|
||||
public void AddWarningMessage(String message)
|
||||
{
|
||||
if (StringUtil.IsEmpty(StringUtil.TrimAll(message))) return;
|
||||
warningMessages.Add(message);
|
||||
}
|
||||
public void AddErrorMessage(String message)
|
||||
{
|
||||
if (StringUtil.IsEmpty(StringUtil.TrimAll(message))) return;
|
||||
errorMessages.Add(message);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace Saxonite.Net.Core.Web.Base.Procs.Data
|
||||
{
|
||||
//=======================================================================
|
||||
/// <summary>
|
||||
/// Object to persist upload file after request has terminated, and the Form File has been disposed.
|
||||
/// <para>- Too allow async processes to access the file after request completed.</para>
|
||||
/// </summary>
|
||||
public class UploadFileData
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
public UploadFileData(IFormFile dataFile)
|
||||
{
|
||||
ContentDisposition = dataFile.ContentDisposition;
|
||||
ContentType = dataFile.ContentType;
|
||||
FileName = dataFile.FileName;
|
||||
Length = dataFile.Length;
|
||||
Name = dataFile.Name;
|
||||
foreach (var header in dataFile.Headers)
|
||||
Headers.Add(header.Key, header.Value.ToString());
|
||||
// Load file data.
|
||||
using (MemoryStream stream = new MemoryStream())
|
||||
{
|
||||
dataFile.CopyTo(stream);
|
||||
FileData = stream.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
|
||||
/// <summary>Gets the raw Content-Disposition header of the uploaded file.</summary>
|
||||
public String ContentDisposition { get; }
|
||||
|
||||
/// <summary>Gets the raw Content-Type header of the uploaded file.</summary>
|
||||
public String ContentType { get; }
|
||||
|
||||
/// <summary>Gets the file name from the Content-Disposition header.</summary>
|
||||
public String FileName { get; }
|
||||
|
||||
/// <summary>Gets the header dictionary of the uploaded file.</summary>
|
||||
public Dictionary<String, String> Headers { get; } = new Dictionary<String, String>();
|
||||
|
||||
/// <summary>Gets the file length in bytes.</summary>
|
||||
public long Length { get; }
|
||||
|
||||
/// <summary>Gets the form field name from the Content-Disposition header.</summary>
|
||||
public String Name { get; }
|
||||
|
||||
/// <summary>File data.</summary>
|
||||
public byte[] FileData { get; }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<RootNamespace>Saxonite.Net.Core.Web</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
@@ -15,7 +15,16 @@ namespace Saxonite.Net.Core.Web.Admin.App
|
||||
//-------------------------------------------------------------------
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
CreateHostBuilder(args).Build().Run();
|
||||
try
|
||||
{
|
||||
CreateHostBuilder(args).Build().Run();
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Cleanup - globals, async processes etc.
|
||||
if (SaxApplication_Admin.AppInstance != null)
|
||||
SaxApplication_Admin.AppInstance.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
@@ -49,30 +49,45 @@ namespace Saxonite.Net.Core.Web.Admin.App
|
||||
try
|
||||
{
|
||||
AppInstance = this;
|
||||
SaxGlobals.App = this;
|
||||
SaxGlobals.System = (System_Web = new SaxSystem_Web());
|
||||
Configuration = configuration;
|
||||
ConsoleHelper_Web = new SaxConsoleHelper_WebAdmin(this);
|
||||
ConsoleHelper_Admin = new SaxConsoleHelper_Admin(this);
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
SaLogger.Error(GetType().Name + ".CTR " + ExceptionUtil.GetErrorStateMessage(exc));
|
||||
throw exc;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
// Clear globals.
|
||||
AppInstance = null;
|
||||
// Console helper.
|
||||
if (ConsoleHelper_Admin != null)
|
||||
ConsoleHelper_Admin.Dispose();
|
||||
ConsoleHelper_Admin = null;
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
public static SaxApplication_Admin AppInstance { get; private set; }
|
||||
public List<String> Messages { get; } = new List<String>();
|
||||
public override SaxConsoleHelper ConsoleHelper { get { return ConsoleHelper_Admin; } }
|
||||
public SaxConsoleHelper_Admin ConsoleHelper_Admin { get; private set; }
|
||||
// Database.
|
||||
public override ISacsDatabase GetDatabase(SaxSessionContext sessionContext, Sax.Database databaseType)
|
||||
{
|
||||
return sessionContexts.GetValue(sessionContext.Index, null)?.Databases.GetValue(databaseType, null);
|
||||
}
|
||||
public override String SessionCookieName { get { return Sax.Config.Admin.Session.Cookie.Name; } }
|
||||
// Configuration.
|
||||
public override SaxAppConfig AppConfig { get { return appConfigs.Values.ToList().getConfigForApplication(); } }
|
||||
public override SaxEmailConfig EmailConfig { get { return emailConfigs.Values.ToList().getConfigForSession(AppConfig); } }
|
||||
public override String SessionCookieName { get { return Sax.Config.Admin.Session.Cookie.Name; } }
|
||||
// Startup messages - for debugging. See Admin.Views._Layout.
|
||||
public List<String> Messages { get; } = new List<String>();
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Initialisation.
|
||||
|
||||
@@ -4,6 +4,7 @@ using Microsoft.AspNetCore.HttpsPolicy;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Saxonite.Net.Core.Web.Admin.Consoles;
|
||||
using Saxonite.Net.Core.Web.Base.App;
|
||||
using Saxonite.Net.Standard.Base.App;
|
||||
using System;
|
||||
|
||||
+29
-2
@@ -10,7 +10,7 @@ using System.Threading.Tasks;
|
||||
namespace Saxonite.Net.Core.Web.Admin.Consoles
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaxConsoleHelper_WebAdmin : SaxConsoleHelper_Web
|
||||
public class SaxConsoleHelper_Admin : SaxConsoleHelper_Web
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Data members:
|
||||
@@ -18,10 +18,23 @@ namespace Saxonite.Net.Core.Web.Admin.Consoles
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public SaxConsoleHelper_WebAdmin(SaxApplication_Admin app)
|
||||
public SaxConsoleHelper_Admin(SaxApplication_Admin app)
|
||||
{
|
||||
this.app = app;
|
||||
}
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
// Clear process consoles.
|
||||
foreach (SaxProcessConsole_Admin processConsole in processConsoles.Values)
|
||||
{
|
||||
processConsole.Dispose();
|
||||
}
|
||||
processConsoles.Clear();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Data cache console.
|
||||
@@ -40,6 +53,20 @@ namespace Saxonite.Net.Core.Web.Admin.Consoles
|
||||
return null;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Process console.
|
||||
private Dictionary<ushort, SaxProcessConsole_Admin> processConsoles { get; } = new Dictionary<ushort, SaxProcessConsole_Admin>();
|
||||
public SaxProcessConsole GetProcessConsole(SaxSessionContext sessionContext)
|
||||
{
|
||||
if (sessionContext == null) throw new NotSupportedException(GetType().Name + ".GetProcessConsole Session Context must be specified");
|
||||
SaxProcessConsole_Admin processConsole = processConsoles.GetValueOrDefault(sessionContext.Index, null);
|
||||
if (processConsole == null)
|
||||
{
|
||||
processConsole = processConsoles[sessionContext.Index] = new SaxProcessConsole_Admin(sessionContext);
|
||||
}
|
||||
return processConsole;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Activity console.
|
||||
public override SaxActivityConsole CreateActivityConsole(SaxSessionContext sessionContext)
|
||||
@@ -0,0 +1,120 @@
|
||||
using MimeKit;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Procs;
|
||||
using Saxonite.Net.Core.Web.Admin.Procs;
|
||||
using Saxonite.Net.Standard.Base.App;
|
||||
using Saxonite.Net.Standard.Base.Consoles;
|
||||
using Saxonite.Net.Standard.Base.Procs;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Saxonite.Net.Core.Web.Admin.Consoles
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaxProcessConsole_Admin : SaxProcessConsole
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Definitions.
|
||||
public enum ProcessType
|
||||
{
|
||||
OrganisationUpload
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Process cache - to sustain processes outside of request/response timescales.
|
||||
internal class ProcessData
|
||||
{
|
||||
public ProcessData(SaxProcess_Admin process)
|
||||
{
|
||||
this.Process = process;
|
||||
|
||||
}
|
||||
public SaxProcess_Admin Process { get; }
|
||||
}
|
||||
// Cache.
|
||||
private Dictionary<ProcessType, ProcessData> processes { get; } = new Dictionary<ProcessType, ProcessData>();
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
private SaxInternals internals = null;
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public SaxProcessConsole_Admin(SaxSessionContext sessionContext) : base(sessionContext)
|
||||
{
|
||||
}
|
||||
protected async override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
// Clear processes.
|
||||
foreach (ProcessData processData in processes.Values)
|
||||
{
|
||||
await processData.Process.StopProcessAsync();
|
||||
processData.Process.Dispose();
|
||||
}
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Processes.
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
public SaxProcess_Admin GetProcess(ProcessType processType)
|
||||
{
|
||||
return processes.GetValueOrDefault(processType, null)?.Process;
|
||||
}
|
||||
|
||||
public bool IsProcessing(ProcessType processType)
|
||||
{
|
||||
SaxProcess_Admin process = GetProcess(processType);
|
||||
if (process != null)
|
||||
if (process.Processing) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove the process from the cache.
|
||||
/// </summary>
|
||||
/// <param name="processType"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="InProgressException"></exception>
|
||||
public bool ClearProcess(ProcessType processType)
|
||||
{
|
||||
SaxProcess_Admin process = GetProcess(processType);
|
||||
if (process != null)
|
||||
{
|
||||
if (process.Processing)
|
||||
throw new SaProcess_Base.InProgressException();
|
||||
process.Dispose();
|
||||
}
|
||||
return processes.Remove(processType);
|
||||
}
|
||||
|
||||
public void SetProcess(ProcessType processType, SaxProcess_Admin process)
|
||||
{
|
||||
ClearProcess(processType);
|
||||
processes.Add(processType, new ProcessData(process));
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Specific processes.
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Organisation Upload.
|
||||
public SaxOrganisationUploader GetSaxOrganisationUploader()
|
||||
{
|
||||
return GetProcess(ProcessType.OrganisationUpload) as SaxOrganisationUploader;
|
||||
}
|
||||
public void SetProcess(SaxOrganisationUploader process)
|
||||
{
|
||||
SetProcess(ProcessType.OrganisationUpload, process);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -26,6 +26,7 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
{
|
||||
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; }
|
||||
@@ -35,6 +36,7 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
{
|
||||
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();
|
||||
@@ -98,10 +100,12 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -36,30 +36,8 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
{
|
||||
String fn = GetType().Name + ".Index";
|
||||
|
||||
// Check for 'Keep Logged In' cookie.
|
||||
// NB Only allowed if there isn't a current user session.
|
||||
if (!ValidUserSession && AppConfig.Security.SignIn.KeepLoggedIn.Allowed)
|
||||
{
|
||||
String encryptedParams = GetRequestCookie(KeepLoggedIn.CookieName);
|
||||
KeepLoggedInParams keepLoggedInParams = ExtractKeepLoggedInParams(encryptedParams);
|
||||
String logSuffix = keepLoggedInParams.GetValidParams().Concat("", " ", ".");
|
||||
if (SysId.IsValid(keepLoggedInParams.UserAccountId))
|
||||
{
|
||||
SaxUserAccount userAccount = AccountMgr.GetUserAccountById(keepLoggedInParams.UserAccountId);
|
||||
if (userAccount != null)
|
||||
{
|
||||
if (userAccount.IsStatusActive)
|
||||
{
|
||||
String errorMessage = "";
|
||||
if (SignUserIn(userAccount, AccountMgr.GetRolesForUser(userAccount.Id), true, ref errorMessage))
|
||||
SaLogger.Info(fn + " Keep Logged In cookie found." + logSuffix);
|
||||
else SaLogger.Warn(fn + " Keep Logged In cookie found but failed to sign user in: " + errorMessage + "." + logSuffix);
|
||||
}
|
||||
else SaLogger.Warn(fn + " Keep Logged In cookie found but UserAccount is not active." + logSuffix);
|
||||
}
|
||||
else SaLogger.Warn(fn + " Keep Logged In cookie found but UserAccount not found." + logSuffix);
|
||||
}
|
||||
}
|
||||
if (!ValidUserSession)
|
||||
AutoLoginUser();
|
||||
|
||||
// Redirect to sign-in if not signed-in.
|
||||
if (!ValidUserSession)
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Email;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using Saxonite.Net.Core.Web.Admin.Consoles;
|
||||
using Saxonite.Net.Core.Web.Admin.Models;
|
||||
using Saxonite.Net.Core.Web.Admin.Procs;
|
||||
using Saxonite.Net.Standard.Base.App;
|
||||
using Saxonite.Net.Standard.Base.Bus;
|
||||
using Saxonite.Net.Standard.Base.Helpers;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
{
|
||||
//=======================================================================
|
||||
// Controller: Organisation - Ajax - Upload
|
||||
//=======================================================================
|
||||
partial class OrganisationController
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Definitions.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Organisation Uploader process info.
|
||||
//-------------------------------------------------------------------
|
||||
private class AjaxResponse_OrganisationUploadInfo : AjaxResponse_Data
|
||||
{
|
||||
// Construction.
|
||||
public AjaxResponse_OrganisationUploadInfo(SaxModel_Admin model) : base(model) { }
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
[HttpPost]
|
||||
[Route("Organisation/Ajax/UploadInfo")]
|
||||
public IActionResult Ajax_OrganisationUploadInfo(SaxModel_Admin model)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_OrganisationUploadInfo";
|
||||
String messageTitle = Localiser["caption.upload.organisations"];
|
||||
AjaxResponse_OrganisationUploadInfo responseData = new AjaxResponse_OrganisationUploadInfo(model);
|
||||
|
||||
// Validate session.
|
||||
if (!ValidUserSession)
|
||||
return GetAjaxResult_InvalidSession(responseData);
|
||||
|
||||
// Record disposable items as they are created so all can be disposed when needed.
|
||||
using (DisposableCollection<SacsHierarchyItem> disposableItems = new DisposableCollection<SacsHierarchyItem>())
|
||||
{
|
||||
|
||||
// Process console.
|
||||
SaxProcessConsole_Admin processConsole = GetProcessConsole_Admin(SessionContext);
|
||||
if (processConsole == null)
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"]));
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
// Check whether upload is in progress.
|
||||
if (processConsole.IsProcessing(SaxProcessConsole_Admin.ProcessType.OrganisationUpload))
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.process.in.progress"]));
|
||||
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
SaLogger.Warn(fn + " " + exc.GetType().Name + " initialising organisation uploader.");
|
||||
return Json(responseData.SetMessage(messageTitle, exc.GetType().Name + " initialising organisation uploader."));
|
||||
}
|
||||
}
|
||||
|
||||
// Complete response.
|
||||
responseData.Success = true;
|
||||
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Upload Organisations.
|
||||
//-------------------------------------------------------------------
|
||||
private class AjaxResponse_OrganisationUpload : AjaxResponse_Data
|
||||
{
|
||||
// Construction.
|
||||
public AjaxResponse_OrganisationUpload(SaxModel_Admin model) : base(model) { }
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
[HttpPost]
|
||||
[Route("Organisation/Ajax/Upload")]
|
||||
public IActionResult Ajax_UploadOrganisations(Model_OrganisationUpload model)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_UploadOrganisations";
|
||||
String messageTitle = Localiser["caption.upload.organisations"];
|
||||
AjaxResponse_OrganisationUpload responseData = new AjaxResponse_OrganisationUpload(model);
|
||||
|
||||
// Validate session.
|
||||
if (!ValidUserSession)
|
||||
return GetAjaxResult_InvalidSession(responseData);
|
||||
|
||||
// Record disposable items as they are created so all can be disposed when needed.
|
||||
using (DisposableCollection<SacsHierarchyItem> disposableItems = new DisposableCollection<SacsHierarchyItem>())
|
||||
{
|
||||
|
||||
// Validate supplied data properties.
|
||||
if (!model.ValidateProperties(responseData))
|
||||
return Json(responseData);
|
||||
|
||||
// Process console.
|
||||
SaxProcessConsole_Admin processConsole = GetProcessConsole_Admin(SessionContext);
|
||||
if (processConsole == null)
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"]));
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
// Check whether upload is in progress.
|
||||
if (processConsole.IsProcessing(SaxProcessConsole_Admin.ProcessType.OrganisationUpload))
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.process.in.progress"]));
|
||||
|
||||
// Create the upload process.
|
||||
SaxOrganisationUploader.Config processConfig = new SaxOrganisationUploader.Config(SessionContext, model.OrganisationDataFile[0]);
|
||||
processConfig.SheetNameOrNumber = model.SheetNameOrNumber;
|
||||
SaxOrganisationUploader process = new SaxOrganisationUploader(processConfig);
|
||||
|
||||
// Store the process and run.
|
||||
processConsole.SetProcess(process);
|
||||
process.RunAsync();
|
||||
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
SaLogger.Warn(fn + " " + exc.GetType().Name + " initialising organisation uploader.");
|
||||
return Json(responseData.SetMessage(messageTitle, exc.GetType().Name + " initialising organisation uploader."));
|
||||
}
|
||||
}
|
||||
|
||||
// Complete response.
|
||||
responseData.Success = true;
|
||||
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
@@ -5,8 +5,10 @@ using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Dbas;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using Saxonite.Net.Core.Web.Admin.Models;
|
||||
using Saxonite.Net.Core.Web.Admin.Procs;
|
||||
using Saxonite.Net.Standard.Base.App;
|
||||
using Saxonite.Net.Standard.Base.Bus;
|
||||
using Saxonite.Net.Standard.Base.Mgr;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
@@ -126,6 +128,7 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
public List<AjaxResponse_Data.ItemCodeDesc> ContactMethods { get; } = new List<ItemCodeDesc>();
|
||||
public List<CodeDesc> Statuses { get; } = new List<CodeDesc>();
|
||||
public String DefaultStatusCode { get; set; }
|
||||
public List<String> UploadContentTypes { get; set; }
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
[HttpPost]
|
||||
@@ -154,6 +157,9 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
responseData.Statuses.Add(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status));
|
||||
responseData.DefaultStatusCode = SacsSystem.GetStatusCode(SaxOrganisation.DefaultStatus);
|
||||
|
||||
// Reference data - Image content types.
|
||||
responseData.UploadContentTypes = SaxOrganisationUploader.ValidContentTypes;
|
||||
|
||||
// Store filter values.
|
||||
SysId filterSportId = model.Filter.OrganisationSportId.ToSysId();
|
||||
SessionData_Admin.Filter.SportId = SysId.IsValid(filterSportId) ? filterSportId : null;
|
||||
@@ -161,14 +167,7 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
SessionData_Admin.Filter.RegionId = SysId.IsValid(filterRegionId) ? filterRegionId : null;
|
||||
|
||||
// Item filter.
|
||||
SaxOrganisation.Params prmOrganisation = new SaxOrganisation.Params();
|
||||
prmOrganisation.OrganisationFilter = model.Filter.Organisation;
|
||||
prmOrganisation.OrganisationType = model.FilterOrganisationType;
|
||||
prmOrganisation.OrganisationCategory = model.FilterOrganisationCategory;
|
||||
prmOrganisation.SportIdsIncluded.AddId(filterSportId);
|
||||
prmOrganisation.RegionIdsIncluded.AddId(filterRegionId);
|
||||
prmOrganisation.StatusCat = model.Filter.OrganisationStatusCategoryCode != null ? model.FilterOrganisationStatusCategory : SaxOrganisation.StatusCat.NotDeleted;
|
||||
prmOrganisation.SortColumns.Add(AccountMgr.GetOrganisationColumnDfn(SaxOrganisation.Column.Name));
|
||||
SaxOrganisation.Params prmOrganisation = GetOrganisationListFilter(model, AccountMgr);
|
||||
model.Paging.ItemTotal = (ulong)AccountMgr.GetOrganisationCount(prmOrganisation);
|
||||
model.PopulatePagingTo(prmOrganisation.ResultsPaging);
|
||||
|
||||
@@ -237,6 +236,27 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Construct Organisation filter params.
|
||||
/// <para>- Shared with Organisation Exporter process.</para>
|
||||
/// </summary>
|
||||
/// <param name="model"></param>
|
||||
/// <returns></returns>
|
||||
public static SaxOrganisation.Params GetOrganisationListFilter(Model_Organisation model, SaxAccountMgr accountMgr)
|
||||
{
|
||||
// Item filter.
|
||||
SaxOrganisation.Params prmOrganisation = new SaxOrganisation.Params();
|
||||
prmOrganisation.OrganisationFilter = model.Filter.Organisation;
|
||||
prmOrganisation.OrganisationType = model.FilterOrganisationType;
|
||||
prmOrganisation.OrganisationCategory = model.FilterOrganisationCategory;
|
||||
prmOrganisation.SportIdsIncluded.AddId(model.Filter.OrganisationSportId.ToSysId());
|
||||
prmOrganisation.RegionIdsIncluded.AddId(model.Filter.OrganisationRegionId.ToSysId());
|
||||
prmOrganisation.StatusCat = model.Filter.OrganisationStatusCategoryCode != null ? model.FilterOrganisationStatusCategory : SaxOrganisation.StatusCat.NotDeleted;
|
||||
prmOrganisation.SortColumns.Add(accountMgr.GetOrganisationColumnDfn(SaxOrganisation.Column.Name));
|
||||
return prmOrganisation;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Get Organisation ajax request.
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Email;
|
||||
using Sarand.Net.Standard.Base.Helpers;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using Sarand.Net.Standard.Proc.Excel;
|
||||
using Saxonite.Net.Core.Web.Admin.Consoles;
|
||||
using Saxonite.Net.Core.Web.Admin.Models;
|
||||
using Saxonite.Net.Core.Web.Admin.Procs;
|
||||
using Saxonite.Net.Core.Web.Base.Controllers;
|
||||
using Saxonite.Net.Standard.Base.App;
|
||||
using Saxonite.Net.Standard.Base.Bus;
|
||||
using Saxonite.Net.Standard.Base.Helpers;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
{
|
||||
//=======================================================================
|
||||
// Controller: Organisation - Download
|
||||
//=======================================================================
|
||||
partial class OrganisationController
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Definitions.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Download Organisations.
|
||||
//-------------------------------------------------------------------
|
||||
[HttpPost]
|
||||
[Route("Organisation/Download")]
|
||||
public IActionResult Ajax_DownloadOrganisations(Model_OrganisationDownload model)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_DownloadOrganisations";
|
||||
|
||||
// Validate session.
|
||||
if (!ValidUserSession)
|
||||
return Unauthorized();
|
||||
|
||||
// Record disposable items as they are created so all can be disposed when needed.
|
||||
using (DisposableCollection<SacsHierarchyItem> disposableItems = new DisposableCollection<SacsHierarchyItem>())
|
||||
{
|
||||
|
||||
// Validate supplied data properties.
|
||||
if (!model.ValidateProperties())
|
||||
return BadRequest();
|
||||
|
||||
// Export data.
|
||||
SaxOrganisationExporter.Config exporterConfig = new SaxOrganisationExporter.Config(SessionContext, GetOrganisationListFilter(model, AccountMgr));
|
||||
exporterConfig.Format = SaxOrganisationExporter.ExportFormat.Excel_Open;
|
||||
exporterConfig.IncludeId = StringUtil.ToBool(model.IncludeId);
|
||||
SaxOrganisationExporter exporter = new SaxOrganisationExporter(exporterConfig);
|
||||
if (exporter.RunProcess())
|
||||
{
|
||||
// Organisations exported successfully.
|
||||
byte[] data = exporter.GetDocumentData();
|
||||
using (MemoryStream content = new MemoryStream(data))
|
||||
{
|
||||
String contentType = exporter.GetContentType();
|
||||
var fileName = "Sportierre-Organisations-" + DateTime.Now.ToString("yyyyMMdd") + ".xlsx";
|
||||
return File(content.ToArray(), contentType, fileName);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Problems occurred.
|
||||
}
|
||||
}
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,8 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
public IActionResult Index(String sta)
|
||||
{
|
||||
// Validate session.
|
||||
if (!ValidUserSession)
|
||||
AutoLoginUser();
|
||||
if (!ValidUserSession)
|
||||
return RedirectToAction("", "");
|
||||
|
||||
@@ -64,6 +66,8 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
public IActionResult Members(Model_OrganisationMembers model)
|
||||
{
|
||||
// Validate session.
|
||||
if (!ValidUserSession)
|
||||
AutoLoginUser();
|
||||
if (!ValidUserSession)
|
||||
return RedirectToAction("", "");
|
||||
|
||||
@@ -90,6 +94,8 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
public IActionResult Associations(Model_OrganisationAssociations model)
|
||||
{
|
||||
// Validate session.
|
||||
if (!ValidUserSession)
|
||||
AutoLoginUser();
|
||||
if (!ValidUserSession)
|
||||
return RedirectToAction("", "");
|
||||
|
||||
|
||||
@@ -26,6 +26,8 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
public IActionResult Index()
|
||||
{
|
||||
// Validate session.
|
||||
if (!ValidUserSession)
|
||||
AutoLoginUser();
|
||||
if (!ValidUserSession)
|
||||
return RedirectToAction("", "");
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Helpers;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using Saxonite.Net.Core.Web.Admin.App;
|
||||
using Saxonite.Net.Core.Web.Admin.Consoles;
|
||||
using Saxonite.Net.Core.Web.Base.App;
|
||||
using Saxonite.Net.Core.Web.Base.Controllers;
|
||||
using Saxonite.Net.Standard.Base.App;
|
||||
@@ -41,6 +42,15 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
return JsonConvert.DeserializeObject<SaxSessionData_Admin>(sessionDataJson, SaxSessionDataJsonSerializerSettings);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Globals.
|
||||
//-------------------------------------------------------------------
|
||||
protected SaxConsoleHelper_Admin ConsoleHelper_Admin { get { return ConsoleHelper as SaxConsoleHelper_Admin; } }
|
||||
protected SaxProcessConsole_Admin GetProcessConsole_Admin(SaxSessionContext sessionContext)
|
||||
{
|
||||
return ConsoleHelper_Admin?.GetProcessConsole(sessionContext) as SaxProcessConsole_Admin;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// User Session.
|
||||
//-------------------------------------------------------------------
|
||||
@@ -50,54 +60,60 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
/// <para>- Open user session - store details against Sesion Data.</para>
|
||||
/// <para>- Set 'Keep logged in' cookie if required.</para>
|
||||
/// </summary>
|
||||
protected bool SignUserIn(SaxUserAccount userAccount, List<SaxUserRole> userRoles, bool keepLoggedIn, ref String errorMessage)
|
||||
protected bool SignUserIn(SaxUserAccount userAccount, bool keepLoggedIn, ref String errorMessage)
|
||||
{
|
||||
String fn = GetType().Name + ".SignUserIn";
|
||||
|
||||
// Validate User Account, just in case - should have been done before arriving here!
|
||||
if (userAccount == null)
|
||||
// Record disposable items as they are created so all can be disposed when needed.
|
||||
using (DisposableCollection<SacsHierarchyItem> disposableItems = new DisposableCollection<SacsHierarchyItem>())
|
||||
{
|
||||
SaLogger.Error(fn + " Unable to sign account in - null user account.");
|
||||
errorMessage = Localiser["security.msg.signin.invalid"];
|
||||
return false;
|
||||
List<SaxUserRole> userRoles = AccountMgr.GetRolesForUser(userAccount.Id);
|
||||
disposableItems.AddRange(userRoles);
|
||||
|
||||
// Validate User Account, just in case - should have been done before arriving here!
|
||||
if (userAccount == null)
|
||||
{
|
||||
SaLogger.Error(fn + " Unable to sign account in - null user account.");
|
||||
errorMessage = Localiser["security.msg.signin.invalid"];
|
||||
return false;
|
||||
}
|
||||
if (!userAccount.IsStatusActive)
|
||||
{
|
||||
SaLogger.Error(fn + " Unable to sign account in - user account is not active. Email: " + userAccount.EmailAddress);
|
||||
errorMessage = Localiser["security.msg.signin.invalid"];
|
||||
return false;
|
||||
}
|
||||
|
||||
// 'Keep logged in' can be switched off by the application configuration.
|
||||
keepLoggedIn = App.AppConfig.Security.SignIn.KeepLoggedIn.Allowed && keepLoggedIn;
|
||||
|
||||
// Log user in - Admin details stored against System Admin role.
|
||||
SaxUserRole userRole = userRoles.Find(item => item.UserRole == Sax.UserRole.SystemAdmin);
|
||||
if (userRole == null)
|
||||
{
|
||||
SaLogger.Warn(fn + " System Admin role not found for " + userAccount.EmailAddress);
|
||||
errorMessage = Localiser["security.msg.signin.invalid"];
|
||||
return false;
|
||||
}
|
||||
userRole.KeepLoggedIn = keepLoggedIn;
|
||||
userRole.LastLoginAt = DateTime.Now;
|
||||
userRole.InvalidLoginCount = 0;
|
||||
userRole.LastInvalidLoginAt = DateTime.MinValue;
|
||||
if (!AccountMgr.UpdateUserRole(userRole, DbUpdateInfo))
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to update Admin user role for " + userAccount.EmailAddress + ": " + AccountMgr.ErrorStateMessage);
|
||||
errorMessage = Localiser["security.msg.signin.invalid"];
|
||||
return false;
|
||||
}
|
||||
SaLogger.Info(fn + " User session opened for " + userAccount.EmailAddress, true);
|
||||
|
||||
// Create session.
|
||||
OpenUserSession(SessionContext, userAccount, userRoles);
|
||||
|
||||
// Send the 'Keep Logged In' cookie if requested.
|
||||
if (userRole.KeepLoggedIn)
|
||||
SetKeepLoggedInCookie();
|
||||
}
|
||||
if (!userAccount.IsStatusActive)
|
||||
{
|
||||
SaLogger.Error(fn + " Unable to sign account in - user account is not active. Email: " + userAccount.EmailAddress);
|
||||
errorMessage = Localiser["security.msg.signin.invalid"];
|
||||
return false;
|
||||
}
|
||||
|
||||
// 'Keep logged in' can be switched off by the application configuration.
|
||||
keepLoggedIn = App.AppConfig.Security.SignIn.KeepLoggedIn.Allowed && keepLoggedIn;
|
||||
|
||||
// Log user in - Admin details stored against System Admin role.
|
||||
SaxUserRole userRole = userRoles.Find(item => item.UserRole == Sax.UserRole.SystemAdmin);
|
||||
if (userRole == null)
|
||||
{
|
||||
SaLogger.Warn(fn + " System Admin role not found for " + userAccount.EmailAddress);
|
||||
errorMessage = Localiser["security.msg.signin.invalid"];
|
||||
return false;
|
||||
}
|
||||
userRole.KeepLoggedIn = keepLoggedIn;
|
||||
userRole.LastLoginAt = DateTime.Now;
|
||||
userRole.InvalidLoginCount = 0;
|
||||
userRole.LastInvalidLoginAt = DateTime.MinValue;
|
||||
if (!AccountMgr.UpdateUserRole(userRole, DbUpdateInfo))
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to update Admin user role for " + userAccount.EmailAddress + ": " + AccountMgr.ErrorStateMessage);
|
||||
errorMessage = Localiser["security.msg.signin.invalid"];
|
||||
return false;
|
||||
}
|
||||
SaLogger.Info(fn + " User session opened for " + userAccount.EmailAddress, true);
|
||||
|
||||
// Create session.
|
||||
OpenUserSession(SessionContext, userAccount, userRoles);
|
||||
|
||||
// Send the 'Keep Logged In' cookie if requested.
|
||||
if (userRole.KeepLoggedIn)
|
||||
SetKeepLoggedInCookie();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -121,22 +137,50 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// IMage utilities.
|
||||
// Keep Logged In.
|
||||
//-------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Construct URL to display Organisation logo.
|
||||
/// <para>- Option to allow for 'Upload' image if active.</para>
|
||||
/// Check for 'Keep Logged In' cookie and auto-login user if details are valid.
|
||||
/// </summary>
|
||||
protected String GetOrganisationLogoLink(SysId organisationId, bool uploadImage)
|
||||
/// <returns></returns>
|
||||
protected bool AutoLoginUser()
|
||||
{
|
||||
String imageLink = "Image/Organisation/Logo" + (uploadImage ? "/Upload" : "") + "?";
|
||||
NameValueCollection parameters = new NameValueCollection();
|
||||
parameters.Add(ImageController.ParamName_OrganisationId, SysId.ToString(organisationId));
|
||||
return imageLink + ImageController.ParamName_OrganisationLogoEncrypted + "=" + EncryptSessionParams(parameters);
|
||||
String fn = "AutoLoginUser";
|
||||
|
||||
// NB Only allowed if there isn't a current user session.
|
||||
if (ValidUserSession) return true;
|
||||
if (!AppConfig.Security.SignIn.KeepLoggedIn.Allowed) return false;
|
||||
|
||||
// Extract cookie details.
|
||||
String encryptedParams = GetRequestCookie(KeepLoggedIn.CookieName);
|
||||
KeepLoggedInParams keepLoggedInParams = ExtractKeepLoggedInParams(encryptedParams);
|
||||
String logSuffix = keepLoggedInParams.GetValidParams().Concat("", " ", ".");
|
||||
if (SysId.IsValid(keepLoggedInParams.UserAccountId))
|
||||
{
|
||||
using (SaxUserAccount userAccount = AccountMgr.GetUserAccountById(keepLoggedInParams.UserAccountId))
|
||||
{
|
||||
if (userAccount != null)
|
||||
{
|
||||
if (userAccount.IsStatusActive)
|
||||
{
|
||||
String errorMessage = "";
|
||||
if (SignUserIn(userAccount, true, ref errorMessage))
|
||||
{
|
||||
// Successful login.
|
||||
SaLogger.Info(fn + " Keep Logged In cookie found." + logSuffix);
|
||||
return true;
|
||||
}
|
||||
else SaLogger.Warn(fn + " Keep Logged In cookie found but failed to sign user in: " + errorMessage + "." + logSuffix);
|
||||
}
|
||||
else SaLogger.Warn(fn + " Keep Logged In cookie found but UserAccount is not active." + logSuffix);
|
||||
}
|
||||
else SaLogger.Warn(fn + " Keep Logged In cookie found but UserAccount not found." + logSuffix);
|
||||
}
|
||||
}
|
||||
ClearKeepLoggedInCookie();
|
||||
return false;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Keep Logged In.
|
||||
//-------------------------------------------------------------------
|
||||
/// <summary>Keep-Logged-In cookie.</summary>
|
||||
protected void SetKeepLoggedInCookie()
|
||||
@@ -164,8 +208,8 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
// - IV Must be regenerated if key is changed: uncomment 'Generated' variable and copy resulting value to IV variable.
|
||||
public static class KeepLoggedIn
|
||||
{
|
||||
public static String CookieName = "SXKLI";
|
||||
public static String Base64Key = SacsEncryptionHelper.EncodePlainKey("<=Saxonite^{kEEp+1Ogg3d-IN}~32*>", SacsEncryptionHelper.KeyLength);
|
||||
public static String CookieName = "SXKLI";
|
||||
public static String Base64Key = SacsEncryptionHelper.EncodePlainKey("<=Saxonite^{kEEp+1Ogg3d-IN}~32*>", SacsEncryptionHelper.KeyLength);
|
||||
public static String Base64IV = "YOX10FIPp1zM1pg5U6fW7A==";
|
||||
private static String Base64IV_Generated = SacsEncryptionHelper.InitSymmetricEncryptionIV(KeepLoggedIn.Base64Key);
|
||||
}
|
||||
@@ -205,12 +249,27 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
return keepLoggedInParams;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Image utilities.
|
||||
//-------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Construct URL to display Organisation logo.
|
||||
/// <para>- Option to allow for 'Upload' image if active.</para>
|
||||
/// </summary>
|
||||
protected String GetOrganisationLogoLink(SysId organisationId, bool uploadImage)
|
||||
{
|
||||
String imageLink = "Image/Organisation/Logo" + (uploadImage ? "/Upload" : "") + "?";
|
||||
NameValueCollection parameters = new NameValueCollection();
|
||||
parameters.Add(ImageController.ParamName_OrganisationId, SysId.ToString(organisationId));
|
||||
return imageLink + ImageController.ParamName_OrganisationLogoEncrypted + "=" + EncryptSessionParams(parameters);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Parameter encryption, eg. for images.
|
||||
//-------------------------------------------------------------------
|
||||
// Encryption key is the same for all users each time the application is started,
|
||||
// but a different IV value is generated for each session so that the links/parameters cannot be shared.
|
||||
public static String Base64Key_AdminApp { get; } = SacsEncryptionHelper.EncodePlainKey("Saxonite&Admin#Encryption-"+DateTime.Today.Format("ddMMyy"), SacsEncryptionHelper.KeyLength);
|
||||
public static String Base64Key_AdminApp { get; } = SacsEncryptionHelper.EncodePlainKey("Saxonite&Admin#Encryption-" + DateTime.Today.Format("ddMMyy"), SacsEncryptionHelper.KeyLength);
|
||||
protected String EncryptSessionParams(NameValueCollection parameters)
|
||||
{
|
||||
return HttpUtility.UrlEncode(EncryptParameters(parameters, SessionData_Admin.Base64IV_AdminApp, Base64Key_AdminApp));
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
return Json(responseData);
|
||||
|
||||
String errorMessage = "";
|
||||
if (!SignUserIn(userAccount, AccountMgr.GetRolesForUser(userAccount.Id), model.KeepMeSignedIn, ref errorMessage))
|
||||
if (!SignUserIn(userAccount, model.KeepMeSignedIn, ref errorMessage))
|
||||
{
|
||||
return Json(responseData.SetControlError(nameof(model.EmailAddress), errorMessage));
|
||||
}
|
||||
|
||||
@@ -26,6 +26,8 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
public IActionResult Index()
|
||||
{
|
||||
// Validate session.
|
||||
if (!ValidUserSession)
|
||||
AutoLoginUser();
|
||||
if (!ValidUserSession)
|
||||
return RedirectToAction("", "");
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
//=======================================================================
|
||||
// System - Ajax - Database controller
|
||||
//=======================================================================
|
||||
partial class SystemController : SaDbProcess_CompareDatabaseSchemas.IProcessNotifier
|
||||
partial class SystemController
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Database data.
|
||||
@@ -169,14 +169,14 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
SaDbProcess_ConvertDbSchema.Config cfgSchemaConvert = new SaDbProcess_ConvertDbSchema.Config();
|
||||
SaDbProcess_ConvertDbSchema procSchemaConvert = new SaDbProcess_ConvertDbSchema(cfgSchemaConvert);
|
||||
List<DbDfnTable> tables = procSchemaConvert.ConvertXmlToTables(xmlSchema);
|
||||
if (procSchemaConvert.HasProcessError())
|
||||
return Json(responseData.SetMessage(messageTitle, "Failed to convert XML schema: " + procSchemaConvert.GetProcessError()));
|
||||
if (procSchemaConvert.HasErrorMessage())
|
||||
return Json(responseData.SetMessage(messageTitle, "Failed to convert XML schema: " + procSchemaConvert.GetErrorMessage()));
|
||||
|
||||
SaDbProcess_CompareDatabaseSchemas.Config cfgSchemaCompare = new SaDbProcess_CompareDatabaseSchemas.Config(tables, db);
|
||||
cfgSchemaCompare.HideIdenticalObjects = true;
|
||||
cfgSchemaCompare.IgnorePosition = true;
|
||||
SaDbProcess_CompareDatabaseSchemas procSchemaCompare = new SaDbProcess_CompareDatabaseSchemas(cfgSchemaCompare);
|
||||
procSchemaCompare.ProcessNotifier = this;
|
||||
procSchemaCompare.OnSchemaComparisonItemAdded += OnSchemaComparisonItemAdded;
|
||||
procSchemaCompare.RunProcess();
|
||||
|
||||
List<SaDbProcess_CompareDatabaseSchemas.SchemaComparisonItem> schemaComparisonItems = procSchemaCompare.GetSchemaComparisonItems();
|
||||
@@ -200,17 +200,10 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
public void OnStartProcess()
|
||||
{
|
||||
}
|
||||
public void SetProgressInfo(List<string> progressInfo)
|
||||
{
|
||||
}
|
||||
public void OnEndProcess()
|
||||
{
|
||||
}
|
||||
public void OnSchemaComparisonItemAdded(SaDbProcess_CompareDatabaseSchemas proc)
|
||||
// Processing events.
|
||||
public void OnSchemaComparisonItemAdded(object sender, SaDbProcess_CompareDatabaseSchemas.SchemaComparisonItemAddedEventArgs e)
|
||||
{
|
||||
SaDbProcess_CompareDatabaseSchemas proc = sender as SaDbProcess_CompareDatabaseSchemas;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
@@ -45,6 +45,8 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
public IActionResult Database(Model_System model)
|
||||
{
|
||||
// Validate session.
|
||||
if (!ValidUserSession)
|
||||
AutoLoginUser();
|
||||
if (!ValidUserSession)
|
||||
return RedirectToAction("", "");
|
||||
|
||||
@@ -60,6 +62,8 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
public IActionResult Logs(Model_System model)
|
||||
{
|
||||
// Validate session.
|
||||
if (!ValidUserSession)
|
||||
AutoLoginUser();
|
||||
if (!ValidUserSession)
|
||||
return RedirectToAction("", "");
|
||||
|
||||
|
||||
@@ -28,6 +28,8 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
public IActionResult Index(String sta)
|
||||
{
|
||||
// Validate session.
|
||||
if (!ValidUserSession)
|
||||
AutoLoginUser();
|
||||
if (!ValidUserSession)
|
||||
return RedirectToAction("", "");
|
||||
|
||||
|
||||
@@ -28,6 +28,8 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
public IActionResult Index(String sta)
|
||||
{
|
||||
// Validate session.
|
||||
if (!ValidUserSession)
|
||||
AutoLoginUser();
|
||||
if (!ValidUserSession)
|
||||
return RedirectToAction("", "");
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sacs.Web.Components;
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Helpers;
|
||||
@@ -63,7 +64,7 @@ namespace Saxonite.Net.Core.Web.Admin.Models
|
||||
// Validation.
|
||||
//-------------------------------------------------------------------
|
||||
// Address.
|
||||
public bool ValidateAddressData(SaxModel_Admin model, SaxController_Base.AjaxResponse_Data responseData)
|
||||
public bool ValidateAddressData(SaxModel_Admin model, SaController.AjaxResponse_Data responseData)
|
||||
{
|
||||
// Are any properties populated.
|
||||
bool populated = IsPopulated();
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using Sarand.Net.Standard.Proc.Excel;
|
||||
using Saxonite.Base.App;
|
||||
using Saxonite.Net.Core.Web.Base.App;
|
||||
using Saxonite.Net.Core.Web.Base.Controllers;
|
||||
using Saxonite.Net.Core.Web.Base.Models;
|
||||
using Saxonite.Net.Standard.Base.App;
|
||||
using Saxonite.Net.Standard.Base.Bus;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Saxonite.Net.Core.Web.Admin.Models
|
||||
{
|
||||
//=======================================================================
|
||||
/// <summary>
|
||||
/// Model for Organisation Download.
|
||||
/// </summary>
|
||||
public class Model_OrganisationDownload : Model_Organisation
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public Model_OrganisationDownload(SaxLocaliser localiser) :
|
||||
base(localiser)
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
public String IncludeId { get; set; }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Validation.
|
||||
//-------------------------------------------------------------------
|
||||
public bool ValidateProperties()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using Sarand.Net.Standard.Proc.Excel;
|
||||
using Saxonite.Base.App;
|
||||
using Saxonite.Net.Core.Web.Base.App;
|
||||
using Saxonite.Net.Core.Web.Base.Controllers;
|
||||
using Saxonite.Net.Core.Web.Base.Models;
|
||||
using Saxonite.Net.Standard.Base.App;
|
||||
using Saxonite.Net.Standard.Base.Bus;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Saxonite.Net.Core.Web.Admin.Models
|
||||
{
|
||||
//=======================================================================
|
||||
/// <summary>
|
||||
/// Model for Organisation Upload.
|
||||
/// </summary>
|
||||
public class Model_OrganisationUpload : SaxModel_Admin
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public Model_OrganisationUpload(SaxLocaliser localiser) :
|
||||
base(localiser)
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Organisation data files - only one allowed per request.
|
||||
public List<IFormFile> OrganisationDataFile { get; set; }
|
||||
// Data file properties.
|
||||
public String SheetNameOrNumber { get; set; }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Validation.
|
||||
//-------------------------------------------------------------------
|
||||
public bool ValidateProperties(SaxController_Base.AjaxResponse_Data responseData)
|
||||
{
|
||||
|
||||
// Data file.
|
||||
{
|
||||
String controlName = nameof(OrganisationDataFile);
|
||||
// A single data file must be supplied.
|
||||
if (OrganisationDataFile == null || !OrganisationDataFile.Any())
|
||||
responseData.SetControlError(controlName, Localiser["msg.error.data.file.missing"]);
|
||||
else if (OrganisationDataFile != null && OrganisationDataFile.Count() > 1)
|
||||
responseData.SetControlError(controlName, Localiser["msg.error.data.file.multiple"]);
|
||||
}
|
||||
|
||||
// Sheet name or number.
|
||||
{
|
||||
String controlName = nameof(SheetNameOrNumber);
|
||||
if (StringUtil.IsBlank(SheetNameOrNumber))
|
||||
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
|
||||
else if (!ExcelHelper.IsValidSheetName(SheetNameOrNumber))
|
||||
responseData.SetControlError(controlName, Localiser["msg.error.sheet.name.invalid"]);
|
||||
}
|
||||
|
||||
return !responseData.HasControlErrors();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Saxonite.Net.Core.Web.Base.Procs.Data;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using Saxonite.Net.Core.Web.Admin.Models;
|
||||
using System.Collections;
|
||||
using Sarand.Net.Standard.Base.Helpers;
|
||||
using Sarand.Net.Standard.Proc.Excel;
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using System.IO;
|
||||
using DocumentFormat.OpenXml.EMMA;
|
||||
using Saxonite.Net.Standard.Base.Bus;
|
||||
using Saxonite.Net.Core.Web.Admin.Controllers;
|
||||
using Saxonite.Net.Standard.Base.App;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
using Sarand.Net.Standard.Base.Dbas;
|
||||
|
||||
namespace Saxonite.Net.Core.Web.Admin.Procs
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaxOrganisationExporter : SaxProcess_Admin
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Definitions.
|
||||
|
||||
public enum ExportFormat
|
||||
{
|
||||
Unknown,
|
||||
Excel_Open, /* xlxs */
|
||||
}
|
||||
|
||||
// Process configuration.
|
||||
public new class Config : SaxProcess_Admin.Config
|
||||
{
|
||||
public Config(SaxSessionContext sessionContext, SaxOrganisation.Params prmOrganisation) : base(sessionContext)
|
||||
{
|
||||
PrmOrganisation = prmOrganisation;
|
||||
}
|
||||
// Properties.
|
||||
public SaxOrganisation.Params PrmOrganisation { get; }
|
||||
public ExportFormat Format { get; set; }
|
||||
public bool IncludeId { get; set; }
|
||||
public ushort MaxRows { get; set; } = 2000;
|
||||
}
|
||||
|
||||
// Processing control data.
|
||||
private class ProcessControlData
|
||||
{
|
||||
public Config Config { get; set; }
|
||||
public SaMsSpreadsheet Spreadsheet { get; set; }
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
private ProcessControlData control { get; } = new ProcessControlData();
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public SaxOrganisationExporter(Config config) : base(config)
|
||||
{
|
||||
control.Config = config;
|
||||
}
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
// Spreadsheet.
|
||||
DisposeSpreadsheet();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
private void DisposeSpreadsheet()
|
||||
{
|
||||
if (control.Spreadsheet != null)
|
||||
control.Spreadsheet.Dispose();
|
||||
control.Spreadsheet = null;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
public override string ProcessDescription => "Organisation Export";
|
||||
public byte[] GetDocumentData()
|
||||
{
|
||||
switch (control.Config.Format)
|
||||
{
|
||||
case ExportFormat.Excel_Open:
|
||||
return control.Spreadsheet.GetDocumentData();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public String GetContentType()
|
||||
{
|
||||
switch (control.Config.Format)
|
||||
{
|
||||
case ExportFormat.Excel_Open: return SacsContentTypeHelper.ContentType_Excel_Open;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Run the process.
|
||||
protected override bool Run()
|
||||
{
|
||||
String fn = GetType().Name + ".Run";
|
||||
|
||||
// Verify configuration.
|
||||
if (control.Config == null)
|
||||
{
|
||||
AddErrorMessage("Configuration must be supplied.");
|
||||
SaLogger.Warn(fn + " " + GetErrorMessage());
|
||||
return OK;
|
||||
}
|
||||
if (control.Config.PrmOrganisation == null)
|
||||
{
|
||||
AddErrorMessage("Organisation params must be supplied.");
|
||||
SaLogger.Warn(fn + " " + GetErrorMessage());
|
||||
return OK;
|
||||
}
|
||||
else if (control.Config.Format != ExportFormat.Excel_Open)
|
||||
{
|
||||
AddErrorMessage("Unsupported export format: " + control.Config.Format.ToString() + ".");
|
||||
SaLogger.Warn(fn + " " + GetErrorMessage());
|
||||
}
|
||||
AddInfoMessage("Export format: " + control.Config.Format.ToString());
|
||||
|
||||
if (OK) ExportOrganisations();
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
private bool ExportOrganisations()
|
||||
{
|
||||
if (!OK) return false;
|
||||
|
||||
DisposeSpreadsheet();
|
||||
control.Spreadsheet = new SaMsSpreadsheet_POI();
|
||||
control.Spreadsheet.CreateWorkbook();
|
||||
control.Spreadsheet.WorksheetName = "Organisations";
|
||||
control.Spreadsheet.ApplyDefaultStyle(GetExceldefaultWorkbookStyle());
|
||||
|
||||
// Columns.
|
||||
ColumnDfn colId = AccountMgr.GetOrganisationColumnDfn(SaxOrganisation.Column.Id);
|
||||
colId.Alignment = ColumnAlignment.Center;
|
||||
|
||||
// Columns to output.
|
||||
List<ColumnDfn> columnsExport = new List<ColumnDfn>();
|
||||
if (control.Config.IncludeId)
|
||||
columnsExport.Add(colId);
|
||||
columnsExport.Add(AccountMgr.GetOrganisationColumnDfn(SaxOrganisation.Column.Name));
|
||||
columnsExport.Add(AccountMgr.GetOrganisationColumnDfn(SaxOrganisation.Column.OrganisationCategory_Desc));
|
||||
columnsExport.Add(AccountMgr.GetOrganisationColumnDfn(SaxOrganisation.Column.OrganisationType_Desc));
|
||||
columnsExport.Add(AccountMgr.GetOrganisationColumnDfn(SaxOrganisation.Column.Sport_Name));
|
||||
columnsExport.Add(AccountMgr.GetOrganisationColumnDfn(SaxOrganisation.Column.Region_Name));
|
||||
columnsExport.Add(AccountMgr.GetOrganisationColumnDfn(SaxOrganisation.Column.User_Count));
|
||||
columnsExport.Add(AccountMgr.GetOrganisationColumnDfn(SaxOrganisation.Column.Member_Count));
|
||||
|
||||
// Initialise spreadsheet column headings and formats etc
|
||||
SaMsExcelColumnHeading_Config configHeading = GetExcelColumnHeadingConfig();
|
||||
control.Spreadsheet.SetColumnHeadings(columnsExport, configHeading);
|
||||
|
||||
// Columns to query - ensure Id is in the list.
|
||||
List<ColumnDfn> columnsQuery = new List<ColumnDfn>(columnsExport);
|
||||
if (!columnsQuery.Exists(item => item.Id == (int)SaxOrganisation.Column.Id))
|
||||
columnsQuery.Add(colId);
|
||||
|
||||
// Organisation params.
|
||||
control.Config.PrmOrganisation.ResultsPaging.PageNo = 1;
|
||||
control.Config.PrmOrganisation.ResultsPaging.PageLength = (ushort)Math.Min(ushort.MaxValue, Math.Max(ushort.MinValue, control.Config.MaxRows));
|
||||
|
||||
// Query Organisations.
|
||||
uint dataRowPos = configHeading.FirstDataRowPos - 1;
|
||||
using (DbResultSet resultSet = AccountMgr.ExecuteOrganisationQuery(columnsQuery, control.Config.PrmOrganisation))
|
||||
{
|
||||
while (resultSet != null && resultSet.HasRows && resultSet.NextRecord())
|
||||
{
|
||||
dataRowPos++;
|
||||
NamedValue.Map values = resultSet.GetRecordValues();
|
||||
SysId organisationId = new SysId(values.GetLong(colId.DataName));
|
||||
int colIdx = -1;
|
||||
foreach (ColumnDfn col in columnsExport)
|
||||
{
|
||||
colIdx++;
|
||||
uint dataColPos = (uint)(configHeading.FirstHeadingColPos + colIdx);
|
||||
DataValue value = AccountMgr.GetOrganisationDataValue(col, values);
|
||||
if (col.ShowZeroValues || !col.IsNumeric || value.ToNumeric() != 0.0)
|
||||
control.Spreadsheet.SetCellValue(dataColPos, dataRowPos, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,259 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sarand.Net.Standard.Base.Helpers;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using Sarand.Net.Standard.Proc.Excel;
|
||||
using Sarand.Net.Standard.Proc.Procs;
|
||||
using Saxonite.Net.Core.Web.Base.Procs.Data;
|
||||
using Saxonite.Net.Standard.Base.App;
|
||||
using Saxonite.Net.Standard.Base.Procs;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Saxonite.Net.Core.Web.Admin.Procs
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaxOrganisationUploader : SaxProcess_Admin
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Definitions.
|
||||
|
||||
// Process configuration.
|
||||
public new class Config : SaxProcess_Admin.Config
|
||||
{
|
||||
public Config(SaxSessionContext sessionContext, IFormFile dataFile) : base(sessionContext)
|
||||
{
|
||||
this.DataFile = new UploadFileData(dataFile);
|
||||
}
|
||||
// Properties.
|
||||
public UploadFileData DataFile { get; }
|
||||
public String SheetNameOrNumber { get; set; }
|
||||
public uint HeaderRowPos { get; set; }
|
||||
public bool ValidateOnly { get; set; }
|
||||
public bool AllowCreateOrganisation { get; set; }
|
||||
public bool RequireOrganisationIdForUpdate { get; set; }
|
||||
}
|
||||
|
||||
// Supported content types.
|
||||
private static HashSet<String> validContentTypes { get; } = new HashSet<string>(StringComparer.OrdinalIgnoreCase) {
|
||||
SacsContentTypeHelper.ContentType_Excel_Legacy, /* xls */
|
||||
SacsContentTypeHelper.ContentType_Excel_Open, /* xlsx */
|
||||
SacsContentTypeHelper.ContentType_Excel_MacroEnabled, /* xlsm */
|
||||
SacsContentTypeHelper.ContentType_Excel_BinaryMacroEnabled /* xlsb */
|
||||
};
|
||||
/// <summary>Allowed content types.</summary>
|
||||
public static List<String> ValidContentTypes { get { return new List<String>(validContentTypes); } }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Organisation data profile.
|
||||
private enum OrganisationProperty
|
||||
{
|
||||
// Property columns.
|
||||
OrganisationId, OrganisationName, Sport, Region,
|
||||
// Address.
|
||||
AddressLine1, AddressLine2, AddressTown, AddressPostcode,
|
||||
// Contact personal.
|
||||
ContactName, ContactRole, ContactEmail,
|
||||
// Contact.
|
||||
ContactPhone, ContactWeb, ContactMap, ContactWiki, ContactFacebook, ContactInstagram, ContactTwitter,
|
||||
}
|
||||
private class OrganisationPropertyData
|
||||
{
|
||||
public OrganisationPropertyData(OrganisationProperty property, String columnHeaders)
|
||||
{
|
||||
this.Property = property;
|
||||
foreach (String value in Regex.Split(columnHeaders, "[\\s,]+", RegexOptions.None))
|
||||
if (!StringUtil.IsBlank(value)) this.ColumnHeaders.Add(value);
|
||||
}
|
||||
public OrganisationProperty Property { get; }
|
||||
public HashSet<String> ColumnHeaders { get; } = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
public uint ColumnPos { get; set; }
|
||||
public bool IsValid { get { return ColumnPos > 0; } }
|
||||
}
|
||||
private class OrganisationDataProfile
|
||||
{
|
||||
public OrganisationDataProfile()
|
||||
{
|
||||
// Property columns.
|
||||
AddProperty(OrganisationProperty.OrganisationId, "Id, Organisation Id");
|
||||
AddProperty(OrganisationProperty.OrganisationName, "Name, Organisation Name");
|
||||
AddProperty(OrganisationProperty.Sport, "Sport");
|
||||
AddProperty(OrganisationProperty.Region, "Region");
|
||||
// Address.
|
||||
AddProperty(OrganisationProperty.AddressLine1, "Address Line 1, Line 1, Street");
|
||||
AddProperty(OrganisationProperty.AddressLine2, "Address Line 2, Line 2");
|
||||
AddProperty(OrganisationProperty.AddressTown, "Town,City,Address Town,Address City");
|
||||
AddProperty(OrganisationProperty.AddressPostcode, "Postcode");
|
||||
// Contact personal.
|
||||
AddProperty(OrganisationProperty.ContactName, "Contact Name");
|
||||
AddProperty(OrganisationProperty.ContactRole, "Contact Role");
|
||||
AddProperty(OrganisationProperty.ContactEmail, "Contatc Email");
|
||||
// Contact.
|
||||
AddProperty(OrganisationProperty.ContactPhone, "Phone");
|
||||
AddProperty(OrganisationProperty.ContactWeb, "Web, Web Link, Website");
|
||||
AddProperty(OrganisationProperty.ContactMap, "Web Map, Map Link");
|
||||
AddProperty(OrganisationProperty.ContactWiki, "Wiki, Wikipedia, Wiki Link");
|
||||
AddProperty(OrganisationProperty.ContactFacebook, "Facebook");
|
||||
AddProperty(OrganisationProperty.ContactInstagram, "Instagram");
|
||||
AddProperty(OrganisationProperty.ContactTwitter, "X, Twitter");
|
||||
}
|
||||
public Dictionary<OrganisationProperty, OrganisationPropertyData> Properties { get; } = new Dictionary<OrganisationProperty, OrganisationPropertyData>();
|
||||
private void AddProperty(OrganisationProperty property, String columnHeaders)
|
||||
{
|
||||
Properties.Add(property, new OrganisationPropertyData(property, columnHeaders));
|
||||
}
|
||||
public bool IsValidProperty(OrganisationProperty property)
|
||||
{
|
||||
OrganisationPropertyData propertyData = Properties[property];
|
||||
return propertyData != null && propertyData.IsValid;
|
||||
}
|
||||
}
|
||||
|
||||
// Processing control data.
|
||||
private class ProcessControlData
|
||||
{
|
||||
public Config config { get; set; }
|
||||
public SaMsSpreadsheet spreadsheet { get; set; }
|
||||
public OrganisationDataProfile dataProfile { get; } = new OrganisationDataProfile();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
private ProcessControlData control { get; } = new ProcessControlData();
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public SaxOrganisationUploader(Config config) : base(config)
|
||||
{
|
||||
control.config = config;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
|
||||
public override string ProcessDescription => "Organisation Upload";
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Run the process.
|
||||
protected override bool Run()
|
||||
{
|
||||
String fn = GetType().Name + ".Run";
|
||||
|
||||
// Verify file.
|
||||
if (control.config.DataFile == null)
|
||||
{
|
||||
AddErrorMessage("Data file must be supplied.");
|
||||
SaLogger.Warn(fn + " " + GetErrorMessage());
|
||||
return OK;
|
||||
}
|
||||
else if (!validContentTypes.Contains(control.config.DataFile.ContentType))
|
||||
{
|
||||
AddErrorMessage("Unsupported content type: " + control.config.DataFile.ContentType + ".");
|
||||
SaLogger.Warn(fn + " " + GetErrorMessage());
|
||||
}
|
||||
AddInfoMessage("Data file: " + control.config.DataFile.FileName);
|
||||
AddInfoMessage("Sheet: " + control.config.SheetNameOrNumber);
|
||||
|
||||
try
|
||||
{
|
||||
if (OK)
|
||||
{
|
||||
// Open spreadsheet.
|
||||
using (SaMsSpreadsheet_POI spreadsheet = new SaMsSpreadsheet_POI())
|
||||
using (Stream stream = new MemoryStream())
|
||||
{
|
||||
stream.Write(control.config.DataFile.FileData, 0, (int)control.config.DataFile.Length);
|
||||
if (!spreadsheet.OpenWorkbook(stream))
|
||||
{
|
||||
// Failed to open workbook.
|
||||
String msg = "Failed to open workbook - " + spreadsheet.ErrorStateMessage;
|
||||
AddErrorMessage(msg);
|
||||
SaLogger.Warn(fn + " " + msg);
|
||||
}
|
||||
if (OK && !spreadsheet.OpenWorksheet(1))
|
||||
{
|
||||
// Failed to open workbook.
|
||||
String msg = "Failed to open worksheet - " + spreadsheet.ErrorStateMessage;
|
||||
AddErrorMessage(msg);
|
||||
SaLogger.Warn(fn + " " + msg);
|
||||
}
|
||||
if (OK)
|
||||
{
|
||||
control.spreadsheet = spreadsheet;
|
||||
PopulateDataProfile();
|
||||
}
|
||||
if (OK)
|
||||
{
|
||||
uint firstRowPos = spreadsheet.FirstRowPos;
|
||||
for (uint rowPos = firstRowPos; rowPos <= firstRowPos; rowPos++)
|
||||
{
|
||||
for (uint colPos = 1; colPos <= 5; colPos++)
|
||||
{
|
||||
SaLogger.Info("Row: " + rowPos + ", colPos: " + colPos + ": '" + spreadsheet.GetCellText(colPos, rowPos) + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
// Clean-up.
|
||||
control.spreadsheet = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
String msg = exc.GetType().Name + " uploading organisation data.";
|
||||
AddErrorMessage(msg);
|
||||
SaLogger.Warn(fn + " " + msg + " " + exc.Message + ExceptionUtil.GetStackEntries(exc, 6).Concat("", "\n\t"));
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
private bool PopulateDataProfile()
|
||||
{
|
||||
String fn = GetType().Name + ".PopulateDataProfile";
|
||||
|
||||
// Identify header row.
|
||||
uint headerRowPos = control.config.HeaderRowPos;
|
||||
if (headerRowPos < 1)
|
||||
headerRowPos = control.spreadsheet.FirstRowPos;
|
||||
|
||||
// Column headings.
|
||||
List<String> columnHeadings = new List<string>();
|
||||
for (uint colPos = 1; colPos <= 100; colPos++)
|
||||
{
|
||||
columnHeadings.Add(control.spreadsheet.GetCellText(colPos, headerRowPos));
|
||||
}
|
||||
SaLogger.Info(fn + " Column headings: " + columnHeadings.Concat(", "));
|
||||
|
||||
// Populate header columns in profile.
|
||||
foreach (OrganisationPropertyData propertyData in control.dataProfile.Properties.Values)
|
||||
{
|
||||
for (uint colPos = 1; colPos <= columnHeadings.Count; colPos++)
|
||||
{
|
||||
String columnHeading = columnHeadings[(int)(colPos - 1)];
|
||||
if (propertyData.ColumnHeaders.ContainsCI(columnHeading))
|
||||
{
|
||||
if (control.dataProfile.Properties.Values.ToList().Exists(item => item.ColumnPos == colPos))
|
||||
AddWarningMessage("Multiple properties associated with column '" + columnHeading + "'.");
|
||||
propertyData.ColumnPos = colPos;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!control.dataProfile.IsValidProperty(OrganisationProperty.OrganisationId) && !control.dataProfile.IsValidProperty(OrganisationProperty.OrganisationName))
|
||||
return AddErrorMessage("Organisation Id or Name column must be present");
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
using Sarand.Net.Standard.Proc.Excel;
|
||||
using Sarand.Net.Standard.Proc.Procs;
|
||||
using Saxonite.Net.Standard.Base.App;
|
||||
using Saxonite.Net.Standard.Base.Procs;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Saxonite.Net.Core.Web.Admin.Procs
|
||||
{
|
||||
//=======================================================================
|
||||
public abstract class SaxProcess_Admin : SaxProcess_Base
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Definitions.
|
||||
public new class Config : SaxProcess_Base.Config
|
||||
{
|
||||
protected Config(SaxSessionContext sessionContext) : base(sessionContext)
|
||||
{ }
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
private Config config;
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
protected SaxProcess_Admin(Config config) : base(config)
|
||||
{
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Excel Spreadsheet utilities.
|
||||
//-------------------------------------------------------------------
|
||||
protected SaMsExcelColumnHeading_Config GetExcelColumnHeadingConfig()
|
||||
{
|
||||
SaMsExcelColumnHeading_Config configHeading = new SaMsExcelColumnHeading_Config();
|
||||
configHeading.FontAttr.Name = "Arial";
|
||||
configHeading.FontAttr.HeightInPoints = 10;
|
||||
configHeading.FontAttr.ColourIndex = SaXlColourIndex.DarkBlue;
|
||||
configHeading.FontAttr.Bold = true;
|
||||
configHeading.HeadingTextWrap = true;
|
||||
configHeading.ForegroundColourIndex = SaXlColourIndex.LightYellow;
|
||||
configHeading.BorderWeight = SaXlBorderWeight.Medium;
|
||||
return configHeading;
|
||||
}
|
||||
|
||||
protected SaMsExcelStyleAttr GetExceldefaultWorkbookStyle()
|
||||
{
|
||||
SaMsExcelStyleAttr styleAttr = new SaMsExcelStyleAttr();
|
||||
styleAttr.FontAttr.Name = "Arial";
|
||||
styleAttr.FontAttr.HeightInPoints = 9;
|
||||
styleAttr.FontAttr.ColourIndex = SaXlColourIndex.Black;
|
||||
styleAttr.HorizontalAlignment = (short)XlHAlign.xlHAlignLeft;
|
||||
styleAttr.VerticalAlignment = (short)XlVAlign.xlVAlignTop;
|
||||
styleAttr.WrapText = true;
|
||||
return styleAttr;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -120,6 +120,9 @@
|
||||
<data name="caption.contact.method" xml:space="preserve">
|
||||
<value>Contact Method</value>
|
||||
</data>
|
||||
<data name="caption.download.organisations" xml:space="preserve">
|
||||
<value>Download Organisations</value>
|
||||
</data>
|
||||
<data name="caption.image.upload" xml:space="preserve">
|
||||
<value>Image Upload</value>
|
||||
</data>
|
||||
@@ -156,6 +159,9 @@
|
||||
<data name="caption.organisations" xml:space="preserve">
|
||||
<value>Organisations</value>
|
||||
</data>
|
||||
<data name="caption.upload.organisations" xml:space="preserve">
|
||||
<value>Upload Organisations</value>
|
||||
</data>
|
||||
<data name="caption.user.report" xml:space="preserve">
|
||||
<value>User Report</value>
|
||||
</data>
|
||||
@@ -276,6 +282,9 @@
|
||||
<data name="label.create" xml:space="preserve">
|
||||
<value>Create</value>
|
||||
</data>
|
||||
<data name="label.data.file" xml:space="preserve">
|
||||
<value>Data file</value>
|
||||
</data>
|
||||
<data name="label.database" xml:space="preserve">
|
||||
<value>Database</value>
|
||||
</data>
|
||||
@@ -288,6 +297,9 @@
|
||||
<data name="label.delete" xml:space="preserve">
|
||||
<value>Delete</value>
|
||||
</data>
|
||||
<data name="label.download" xml:space="preserve">
|
||||
<value>Download</value>
|
||||
</data>
|
||||
<data name="label.edit" xml:space="preserve">
|
||||
<value>Edit</value>
|
||||
</data>
|
||||
@@ -321,6 +333,9 @@
|
||||
<data name="label.images" xml:space="preserve">
|
||||
<value>Images</value>
|
||||
</data>
|
||||
<data name="label.include.id" xml:space="preserve">
|
||||
<value>Include Id</value>
|
||||
</data>
|
||||
<data name="label.index" xml:space="preserve">
|
||||
<value>Index</value>
|
||||
</data>
|
||||
@@ -405,6 +420,9 @@
|
||||
<data name="label.online.today" xml:space="preserve">
|
||||
<value>Online today</value>
|
||||
</data>
|
||||
<data name="label.options" xml:space="preserve">
|
||||
<value>Options</value>
|
||||
</data>
|
||||
<data name="label.organisation" xml:space="preserve">
|
||||
<value>Organisation</value>
|
||||
</data>
|
||||
@@ -474,6 +492,9 @@
|
||||
<data name="label.selected.none" xml:space="preserve">
|
||||
<value>none selected</value>
|
||||
</data>
|
||||
<data name="label.sheet.name.or.number" xml:space="preserve">
|
||||
<value>Sheet name or number (from 1)</value>
|
||||
</data>
|
||||
<data name="label.speciality" xml:space="preserve">
|
||||
<value>Speciality</value>
|
||||
</data>
|
||||
@@ -540,6 +561,15 @@
|
||||
<data name="msg.drag.image.here" xml:space="preserve">
|
||||
<value>Drag image here</value>
|
||||
</data>
|
||||
<data name="msg.drop.organisation.data.file.here" xml:space="preserve">
|
||||
<value>Drop organisation data file here.</value>
|
||||
</data>
|
||||
<data name="msg.error.data.file.missing" xml:space="preserve">
|
||||
<value>Data file must be supplied for upload.</value>
|
||||
</data>
|
||||
<data name="msg.error.data.file.multiple" xml:space="preserve">
|
||||
<value>Only a single data file can be supplied for upload.</value>
|
||||
</data>
|
||||
<data name="msg.error.data.incomplete" xml:space="preserve">
|
||||
<value>Data is incomplete</value>
|
||||
</data>
|
||||
@@ -561,9 +591,18 @@
|
||||
<data name="msg.error.item.update.failed" xml:space="preserve">
|
||||
<value>Item update failed</value>
|
||||
</data>
|
||||
<data name="msg.error.sheet.missing" xml:space="preserve">
|
||||
<value>Sheet not found.</value>
|
||||
</data>
|
||||
<data name="msg.error.sheet.name.invalid" xml:space="preserve">
|
||||
<value>Invalid sheet name supplied.</value>
|
||||
</data>
|
||||
<data name="msg.error.system" xml:space="preserve">
|
||||
<value>System error encountered.</value>
|
||||
</data>
|
||||
<data name="msg.process.in.progress" xml:space="preserve">
|
||||
<value>The process is already running.</value>
|
||||
</data>
|
||||
<data name="msg.something.gone.wrong" xml:space="preserve">
|
||||
<value>Unfortunately, something has gone wrong.\n\nYou will be returned to the home page.</value>
|
||||
</data>
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development",
|
||||
"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation"
|
||||
}
|
||||
},
|
||||
"nativeDebugging": false
|
||||
},
|
||||
"SaxoniteCoreWebAdmin": {
|
||||
"commandName": "Project",
|
||||
@@ -23,8 +24,8 @@
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:50421",
|
||||
"sslPort": 44351
|
||||
"applicationUrl": "http://localhost:43216",
|
||||
"sslPort": 44365
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<CopyRefAssembliesToPublishDirectory>false</CopyRefAssembliesToPublishDirectory>
|
||||
<RootNamespace>Saxonite.Net.Core.Web</RootNamespace>
|
||||
<AssemblyName>Saxonite.Net.Core.Web</AssemblyName>
|
||||
@@ -9,14 +9,16 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="jQuery.UI.Combined" Version="1.12.1" />
|
||||
<PackageReference Include="jQuery.UI.Combined" Version="1.13.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="3.1.16" />
|
||||
<PackageReference Include="System.Collections.Specialized" Version="4.3.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\Common-VS\Workspace\SacsCoreWeb\SacsCoreWeb.csproj" />
|
||||
<ProjectReference Include="..\..\..\Common-VS\Workspace\SacsStandardBase\SacsStandardBase.csproj" />
|
||||
<ProjectReference Include="..\..\..\Common-VS\Workspace\SacsStandardDbas\SacsStandardDbas.csproj" />
|
||||
<ProjectReference Include="..\..\..\Common-VS\Workspace\SacsStandardProc\SacsStandardProc.csproj" />
|
||||
<ProjectReference Include="..\SaxoniteCoreWeb\SaxoniteCoreWeb.csproj" />
|
||||
<ProjectReference Include="..\SaxoniteStandardBase\SaxoniteStandardBase.csproj" />
|
||||
<ProjectReference Include="..\SaxoniteStandardDbas\SaxoniteStandardDbas.csproj" />
|
||||
|
||||
@@ -183,6 +183,10 @@
|
||||
<partial name="Panel-Organisation-Address.cshtml" />
|
||||
@* Organisation Images dialog, form and script *@
|
||||
<partial name="Panel-Organisation-Images.cshtml" />
|
||||
@* Organisation download dialog, form and script *@
|
||||
<partial name="Panel-Organisation-Download.cshtml" />
|
||||
@* Organisation upload dialog, form and script *@
|
||||
<partial name="Panel-Organisation-Upload.cshtml" />
|
||||
@* Select Item dialog and script *@
|
||||
<partial name="~/Views/Common/SelectItem.cshtml" />
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
@model SaxModel_Admin
|
||||
@inject SaxLocaliser Localiser
|
||||
@{
|
||||
/* Organisations - Organisation Download panel */
|
||||
// Ensure view is only included once in page.
|
||||
if (!Model.RegisterView("Views/Organisation/Panel-Organisation-Download")) return;
|
||||
// Scripts.
|
||||
Model.AdditionalFiles_JS.Add("js/sax-org-dnl.js");
|
||||
}
|
||||
|
||||
<style>
|
||||
</style>
|
||||
|
||||
<script type="text/javascript">
|
||||
sax.lbl.download = '@(Localiser.GetJavascriptText("label.download"))';
|
||||
sax.dlg.title.downloadOrganisation = '@Localiser.GetJavascriptText("caption.download.organisations")';
|
||||
</script>
|
||||
|
||||
<div id="dlgOrgDownload" class="sax-dialog" title="@(HttpUtility.HtmlAttributeEncode(Localiser.GetText("caption.download.organisations")))">
|
||||
|
||||
<div class="spacer4"></div>
|
||||
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmOrgDownload", @class = "sax-form" }))
|
||||
{
|
||||
@* Organisation filter. *@
|
||||
<input type="hidden" name="Filter.Organisation" class="FilterOrganisation" />
|
||||
<input type="hidden" name="Filter.OrganisationCategoryCode" class="FilterOrganisationCategory" />
|
||||
<input type="hidden" name="Filter.OrganisationSportId" class="FilterOrganisationSportId" />
|
||||
<input type="hidden" name="Filter.OrganisationRegionId" class="FilterOrganisationRegionId" />
|
||||
<input type="hidden" name="Filter.OrganisationStatusCategoryCode" class="FilterOrganisationStatusCategory" />
|
||||
|
||||
@* Sheet name or number *@
|
||||
<div class="sax-form-control Options">
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<div class="sax-label">
|
||||
<label for="chkIncludeId"><span>@Localiser["label.options"]</span> <span class="required hidden">*</span></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="sax-control">
|
||||
<input type="checkbox" id="chkIncludeId" name="IncludeId" class="IncludeId" /> <span class="" onclick="$('#chkIncludeId').click()">@Localiser["label.include.id"]</span>
|
||||
</div>
|
||||
<div class="sax-message"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
}
|
||||
<div class="spacer4"></div>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
if (!Model.RegisterView("Views/Organisation/Panel-Organisation-Images")) return;
|
||||
// Scripts.
|
||||
Model.AdditionalFiles_JS.Add("js/sax-org-img.js");
|
||||
// Dynamic style values (to avoid build warning).
|
||||
String maxImageWidth = Sax.Config.Organisation.Logo.DisplayWidthMax_Item + "px";
|
||||
String maxImageHeight = Sax.Config.Organisation.Logo.DisplayHeightMax_Item + "px";
|
||||
}
|
||||
|
||||
<style>
|
||||
@@ -19,8 +22,8 @@
|
||||
#dlgOrganisationImages .sax-panel-drop.OrganisationLogoImageDrop img
|
||||
{
|
||||
display: none;
|
||||
max-width:@(Sax.Config.Organisation.Logo.DisplayWidthMax_Item + "px");
|
||||
max-height:@(Sax.Config.Organisation.Logo.DisplayHeightMax_Item + "px");
|
||||
max-width: @maxImageWidth;
|
||||
max-height: @maxImageHeight;
|
||||
margin-right: 8px;
|
||||
border: 1px solid #b0b0b080;
|
||||
border-radius: 4px;
|
||||
@@ -33,7 +36,7 @@
|
||||
|
||||
#dlgOrganisationImages .sax-panel-drop.OrganisationLogoImageDrop.sax-file-drag
|
||||
{
|
||||
background-color:#c0fff0;
|
||||
background-color: #c0fff0;
|
||||
border-color: darkgreen;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
@model SaxModel_Admin
|
||||
@inject SaxLocaliser Localiser
|
||||
@{
|
||||
/* Organisations - Organisation Upload panel */
|
||||
// Ensure view is only included once in page.
|
||||
if (!Model.RegisterView("Views/Organisation/Panel-Organisation-Upload")) return;
|
||||
// Scripts.
|
||||
Model.AdditionalFiles_JS.Add("js/sax-org-upl.js");
|
||||
}
|
||||
|
||||
<style>
|
||||
#dlgOrgUpload .sax-panel-drop.OrgDataFileDrop
|
||||
{
|
||||
min-height:240px;
|
||||
padding: 4px 8px;
|
||||
border: 1px solid #f0f0f0;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
#dlgOrgUpload .sax-panel-drop.OrgDataFileDrop.sax-file-drag
|
||||
{
|
||||
background-color: #f0fffc;
|
||||
border-color: darkgreen;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script type="text/javascript">
|
||||
sax.lbl.upload = '@(Localiser.GetJavascriptText("label.upload"))';
|
||||
sax.lbl.download = '@(Localiser.GetJavascriptText("label.download"))';
|
||||
sax.dlg.title.uploadOrganisation = '@Localiser.GetJavascriptText("caption.upload.organisations")';
|
||||
</script>
|
||||
|
||||
<div id="dlgOrgUpload" class="sax-dialog" title="@(HttpUtility.HtmlAttributeEncode(Localiser.GetText("caption.upload.organisations")))">
|
||||
|
||||
<div class="spacer4"></div>
|
||||
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmOrgUpload", @class = "sax-form", @enctype = "multipart/form-data", @onSubmit = "return false;" }))
|
||||
{
|
||||
|
||||
<div class="sax-panel-drop OrgDataFileDrop">
|
||||
|
||||
<div class="spacer2"></div>
|
||||
<div class="sax-note">@Localiser["msg.drop.organisation.data.file.here"]</div>
|
||||
<div class="spacer4"></div>
|
||||
|
||||
@* Organisation data file *@
|
||||
<div class="sax-form-control OrganisationDataFile">
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<div class="sax-label">
|
||||
<label for="ifOrganisationName"><span>@Localiser["label.data.file"]</span></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="sax-control">
|
||||
<input type="file" name="OrganisationDataFile" class="OrganisationDataFile fullwidth" style="" />
|
||||
</div>
|
||||
<div class="sax-message"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@* Sheet name or number *@
|
||||
<div class="sax-form-control SheetNameOrNumber">
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<div class="sax-label">
|
||||
<label for="ifSheetNameOrNumber"><span>@Localiser["label.sheet.name.or.number"]</span> <span class="required">*</span></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="sax-control">
|
||||
<input type="text" id="ifSheetNameOrNumber" name="SheetNameOrNumber" class="SheetNameOrNumber sax-input" maxlength="31" />
|
||||
</div>
|
||||
<div class="sax-message"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
}
|
||||
<div class="spacer4"></div>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
@using Sarand.Net.Standard.Base.Core
|
||||
@using System.Web
|
||||
@using Sarand.Net.Standard.Base.Core
|
||||
@using Sarand.Net.Standard.Base.Utils
|
||||
@using Saxonite.Base.App
|
||||
@using Saxonite.Net.Standard.Base.App
|
||||
|
||||
@@ -116,6 +116,7 @@
|
||||
.sax-header ul.nav.sax-burger ul.sax-dropdown-menu
|
||||
{
|
||||
padding: 4px 8px 4px 4px;
|
||||
border-radius:2px 2px 8px 4px;
|
||||
box-shadow: 0 0 8px 2px #80808080;
|
||||
}
|
||||
|
||||
@@ -187,6 +188,16 @@
|
||||
background-image: url('../img/action/process24.png');
|
||||
}
|
||||
|
||||
.sax-header ul.nav.sax-burger ul.sax-dropdown-menu li.sax-action.sax-dropdown-item.sax-upload
|
||||
{
|
||||
background-image: url('../img/action/upload24.png');
|
||||
}
|
||||
|
||||
.sax-header ul.nav.sax-burger ul.sax-dropdown-menu li.sax-action.sax-dropdown-item.sax-download
|
||||
{
|
||||
background-image: url('../img/action/download24.png');
|
||||
}
|
||||
|
||||
.sax-header ul.nav.sax-burger ul.sax-dropdown-menu li.sax-action.sax-dropdown-item.sax-network
|
||||
{
|
||||
background-image: url('../img/action/network-24.png');
|
||||
|
||||
@@ -33,17 +33,17 @@
|
||||
if (!response.success) return;
|
||||
//return $msgs.append($('<div class="sax-message">' + sax.msg.noItemsAwaitAct + '</div>')).fadeIn(500);
|
||||
// Users.
|
||||
let user = response.stats.user;
|
||||
let $user = sax.getAppStatItemTemplate();
|
||||
$('.sax-header .sax-caption', $user).text(user.caption || 'Users');
|
||||
ah.populateAppStat($user, user.awaiting.label, user.awaiting.value, user.awaitingLink)
|
||||
for (let item of user.onlineStats)
|
||||
ah.populateAppStat($user, item.label, item.value, user.onlineLink)
|
||||
$items.append($user);
|
||||
let usr = response.stats.user;
|
||||
let $usr = sax.getAppStatItemTemplate();
|
||||
$('.sax-header .sax-caption', $usr).text(usr.caption || 'Users').on('click', function () { win.location = usr.usersLink; }).addClass("sax-action");
|
||||
ah.populateAppStat($usr, usr.awaiting.label, usr.awaiting.value, usr.awaitingLink)
|
||||
for (let item of usr.onlineStats)
|
||||
ah.populateAppStat($usr, item.label, item.value, usr.onlineLink)
|
||||
$items.append($usr);
|
||||
// Organisations.
|
||||
let org = response.stats.organisation;
|
||||
let $org = sax.getAppStatItemTemplate();
|
||||
$('.sax-header .sax-caption', $org).text(org.caption || 'Organisations');
|
||||
$('.sax-header .sax-caption', $org).text(org.caption || 'Organisations').on('click', function () { win.location = org.organisationsLink; }).addClass("sax-action");
|
||||
ah.populateAppStat($org, org.awaiting.label, org.awaiting.value, org.awaitingLink)
|
||||
$items.append($org);
|
||||
$items.slideDown(750);
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Admin - Organisation Download scripts.
|
||||
*/
|
||||
|
||||
(function (win, doc, undef)
|
||||
{
|
||||
"use strict";
|
||||
let od = sax.mdl.orgDownload = { data: {}, ajax: {} };
|
||||
let $pnl = od.$pnl = {}, $frm = od.$frm = {}, $ctrl = od.$ctrl = {}, $dlg = od.$dlg = {};
|
||||
od.classFileDrag = 'sax-file-drag';
|
||||
|
||||
//--------------------------------------------------------------
|
||||
sax.downloadOrganisationData = function ()
|
||||
{
|
||||
//sax.debug('downloadOrganisationData');
|
||||
let frm = $frm.orgDnl;
|
||||
if (!frm.length) return;
|
||||
sax.clearControlErrors(frm);
|
||||
sax.openDialog($dlg.orgDnl, 640, 480);
|
||||
}
|
||||
|
||||
od.downloadOrgData = function ()
|
||||
{
|
||||
sax.debug("downloadOrgData");
|
||||
$('.FilterOrganisation', $frm.orgDnl).val($('.FilterOrganisation', $frm.orgFlt).val());
|
||||
$('.FilterOrganisationCategory', $frm.orgDnl).val($('.FilterOrganisationCategory', $frm.orgFlt).val());
|
||||
sax.debug($('.FilterOrganisationSportId', $frm.orgFlt));
|
||||
sax.debug($('.FilterOrganisationSportId', $frm.orgFlt).val());
|
||||
$('.FilterOrganisationSportId', $frm.orgDnl).val($('.FilterOrganisationSportId', $frm.orgFlt).val());
|
||||
$('.FilterOrganisationRegionId', $frm.orgDnl).val($('.FilterOrganisationRegionId', $frm.orgFlt).val());
|
||||
$('.FilterOrganisationStatusCategory', $frm.orgDnl).val($('.FilterOrganisationStatusCategory', $frm.orgFlt).val());
|
||||
sax.debug($frm.orgDnl);
|
||||
if (!$frm.orgDnl.length) return;
|
||||
$frm.orgDnl.prop('target', '_blank').prop('action', '/Organisation/Download').submit();
|
||||
}
|
||||
|
||||
od.onDownloadOrgData = function (response)
|
||||
{
|
||||
sax.debug('onDownloadOrgData', response);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
$(function ()
|
||||
{
|
||||
$frm.orgFlt = $('#frmOrganisationFilter');
|
||||
// Organisation Download dialog and form.
|
||||
var opt = sax.dlgOpts();
|
||||
opt.buttons[sax.lbl.download] = function () { od.downloadOrgData(); };
|
||||
opt.buttons[sax.dlg.btn.cancel] = function () { $(this).dialog('close'); };
|
||||
$dlg.orgDnl= $('#dlgOrgDownload').dialog(opt);
|
||||
$frm.orgDnl = $('#frmOrgDownload', $dlg.orgDnl);
|
||||
$frm.orgDnl.on('input', '.sax-input, .sax-textarea', function () { sax.clearControlError(this); }).on('change', '.sax-select', function () { sax.clearControlError(this); });
|
||||
});
|
||||
|
||||
//--------------------------------------------------------------
|
||||
}(window, window.document));
|
||||
|
||||
/* The End */
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Admin - Organisation Upload scripts.
|
||||
*/
|
||||
|
||||
(function (win, doc, undef)
|
||||
{
|
||||
"use strict";
|
||||
let ou = sax.mdl.orgUpload = { data: {}, ajax: {} };
|
||||
let $pnl = ou.$pnl = {}, $frm = ou.$frm = {}, $ctrl = ou.$ctrl = {}, $dlg = ou.$dlg = {};
|
||||
ou.classFileDrag = 'sax-file-drag';
|
||||
|
||||
//--------------------------------------------------------------
|
||||
sax.uploadOrganisationData = function ()
|
||||
{
|
||||
//sax.debug('uploadOrganisationData');
|
||||
let frm = $frm.orgUpl;
|
||||
if (!frm.length) return;
|
||||
$ctrl.file.val('');
|
||||
sax.clearControlErrors(frm);
|
||||
sax.openDialog($dlg.orgUpl, 640, 480);
|
||||
}
|
||||
|
||||
ou.onDropOrgDataFile = function (evt)
|
||||
{
|
||||
//sax.debug('onDropOrgDataFile');
|
||||
let files = evt.originalEvent.dataTransfer.files;
|
||||
if (files.length < 1) return;
|
||||
if (files.length > 1) return sax.doAlert(sax.dlg.title.uploadOrganisation, sax.msg.uploadImageSingle);
|
||||
let file = files[0];
|
||||
if (file.size > sax.maxProfileImageSize) return sax.doAlert(sax.dlg.title.uploadOrganisation, sax.msg.uploadFileSizeMax.format(sax.formatFileSize(sax.maxProfileOrgData)));
|
||||
if ((sax.data.orgUploadContentTypes || []).indexOf(file.type) < 0) return sax.doAlert(sax.dlg.title.imageUpload, sax.msg.uploadFileTypeInvalid.format(sax.getFileType(file)));
|
||||
if ($ctrl.file.length) $ctrl.file[0].files = files;
|
||||
sax.clearControlError($ctrl.file);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
ou.uploadOrgData = function ()
|
||||
{
|
||||
ou.ajax.upload = ou.ajax.upload || { url: sax.url.base + 'Organisation/Ajax/Upload', callbackFn: ou.onUploadOrgData };
|
||||
ou.ajax.upload.formData = new FormData($frm.orgUpl[0]);
|
||||
sax.doAjaxRequest(ou.ajax.upload, 50);
|
||||
}
|
||||
|
||||
ou.onUploadOrgData = function (response)
|
||||
{
|
||||
//sax.debug('onUploadOrgData', response);
|
||||
sax.refreshControlValues(response.controlValues, $frm.org);
|
||||
if (!response.success) return;
|
||||
|
||||
$dlg.orgUpl.dialog('close');
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
$(function ()
|
||||
{
|
||||
// Organisation Upload dialog and form.
|
||||
var opt = sax.dlgOpts();
|
||||
opt.buttons[sax.lbl.upload] = function () { ou.uploadOrgData(); };
|
||||
opt.buttons[sax.dlg.btn.cancel] = function () { $(this).dialog('close'); };
|
||||
$dlg.orgUpl = $('#dlgOrgUpload').dialog(opt);
|
||||
$frm.orgUpl = $('#frmOrgUpload', $dlg.orgUpl);
|
||||
$ctrl.file = $('input.OrganisationDataFile[type="file"]', $frm.orgUpl);
|
||||
$frm.orgUpl.on('input', '.sax-input, .sax-textarea', function () { sax.clearControlError(this); }).on('change', '.sax-select', function () { sax.clearControlError(this); });
|
||||
|
||||
// Organisation data file drop area.
|
||||
$pnl.orgLogoImgDrop = $('.sax-panel-drop.OrgDataFileDrop', $dlg.orgUpl)
|
||||
.on('dragenter', function (evt) { sax.haltEvent(evt); })
|
||||
.on('dragover', function (evt) { sax.haltEvent(evt); if (!$pnl.orgLogoImgDrop.hasClass(ou.classFileDrag)) $pnl.orgLogoImgDrop.addClass(ou.classFileDrag); })
|
||||
.on('dragleave', function (evt) { sax.haltEvent(evt); $pnl.orgLogoImgDrop.removeClass(ou.classFileDrag); })
|
||||
.on('drop', function (evt) { sax.haltEvent(evt); $pnl.orgLogoImgDrop.removeClass(ou.classFileDrag); ou.onDropOrgDataFile(evt); });
|
||||
|
||||
});
|
||||
|
||||
//--------------------------------------------------------------
|
||||
}(window, window.document));
|
||||
|
||||
/* The End */
|
||||
@@ -32,11 +32,14 @@
|
||||
op.data.contactMethods = response.contactMethods;
|
||||
op.data.defaultStatusCode = response.defaultStatusCode;
|
||||
sax.populateSelectCodeDesc('#cbOrganisationStatus', response.statuses);
|
||||
sax.data.orgUploadContentTypes = response.uploadContentTypes;
|
||||
// Menu.
|
||||
var $bgr = $('.sax-burger', $pnl.filter).hide();
|
||||
var $mnu = $('ul.sax-dropdown-menu', $bgr).empty();
|
||||
$mnu.append(op.getFilterMenuOption(sax.lbl.refresh, function () { op.refreshResults(); }, 'sax-refresh'));
|
||||
$mnu.append(op.getFilterMenuOption(sax.lbl.create, function () { op.createItem(); }, 'sax-add'));
|
||||
$mnu.append(op.getFilterMenuOption(sax.lbl.download, function () { sax.downloadOrganisationData(); }, 'sax-download'));
|
||||
$mnu.append(op.getFilterMenuOption(sax.lbl.upload, function () { sax.uploadOrganisationData(); }, 'sax-upload'));
|
||||
$mnu.append(op.getFilterMenuOption(sax.lbl.refresh, function () { op.refreshResults(); }, 'sax-refresh'));
|
||||
$bgr.toggle(!!$('.sax-dropdown-item', $mnu).length);
|
||||
// Items.
|
||||
var items = response.organisations;
|
||||
|
||||
@@ -17,7 +17,16 @@ namespace Saxonite.Net.Core.Web.Online.App
|
||||
//-------------------------------------------------------------------
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
CreateHostBuilder(args).Build().Run();
|
||||
try
|
||||
{
|
||||
CreateHostBuilder(args).Build().Run();
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Cleanup - globals, async processes etc.
|
||||
if (SaxApplication_Online.AppInstance != null)
|
||||
SaxApplication_Online.AppInstance.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
@@ -44,29 +44,43 @@ namespace Saxonite.Net.Core.Web.Online.App
|
||||
try
|
||||
{
|
||||
AppInstance = this;
|
||||
SaxGlobals.App = this;
|
||||
SaxGlobals.System = (System_Web = new SaxSystem_Web());
|
||||
Configuration = configuration;
|
||||
ConsoleHelper_Web = new SaxConsoleHelper_WebOnline(this);
|
||||
ConsoleHelper_Online = new SaxConsoleHelper_Online(this);
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
SaLogger.Error(GetType().Name + ".CTR " + ExceptionUtil.GetErrorStateMessage(exc));
|
||||
throw exc;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
// Clear globals.
|
||||
AppInstance = null;
|
||||
// Console helper.
|
||||
if (ConsoleHelper_Online!= null)
|
||||
ConsoleHelper_Online.Dispose();
|
||||
ConsoleHelper_Online= null;
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
// Globals.
|
||||
public static SaxApplication_Online AppInstance { get; private set; }
|
||||
public override SaxConsoleHelper ConsoleHelper { get { return ConsoleHelper_Online; } }
|
||||
public SaxConsoleHelper_Online ConsoleHelper_Online { get; private set; }
|
||||
// Database.
|
||||
public override ISacsDatabase GetDatabase(SaxSessionContext sessionContext, Sax.Database databaseType)
|
||||
{
|
||||
return sessionContexts.GetValue(sessionContext.Index, null)?.Databases.GetValue(databaseType, null) ?? null;
|
||||
}
|
||||
public override String SessionCookieName { get { return Sax.Config.Online.Session.Cookie.Name; } }
|
||||
// Configuration.
|
||||
public override SaxAppConfig AppConfig { get { return appConfigs.Values.ToList().getConfigForApplication(); } }
|
||||
public override SaxEmailConfig EmailConfig { get { return emailConfigs.Values.ToList().getConfigForSession(AppConfig); } }
|
||||
public override String SessionCookieName { get { return Sax.Config.Online.Session.Cookie.Name; } }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Initialisation.
|
||||
|
||||
+17
-2
@@ -10,7 +10,7 @@ using System.Threading.Tasks;
|
||||
namespace Saxonite.Net.Core.Web.Online.Consoles
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaxConsoleHelper_WebOnline : SaxConsoleHelper_Web
|
||||
public class SaxConsoleHelper_Online : SaxConsoleHelper_Web
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
@@ -18,10 +18,25 @@ namespace Saxonite.Net.Core.Web.Online.Consoles
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// construction.
|
||||
public SaxConsoleHelper_WebOnline(SaxApplication_Online app)
|
||||
public SaxConsoleHelper_Online(SaxApplication_Online app)
|
||||
{
|
||||
this.app = app;
|
||||
}
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
// Data cache consoles.
|
||||
foreach (SaxDataCacheConsole_Online dataCacheConsole in dataCacheConsoles.Values)
|
||||
dataCacheConsole.Dispose();
|
||||
dataCacheConsoles.Clear();
|
||||
// Session data consoles.
|
||||
foreach (SaxSessionDataConsole_Online sessionDataConsole in sessionDataConsoles.Values)
|
||||
sessionDataConsole.Dispose();
|
||||
sessionDataConsoles.Clear();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Data cache console.
|
||||
@@ -1,4 +1,5 @@
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sacs.Web.Components;
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
using Sarand.Net.Standard.Base.Helpers;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
@@ -172,7 +173,7 @@ namespace Saxonite.Net.Core.Web.Online.Models
|
||||
return new SysId();
|
||||
if (StringUtil.IsNumeric(encryptedId))
|
||||
return encryptedId.ToSysId();
|
||||
NameValueCollection idObfuscationParams = SaxController_Base.DecryptParameters(encryptedId, Base64IV_IdObfuscation, Base64Key_IdObfuscation);
|
||||
NameValueCollection idObfuscationParams = SaController.DecryptParameters(encryptedId, Base64IV_IdObfuscation, Base64Key_IdObfuscation);
|
||||
return idObfuscationParams.Get(ParamName_IdObfuscation_Id).ToSysId();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<CopyRefAssembliesToPublishDirectory>false</CopyRefAssembliesToPublishDirectory>
|
||||
<RootNamespace>Saxonite.Net.Core.Web</RootNamespace>
|
||||
<AssemblyName>Saxonite.Net.Core.Web</AssemblyName>
|
||||
@@ -9,7 +9,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="jQuery.UI.Combined" Version="1.12.1" />
|
||||
<PackageReference Include="jQuery.UI.Combined" Version="1.13.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="3.1.16" />
|
||||
<PackageReference Include="System.Collections.Specialized" Version="4.3.0" />
|
||||
</ItemGroup>
|
||||
@@ -23,11 +23,6 @@
|
||||
<ProjectReference Include="..\SaxoniteStandardDbas\SaxoniteStandardDbas.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Online\Core\" />
|
||||
<Folder Include="Online\Data\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Update="appsettings.Machine.Sarand602.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
|
||||
@@ -88,6 +88,7 @@
|
||||
sax.msg.mandatoryValue = '@Localiser.GetJavascriptText("msg.validation.mandatory.value")';
|
||||
sax.msg.invalidValue = '@Localiser.GetJavascriptText("msg.validation.invalid.value")';
|
||||
sax.maxProfileImageSize = 2 * 10 ** 6;
|
||||
sax.maxProfileDataFileSize = 2 * 10 ** 9;
|
||||
sax.session.cookieName = '@Model.SessionCookieName';
|
||||
sax.awaitingLogin = @awaitingLogin;
|
||||
sax.kli.active = @keepLoggedIn;
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Saxonite.Net.Standard.Base.App
|
||||
//-------------------------------------------------------------------
|
||||
public static class Version
|
||||
{
|
||||
private static String version { get; } = "1.2.11.1";
|
||||
private static String version { get; } = "1.2.11.2";
|
||||
// Retrieve version.
|
||||
public static String GetFullVersion () { return version; }
|
||||
public static String GetAppVersion ()
|
||||
@@ -41,7 +41,7 @@ namespace Saxonite.Net.Standard.Base.App
|
||||
// Version history.
|
||||
//-------------------------------------------------------------------
|
||||
// 1.2.11 6-Jul-2023
|
||||
// - Organisation associations.
|
||||
// - Organisation associations, admin download [Feb24].
|
||||
// 1.2.10 11-Oct-2022
|
||||
// - Online organisations display issue fixed.
|
||||
// - User Sport 'Preparing' options.
|
||||
|
||||
@@ -4,22 +4,33 @@ using Saxonite.Net.Standard.Base.App;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
|
||||
namespace Saxonite.Net.Standard.Base.App
|
||||
{
|
||||
//=======================================================================
|
||||
public abstract class SaxApplication_Base
|
||||
public abstract class SaxApplication_Base : SacsDisposable
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Protected construction.
|
||||
protected SaxApplication_Base()
|
||||
{
|
||||
App = this;
|
||||
}
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
App = null;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
// Globals.
|
||||
public static SaxApplication_Base App { get; private set; }
|
||||
public abstract SaxSystem System { get; }
|
||||
public abstract SaxConsoleHelper ConsoleHelper { get; }
|
||||
// Database.
|
||||
public abstract ISacsDatabase GetDatabase(SaxSessionContext sessionContext, Sax.Database databaseType);
|
||||
public abstract IDatabaseInfo CreateDbInfo(SaxSessionContext sessionContext, Sax.Database databaseType);
|
||||
// Application instance.
|
||||
|
||||
@@ -10,11 +10,11 @@ namespace Saxonite.Net.Standard.Base.App
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// System.
|
||||
public static SaxSystem System { get; set; }
|
||||
public static SaxSystem System { get { return App.System; } }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Application.
|
||||
public static SaxApplication_Base App { get; set; }
|
||||
public static SaxApplication_Base App { get { return SaxApplication_Base.App; } }
|
||||
public static SaxConsoleHelper ConsoleHelper { get { return App.ConsoleHelper; } }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Saxonite.Net.Standard.Base.App;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Saxonite.Net.Standard.Base.App;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
@@ -6,13 +7,16 @@ using System.Text;
|
||||
namespace Saxonite.Net.Standard.Base.Consoles
|
||||
{
|
||||
//=======================================================================
|
||||
public abstract class SaxConsoleHelper
|
||||
public abstract class SaxConsoleHelper : SacsDisposable
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Protected construction.
|
||||
protected SaxConsoleHelper()
|
||||
{
|
||||
}
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Data cache console.
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
using Saxonite.Net.Standard.Base.App;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Saxonite.Net.Standard.Base.Consoles
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaxProcessConsole : SaErrorStateItem
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
private SaxInternals internals = null;
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
protected SaxProcessConsole(SaxSessionContext sessionContext)
|
||||
{
|
||||
SessionContext = sessionContext;
|
||||
}
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
if (internals != null) internals.Dispose(); internals = null;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
protected SaxSessionContext SessionContext { get; }
|
||||
protected SaxInternals Internals { get { if (internals == null) internals = new SaxInternals(SessionContext); return internals; } }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using NPOI.SS.Formula.Functions;
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Dbas;
|
||||
@@ -255,23 +256,35 @@ namespace Saxonite.Net.Standard.Base.Mgr
|
||||
//-----------------------------------------------------------
|
||||
// Organisation type.
|
||||
case SaxOrganisation.Column.OrganisationType_Desc:
|
||||
String organisationType = values.GetValue(column.DataName).ToString();
|
||||
// ToDo Translate organisation type.
|
||||
value = new DataValue();
|
||||
{
|
||||
String organisationTypeCode = values.GetValue(column.DataName).ToString();
|
||||
TypeCodeDesc organisationType = OrganisationTypeCodes.Find(item => item.Code.Equals(organisationTypeCode));
|
||||
if (!StringUtil.IsBlank(organisationType?.Desc ?? ""))
|
||||
value = new DataValue(organisationType.Desc);
|
||||
else
|
||||
value = new DataValue(organisationTypeCode);
|
||||
}
|
||||
break;
|
||||
|
||||
//-----------------------------------------------------------
|
||||
// Organisation category.
|
||||
case SaxOrganisation.Column.OrganisationCategory_Desc:
|
||||
String organisationCategory = values.GetValue(column.DataName).ToString();
|
||||
// ToDo Translate organisation category.
|
||||
value = new DataValue();
|
||||
{
|
||||
String organisationCategoryCode = values.GetValue(column.DataName).ToString();
|
||||
TypeCodeDesc organisationCategory = OrganisationCategoryCodes.Find(item => item.Code.Equals(organisationCategoryCode));
|
||||
if (!StringUtil.IsBlank(organisationCategory?.Desc ?? ""))
|
||||
value = new DataValue(organisationCategory.Desc);
|
||||
else
|
||||
value = new DataValue(organisationCategoryCode);
|
||||
}
|
||||
break;
|
||||
|
||||
//-----------------------------------------------------------
|
||||
// Notes - limit to 200 chars.
|
||||
case SaxOrganisation.Column.Notes:
|
||||
value = new DataValue(SacsHierarchyItem.FormatForDisplay(values.GetValue(column.DataName).ToString(), 200));
|
||||
{
|
||||
value = new DataValue(SacsHierarchyItem.FormatForDisplay(values.GetValue(column.DataName).ToString(), 200));
|
||||
}
|
||||
break;
|
||||
|
||||
//-----------------------------------------------------------
|
||||
@@ -288,7 +301,13 @@ namespace Saxonite.Net.Standard.Base.Mgr
|
||||
}
|
||||
break;
|
||||
|
||||
//-----------------------------------------------------------
|
||||
//-----------------------------------------------------------
|
||||
default:
|
||||
{
|
||||
value = values.GetValue(column.DataName);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -124,7 +124,11 @@ namespace Saxonite.Net.Standard.Base.Mgr
|
||||
}
|
||||
break;
|
||||
|
||||
//-----------------------------------------------------------
|
||||
//-----------------------------------------------------------
|
||||
default:
|
||||
value = values.GetValue(column.DataName);
|
||||
break;
|
||||
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -242,7 +242,11 @@ namespace Saxonite.Net.Standard.Base.Mgr
|
||||
}
|
||||
break;
|
||||
|
||||
//-----------------------------------------------------------
|
||||
//-----------------------------------------------------------
|
||||
default:
|
||||
value = values.GetValue(column.DataName);
|
||||
break;
|
||||
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -117,6 +117,10 @@ namespace Saxonite.Net.Standard.Base.Mgr
|
||||
break;
|
||||
|
||||
//-----------------------------------------------------------
|
||||
default:
|
||||
value = values.GetValue(column.DataName);
|
||||
break;
|
||||
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -325,7 +325,11 @@ namespace Saxonite.Net.Standard.Base.Mgr
|
||||
}
|
||||
break;
|
||||
|
||||
//-----------------------------------------------------------
|
||||
//-----------------------------------------------------------
|
||||
default:
|
||||
value = values.GetValue(column.DataName);
|
||||
break;
|
||||
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -235,6 +235,10 @@ namespace Saxonite.Net.Standard.Base.Mgr
|
||||
break;
|
||||
|
||||
//-----------------------------------------------------------
|
||||
default:
|
||||
value = values.GetValue(column.DataName);
|
||||
break;
|
||||
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -110,6 +110,10 @@ namespace Saxonite.Net.Standard.Base.Mgr
|
||||
break;
|
||||
|
||||
//-----------------------------------------------------------
|
||||
default:
|
||||
value = values.GetValue(column.DataName);
|
||||
break;
|
||||
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -267,7 +267,11 @@ namespace Saxonite.Net.Standard.Base.Mgr
|
||||
}
|
||||
break;
|
||||
|
||||
//-----------------------------------------------------------
|
||||
//-----------------------------------------------------------
|
||||
default:
|
||||
value = values.GetValue(column.DataName);
|
||||
break;
|
||||
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -256,7 +256,11 @@ namespace Saxonite.Net.Standard.Base.Mgr
|
||||
}
|
||||
break;
|
||||
|
||||
//-----------------------------------------------------------
|
||||
//-----------------------------------------------------------
|
||||
default:
|
||||
value = values.GetValue(column.DataName);
|
||||
break;
|
||||
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -180,7 +180,11 @@ namespace Saxonite.Net.Standard.Base.Mgr
|
||||
}
|
||||
break;
|
||||
|
||||
//-----------------------------------------------------------
|
||||
//-----------------------------------------------------------
|
||||
default:
|
||||
value = values.GetValue(column.DataName);
|
||||
break;
|
||||
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -191,7 +191,11 @@ namespace Saxonite.Net.Standard.Base.Mgr
|
||||
}
|
||||
break;
|
||||
|
||||
//-----------------------------------------------------------
|
||||
//-----------------------------------------------------------
|
||||
default:
|
||||
value = values.GetValue(column.DataName);
|
||||
break;
|
||||
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -256,7 +256,11 @@ namespace Saxonite.Net.Standard.Base.Mgr
|
||||
}
|
||||
break;
|
||||
|
||||
//-----------------------------------------------------------
|
||||
//-----------------------------------------------------------
|
||||
default:
|
||||
value = values.GetValue(column.DataName);
|
||||
break;
|
||||
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -249,7 +249,11 @@ namespace Saxonite.Net.Standard.Base.Mgr
|
||||
}
|
||||
break;
|
||||
|
||||
//-----------------------------------------------------------
|
||||
//-----------------------------------------------------------
|
||||
default:
|
||||
value = values.GetValue(column.DataName);
|
||||
break;
|
||||
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -235,7 +235,11 @@ namespace Saxonite.Net.Standard.Base.Mgr
|
||||
}
|
||||
break;
|
||||
|
||||
//-----------------------------------------------------------
|
||||
//-----------------------------------------------------------
|
||||
default:
|
||||
value = values.GetValue(column.DataName);
|
||||
break;
|
||||
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -172,7 +172,11 @@ namespace Saxonite.Net.Standard.Base.Mgr
|
||||
}
|
||||
break;
|
||||
|
||||
//-----------------------------------------------------------
|
||||
//-----------------------------------------------------------
|
||||
default:
|
||||
value = values.GetValue(column.DataName);
|
||||
break;
|
||||
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -262,7 +262,11 @@ namespace Saxonite.Net.Standard.Base.Mgr
|
||||
}
|
||||
break;
|
||||
|
||||
//-----------------------------------------------------------
|
||||
//-----------------------------------------------------------
|
||||
default:
|
||||
value = values.GetValue(column.DataName);
|
||||
break;
|
||||
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -203,7 +203,11 @@ namespace Saxonite.Net.Standard.Base.Mgr
|
||||
}
|
||||
break;
|
||||
|
||||
//-----------------------------------------------------------
|
||||
//-----------------------------------------------------------
|
||||
default:
|
||||
value = values.GetValue(column.DataName);
|
||||
break;
|
||||
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -221,7 +221,11 @@ namespace Saxonite.Net.Standard.Base.Mgr
|
||||
}
|
||||
break;
|
||||
|
||||
//-----------------------------------------------------------
|
||||
//-----------------------------------------------------------
|
||||
default:
|
||||
value = values.GetValue(column.DataName);
|
||||
break;
|
||||
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -181,7 +181,11 @@ namespace Saxonite.Net.Standard.Base.Mgr
|
||||
}
|
||||
break;
|
||||
|
||||
//-----------------------------------------------------------
|
||||
//-----------------------------------------------------------
|
||||
default:
|
||||
value = values.GetValue(column.DataName);
|
||||
break;
|
||||
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -209,7 +209,11 @@ namespace Saxonite.Net.Standard.Base.Mgr
|
||||
}
|
||||
break;
|
||||
|
||||
//-----------------------------------------------------------
|
||||
//-----------------------------------------------------------
|
||||
default:
|
||||
value = values.GetValue(column.DataName);
|
||||
break;
|
||||
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -195,7 +195,11 @@ namespace Saxonite.Net.Standard.Base.Mgr
|
||||
}
|
||||
break;
|
||||
|
||||
//-----------------------------------------------------------
|
||||
//-----------------------------------------------------------
|
||||
default:
|
||||
value = values.GetValue(column.DataName);
|
||||
break;
|
||||
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -179,7 +179,11 @@ namespace Saxonite.Net.Standard.Base.Mgr.Support
|
||||
}
|
||||
break;
|
||||
|
||||
//-----------------------------------------------------------
|
||||
//-----------------------------------------------------------
|
||||
default:
|
||||
value = values.GetValue(column.DataName);
|
||||
break;
|
||||
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
using Sarand.Net.Standard.Proc.Procs;
|
||||
using Saxonite.Net.Standard.Base.Mgr.Support;
|
||||
using Saxonite.Net.Standard.Base.Mgr;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Saxonite.Net.Standard.Base.App;
|
||||
|
||||
namespace Saxonite.Net.Standard.Base.Procs
|
||||
{
|
||||
//=======================================================================
|
||||
public abstract class SaxProcess_Base : SaProcess
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Definitions.
|
||||
public new class Config : SaProcess.Config
|
||||
{
|
||||
protected Config(SaxSessionContext sessionContext) : base()
|
||||
{
|
||||
SessionContext = sessionContext;
|
||||
}
|
||||
public SaxSessionContext SessionContext { get; }
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
private SaxInternals internals;
|
||||
private Config config;
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
protected SaxProcess_Base(Config config) : base(config)
|
||||
{
|
||||
this.config = config;
|
||||
}
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
if (internals != null) internals.Dispose();
|
||||
internals = null;
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
public SaxInternals Internals { get { if (internals == null) internals = new SaxInternals(config.SessionContext); return internals; } }
|
||||
// Managers.
|
||||
public SaxReferenceMgr ReferenceMgr { get { return Internals.ReferenceMgr; } }
|
||||
public SaxAccountMgr AccountMgr { get { return Internals.AccountMgr; } }
|
||||
public SaxActivityMgr ActivityMgr { get { return Internals.ActivityMgr; } }
|
||||
public SaxItemDataMgr ItemDataMgr { get { return Internals.ItemDataMgr; } }
|
||||
public SaxSupportMgr SupportMgr { get { return Internals.SupportMgr; } }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -1,12 +1,13 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<RootNamespace>Saxonite.Net.Standard</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\Common-VS\Workspace\SacsStandardBase\SacsStandardBase.csproj" />
|
||||
<ProjectReference Include="..\..\..\Common-VS\Workspace\SacsStandardProc\SacsStandardProc.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -290,7 +290,7 @@ namespace Saxonite.Net.Standard.Dbas.Mgr
|
||||
columnDfn.ReadOnly = true;
|
||||
break;
|
||||
case SaxOrganisation.Column.Name:
|
||||
SetOrganisationColDfn(columnDfn, "Name", 120, SaxDbDfn_Core.ColumnIdx.Organisation_Name);
|
||||
SetOrganisationColDfn(columnDfn, "Name", 180, SaxDbDfn_Core.ColumnIdx.Organisation_Name);
|
||||
break;
|
||||
case SaxOrganisation.Column.OrganisationType:
|
||||
SetOrganisationColDfn(columnDfn, "Type", 80, SaxDbDfn_Core.ColumnIdx.Organisation_OrganisationType, ColumnAlignment.Center, DataValue.DataType.String);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<RootNamespace>Saxonite.Net.Standard</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<RootNamespace>Saxonite.Net.Standard</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user