This commit is contained in:
2021-11-01 18:14:21 +00:00
parent ea61d37840
commit 806ebb4024
34 changed files with 766 additions and 411 deletions
+1 -1
View File
@@ -55,7 +55,7 @@ namespace Saxonite.Net.Core.Web.Base.App
try
{
if (StringUtil.IsEmpty(ComputerName))
ComputerName = Environment.GetEnvironmentVariable("CUMPUTERNAME") ?? Environment.GetEnvironmentVariable("HOSTNAME");
ComputerName = Environment.GetEnvironmentVariable("COMPUTERNAME") ?? Environment.GetEnvironmentVariable("HOSTNAME");
}
catch (Exception exc)
{
@@ -69,6 +69,7 @@ namespace Saxonite.Net.Core.Web.Admin.App
//-------------------------------------------------------------------
// Properties.
public static SaxApplication_Admin AppInstance { get; private set; }
public List<String> Messages { get; } = new List<String>();
public override ISacsDatabase GetCoreDatabase(SaxSessionContext sessionContext)
{
return sessionContexts.GetValue(sessionContext.Index, null)?.CoreDatabase;
@@ -106,6 +107,9 @@ namespace Saxonite.Net.Core.Web.Admin.App
.AddEnvironmentVariables();
SaxConfiguration = builder.Build();
//Messages.Add($"Host: {SaxSystem.ComputerName}");
//Messages.Add($"Config file: appsettings.machine.{SaxSystem.ComputerName}.json");
// Application configuration.
appConfigs = SaxAppConfigHelper.ExtractAppConfigs(SaxConfiguration.GetSection("AppConfigs"));
emailConfigs = SaxEmailConfigHelper.ExtractEmailConfigs(SaxConfiguration.GetSection("EmailConfigs"));
@@ -127,6 +131,9 @@ namespace Saxonite.Net.Core.Web.Admin.App
SaLogger.LogFolder = LoggingRootFolder;
LogApplicationStart(fn);
//Messages.Add($"Database location: {AppConfig.CoreDatabase.Location}");
//Messages.Add($"LoggingRootFolder: {SaLogger.LogFolder}");
// Configure database connection.
SacsDatabaseConsole.OdbcConfig config = new SacsDatabaseConsole.OdbcConfig();
config.location = AppConfig.CoreDatabase.Location;
@@ -136,6 +143,11 @@ namespace Saxonite.Net.Core.Web.Admin.App
if (coreDatabase.HasErrorState())
SaLogger.Warn(fn + " Database initialisation error: " + coreDatabase.ErrorStateMessage);
//Messages.Add($"Database location: {AppConfig.CoreDatabase.Location}");
//Messages.Add($"LoggingRootFolder: {SaLogger.LogFolder}");
//Messages.Add($"OdbcDrivers: {OdbcUtil.GetOdbcDriverNames().Concat(", ")}");
//Messages.Add($"DbConnection: {coreDatabase.ConnectionString}");
// Session context - only one context available/necessary (for now).
SessionContextData sessionContextData = new SessionContextData(new SaxSessionContext_Web(100, Sax.Application.Admin));
sessionContextData.CoreDatabase = coreDatabase;
@@ -181,9 +181,7 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
// Activate awaiting members and send welcome email to each.
foreach (OrganisationMemberData organisationMember in organisationMembersToActivate)
{
// Ensure that User Organisation has 'Member Admin' role.
if (organisationMember.UserOrganisation == null) continue;
organisationMember.UserOrganisation.AddOrganisationRole(Sax.OrganisationRole.MemberAdmin);
if (AccountMgr.UpdateUserOrganisation(organisationMember.UserOrganisation, DbUpdateInfo))
{
if (organisationMember.UserAccount == null) continue;
@@ -159,6 +159,12 @@
<data name="label.any" xml:space="preserve">
<value>Any</value>
</data>
<data name="label.assigned" xml:space="preserve">
<value>Assigned</value>
</data>
<data name="label.available" xml:space="preserve">
<value>Available</value>
</data>
<data name="label.cancel" xml:space="preserve">
<value>Cancel</value>
</data>
@@ -0,0 +1,113 @@
{
"$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"metadata": {
"_dependencyType": "appService.windows"
},
"parameters": {
"resourceGroupName": {
"type": "string",
"defaultValue": "Sportierre",
"metadata": {
"description": "Name of the resource group for the resource. It is recommended to put resources under same resource group for better tracking."
}
},
"resourceGroupLocation": {
"type": "string",
"defaultValue": "westeurope",
"metadata": {
"description": "Location of the resource group. Resource groups could have different location than resources, however by default we use API versions from latest hybrid profile which support all locations for resource types we support."
}
},
"resourceName": {
"type": "string",
"defaultValue": "SportierreAdmin",
"metadata": {
"description": "Name of the main resource to be created by this template."
}
},
"resourceLocation": {
"type": "string",
"defaultValue": "[parameters('resourceGroupLocation')]",
"metadata": {
"description": "Location of the resource. By default use resource group's location, unless the resource provider is not supported there."
}
}
},
"variables": {
"appServicePlan_name": "[concat('Plan', uniqueString(concat(parameters('resourceName'), subscription().subscriptionId)))]",
"appServicePlan_ResourceId": "[concat('/subscriptions/', subscription().subscriptionId, '/resourceGroups/', parameters('resourceGroupName'), '/providers/Microsoft.Web/serverFarms/', variables('appServicePlan_name'))]"
},
"resources": [
{
"type": "Microsoft.Resources/resourceGroups",
"name": "[parameters('resourceGroupName')]",
"location": "[parameters('resourceGroupLocation')]",
"apiVersion": "2019-10-01"
},
{
"type": "Microsoft.Resources/deployments",
"name": "[concat(parameters('resourceGroupName'), 'Deployment', uniqueString(concat(parameters('resourceName'), subscription().subscriptionId)))]",
"resourceGroup": "[parameters('resourceGroupName')]",
"apiVersion": "2019-10-01",
"dependsOn": [
"[parameters('resourceGroupName')]"
],
"properties": {
"mode": "Incremental",
"template": {
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"location": "[parameters('resourceLocation')]",
"name": "[parameters('resourceName')]",
"type": "Microsoft.Web/sites",
"apiVersion": "2015-08-01",
"tags": {
"[concat('hidden-related:', variables('appServicePlan_ResourceId'))]": "empty"
},
"dependsOn": [
"[variables('appServicePlan_ResourceId')]"
],
"kind": "app",
"properties": {
"name": "[parameters('resourceName')]",
"kind": "app",
"httpsOnly": true,
"reserved": false,
"serverFarmId": "[variables('appServicePlan_ResourceId')]",
"siteConfig": {
"metadata": [
{
"name": "CURRENT_STACK",
"value": "dotnetcore"
}
]
}
},
"identity": {
"type": "SystemAssigned"
}
},
{
"location": "[parameters('resourceLocation')]",
"name": "[variables('appServicePlan_name')]",
"type": "Microsoft.Web/serverFarms",
"apiVersion": "2015-08-01",
"sku": {
"name": "S1",
"tier": "Standard",
"family": "S",
"size": "S1"
},
"properties": {
"name": "[variables('appServicePlan_name')]"
}
}
]
}
}
}
]
}
@@ -1,60 +1,65 @@
@model SaxModel_Admin
@inject SaxLocaliser Localiser
<link rel="stylesheet" href="~/css/sax-selectCode.css?@Model.HrefVersion" />
<script src="~/js/sax-selectCode.js?@Model.HrefVersion"></script>
<script type="text/javascript">
</script>
<link rel="stylesheet" href="~/css/sax-selectCode.css?@Model.HrefVersion" />
<script src="~/js/sax-selectCode.js?@Model.HrefVersion"></script>
<script type="text/javascript">
</script>
<div id="dlgSelectCode" class="sax-dialog sax-form">
<div id="dlgSelectCode" class="sax-dialog sax-form">
@* Filter *@
<div class="">
@* Filter *@
<div class="">
</div>
</div>
<div class="row h-100">
<div class="row h-100">
@* Available codes *@
<div class="col-sm-5">
@* Available codes *@
<div class="col-sm-5">
<div class="h-100 sax-selectCode-codes AvailableCodes">
</div>
</div>
@* Code selection *@
<div class="col-sm-2">
<div class="row">
<div class="col-sx-6 col-sm-12 center">
<button class="sax-button Select">@Localiser["label.select"]</button>
</div>
<div class="col-sx-6 col-sm-12 center">
<button class="sax-button Remove">@Localiser["label.remove"]</button>
</div>
</div>
</div>
@* Selected codes *@
<div class="col-sm-5">
<div class="h-100 sax-selectCode-codes SelectedCodes">
</div>
<div class="h-100 d-flex flex-column">
<div class="">@Localiser["label.available"]:</div>
<div class="spacer"></div>
<div class="sax-selectCode-codes AvailableCodes flex-grow-1 mr-1"></div>
</div>
</div>
<div class="sax-panel-item-template">
<div class="sax-panel-item Code">
<div class="CodeDesc"></div>
@* Code selection *@
<div class="col-sm-2">
<div class="spacer8"></div>
<div class="row">
<div class="col-sx-6 col-sm-12 center">
<button class="sax-button Select">@Localiser["label.select"]</button>
</div>
<div class="col-sx-6 col-sm-12 center">
<button class="sax-button Remove">@Localiser["label.remove"]</button>
</div>
</div>
</div>
@* Selected codes *@
<div class="col-sm-5">
<div class="h-100 d-flex flex-column">
<div class="">@Localiser["label.assigned"]:</div>
<div class="spacer"></div>
<div class="sax-selectCode-codes SelectedCodes flex-grow-1 ml-1"></div>
</div>
</div>
</div>
<div class="sax-panel-item-template">
<div class="sax-panel-item Code">
<div class="CodeDesc"></div>
</div>
</div>
</div>
@@ -16,12 +16,13 @@
{
@Html.HiddenFor(model => model.UserOrganisationId, new { @id = "", @class = "UserOrganisationId" })
}
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmUserEmail"}))
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmUserEmail" }))
{
<input type="hidden" id="" class="UserEmailAddress" name="UserEmailAddress" />
}
<div id="dlgMember" class="sax-dialog" title="">
<div class="spacer"></div>
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmMember", @class = "sax-form", @onSubmit = "return false;" }))
{
@Html.HiddenFor(model => model.UserOrganisationId, new { @id = "", @class = "UserOrganisationId" })
@@ -29,52 +30,77 @@
@* User email *@
<div class="sax-form-control UserEmailAddress">
<div class="sax-label">
<label for="ifMemberUserEmailAddress"><span><span class="required">*</span> @Localiser["label.email.address"]</span></label>
<div class="row">
<div class="col-sm-4">
<div class="sax-label">
<label for="ifMemberUserEmailAddress"><span>@Localiser["label.email.address"]</span>&nbsp;<span class="required">*</span></label>
</div>
</div>
<div class="col-sm">
<div class="sax-control">
@Html.TextBoxFor(model => model.MemberUserEmailAddress, new { @id = "ifMemberUserEmailAddress", @class = "MemberUserEmailAddress sax-input", @maxlength = @Model.GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.UserAccount_EmailAddress) })
</div>
<div class="sax-message"></div>
</div>
</div>
<div class="sax-control">
@Html.TextBoxFor(model => model.MemberUserEmailAddress, new { @id = "ifMemberUserEmailAddress", @class = "MemberUserEmailAddress sax-input", @maxlength = @Model.GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.UserAccount_EmailAddress) })
</div>
<div class="sax-message"></div>
</div>
@* User email *@
<div class="sax-form-control UserName">
<div class="sax-label">
<label for="ifMemberUserName"><span>@Localiser["label.name"]</span></label>
<div class="row">
<div class="col-sm-4">
<div class="sax-label">
<label for="ifMemberUserName"><span>@Localiser["label.name"]</span></label>
</div>
</div>
<div class="col-sm">
<div class="sax-control">
<input type="text" id="ifMemberUserName" class="MemberUserName sax-input" readonly="readonly" />
</div>
<div class="sax-message"></div>
</div>
</div>
<div class="sax-control">
<input type="text" id="ifMemberUserName" class="MemberUserName sax-input" readonly="readonly" />
</div>
<div class="sax-message"></div>
</div>
@* Member roles *@
<div class="sax-form-control MemberRoleCodes">
<div class="sax-label">
<label for="ifMemberRoles"><span>@Localiser["label.roles"]</span></label>
<div class="row">
<div class="col-sm-4">
<div class="sax-label">
<label for="ifMemberRoles"><span>@Localiser["label.roles"]</span></label>
</div>
</div>
<div class="col-sm">
<div class="sax-control row">
@Html.HiddenFor(model => model.MemberRoleCodes, new { @id = "ifMemberRoleCodes", @class = "MemberRoleCodes sax-input" })
<div class="col"><textarea id="ifMemberRoles" class="MemberRoles sax-input" rows="6" readonly="readonly" ondblclick="sax.selectMemberRoles()"></textarea></div>
<div class="fixed"><button id="" class="sax-button" style="min-width:auto;margin-left:4px;padding:4px 6px" onclick="sax.selectMemberRoles()">@Localiser["label.select"]</button></div>
</div>
<div class="sax-message"></div>
</div>
</div>
<div class="sax-control row">
@Html.HiddenFor(model => model.MemberRoleCodes, new { @id = "ifMemberRoleCodes", @class = "MemberRoleCodes sax-input" })
<div class="col"><textarea id="ifMemberRoles" class="MemberRoles sax-input" rows="6" readonly="readonly" ondblclick="sax.selectMemberRoles()"></textarea></div>
<div class="fixed"><button id="" class="sax-button" style="min-width:auto;margin-left:4px;padding:4px 6px" onclick="sax.selectMemberRoles()">@Localiser["label.select"]</button></div>
</div>
<div class="sax-message"></div>
</div>
@* Member status *@
<div class="sax-form-control MemberStatus">
<div class="sax-label">
<label for="cbMemberStatus"><span><span class="required">*</span> @Localiser["label.status"]</span></label>
<div class="row">
<div class="col-sm-4">
<div class="sax-label">
<label for="cbMemberStatus"><span>@Localiser["label.status"]</span>&nbsp;<span class="required">*</span></label>
</div>
</div>
<div class="col-sm">
<div class="sax-control">
<select id="cbMemberStatus" class="sax-select MemberStatus" name="MemberStatusCode"></select>
</div>
<div class="sax-message"></div>
</div>
</div>
<div class="sax-control">
<select id="cbMemberStatus" class="sax-select MemberStatus" name="MemberStatusCode"></select>
</div>
<div class="sax-message"></div>
</div>
}
<partial name="~/Views/Common/SelectCode.cshtml" />
<div class="spacer"></div>
</div>
<partial name="~/Views/Common/SelectCode.cshtml" />
@@ -41,7 +41,7 @@
<div class="row">
<div class="col-sm-4"></div>
<div class="col-sm">
<div class="col-sm-4">
@* Organisation category *@
<div class="sax-form-control OrganisationCategory pr4">
@@ -56,7 +56,7 @@
</div>
<div class="col-sm-6">
<div class="col-sm-4">
@* Organisation type *@
<div class="sax-form-control OrganisationType">
@@ -24,9 +24,9 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
@if (Model.ProhibitCache)
{
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />
}
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta http-equiv="Content-Script-Type" content="application/javascript" />
@@ -50,7 +50,7 @@
<link rel="stylesheet" href="~/css/sax-form.css?@Model.HrefVersion" />
@foreach (var cssFile in Model.AdditionalFiles_CSS)
{
<link rel="stylesheet" href="~/@cssFile?@Model.HrefVersion" />
<link rel="stylesheet" href="~/@cssFile?@Model.HrefVersion" />
}
@* Scripts *@
@@ -109,52 +109,52 @@
*@
@if (Model.AwaitingLogin)
{
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Policies" asp-action="Privacy">@Localiser["policies.caption.privacy"]</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Security" asp-action="">@Localiser["security.caption.signin"]</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Policies" asp-action="Privacy">@Localiser["policies.caption.privacy"]</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Security" asp-action="">@Localiser["security.caption.signin"]</a>
</li>
}
else
{
<li class="nav-item dropdown">
<a class="nav-link text-dark dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
@Localiser["label.reference"]
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
<div class="dropdown-item text-dark sax-action" onclick="sax.goToPage('Sport');">@Localiser["sport.caption.sports"]</div>
<div class="dropdown-item text-dark sax-action" onclick="sax.goToPage('Region');">@Localiser["region.caption.regions"]</div>
</div>
</li>
<li class="nav-item dropdown">
<a class="nav-link text-dark dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
@Localiser["label.accounts"]
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
<div class="dropdown-item text-dark sax-action" onclick="sax.goToPage('User');">@Localiser["user.caption.users"]</div>
<div class="dropdown-item text-dark sax-action" onclick="sax.goToPage('Organisation');">@Localiser["organisation.caption.organisations"]</div>
</div>
</li>
<li class="nav-item dropdown">
<a class="nav-link text-dark dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
@Localiser["label.system"]
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
<div class="dropdown-item text-dark sax-action" onclick="sax.goToPage('System/Database');">@Localiser["label.database"]</div>
<div class="dropdown-item text-dark sax-action" onclick="sax.goToPage('System/Logs');">@Localiser["label.logs"]</div>
</div>
</li>
<li class="nav-item dropdown">
<a class="nav-link text-dark dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
@Localiser["label.security"]
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
<div class="dropdown-item text-dark sax-action" onclick="sax.navigateTo('Security/ChangePassword');">@Localiser["security.caption.change.password"]</div>
<div class="dropdown-divider"></div>
<div class="dropdown-item text-dark sax-action" onclick="sax.onSignOut();">@Localiser["security.caption.signout"]</div>
</div>
</li>
<li class="nav-item dropdown">
<a class="nav-link text-dark dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
@Localiser["label.reference"]
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
<div class="dropdown-item text-dark sax-action" onclick="sax.goToPage('Sport');">@Localiser["sport.caption.sports"]</div>
<div class="dropdown-item text-dark sax-action" onclick="sax.goToPage('Region');">@Localiser["region.caption.regions"]</div>
</div>
</li>
<li class="nav-item dropdown">
<a class="nav-link text-dark dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
@Localiser["label.accounts"]
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
<div class="dropdown-item text-dark sax-action" onclick="sax.goToPage('User');">@Localiser["user.caption.users"]</div>
<div class="dropdown-item text-dark sax-action" onclick="sax.goToPage('Organisation');">@Localiser["organisation.caption.organisations"]</div>
</div>
</li>
<li class="nav-item dropdown">
<a class="nav-link text-dark dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
@Localiser["label.system"]
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
<div class="dropdown-item text-dark sax-action" onclick="sax.goToPage('System/Database');">@Localiser["label.database"]</div>
<div class="dropdown-item text-dark sax-action" onclick="sax.goToPage('System/Logs');">@Localiser["label.logs"]</div>
</div>
</li>
<li class="nav-item dropdown">
<a class="nav-link text-dark dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
@Localiser["label.security"]
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
<div class="dropdown-item text-dark sax-action" onclick="sax.navigateTo('Security/ChangePassword');">@Localiser["security.caption.change.password"]</div>
<div class="dropdown-divider"></div>
<div class="dropdown-item text-dark sax-action" onclick="sax.onSignOut();">@Localiser["security.caption.signout"]</div>
</div>
</li>
}
</ul>
</div>
@@ -164,9 +164,9 @@
@* Page caption *@
@if (!StringUtil.IsEmpty(Model.PageCaption))
{
<div class="container">
<div class="sax-page-caption">@(Model.PageCaption)</div>
</div>
<div class="container">
<div class="sax-page-caption">@(Model.PageCaption)</div>
</div>
}
</header>
@@ -181,7 +181,15 @@
@* Footer *@
<footer id="sax-page-footer" class="border-top footer text-muted">
<div class="container">
@(Model.CopyrightNotice) - @Localiser["company.name"] @(Model.InstanceVersion)
<div class="row">
<div class="col-sm">@(Model.CopyrightNotice) - @Localiser["company.name"] @(Model.InstanceVersion)</div>
<div class="fixed-sm">
<div style="padding-top:4px;font-size:.8rem;line-height:1.2;">
@* Application messages - for debugging. *@
@(new Microsoft.AspNetCore.Html.HtmlString(Saxonite.Net.Core.Web.Admin.App.SaxApplication_Admin.AppInstance.Messages.Concat("<br/>")))
</div>
</div>
</div>
</div>
</footer>
@@ -212,11 +220,11 @@
<script src="~/js/sax-main.js?@Model.HrefVersion"></script>
@foreach (var jsFile in Model.AdditionalFiles_JS)
{
<script src="~/@jsFile?@Model.HrefVersion"></script>
<script src="~/@jsFile?@Model.HrefVersion"></script>
}
@if (Model.IncludeGoogleAnalytics)
{
<partial name="~/Views/Shared/_GoogleAnalytics.cshtml" />
<partial name="~/Views/Shared/_GoogleAnalytics.cshtml" />
}
@RenderSection("Scripts", required: false)
@@ -0,0 +1,55 @@
{
"AppConfigs": {
"SAX-Prod": {
"Environments": [ "Production" ],
"Instance": "",
"URLs": {
"Online": {
"Root": "https://sportierre.com/"
}
},
"CoreDatabase": {
"Location": "MsSql:sportierre.database.windows.net\\Saxonite_Core_Demo",
"User": "dbadmin",
"Password": "azdb-sport-1970!"
},
"Security": {
"Password": {
"MinLength": 9
},
"SignIn": {
"KeepLoggedIn": {
"Allowed": true,
"CookieExpiresDays": 5
},
"PasswordRequest": {
"LinkExpiresMins": 30
}
}
},
"Email": {
"Context": "SAX-SF-Prod",
"ContactUs": {
"AddressesTo": [],
"AddressesBcc": [ "info@sportierre.com" ]
},
"Signup": {
"Activate": {
"AddressesBcc": [ "info@sportierre.com" ]
},
"Welcome": {
"AddressesBcc": [ "info@sportierre.com" ]
}
}
},
"Documents": {
"RootFolder": "D:\\Home\\Logfiles\\Application\\Saxonite\\Admin\\Docs"
},
"Logging": {
"RootFolder": "D:\\Home\\Logfiles\\Application\\Saxonite\\Admin\\Logs"
},
"Variants": [
]
}
}
}
@@ -28,7 +28,7 @@ html
{
html
{
font-size: 16px;
font-size: 14px;
}
}
@@ -6,7 +6,7 @@
{
"use strict";
let op = sax.mdl.organisations = sax.mdl.organisations || { data: {}, ajax: {} };
let $pnl = sax.$pnl, $frm = sax.$frm, $dlg = sax.$dlg;
let $pnl = op.$pnl = {}, $frm = op.$frm = {}, $dlg = op.$dlg = {};
sax.itemIdPrefix = 'Itm_';
//--------------------------------------------------------------
@@ -200,7 +200,7 @@
$('.OrganisationStatus', frm).val(sax.data.defaultStatusCode);
sax.clearControlErrors();
$dlg.organisation.dialog('option', 'title', sax.dlg.title.createOrganisation);
sax.openDialog($dlg.organisation, 600, 600);
sax.openDialog($dlg.organisation, 600, 480);
}
//--------------------------------------------------------------
@@ -228,7 +228,7 @@
$('.OrganisationStatus', frm).val(item.statusCode);
sax.clearControlErrors();
$dlg.organisation.dialog('option', 'title', sax.dlg.title.updateOrganisation);
sax.openDialog($dlg.organisation, 600, 600);
sax.openDialog($dlg.organisation, 600, 480);
}
//--------------------------------------------------------------
@@ -269,7 +269,6 @@
sax.debug('showActivationInfo', response);
if (!response.success || !response.organisation) return;
let item = response.organisation;
let $dlg = $dlg.activate;
let frm = $('#frmOrganisationActivation');
$('.OrganisationId', frm).val($('.OrganisationId', $frm.orgId).val());
let popItemValue = function (sel, val)
@@ -281,7 +280,7 @@
popItemValue('.OrganisationRegion', item.regionNameCountry);
popItemValue('.OrganisationCategory', item.categoryDesc);
popItemValue('.OrganisationAddress', item.addressSummary);
let $orgMbrs = $('.OrganisationMembers', $dlg).empty();
let $orgMbrs = $('.OrganisationMembers', $dlg.activate).empty();
let $mbrTmpl = $('.sax-panel-item-template tr.sax-item.Member');
sax.debug(response.members, $orgMbrs, $mbrTmpl);
for (let idx = 0; idx < response.members.length; idx++)
@@ -295,7 +294,7 @@
$orgMbrs.append($item);
sax.debug($item);
}
sax.openDialog($dlg, 480, 640);
sax.openDialog($dlg.activate, 480, 420);
}
sax.activateOrganisation = function ()
{
@@ -135,11 +135,7 @@
sax.clearControlErrors();
sax.member = { roleCodes: [] };
sax.$dlg.member.dialog('option', 'title', sax.dlg.title.createMember);
sax.openDialog(sax.$dlg.member, 600, 600);
}
sax.doCreateItem = function ()
{
sax.storeItem();
sax.openDialog(sax.$dlg.member, 600, 480);
}
//--------------------------------------------------------------
@@ -165,11 +161,7 @@
$('.MemberStatus', $frm).val(item.statusCode);
sax.clearControlErrors();
sax.$dlg.member.dialog('option', 'title', sax.dlg.title.updateMember);
sax.openDialog(sax.$dlg.member, 600, 600);
}
sax.doUpdateItem = function ()
{
sax.storeItem();
sax.openDialog(sax.$dlg.member, 600, 480);
}
//--------------------------------------------------------------
@@ -208,7 +200,7 @@
$('#ifMemberUserEmailAddress', sax.$frm.member).on('change', function () { sax.onChangeEmail(); });
var opt = sax.dlgOpts();
opt.buttons[sax.dlg.btn.ok] = function () { sax.doCreateItem(); };
opt.buttons[sax.dlg.btn.ok] = function () { sax.storeItem(); };
opt.buttons[sax.dlg.btn.cancel] = function () { $(this).dialog('close'); };
sax.$dlg.member = $('#dlgMember').dialog(opt);
@@ -101,10 +101,6 @@
sax.$dlg.region.dialog('option', 'title', sax.dlg.title.createRegion);
sax.openDialog(sax.$dlg.region, 600, 600);
}
sax.doCreateItem = function ()
{
sax.storeItem();
}
//--------------------------------------------------------------
sax.updateItem = function (id)
@@ -131,10 +127,6 @@
sax.$dlg.region.dialog('option', 'title', sax.dlg.title.updateRegion);
sax.openDialog(sax.$dlg.region, 600, 600);
}
sax.doUpdateItem = function ()
{
sax.storeItem();
}
//--------------------------------------------------------------
sax.storeItem = function ()
@@ -174,7 +166,7 @@
sax.$frm.region = $('#frmRegion');
var opt = sax.dlgOpts();
opt.buttons[sax.dlg.btn.ok] = function () { sax.doCreateItem(); };
opt.buttons[sax.dlg.btn.ok] = function () { sax.storeItem(); };
opt.buttons[sax.dlg.btn.cancel] = function () { $(this).dialog('close'); };
sax.$dlg.region = $('#dlgRegion').dialog(opt);
@@ -75,10 +75,6 @@
sax.$dlg.dbTable.dialog('option', 'title', sax.dlg.title.viewDatabaseTable);
sax.openDialog(sax.$dlg.dbTable, 600, 600);
}
sax.doUpdateItem = function ()
{
sax.storeItem();
}
//--------------------------------------------------------------
$(function ()
@@ -92,7 +88,7 @@
sax.$frm.dbTable = $('#frmDatabaseTable');
var opt = sax.dlgOpts();
opt.buttons[sax.dlg.btn.ok] = function () { sax.doCreateItem(); };
opt.buttons[sax.dlg.btn.ok] = function () { sax.storeItem(); };
opt.buttons[sax.dlg.btn.cancel] = function () { $(this).dialog('close'); };
sax.$dlg.dbTable = $('#dlgDatabaseTable').dialog(opt);
+3 -3
View File
@@ -210,7 +210,7 @@
sax.clearControlErrors();
sax.userAccount = { userRoleCodes: [] };
$dlg.user.dialog('option', 'title', sax.dlg.title.createUser);
sax.openDialog($dlg.user, 600, 600);
sax.openDialog($dlg.user, 600, 480);
}
//--------------------------------------------------------------
@@ -237,7 +237,7 @@
$('#ifUserRoleCodes').val(item.userRoleCodes.join(sax.data.userRoleCodeDelim));
$('.UserStatus', frm).val(item.statusCode);
$dlg.user.dialog('option', 'title', sax.dlg.title.updateUser);
sax.openDialog($dlg.user, 600, 600);
sax.openDialog($dlg.user, 600, 480);
}
//--------------------------------------------------------------
@@ -274,7 +274,7 @@
$('.RequestPasswordAdminOption', frm).toggle(item.systemAdmin);
$('input[type="checkbox"]', frm).prop('checked', false);
$dlg.emails.dialog('option', { 'title': sax.dlg.title.selectUserEmails });
sax.openDialog($dlg.emails, 600, 600);
sax.openDialog($dlg.emails, 600, 360);
}
sax.sendUserEmails = function ()
{
@@ -14,6 +14,7 @@ using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Utils;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Dbas;
using Saxonite.Net.Standard.Base.App;
namespace Saxonite.Net.Core.Web.Online.Controllers
{
@@ -35,6 +36,11 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
public String RegionName { get; set; }
public long MemberCount { get; set; }
public long OpportunityCount { get; set; }
public bool? Admin { get; set; } = null;
public bool? MemberAdmin { get; set; } = null;
public bool? OpportunitiyAdmin { get; set; } = null;
public bool? ScheduleAdmin { get; set; } = null;
public bool? ArticleAdmin { get; set; } = null;
}
private class AjaxResponse_ProfileOrganisationsData : AjaxResponse_Data
{
@@ -78,13 +84,15 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
ColumnDfn colOpportunityCount = AccountMgr.GetUserOrganisationColumnDfn(SaxUserOrganisation.Column.Organisation_Opportunity_Count);
ColumnDfn colStatus = AccountMgr.GetUserOrganisationColumnDfn(SaxUserOrganisation.Column.Status);
ColumnDfn colCreatedOn = AccountMgr.GetUserOrganisationColumnDfn(SaxUserOrganisation.Column.CreateOn_Date);
ColumnDfn colRoleCodes = AccountMgr.GetUserOrganisationColumnDfn(SaxUserOrganisation.Column.OrganisationRoleCodes);
List<ColumnDfn> columns = new List<ColumnDfn>()
{
colId, colOrganisationId , colOrganisationName,
colOrganisationSportId, colOrganisationSportName,
colOrganisationRegionId, colOrganisationRegionName,
colMemberCount, colOpportunityCount,
colStatus, colStatus, colCreatedOn
colStatus, colStatus, colCreatedOn,
colRoleCodes
};
// Sort columns.
@@ -97,6 +105,7 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
while (resultSet != null && resultSet.HasRows && resultSet.NextRecord())
{
NamedValue.Map values = resultSet.GetRecordValues();
List<String> roleCodes = StringListUtil.Split(values.GetString(colRoleCodes.DataName), ",");
ProfileOrganisationData organisationData = new ProfileOrganisationData()
{
Id = values.GetLong(colId.DataName),
@@ -108,6 +117,16 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
MemberCount = values.GetLong(colMemberCount.DataName),
OpportunityCount = values.GetLong(colOpportunityCount.DataName)
};
if (roleCodes.ContainsCI(OrganisationRoleCodes.GetCodeForType(Sax.OrganisationRole.Admin)))
organisationData.Admin = true;
if (roleCodes.ContainsCI(OrganisationRoleCodes.GetCodeForType(Sax.OrganisationRole.MemberAdmin)))
organisationData.MemberAdmin = true;
if (roleCodes.ContainsCI(OrganisationRoleCodes.GetCodeForType(Sax.OrganisationRole.OpportunityAdmin)))
organisationData.OpportunitiyAdmin = true;
if (roleCodes.ContainsCI(OrganisationRoleCodes.GetCodeForType(Sax.OrganisationRole.ScheduleAdmin)))
organisationData.ScheduleAdmin = true;
if (roleCodes.ContainsCI(OrganisationRoleCodes.GetCodeForType(Sax.OrganisationRole.ArticleAdmin)))
organisationData.ArticleAdmin = true;
responseData.Organisations.Add(organisationData);
}
}
@@ -145,7 +145,7 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
RefreshModel(model);
// Organisations that the user has rights to author articles for.
foreach (SaxAccountMgr.OrganisationIdName organisation in AccountMgr.GetOrganisationsForUserRole(userAccountId, Sax.OrganisationRole.ArticleAdmin))
foreach (SaxAccountMgr.OrganisationIdName organisation in AccountMgr.GetOrganisationsForAnyUserRole(userAccountId, new [] { Sax.OrganisationRole.Admin, Sax.OrganisationRole.ArticleAdmin }))
{
if (responseData.Organisations == null) responseData.Organisations = new List<OrganisationData>();
OrganisationData organisationData = new OrganisationData()
@@ -450,7 +450,7 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
if (SysId.IsValid(organisationId))
{
// Organisation specified - User must have Article Admin role.
if (!AccountMgr.UserHasOrganisationRole(userAccountId, organisationId, Sax.OrganisationRole.ArticleAdmin))
if (!AccountMgr.UserHasAnyOrganisationRole(userAccountId, organisationId, new [] { Sax.OrganisationRole.Admin, Sax.OrganisationRole.ArticleAdmin }))
{
SaLogger.Warn(fn + " User does not have Article Admin role for organisation." + GetLogSuffix());
return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"]));
@@ -34,7 +34,7 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
return RedirectToAction("", "");
// User must either be a Journalist or have Article Admin rights with at least one organisation.
List<SaxAccountMgr.OrganisationIdName> organisations = AccountMgr.GetOrganisationsForUserRole(SessionData.User.UserAccountId, Sax.OrganisationRole.ArticleAdmin);
List<SaxAccountMgr.OrganisationIdName> organisations = AccountMgr.GetOrganisationsForAnyUserRole(SessionData.User.UserAccountId, new [] { Sax.OrganisationRole.Admin, Sax.OrganisationRole.ArticleAdmin });
if (organisations.Count < 1 && !UserIsJournalist)
return RedirectToAction("", "");
@@ -104,17 +104,20 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
RefreshModel(model);
// Organisation.
SysId organisationId = model.ExtractSysId(model.Filter.OrganisationId);
SaxOrganisation organisation = AccountMgr.GetOrganisationById(organisationId);
if (organisation == null || !organisation.IsStatusActive)
// Record disposable items as they are created so all can be disposed when needed.
using (DisposableCollection<SacsHierarchyItem> disposableItems = new DisposableCollection<SacsHierarchyItem>())
{
SaLogger.Warn(fn + " " + (organisation == null ? "Invalid" : "Inactive") + " organisation for Member list. OrganisationId: '" + model.Filter.OrganisationId + "'");
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"]));
}
if (organisation != null)
{
// Organisation.
SysId organisationId = model.ExtractSysId(model.Filter.OrganisationId);
SaxOrganisation organisation = AccountMgr.GetOrganisationById(organisationId);
disposableItems.Add(organisation);
if (organisation == null || !organisation.IsStatusActive)
{
SaLogger.Warn(fn + " " + (organisation == null ? "Invalid" : "Inactive") + " organisation for Member list. OrganisationId: '" + model.Filter.OrganisationId + "'");
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"]));
}
// Store filter data.
SessionData_Online.Filter.SetMemberOrganisation(organisation);
@@ -124,11 +127,11 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
responseData.Titles.Add(title.Code, title.Desc);
// Reference data - member roles.
foreach (TypeCodeDesc memberRole in OrganisationRoleCodes.FindAll( item => item.Type != (int)Sax.OrganisationRole.Member))
foreach (TypeCodeDesc memberRole in OrganisationRoleCodes.FindAll(item => item.Type != (int)Sax.OrganisationRole.Member))
responseData.MemberRoles.Add(memberRole.Code, Localiser.GetOrganisationRoleCaption((Sax.OrganisationRole)memberRole.Type));
// Session User roles.
responseData.User.CanManage = AccountMgr.UserHasOrganisationRole(SessionData.User.UserAccountId, organisationId, Sax.OrganisationRole.MemberAdmin);
responseData.User.CanManage = AccountMgr.UserHasAnyOrganisationRole(SessionData.User.UserAccountId, organisation.Id, new List<Sax.OrganisationRole> { Sax.OrganisationRole.Admin, Sax.OrganisationRole.MemberAdmin });
// Item filter.
SaxUserOrganisation.Params prmMember = new SaxUserOrganisation.Params();
@@ -150,11 +153,11 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
ColumnDfn colAdminComment = responseData.User.CanManage ? AccountMgr.GetUserOrganisationColumnDfn(SaxUserOrganisation.Column.AdminComment) : new ColumnDfn(-1, "");
ColumnDfn colCreatedOn = AccountMgr.GetUserOrganisationColumnDfn(SaxUserOrganisation.Column.CreateOn_Date);
List<ColumnDfn> columns = new List<ColumnDfn>()
{
colId, colUserAccountId , colEmailAddress, colDisplayName,
colOrganisationRoleCodes, colUserStatus,
colAdminComment, colCreatedOn
};
{
colId, colUserAccountId , colEmailAddress, colDisplayName,
colOrganisationRoleCodes, colUserStatus,
colAdminComment, colCreatedOn
};
// Sort columns.
colCreatedOn.SortAscending = false;
@@ -230,9 +233,13 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
if (!SysId.IsValid(memberId))
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.specified"]));
// Retrieve item.
using (SaxUserOrganisation userOrganisation = AccountMgr.GetUserOrganisationById(memberId))
// Record disposable items as they are created so all can be disposed when needed.
using (DisposableCollection<SacsHierarchyItem> disposableItems = new DisposableCollection<SacsHierarchyItem>())
{
// Retrieve item.
SaxUserOrganisation userOrganisation = AccountMgr.GetUserOrganisationById(memberId);
disposableItems.Add(userOrganisation);
if (userOrganisation == null)
{
SaLogger.Warn(fn + " Failed to retrieve Organisation Member for Id: '" + model.MemberId + "'");
@@ -240,33 +247,31 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
}
// Validate organisation.
using (SaxOrganisation organisation = AccountMgr.GetOrganisationById(userOrganisation.OrganisationId))
SaxOrganisation organisation = AccountMgr.GetOrganisationById(userOrganisation.OrganisationId);
disposableItems.Add(organisation);
if (organisation == null || !organisation.IsStatusActive)
{
if (organisation == null || !organisation.IsStatusActive)
{
SaLogger.Warn(fn + " " + (organisation == null ? "Invalid" : "Inactive") + " Organisation for Member. Id: '" + userOrganisation.OrganisationId + "'");
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"]));
}
// Session User roles.
bool userCanManageMembers = AccountMgr.UserHasOrganisationRole(SessionData.User.UserAccountId, organisation.Id, Sax.OrganisationRole.MemberAdmin);
// Validate user account.
using (SaxUserAccount userAccount = AccountMgr.GetUserAccountById(userOrganisation.UserAccountId))
{
bool userActive = userAccount.IsStatusActive || (userAccount.IsStatusAwaiting && userCanManageMembers);
if (userAccount == null || !userActive)
{
SaLogger.Warn(fn + " " + (organisation == null ? "Invalid" : "Inactive") + " User Account for Member. Id: '" + userOrganisation.UserAccountId + "'");
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"]));
}
// Make a note of the selected Organisation.
SessionData_Online.Filter.SetMemberOrganisation(organisation);
PopulateMemberResponseData(model, userOrganisation, userAccount, organisation, responseData.Member);
}
SaLogger.Warn(fn + " " + (organisation == null ? "Invalid" : "Inactive") + " Organisation for Member. Id: '" + userOrganisation.OrganisationId + "'");
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"]));
}
// Session User roles.
bool userCanManageMembers = AccountMgr.UserHasAnyOrganisationRole(SessionData.User.UserAccountId, organisation.Id, new List<Sax.OrganisationRole> { Sax.OrganisationRole.Admin, Sax.OrganisationRole.MemberAdmin });
// Validate user account.
SaxUserAccount userAccount = AccountMgr.GetUserAccountById(userOrganisation.UserAccountId);
disposableItems.Add(userAccount);
bool userActive = userAccount.IsStatusActive || (userAccount.IsStatusAwaiting && userCanManageMembers);
if (userAccount == null || !userActive)
{
SaLogger.Warn(fn + " " + (organisation == null ? "Invalid" : "Inactive") + " User Account for Member. Id: '" + userOrganisation.UserAccountId + "'");
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"]));
}
// Make a note of the selected Organisation.
SessionData_Online.Filter.SetMemberOrganisation(organisation);
PopulateMemberResponseData(model, userOrganisation, userAccount, organisation, responseData.Member);
}
// Construct response.
@@ -361,7 +366,7 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
}
// Ensure that the user has the correct role to update Members for this organisation.
bool userCanManageMembers = AccountMgr.UserHasOrganisationRole(SessionData.User.UserAccountId, organisationId, Sax.OrganisationRole.MemberAdmin);
bool userCanManageMembers = AccountMgr.UserHasAnyOrganisationRole(SessionData.User.UserAccountId, organisationId, new List<Sax.OrganisationRole> { Sax.OrganisationRole.Admin, Sax.OrganisationRole.MemberAdmin });
if (!userCanManageMembers)
{
SaLogger.Warn(fn + " User doesn't have 'Member Admin' role for Organisation Id: " + organisationId);
@@ -385,6 +390,23 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
SaLogger.Warn(fn + " Inconsistent User Account Id specified for User Organisation. Expected: " + userOrganisation.UserAccountId + ". Found: " + userAccount.Id);
return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"]));
}
// Validate roles for current user.
if (userOrganisation.UserAccountId.Equals(SessionData.User.UserAccountId))
{
// User is modifying their own organisation member.
if (userOrganisation.CanManageOrganisation && !model.OrganisationRoleCodes.Any(item => item.Type == (int)Sax.OrganisationRole.Admin))
{
// User has removed their own 'Admin' role.
SaLogger.Warn(fn + " Unable to store member - user is attempting to remove their own 'Admin' role.");
return Json(responseData.SetMessage(messageTitle, Localiser["organisation.members.msg.remove.own.admin.role"]));
}
if (!userOrganisation.CanManageMembers)
{
SaLogger.Warn(fn + " Unable to store member - user is attempting to remove their own 'Admin' and/or 'Member Admin' role.");
return Json(responseData.SetMessage(messageTitle, Localiser["organisation.members.msg.remove.own.admin.role"]));
}
}
}
// New member - Lookup user by email and create new account if needed.
@@ -458,17 +480,6 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
// Ensure user has member role.
userOrganisation.AddOrganisationRole(Sax.OrganisationRole.Member);
// Validate roles.
if (userOrganisation.UserAccountId.Equals(SessionData.User.UserAccountId))
{
// User is modifying their own member.
if (!userOrganisation.HasOrganisationRole(Sax.OrganisationRole.MemberAdmin))
{
SaLogger.Warn(fn + " Unable to store member - user is attempting to remove their own 'Member Admin' role.");
return Json(responseData.SetMessage(messageTitle, Localiser["organisation.members.msg.remove.own.admin.role"]));
}
}
// User organisation properties.
if (model.MemberAdminComment != null)
userOrganisation.AdminComment = model.MemberAdminComment;
@@ -548,7 +559,7 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
}
// Ensure that the user has the correct role to update Members for this organisation.
bool userCanManageMembers = AccountMgr.UserHasOrganisationRole(SessionData.User.UserAccountId, organisation.Id, Sax.OrganisationRole.MemberAdmin);
bool userCanManageMembers = AccountMgr.UserHasAnyOrganisationRole(SessionData.User.UserAccountId, organisation.Id, new List<Sax.OrganisationRole> { Sax.OrganisationRole.Admin, Sax.OrganisationRole.MemberAdmin });
if (!userCanManageMembers)
{
SaLogger.Warn(fn + " User doesn't have 'Member Admin' role for Organisation Id: " + organisation.Id);
@@ -664,7 +675,7 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
}
// Ensure that the user has the correct role to update Members for this organisation.
bool userCanManageMembers = AccountMgr.UserHasOrganisationRole(SessionData.User.UserAccountId, organisation.Id, Sax.OrganisationRole.MemberAdmin);
bool userCanManageMembers = AccountMgr.UserHasAnyOrganisationRole(SessionData.User.UserAccountId, organisation.Id, new List<Sax.OrganisationRole> { Sax.OrganisationRole.Admin, Sax.OrganisationRole.MemberAdmin });
if (!userCanManageMembers)
{
SaLogger.Warn(fn + " User doesn't have 'Member Admin' role for Organisation Id: " + organisation.Id);
@@ -154,7 +154,7 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
responseData.Organisation.RegionName = model.GetRegionCaption(organisation.RegionIdPrimary);
// User details.
responseData.User.CanManage = userOrganisation?.HasOrganisationRole(Sax.OrganisationRole.OpportunityAdmin) ?? false;
responseData.User.CanManage = userOrganisation.CanManageOpportunities;
// Item filter.
SaxOrganisationOpportunity.Params prmOpportunity = new SaxOrganisationOpportunity.Params();
@@ -354,7 +354,7 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
}
// Ensure that the user has the correct role to update Opportunities for this organisation.
if (!AccountMgr.UserHasOrganisationRole(SessionData.User.UserAccountId, organisationId, Sax.OrganisationRole.OpportunityAdmin))
if (!AccountMgr.UserHasAnyOrganisationRole(SessionData.User.UserAccountId, organisationId, new [] { Sax.OrganisationRole.Admin, Sax.OrganisationRole.OpportunityAdmin }))
{
SaLogger.Warn(fn + " User doesn't have 'Opportunity Admin' role for Organisation Id: " + organisationId);
return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"]));
@@ -152,7 +152,7 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
// Add user as member of organisation.
SaxUserOrganisation userOrganisation = AccountMgr.CreateUserOrganisation(userAccount.Id, organisation.Id);
userOrganisation.OrganisationRoles = new List<Sax.OrganisationRole>() { Sax.OrganisationRole.Member, Sax.OrganisationRole.MemberAdmin };
userOrganisation.OrganisationRoles = new [] { Sax.OrganisationRole.Member, Sax.OrganisationRole.Admin };
if (!AccountMgr.InsertUserOrganisation(userOrganisation, DbUpdateInfo))
{
SaLogger.Warn(fn + " Failed to insert user organisation - " + AccountMgr.ErrorStateMessage);
@@ -181,7 +181,7 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
}
// Complete response.
responseData.SetMessage(messageTitle, Localiser["msg.organisation.request.success"].ToString().ReplaceAll("\n", "<br>"));
responseData.SetMessage(messageTitle, Localiser["msg.organisation.request.success"].ToString().ReplaceAll("\n", "<br/><br/>"));
responseData.Success = true;
return Json(responseData);
}
@@ -22,8 +22,9 @@ namespace Saxonite.Net.Core.Web.Online.Models
//-------------------------------------------------------------------
// Data members.
private bool? userCanManageOrganisationMembers = null;
private bool? userCanManageOrganisationArticles = null;
private bool? userCanManageOrganisationOpportunities = null;
private bool? userCanManageOrganisationSchedule = null;
private bool? userCanManageOrganisationArticles = null;
//-------------------------------------------------------------------
// Protected construction.
@@ -51,29 +52,14 @@ namespace Saxonite.Net.Core.Web.Online.Models
SaxUserOrganisation.Params prmUserOrganisation = new SaxUserOrganisation.Params();
prmUserOrganisation.UserAccountIdsIncluded.Add(SessionData.User.UserAccountId);
prmUserOrganisation.OrganisationMembersOnly = true;
prmUserOrganisation.OrganisationRoles.Add(Sax.OrganisationRole.OpportunityAdmin);
prmUserOrganisation.OrganisationRolesAny.Add(Sax.OrganisationRole.Admin);
prmUserOrganisation.OrganisationRolesAny.Add(Sax.OrganisationRole.MemberAdmin);
prmUserOrganisation.StatusCat = SaxUserOrganisation.StatusCat.ActiveOnly;
userCanManageOrganisationMembers = (AccountMgr.GetUserOrganisationCount(prmUserOrganisation) > 0);
}
return userCanManageOrganisationMembers == true ? true : false;
}
}
public bool UserCanManageOrganisationArticles
{
get
{
if (userCanManageOrganisationArticles == null && ValidUserSession)
{
SaxUserOrganisation.Params prmUserOrganisation = new SaxUserOrganisation.Params();
prmUserOrganisation.UserAccountIdsIncluded.Add(SessionData.User.UserAccountId);
prmUserOrganisation.OrganisationMembersOnly = true;
prmUserOrganisation.OrganisationRoles.Add(Sax.OrganisationRole.ArticleAdmin);
prmUserOrganisation.StatusCat = SaxUserOrganisation.StatusCat.ActiveOnly;
userCanManageOrganisationArticles = (AccountMgr.GetUserOrganisationCount(prmUserOrganisation) > 0);
}
return userCanManageOrganisationArticles == true ? true : false;
}
}
public bool UserCanManageOrganisationOpportunities
{
get
@@ -83,13 +69,48 @@ namespace Saxonite.Net.Core.Web.Online.Models
SaxUserOrganisation.Params prmUserOrganisation = new SaxUserOrganisation.Params();
prmUserOrganisation.UserAccountIdsIncluded.Add(SessionData.User.UserAccountId);
prmUserOrganisation.OrganisationMembersOnly = true;
prmUserOrganisation.OrganisationRoles.Add(Sax.OrganisationRole.OpportunityAdmin);
prmUserOrganisation.OrganisationRolesAny.Add(Sax.OrganisationRole.Admin);
prmUserOrganisation.OrganisationRolesAny.Add(Sax.OrganisationRole.OpportunityAdmin);
prmUserOrganisation.StatusCat = SaxUserOrganisation.StatusCat.ActiveOnly;
userCanManageOrganisationOpportunities = (AccountMgr.GetUserOrganisationCount(prmUserOrganisation) > 0);
}
return userCanManageOrganisationOpportunities == true ? true : false;
}
}
public bool UserCanManageOrganisationSchedule
{
get
{
if (userCanManageOrganisationSchedule == null && ValidUserSession)
{
SaxUserOrganisation.Params prmUserOrganisation = new SaxUserOrganisation.Params();
prmUserOrganisation.UserAccountIdsIncluded.Add(SessionData.User.UserAccountId);
prmUserOrganisation.OrganisationMembersOnly = true;
prmUserOrganisation.OrganisationRolesAny.Add(Sax.OrganisationRole.Admin);
prmUserOrganisation.OrganisationRolesAny.Add(Sax.OrganisationRole.ScheduleAdmin);
prmUserOrganisation.StatusCat = SaxUserOrganisation.StatusCat.ActiveOnly;
userCanManageOrganisationSchedule = (AccountMgr.GetUserOrganisationCount(prmUserOrganisation) > 0);
}
return userCanManageOrganisationSchedule == true ? true : false;
}
}
public bool UserCanManageOrganisationArticles
{
get
{
if (userCanManageOrganisationArticles == null && ValidUserSession)
{
SaxUserOrganisation.Params prmUserOrganisation = new SaxUserOrganisation.Params();
prmUserOrganisation.UserAccountIdsIncluded.Add(SessionData.User.UserAccountId);
prmUserOrganisation.OrganisationMembersOnly = true;
prmUserOrganisation.OrganisationRolesAny.Add(Sax.OrganisationRole.Admin);
prmUserOrganisation.OrganisationRolesAny.Add(Sax.OrganisationRole.ArticleAdmin);
prmUserOrganisation.StatusCat = SaxUserOrganisation.StatusCat.ActiveOnly;
userCanManageOrganisationArticles = (AccountMgr.GetUserOrganisationCount(prmUserOrganisation) > 0);
}
return userCanManageOrganisationArticles == true ? true : false;
}
}
//-------------------------------------------------------------------
// Item Id Obfuscation.
@@ -1,13 +1,13 @@
@model SaxModel_Online
@inject SaxLocaliser Localiser
@{
int regionIdCountry = Model.ValidUserSession ? Model.SessionData.User.RegionIdCountry.ToInt() : 0;
String regionIdCountry = Model.ValidUserSession ? Model.SessionData.User.RegionIdCountry.ToString() : "";
String regionNameCountry = Model.ValidUserSession ? Localiser.EscapeJavascriptText(Model.GetRegionCaption(Model.SessionData.User.RegionIdCountry)) : "";
}
<script type="text/javascript">
let or = sax.orgReq = {};
or.dlgTitleRequestOrganisation = '@Localiser.GetJavascriptText("organisation.caption.organisation.request")';
sax.data.regionIdCountryDefault = @regionIdCountry;
sax.data.regionIdCountryDefault = '@regionIdCountry';
sax.data.regionNameCountryDefault = '@regionNameCountry';
</script>
@@ -28,47 +28,52 @@
@* Contact Email Address *@
<div class="sax-form-control ContactEmailAddress">
<div class="sax-label">
<label for="ifContactEmailAddress"><span>@Localiser["label.email"]</span><span class="required">&nbsp;*</span></label>
<div class="row">
<div class="col-sm-4">
<div class="sax-label">
<label for="ifContactEmailAddress"><span>@Localiser["label.email"]</span><span class="required">&nbsp;*</span></label>
</div>
</div>
<div class="col-sm">
<div class="sax-control">
<input type="text" id="ifContactEmailAddress" name="ContactEmailAddress" class="ContactEmailAddress sax-input" autocomplete="off" maxlength="@Model.GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.UserAccount_EmailAddress)" />
</div>
<div class="sax-message"></div>
</div>
</div>
<div class="sax-control">
<input type="text" id="ifContactEmailAddress" name="ContactEmailAddress" class="ContactEmailAddress sax-input" autocomplete="off" maxlength="@Model.GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.UserAccount_EmailAddress)" />
</div>
<div class="sax-message"></div>
</div>
<div class="row">
<div class="col-sm-6">
<div class="col-sm-4">@* No label. *@</div>
<div class="col-sm row">
@* Contact First Name *@
<div class="sax-form-control ContactFirstName pr4">
<div class="sax-label">
<label for="cbContactFirstName"><span>@Localiser["label.first.name"]</span><span class="required">&nbsp;*</span></label>
<div class="col-sm-6">
<div class="sax-form-control ContactFirstName pr4">
<div class="sax-label">
<label for="cbContactFirstName"><span>@Localiser["label.first.name"]</span><span class="required">&nbsp;*</span></label>
</div>
<div class="sax-control">
<input type="text" id="ifContactFirstName" name="ContactFirstName" class="ContactFirstName sax-input" autocomplete="off" maxlength="@Model.GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.UserAccount_FirstName)" />
</div>
<div class="sax-message"></div>
</div>
<div class="sax-control">
<input type="text" id="ifContactFirstName" name="ContactFirstName" class="ContactFirstName sax-input" autocomplete="off" maxlength="@Model.GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.UserAccount_FirstName)" />
</div>
<div class="sax-message"></div>
</div>
</div>
<div class="col-sm-6">
@* Contact Last Name *@
<div class="sax-form-control ContactLastName pr4">
<div class="sax-label">
<label for="cbContactLastName"><span>@Localiser["label.last.name"]</span><span class="required">&nbsp;*</span></label>
<div class="col-sm-6">
<div class="sax-form-control ContactLastName">
<div class="sax-label">
<label for="cbContactLastName"><span>@Localiser["label.last.name"]</span><span class="required">&nbsp;*</span></label>
</div>
<div class="sax-control">
<input type="text" id="ifContactLastName" name="ContactLastName" class="ContactLastName sax-input" autocomplete="off" maxlength="@Model.GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.UserAccount_LastName)" />
</div>
<div class="sax-message"></div>
</div>
<div class="sax-control">
<input type="text" id="ifContactLastName" name="ContactLastName" class="ContactLastName sax-input" autocomplete="off" maxlength="@Model.GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.UserAccount_LastName)" />
</div>
<div class="sax-message"></div>
</div>
</div>
</div>
}
@@ -81,147 +86,202 @@
@* Organisation name *@
<div class="sax-form-control OrganisationName">
<div class="sax-label">
<label for="ifOrganisationName"><span>@Localiser["label.name"]</span><span class="required">&nbsp;*</span></label>
<div class="row">
<div class="col-sm-4">
<div class="sax-label">
<label for="ifOrganisationName"><span>@Localiser["label.name"]</span><span class="required">&nbsp;*</span></label>
</div>
</div>
<div class="col-sm">
<div class="sax-control">
<input type="text" id="ifOrganisationName" name="OrganisationName" class="OrganisationName sax-input" autocomplete="off" maxlength="@Model.GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.Organisation_Name)" />
</div>
<div class="sax-message"></div>
</div>
</div>
<div class="sax-control">
<input type="text" id="ifOrganisationName" name="OrganisationName" class="OrganisationName sax-input" autocomplete="off" maxlength="@Model.GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.Organisation_Name)" />
</div>
<div class="sax-message"></div>
</div>
<div class="row">
<div class="col-sm-6">
<div class="col-sm-4"></div>
<div class="col-sm row">
@* Organisation category *@
<div class="sax-form-control OrganisationCategory pr4">
<div class="sax-label">
<label for="cbOrganisationCategory"><span>@Localiser["label.category"]</span><span class="required">&nbsp;*</span></label>
<div class="col-sm-6">
<div class="sax-form-control OrganisationCategory pr4">
<div class="sax-label">
<label for="cbOrganisationCategory"><span>@Localiser["label.category"]</span><span class="required">&nbsp;*</span></label>
</div>
<div class="sax-control">
@Html.DropDownList("", Model.OrganisationCategoriesForSelect, Localiser["label.select"], new { @id = "cbOrganisationCategory", @name = "OrganisationCategory", @class = "OrganisationCategory sax-select" })
</div>
<div class="sax-message"></div>
</div>
<div class="sax-control">
@Html.DropDownList("", Model.OrganisationCategoriesForSelect, Localiser["label.select"], new { @id = "cbOrganisationCategory", @name = "OrganisationCategory", @class = "OrganisationCategory sax-select" })
</div>
<div class="sax-message"></div>
</div>
</div>
<div class="col-sm-6">
@* Organisation type *@
<div class="sax-form-control OrganisationType">
<div class="sax-label">
<label for="cbOrganisationType"><span>@Localiser["label.type"]</span><span class="required">&nbsp;*</span></label>
<div class="col-sm-6">
<div class="sax-form-control OrganisationType">
<div class="sax-label">
<label for="cbOrganisationType"><span>@Localiser["label.type"]</span><span class="required">&nbsp;*</span></label>
</div>
<div class="sax-control">
@Html.DropDownList("", Model.OrganisationTypesForSelect, Localiser["label.select"], new { @id = "cbOrganisationType", @name = "OrganisationType", @class = "OrganisationType sax-select" })
</div>
<div class="sax-message"></div>
</div>
<div class="sax-control">
@Html.DropDownList("", Model.OrganisationTypesForSelect, Localiser["label.select"], new { @id = "cbOrganisationType", @name = "OrganisationType", @class = "OrganisationType sax-select" })
</div>
<div class="sax-message"></div>
</div>
</div>
</div>
@* Organisation sport *@
<div class="sax-form-control OrganisationSportId">
<div class="sax-label">
<label for="ifOrganisationSportCaption"><span>@Localiser["label.sport"]</span><span class="required">&nbsp;*</span></label>
<div class="row">
<div class="col-sm-4">
<div class="sax-label">
<label for="ifOrganisationSportCaption"><span>@Localiser["label.sport"]</span><span class="required">&nbsp;(*)</span></label>
</div>
</div>
<div class="col-sm">
<div class="sax-control row">
<input type="hidden" id="ifOrganisationSportId" name="OrganisationSportId" OrganisationSportId"" class="OrganisationSportId" />
<div class="col"><input type="text" id="ifOrganisationSportCaption" class="OrganisationSportCaption sax-input" readonly="readonly" ondblclick="sax.selectSport()" /> </div>
<div class="fixed"><button class="SelectSport sax-button" style="min-width:auto;margin-left:4px;padding:4px 6px" onclick="sax.selectOrgSport()">@Localiser["label.select"]</button></div>
</div>
<div class="sax-message"></div>
</div>
</div>
<div class="sax-control row">
<input type="hidden" id="ifOrganisationSportId" name="OrganisationSportId" OrganisationSportId"" class="OrganisationSportId" />
<div class="col"><input type="text" id="ifOrganisationSportCaption" class="OrganisationSportCaption sax-input" readonly="readonly" ondblclick="sax.selectSport()" /> </div>
<div class="fixed"><button class="SelectSport sax-button" style="min-width:auto;margin-left:4px;padding:4px 6px" onclick="sax.selectOrgSport()">@Localiser["label.select"]</button></div>
</div>
<div class="sax-message"></div>
</div>
@* Organisation country *@
<div class="sax-form-control OrganisationRegionIdCountry">
<div class="sax-label">
<label for="ifOrganisationRegionCaption"><span>@Localiser["label.country"]</span><span class="required">&nbsp;*</span></label>
<div class="row">
<div class="col-sm-4">
<div class="sax-label">
<label for="ifOrganisationRegionCaption"><span>@Localiser["label.country"]</span><span class="required">&nbsp;*</span></label>
</div>
</div>
<div class="col-sm">
<div class="sax-control row">
<input type="hidden" id="ifOrganisationRegionIdCountry" name="OrganisationRegionIdCountry" OrganisationRegionIdCountry"" class="OrganisationRegionIdCountry" />
<div class="col"><input type="text" id="ifOrganisationRegionCaptionCountry" class="OrganisationRegionCaptionCountry sax-input" readonly="readonly" ondblclick="sax.selectRegion()" /> </div>
<div class="fixed"><button class="SelectRegion sax-button" style="min-width:auto;margin-left:4px;padding:4px 6px" onclick="sax.selectOrgRegion()">@Localiser["label.select"]</button></div>
</div>
<div class="sax-message"></div>
</div>
</div>
<div class="sax-control row">
<input type="hidden" id="ifOrganisationRegionIdCountry" name="OrganisationRegionIdCountry" OrganisationRegionIdCountry"" class="OrganisationRegionIdCountry" />
<div class="col"><input type="text" id="ifOrganisationRegionCaptionCountry" class="OrganisationRegionCaptionCountry sax-input" readonly="readonly" ondblclick="sax.selectRegion()" /> </div>
<div class="fixed"><button class="SelectRegion sax-button" style="min-width:auto;margin-left:4px;padding:4px 6px" onclick="sax.selectOrgRegion()">@Localiser["label.select"]</button></div>
</div>
<div class="sax-message"></div>
</div>
@* Organisation address - Line 1 *@
<div class="sax-form-control OrganisationAddressLine1">
<div class="sax-caption">
<label for="ifOrganisationAddressLine1"><span>@Localiser["label.organisation.address"]</span><span class="required">&nbsp;*</span></label>
<div class="row">
<div class="col-sm-4">
<div class="sax-caption">
<label for="ifOrganisationAddressLine1"><span>@Localiser["label.organisation.address"]</span><span class="required">&nbsp;*</span></label>
</div>
</div>
<div class="col-sm">
<div class="sax-control row">
<div class="col"><input type="text" id="ifOrganisationAddressLine1" name="OrganisationAddressLine1" class="OrganisationAddressLine1 sax-input" autocomplete="off" maxlength="@Model.GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.ItemAddress_Line1)" /> </div>
</div>
<div class="sax-message"></div>
</div>
</div>
<div class="sax-control row">
<div class="col"><input type="text" id="ifOrganisationAddressLine1" name="OrganisationAddressLine1" class="OrganisationAddressLine1 sax-input" autocomplete="off" maxlength="@Model.GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.ItemAddress_Line1)" /> </div>
</div>
<div class="sax-message"></div>
</div>
@* Organisation address - Line 2 *@
<div class="sax-form-control OrganisationAddressLine2">
<div class="sax-control row">
<div class="col"><input type="text" id="ifOrganisationAddressLine2" name="OrganisationAddressLine2" class="OrganisationAddressLine2 sax-input" autocomplete="off" maxlength="@Model.GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.ItemAddress_Line2)" /> </div>
<div class="row">
<div class="col-sm-4"></div>
<div class="col-sm">
<div class="sax-control row">
<div class="col"><input type="text" id="ifOrganisationAddressLine2" name="OrganisationAddressLine2" class="OrganisationAddressLine2 sax-input" autocomplete="off" maxlength="@Model.GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.ItemAddress_Line2)" /> </div>
</div>
<div class="sax-message"></div>
</div>
</div>
<div class="sax-message"></div>
</div>
@* Organisation address - Line 3 *@
<div class="sax-form-control OrganisationAddressLine3">
<div class="sax-control row">
<div class="col"><input type="text" id="ifOrganisationAddressLine3" name="OrganisationAddressLine3" class="OrganisationAddressLine3 sax-input" autocomplete="off" maxlength="@Model.GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.ItemAddress_Line3)" /> </div>
<div class="row">
<div class="col-sm-4"></div>
<div class="col-sm">
<div class="sax-control row">
<div class="col"><input type="text" id="ifOrganisationAddressLine3" name="OrganisationAddressLine3" class="OrganisationAddressLine3 sax-input" autocomplete="off" maxlength="@Model.GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.ItemAddress_Line3)" /> </div>
</div>
<div class="sax-message"></div>
</div>
</div>
<div class="sax-message"></div>
</div>
@* Organisation address - Town *@
<div class="sax-form-control OrganisationAddressTown">
<div class="sax-label">
<label for="ifOrganisationAddressTown"><span>@Localiser["label.town"]</span><span class="required">&nbsp;*</span></label>
<div class="row">
<div class="col-sm-4">
<div class="sax-label">
<label for="ifOrganisationAddressTown"><span>@Localiser["label.town"]</span><span class="required">&nbsp;*</span></label>
</div>
</div>
<div class="col-sm">
<div class="sax-control row">
<div class="col"><input type="text" id="ifOrganisationAddressTown" name="OrganisationAddressTown" class="OrganisationAddressTown sax-input" autocomplete="off" maxlength="@Model.GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.ItemAddress_Town)" /> </div>
</div>
<div class="sax-message"></div>
</div>
</div>
<div class="sax-control row">
<div class="col"><input type="text" id="ifOrganisationAddressTown" name="OrganisationAddressTown" class="OrganisationAddressTown sax-input" autocomplete="off" maxlength="@Model.GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.ItemAddress_Town)" /> </div>
</div>
<div class="sax-message"></div>
</div>
@* Organisation address - Province *@
<div class="sax-form-control OrganisationAddressProvince">
<div class="sax-label">
<label for="ifOrganisationAddressProvince"><span>@Localiser["label.province"]</span><span class="required">&nbsp;*</span></label>
<div class="row">
<div class="col-sm-4">
<div class="sax-label">
<label for="ifOrganisationAddressProvince"><span>@Localiser["label.province"]</span></label>
</div>
</div>
<div class="col-sm">
<div class="sax-control row">
<div class="col"><input type="text" id="ifOrganisationAddressProvince" name="OrganisationAddressProvince" class="OrganisationAddressProvince sax-input" autocomplete="off" maxlength="@Model.GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.ItemAddress_Province)" /> </div>
</div>
<div class="sax-message"></div>
</div>
</div>
<div class="sax-control row">
<div class="col"><input type="text" id="ifOrganisationAddressProvince" name="OrganisationAddressProvince" class="OrganisationAddressProvince sax-input" autocomplete="off" maxlength="@Model.GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.ItemAddress_Province)" /> </div>
</div>
<div class="sax-message"></div>
</div>
@* Organisation address - PostalCode *@
<div class="sax-form-control OrganisationAddressPostalCode">
<div class="sax-label">
<label for="ifOrganisationAddressPostalCode"><span>@Localiser["label.postalCode"]</span><span class="required">&nbsp;*</span></label>
<div class="row">
<div class="col-sm-4">
<div class="sax-label">
<label for="ifOrganisationAddressPostalCode"><span>@Localiser["label.postalCode"]</span></label>
</div>
</div>
<div class="col-sm">
<div class="sax-control row">
<div class="col"><input type="text" id="ifOrganisationAddressPostalCode" name="OrganisationAddressPostalCode" class="OrganisationAddressPostalCode sax-input" autocomplete="off" maxlength="@Model.GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.ItemAddress_PostalCode)" /> </div>
</div>
<div class="sax-message"></div>
</div>
</div>
<div class="sax-control row">
<div class="col"><input type="text" id="ifOrganisationAddressPostalCode" name="OrganisationAddressPostalCode" class="OrganisationAddressPostalCode sax-input" autocomplete="off" maxlength="@Model.GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.ItemAddress_PostalCode)" /> </div>
</div>
<div class="sax-message"></div>
</div>
@* Organisation PhoneMain *@
@*
<div class="sax-form-control OrganisationPhoneMain">
<div class="sax-label">
<label for="ifOrganisationPhoneMain"><span>@Localiser["label.phone"]</span></label>
<div class="sax-form-control OrganisationPhoneMain">
<div class="row">
<div class="col-sm-4">
<div class="sax-label">
<label for="ifOrganisationPhoneMain"><span>@Localiser["label.phone"]</span></label>
</div>
</div>
<div class="sax-control row">
<div class="col"><input type="text" id="ifOrganisationPhoneMain" name="OrganisationPhoneMain" class="OrganisationPhoneMain sax-input" autocomplete="off" maxlength="@Model.GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.Item_PhoneMain)" /> </div>
<div class="col-sm">
<div class="sax-control row">
<div class="col"><input type="text" id="ifOrganisationPhoneMain" name="OrganisationPhoneMain" class="OrganisationPhoneMain sax-input" autocomplete="off" maxlength="@Model.GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.Organisation_PhoneMain)" /> </div>
</div>
<div class="sax-message"></div>
</div>
<div class="sax-message"></div>
</div>
*@
</div>
}
@@ -205,18 +205,19 @@
.sax-form .sax-form-control .sax-message
{
display: none;
margin-top: 8px;
margin-top: 4px;
padding-left: 24px;
font-size: 16px;
font-size: 1.00Rem;
background-position: left top;
background-repeat: no-repeat;
}
.sax-form .sax-form-control.sax-error .sax-message
{
min-height:16px;
display: block;
color: #e3120b;
background-image: url("../img/icon/error-18.png");
background-image: url("../img/icon/error-16.png");
}
/* Buttons */
Binary file not shown.

