v1.2.3.2
This commit is contained in:
@@ -486,6 +486,14 @@ namespace Saxonite.Net.Core.Web.Base.Controllers
|
||||
public String UpdatedOnFmt { 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>
|
||||
|
||||
@@ -392,6 +392,21 @@ namespace Saxonite.Net.Core.Web.Base.Models
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// List of Organisation Categories for Admin dropdown.
|
||||
/// <para>Includes complete set of categories.</para>
|
||||
/// </summary>
|
||||
public IEnumerable<SelectListItem> AdminOrganisationCategoriesForSelect
|
||||
{
|
||||
get
|
||||
{
|
||||
List<SelectListItem> values = new List<SelectListItem>();
|
||||
foreach (TypeCodeDesc organisationCategory in OrganisationCategoryCodes)
|
||||
values.Add(new SelectListItem(Localiser.GetOrganisationCategoryCaption((Sax.OrganisationCategory)organisationCategory.Type), organisationCategory.Code));
|
||||
return values;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Messages.
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,184 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Dbas;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using Sarand.Net.Standard.Dbas.Data;
|
||||
using Saxonite.Net.Core.Web.Admin.Models;
|
||||
using Saxonite.Net.Standard.Base.App;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
{
|
||||
//=======================================================================
|
||||
// Home Controller - Ajax - Application Stats
|
||||
//=======================================================================
|
||||
partial class HomeController
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Application Stats data.
|
||||
private class ApplicationStatsData
|
||||
{
|
||||
public class UserStatsData
|
||||
{
|
||||
public String Caption { get; set; }
|
||||
public AjaxResponse_Data.ItemLabelValue Awaiting { get; set; }
|
||||
public String AwaitingLink { get; set; }
|
||||
public List<AjaxResponse_Data.ItemLabelValue> OnlineStats { get; set; }
|
||||
public String OnlineLink { get; set; }
|
||||
}
|
||||
public UserStatsData User { get; } = new UserStatsData();
|
||||
public class OrganisationStatsData
|
||||
{
|
||||
public String Caption { get; set; }
|
||||
public AjaxResponse_Data.ItemLabelValue Awaiting { get; set; }
|
||||
public String AwaitingLink { get; set; }
|
||||
}
|
||||
public OrganisationStatsData Organisation { get; } = new OrganisationStatsData();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Get Application Stats ajax request.
|
||||
//-------------------------------------------------------------------
|
||||
private class AjaxResponse_ApplicationStats : AjaxResponse_Data
|
||||
{
|
||||
// Construction.
|
||||
public AjaxResponse_ApplicationStats(SaxModel_Admin model) : base(model) { }
|
||||
// Table list.
|
||||
public ApplicationStatsData Stats { get; } = new ApplicationStatsData();
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
[HttpPost]
|
||||
[Route("Home/Ajax/GetApplicationStats")]
|
||||
public IActionResult Ajax_GetApplicationStats(Model_Sport model)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_GetApplicationStats";
|
||||
String messageTitle = Localiser["home.caption.application"];
|
||||
AjaxResponse_ApplicationStats responseData = new AjaxResponse_ApplicationStats(model);
|
||||
|
||||
// Validate session.
|
||||
if (!ValidUserSession)
|
||||
return GetAjaxResult_InvalidSession(responseData);
|
||||
|
||||
// Captions.
|
||||
responseData.Stats.User.Caption = Localiser["user.caption.users"];
|
||||
responseData.Stats.Organisation.Caption = Localiser["organisation.caption.organisations"];
|
||||
|
||||
// Core Database connection.
|
||||
ISacsDatabase db = SaxGlobals.App.GetCoreDatabase(SessionContext);
|
||||
|
||||
// Query to count items awaiting activation.
|
||||
Dictionary<String, int> tableRowCounts = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
|
||||
List<String> query = new List<string>()
|
||||
{
|
||||
// User accounts.
|
||||
"SELECT",
|
||||
"ItemType = '" + DbQuery.FormatForCondition(nameof(Sax.DataItemType.UserAccount)) + "',",
|
||||
"ItemCount = Count(*)",
|
||||
"FROM UserAccount ua",
|
||||
"WHERE ua.Status = 'AWA'",
|
||||
// Organisations.
|
||||
"UNION SELECT",
|
||||
"ItemType = '" + DbQuery.FormatForCondition(nameof(Sax.DataItemType.Organisation)) + "',",
|
||||
"ItemCount = Count(*)",
|
||||
"FROM Organisation org",
|
||||
"WHERE org.Status = 'AWA'",
|
||||
};
|
||||
using (DbResultSet dbResultSet = DbResultSet_DataReader.ExecuteQuery(db, query.Concat("\n")))
|
||||
{
|
||||
while (dbResultSet != null && dbResultSet.NextRecord())
|
||||
{
|
||||
NamedValue.Map values = dbResultSet.GetRecordValues();
|
||||
Sax.DataItemType itemType = EnumUtil.ParseEnum(values.GetValue("ItemType").ToString(), Sax.DataItemType.Unknown);
|
||||
int itemCount = (int)values.GetValue("ItemCount").AsLong();
|
||||
switch (itemType)
|
||||
{
|
||||
case Sax.DataItemType.UserAccount:
|
||||
responseData.Stats.User.Awaiting = new AjaxResponse_Data.ItemLabelValue() { Label = Localiser["label.awaiting.activation"], Value = itemCount.ToString() };
|
||||
responseData.Stats.User.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.AwaitingLink = Url.Action("", "Organisation", new RouteValueDictionary() { { "sta", "Await" } }).TrimStart('/');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Query to count users online.
|
||||
DateTime today = DateTime.Today;
|
||||
DateTime now = DateTime.Now;
|
||||
const String online5Mins = "Online5Mins";
|
||||
const String online15Mins = "Online15Mins";
|
||||
const String online30Mins = "Online30Mins";
|
||||
const String online60Mins = "Online60Mins";
|
||||
const String onlineToday = "OnlineToday";
|
||||
const String onlineWeek = "OnlineWeek";
|
||||
const String onlineMonth = "OnlineMonth";
|
||||
query = new List<string>()
|
||||
{
|
||||
// Users Online last 5 mins.
|
||||
"Select '" + online5Mins + "' ItemType, (Select Count(*) From UserOnline Where OnlineAt>=" + DbQuery.FormatDateTimeForCondition(now.AddMinutes(-5)) + ") ItemCount ",
|
||||
"Union Select '" + online15Mins + "' ItemType, (Select Count(*) From UserOnline Where OnlineAt>=" + DbQuery.FormatDateTimeForCondition(now.AddMinutes(-15)) + ") ItemCount ",
|
||||
"Union Select '" + online30Mins + "' ItemType, (Select Count(*) From UserOnline Where OnlineAt>=" + DbQuery.FormatDateTimeForCondition(now.AddMinutes(-30)) + ") ItemCount ",
|
||||
"Union Select '" + online60Mins + "' ItemType, (Select Count(*) From UserOnline Where OnlineAt>=" + DbQuery.FormatDateTimeForCondition(now.AddMinutes(-60)) + ") ItemCount ",
|
||||
"Union Select '" + onlineToday + "' ItemType, (Select Count(*) From UserOnline Where OnlineAt>=" + DbQuery.FormatDateForCondition(today) + ") ItemCount ",
|
||||
"Union Select '" + onlineWeek + "' ItemType, (Select Count(*) From UserOnline Where OnlineAt>=" + DbQuery.FormatDateForCondition(DateUtil.StartOfWorkingWeek(today)) + ") ItemCount ",
|
||||
"Union Select '" + onlineMonth + "' ItemType, (Select Count(*) From UserOnline Where OnlineAt>=" + DbQuery.FormatDateForCondition(DateUtil.StartOfMonth(today)) + ") ItemCount ",
|
||||
};
|
||||
using (DbResultSet dbResultSet = DbResultSet_DataReader.ExecuteQuery(db, query.Concat("\n")))
|
||||
{
|
||||
while (dbResultSet != null && dbResultSet.NextRecord())
|
||||
{
|
||||
if (responseData.Stats.User.OnlineStats == null)
|
||||
responseData.Stats.User.OnlineStats = new List<AjaxResponse_Data.ItemLabelValue>();
|
||||
NamedValue.Map values = dbResultSet.GetRecordValues();
|
||||
String itemType = values.GetValue("ItemType").ToString();
|
||||
int itemCount = (int)values.GetValue("ItemCount").AsLong();
|
||||
switch (itemType)
|
||||
{
|
||||
case online5Mins:
|
||||
if (itemCount > 0)
|
||||
responseData.Stats.User.OnlineStats.Add(new AjaxResponse_Data.ItemLabelValue() { Label = Localiser["label.online.last5Mins"], Value = itemCount.ToString() });
|
||||
break;
|
||||
case online15Mins:
|
||||
if (itemCount > 0)
|
||||
responseData.Stats.User.OnlineStats.Add(new AjaxResponse_Data.ItemLabelValue() { Label = Localiser["label.online.last15Mins"], Value = itemCount.ToString() });
|
||||
break;
|
||||
case online30Mins:
|
||||
if (itemCount > 0)
|
||||
responseData.Stats.User.OnlineStats.Add(new AjaxResponse_Data.ItemLabelValue() { Label = Localiser["label.online.last30Mins"], Value = itemCount.ToString() });
|
||||
break;
|
||||
case online60Mins:
|
||||
if (itemCount > 0)
|
||||
responseData.Stats.User.OnlineStats.Add(new AjaxResponse_Data.ItemLabelValue() { Label = Localiser["label.online.last60Mins"], Value = itemCount.ToString() });
|
||||
break;
|
||||
case onlineToday:
|
||||
if (itemCount > 0)
|
||||
responseData.Stats.User.OnlineStats.Add(new AjaxResponse_Data.ItemLabelValue() { Label = Localiser["label.online.today"], Value = itemCount.ToString() });
|
||||
break;
|
||||
case onlineWeek:
|
||||
if (itemCount > 0)
|
||||
responseData.Stats.User.OnlineStats.Add(new AjaxResponse_Data.ItemLabelValue() { Label = Localiser["label.online.thisWeek"], Value = itemCount.ToString() });
|
||||
break;
|
||||
case onlineMonth:
|
||||
if (itemCount > 0)
|
||||
responseData.Stats.User.OnlineStats.Add(new AjaxResponse_Data.ItemLabelValue() { Label = Localiser["label.online.thisMonth"], Value = itemCount.ToString() });
|
||||
break;
|
||||
}
|
||||
responseData.Stats.User.OnlineLink = Url.Action("", "UsersOnline", new RouteValueDictionary() { }).TrimStart('/');
|
||||
}
|
||||
}
|
||||
|
||||
// Complete response.
|
||||
responseData.Success = true;
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -1,116 +0,0 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Dbas;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using Sarand.Net.Standard.Dbas.Data;
|
||||
using Saxonite.Net.Core.Web.Admin.Models;
|
||||
using Saxonite.Net.Standard.Base.App;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
{
|
||||
//=======================================================================
|
||||
// Home - Ajax - Awaiting Activation controller
|
||||
//=======================================================================
|
||||
partial class HomeController
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Items Awaiting Activation data.
|
||||
private class ActivationItemData
|
||||
{
|
||||
public String ItemType { get; set; }
|
||||
public String ItemTypeDesc { get; set; }
|
||||
public String ItemTypeDescPlural { get; set; }
|
||||
public long ItemCount { get; set; }
|
||||
public String ViewLink { get; set; }
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Get Items Awaiting Activation ajax request.
|
||||
//-------------------------------------------------------------------
|
||||
private class AjaxResponse_ItemsAwaitingActivation : AjaxResponse_Data
|
||||
{
|
||||
// Construction.
|
||||
public AjaxResponse_ItemsAwaitingActivation(SaxModel_Admin model) : base(model) { }
|
||||
// Table list.
|
||||
public List<ActivationItemData> Items { get; } = new List<ActivationItemData>();
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
[HttpPost]
|
||||
[Route("Home/Ajax/GetItemsAwaitingActivation")]
|
||||
public IActionResult Ajax_GetItemsAwaitingActivation(Model_Sport model)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_GetItemsAwaitingActivation";
|
||||
String messageTitle = Localiser["home.caption.application"];
|
||||
AjaxResponse_ItemsAwaitingActivation responseData = new AjaxResponse_ItemsAwaitingActivation(model);
|
||||
|
||||
// Validate session.
|
||||
if (!ValidUserSession)
|
||||
return GetAjaxResult_InvalidSession(responseData);
|
||||
|
||||
// Core Database connection.
|
||||
ISacsDatabase db = SaxGlobals.App.GetCoreDatabase(SessionContext);
|
||||
|
||||
// Query to count items awaiting activation.
|
||||
Dictionary<String, int> tableRowCounts = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
|
||||
List<String> query = new List<string>()
|
||||
{
|
||||
// User accounts.
|
||||
"SELECT",
|
||||
"ItemType = '" + DbQuery.FormatForCondition(nameof(Sax.DataItemType.UserAccount)) + "',",
|
||||
"ItemCount = Count(*)",
|
||||
"FROM UserAccount ua",
|
||||
"WHERE ua.Status = 'AWA'",
|
||||
// Organisations.
|
||||
"UNION SELECT",
|
||||
"ItemType = '" + DbQuery.FormatForCondition(nameof(Sax.DataItemType.Organisation)) + "',",
|
||||
"ItemCount = Count(*)",
|
||||
"FROM Organisation org",
|
||||
"WHERE org.Status = 'AWA'",
|
||||
};
|
||||
using (DbResultSet dbResultSet = DbResultSet_DataReader.ExecuteQuery(db, query.Concat("\n")))
|
||||
{
|
||||
while (dbResultSet != null && dbResultSet.NextRecord())
|
||||
{
|
||||
Sax.DataItemType itemType = EnumUtil.ParseEnum(dbResultSet.GetRecordValues().GetValue("ItemType").ToString(), Sax.DataItemType.Unknown);
|
||||
String itemTypeDesc = nameof(itemType);
|
||||
String itemTypeDescPlural = itemTypeDesc;
|
||||
String viewLink = "";
|
||||
switch (itemType)
|
||||
{
|
||||
case Sax.DataItemType.UserAccount:
|
||||
itemTypeDesc = "User Account";
|
||||
itemTypeDescPlural = "User Accounts";
|
||||
viewLink = Url.Action("", "User", new RouteValueDictionary() { { "sta", "Await" } }).TrimStart('/');
|
||||
break;
|
||||
case Sax.DataItemType.Organisation:
|
||||
itemTypeDesc = "Organisation";
|
||||
itemTypeDescPlural = "Organisations";
|
||||
viewLink = Url.Action("", "Organisation", new RouteValueDictionary() { { "sta", "Await" } }).TrimStart('/');
|
||||
break;
|
||||
}
|
||||
ActivationItemData activationItem = new ActivationItemData()
|
||||
{
|
||||
ItemType = nameof(itemType),
|
||||
ItemTypeDesc = itemTypeDesc,
|
||||
ItemTypeDescPlural = itemTypeDescPlural,
|
||||
ItemCount = dbResultSet.GetRecordValues().GetValue("ItemCount").AsLong(),
|
||||
ViewLink = viewLink,
|
||||
};
|
||||
responseData.Items.Add(activationItem);
|
||||
}
|
||||
}
|
||||
|
||||
// Complete response.
|
||||
responseData.Success = true;
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -45,28 +45,34 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
if (!ValidUserSession)
|
||||
return GetAjaxResult_InvalidSession(responseData);
|
||||
|
||||
if (StringUtil.IsEmpty(AppConfig.URL.Online.Root))
|
||||
return Json(responseData.SetMessage(messageTitle, "Root online URL not specified."));
|
||||
|
||||
// Identify item.
|
||||
SysId organisationId = model.OrganisationId.ToSysId();
|
||||
if (!SysId.IsValid(organisationId))
|
||||
// Record disposable items as they are created so all can be disposed when needed.
|
||||
using (DisposableCollection<SacsHierarchyItem> disposableItems = new DisposableCollection<SacsHierarchyItem>())
|
||||
{
|
||||
SaLogger.Warn(fn + " Request to get activation info without valid organisation Id.");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.specified"]));
|
||||
}
|
||||
|
||||
// Retrieve item.
|
||||
SaxOrganisation organisation = AccountMgr.GetOrganisationById(organisationId);
|
||||
if (organisation == null)
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to retrieve organisation for Id: '" + model.OrganisationId + "'");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
|
||||
}
|
||||
if (StringUtil.IsEmpty(AppConfig.URL.Online.Root))
|
||||
return Json(responseData.SetMessage(messageTitle, "Root online URL not specified."));
|
||||
|
||||
// Construct response.
|
||||
PopulateOrganisationResponseData(organisation, responseData.organisation);
|
||||
GetOrganisationMembers(model, organisationId, responseData.Members);
|
||||
// Identify item.
|
||||
SysId organisationId = model.OrganisationId.ToSysId();
|
||||
if (!SysId.IsValid(organisationId))
|
||||
{
|
||||
SaLogger.Warn(fn + " Request to get activation info without valid organisation Id.");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.specified"]));
|
||||
}
|
||||
|
||||
// Retrieve item.
|
||||
SaxOrganisation organisation = AccountMgr.GetOrganisationById(organisationId);
|
||||
disposableItems.Add(organisation);
|
||||
if (organisation == null)
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to retrieve organisation for Id: '" + model.OrganisationId + "'");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
|
||||
}
|
||||
|
||||
// Construct response.
|
||||
PopulateOrganisationResponseData(organisation, responseData.organisation);
|
||||
GetOrganisationMembers(model, organisationId, responseData.Members);
|
||||
}
|
||||
|
||||
// Complete response.
|
||||
responseData.Success = true;
|
||||
@@ -105,10 +111,14 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
if (!ValidUserSession)
|
||||
return GetAjaxResult_InvalidSession(responseData);
|
||||
|
||||
// Retrieve existing item.
|
||||
SysId organisationId = model.OrganisationId.ToSysId();
|
||||
using (SaxOrganisation organisation = AccountMgr.GetOrganisationById(organisationId))
|
||||
// Record disposable items as they are created so all can be disposed when needed.
|
||||
using (DisposableCollection<SacsDisposable> disposableItems = new DisposableCollection<SacsDisposable>())
|
||||
{
|
||||
|
||||
// Retrieve existing item.
|
||||
SysId organisationId = model.OrganisationId.ToSysId();
|
||||
SaxOrganisation organisation = AccountMgr.GetOrganisationById(organisationId);
|
||||
disposableItems.Add(organisation);
|
||||
if (organisation == null && SysId.IsValid(organisationId))
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to retrieve organisation for. : '" + model.OrganisationId + "'");
|
||||
@@ -116,93 +126,87 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
}
|
||||
|
||||
// Retrieve users.
|
||||
using (DisposableCollection<OrganisationMemberData> organisationMembersToActivate = new DisposableCollection<OrganisationMemberData>())
|
||||
List<OrganisationMemberData> organisationMembersToActivate = new List<OrganisationMemberData>();
|
||||
foreach (String userOrganisationId in model.OrganisationMemberIds)
|
||||
{
|
||||
foreach (String userOrganisationId in model.OrganisationMemberIds)
|
||||
if (userOrganisationId == null) continue;
|
||||
OrganisationMemberData organisationMember = new OrganisationMemberData();
|
||||
disposableItems.Add(organisationMember);
|
||||
organisationMember.UserOrganisation = AccountMgr.GetUserOrganisationById(userOrganisationId.ToSysId());
|
||||
organisationMember.UserAccount = AccountMgr.GetUserAccountById(organisationMember.UserOrganisation?.UserAccountId ?? null);
|
||||
if (organisationMember.UserOrganisation == null)
|
||||
{
|
||||
if (userOrganisationId == null) continue;
|
||||
OrganisationMemberData organisationMember = new OrganisationMemberData();
|
||||
organisationMember.UserOrganisation = AccountMgr.GetUserOrganisationById(userOrganisationId.ToSysId());
|
||||
organisationMember.UserAccount = AccountMgr.GetUserAccountById(organisationMember.UserOrganisation?.UserAccountId ?? null);
|
||||
if (organisationMember.UserOrganisation == null)
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to retrieve user organisation. Id: '" + userOrganisationId + "'");
|
||||
organisationMember.Dispose();
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"]));
|
||||
}
|
||||
if (organisationMember.UserAccount == null)
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to retrieve user account . Id: '" + organisationMember.UserOrganisation.UserAccountId + "'");
|
||||
organisationMember.Dispose();
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"]));
|
||||
}
|
||||
if (organisationMember.UserAccount.Status != SaStatus.Awaiting)
|
||||
{
|
||||
SaLogger.Warn(fn + " User organisation is not awaiting. Id: '" + userOrganisationId + "'. Status: " + organisationMember.UserAccount.StatusDesc);
|
||||
organisationMember.Dispose();
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"]));
|
||||
}
|
||||
// Check if this user is to be activated.
|
||||
bool activateUser = false;
|
||||
String controlName_Activate = "MemberActivate_" + userOrganisationId;
|
||||
foreach (String key in Request.Form.Keys)
|
||||
{
|
||||
if (key.EqualsCI(controlName_Activate))
|
||||
{
|
||||
activateUser = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (activateUser)
|
||||
organisationMembersToActivate.Add(organisationMember);
|
||||
else organisationMember.Dispose();
|
||||
organisationMember = null;
|
||||
SaLogger.Warn(fn + " Failed to retrieve user organisation. Id: '" + userOrganisationId + "'");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"]));
|
||||
}
|
||||
|
||||
if (organisationMembersToActivate.IsEmpty())
|
||||
if (organisationMember.UserAccount == null)
|
||||
{
|
||||
// No users to be activated.
|
||||
// Check that organisation already has active members.
|
||||
if (AccountMgr.GetOrganisationMemberCount(organisation.Id) < 1)
|
||||
SaLogger.Warn(fn + " Failed to retrieve user account . Id: '" + organisationMember.UserOrganisation.UserAccountId + "'");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"]));
|
||||
}
|
||||
if (organisationMember.UserAccount.Status != SaStatus.Awaiting)
|
||||
{
|
||||
SaLogger.Warn(fn + " User organisation is not awaiting. Id: '" + userOrganisationId + "'. Status: " + organisationMember.UserAccount.StatusDesc);
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"]));
|
||||
}
|
||||
// Check if this user is to be activated.
|
||||
bool activateUser = false;
|
||||
String controlName_Activate = "MemberActivate_" + userOrganisationId;
|
||||
foreach (String key in Request.Form.Keys)
|
||||
{
|
||||
if (key.EqualsCI(controlName_Activate))
|
||||
{
|
||||
SaLogger.Warn(fn + " Unable to activate Organisation - no active members. Id: '" + SysId.ToString(organisationId));
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["organisation.activate.msg.no.active.members"]));
|
||||
activateUser = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (activateUser)
|
||||
organisationMembersToActivate.Add(organisationMember);
|
||||
}
|
||||
|
||||
// Activate organisation.
|
||||
organisation.Status = Sarand.Net.Standard.Base.Core.SaStatus.Active;
|
||||
if (!AccountMgr.UpdateOrganisation(organisation, DbUpdateInfo))
|
||||
if (organisationMembersToActivate.IsEmpty())
|
||||
{
|
||||
// No users to be activated.
|
||||
// Check that organisation already has active members.
|
||||
if (AccountMgr.GetOrganisationMemberCount(organisation.Id) < 1)
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to update organisation [Id:" + SysId.ToString(organisation.Id) + "]: " + AccountMgr.ErrorStateMessage);
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.update.failed"] + "\n\n" + AccountMgr.ErrorStateMessage));
|
||||
SaLogger.Warn(fn + " Unable to activate Organisation - no active members. Id: '" + SysId.ToString(organisationId));
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["organisation.activate.msg.no.active.members"]));
|
||||
}
|
||||
}
|
||||
|
||||
// Activate awaiting members and send welcome email to each.
|
||||
foreach (OrganisationMemberData organisationMember in organisationMembersToActivate)
|
||||
// Activate organisation.
|
||||
organisation.Status = Sarand.Net.Standard.Base.Core.SaStatus.Active;
|
||||
if (!AccountMgr.UpdateOrganisation(organisation, DbUpdateInfo))
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to update organisation [Id:" + SysId.ToString(organisation.Id) + "]: " + AccountMgr.ErrorStateMessage);
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.update.failed"] + "\n\n" + AccountMgr.ErrorStateMessage));
|
||||
}
|
||||
|
||||
// Activate awaiting members and send welcome email to each.
|
||||
foreach (OrganisationMemberData organisationMember in organisationMembersToActivate)
|
||||
{
|
||||
if (organisationMember.UserOrganisation == null) continue;
|
||||
if (AccountMgr.UpdateUserOrganisation(organisationMember.UserOrganisation, DbUpdateInfo))
|
||||
{
|
||||
if (organisationMember.UserOrganisation == null) continue;
|
||||
if (AccountMgr.UpdateUserOrganisation(organisationMember.UserOrganisation, DbUpdateInfo))
|
||||
if (organisationMember.UserAccount == null) continue;
|
||||
organisationMember.UserAccount.Status = SaStatus.Active;
|
||||
if (AccountMgr.UpdateUserAccount(organisationMember.UserAccount, DbUpdateInfo))
|
||||
{
|
||||
if (organisationMember.UserAccount == null) continue;
|
||||
organisationMember.UserAccount.Status = SaStatus.Active;
|
||||
if (AccountMgr.UpdateUserAccount(organisationMember.UserAccount, DbUpdateInfo))
|
||||
{
|
||||
// Send activation email.
|
||||
if (SendAccountActivatedEmail(this, organisationMember.UserAccount))
|
||||
SaLogger.Info(fn + " User Activation email sent to " + organisationMember.UserAccount.EmailAddress, true);
|
||||
else SaLogger.Warn(fn + " Failed to send User Activation email to " + organisationMember.UserAccount.EmailAddress);
|
||||
}
|
||||
else
|
||||
SaLogger.Warn(fn + " Failed to update user account [Id:" + SysId.ToString(organisationMember.UserAccount.Id) + "]: " + AccountMgr.ErrorStateMessage);
|
||||
// Send activation email.
|
||||
if (SendAccountActivatedEmail(this, organisationMember.UserAccount))
|
||||
SaLogger.Info(fn + " User Activation email sent to " + organisationMember.UserAccount.EmailAddress, true);
|
||||
else SaLogger.Warn(fn + " Failed to send User Activation email to " + organisationMember.UserAccount.EmailAddress);
|
||||
}
|
||||
else
|
||||
SaLogger.Warn(fn + " Failed to update user organisation [Id:" + SysId.ToString(organisationMember.UserOrganisation.Id) + "]: " + AccountMgr.ErrorStateMessage);
|
||||
SaLogger.Warn(fn + " Failed to update user account [Id:" + SysId.ToString(organisationMember.UserAccount.Id) + "]: " + AccountMgr.ErrorStateMessage);
|
||||
}
|
||||
|
||||
// Construct response.
|
||||
PopulateOrganisationResponseData(organisation, responseData.organisation);
|
||||
else
|
||||
SaLogger.Warn(fn + " Failed to update user organisation [Id:" + SysId.ToString(organisationMember.UserOrganisation.Id) + "]: " + AccountMgr.ErrorStateMessage);
|
||||
}
|
||||
|
||||
// Construct response.
|
||||
PopulateOrganisationResponseData(organisation, responseData.organisation);
|
||||
}
|
||||
|
||||
// Complete response.
|
||||
@@ -216,7 +220,7 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
/// <para>NB URL must be to the Online application.</para>
|
||||
/// <para>NB Encryption must be done with the Online logic.</para>
|
||||
/// </summary>
|
||||
public static bool SendAccountActivatedEmail (SaxController_Admin controller, SaxUserAccount userAccount)
|
||||
public static bool SendAccountActivatedEmail(SaxController_Admin controller, SaxUserAccount userAccount)
|
||||
{
|
||||
SaEmailData emailData = new SaEmailData();
|
||||
emailData.Config = controller.EmailConfig;
|
||||
|
||||
@@ -119,6 +119,7 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
SaxUserOrganisation.Params prmUserOrganisation = new SaxUserOrganisation.Params();
|
||||
prmUserOrganisation.OrganisationIdsIncluded.Add(organisationId);
|
||||
prmUserOrganisation.OrganisationMembersOnly = true;
|
||||
prmUserOrganisation.UserAccountStatusCat = SaxUserAccount.StatusCat.AwaitingOnly;
|
||||
prmUserOrganisation.StatusCat = SaxUserOrganisation.StatusCat.NotDeleted;
|
||||
model.Paging.ItemTotal = (ulong)AccountMgr.GetUserOrganisationCount(prmUserOrganisation);
|
||||
model.PopulatePagingTo(prmUserOrganisation.ResultsPaging);
|
||||
@@ -193,37 +194,46 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
if (!ValidUserSession)
|
||||
return GetAjaxResult_InvalidSession(responseData);
|
||||
|
||||
// Identify item.
|
||||
SysId userOrganisationId = model.UserOrganisationId.ToSysId();
|
||||
if (!SysId.IsValid(userOrganisationId))
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.specified"]));
|
||||
|
||||
// Retrieve item.
|
||||
SaxUserOrganisation userOrganisation = AccountMgr.GetUserOrganisationById(userOrganisationId);
|
||||
if (userOrganisation == null)
|
||||
// Record disposable items as they are created so all can be disposed when needed.
|
||||
using (DisposableCollection<SacsHierarchyItem> disposableItems = new DisposableCollection<SacsHierarchyItem>())
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to retrieve User Organisation for Id: '" + model.UserOrganisationId + "'");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
|
||||
|
||||
// Identify item.
|
||||
SysId userOrganisationId = model.UserOrganisationId.ToSysId();
|
||||
if (!SysId.IsValid(userOrganisationId))
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.specified"]));
|
||||
|
||||
// Retrieve item.
|
||||
SaxUserOrganisation userOrganisation = AccountMgr.GetUserOrganisationById(userOrganisationId);
|
||||
disposableItems.Add(userOrganisation);
|
||||
if (userOrganisation == null)
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to retrieve User Organisation for Id: '" + model.UserOrganisationId + "'");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
|
||||
}
|
||||
|
||||
// Retrieve User Account.
|
||||
SaxUserAccount userAccount = AccountMgr.GetUserAccountById(userOrganisation.UserAccountId);
|
||||
disposableItems.Add(userAccount);
|
||||
if (userAccount == null)
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to retrieve user account for Id: '" + userOrganisation.UserAccountId + "'");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
|
||||
}
|
||||
|
||||
// Retrieve Organisation.
|
||||
SaxOrganisation organisation = AccountMgr.GetOrganisationById(userOrganisation.OrganisationId);
|
||||
disposableItems.Add(organisation);
|
||||
if (organisation == null)
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to retrieve organisation for Id: '" + userOrganisation.OrganisationId + "'");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
|
||||
}
|
||||
|
||||
// Construct response.
|
||||
PopulateMemberResponseData(responseData.Member, userOrganisation, userAccount, organisation);
|
||||
}
|
||||
|
||||
// Retrieve User Account.
|
||||
SaxUserAccount userAccount = AccountMgr.GetUserAccountById(userOrganisation.UserAccountId);
|
||||
if (userAccount == null)
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to retrieve user account for Id: '" + userOrganisation.UserAccountId + "'");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
|
||||
}
|
||||
|
||||
// Retrieve Organisation.
|
||||
SaxOrganisation organisation = AccountMgr.GetOrganisationById(userOrganisation.OrganisationId);
|
||||
if (organisation == null)
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to retrieve organisation for Id: '" + userOrganisation.OrganisationId + "'");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
|
||||
}
|
||||
|
||||
// Construct response.
|
||||
PopulateMemberResponseData(responseData.Member, userOrganisation, userAccount, organisation);
|
||||
responseData.Success = true;
|
||||
return Json(responseData);
|
||||
}
|
||||
@@ -248,94 +258,109 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
if (responseData.HasControlErrors())
|
||||
return Json(responseData);
|
||||
|
||||
// User account.
|
||||
SysId userAccountId = model.MemberUserAccountId.ToSysId();
|
||||
SaxUserAccount userAccount = null;
|
||||
if (!SysId.IsValid(userAccountId) && !StringUtil.IsEmpty(model.MemberUserEmailAddress))
|
||||
// Record disposable items as they are created so all can be disposed when needed.
|
||||
using (DisposableCollection<SacsHierarchyItem> disposableItems = new DisposableCollection<SacsHierarchyItem>())
|
||||
{
|
||||
userAccount = AccountMgr.GetUserAccountByEmailAddress(model.MemberUserEmailAddress);
|
||||
userAccountId = userAccount?.Id ?? new SysId();
|
||||
}
|
||||
if (!SysId.IsValid(userAccountId))
|
||||
{
|
||||
SaLogger.Warn(fn + " User Account must be identified");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.data.incomplete"]));
|
||||
}
|
||||
|
||||
// Organisation.
|
||||
SysId organisationId = model.MemberOrganisationId.ToSysId();
|
||||
SaxOrganisation organisation = null;
|
||||
if (!SysId.IsValid(organisationId))
|
||||
{
|
||||
SaLogger.Warn(fn + " Organisation Id must be specified");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.data.incomplete"]));
|
||||
}
|
||||
// User account.
|
||||
SysId userAccountId = model.MemberUserAccountId.ToSysId();
|
||||
SaxUserAccount userAccount = null;
|
||||
if (!SysId.IsValid(userAccountId) && !StringUtil.IsEmpty(model.MemberUserEmailAddress))
|
||||
{
|
||||
userAccount = AccountMgr.GetUserAccountByEmailAddress(model.MemberUserEmailAddress);
|
||||
disposableItems.Add(userAccount);
|
||||
userAccountId = userAccount?.Id ?? new SysId();
|
||||
}
|
||||
if (!SysId.IsValid(userAccountId))
|
||||
{
|
||||
SaLogger.Warn(fn + " User Account must be identified");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.data.incomplete"]));
|
||||
}
|
||||
|
||||
// Retrieve existing item.
|
||||
SysId userOrganisationId = model.UserOrganisationId.ToSysId();
|
||||
SaxUserOrganisation userOrganisation = AccountMgr.GetUserOrganisationById(userOrganisationId);
|
||||
if (userOrganisation == null && SysId.IsValid(userOrganisationId))
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to retrieve user organisation for Id: '" + userOrganisationId + "'");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
|
||||
}
|
||||
if (userOrganisation != null && (!userOrganisation.UserAccountId.Equals(userAccountId) || !userOrganisation.OrganisationId.Equals(organisationId)))
|
||||
{
|
||||
// Either User Account and/or Organisation Ids don't match.
|
||||
SaLogger.Warn(fn + " Inconsistent user organisation properties. UserAccountId: " + userOrganisation.UserAccountId + " vs " + userAccountId + ". OrganisationId: " + userOrganisation.OrganisationId + " vs " + organisationId + ".");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
|
||||
}
|
||||
// Organisation.
|
||||
SysId organisationId = model.MemberOrganisationId.ToSysId();
|
||||
SaxOrganisation organisation = null;
|
||||
if (!SysId.IsValid(organisationId))
|
||||
{
|
||||
SaLogger.Warn(fn + " Organisation Id must be specified");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.data.incomplete"]));
|
||||
}
|
||||
|
||||
// User Organisation not identified.
|
||||
if (userOrganisation == null)
|
||||
{
|
||||
// See whether user has an 'interest' in the organisation.
|
||||
SaxUserOrganisation.Params prmUserOrganisation = new SaxUserOrganisation.Params();
|
||||
prmUserOrganisation.UserAccountIdsIncluded.Add(userAccountId);
|
||||
prmUserOrganisation.OrganisationIdsIncluded.Add(organisationId);
|
||||
prmUserOrganisation.OrganisationMembersOnly = false;
|
||||
prmUserOrganisation.StatusCat = SaxUserOrganisation.StatusCat.Any;
|
||||
userOrganisation = AccountMgr.GetUserOrganisation(prmUserOrganisation);
|
||||
if (userOrganisation != null)
|
||||
userOrganisation.Status = SaStatus.Active;
|
||||
// Retrieve existing item.
|
||||
SysId userOrganisationId = model.UserOrganisationId.ToSysId();
|
||||
SaxUserOrganisation userOrganisation = AccountMgr.GetUserOrganisationById(userOrganisationId);
|
||||
disposableItems.Add(userOrganisation);
|
||||
if (userOrganisation == null && SysId.IsValid(userOrganisationId))
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to retrieve user organisation for Id: '" + userOrganisationId + "'");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
|
||||
}
|
||||
if (userOrganisation != null && (!userOrganisation.UserAccountId.Equals(userAccountId) || !userOrganisation.OrganisationId.Equals(organisationId)))
|
||||
{
|
||||
// Either User Account and/or Organisation Ids don't match.
|
||||
SaLogger.Warn(fn + " Inconsistent user organisation properties. UserAccountId: " + userOrganisation.UserAccountId + " vs " + userAccountId + ". OrganisationId: " + userOrganisation.OrganisationId + " vs " + organisationId + ".");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
|
||||
}
|
||||
|
||||
// User Organisation not identified.
|
||||
if (userOrganisation == null)
|
||||
{
|
||||
// See whether user has an 'interest' in the organisation.
|
||||
SaxUserOrganisation.Params prmUserOrganisation = new SaxUserOrganisation.Params();
|
||||
prmUserOrganisation.UserAccountIdsIncluded.Add(userAccountId);
|
||||
prmUserOrganisation.OrganisationIdsIncluded.Add(organisationId);
|
||||
prmUserOrganisation.OrganisationMembersOnly = false;
|
||||
prmUserOrganisation.StatusCat = SaxUserOrganisation.StatusCat.Any;
|
||||
userOrganisation = AccountMgr.GetUserOrganisation(prmUserOrganisation);
|
||||
if (userOrganisation != null)
|
||||
userOrganisation.Status = SaStatus.Active;
|
||||
else
|
||||
// Organisation not found for user.
|
||||
userOrganisation = AccountMgr.CreateUserOrganisation(userAccountId, organisationId);
|
||||
disposableItems.Add(userOrganisation);
|
||||
}
|
||||
|
||||
// Retrieve associated items.
|
||||
if (userAccount == null)
|
||||
{
|
||||
userAccount = AccountMgr.GetUserAccountById(userAccountId);
|
||||
disposableItems.Add(userAccount);
|
||||
}
|
||||
if (organisation == null)
|
||||
{
|
||||
organisation = AccountMgr.GetOrganisationById(organisationId);
|
||||
disposableItems.Add(organisation);
|
||||
}
|
||||
|
||||
// Populate item properties.
|
||||
if (model.MemberRoleCodes != null)
|
||||
userOrganisation.OrganisationRoles = SaxUserOrganisation.GetOrganisationRolesFromCodes(model.GetMemberRoleCodes());
|
||||
userOrganisation.AddOrganisationRole(Sax.OrganisationRole.Member);
|
||||
if (model.MemberStatusCode != null)
|
||||
userOrganisation.Status = model.MemberStatus;
|
||||
|
||||
// Store item.
|
||||
if (!SysId.IsValid(userOrganisation.Id))
|
||||
{
|
||||
if (!AccountMgr.InsertUserOrganisation(userOrganisation, DbUpdateInfo))
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to insert user organisation: " + AccountMgr.ErrorStateMessage);
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.insert.failed"] + "\n\n" + AccountMgr.ErrorStateMessage));
|
||||
}
|
||||
}
|
||||
else
|
||||
// Organisation not found for user.
|
||||
userOrganisation = AccountMgr.CreateUserOrganisation(userAccountId, organisationId);
|
||||
}
|
||||
|
||||
// Retrieve associated items.
|
||||
if (userAccount == null)
|
||||
userAccount = AccountMgr.GetUserAccountById(userAccountId);
|
||||
if (organisation == null)
|
||||
organisation = AccountMgr.GetOrganisationById(organisationId);
|
||||
|
||||
// Populate item properties.
|
||||
if (model.MemberRoleCodes != null)
|
||||
userOrganisation.OrganisationRoles = SaxUserOrganisation.GetOrganisationRolesFromCodes(model.GetMemberRoleCodes());
|
||||
userOrganisation.AddOrganisationRole(Sax.OrganisationRole.Member);
|
||||
if (model.MemberStatusCode != null)
|
||||
userOrganisation.Status = model.MemberStatus;
|
||||
|
||||
// Store item.
|
||||
if (!SysId.IsValid(userOrganisation.Id))
|
||||
{
|
||||
if (!AccountMgr.InsertUserOrganisation(userOrganisation, DbUpdateInfo))
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to insert user organisation: " + AccountMgr.ErrorStateMessage);
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.insert.failed"] + "\n\n" + AccountMgr.ErrorStateMessage));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!AccountMgr.UpdateUserOrganisation(userOrganisation, DbUpdateInfo))
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to update user organisation [Id:" + SysId.ToString(userOrganisation.Id) + "]: " + AccountMgr.ErrorStateMessage);
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.update.failed"] + "\n\n" + AccountMgr.ErrorStateMessage));
|
||||
if (!AccountMgr.UpdateUserOrganisation(userOrganisation, DbUpdateInfo))
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to update user organisation [Id:" + SysId.ToString(userOrganisation.Id) + "]: " + AccountMgr.ErrorStateMessage);
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.update.failed"] + "\n\n" + AccountMgr.ErrorStateMessage));
|
||||
}
|
||||
}
|
||||
|
||||
// Construct response.
|
||||
PopulateMemberResponseData(responseData.Member, userOrganisation, userAccount, organisation);
|
||||
}
|
||||
|
||||
// Construct response.
|
||||
PopulateMemberResponseData(responseData.Member, userOrganisation, userAccount, organisation);
|
||||
responseData.Success = true;
|
||||
return Json(responseData);
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
//-------------------------------------------------------------------
|
||||
[HttpPost]
|
||||
[Route("System/Ajax/GetDatabaseTables")]
|
||||
public IActionResult Ajax_GetDatabaseTables(Model_Sport model)
|
||||
public IActionResult Ajax_GetDatabaseTables(Model_System model)
|
||||
{
|
||||
String fn = GetType().Name + ".Ajax_GetDatabaseTables";
|
||||
String messageTitle = Localiser["system.caption.database"];
|
||||
@@ -83,6 +83,10 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
List<DbDfnTable> tableDfns = db.GetTableDfns();
|
||||
foreach (DbDfnTable tableDfn in tableDfns.OrderBy(item => item.Name))
|
||||
{
|
||||
// Filter by table name.
|
||||
if (!StringUtil.IsEmpty(model.DatabaseFilter.Table) && !tableDfn.Name.ContainsCI(model.DatabaseFilter.Table))
|
||||
continue;
|
||||
|
||||
DatabaseTableData tableData = new DatabaseTableData();
|
||||
tableData.SchemaName = tableDfn.Schema;
|
||||
tableData.TableName = tableDfn.Name;
|
||||
|
||||
@@ -211,7 +211,7 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
{
|
||||
|
||||
// Identify item.
|
||||
SysId userAccountId = model.UserAccountId.ToSysId();
|
||||
SysId userAccountId = model.UserId.ToSysId();
|
||||
if (!SysId.IsValid(userAccountId))
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.specified"]));
|
||||
|
||||
@@ -302,12 +302,12 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
{
|
||||
|
||||
// Retrieve existing item.
|
||||
SysId userAccountId = model.UserAccountId.ToSysId();
|
||||
SysId userAccountId = model.UserId.ToSysId();
|
||||
SaxUserAccount user = AccountMgr.GetUserAccountById(userAccountId);
|
||||
disposableItems.Add(user);
|
||||
if (user == null && SysId.IsValid(userAccountId))
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to retrieve user for Id: '" + model.UserAccountId + "'");
|
||||
SaLogger.Warn(fn + " Failed to retrieve user for Id: '" + model.UserId + "'");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
|
||||
}
|
||||
|
||||
@@ -428,12 +428,12 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
{
|
||||
|
||||
// Retrieve user.
|
||||
SysId userAccountId = model.UserAccountId.ToSysId();
|
||||
SysId userAccountId = model.UserId.ToSysId();
|
||||
SaxUserAccount userAccount = AccountMgr.GetUserAccountById(userAccountId);
|
||||
disposableItems.Add(userAccount);
|
||||
if (userAccount == null)
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to retrieve user for Id: '" + model.UserAccountId + "'");
|
||||
SaLogger.Warn(fn + " Failed to retrieve user for Id: '" + model.UserId + "'");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
|
||||
}
|
||||
|
||||
|
||||
@@ -160,7 +160,7 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
|
||||
{
|
||||
|
||||
// Identify item.
|
||||
SysId userAccountId = model.UserAccountId.ToSysId();
|
||||
SysId userAccountId = model.UserId.ToSysId();
|
||||
if (!SysId.IsValid(userAccountId))
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.specified"]));
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ namespace Saxonite.Net.Core.Web.Admin.Models
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// User properties.
|
||||
public String UserAccountId { get; set; }
|
||||
public String UserId { get; set; }
|
||||
[EmailAddress]
|
||||
public String UserEmailAddress { get; set; }
|
||||
public String UserTitle { get; set; }
|
||||
@@ -115,7 +115,7 @@ namespace Saxonite.Net.Core.Web.Admin.Models
|
||||
{
|
||||
// Check for duplicate email address.
|
||||
SaxUserAccount.Params prmUserAccount = new SaxUserAccount.Params();
|
||||
SysId userAccountId = UserAccountId.ToSysId();
|
||||
SysId userAccountId = UserId.ToSysId();
|
||||
if (SysId.IsValid(userAccountId))
|
||||
prmUserAccount.IdsExcluded.Add(userAccountId);
|
||||
prmUserAccount.EmailAddress = UserEmailAddress;
|
||||
|
||||
@@ -138,8 +138,8 @@
|
||||
<data name="home.caption.application" xml:space="preserve">
|
||||
<value>Admin</value>
|
||||
</data>
|
||||
<data name="home.caption.awaiting.activation" xml:space="preserve">
|
||||
<value>Awaiting Activation</value>
|
||||
<data name="home.caption.application.status" xml:space="preserve">
|
||||
<value>Application Status</value>
|
||||
</data>
|
||||
<data name="home.caption.home" xml:space="preserve">
|
||||
<value>Home</value>
|
||||
@@ -165,6 +165,9 @@
|
||||
<data name="label.available" xml:space="preserve">
|
||||
<value>Available</value>
|
||||
</data>
|
||||
<data name="label.awaiting.activation" xml:space="preserve">
|
||||
<value>Awaiting activation</value>
|
||||
</data>
|
||||
<data name="label.cancel" xml:space="preserve">
|
||||
<value>Cancel</value>
|
||||
</data>
|
||||
@@ -267,6 +270,9 @@
|
||||
<data name="label.members" xml:space="preserve">
|
||||
<value>Members</value>
|
||||
</data>
|
||||
<data name="label.members.awaiting.activation" xml:space="preserve">
|
||||
<value>Members awaiting activation</value>
|
||||
</data>
|
||||
<data name="label.name" xml:space="preserve">
|
||||
<value>Name</value>
|
||||
</data>
|
||||
@@ -282,6 +288,27 @@
|
||||
<data name="label.ok" xml:space="preserve">
|
||||
<value>OK</value>
|
||||
</data>
|
||||
<data name="label.online.last15Mins" xml:space="preserve">
|
||||
<value>Online last 15 mins</value>
|
||||
</data>
|
||||
<data name="label.online.last30Mins" xml:space="preserve">
|
||||
<value>Online last 30 mins</value>
|
||||
</data>
|
||||
<data name="label.online.last5Mins" xml:space="preserve">
|
||||
<value>Online last 5 mins</value>
|
||||
</data>
|
||||
<data name="label.online.last60Mins" xml:space="preserve">
|
||||
<value>Online last 60 mins</value>
|
||||
</data>
|
||||
<data name="label.online.thisMonth" xml:space="preserve">
|
||||
<value>Online this month</value>
|
||||
</data>
|
||||
<data name="label.online.thisWeek" xml:space="preserve">
|
||||
<value>Online this week</value>
|
||||
</data>
|
||||
<data name="label.online.today" xml:space="preserve">
|
||||
<value>Online today</value>
|
||||
</data>
|
||||
<data name="label.page.info" xml:space="preserve">
|
||||
<value>Page {0} of {1}</value>
|
||||
</data>
|
||||
|
||||
@@ -7,27 +7,46 @@
|
||||
sax.msg.noItemsAwaitAct = '@Localiser.GetJavascriptText("home.msg.no.items.awaiting.activation")';
|
||||
sax.msg.dbSchemaValid = '@Localiser.GetJavascriptText("system.msg.database.schema.valid")';
|
||||
</script>
|
||||
<style>
|
||||
table.sax-item-stats .sax-value
|
||||
{
|
||||
min-width: 80px;
|
||||
text-align: right;
|
||||
}
|
||||
table.sax-item-stats tr:hover .sax-value
|
||||
{
|
||||
text-decoration: underline;
|
||||
}
|
||||
</style>
|
||||
|
||||
@* Items Awaiting Activation *@
|
||||
<div class="sax-panel-info sax-panel-results AwaitActivate">
|
||||
<div class="sax-panel-info sax-panel-results ApplicationStats">
|
||||
|
||||
<div class="sax-header">
|
||||
<div class="sax-caption">@Localiser["home.caption.awaiting.activation"]</div>
|
||||
<div class="sax-caption">@Localiser["home.caption.application.status"]</div>
|
||||
</div>
|
||||
<div class="sax-content">
|
||||
<div class="sax-panel-messages"></div>
|
||||
<div class="sax-panel-item-list"></div>
|
||||
@* Items awaiting activation templates *@
|
||||
<div class="sax-panel-item-template">
|
||||
<div class="sax-panel-item AwaitActivateItem">
|
||||
<div class="sax-panel-item sax-item-stats">
|
||||
<div class="sax-header">
|
||||
<div class="sax-caption sax-action sax-view AwaitActivateItemType"></div>
|
||||
<div class="sax-caption sax-view "></div>
|
||||
</div>
|
||||
<div class="sax-content">
|
||||
<div class="SchemaIndex">@(Localiser["label.items.awaiting.activation"]): <span class="AwaitActivateItemCount"></span></div>
|
||||
<table class="sax-item-stats"></table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<table>
|
||||
<tbody class="sax-panel-item-template">
|
||||
<tr class="sax-item-stat sax-action">
|
||||
<td class="sax-label"></td>
|
||||
<td class="sax-value"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
<div class="row pb4">
|
||||
<div class="col-sm-5 sax-label text-left text-sm-right">@Localiser["label.category"]</div>
|
||||
<div class="col-sm-7">
|
||||
@Html.DropDownListFor(model => model.Filter.OrganisationCategoryCode, Model.OrganisationCategoriesForSelect, Localiser["label.any"], new { @id = "", @class = "FilterOrganisationCategory sax-select" })
|
||||
@Html.DropDownListFor(model => model.Filter.OrganisationCategoryCode, Model.AdminOrganisationCategoriesForSelect, Localiser["label.any"], new { @id = "", @class = "FilterOrganisationCategory sax-select" })
|
||||
</div>
|
||||
</div>
|
||||
@* Organisation sport *@
|
||||
|
||||
@@ -68,19 +68,21 @@
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div>Members awaiting activation.</div>
|
||||
<table class="OrganisationMembers"></table>
|
||||
<div class="sax-panel-item-template">
|
||||
<table>
|
||||
<tr class="sax-item Member">
|
||||
<td>
|
||||
<input type="hidden" name="OrganisationMemberIds" class="MemberId" />
|
||||
<input type="checkbox" class="MemberActivate" checked="checked" />
|
||||
</td>
|
||||
<td class="MemberEmail center"></td>
|
||||
<td class="MemberName"></td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="MembersAwaitingActivation">
|
||||
<div>@Localiser["label.members.awaiting.activation"]:</div>
|
||||
<table class="OrganisationMembers"></table>
|
||||
<div class="sax-panel-item-template">
|
||||
<table>
|
||||
<tr class="sax-item Member">
|
||||
<td>
|
||||
<input type="hidden" name="OrganisationMemberIds" class="MemberId" />
|
||||
<input type="checkbox" class="MemberActivate" checked="checked" />
|
||||
</td>
|
||||
<td class="MemberEmail center"></td>
|
||||
<td class="MemberName"></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
<label for="cbOrganisationCategory"><span>@Localiser["label.category"]</span> <span class="required">*</span></label>
|
||||
</div>
|
||||
<div class="sax-control">
|
||||
@Html.DropDownListFor(model => model.OrganisationCategoryValue, Model.OrganisationCategoriesForSelect, Localiser["label.select"], new { @id = "cbOrganisationCategory", @class = "OrganisationCategory sax-select" })
|
||||
@Html.DropDownListFor(model => model.OrganisationCategoryValue, Model.AdminOrganisationCategoriesForSelect, Localiser["label.select"], new { @id = "cbOrganisationCategory", @class = "OrganisationCategory sax-select" })
|
||||
</div>
|
||||
<div class="sax-message"></div>
|
||||
</div>
|
||||
@@ -78,14 +78,15 @@
|
||||
<div class="row">
|
||||
<div class="col-sm-4">
|
||||
<div class="sax-label">
|
||||
<label for="ifOrganisationSportCaption"><span>@Localiser["label.sport"]</span> <span class="required">*</span></label>
|
||||
<label for="ifOrganisationSportCaption"><span>@Localiser["label.sport"]</span> <span class="required">(*)</span></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="sax-control row">
|
||||
@Html.HiddenFor(model => model.OrganisationSportId, new { @id = "ifOrganisationSportId", @class = "OrganisationSportId" })
|
||||
<div class="col"><input type="text" id="ifOrganisationSportCaption" class="OrganisationSportCaption sax-input" readonly="readonly" ondblclick="sax.selectSport()" /> </div>
|
||||
<div class="fixed"><button id="pbSelectSport" class="sax-button" style="min-width:auto;margin-left:4px;padding:4px 6px" onclick="sax.selectSport()">@Localiser["label.select"]</button></div>
|
||||
<div class="col"><input type="text" id="ifOrganisationSportCaption" class="OrganisationSportCaption sax-input" readonly="readonly" /> </div>
|
||||
<div class="fixed"><div class="sax-action OrganisationSportClear"><img src="~/img/action/delete24.png" alt="@(Localiser["label.clear"])" title="@(Localiser["label.clear"])" /></div></div>
|
||||
<div class="fixed"><button id="pbSelectSport" class="sax-button" style="min-width:auto;margin-left:4px;padding:4px 6px">@Localiser["label.select"]</button></div>
|
||||
</div>
|
||||
<div class="sax-message"></div>
|
||||
</div>
|
||||
@@ -103,8 +104,8 @@
|
||||
<div class="col-sm">
|
||||
<div class="sax-control row">
|
||||
@Html.HiddenFor(model => model.OrganisationRegionIdCountry, new { @id = "ifOrganisationRegionIdCountry", @class = "OrganisationRegionIdCountry" })
|
||||
<div class="col"><input type="text" id="ifOrganisationRegionCaptionCountry" class="OrganisationRegionCaptionCountry sax-input" readonly="readonly" ondblclick="sax.selectRegion()" /> </div>
|
||||
<div class="fixed"><button id="pbSelectRegion" class="sax-button" style="min-width:auto;margin-left:4px;padding:4px 6px" onclick="sax.selectRegion()">@Localiser["label.select"]</button></div>
|
||||
<div class="col"><input type="text" id="ifOrganisationRegionCaptionCountry" class="OrganisationRegionCaptionCountry sax-input" readonly="readonly" /> </div>
|
||||
<div class="fixed"><button id="pbSelectRegion" class="sax-button" style="min-width:auto;margin-left:4px;padding:4px 6px">@Localiser["label.select"]</button></div>
|
||||
</div>
|
||||
<div class="sax-message"></div>
|
||||
</div>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmDatabaseFilter", @class = "sax-form", @onSubmit = "return false;" }))
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col-sm-5 sax-label text-left text-sm-right">@Localiser["label.database.table"]</div>
|
||||
<div class="col-sm-5 sax-label text-left text-sm-right">@Localiser["label.search"]</div>
|
||||
<div class="col-sm-7">@Html.TextBoxFor(model => model.DatabaseFilter.Table, new { @id = "ifFilterDatabaseTable", @class = "FilterDatabaseTable", @maxlength = "32" })</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -15,14 +15,14 @@
|
||||
</script>
|
||||
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmUserId", @class = "sax-form" }))
|
||||
{
|
||||
@Html.HiddenFor(model => model.UserAccountId, new { @class = "UserAccountId" })
|
||||
@Html.HiddenFor(model => model.UserId, new { @class = "UserId" })
|
||||
}
|
||||
<div id="dlgUser" class="sax-dialog" title="">
|
||||
<div class="spacer"></div>
|
||||
|
||||
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmUser", @class = "sax-form", @onSubmit = "return false;" }))
|
||||
{
|
||||
@Html.HiddenFor(model => model.UserAccountId, new { @class = "UserAccountId" })
|
||||
@Html.HiddenFor(model => model.UserId, new { @class = "UserId" })
|
||||
|
||||
@* User email *@
|
||||
<div class="sax-form-control UserEmailAddress">
|
||||
@@ -181,7 +181,7 @@
|
||||
<div class="spacer"></div>
|
||||
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmUserEmails", @class = "sax-form", @onSubmit = "return false;" }))
|
||||
{
|
||||
@Html.HiddenFor(model => model.UserAccountId, new { @class = "UserAccountId" })
|
||||
@Html.HiddenFor(model => model.UserId, new { @class = "UserId" })
|
||||
|
||||
<div class="sax-para">@Localiser["user.emails.intro"]</div>
|
||||
<div class="spacer2"></div>
|
||||
|
||||
@@ -346,6 +346,8 @@ a:focus
|
||||
.ui-dialog.ui-widget.ui-widget-content.ui-corner-all
|
||||
{
|
||||
border-radius: 6px;
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
|
||||
.ui-dialog.ui-widget .ui-widget-header
|
||||
@@ -375,11 +377,14 @@ a:focus
|
||||
|
||||
.ui-dialog .ui-dialog-buttonpane
|
||||
{
|
||||
padding: 4px 8px;
|
||||
border-color: #d4af37;
|
||||
}
|
||||
|
||||
.ui-dialog .ui-dialog-buttonpane button
|
||||
{
|
||||
min-width:80px;
|
||||
margin:4px 8px 4px 0;
|
||||
color: #fff;
|
||||
background-color: #d4af37;
|
||||
border-color: #d4af37;
|
||||
|
||||
@@ -5,68 +5,84 @@
|
||||
(function (win, doc, undef)
|
||||
{
|
||||
"use strict";
|
||||
let $pnl = sax.$pnl, $dlg = sax.$dlg, $frm = sax.$frm;
|
||||
let ah = sax.adminHome = {};
|
||||
let $pnl = ah.$pnl = {}, $dlg = ah.$dlg = {}, $frm = ah.$frm = {};
|
||||
sax.itemIdPrefix = 'Itm_';
|
||||
|
||||
//--------------------------------------------------------------
|
||||
sax.refreshAwaitActivate = function (delay)
|
||||
ah.refreshApplicationStats = function (delay)
|
||||
{
|
||||
clearTimeout(ah.toStats);
|
||||
if (sax.awaitingLogin) return;
|
||||
if (!sax.awaitingRefreshResponse)
|
||||
if (!ah.awaitingStatsResponse)
|
||||
{
|
||||
var $items = $('.sax-panel-item-list', $pnl.awaitAct).fadeOut(200).empty();
|
||||
var $msgs = $('.sax-panel-messages', $pnl.awaitAct).hide().empty().append($('<div class="sax-message">' + sax.msg.dataQuerying + '</div>')).fadeIn(200);
|
||||
var $items = $('.sax-panel-item-list', $pnl.appStats).fadeOut(200).empty();
|
||||
var $msgs = $('.sax-panel-messages', $pnl.appStats).hide().empty().append($('<div class="sax-message">' + sax.msg.dataQuerying + '</div>')).fadeIn(200);
|
||||
}
|
||||
sax.ajax.awaitAct = sax.ajax.awaitAct || { url: sax.url.base + 'Home/Ajax/GetItemsAwaitingActivation', formId: 'frmNavigate', callbackFn: sax.handleAwaitActivateResponse, noWaitIcon: true };
|
||||
sax.ajax.awaitAct = sax.ajax.awaitAct || { url: sax.url.base + 'Home/Ajax/GetApplicationStats', formId: 'frmNavigate', callbackFn: ah.handleStatsResponse, noWaitIcon: true };
|
||||
sax.doAjaxRequest(sax.ajax.awaitAct, delay || 50);
|
||||
sax.awaitingRefreshResponse = true;
|
||||
ah.awaitingStatsResponse = true;
|
||||
}
|
||||
sax.handleAwaitActivateResponse = function (response)
|
||||
ah.handleStatsResponse = function (response)
|
||||
{
|
||||
//sax.debug('handleAwaitActivateResponse', response);
|
||||
delete sax.awaitingRefreshResponse;
|
||||
var $msgs = $('.sax-panel-messages', $pnl.awaitAct).hide().empty();
|
||||
var $items = $('.sax-panel-item-list', $pnl.awaitAct).hide().empty();
|
||||
var $tmpl = $('.sax-panel-item-template .sax-panel-item.AwaitActivateItem', $pnl.awaitAct);
|
||||
delete ah.awaitingStatsResponse;
|
||||
var $msgs = $('.sax-panel-messages', $pnl.appStats).hide().empty();
|
||||
var $items = $('.sax-panel-item-list', $pnl.appStats).hide().empty();
|
||||
ah.toStats = setTimeout(ah.refreshApplicationStats, 60000);
|
||||
if (!response.success) return;
|
||||
// Items.
|
||||
var items = response.items;
|
||||
if (!items.length)
|
||||
return $msgs.append($('<div class="sax-message">' + sax.msg.noItemsAwaitAct + '</div>')).fadeIn(500);
|
||||
for (let itemIdx = 0; itemIdx < items.length; itemIdx++)
|
||||
$items.append(sax.populateAwaitActivateItem($tmpl.clone(), items[itemIdx]));
|
||||
//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);
|
||||
// Organisations.
|
||||
let org = response.stats.organisation;
|
||||
let $org = sax.getAppStatItemTemplate();
|
||||
$('.sax-header .sax-caption', $org).text(org.caption||'Organisations');
|
||||
ah.populateAppStat($org, org.awaiting.label, org.awaiting.value, org.awaitingLink)
|
||||
$items.append($org);
|
||||
$items.slideDown(750);
|
||||
}
|
||||
sax.populateAwaitActivateItem = function ($item, item)
|
||||
ah.populateAppStat = function ($item, label, value, link)
|
||||
{
|
||||
if (!item) return;
|
||||
if (item.viewLink)$('.sax-action.sax-view', $item).on('click', function () { sax.goToPage(item.viewLink); });
|
||||
$('.AwaitActivateItemType', $item).text(item.itemTypeDescPlural);
|
||||
$('.AwaitActivateItemCount', $item).text(item.itemCount);
|
||||
let $stat = sax.getAppStatStatTemplate();
|
||||
$stat.on('click', function () { win.location = link; });
|
||||
$('.sax-label', $stat).text(label + ':');
|
||||
$('.sax-value', $stat).text(value);
|
||||
$('table.sax-item-stats', $item).append($stat);
|
||||
return $item;
|
||||
}
|
||||
sax.getAwaitActivateItemTemplate = function ()
|
||||
sax.getAppStatItemTemplate = function ()
|
||||
{
|
||||
return $('.sax-panel-item-template .sax-panel-item.AwaitActivateItem', $pnl.results).clone();
|
||||
return $('.sax-panel-item-template .sax-panel-item.sax-item-stats', $pnl.appStats).clone();
|
||||
}
|
||||
sax.getAppStatStatTemplate = function ()
|
||||
{
|
||||
return $('.sax-panel-item-template .sax-item-stat', $pnl.appStats).clone();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
sax.refreshDbSchema = function (delay)
|
||||
{
|
||||
if (sax.awaitingLogin) return;
|
||||
if (!sax.awaitingRefreshResponse)
|
||||
if (!ah.awaitingSchemaResponse)
|
||||
{
|
||||
var $items = $('.sax-panel-item-list', $pnl.dbSchema).fadeOut(200).empty();
|
||||
var $msgs = $('.sax-panel-messages', $pnl.dbSchema).hide().empty().append($('<div class="sax-message">' + sax.msg.dataQuerying + '</div>')).fadeIn(200);
|
||||
}
|
||||
sax.ajax.dbSchema = sax.ajax.dbSchema || { url: sax.url.base + 'System/Ajax/ValidateDatabaseSchema', formId: 'frmNavigate', callbackFn: sax.handleDbSchemaResponse, noWaitIcon: true };
|
||||
sax.doAjaxRequest(sax.ajax.dbSchema, delay || 50);
|
||||
sax.awaitingRefreshResponse = true;
|
||||
ah.awaitingSchemaResponse = true;
|
||||
}
|
||||
sax.handleDbSchemaResponse = function (response)
|
||||
{
|
||||
//sax.debug('handleDbSchemaResponse', response);
|
||||
delete sax.awaitingRefreshResponse;
|
||||
delete ah.awaitingSchemaResponse;
|
||||
var $msgs = $('.sax-panel-messages', $pnl.dbSchema).hide().empty();
|
||||
var $items = $('.sax-panel-item-list', $pnl.dbSchema).hide().empty();
|
||||
var $tmpl = $('.sax-panel-item-template .sax-panel-item.DbSchemaItem', $pnl.dbSchema);
|
||||
@@ -95,11 +111,11 @@
|
||||
//--------------------------------------------------------------
|
||||
$(function ()
|
||||
{
|
||||
$pnl.awaitAct = $('.sax-panel-results.AwaitActivate');
|
||||
$pnl.appStats = $('.sax-panel-results.ApplicationStats');
|
||||
$pnl.dbSchema = $('.sax-panel-results.DbSchema');
|
||||
|
||||
setTimeout(sax.refreshAwaitActivate, 250);
|
||||
setTimeout(sax.refreshDbSchema, 250);
|
||||
ah.toStats = setTimeout(ah.refreshApplicationStats, 400);
|
||||
ah.toSchema = setTimeout(sax.refreshDbSchema, 600);
|
||||
});
|
||||
|
||||
}(window, window.document));
|
||||
|
||||
@@ -359,18 +359,18 @@
|
||||
// Session.
|
||||
sax.configureKeepLoggedIn = function (single)
|
||||
{
|
||||
sax.debug('KeepLoggedIn Configuring');
|
||||
//sax.debug('KeepLoggedIn Configuring');
|
||||
let kli = sax.kli;
|
||||
if (!kli.timeout) kli.timeout = setTimeout(function () { sax.doKeepLoggedIn(single); }, Math.max(30000, kli.interval || 300000));
|
||||
}
|
||||
sax.doKeepLoggedIn = function (single)
|
||||
{
|
||||
sax.debug('KeepLoggedIn Calling');
|
||||
//sax.debug('KeepLoggedIn Calling');
|
||||
let kli = sax.kli;
|
||||
delete kli.timeout;
|
||||
var onKeepLoggedIn = function (response)
|
||||
{
|
||||
sax.debug('KeepLoggedIn Responded', response);
|
||||
//sax.debug('KeepLoggedIn Responded', response);
|
||||
kli.lastAt = sax.getTime();
|
||||
if (!single) sax.configureKeepLoggedIn();
|
||||
}
|
||||
@@ -378,13 +378,13 @@
|
||||
}
|
||||
sax.configureSessionRefresh = function ()
|
||||
{
|
||||
sax.debug('SessionRefresh Configuring');
|
||||
//sax.debug('SessionRefresh Configuring');
|
||||
$(document).on('mousedown mousemove touchstart scroll keydown', sax.triggeRefreshSession);
|
||||
}
|
||||
sax.triggeRefreshSession = function ()
|
||||
{
|
||||
if (sax.kli.timeout) return;
|
||||
sax.debug('SessionRefresh Triggering');
|
||||
//sax.debug('SessionRefresh Triggering');
|
||||
sax.configureKeepLoggedIn(1);
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
}
|
||||
op.getItemTemplate = function ()
|
||||
{
|
||||
return $('.sax-panel-item-template .sax-panel-item.Organisation', $pnl.results);
|
||||
return $('.sax-panel-item-template .sax-panel-item.Organisation', $pnl.results).clone();
|
||||
}
|
||||
op.getDropdownItemTemplate = function ()
|
||||
{
|
||||
@@ -36,7 +36,6 @@
|
||||
sax.refreshControlValues(response.controlValues);
|
||||
var $msgs = $('.sax-panel-messages', $pnl.results).hide().empty();
|
||||
var $items = $('.sax-panel-item-list', $pnl.results).hide().empty();
|
||||
var $tmpl = op.getItemTemplate();
|
||||
sax.refreshPaging(response, '#frmOrganisationFilter', sax.refreshResults);
|
||||
if (!response.success) return;
|
||||
// Reference data - Statuses.
|
||||
@@ -48,12 +47,7 @@
|
||||
if (!items.length)
|
||||
return $msgs.append($('<div class="sax-message">' + sax.msg.dataNoneFound + '</div>')).fadeIn(500);
|
||||
for (let itemIdx = 0; itemIdx < items.length; itemIdx++)
|
||||
{
|
||||
let item = items[itemIdx];
|
||||
let $item = $tmpl.clone();
|
||||
op.populateItem($item, item);
|
||||
$items.append($item);
|
||||
}
|
||||
$items.append(op.populateItem(op.getItemTemplate(), items[itemIdx]));
|
||||
$items.fadeIn(50);
|
||||
}
|
||||
op.populateItem = function ($item, item)
|
||||
@@ -65,17 +59,17 @@
|
||||
$('.OrganisationCategory', $item).text(item.categoryDesc);
|
||||
$('.OrganisationSport', $item).text(item.sportName);
|
||||
$('.OrganisationRegion', $item).text(item.regionName);
|
||||
$('.OrganisationMemberCount', $item).on('click', function () { sax.onClickMemberCount(item.id); }).find('.MemberCount').text(item.memberCount);
|
||||
$('.OrganisationMemberCount', $item).on('click', function () { op.onClickMemberCount(item.id); }).find('.MemberCount').text(item.memberCount);
|
||||
$('.StatusDesc', $item).text(item.statusDesc).addClass('sax-status-' + item.statusCode.toLowerCase());
|
||||
$('.sax-caption .sax-action').toggleClass('sax-action', !item.deleted);
|
||||
if (!item.deleted)
|
||||
{
|
||||
let $mnu = $('ul.sax-dropdown-menu', $item);
|
||||
$mnu.append(op.getDropdownItemTemplate().clone().find('div.sax-label').text(sax.lbl.edit).end().on('click', function () { sax.updateItem(item.id) }));
|
||||
$mnu.append(op.getDropdownItemTemplate().clone().find('div.sax-label').text(sax.lbl.edit).end().on('click', function () { op.updateItem(item, $item) }));
|
||||
if (item.awaiting)
|
||||
$mnu.append(op.getDropdownItemTemplate().clone().find('div.sax-label').text(sax.lbl.activate).end().on('click', function () { sax.activateItem(item.id) }));
|
||||
$('.sax-header .sax-action.sax-item-update', $item).off('click').on('click', function () { sax.updateItem(item.id) });
|
||||
$item.off('dblclick').on('dblclick', function () { sax.updateItem(item.id) });
|
||||
$mnu.append(op.getDropdownItemTemplate().clone().find('div.sax-label').text(sax.lbl.activate).end().on('click', function () { op.activateItem(item) }));
|
||||
$('.sax-header .sax-action.sax-item-update', $item).off('click').on('click', function () { op.updateItem(item, $item) });
|
||||
$item.off('dblclick').on('dblclick', function () { op.updateItem(item, $item) });
|
||||
}
|
||||
$('.sax-burger', $item).toggle(!!$('.sax-burger .sax-dropdown-menu .sax-dropdown-item', $item).length);
|
||||
$('.sax-panel-messages', $pnl.results).hide().empty();
|
||||
@@ -118,22 +112,26 @@
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
sax.selectSport = function ()
|
||||
op.selectOrgSport = function ()
|
||||
{
|
||||
if (!op.data.sports)
|
||||
op.populateSports(sax.showSelectSport);
|
||||
else sax.showSelectSport();
|
||||
op.populateSports(op.showSelectOrgSport);
|
||||
else op.showSelectOrgSport();
|
||||
}
|
||||
sax.showSelectSport = function ()
|
||||
op.showSelectOrgSport = function ()
|
||||
{
|
||||
sax.data.selectItem.fn.selectItem({ caption: sax.dlg.title.selectSport, items: op.data.sports, fnCallback: sax.onSportSelected });
|
||||
sax.data.selectItem.fn.selectItem({ caption: sax.dlg.title.selectSport, items: op.data.sports, fnCallback: op.onOrgSportSelected });
|
||||
}
|
||||
sax.onSportSelected = function (spt)
|
||||
op.onOrgSportSelected = function (spt)
|
||||
{
|
||||
let frm = $frm.org;
|
||||
$('.OrganisationSportId', frm).val(spt.id);
|
||||
$('.OrganisationSportCaption', frm).val(spt.name);
|
||||
sax.clearControlError($('.OrganisationSportCaption', frm));
|
||||
sax.clearControlError($('.OrganisationSportId', frm));
|
||||
}
|
||||
op.clearOrgSport = function ()
|
||||
{
|
||||
$('.OrganisationSportId,.OrganisationSportCaption', $frm.org).val('');
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
@@ -173,17 +171,17 @@
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
sax.selectRegion = function ()
|
||||
op.selectOrgRegion = function ()
|
||||
{
|
||||
if (!op.data.regions)
|
||||
op.populateRegions(sax.showSelectRegion);
|
||||
else sax.showSelectRegion();
|
||||
op.populateRegions(op.showSelectOrgRegion);
|
||||
else op.showSelectOrgRegion();
|
||||
}
|
||||
sax.showSelectRegion = function ()
|
||||
op.showSelectOrgRegion = function ()
|
||||
{
|
||||
sax.data.selectItem.fn.selectItem({ caption: sax.dlg.title.selectRegion, items: op.data.regions, fnCallback: sax.onRegionSelected });
|
||||
sax.data.selectItem.fn.selectItem({ caption: sax.dlg.title.selectRegion, items: op.data.regions, fnCallback: op.onOrgRegionSelected });
|
||||
}
|
||||
sax.onRegionSelected = function (rgn)
|
||||
op.onOrgRegionSelected = function (rgn)
|
||||
{
|
||||
//sax.debug('onRegionSelected', rgn);
|
||||
let frm = $frm.org;
|
||||
@@ -193,30 +191,34 @@
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
sax.createItem = function ()
|
||||
op.createItem = function ()
|
||||
{
|
||||
op.clearItem();
|
||||
$dlg.organisation.dialog('option', 'title', sax.dlg.title.createOrganisation);
|
||||
sax.openDialog($dlg.organisation, 600, 480);
|
||||
}
|
||||
op.clearItem = function ()
|
||||
{
|
||||
let frm = $frm.org;
|
||||
$('.OrganisationId,.OrganisationSportId,.OrganisationRegionIdCountry,input[type="text"],textarea,select', frm).val('');
|
||||
$('.OrganisationStatus', frm).val(sax.data.defaultStatusCode);
|
||||
sax.clearControlErrors();
|
||||
$dlg.organisation.dialog('option', 'title', sax.dlg.title.createOrganisation);
|
||||
sax.openDialog($dlg.organisation, 600, 480);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
sax.updateItem = function (id)
|
||||
op.updateItem = function (item, $item)
|
||||
{
|
||||
$('.OrganisationId', $frm.orgId).val(id);
|
||||
op.ajax.updateItem = op.ajax.updateItem || { url: sax.url.base + 'Organisation/Ajax/GetItem', formId: 'frmOrganisationId', callbackFn: sax.onUpdateItem };
|
||||
$('.OrganisationId', $frm.orgId).val(item.id);
|
||||
op.ajax.updateItem = op.ajax.updateItem || { url: sax.url.base + 'Organisation/Ajax/GetItem', formId: 'frmOrganisationId', callbackFn: op.onUpdateItem };
|
||||
sax.doAjaxRequest(op.ajax.updateItem, 50);
|
||||
}
|
||||
sax.onUpdateItem = function (response)
|
||||
op.onUpdateItem = function (response)
|
||||
{
|
||||
//sax.debug('onUpdateItem', response);
|
||||
let frm = $frm.org;
|
||||
$('.OrganisationId,input[type="text"],textarea,select', frm).val('');
|
||||
op.clearItem();
|
||||
if (!response.success) return;
|
||||
let item = response.organisation;
|
||||
let frm = $frm.org;
|
||||
$('.OrganisationId', frm).val(item.id);
|
||||
$('.OrganisationName', frm).val(item.name);
|
||||
$('.OrganisationType', frm).val(item.typeCode);
|
||||
@@ -232,20 +234,20 @@
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
sax.storeItem = function ()
|
||||
op.storeItem = function ()
|
||||
{
|
||||
op.ajax.storeItem = op.ajax.storeItem || { url: sax.url.base + 'Organisation/Ajax/StoreItem', formId: 'frmOrganisation', callbackFn: sax.onStoreItem };
|
||||
op.ajax.storeItem = op.ajax.storeItem || { url: sax.url.base + 'Organisation/Ajax/StoreItem', formId: 'frmOrganisation', callbackFn: op.onStoreItem };
|
||||
sax.doAjaxRequest(op.ajax.storeItem, 50);
|
||||
}
|
||||
sax.onStoreItem = function (response)
|
||||
op.onStoreItem = function (response)
|
||||
{
|
||||
//sax.debug('onStoreItem', response);
|
||||
sax.refreshControlValues(response.controlValues);
|
||||
if (!response.success) return;
|
||||
$dlg.organisation.dialog('close');
|
||||
sax.refreshItem(response.organisation);
|
||||
op.refreshItem(response.organisation);
|
||||
}
|
||||
sax.refreshItem = function (item)
|
||||
op.refreshItem = function (item)
|
||||
{
|
||||
var $item = $('#' + sax.itemIdPrefix + item.id);
|
||||
if (!$item.length)
|
||||
@@ -257,16 +259,16 @@
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
sax.activateItem = function (id)
|
||||
op.activateItem = function (item)
|
||||
{
|
||||
//sax.debug('activateItem(' + id + ')')
|
||||
$('.OrganisationId', $frm.orgId).val(id);
|
||||
op.ajax.getActivationInfo = op.ajax.getActivationInfo || { url: sax.url.base + 'Organisation/Ajax/GetActivationInfo', formId: 'frmOrganisationId', callbackFn: sax.showActivationInfo };
|
||||
//sax.debug('activateItem(' + item.id + ')')
|
||||
$('.OrganisationId', $frm.orgId).val(item.id);
|
||||
op.ajax.getActivationInfo = op.ajax.getActivationInfo || { url: sax.url.base + 'Organisation/Ajax/GetActivationInfo', formId: 'frmOrganisationId', callbackFn: op.showActivationInfo };
|
||||
sax.doAjaxRequest(op.ajax.getActivationInfo, 50);
|
||||
}
|
||||
sax.showActivationInfo = function (response)
|
||||
op.showActivationInfo = function (response)
|
||||
{
|
||||
sax.debug('showActivationInfo', response);
|
||||
//sax.debug('showActivationInfo', response);
|
||||
if (!response.success || !response.organisation) return;
|
||||
let item = response.organisation;
|
||||
let frm = $('#frmOrganisationActivation');
|
||||
@@ -282,36 +284,38 @@
|
||||
popItemValue('.OrganisationAddress', item.addressSummary);
|
||||
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++)
|
||||
let members = response.members;
|
||||
//sax.debug(members, $orgMbrs, $mbrTmpl);
|
||||
for (let idx = 0; idx < members.length; idx++)
|
||||
{
|
||||
let item = response.members[idx];
|
||||
let item = members[idx];
|
||||
let $item = $mbrTmpl.clone();
|
||||
$('.MemberId', $item).val(item.id);
|
||||
$('.MemberActivate', $item).prop('name', 'MemberActivate_' + item.id)
|
||||
$('.MemberEmail', $item).text(item.emailAddress);
|
||||
$('.MemberName', $item).text(item.displayName);
|
||||
$orgMbrs.append($item);
|
||||
sax.debug($item);
|
||||
//sax.debug($item);
|
||||
}
|
||||
$('.MembersAwaitingActivation', $dlg.activate).toggle(!!members.length);
|
||||
sax.openDialog($dlg.activate, 480, 420);
|
||||
}
|
||||
sax.activateOrganisation = function ()
|
||||
op.activateOrganisation = function ()
|
||||
{
|
||||
let frm = $('#frmOrganisationActivation');
|
||||
op.ajax.activateOrganisation = op.ajax.activateOrganisation || { url: sax.url.base + 'Organisation/Ajax/Activate', formId: frm.prop('id'), callbackFn: sax.handleAtivateResponse };
|
||||
op.ajax.activateOrganisation = op.ajax.activateOrganisation || { url: sax.url.base + 'Organisation/Ajax/Activate', formId: frm.prop('id'), callbackFn: op.handleAtivateResponse };
|
||||
sax.doAjaxRequest(op.ajax.activateOrganisation, 50);
|
||||
}
|
||||
sax.handleAtivateResponse = function (response)
|
||||
op.handleAtivateResponse = function (response)
|
||||
{
|
||||
sax.debug('handleAtivateResponse', response);
|
||||
//sax.debug('handleAtivateResponse', response);
|
||||
if (!response.success) return;
|
||||
$dlg.activate.dialog('close');
|
||||
sax.refreshItem(response.organisation);
|
||||
op.refreshItem(response.organisation);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
sax.onClickMemberCount = function (id)
|
||||
op.onClickMemberCount = function (id)
|
||||
{
|
||||
if (!(id * 1)) return;
|
||||
sax.doPleaseWait();
|
||||
@@ -327,7 +331,7 @@
|
||||
$pnl.filter = $('.sax-panel-filter', $pnl.orgs);
|
||||
$pnl.results = $('.sax-panel-results', $pnl.orgs);
|
||||
|
||||
$('.sax-action.sax-item-create', $pnl.filter).on('click', function () { sax.createItem(); });
|
||||
$('.sax-action.sax-item-create', $pnl.filter).on('click', function () { op.createItem(); });
|
||||
$('.sax-action.sax-results-refresh', $pnl.filter).on('click', function () { sax.refreshResults(); });
|
||||
|
||||
$frm.filter = $('#frmOrganisationFilter');
|
||||
@@ -337,16 +341,17 @@
|
||||
$frm.filter.on('dblclick', '.FilterOrganisationRegionCaption', op.selectFilterRegion).on('click', '.FilterRegionSelect', op.selectFilterRegion).on('click', '.FilterRegionClear', op.clearFilterRegion);
|
||||
$frm.orgId = $('#frmOrganisationId');
|
||||
$frm.org = $('#frmOrganisation');
|
||||
$('.sax-input, .sax-textarea', $frm.org).on('input', function () { sax.clearControlError(this); });
|
||||
$('.sax-select', $frm.org).on('change', function () { sax.clearControlError(this); });
|
||||
$frm.org.on('input', '.sax-input, .sax-textarea', function () { sax.clearControlError(this); }).on('change', '.sax-select', function () { sax.clearControlError(this); });
|
||||
$frm.org.on('dblclick', '.OrganisationSportCaption', op.selectOrgSport).on('click', '#pbSelectSport', op.selectOrgSport).on('click', '.OrganisationSportClear', op.clearOrgSport);
|
||||
$frm.org.on('dblclick', '.OrganisationRegionCaptionCountry', op.selectOrgRegion).on('click', '#pbSelectRegion', op.selectOrgRegion);
|
||||
|
||||
var opt = sax.dlgOpts();
|
||||
opt.buttons[sax.dlg.btn.ok] = function () { sax.storeItem(); };
|
||||
opt.buttons[sax.dlg.btn.ok] = function () { op.storeItem(); };
|
||||
opt.buttons[sax.dlg.btn.cancel] = function () { $(this).dialog('close'); };
|
||||
$dlg.organisation = $('#dlgOrganisation').dialog(opt);
|
||||
|
||||
var opt = sax.dlgOpts();
|
||||
opt.buttons[sax.dlg.btn.ok] = function () { sax.activateOrganisation(); };
|
||||
opt.buttons[sax.dlg.btn.ok] = function () { op.activateOrganisation(); };
|
||||
opt.buttons[sax.dlg.btn.cancel] = function () { $(this).dialog('close'); };
|
||||
$dlg.activate = $('#dlgOrganisationActivation').dialog(opt);
|
||||
|
||||
|
||||
@@ -264,14 +264,14 @@
|
||||
//--------------------------------------------------------------
|
||||
sax.createItem = function ()
|
||||
{
|
||||
sax.clearUserData();
|
||||
sax.clearItemData();
|
||||
$dlg.user.dialog('option', 'title', sax.dlg.title.createUser);
|
||||
sax.openDialog($dlg.user, 600, 480);
|
||||
}
|
||||
sax.clearUserData = function ()
|
||||
sax.clearItemData = function ()
|
||||
{
|
||||
let frm = $frm.user;
|
||||
$('.UserAccountId,.UserRegionIdCountry,.UserRegionIdProvince,.UserRoleCodes,input[type="text"],textarea,select', frm).val('');
|
||||
$('.UserId,.UserRegionIdCountry,.UserRegionIdProvince,.UserRoleCodes,input[type="text"],textarea,select', frm).val('');
|
||||
$('.UserStatus', frm).val(sax.data.defaultStatusCode);
|
||||
sax.clearControlErrors();
|
||||
sax.userAccount = { userRoleCodes: [] };
|
||||
@@ -280,7 +280,7 @@
|
||||
//--------------------------------------------------------------
|
||||
sax.updateItem = function (item)
|
||||
{
|
||||
$('.UserAccountId', $frm.userId).val(item.id);
|
||||
$('.UserId', $frm.userId).val(item.id);
|
||||
sax.ajax.updateItem = sax.ajax.updateItem || { url: sax.url.base + 'User/Ajax/GetItem', formId: 'frmUserId', callbackFn: sax.onUpdateItem };
|
||||
sax.doAjaxRequest(sax.ajax.updateItem, 50);
|
||||
}
|
||||
@@ -288,10 +288,10 @@
|
||||
{
|
||||
//sax.debug('onUpdateItem', response);
|
||||
if (!response.success) return;
|
||||
sax.clearUserData();
|
||||
sax.clearItemData();
|
||||
let item = sax.userAccount = response.user;
|
||||
let frm = $frm.user;
|
||||
$('.UserAccountId', frm).val(item.id);
|
||||
$('.UserId', frm).val(item.id);
|
||||
$('.UserEmailAddress', frm).val(item.emailAddress);
|
||||
$('.UserTitle', frm).val(item.title);
|
||||
$('.UserFirstName', frm).val(item.firstName);
|
||||
@@ -333,9 +333,9 @@
|
||||
//--------------------------------------------------------------
|
||||
sax.userEmails = function (item)
|
||||
{
|
||||
sax.debug('userEmails', item);
|
||||
//sax.debug('userEmails', item);
|
||||
let frm = $frm.emailsl
|
||||
$('.UserAccountId', frm).val(item.id);
|
||||
$('.UserId', frm).val(item.id);
|
||||
$('.UserEmailAddress', frm).val(item.emailAddress);
|
||||
$('.UserDisplayName', frm).val(item.displayName);
|
||||
$('.RequestPasswordAdminOption', frm).toggle(item.systemAdmin);
|
||||
|
||||
@@ -198,20 +198,24 @@
|
||||
|
||||
//--------------------------------------------------------------
|
||||
sax.createItem = function ()
|
||||
{
|
||||
sax.clearItemData();
|
||||
$dlg.user.dialog('option', 'title', sax.dlg.title.createUser);
|
||||
sax.openDialog($dlg.user, 600, 480);
|
||||
}
|
||||
sax.clearItemData = function ()
|
||||
{
|
||||
let frm = $frm.user;
|
||||
$('.UserAccountId,.UserRoleCodes,input[type="text"],textarea,select', frm).val('');
|
||||
$('.UserId,.UserRoleCodes,input[type="text"],textarea,select', frm).val('');
|
||||
$('.UserStatus', frm).val(sax.data.defaultStatusCode);
|
||||
sax.clearControlErrors();
|
||||
sax.userAccount = { userRoleCodes: [] };
|
||||
$dlg.user.dialog('option', 'title', sax.dlg.title.createUser);
|
||||
sax.openDialog($dlg.user, 600, 480);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
sax.updateItem = function (item)
|
||||
{
|
||||
$('.UserAccountId', $frm.userId).val(item.id);
|
||||
$('.UserId', $frm.userId).val(item.id);
|
||||
sax.ajax.updateItem = sax.ajax.updateItem || { url: sax.url.base + 'User/Ajax/GetItem', formId: 'frmUserId', callbackFn: sax.onUpdateItem };
|
||||
sax.doAjaxRequest(sax.ajax.updateItem, 50);
|
||||
}
|
||||
@@ -219,11 +223,10 @@
|
||||
{
|
||||
//sax.debug('onUpdateItem', response);
|
||||
let frm = $frm.user;
|
||||
$('.UserAccountId,input[type="text"],textarea,select', frm).val('');
|
||||
sax.clearControlErrors();
|
||||
sax.clearItemData();
|
||||
if (!response.success) return;
|
||||
let item = sax.userAccount = response.user;
|
||||
$('.UserAccountId', frm).val(item.id);
|
||||
$('.UserId', frm).val(item.id);
|
||||
$('.UserEmailAddress', frm).val(item.emailAddress);
|
||||
$('.UserTitle', frm).val(item.title);
|
||||
$('.UserFirstName', frm).val(item.firstName);
|
||||
@@ -263,7 +266,7 @@
|
||||
{
|
||||
sax.debug('userEmails', item);
|
||||
let frm = $frm.emailsl
|
||||
$('.UserAccountId', frm).val(item.id);
|
||||
$('.UserId', frm).val(item.id);
|
||||
$('.UserEmailAddress', frm).val(item.emailAddress);
|
||||
$('.UserDisplayName', frm).val(item.displayName);
|
||||
$('.RequestPasswordAdminOption', frm).toggle(item.systemAdmin);
|
||||
|
||||
@@ -173,6 +173,9 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
|
||||
SysId userAccountId = UserAccountId;
|
||||
SaxActivityConsole.IndexContext indexContext = new SaxActivityConsole.IndexContext(userAccountId);
|
||||
|
||||
// Period.
|
||||
indexContext.EffectiveTo = DateTime.Today;
|
||||
|
||||
// Regions.
|
||||
if (SysId.IsValid(sessionData.User.RegionIdProvince))
|
||||
indexContext.RegionIds.Add(sessionData.User.RegionIdProvince);
|
||||
|
||||
@@ -67,7 +67,8 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
|
||||
{
|
||||
public String RegionIdPrimary { get; set; }
|
||||
public String SportIdPrimary { get; set; }
|
||||
public bool Published { get; set; }
|
||||
public bool? Published { get; set; } = null;
|
||||
public bool? PublishedInFuture { get; set; } = null;
|
||||
public String PublishedOn_YYYYMMDD { get; set; }
|
||||
public String PublishedOn_Calendar { get; set; }
|
||||
public ArticleContentData Content { get; } = new ArticleContentData();
|
||||
@@ -90,7 +91,8 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
|
||||
PopulateArticleResponseData(model, article, data as ArticleData_List);
|
||||
data.RegionIdPrimary = model.GetEncryptedRegionId(article.RegionIdPrimary);
|
||||
data.SportIdPrimary = model.GetEncryptedSportId(article.SportIdPrimary);
|
||||
data.Published = DateUtil.IsValid(article.PublishedAt);
|
||||
data.Published = DateUtil.IsValid(article.PublishedAt) ? true : (bool?)null;
|
||||
data.PublishedInFuture = (data.Published == true && article.PublishedAt.CompareTo(DateTime.Today) >= 0) ? true : (bool?)null;
|
||||
data.PublishedOn_YYYYMMDD = DateUtil.Format(article.PublishedAt, "yyyyMMdd");
|
||||
data.PublishedOn_Calendar = model.FormatDateForForm(article.PublishedAt);
|
||||
|
||||
@@ -126,6 +128,8 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
|
||||
public List<ArticleData_List> Articles { get; } = new List<ArticleData_List>();
|
||||
/// <summary>Organisations that the user has rights to author articles for.</summary>
|
||||
public List<OrganisationData> Organisations { get; set; }
|
||||
public ItemIdName defaultSport { get; set; }
|
||||
public ItemIdName defaultRegion { get; set; }
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
[HttpPost]
|
||||
@@ -144,88 +148,120 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
|
||||
SysId userAccountId = UserAccountId;
|
||||
RefreshModel(model);
|
||||
|
||||
// Organisations that the user has rights to author articles for.
|
||||
foreach (SaxAccountMgr.OrganisationIdName organisation in AccountMgr.GetOrganisationsForAnyUserRole(userAccountId, new [] { Sax.OrganisationRole.Admin, Sax.OrganisationRole.ArticleAdmin }))
|
||||
// Record disposable items as they are created so all can be disposed when needed.
|
||||
using (DisposableCollection<SacsHierarchyItem> disposableItems = new DisposableCollection<SacsHierarchyItem>())
|
||||
{
|
||||
if (responseData.Organisations == null) responseData.Organisations = new List<OrganisationData>();
|
||||
OrganisationData organisationData = new OrganisationData()
|
||||
// User account.
|
||||
SaxUserAccount userAccount = AccountMgr.GetUserAccountById(UserAccountId);
|
||||
disposableItems.Add(userAccount);
|
||||
|
||||
// Organisations that the user has rights to author articles for.
|
||||
foreach (SaxAccountMgr.OrganisationIdName articleOrganisation in AccountMgr.GetOrganisationsForAnyUserRole(userAccountId, new[] { Sax.OrganisationRole.Admin, Sax.OrganisationRole.ArticleAdmin }))
|
||||
{
|
||||
Id = model.EncryptId(organisation.Id),
|
||||
Name = organisation.Name
|
||||
};
|
||||
responseData.Organisations.Add(organisationData);
|
||||
}
|
||||
|
||||
// User must either be a journalist or allowed to author organisation articles.
|
||||
if (!UserIsJournalist && responseData.Organisations == null) return GetAjaxResult_GoHome(responseData);
|
||||
if (UserIsJournalist && responseData.Organisations != null)
|
||||
{
|
||||
OrganisationData organisationData = new OrganisationData()
|
||||
{
|
||||
Id = "",
|
||||
Name = "No Organisation - Journalist Articles"
|
||||
};
|
||||
responseData.Organisations.Insert(0, organisationData);
|
||||
}
|
||||
|
||||
// Filter organisation.
|
||||
SysId organisationIdFilter = model.ExtractSysId(model.Filter.OrganisationId);
|
||||
|
||||
// Item filter.
|
||||
SaxArticle.Params prmArticle = new SaxArticle.Params();
|
||||
prmArticle.UserAccountIdsAuthorIncluded.Add(sessionData.User.UserAccountId);
|
||||
if (SysId.IsValid(organisationIdFilter))
|
||||
prmArticle.OrganisationIdsIncluded.Add(organisationIdFilter);
|
||||
prmArticle.ArticleFilter = model.Filter.Article;
|
||||
prmArticle.StatusCat = SaxArticle.StatusCat.NotDeleted;
|
||||
model.Paging.ItemTotal = (ulong)ActivityMgr.GetArticleCount(prmArticle);
|
||||
model.PopulatePagingTo(prmArticle.ResultsPaging);
|
||||
|
||||
// Item columns.
|
||||
ColumnDfn colId = ActivityMgr.GetArticleColumnDfn(SaxArticle.Column.Id);
|
||||
ColumnDfn colOrganisationId = ActivityMgr.GetArticleColumnDfn(SaxArticle.Column.OrganisationId);
|
||||
ColumnDfn colHeadline = ActivityMgr.GetArticleColumnDfn(SaxArticle.Column.Headline);
|
||||
ColumnDfn colSummary = ActivityMgr.GetArticleColumnDfn(SaxArticle.Column.Summary);
|
||||
ColumnDfn colRegionIdPrimary = ActivityMgr.GetArticleColumnDfn(SaxArticle.Column.RegionIdPrimary);
|
||||
ColumnDfn colSportIdPrimary = ActivityMgr.GetArticleColumnDfn(SaxArticle.Column.SportIdPrimary);
|
||||
ColumnDfn colPublishedOn = ActivityMgr.GetArticleColumnDfn(SaxArticle.Column.PublishedAt_Date);
|
||||
ColumnDfn colStatus = ActivityMgr.GetArticleColumnDfn(SaxArticle.Column.Status);
|
||||
ColumnDfn colCreatedOn = ActivityMgr.GetArticleColumnDfn(SaxArticle.Column.CreateOn_Date);
|
||||
List<ColumnDfn> columns = new List<ColumnDfn>()
|
||||
{
|
||||
colId, colOrganisationId, colHeadline, colSummary,
|
||||
colRegionIdPrimary, colSportIdPrimary, colPublishedOn,
|
||||
colStatus, colCreatedOn
|
||||
};
|
||||
|
||||
// Sort columns.
|
||||
colCreatedOn.SortAscending = false;
|
||||
prmArticle.SortColumns.Add(colCreatedOn);
|
||||
|
||||
// Query items.
|
||||
using (DbResultSet resultSet = ActivityMgr.ExecuteArticleQuery(columns, prmArticle))
|
||||
{
|
||||
while (resultSet != null && resultSet.HasRows && resultSet.NextRecord())
|
||||
{
|
||||
NamedValue.Map values = resultSet.GetRecordValues();
|
||||
ArticleData_List articleData = new ArticleData_List()
|
||||
if (responseData.Organisations == null) responseData.Organisations = new List<OrganisationData>();
|
||||
OrganisationData organisationData = new OrganisationData()
|
||||
{
|
||||
Id = values.GetString(colId.DataName),
|
||||
OrganisationId = values.GetString(colOrganisationId.DataName),
|
||||
Headline = values.GetString(colHeadline.DataName),
|
||||
Summary = values.GetString(colSummary.DataName),
|
||||
RegionCaptionPrimary = model.GetRegionCaption(values.GetString(colRegionIdPrimary.DataName).ToSysId()),
|
||||
SportCaptionPrimary = model.GetSportCaption(values.GetString(colSportIdPrimary.DataName).ToSysId()),
|
||||
CreatedOnFmt = DateUtil.Format(values.GetDateTime(colCreatedOn.DataName), "d-MMM-yyyy"),
|
||||
PublishedOnFmt = DateUtil.Format(values.GetDateTime(colPublishedOn.DataName), "d-MMM-yyyy"),
|
||||
StatusCode = values.GetString(colStatus.DataName),
|
||||
StatusDesc = SacsSystem.GetStatusDescForCode(values.GetString(colStatus.DataName))
|
||||
Id = model.EncryptId(articleOrganisation.Id),
|
||||
Name = articleOrganisation.Name
|
||||
};
|
||||
responseData.Articles.Add(articleData);
|
||||
responseData.Organisations.Add(organisationData);
|
||||
}
|
||||
|
||||
// User must either be a journalist or allowed to author organisation articles.
|
||||
if (!UserIsJournalist && responseData.Organisations == null) return GetAjaxResult_GoHome(responseData);
|
||||
if (UserIsJournalist && responseData.Organisations != null)
|
||||
{
|
||||
OrganisationData organisationData = new OrganisationData()
|
||||
{
|
||||
Id = "",
|
||||
Name = "No Organisation - Journalist Articles"
|
||||
};
|
||||
responseData.Organisations.Insert(0, organisationData);
|
||||
}
|
||||
|
||||
// Filter organisation.
|
||||
SysId organisationIdFilter = model.ExtractSysId(model.Filter.OrganisationId);
|
||||
SaxOrganisation organisation = AccountMgr.GetOrganisationById(organisationIdFilter);
|
||||
disposableItems.Add(organisation);
|
||||
|
||||
// Default Sport - defined by organisation if selected.
|
||||
SysId defaultSportId = organisation?.SportIdPrimary ?? null;
|
||||
if (SysId.IsValid(defaultSportId))
|
||||
{
|
||||
responseData.defaultSport = new AjaxResponse_Data.ItemIdName()
|
||||
{
|
||||
Id = model.GetEncryptedSportId(defaultSportId),
|
||||
Name = model.GetSportCaption(defaultSportId)
|
||||
};
|
||||
}
|
||||
|
||||
// Default region - defined by organisation (if selected) otherwise user themselves.
|
||||
SysId defaultRegionId = organisation?.RegionIdPrimary ?? userAccount?.RegionIdCountry ?? null;
|
||||
if (SysId.IsValid(defaultRegionId))
|
||||
{
|
||||
responseData.defaultRegion = new AjaxResponse_Data.ItemIdName()
|
||||
{
|
||||
Id = model.GetEncryptedRegionId(defaultRegionId),
|
||||
Name = model.GetRegionCaption(defaultRegionId)
|
||||
};
|
||||
}
|
||||
|
||||
// Item filter.
|
||||
SaxArticle.Params prmArticle = new SaxArticle.Params();
|
||||
prmArticle.UserAccountIdsAuthorIncluded.Add(sessionData.User.UserAccountId);
|
||||
if (SysId.IsValid(organisationIdFilter))
|
||||
prmArticle.OrganisationIdsIncluded.Add(organisationIdFilter);
|
||||
prmArticle.ArticleFilter = model.Filter.Article;
|
||||
prmArticle.StatusCat = SaxArticle.StatusCat.NotDeleted;
|
||||
model.Paging.ItemTotal = (ulong)ActivityMgr.GetArticleCount(prmArticle);
|
||||
model.PopulatePagingTo(prmArticle.ResultsPaging);
|
||||
|
||||
// Item columns.
|
||||
ColumnDfn colId = ActivityMgr.GetArticleColumnDfn(SaxArticle.Column.Id);
|
||||
ColumnDfn colOrganisationId = ActivityMgr.GetArticleColumnDfn(SaxArticle.Column.OrganisationId);
|
||||
ColumnDfn colHeadline = ActivityMgr.GetArticleColumnDfn(SaxArticle.Column.Headline);
|
||||
ColumnDfn colSummary = ActivityMgr.GetArticleColumnDfn(SaxArticle.Column.Summary);
|
||||
ColumnDfn colRegionIdPrimary = ActivityMgr.GetArticleColumnDfn(SaxArticle.Column.RegionIdPrimary);
|
||||
ColumnDfn colSportIdPrimary = ActivityMgr.GetArticleColumnDfn(SaxArticle.Column.SportIdPrimary);
|
||||
ColumnDfn colPublishedOn = ActivityMgr.GetArticleColumnDfn(SaxArticle.Column.PublishedAt_Date);
|
||||
ColumnDfn colStatus = ActivityMgr.GetArticleColumnDfn(SaxArticle.Column.Status);
|
||||
ColumnDfn colCreatedOn = ActivityMgr.GetArticleColumnDfn(SaxArticle.Column.CreateOn_Date);
|
||||
List<ColumnDfn> columns = new List<ColumnDfn>()
|
||||
{
|
||||
colId, colOrganisationId, colHeadline, colSummary,
|
||||
colRegionIdPrimary, colSportIdPrimary, colPublishedOn,
|
||||
colStatus, colCreatedOn
|
||||
};
|
||||
|
||||
// Sort columns.
|
||||
colCreatedOn.SortAscending = false;
|
||||
prmArticle.SortColumns.Add(colCreatedOn);
|
||||
|
||||
// Query items.
|
||||
using (DbResultSet resultSet = ActivityMgr.ExecuteArticleQuery(columns, prmArticle))
|
||||
{
|
||||
while (resultSet != null && resultSet.HasRows && resultSet.NextRecord())
|
||||
{
|
||||
NamedValue.Map values = resultSet.GetRecordValues();
|
||||
ArticleData_List articleData = new ArticleData_List()
|
||||
{
|
||||
Id = values.GetString(colId.DataName),
|
||||
OrganisationId = values.GetString(colOrganisationId.DataName),
|
||||
Headline = values.GetString(colHeadline.DataName),
|
||||
Summary = values.GetString(colSummary.DataName),
|
||||
RegionCaptionPrimary = model.GetRegionCaption(values.GetString(colRegionIdPrimary.DataName).ToSysId()),
|
||||
SportCaptionPrimary = model.GetSportCaption(values.GetString(colSportIdPrimary.DataName).ToSysId()),
|
||||
CreatedOnFmt = DateUtil.Format(values.GetDateTime(colCreatedOn.DataName), "d-MMM-yyyy"),
|
||||
PublishedOnFmt = DateUtil.Format(values.GetDateTime(colPublishedOn.DataName), "d-MMM-yyyy"),
|
||||
StatusCode = values.GetString(colStatus.DataName),
|
||||
StatusDesc = SacsSystem.GetStatusDescForCode(values.GetString(colStatus.DataName))
|
||||
};
|
||||
responseData.Articles.Add(articleData);
|
||||
}
|
||||
}
|
||||
if (model.Paging.IsPaged)
|
||||
model.Paging.ItemCount = (ushort)responseData.Articles.Count;
|
||||
}
|
||||
if (model.Paging.IsPaged)
|
||||
model.Paging.ItemCount = (ushort)responseData.Articles.Count;
|
||||
|
||||
// Complete response.
|
||||
responseData.SetPaging(model);
|
||||
@@ -260,39 +296,46 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
|
||||
SysId userAccountId = UserAccountId;
|
||||
RefreshModel(model);
|
||||
|
||||
// Identify item.
|
||||
SysId articleId = model.ExtractSysId(model.ArticleId);
|
||||
if (!SysId.IsValid(articleId))
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.specified"]));
|
||||
|
||||
// Retrieve item.
|
||||
SaxArticle article = ActivityMgr.GetArticleById(articleId);
|
||||
if (article == null)
|
||||
// Record disposable items as they are created so all can be disposed when needed.
|
||||
using (DisposableCollection<SacsHierarchyItem> disposableItems = new DisposableCollection<SacsHierarchyItem>())
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to retrieve Article for Id: '" + model.ArticleId + "'");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
|
||||
}
|
||||
if (!article.UserAccountIdAuthor.Equals(userAccountId))
|
||||
{
|
||||
SaLogger.Warn(fn + " Inconsistent Article Author. Expected: " + userAccountId + ". Found: " + article.UserAccountIdAuthor);
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"]));
|
||||
}
|
||||
|
||||
// Delete upload images.
|
||||
SaxItemImage.Params prmItemImage = new SaxItemImage.Params();
|
||||
prmItemImage.ItemIdsIncluded.Add(new ItemId((short)Sax.DataItemType.Article, articleId));
|
||||
prmItemImage.ImageTypesIncluded.Add(Sax.ImageType.ArticleUpload);
|
||||
prmItemImage.StatusCat = SaxItemImage.StatusCat.NotDeleted;
|
||||
foreach (SaxItemImage itemImage in ItemDataMgr.GetItemImageList(prmItemImage))
|
||||
{
|
||||
itemImage.SessionUid = 0;
|
||||
itemImage.ImageUid = 0;
|
||||
itemImage.Status = SaStatus.Deleted;
|
||||
ItemDataMgr.UpdateItemImage(itemImage, DbUpdateInfo);
|
||||
}
|
||||
// Identify item.
|
||||
SysId articleId = model.ExtractSysId(model.ArticleId);
|
||||
if (!SysId.IsValid(articleId))
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.specified"]));
|
||||
|
||||
// Construct response.
|
||||
PopulateArticleResponseData(model, article, responseData.Article);
|
||||
// Retrieve item.
|
||||
SaxArticle article = ActivityMgr.GetArticleById(articleId);
|
||||
disposableItems.Add(article);
|
||||
if (article == null)
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to retrieve Article for Id: '" + model.ArticleId + "'");
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
|
||||
}
|
||||
if (!article.UserAccountIdAuthor.Equals(userAccountId))
|
||||
{
|
||||
SaLogger.Warn(fn + " Inconsistent Article Author. Expected: " + userAccountId + ". Found: " + article.UserAccountIdAuthor);
|
||||
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.system"]));
|
||||
}
|
||||
|
||||
// Delete upload images.
|
||||
SaxItemImage.Params prmItemImage = new SaxItemImage.Params();
|
||||
prmItemImage.ItemIdsIncluded.Add(new ItemId((short)Sax.DataItemType.Article, articleId));
|
||||
prmItemImage.ImageTypesIncluded.Add(Sax.ImageType.ArticleUpload);
|
||||
prmItemImage.StatusCat = SaxItemImage.StatusCat.NotDeleted;
|
||||
foreach (SaxItemImage itemImage in ItemDataMgr.GetItemImageList(prmItemImage))
|
||||
{
|
||||
disposableItems.Add(itemImage);
|
||||
itemImage.SessionUid = 0;
|
||||
itemImage.ImageUid = 0;
|
||||
itemImage.Status = SaStatus.Deleted;
|
||||
ItemDataMgr.UpdateItemImage(itemImage, DbUpdateInfo);
|
||||
}
|
||||
|
||||
// Construct response.
|
||||
PopulateArticleResponseData(model, article, responseData.Article);
|
||||
}
|
||||
responseData.Success = true;
|
||||
return Json(responseData);
|
||||
}
|
||||
@@ -311,9 +354,9 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
|
||||
// Ajax request.
|
||||
[HttpPost]
|
||||
[Route("Article/Ajax/UploadImage")]
|
||||
public IActionResult UploadArticleImage(Model_Article model)
|
||||
public IActionResult Ajax_UploadArticleImage(Model_Article model)
|
||||
{
|
||||
String fn = GetType().Name + ".UploadArticleImage";
|
||||
String fn = GetType().Name + ".Ajax_UploadArticleImage";
|
||||
AjaxResponse_UploadArticleImage responseData = new AjaxResponse_UploadArticleImage(model);
|
||||
String messageTitle = Localiser["article.caption.article"];
|
||||
|
||||
@@ -323,85 +366,91 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
|
||||
SaxSessionData_Online sessionData = SessionData_Online;
|
||||
RefreshModel(model);
|
||||
|
||||
// Validate number of images.
|
||||
if (model.ArticleImage.IsEmpty())
|
||||
// Record disposable items as they are created so all can be disposed when needed.
|
||||
using (DisposableCollection<SacsHierarchyItem> disposableItems = new DisposableCollection<SacsHierarchyItem>())
|
||||
{
|
||||
SaLogger.Warn(fn + " No image file supplied for upload");
|
||||
return Json(responseData);
|
||||
}
|
||||
if (model.ArticleImage.Count != 1)
|
||||
{
|
||||
SaLogger.Warn(fn + " Invalid number of image files uploaded: " + model.ArticleImage.Count);
|
||||
return Json(responseData.SetControlError("ArticleImage", Localiser["msg.upload.image.single"]));
|
||||
}
|
||||
IFormFile file = model.ArticleImage[0];
|
||||
|
||||
// Image properties.
|
||||
byte[] imageData = null;
|
||||
using (MemoryStream fileStream = new MemoryStream())
|
||||
{
|
||||
file.CopyTo(fileStream);
|
||||
imageData = fileStream.ToArray();
|
||||
}
|
||||
|
||||
// Validate the image.
|
||||
ImageUtils.ImageConfig imageConfig = ImageUtils.VerifyImageData(imageData);
|
||||
if (!imageConfig.ValidImage)
|
||||
return Json(responseData.SetControlError("ArticleImage", Localiser["msg.upload.image.invalid"]));
|
||||
|
||||
// Image belongs to the article.
|
||||
// If the article doesn't yet exist, it will need to be uploaded to the user first and later transferred.
|
||||
SysId articleId = model.ExtractSysId(model.ArticleId);
|
||||
ItemId articleItemId = new ItemId((short)Sax.DataItemType.Article, articleId);
|
||||
ItemId userItemId = new ItemId((short)Sax.DataItemType.UserAccount, sessionData.User.UserAccountId);
|
||||
ItemId imageItemId = SysId.IsValid(articleId) ? articleItemId : userItemId;
|
||||
|
||||
// Store uploaded image as 'Upload' - awaiting confirmation that the article details are to be saved.
|
||||
// NB Reuse any existing deleted article upload image to avoid creating new images unless necessary.
|
||||
SaxItemImage.Params prmItemImage = new SaxItemImage.Params();
|
||||
prmItemImage.ItemIdsIncluded.Add(imageItemId);
|
||||
prmItemImage.ImageTypesIncluded.Add(Sax.ImageType.Article);
|
||||
prmItemImage.ImageTypesIncluded.Add(Sax.ImageType.ArticleUpload);
|
||||
prmItemImage.StatusCat = SaxItemImage.StatusCat.DeletedOnly;
|
||||
prmItemImage.ResultsPaging.PageLength = 1;
|
||||
prmItemImage.ResultsPaging.PageNo = 1;
|
||||
List<SaxItemImage> itemImages = ItemDataMgr.GetItemImageList(prmItemImage);
|
||||
SaxItemImage itemImage = !itemImages.IsEmpty() ? itemImages[0] : null;
|
||||
if (itemImage == null)
|
||||
itemImage = ItemDataMgr.CreateItemImage(imageItemId, Sax.ImageType.ArticleUpload);
|
||||
itemImage.ImageType = Sax.ImageType.ArticleUpload;
|
||||
itemImage.Filename = file.FileName;
|
||||
itemImage.Mime = SacsContentTypeHelper.GetMimeTypeFromContentType(file.ContentType).ToString().ToLower();
|
||||
itemImage.ContentType = file.ContentType;
|
||||
itemImage.Width = imageConfig.Width;
|
||||
itemImage.Height = imageConfig.Height;
|
||||
itemImage.ImageData = imageData;
|
||||
itemImage.SessionUid = sessionData.SessionIdx;
|
||||
itemImage.ImageUid = sessionData.NextItemIdx;
|
||||
itemImage.Status = SaxItemImage.DefaultStatus;
|
||||
|
||||
if (!SysId.IsValid(itemImage.Id))
|
||||
{
|
||||
if (!ItemDataMgr.InsertItemImage(itemImage, DbUpdateInfo))
|
||||
// Validate number of images.
|
||||
if (model.ArticleImage.IsEmpty())
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to insert uploaded image - " + ItemDataMgr.ErrorStateMessage);
|
||||
return Json(responseData.SetControlError("ArticleImage", Localiser["msg.error.item.insert.failed"]));
|
||||
SaLogger.Warn(fn + " No image file supplied for upload");
|
||||
return Json(responseData);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ItemDataMgr.UpdateItemImage(itemImage, DbUpdateInfo))
|
||||
if (model.ArticleImage.Count != 1)
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to update uploaded image - " + ItemDataMgr.ErrorStateMessage);
|
||||
return Json(responseData.SetControlError("ArticleImage", Localiser["msg.error.item.insert.failed"]));
|
||||
SaLogger.Warn(fn + " Invalid number of image files uploaded: " + model.ArticleImage.Count);
|
||||
return Json(responseData.SetControlError("ArticleImage", Localiser["msg.upload.image.single"]));
|
||||
}
|
||||
}
|
||||
IFormFile file = model.ArticleImage[0];
|
||||
|
||||
// Segment image info.
|
||||
responseData.Segment = new ArticleContentSegmentData();
|
||||
responseData.Segment.Image = new ArticleContentSegmentImageData();
|
||||
responseData.Segment.Image.ImageLink = GetArticleImageLink(itemImage.Id);
|
||||
responseData.Segment.Image.ImageIdx = itemImage.ImageUid;
|
||||
// Image properties.
|
||||
byte[] imageData = null;
|
||||
using (MemoryStream fileStream = new MemoryStream())
|
||||
{
|
||||
file.CopyTo(fileStream);
|
||||
imageData = fileStream.ToArray();
|
||||
}
|
||||
|
||||
// Validate the image.
|
||||
ImageUtils.ImageConfig imageConfig = ImageUtils.VerifyImageData(imageData);
|
||||
if (!imageConfig.ValidImage)
|
||||
return Json(responseData.SetControlError("ArticleImage", Localiser["msg.upload.image.invalid"]));
|
||||
|
||||
// Image belongs to the article.
|
||||
// If the article doesn't yet exist, it will need to be uploaded to the user first and later transferred.
|
||||
SysId articleId = model.ExtractSysId(model.ArticleId);
|
||||
ItemId articleItemId = new ItemId((short)Sax.DataItemType.Article, articleId);
|
||||
ItemId userItemId = new ItemId((short)Sax.DataItemType.UserAccount, sessionData.User.UserAccountId);
|
||||
ItemId imageItemId = SysId.IsValid(articleId) ? articleItemId : userItemId;
|
||||
|
||||
// Store uploaded image as 'Upload' - awaiting confirmation that the article details are to be saved.
|
||||
// NB Reuse any existing deleted article upload image to avoid creating new images unless necessary.
|
||||
SaxItemImage.Params prmItemImage = new SaxItemImage.Params();
|
||||
prmItemImage.ItemIdsIncluded.Add(imageItemId);
|
||||
prmItemImage.ImageTypesIncluded.Add(Sax.ImageType.Article);
|
||||
prmItemImage.ImageTypesIncluded.Add(Sax.ImageType.ArticleUpload);
|
||||
prmItemImage.StatusCat = SaxItemImage.StatusCat.DeletedOnly;
|
||||
prmItemImage.ResultsPaging.PageLength = 1;
|
||||
prmItemImage.ResultsPaging.PageNo = 1;
|
||||
List<SaxItemImage> itemImages = ItemDataMgr.GetItemImageList(prmItemImage);
|
||||
SaxItemImage itemImage = !itemImages.IsEmpty() ? itemImages[0] : null;
|
||||
if (itemImage == null)
|
||||
itemImage = ItemDataMgr.CreateItemImage(imageItemId, Sax.ImageType.ArticleUpload);
|
||||
disposableItems.Add(itemImage);
|
||||
itemImage.ImageType = Sax.ImageType.ArticleUpload;
|
||||
itemImage.Filename = file.FileName;
|
||||
itemImage.Mime = SacsContentTypeHelper.GetMimeTypeFromContentType(file.ContentType).ToString().ToLower();
|
||||
itemImage.ContentType = file.ContentType;
|
||||
itemImage.Width = imageConfig.Width;
|
||||
itemImage.Height = imageConfig.Height;
|
||||
itemImage.ImageData = imageData;
|
||||
itemImage.SessionUid = sessionData.SessionIdx;
|
||||
itemImage.ImageUid = sessionData.NextItemIdx;
|
||||
itemImage.Status = SaxItemImage.DefaultStatus;
|
||||
|
||||
if (!SysId.IsValid(itemImage.Id))
|
||||
{
|
||||
if (!ItemDataMgr.InsertItemImage(itemImage, DbUpdateInfo))
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to insert uploaded image - " + ItemDataMgr.ErrorStateMessage);
|
||||
return Json(responseData.SetControlError("ArticleImage", Localiser["msg.error.item.insert.failed"]));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ItemDataMgr.UpdateItemImage(itemImage, DbUpdateInfo))
|
||||
{
|
||||
SaLogger.Warn(fn + " Failed to update uploaded image - " + ItemDataMgr.ErrorStateMessage);
|
||||
return Json(responseData.SetControlError("ArticleImage", Localiser["msg.error.item.insert.failed"]));
|
||||
}
|
||||
}
|
||||
|
||||
// Segment image info.
|
||||
responseData.Segment = new ArticleContentSegmentData();
|
||||
responseData.Segment.Image = new ArticleContentSegmentImageData();
|
||||
responseData.Segment.Image.ImageLink = GetArticleImageLink(itemImage.Id);
|
||||
responseData.Segment.Image.ImageIdx = itemImage.ImageUid;
|
||||
}
|
||||
|
||||
// Complete response.
|
||||
//responseData.SetNotification(messageTitle, "Image uploaded.");
|
||||
@@ -450,7 +499,7 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
|
||||
if (SysId.IsValid(organisationId))
|
||||
{
|
||||
// Organisation specified - User must have Article Admin role.
|
||||
if (!AccountMgr.UserHasAnyOrganisationRole(userAccountId, organisationId, new [] { Sax.OrganisationRole.Admin, 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"]));
|
||||
@@ -515,8 +564,13 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
|
||||
article.Headline = model.ArticleHeadline;
|
||||
if (model.ArticleSummary != null)
|
||||
article.Summary = model.ArticleSummary;
|
||||
if (model.ArticlePublish)
|
||||
article.PublishedAt = model.GetArticlePublishOn();
|
||||
if (!model.ArticlePublished.ToBool())
|
||||
{
|
||||
if (model.ArticlePublish)
|
||||
article.PublishedAt = model.GetArticlePublishOn();
|
||||
else
|
||||
article.PublishedAt = DateTime.MinValue;
|
||||
}
|
||||
if (model.ArticleStatusCode != null)
|
||||
article.Status = model.ArticleStatus;
|
||||
|
||||
|
||||
@@ -73,6 +73,7 @@ namespace Saxonite.Net.Core.Web.Online.Models
|
||||
// Article images.
|
||||
public List<IFormFile> ArticleImage { get; set; }
|
||||
// Article publication.
|
||||
public String ArticlePublished { get; set; }
|
||||
public bool ArticlePublish { get; set; }
|
||||
public String ArticlePublishOn { get; set; }
|
||||
public DateTime GetArticlePublishOn()
|
||||
@@ -123,7 +124,8 @@ namespace Saxonite.Net.Core.Web.Online.Models
|
||||
}
|
||||
|
||||
// Article publication.
|
||||
if (ArticlePublish)
|
||||
// Only relevant when the article hasn't yet been published and user has selected 'Publish'.
|
||||
if (!ArticlePublished.ToBool() && ArticlePublish)
|
||||
{
|
||||
String controlName = "ArticlePublication";
|
||||
DateTime publishedOn = GetArticlePublishOn();
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<div class="sax-panel Articles">
|
||||
|
||||
<script type="text/javascript">
|
||||
sax.maxPublishDaysAhead = '@(Sax.Config.Online.Articles.PublishMaxDaysAhead)';
|
||||
sax.articlePublish = { maxDaysBefore: '@(Sax.Config.Online.Articles.PublishMaxDaysBefore)', maxDaysAhead: '@(Sax.Config.Online.Articles.PublishMaxDaysAhead)' };
|
||||
sax.lbl.edit = '@(Localiser.GetJavascriptText("label.edit"))';
|
||||
sax.lbl.remove = '@(Localiser.GetJavascriptText("label.remove"))';
|
||||
</script>
|
||||
|
||||
@@ -118,6 +118,7 @@
|
||||
<div class="col-sm">
|
||||
<div class="sax-control">
|
||||
<div class="row ArticlePublish">
|
||||
@Html.HiddenFor(model => model.ArticlePublished, new { @id = "ifArticlePublished" })
|
||||
<div class="fixed"><div class="pl16 pt4 pr8">@Html.CheckBoxFor(model => model.ArticlePublish, new { @id = "chkArticlePublish", @class = "ArticlePublish" }) <span class="" onclick="$('#chkArticlePublish').click()">@Localiser["label.publish"]</span></div></div>
|
||||
<div class="col">@Html.TextBoxFor(model => model.ArticlePublishOn, new { @id = "ifArticlePublishOn", @class = "sax-input sax-calendar ArticlePublishOn", @readonly = "readonly" })</div>
|
||||
</div>
|
||||
|
||||
@@ -32,6 +32,8 @@
|
||||
var $items = $('.sax-panel-item-list', $pnl.results).hide().empty();
|
||||
if (!response.success) return;
|
||||
sax.data.articleOrganisations = response.organisations;
|
||||
sax.data.defaultSport = response.defaultSport;
|
||||
sax.data.defaultRegion = response.defaultRegion;
|
||||
sax.refreshPaging(response, '#frmArticleFilter', sax.refreshResults);
|
||||
// Menu.
|
||||
let $mnu = $('.sax-burger ul.sax-dropdown-menu', $pnl.filter).empty();
|
||||
@@ -129,6 +131,17 @@
|
||||
sax.createItem = function ()
|
||||
{
|
||||
sax.clearItem();
|
||||
let $frmA = $frm.article;
|
||||
if (sax.data.defaultSport)
|
||||
{
|
||||
$('#ifArticleSportId', $frmA).val(sax.data.defaultSport.id);
|
||||
$('#ifArticleSportCaption', $frmA).val(sax.data.defaultSport.name);
|
||||
}
|
||||
if (sax.data.defaultRegion)
|
||||
{
|
||||
$('#ifArticleRegionId', $frmA).val(sax.data.defaultRegion.id);
|
||||
$('#ifArticleRegionCaption', $frmA).val(sax.data.defaultRegion.name);
|
||||
}
|
||||
sax.populateArticleContent({});
|
||||
sax.openArticleDialog(sax.dlg.title.createArticle);
|
||||
}
|
||||
@@ -136,7 +149,7 @@
|
||||
{
|
||||
let $frmF = $frm.filter;
|
||||
let $frmA = $frm.article;
|
||||
$('#ifArticleId,#ifArticleExists,#ifArticleOrganisationId,#ifArticleRegionId,#ifArticleSportId,input[type="text"],textarea,select', $frmA).val('');
|
||||
$('#ifArticleId,#ifArticleExists,#ifArticleOrganisationId,#ifArticleRegionId,#ifArticleSportId,#ifArticlePublish,input[type="text"],textarea,select', $frmA).val('');
|
||||
let orgId = $('#ifFilterOrganisationId', $frmF).val();
|
||||
$('#ifArticleOrganisationId', $frmA).val(orgId);
|
||||
$('#ifArticleOrganisation', $frmA).val($('#ifFilterOrganisation', $frmF).val());
|
||||
@@ -177,10 +190,12 @@
|
||||
$('#ifArticleRegionCaption', $frmA).val(item.regionCaptionPrimary);
|
||||
$('#ifArticleSportId', $frmA).val(item.sportIdPrimary);
|
||||
$('#ifArticleSportCaption', $frmA).val(item.sportCaptionPrimary);
|
||||
if (item.published)
|
||||
$('span.ArticlePublishedOn', $frmA).text(item.publishedOnFmt);
|
||||
$('div.ArticlePublish', $frmA).toggle(!item.published);
|
||||
$('div.ArticlePublished', $frmA).toggle(!!item.published);
|
||||
$('#ifArticlePublished', $frmA).val(item.published && !item.publishedInFuture ? 1 : 0);
|
||||
$('#chkArticlePublish', $frmA).prop("checked", item.published);
|
||||
$('.sax-input.sax-calendar.ArticlePublishOn', $frmA).datepicker('setDate', item.published ? item.publishedOn_Calendar : 'today');
|
||||
$('span.ArticlePublishedOn', $frmA).text(item.publishedOnFmt);
|
||||
$('div.ArticlePublish', $frmA).toggle(!item.published || item.publishedInFuture);
|
||||
$('div.ArticlePublished', $frmA).toggle(!!item.published && !item.publishedInFuture);
|
||||
$('#cbArticleStatusCode', $frmA).val(item.statusCode);
|
||||
sax.populateArticleContent(item.content);
|
||||
sax.openArticleDialog(sax.dlg.title.updateArticle);
|
||||
@@ -453,7 +468,7 @@
|
||||
$(function ()
|
||||
{
|
||||
$pnl.filter = $('.sax-panel-filter');
|
||||
$pnl.results= $('.sax-panel-results');
|
||||
$pnl.results = $('.sax-panel-results');
|
||||
|
||||
$frm.filter = $('#frmArticleFilter');
|
||||
$('.sax-action.sax-item-create', $pnl.filter).on('click', function () { sax.createItem(); });
|
||||
@@ -475,7 +490,7 @@
|
||||
|
||||
ac.$content = $('.sax-article-panel.sax-article-content');
|
||||
ac.$segList = $('.sax-article-segment-list', ac.$content);
|
||||
sax.initCalendars('.sax-input.sax-calendar').datepicker('option', { maxDate: '+' + (sax.maxPublishDaysAhead||'0') });
|
||||
sax.initCalendars('.sax-input.sax-calendar', { minDate: '-' + (sax.articlePublish.maxDaysBefore || '7'), maxDate: '+' + (sax.articlePublish.maxDaysAhead || '7') });
|
||||
|
||||
var opt = sax.dlgOpts();
|
||||
opt.buttons[sax.dlg.btn.ok] = function () { sax.uploadArticleImage(); };
|
||||
|
||||
@@ -145,7 +145,7 @@
|
||||
}
|
||||
sax.setActivityReaction = function (r)
|
||||
{
|
||||
sax.debug('setActivityReaction', r, $('.sax-dialog-activity button.ActivityReaction' + r));
|
||||
//sax.debug('setActivityReaction', r, $('.sax-dialog-activity button.ActivityReaction' + r));
|
||||
if ($('.sax-dialog-activity button.ActivityReaction' + r).hasClass(selectedClass)) r = 0;
|
||||
sax.clearActivityReactionButton();
|
||||
let fn = function (response)
|
||||
|
||||
@@ -253,7 +253,7 @@
|
||||
$frm.evtId = $('#frmEventId');
|
||||
$frm.evt = $('#frmEvent');
|
||||
$('.sax-input', $frm.evt).on('input', function () { sax.clearControlError(this); });
|
||||
sax.initCalendars('#frmEvent .sax-input.sax-calendar').datepicker('option', { maxDate: '+700' });
|
||||
sax.initCalendars('#frmEvent .sax-input.sax-calendar', { maxDate: '+700' });
|
||||
$frm.evt.on('dblclick', 'input.EventSportCaptionPrimary', oe.selectSportPrimary).on('click', 'button.SelectEventSportPrimary', oe.selectSportPrimary);
|
||||
$frm.evt.on('dblclick', 'input.EventRegionCaptionCountry', oe.selectRegionCountry).on('click', 'button.SelectEventRegionCountry', oe.selectRegionCountry);
|
||||
|
||||
|
||||
@@ -75,7 +75,8 @@ namespace Saxonite.Net.Standard.Base.App
|
||||
}
|
||||
public static class Articles
|
||||
{
|
||||
public static ushort PublishMaxDaysAhead { get; } = 14;
|
||||
public static ushort PublishMaxDaysBefore { get; } = 7;
|
||||
public static ushort PublishMaxDaysAhead { get; } = 10;
|
||||
}
|
||||
public static class Search
|
||||
{
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Saxonite.Net.Standard.Base.App
|
||||
//-------------------------------------------------------------------
|
||||
public static class Version
|
||||
{
|
||||
private static String version { get; } = "1.2.3.1";
|
||||
private static String version { get; } = "1.2.3.2";
|
||||
// Retrieve version.
|
||||
public static String GetFullVersion () { return version; }
|
||||
public static String GetAppVersion ()
|
||||
|
||||
@@ -25,16 +25,16 @@ namespace Saxonite.Net.Standard.Base.Consoles
|
||||
public class IndexContext
|
||||
{
|
||||
// ToDo Include Localiser.
|
||||
public IndexContext (SysId userAccountId)
|
||||
public IndexContext(SysId userAccountId)
|
||||
{
|
||||
UserAccountId = userAccountId;
|
||||
}
|
||||
public SysId UserAccountId { get; }
|
||||
public List<SysId> SportIds { get; } = new List<SysId>();
|
||||
public List<SysId> RegionIds { get; } = new List<SysId>();
|
||||
// Default period is ~12 months ago up to ~3 months in the future.
|
||||
public DateTime EffectiveFrom { get; } = DateUtil.IncrementDate(DateTime.Today, -365);
|
||||
public DateTime EffectiveTo { get; } = DateUtil.IncrementDate(DateTime.Today, 30);
|
||||
// Todo: Default period is ~12 months ago up to ~3 months in the future.
|
||||
public DateTime EffectiveFrom { get; set; } = DateUtil.IncrementDate(DateTime.Today, -365);
|
||||
public DateTime EffectiveTo { get; set; } = DateUtil.IncrementDate(DateTime.Today, 30);
|
||||
public bool IsValid()
|
||||
{
|
||||
// Context must contain at least a sport, a region and a valid effective period.
|
||||
|
||||
Reference in New Issue
Block a user