After

Width:  |  Height:  |  Size: 462 B

@@ -185,10 +185,6 @@
$('#ifOpportunityId,#ifOpportunityExists,#ifOpportunityRegionId,#ifOpportunitySportId,input[type="text"],textarea,select', $frm.opportunity).val('');
sax.clearControlErrors();
}
sax.doCreateItem = function ()
{
sax.storeItem();
}
//--------------------------------------------------------------
sax.updateItem = function (item)
@@ -219,10 +215,6 @@
$dlg.opportunity.dialog('option', 'title', sax.dlg.title.updateOpportunity);
sax.openDialog($dlg.opportunity, 600, 600);
}
sax.doUpdateItem = function ()
{
sax.storeItem();
}
//--------------------------------------------------------------
sax.storeItem = function ()
@@ -263,7 +255,7 @@
$('.sax-input', $frm.opportunity).on('input', function () { sax.clearControlError(this); });
var opt = sax.dlgOpts();
opt.buttons[sax.dlg.btn.ok] = function () { sax.doCreateItem(); };
opt.buttons[sax.dlg.btn.ok] = function () { sax.storeItem(); };
opt.buttons[sax.dlg.btn.cancel] = function () { $(this).dialog('close'); };
$dlg.opportunity = $('#dlgOpportunity').dialog(opt);
+16 -14
View File
@@ -5,16 +5,16 @@
(function (win, doc, undef)
{
"use strict";
let $pnl = sax.$pnl, $dlg = sax.$dlg, $frm = sax.$frm;
let po = sax.mdl.profileOrganisations = sax.mdl.profileOrganisations || { $pnl: {}, $dlg: {}, $frm: {} };
let $pnl = po.$pnl, $dlg = po.$dlg, $frm = po.$frm;
//--------------------------------------------------------------
sax.refreshProfileOrganisationsInfo = function (delay)
{
var $section = $('.sax-panel-section.ProfileOrganisations');
$section.removeClass('sax-edit').addClass('sax-populating');
$('.sax-property', $section).hide();
sax.showDataRefreshingMsg($section);
sax.refreshProfileOrganisations(sax.onRefreshProfileOrganisationsInfo);
$pnl.section.removeClass('sax-edit').addClass('sax-populating');
$('.sax-property', $pnl.section).hide();
sax.showDataRefreshingMsg($pnl.section);
sax.refreshProfileOrganisations(po.onRefreshProfileOrganisationsInfo);
}
sax.refreshProfileOrganisations = function (callbackFn)
{
@@ -24,17 +24,16 @@
sax.ajax.profileOrganisations.callbackFn = callbackFn;
sax.doAjaxRequest(sax.ajax.profileOrganisations, 50);
}
sax.onRefreshProfileOrganisationsInfo = function (response)
po.onRefreshProfileOrganisationsInfo = function (response)
{
//sax.debug('onRefreshProfileOrganisationsInfo', response);
sax.debug('onRefreshProfileOrganisationsInfo', response);
if (!response || !response.success) return;
var $section = $('.sax-panel-section.ProfileOrganisations');
$('.sax-message', $section).stop(true, false).fadeOut(200).empty();
$('.sax-message', $pnl.section).stop(true, false).fadeOut(200).empty();
let items = response.organisations;
if (!items) return;
let $items = $('.sax-panel-results.Organisations', $section).empty();
let $tmpl = $('.sax-panel-item-template .sax-panel-item.Organisation', $section);
let $items = $('.sax-panel-results.Organisations', $pnl.section).empty();
let $tmpl = $('.sax-panel-item-template .sax-panel-item.Organisation', $pnl.section);
for (let itemIdx = 0; itemIdx < items.length; itemIdx++)
{
let item = items[itemIdx];
@@ -47,13 +46,16 @@
$items.append($item);
}
$items.show();
sax.showNoInfoMsg($section);
$section.removeClass('sax-populating');
sax.showNoInfoMsg($pnl.section);
$pnl.section.removeClass('sax-populating');
}
//--------------------------------------------------------------
//--------------------------------------------------------------
$(function ()
{
$pnl.section = $('.sax-panel-section.ProfileOrganisations');
});
//--------------------------------------------------------------
+5 -2
View File
@@ -18,7 +18,7 @@ namespace Saxonite.Net.Standard.Base.App
//-------------------------------------------------------------------
public static class Version
{
private static String version { get; } = "1.1.8.0";
private static String version { get; } = "1.2.0.0";
// Retrieve version.
public static String GetFullVersion () { return version; }
public static String GetAppVersion ()
@@ -40,8 +40,11 @@ namespace Saxonite.Net.Standard.Base.App
//-------------------------------------------------------------------
// Version history.
//-------------------------------------------------------------------
// 1.2.0 1-Nov-2021 'Admin' Organisation role
// - 'Admin' Organisation role
// - Azure App Service configuration.
// 1.1.8 21-Oct-2021 Online Users Search
// - ONlien Search - Users.
// - Online Search - Users.
// - Admin Account Users filter.
// 1.1.7 14-Oct-2021 Online Organisation Search
// - Online Profile Sport About & snags.
+1
View File
@@ -232,6 +232,7 @@ namespace Saxonite.Net.Standard.Base.App
Unknown = 0,
/* Do not change the values/codes - tied to database. */
Member,
Admin,
MemberAdmin,
ScheduleAdmin,
OpportunityAdmin,
@@ -144,10 +144,11 @@ namespace Saxonite.Net.Standard.Base.App
//---------------------------------------------------------------
// Organisation roles.
organisationRoleCodes.Add(Sax.OrganisationRole.Member, "MBR", "Member");
organisationRoleCodes.Add(Sax.OrganisationRole.MemberAdmin, "MBA", "Member Admin");
organisationRoleCodes.Add(Sax.OrganisationRole.ScheduleAdmin, "SCA", "Schedule Admin");
organisationRoleCodes.Add(Sax.OrganisationRole.OpportunityAdmin, "OPA", "Opportunity Admin");
organisationRoleCodes.Add(Sax.OrganisationRole.ArticleAdmin, "ARA", "Article Admin");
organisationRoleCodes.Add(Sax.OrganisationRole.Admin, "ADM", "Admin");
organisationRoleCodes.Add(Sax.OrganisationRole.MemberAdmin, "MBA", "Members");
organisationRoleCodes.Add(Sax.OrganisationRole.ScheduleAdmin, "SCA", "Schedule");
organisationRoleCodes.Add(Sax.OrganisationRole.OpportunityAdmin, "OPA", "Opportunities");
organisationRoleCodes.Add(Sax.OrganisationRole.ArticleAdmin, "ARA", "Articles");
//---------------------------------------------------------------
// Opportunity types.
@@ -101,9 +101,9 @@ namespace Saxonite.Net.Standard.Base.Bus
if (!Changed) Changed = !data.OrganisationRoles.IsEmpty();
data.OrganisationRoles.Clear();
}
public bool HasOrganisationRole(Sax.OrganisationRole organisationRole)
public bool HasAnyOrganisationRole(IEnumerable<Sax.OrganisationRole> organisationRoles)
{
return data.OrganisationRoles.Contains(organisationRole);
return data.OrganisationRoles.Any(item => organisationRoles.Contains(item));
}
public void AddOrganisationRole(Sax.OrganisationRole organisationRole)
{
@@ -114,7 +114,7 @@ namespace Saxonite.Net.Standard.Base.Bus
}
}
/// <summary>Store organisation roles.</summary>
public List<Sax.OrganisationRole> OrganisationRoles
public IEnumerable<Sax.OrganisationRole> OrganisationRoles
{
set
{
@@ -240,6 +240,16 @@ namespace Saxonite.Net.Standard.Base.Bus
{
return GetOrganisationRoleCodes().Concat(UserOrgnisationRoleDelim);
}
// Query roles.
public bool CanManageOrganisation{ get { return HasAnyOrganisationRole(new [] { Sax.OrganisationRole.Admin }); } }
public bool CanManageMembers { get { return HasAnyOrganisationRole(new [] { Sax.OrganisationRole.Admin, Sax.OrganisationRole.MemberAdmin }); } }
public bool CanManageOpportunities { get { return HasAnyOrganisationRole(new [] { Sax.OrganisationRole.Admin, Sax.OrganisationRole.OpportunityAdmin }); } }
public bool CanManageSchedule { get { return HasAnyOrganisationRole(new [] { Sax.OrganisationRole.Admin, Sax.OrganisationRole.ScheduleAdmin }); } }
public bool CanManageArticles { get { return HasAnyOrganisationRole(new [] { Sax.OrganisationRole.Admin, Sax.OrganisationRole.ArticleAdmin }); } }
public bool HasAnyOrganisationRole(IEnumerable<Sax.OrganisationRole> organisationRoles)
{
return data.HasAnyOrganisationRole(organisationRoles);
}
//-------------------------------------------------------------------
// Properties.
@@ -290,7 +300,7 @@ namespace Saxonite.Net.Standard.Base.Bus
return data.GetOrganisationRoles();
}
/// <summary>Store Organisation Roles.</summary>
public List<Sax.OrganisationRole> OrganisationRoles
public IEnumerable<Sax.OrganisationRole> OrganisationRoles
{
set { data.OrganisationRoles = value; }
}
@@ -298,10 +308,6 @@ namespace Saxonite.Net.Standard.Base.Bus
{
data.ClearOrganisationRoles();
}
public bool HasOrganisationRole(Sax.OrganisationRole organisationRole)
{
return data.HasOrganisationRole(organisationRole);
}
public void AddOrganisationRole(Sax.OrganisationRole organisationRole)
{
data.AddOrganisationRole(organisationRole);
@@ -347,6 +353,7 @@ namespace Saxonite.Net.Standard.Base.Bus
/// <summary>Set true to restruct to User Organisations with at least one Organisation Role.</summary>
public bool OrganisationMembersOnly { get; set; }
public List<Sax.OrganisationRole> OrganisationRoles { get; } = new List<Sax.OrganisationRole>();
public List<Sax.OrganisationRole> OrganisationRolesAny { get; } = new List<Sax.OrganisationRole>();
// Common properties.
public String NotesPartial { get; set; }
public StatusCat StatusCat { get; set; } = StatusCat.NotDeleted;
@@ -39,8 +39,16 @@ namespace Saxonite.Net.Standard.Base.Mgr
/// </summary>
public bool UserHasOrganisationRole(SysId userAccountId, SysId organisationId, Sax.OrganisationRole organisationRole, SaxUserOrganisation.StatusCat statusCat = SaxUserOrganisation.StatusCat.ActiveOnly)
{
if (!SysId.IsValid(userAccountId) || !SysId.IsValid(organisationId) || organisationRole <= 0) return false;
return GetOrganisationRolesForUser(userAccountId, organisationId, statusCat).Contains(organisationRole);
return UserHasAnyOrganisationRole(userAccountId, organisationId, new [] { organisationRole }, statusCat);
}
/// <summary>
/// Does the user have any of the specified roles with the organisation.
/// </summary>
public bool UserHasAnyOrganisationRole(SysId userAccountId, SysId organisationId, IEnumerable<Sax.OrganisationRole> organisationRoles, SaxUserOrganisation.StatusCat statusCat = SaxUserOrganisation.StatusCat.ActiveOnly)
{
if (!SysId.IsValid(userAccountId) || !SysId.IsValid(organisationId) || organisationRoles.IsEmpty() || !organisationRoles.Any(item => item > 0)) return false;
return GetOrganisationRolesForUser(userAccountId, organisationId, statusCat).Any(item => organisationRoles.Contains(item));
}
/// <summary>
@@ -67,24 +75,40 @@ namespace Saxonite.Net.Standard.Base.Mgr
}
/// <summary>
/// Get list of organisation Ids that the user has the specified role with.
/// Get list of organisation Ids and names that the user has the specified role with.
/// </summary>
public List<OrganisationIdName> GetOrganisationsForUserRole(SysId userAccountId, Sax.OrganisationRole organisationRole, SaxUserOrganisation.StatusCat statusCat = SaxUserOrganisation.StatusCat.ActiveOnly)
{
List<OrganisationIdName> organisationsData = new List<OrganisationIdName>();
String organisationRoleCode = Internals.OrganisationRoleCodes.GetCodeForType(organisationRole);
if (!SysId.IsValid(userAccountId) || StringUtil.IsEmpty(organisationRoleCode)) return organisationsData;
// Columns.
ColumnDfn colOrganisationId = GetUserOrganisationColumnDfn(SaxUserOrganisation.Column.OrganisationId);
ColumnDfn colOrganisationName = GetUserOrganisationColumnDfn(SaxUserOrganisation.Column.Organisation_Name);
return GetOrganisationsForAnyUserRole(userAccountId, new [] { organisationRole }, statusCat);
}
/// <summary>
/// Get list of organisation Ids and names that the user has any of the specified roles with.
/// </summary>
public List<OrganisationIdName> GetOrganisationsForAnyUserRole(SysId userAccountId, IEnumerable<Sax.OrganisationRole> organisationRoles, SaxUserOrganisation.StatusCat statusCat = SaxUserOrganisation.StatusCat.ActiveOnly)
{
if (!SysId.IsValid(userAccountId) || organisationRoles.IsEmpty() || !organisationRoles.Any(item => item > 0)) return null;
// Filter.
SaxUserOrganisation.Params prmUserOrganisation = new SaxUserOrganisation.Params();
prmUserOrganisation.UserAccountIdsIncluded.Add(userAccountId);
prmUserOrganisation.OrganisationStatusCat = SaxOrganisation.StatusCat.ActiveOnly;
prmUserOrganisation.OrganisationMembersOnly = true;
prmUserOrganisation.OrganisationRoles.Add(organisationRole);
prmUserOrganisation.OrganisationRolesAny.AddRange(organisationRoles);
prmUserOrganisation.StatusCat = statusCat;
prmUserOrganisation.SortColumns.Add(colOrganisationName);
return GetOrganisations(prmUserOrganisation);
}
/// <summary>
/// Get list of organisation Ids and names that matc the specified parameters.
/// </summary>
public List<OrganisationIdName> GetOrganisations(SaxUserOrganisation.Params prmUserOrganisation)
{
List<OrganisationIdName> organisationsData = new List<OrganisationIdName>();
// Columns.
ColumnDfn colOrganisationId = GetUserOrganisationColumnDfn(SaxUserOrganisation.Column.OrganisationId);
ColumnDfn colOrganisationName = GetUserOrganisationColumnDfn(SaxUserOrganisation.Column.Organisation_Name);
if (prmUserOrganisation.SortColumns.IsEmpty())
prmUserOrganisation.SortColumns.Add(colOrganisationName);
// Query.
using (DbResultSet resultSet = ExecuteUserOrganisationQuery(new List<ColumnDfn>() { colOrganisationId, colOrganisationName }, prmUserOrganisation))
{
@@ -488,7 +488,6 @@ namespace Saxonite.Net.Standard.Dbas.Mgr
filter.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.UserOrganisation_OrganisationRoleCount, aliasUserOrganisation) + ">0");
if (!prm.OrganisationRoles.IsEmpty())
{
List<String> organisationRoleCodes = new List<string>();
foreach (Sax.OrganisationRole organisationRole in prm.OrganisationRoles)
{
String organisationRoleCode = OrganisationRoleCodes.GetCodeForType(organisationRole).TrimAll();
@@ -496,6 +495,18 @@ namespace Saxonite.Net.Standard.Dbas.Mgr
filter.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.UserOrganisation_OrganisationRoleCodes, aliasUserOrganisation) + " LIKE '%" + DbQuery.FormatForLike(organisationRoleCode) + "%'");
}
}
if (!prm.OrganisationRolesAny.IsEmpty())
{
List<String> roleFilter = new List<string>();
foreach (Sax.OrganisationRole organisationRole in prm.OrganisationRolesAny)
{
String organisationRoleCode = OrganisationRoleCodes.GetCodeForType(organisationRole).TrimAll();
if (!StringUtil.IsEmpty(organisationRoleCode))
roleFilter.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.UserOrganisation_OrganisationRoleCodes, aliasUserOrganisation) + " LIKE '%" + DbQuery.FormatForLike(organisationRoleCode) + "%'");
}
if (!roleFilter.IsEmpty())
filter.Add(roleFilter.Concat(" OR "));
}
// Notes.
if (!StringUtil.IsEmpty(prm.NotesPartial))