This commit is contained in:
2022-05-29 13:45:22 +01:00
parent d631ad0223
commit 833798c9f8
93 changed files with 2063 additions and 788 deletions
@@ -1,4 +1,7 @@
using Newtonsoft.Json;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Helpers;
using Saxonite.Net.Core.Web.Admin.Controllers;
using Saxonite.Net.Core.Web.Base.App;
using Saxonite.Net.Standard.Base.App;
using Saxonite.Net.Standard.Base.Bus;
@@ -45,6 +48,21 @@ namespace Saxonite.Net.Core.Web.Admin.App
/// <summary>User - JSON deserialisation route.</summary>
public new UserData User { get { return base.User; } set { SetUser(new UserData_Admin(value)); } }
//-------------------------------------------------------------------
// General filters.
public class FilterData
{
// Sport.
public SysId SportId { get; set; }
// Region.
public SysId RegionId { get; set; }
}
public FilterData Filter { get; private set; } = new FilterData();
//-------------------------------------------------------------------
// Online application encryption IV value - for consistent encryption during session.
public String Base64IV_AdminApp { get; private set; } = SacsEncryptionHelper.InitSymmetricEncryptionIV(SaxController_Admin.Base64Key_AdminApp);
//-------------------------------------------------------------------
}
//=======================================================================
@@ -0,0 +1,214 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.Net.Http.Headers;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Utils;
using Saxonite.Net.Core.Web.Base.App;
using Saxonite.Net.Standard.Base.App;
using Saxonite.Net.Standard.Base.Bus;
using System;
using System.Collections.Specialized;
namespace Saxonite.Net.Core.Web.Admin.Controllers
{
//=======================================================================
// Admin Image Controller - delivers dynamic images.
//=======================================================================
public partial class ImageController : SaxController_Admin
{
//-------------------------------------------------------------------
// Data members.
public static String ParamName_OrganisationLogoEncrypted { get; } = "ole";
public static String ParamName_ArticleImageEncrypted { get; } = "aie";
public static String ParamName_OrganisationId { get; } = "ori";
public static String ParamName_ItemImageId { get; } = "iii";
//-------------------------------------------------------------------
// Construction.
public ImageController(SaxLocaliser localiser, ILogger<HomeController> logger) :
base(localiser, logger)
{
}
//-------------------------------------------------------------------
// Account Contact image request.
//-------------------------------------------------------------------
/// <summary>
/// Get the Account Contact Image for the specified account.
/// <para>Current User Account is used if no other specified in the encrypted parameter.</para>
/// <para>Encrypted parameter:</para>
/// <para>- uaie: User Account Id encrypted.</para>
/// </summary>
[HttpGet]
[Route("Image/Account/Contact")]
public IActionResult GetAccountContactImage(String uaie)
{
String userAccountIdParam = "";// ToDo Decrypt from uaie value.
SysId userAccountId = userAccountIdParam.ToSysId();
if (!SysId.IsValid(userAccountId))
userAccountId = UserAccountId;
return GetAccountContactImage(userAccountId, Sax.ImageType.Avatar);
}
//-------------------------------------------------------------------
// Account Contact Image Profile/Upload request.
//-------------------------------------------------------------------
/// <summary>
/// Get the current Account Profile Contact Image for the specified account.
/// <para>Account is always current User Account - this request is only fir use from the user's own profile page.</para>
/// <para>'Uploaded' avatar image will take precedence as this will be the latest if present.</para>
/// <para>NB Avoid caching this image as it will change whenever a new one is uploaded.</para>
/// </summary>
[HttpGet]
[Route("Image/Account/Contact/Profile")]
[Route("Image/Account/Contact/Upload")]
[ResponseCache(NoStore = true, Location = ResponseCacheLocation.None)]
public IActionResult GetAccountContactImage()
{
// Response should not be cached.
Response.Headers[HeaderNames.CacheControl] = "no-cache, no-store, must-revalidate, max-age=0";
Response.Headers[HeaderNames.Expires] = "-1";
SysId userAccountId = UserAccountId;
return GetAccountContactImage(userAccountId, Sax.ImageType.Avatar_Upload);
}
//-------------------------------------------------------------------
/// <summary>
/// Get the Avatar image for the specified user account.
/// </summary>
/// <param name="imageTypePriority"></param>
/// <returns></returns>
private IActionResult GetAccountContactImage(SysId userAccountId, Sax.ImageType imageTypePriority)
{
String fn = GetType().Name + ".GetAccountContactImage";
// Validate session and referrer.
if (!ValidReferer || !ValidUserSession) return Forbid();
ItemId userItemId = new ItemId((short)Sax.DataItemType.UserAccount, userAccountId);
// Retrieve account contact images.
SaxItemImage.Params prmItemImage = new SaxItemImage.Params();
prmItemImage.ItemIdsIncluded.Add(userItemId);
prmItemImage.ImageTypesIncluded.Add(Sax.ImageType.Avatar);
prmItemImage.ImageTypesIncluded.Add(Sax.ImageType.Avatar_Upload);
prmItemImage.StatusCat = SaxItemImage.StatusCat.ActiveOnly;
SaxItemImage itemImage = null;
foreach (SaxItemImage itemImageCandidate in ItemDataMgr.GetItemImageList(prmItemImage))
{
// One of the 'Avatar' image types will take precedence.
if (itemImage == null || itemImageCandidate.ImageType == imageTypePriority)
itemImage = itemImageCandidate;
}
if (itemImage == null)
return NotFound();
// Construct response.
return File(itemImage.ImageData, itemImage.ContentType);
}
//-------------------------------------------------------------------
// Organisation logo.
//-------------------------------------------------------------------
/// <summary>
/// Get the logo for the specified Organisation.
/// <para>Method parameter name (ole) must match name of encrypted parameter.</para>
/// <para>Encrypted parameters:</para>
/// <para>- ori: Organisation Id.</para>
/// </summary>
[HttpGet]
[Route("Image/Organisation/Logo")]
public IActionResult GetOrganisationLogo(String ole)
{
return GetOrganisationLogo(ole, false);
}
/// <summary>
/// Get the logo for the specified Organisation.
/// <para>Method parameter name (ole) must match name of encrypted parameter.</para>
/// <para>Encrypted parameters:</para>
/// <para>- ori: Organisation Id.</para>
/// </summary>
[HttpGet]
[Route("Image/Organisation/Logo/Upload")]
public IActionResult GetOrganisationLogoUpload(String ole)
{
return GetOrganisationLogo(ole, true);
}
private IActionResult GetOrganisationLogo(String encryptedParams, bool allowUploadImage)
{
String fn = GetType().Name + ".GetOrganisationLogo";
// Validate session and referrer.
if (!ValidReferer || !ValidUserSession) return Forbid();
// Extract encrypted parameters.
NameValueCollection parameters = ExtractSessionParams(encryptedParams);
if (parameters.Count < 1) return Forbid();
// Organisation Id.
SysId organisationId = parameters.Get(ParamName_OrganisationId).ToSysId();
if (!SysId.IsValid(organisationId)) return Forbid();
ItemId organisationItemId = new ItemId((short)Sax.DataItemType.Organisation, organisationId);
// Query Organisation Logo images.
SaxItemImage.Params prmItemImage = new SaxItemImage.Params();
prmItemImage.ItemIdsIncluded.Add(organisationItemId);
prmItemImage.ImageTypesIncluded.Add(Sax.ImageType.OrganisationLogo);
if (allowUploadImage)
prmItemImage.ImageTypesIncluded.Add(Sax.ImageType.OrganisationLogo_Upload);
prmItemImage.StatusCat = SaxItemImage.StatusCat.ActiveOnly;
SaxItemImage itemImage = null;
foreach (SaxItemImage itemImageCandidate in ItemDataMgr.GetItemImageList(prmItemImage))
{
// The 'Upload' image will take precedence if allowed.
if (itemImage == null || itemImageCandidate.ImageType == Sax.ImageType.OrganisationLogo_Upload)
itemImage = itemImageCandidate;
}
if (itemImage == null)
return NotFound();
// Construct response.
Response.Headers[HeaderNames.CacheControl] = "no-cache, no-store, must-revalidate, max-age=0";
Response.Headers[HeaderNames.Expires] = "-1";
return File(itemImage.ImageData, itemImage.ContentType);
}
//-------------------------------------------------------------------
// Article image.
//-------------------------------------------------------------------
/// <summary>
/// Get the specified Article Image.
/// <para>Method parameter name (aie) must match name of encrypted parameter.</para>
/// <para>Encrypted parameters:</para>
/// <para>- iii: Item Image Id.</para>
/// </summary>
[HttpGet]
[Route("Image/Article")]
public IActionResult GetArticleImage(String aie)
{
String fn = GetType().Name + ".GetArticleImage";
// Validate session and referrer.
if (!ValidReferer || !ValidUserSession) return Forbid();
ItemId userItemId = new ItemId((short)Sax.DataItemType.UserAccount, UserAccountId);
// Extract encrypted parameters.
NameValueCollection parameters = ExtractSessionParams(aie);
if (parameters.Count < 1) return Forbid();
// Item Image.
SysId itemImageId = parameters.Get(ParamName_ItemImageId).ToSysId();
if (!SysId.IsValid(itemImageId)) return Forbid();
SaxItemImage itemImage = ItemDataMgr.GetItemImageById(itemImageId);
if (itemImage == null)
return NotFound();
// Construct response.
return File(itemImage.ImageData, itemImage.ContentType);
}
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -9,6 +9,7 @@ using Saxonite.Net.Standard.Base.App;
using Saxonite.Net.Standard.Base.Bus;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Threading.Tasks;
@@ -30,13 +31,20 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
public String CategoryDesc { get; set; }
public long MemberCount { get; set; }
// Sport.
public long SportId { get; set; }
public String SportId { get; set; }
public String SportName { get; set; }
// Region - country.
public long RegionIdCountry { get; set; }
public String RegionNameCountry { get; set; }
// Primary Region.
public class RegionData
{
public String Id { get; set; }
public String Name { get; set; }
public bool? Country { get; set; } = null;
}
public RegionData RegionPrimary { get; } = new RegionData();
// Address.
public String AddressSummary { get; set; }
// Logo.
public String LogoImageUrl { get; set; }
}
private class OrganisationItemData : OrganisationListData
{
@@ -55,22 +63,30 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
data.CategoryDesc = OrganisationCategoryCodes.GetDescForType(organisation.OrganisationCategory);
data.MemberCount = AccountMgr.GetOrganisationMemberCount(organisation.Id);
// Sport.
data.SportId = SysId.ToLong(organisation.SportIdPrimary);
data.SportId = SysId.ToString(organisation.SportIdPrimary, null);
using (SaxSport sport = ReferenceMgr.GetSportById(organisation.SportIdPrimary))
data.SportName = sport?.Name ?? "";
// Region.
data.RegionIdCountry = SysId.ToLong(organisation.RegionIdPrimary);
using (SaxRegion region = ReferenceMgr.GetRegionById(organisation.RegionIdPrimary))
data.RegionNameCountry = region?.Name ?? "";
data.SportName = sport?.Name ?? null;
// Primary region.
data.RegionPrimary.Id = SysId.ToString(organisation.RegionIdPrimary, null);
SaxRegion.Data region = Internals.GetRegion(organisation.RegionIdPrimary);
if (region != null)
{
data.RegionPrimary.Name = region.Name;
data.RegionPrimary.Country = region.RegionType == Sax.RegionType.Country ? true : (bool?)null;
}
// Common properties.
data.StatusCode = organisation.StatusCode;
data.StatusDesc = organisation.StatusDesc;
// Organisation Logo image url.
if (ItemDataMgr.ItemHasActiveImage(organisation.GetItemId(), Sax.ImageType.OrganisationLogo))
data.LogoImageUrl = GetOrganisationLogoUrl(organisation.Id, false);
}
private void PopulateOrganisationResponseItemData(SaxOrganisation organisation, SaxItemAddress address, OrganisationItemData data)
{
PopulateOrganisationResponseListData(organisation, data as OrganisationListData);
data.About = organisation.About;
data.Facilities = organisation.Facilities;
PopulateOrganisationResponseListData(organisation, data);
data.About = StringUtil.OnEmpty(organisation.About, null);
data.Facilities = StringUtil.OnEmpty(organisation.Facilities, null);
// Contact methods.
SaxContactData contactData = new SaxContactData(organisation.ContactData);
foreach (Sax.ContactMethod method in contactData.Methods)
@@ -82,14 +98,16 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
if (address != null && !address.IsStatusDeleted)
{
data.Address = new AjaxResponse_Data.AddressData();
data.Address.Id = address.Id.ToString();
data.Address.Line1 = address.Line1;
data.Address.Line2 = address.Line2;
data.Address.Line3 = address.Line3;
data.Address.Id = address.Id.ToString(null);
data.Address.Line1 = StringUtil.OnEmpty(address.Line1, null);
data.Address.Line2 = StringUtil.OnEmpty(address.Line2, null);
data.Address.Line3 = StringUtil.OnEmpty(address.Line3, null);
data.Address.Town = address.Town;
data.Address.Province = address.Province;
data.Address.Country = address.Country;
data.Address.PostalCode = address.PostalCode;
data.Address.RegionIdProvince = SysId.ToString(address.RegionIdProvince, null);
data.Address.RegionNameProvince = StringUtil.OnEmpty(address.Province, null);
data.Address.RegionIdCountry = SysId.ToString(address.RegionIdCountry, null);
data.Address.RegionNameCountry = StringUtil.OnEmpty(address.Country, null);
data.Address.PostalCode = StringUtil.OnEmpty(address.PostalCode, null);
}
// Common properties.
data.Notes = organisation.Notes;
@@ -136,13 +154,19 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
responseData.Statuses.Add(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status));
responseData.DefaultStatusCode = SacsSystem.GetStatusCode(SaxOrganisation.DefaultStatus);
// Store filter values.
SysId filterSportId = model.Filter.OrganisationSportId.ToSysId();
SessionData_Admin.Filter.SportId = SysId.IsValid(filterSportId) ? filterSportId : null;
SysId filterRegionId = model.Filter.OrganisationRegionId.ToSysId();
SessionData_Admin.Filter.RegionId = SysId.IsValid(filterRegionId) ? filterRegionId : null;
// Item filter.
SaxOrganisation.Params prmOrganisation = new SaxOrganisation.Params();
prmOrganisation.OrganisationFilter = model.Filter.Organisation;
prmOrganisation.OrganisationType = model.FilterOrganisationType;
prmOrganisation.OrganisationCategory = model.FilterOrganisationCategory;
prmOrganisation.SportIdsIncluded.AddId(model.Filter.OrganisationSportId.ToSysId());
prmOrganisation.RegionIdsIncluded.AddId(model.Filter.OrganisationRegionId.ToSysId());
prmOrganisation.SportIdsIncluded.AddId(filterSportId);
prmOrganisation.RegionIdsIncluded.AddId(filterRegionId);
prmOrganisation.StatusCat = model.Filter.OrganisationStatusCategoryCode != null ? model.FilterOrganisationStatusCategory : SaxOrganisation.StatusCat.NotDeleted;
prmOrganisation.SortColumns.Add(AccountMgr.GetOrganisationColumnDfn(SaxOrganisation.Column.Name));
model.Paging.ItemTotal = (ulong)AccountMgr.GetOrganisationCount(prmOrganisation);
@@ -153,10 +177,9 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
ColumnDfn colName = AccountMgr.GetOrganisationColumnDfn(SaxOrganisation.Column.Name);
ColumnDfn colOrganisationType = AccountMgr.GetOrganisationColumnDfn(SaxOrganisation.Column.OrganisationType);
ColumnDfn colOrganisationCategory = AccountMgr.GetOrganisationColumnDfn(SaxOrganisation.Column.OrganisationCategory);
ColumnDfn colPhoneMain = AccountMgr.GetOrganisationColumnDfn(SaxOrganisation.Column.PhoneMain);
ColumnDfn colPhoneAlt = AccountMgr.GetOrganisationColumnDfn(SaxOrganisation.Column.PhoneAlt);
ColumnDfn colUserCount = AccountMgr.GetOrganisationColumnDfn(SaxOrganisation.Column.User_Count);
ColumnDfn colMemberCount = AccountMgr.GetOrganisationColumnDfn(SaxOrganisation.Column.Member_Count);
ColumnDfn colLogoCount = AccountMgr.GetOrganisationColumnDfn(SaxOrganisation.Column.LogoImage_Count);
ColumnDfn colSportId = AccountMgr.GetOrganisationColumnDfn(SaxOrganisation.Column.SportId);
ColumnDfn colSportName = AccountMgr.GetOrganisationColumnDfn(SaxOrganisation.Column.Sport_Name);
ColumnDfn colRegionId = AccountMgr.GetOrganisationColumnDfn(SaxOrganisation.Column.RegionId);
@@ -168,9 +191,7 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
colName,
colOrganisationType,
colOrganisationCategory,
colPhoneMain,
colPhoneAlt,
colUserCount, colMemberCount,
colUserCount, colMemberCount, colLogoCount,
colSportId, colSportName,
colRegionId, colRegionName,
colStatus
@@ -182,22 +203,28 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
while (resultSet != null && resultSet.HasRows && resultSet.NextRecord())
{
NamedValue.Map values = resultSet.GetRecordValues();
SysId organisationId = new SysId(values.GetLong(colId.DataName));
OrganisationListData organisationData = new OrganisationListData()
{
Id = values.GetLong(colId.DataName).ToString(),
Id = organisationId.ToString(),
Name = values.GetString(colName.DataName),
TypeCode = values.GetString(colOrganisationType.DataName),
TypeDesc = OrganisationTypeCodes.GetDescForCode(values.GetString(colOrganisationType.DataName)),
CategoryCode = values.GetString(colOrganisationCategory.DataName),
CategoryDesc = OrganisationCategoryCodes.GetDescForCode(values.GetString(colOrganisationCategory.DataName)),
MemberCount = StringUtil.ToLong(values.GetString(colMemberCount.DataName)),
SportId = values.GetLong(colSportId.DataName),
SportName = values.GetString(colSportName.DataName),
RegionIdCountry = values.GetLong(colRegionId.DataName),
RegionNameCountry = values.GetString(colRegionName.DataName),
SportId = SysId.ToString(new SysId(values.GetLong(colSportId.DataName)), null),
SportName = StringUtil.OnEmpty(values.GetString(colSportName.DataName), null),
StatusCode = values.GetString(colStatus.DataName),
StatusDesc = SacsSystem.GetStatusDescForCode(values.GetString(colStatus.DataName))
};
// Logo image.
if (StringUtil.ToLong(values.GetString(colLogoCount.DataName)) > 0)
organisationData.LogoImageUrl = GetOrganisationLogoUrl(organisationId, false);
// Primary region.
organisationData.RegionPrimary.Id = SysId.ToString(new SysId(values.GetLong(colRegionId.DataName)), null);
organisationData.RegionPrimary.Name = StringUtil.OnEmpty(values.GetString(colRegionName.DataName), null);
// Add item to list.
responseData.Organisations.Add(organisationData);
}
}
@@ -318,8 +345,8 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
organisation.OrganisationCategory = model.OrganisationCategory;
if (model.OrganisationSportId != null)
organisation.SportIdPrimary = model.OrganisationSportId.ToSysId();
if (model.OrganisationRegionIdCountry != null)
organisation.RegionIdPrimary = model.OrganisationRegionIdCountry.ToSysId();
if (model.OrganisationRegionIdPrimary != null)
organisation.RegionIdPrimary = model.OrganisationRegionIdPrimary.ToSysId();
if (model.OrganisationAbout != null)
organisation.About = model.OrganisationAbout;
if (model.OrganisationFacilities != null)
@@ -356,7 +383,10 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
if (model.Address.IsPopulated())
{
// Organisation regions.
SaxRegion.Data regionCountry = Internals.GetRegion(organisation.RegionIdPrimary);
SaxRegion.Data regionCountry = Internals.GetRegion(model.Address.RegionIdCountry.ToSysId());
if (regionCountry == null)
// Default to Organisation's primary region.
regionCountry = Internals.GetRegion(organisation.RegionIdPrimary);
if (regionCountry != null && regionCountry.RegionType != Sax.RegionType.Country)
regionCountry = null;
SaxRegion.Data regionProvince = null;
@@ -392,11 +422,6 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
organisationAddress.Country = regionCountry.Name;
organisationAddress.RegionIdCountry = regionCountry.Id;
}
else
{
if (model.Address.Country != null)
organisationAddress.Country = model.Address.Country;
}
organisationAddress.PostalCode = model.Address.PostalCode;
organisationAddress.Status = SaxItemAddress.DefaultStatus;
@@ -420,7 +445,7 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
}
}
}
else
else if (organisationAddress != null && !organisationAddress.IsStatusDeleted)
{
// Address not populated - delete it.
if (!ItemDataMgr.DeleteItemAddress(organisationAddress, DbUpdateInfo))
@@ -0,0 +1,308 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Sarand.Net.Standard.Base.App;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Dbas;
using Sarand.Net.Standard.Base.Helpers;
using Sarand.Net.Standard.Base.Utils;
using Saxonite.Net.Core.Web.Admin.Models;
using Saxonite.Net.Standard.Base.App;
using Saxonite.Net.Standard.Base.Bus;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
namespace Saxonite.Net.Core.Web.Admin.Controllers
{
//=======================================================================
// Controller: Organisation Images - Ajax
//=======================================================================
partial class OrganisationController
{
//-------------------------------------------------------------------
private class OrganisationImagesData : OrganisationItemData
{
}
private void PopulateOrganisationResponseImagesData(SaxOrganisation organisation, SaxItemAddress address, OrganisationImagesData data)
{
PopulateOrganisationResponseItemData(organisation, address, data);
}
//-------------------------------------------------------------------
// Get Organisation Images ajax request.
//-------------------------------------------------------------------
private class AjaxResponse_OrganisationImages : AjaxResponse_Data
{
// Construction.
public AjaxResponse_OrganisationImages(SaxModel_Admin model) : base(model) { }
// Organisation details.
public OrganisationImagesData organisation { get; } = new OrganisationImagesData();
// Reference data.
public List<String> ImageContentTypes { get; set; }
}
//-------------------------------------------------------------------
[HttpPost]
[Route("Organisation/Ajax/GetImages")]
[Route("Organisation/Ajax/GetItemImages")]
public IActionResult Ajax_GetImages(Model_Organisation model)
{
String fn = GetType().Name + ".Ajax_GetImages";
String messageTitle = Localiser["organisation.caption.organisation"];
AjaxResponse_OrganisationImages responseData = new AjaxResponse_OrganisationImages(model);
// Validate session.
if (!ValidUserSession)
return GetAjaxResult_InvalidSession(responseData);
// Record disposable items as they are created so all can be disposed when needed.
using (DisposableCollection<SacsHierarchyItem> disposableItems = new DisposableCollection<SacsHierarchyItem>())
{
// Reference data - Image content types.
responseData.ImageContentTypes = SaxItemImage.GetValidContentTypes(Sax.DataItemType.Organisation);
// Identify item.
SysId organisationId = model.OrganisationId.ToSysId();
if (!SysId.IsValid(organisationId))
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"]));
}
// Organisation address.
SaxItemAddress address = ItemDataMgr.GetFirstItemAddressByItemAndType(organisation.GetItemId());
disposableItems.Add(address);
// Construct response.
PopulateOrganisationResponseImagesData(organisation, address, responseData.organisation);
// Complete response.
responseData.Success = true;
}
return Json(responseData);
}
//-------------------------------------------------------------------
// Account - Upload Contact Image.
// Ref. http://www.binaryintellect.net/articles/474dc031-087f-4b81-b994-9ca2adb949d6.aspx
//-------------------------------------------------------------------
private class AjaxResponse_UploadOrganisationLogoImage : AjaxResponse_Data
{
// Construction.
public AjaxResponse_UploadOrganisationLogoImage(SaxModel_Admin model) : base(model) { }
// Uploaded image URL.
public String ImageUrl { get; set; }
// Upload message.
public String UploadMsg { get; set; }
}
// Ajax request.
[HttpPost]
[Route("Organisation/Ajax/UploadLogo")]
[Route("Organisation/Ajax/UploadLogoImage")]
public IActionResult UploadOrganisationLogoImage(Model_Organisation model)
{
String fn = GetType().Name + ".UploadOrganisationLogoImage";
AjaxResponse_UploadOrganisationLogoImage responseData = new AjaxResponse_UploadOrganisationLogoImage(model);
String messageTitle = Localiser["organisation.caption.organisation"];
// Validate session and referrer.
if (!ValidReferer) return Forbid();
if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
RefreshModel(model);
// Record disposable items as they are created so all can be disposed when needed.
using (DisposableCollection<SacsHierarchyItem> disposableItems = new DisposableCollection<SacsHierarchyItem>())
{
// Retrieve organisation.
SysId organisationId = model.OrganisationId.ToSysId();
if (!SysId.IsValid(organisationId))
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.specified"]));
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"]));
}
// Validate number of images.
if (model.OrganisationLogoImage.IsEmpty())
{
SaLogger.Warn(fn + " No image file supplied for upload");
return Json(responseData);
}
if (model.OrganisationLogoImage.Count != 1)
{
SaLogger.Warn(fn + " Invalid number of image files uploaded: " + model.OrganisationLogoImage.Count);
return Json(responseData.SetControlError("OrganisationLogoImage", Localiser["msg.upload.image.single"]));
}
IFormFile file = model.OrganisationLogoImage[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("OrganisationLogoImage", Localiser["msg.upload.image.invalid"]));
// Validate mime type.
if (!SaxItemImage.GetValidMimeTypes(Sax.DataItemType.UserAccount).Contains(imageConfig.MimeType))
return Json(responseData.SetControlError("OrganisationLogoImage", Localiser["msg.upload.image.invalid.mime"]));
// Validate content type.
if (StringUtil.IsEmpty(file.ContentType) || !SaxItemImage.GetValidContentTypes(Sax.DataItemType.UserAccount).ContainsCI(file.ContentType))
return Json(responseData.SetControlError("OrganisationLogoImage", Localiser["msg.upload.image.invalid.content.type"]));
// Resize the image if required.
if (!ImageUtils.ConstrainImage(imageConfig, Sax.Config.Organisation.Logo.WidthMax, Sax.Config.Organisation.Logo.HeightMax))
return Json(responseData.SetControlError("OrganisationLogoImage", Localiser["msg.upload.image.resize.failed"]));
// Image belongs to the organisation.
ItemId organisationItemId = organisation.GetItemId();
// Store uploaded image as 'Upload' Logo - awaiting confirmation that the details are to be saved.
SaxItemImage itemImage = ItemDataMgr.GetItemImage(organisationItemId, Sax.ImageType.OrganisationLogo_Upload, SaxItemImage.StatusCat.Any);
if (itemImage == null)
itemImage = ItemDataMgr.CreateItemImage(organisationItemId, Sax.ImageType.OrganisationLogo_Upload);
itemImage.Filename = file.FileName;
itemImage.Mime = SacsContentTypeHelper.GetMimeTypeFromContentType(file.ContentType).ToString().ToLower();
itemImage.ContentType = file.ContentType;
itemImage.ImageData = imageConfig.ImageData;
itemImage.Width = imageConfig.Width;
itemImage.Height = imageConfig.Height;
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("OrganisationLogoImage", 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("OrganisationLogoImage", Localiser["msg.error.item.insert.failed"]));
}
}
// Return image url with response.
responseData.ImageUrl = GetOrganisationLogoUrl(organisation.Id, true);
}
// Complete response.
responseData.SetNotification(messageTitle, "Image uploaded.");
responseData.Success = true;
return Json(responseData);
}
//-------------------------------------------------------------------
// Store Organisation Images ajax request.
//-------------------------------------------------------------------
[HttpPost]
[Route("Organisation/Ajax/StoreImages")]
public IActionResult Ajax_StoreImages(Model_Organisation model)
{
String fn = GetType().Name + ".Ajax_StoreImages";
String messageTitle = Localiser["organisation.caption.organisation"];
AjaxResponse_OrganisationImages responseData = new AjaxResponse_OrganisationImages(model);
// Validate session.
if (!ValidUserSession)
return GetAjaxResult_InvalidSession(responseData);
// Record disposable items as they are created so all can be disposed when needed.
using (DisposableCollection<SacsHierarchyItem> disposableItems = new DisposableCollection<SacsHierarchyItem>())
{
// Validate item properties.
model.ValidateOrganisationData(responseData);
if (responseData.HasControlErrors())
return Json(responseData);
// Retrieve organisation.
SysId organisationId = model.OrganisationId.ToSysId();
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"]));
}
// Organisation address.
SaxItemAddress address = ItemDataMgr.GetFirstItemAddressByItemAndType(organisation.GetItemId());
disposableItems.Add(address);
// Check for uploaded logo image.
ItemId organisationItemId = organisation.GetItemId();
SaxItemImage itemImageLogoUploaded = ItemDataMgr.GetItemImage(organisationItemId, Sax.ImageType.OrganisationLogo_Upload, SaxItemImage.StatusCat.ActiveOnly);
disposableItems.Add(itemImageLogoUploaded);
if (itemImageLogoUploaded != null)
{
// Retrieve current OrganisationLogo image.
SaxItemImage itemImageLogo = ItemDataMgr.GetItemImage(organisationItemId, Sax.ImageType.OrganisationLogo, SaxItemImage.StatusCat.Any);
if (itemImageLogo == null)
itemImageLogo = ItemDataMgr.CreateItemImage(organisationItemId, Sax.ImageType.OrganisationLogo);
disposableItems.Add(itemImageLogo);
// Copy properties from uploaded image.
itemImageLogo.Filename = itemImageLogoUploaded.Filename;
itemImageLogo.Mime = itemImageLogoUploaded.Mime;
itemImageLogo.ContentType = itemImageLogoUploaded.ContentType;
itemImageLogo.Width = itemImageLogoUploaded.Width;
itemImageLogo.Height = itemImageLogoUploaded.Height;
itemImageLogo.ImageData = itemImageLogoUploaded.ImageData;
itemImageLogo.Status = SaxItemImage.DefaultStatus;
if (!SysId.IsValid(itemImageLogo.Id))
{
if (!ItemDataMgr.InsertItemImage(itemImageLogo, DbUpdateInfo))
{
SaLogger.Warn(fn + " Failed to insert logo image - " + ItemDataMgr.ErrorStateMessage);
return Json(responseData.SetControlError("AccountContactImage", Localiser["msg.error.item.insert.failed"]));
}
}
else
{
if (!ItemDataMgr.UpdateItemImage(itemImageLogo, DbUpdateInfo))
{
SaLogger.Warn(fn + " Failed to update logo image - " + ItemDataMgr.ErrorStateMessage);
return Json(responseData.SetControlError("AccountContactImage", Localiser["msg.error.item.update.failed"]));
}
}
// Logically delete the uplaoded image.
itemImageLogoUploaded.Status = SaStatus.Deleted;
if (!ItemDataMgr.UpdateItemImage(itemImageLogoUploaded, DbUpdateInfo))
SaLogger.Warn(fn + " Failed to logically delete uploaded logo image - " + ItemDataMgr.ErrorStateMessage);
}
// Construct response.
PopulateOrganisationResponseImagesData(organisation, address, responseData.organisation);
}
// Complete response.
responseData.Success = true;
return Json(responseData);
}
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -32,8 +32,19 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
if (!ValidUserSession)
return RedirectToAction("", "");
// Paging.
// Model.
Model_Organisation model = new Model_Organisation(Localiser);
// Stored Sport filter.
model.Filter.OrganisationSportId = SessionData_Admin.Filter.SportId?.ToString() ?? null;
using (SaxSport filterSport = ReferenceMgr.GetSportById(SessionData_Admin.Filter.SportId))
model.Filter.OrganisationSportName = Localiser.GetSportName(SessionData_Admin.Filter.SportId, filterSport?.Name ?? "");
// Stored Region filter.
model.Filter.OrganisationRegionId = SessionData_Admin.Filter.RegionId?.ToString() ?? null;
using (SaxRegion filterRegion = ReferenceMgr.GetRegionById(SessionData_Admin.Filter.RegionId))
model.Filter.OrganisationRegionName = Localiser.GetRegionName(SessionData_Admin.Filter.RegionId, filterRegion?.Name ?? "");
// Paging.
model.Paging.PageNo = 1;
model.Paging.PageLength = 8;
@@ -21,7 +21,7 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
// Region data.
private class RegionListData : AjaxResponse_Data.ItemData_Base
{
public String RegionTypeCode { get; set; }
public int? RegionType { get; set; } = null;
public String RegionTypeDesc { get; set; }
public String CountryIso2Code { get; set; }
public String Name { get; set; }
@@ -29,12 +29,13 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
}
private class RegionItemData : RegionListData
{
public String RegionTypeCode { get; set; }
public String RegionIdParent { get; set; }
}
private void PopulateRegionResponseListData(SaxRegion region, RegionListData data)
{
data.Id = SysId.ToString(region.Id);
data.RegionTypeCode = RegionTypeCodes.GetCodeForType(region.RegionType);
data.RegionType = (int)region.RegionType;
data.RegionTypeDesc = RegionTypeCodes.GetDescForType(region.RegionType);
data.CountryIso2Code = region.CountryIso2Code;
data.Name = region.Name;
@@ -48,6 +49,7 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
private void PopulateRegionResponseItemData(SaxRegion region, RegionItemData data)
{
PopulateRegionResponseListData(region, data);
data.RegionTypeCode = RegionTypeCodes.GetCodeForType(region.RegionType);
data.RegionIdParent = SysId.ToString(region.RegionIdParent);
}
@@ -121,7 +123,7 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
RegionListData regionData = new RegionListData()
{
Id = values.GetString(colId.DataName),
RegionTypeCode = RegionTypeCodes.GetCodeForType(regionType),
RegionType = (int)regionType,
RegionTypeDesc = RegionTypeCodes.GetDescForType(regionType),
CountryIso2Code = values.GetString(colIso2Code.DataName),
Name = values.GetString(colName.DataName),
@@ -15,6 +15,7 @@ using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
namespace Saxonite.Net.Core.Web.Admin.Controllers
{
@@ -119,6 +120,21 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
ClearSessionData();
}
//-------------------------------------------------------------------
// Organisation utilities.
//-------------------------------------------------------------------
/// <summary>
/// Construct URL to display Organisation logo.
/// <para>- Option to allow for 'Upload' image if active.</para>
/// </summary>
protected String GetOrganisationLogoUrl(SysId organisationId, bool uploadImage)
{
String imageLink = "Image/Organisation/Logo" + (uploadImage ? "/Upload" : "") + "?";
NameValueCollection parameters = new NameValueCollection();
parameters.Add(ImageController.ParamName_OrganisationId, SysId.ToString(organisationId));
return imageLink + ImageController.ParamName_OrganisationLogoEncrypted + "=" + EncryptSessionParams(parameters);
}
//-------------------------------------------------------------------
// Keep Logged In.
//-------------------------------------------------------------------
@@ -187,6 +203,25 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
return keepLoggedInParams;
}
//-------------------------------------------------------------------
// Parameter encryption, eg. for images.
//-------------------------------------------------------------------
// Encryption key is the same for all users each time the application is started,
// but a different IV value is generated for each session so that the links/parameters cannot be shared.
public static String Base64Key_AdminApp { get; } = SacsEncryptionHelper.EncodePlainKey("Saxonite&Admin#Encryption-"+DateTime.Today.Format("ddMMyy"), SacsEncryptionHelper.KeyLength);
protected String EncryptSessionParams(NameValueCollection parameters)
{
return HttpUtility.UrlEncode(EncryptParameters(parameters, SessionData_Admin.Base64IV_AdminApp, Base64Key_AdminApp));
}
public static String EncryptSessionParams(SaxController_Admin controller, NameValueCollection parameters)
{
return controller.EncryptSessionParams(parameters);
}
protected NameValueCollection ExtractSessionParams(String encryptedParams)
{
return DecryptParameters(encryptedParams, SessionData_Admin.Base64IV_AdminApp, Base64Key_AdminApp);
}
//-------------------------------------------------------------------
}
//=======================================================================
@@ -161,6 +161,12 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
foreach (SaStatus status in SaxUserAccount.ValidStatuses.FindAll(item => item != SaStatus.Deleted))
responseData.Statuses.Add(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status));
// Store filter values.
SysId filterSportId = model.Filter.UserSportId.ToSysId();
SessionData_Admin.Filter.SportId = SysId.IsValid(filterSportId) ? filterSportId : null;
SysId filterRegionId = model.Filter.UserRegionId.ToSysId();
SessionData_Admin.Filter.RegionId = SysId.IsValid(filterRegionId) ? filterRegionId : null;
// Item filter.
SaxUserAccount.Params prmUserAccount = new SaxUserAccount.Params();
prmUserAccount.UserFilterPartial = model.Filter.User;
@@ -31,8 +31,19 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
if (!ValidUserSession)
return RedirectToAction("", "");
// Paging.
// Model.
Model_User model = new Model_User(Localiser);
// Stored Sport filter.
model.Filter.UserSportId = SessionData_Admin.Filter.SportId?.ToString() ?? null;
using (SaxSport filterSport = ReferenceMgr.GetSportById(SessionData_Admin.Filter.SportId))
model.Filter.UserSportName = Localiser.GetSportName(SessionData_Admin.Filter.SportId, filterSport?.Name ?? "");
// Stored Region filter.
model.Filter.UserRegionId = SessionData_Admin.Filter.RegionId?.ToString() ?? null;
using (SaxRegion filterRegion = ReferenceMgr.GetRegionById(SessionData_Admin.Filter.RegionId))
model.Filter.UserRegionName = Localiser.GetRegionName(SessionData_Admin.Filter.RegionId, filterRegion?.Name ?? "");
// Paging.
model.Paging.PageNo = 1;
model.Paging.PageLength = 12;
@@ -39,7 +39,7 @@ namespace Saxonite.Net.Core.Web.Admin.Models
public String Town { get; set; }
public String Province { get; set; }
public String RegionIdProvince { get; set; }
public String Country { get; set; }
public String RegionIdCountry { get; set; }
public String PostalCode { get; set; }
//-------------------------------------------------------------------
@@ -47,14 +47,14 @@ namespace Saxonite.Net.Core.Web.Admin.Models
/// <summary>Have any address values been supplied by the form.</summary>
public bool IsSpecified()
{
if (Id != null || Line1 != null || Town != null || Province != null || Country != null || PostalCode != null)
if (Id != null || Line1 != null || Town != null || Province != null || RegionIdCountry != null || PostalCode != null)
return true;
return false;
}
/// <summary>Have any address values been populated on the form.</summary>
public bool IsPopulated()
{
if (SysId.IsValid(Id.ToSysId()) || !StringUtil.IsEmpty(Line1) || !StringUtil.IsEmpty(Town) || !StringUtil.IsEmpty(Province) || !StringUtil.IsEmpty(Country) || !StringUtil.IsEmpty(PostalCode))
if (SysId.IsValid(Id.ToSysId()) || !StringUtil.IsEmpty(Line1) || !StringUtil.IsEmpty(Town) || !StringUtil.IsEmpty(Province) || !StringUtil.IsEmpty(RegionIdCountry) || !StringUtil.IsEmpty(PostalCode))
return true;
return false;
}
@@ -63,7 +63,7 @@ namespace Saxonite.Net.Core.Web.Admin.Models
// Validation.
//-------------------------------------------------------------------
// Address.
public bool ValidateAddressData(SaxController_Base.AjaxResponse_Data responseData)
public bool ValidateAddressData(SaxModel_Admin model, SaxController_Base.AjaxResponse_Data responseData)
{
// Are any properties populated.
bool populated = IsPopulated();
@@ -101,32 +101,37 @@ namespace Saxonite.Net.Core.Web.Admin.Models
// Address Town - mandatory if any value populated.
if (Town != null)
{
responseData.SetControlValue(ControlNameSuffix + "Town", Town);
String controlName = ControlNameSuffix + nameof(Town);
responseData.SetControlValue(controlName, Town);
if (StringUtil.IsEmpty(Town) && populated)
responseData.SetControlError(ControlNameSuffix + "Town", Model.Localiser["msg.validation.mandatory.value"]);
responseData.SetControlError(controlName, Model.Localiser["msg.validation.mandatory.value"]);
else if (StringUtil.GetLength(Town) > Model.GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.ItemAddress_Town))
responseData.SetControlError(ControlNameSuffix + "Town", Model.Localiser["msg.validation.maximum.length", Model.GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.ItemAddress_Town)]);
responseData.SetControlError(controlName, Model.Localiser["msg.validation.maximum.length", Model.GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.ItemAddress_Town)]);
}
// Address Province - optional.
if (Province != null)
{
responseData.SetControlValue(ControlNameSuffix + "Province", Province);
String controlName = ControlNameSuffix + nameof(Province);
responseData.SetControlValue(controlName, Province);
if (!StringUtil.IsEmpty(Province))
{
if (StringUtil.GetLength(Province) > Model.GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.ItemAddress_Province))
responseData.SetControlError(ControlNameSuffix + "Province", Model.Localiser["msg.validation.maximum.length", Model.GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.ItemAddress_Province)]);
responseData.SetControlError(controlName, Model.Localiser["msg.validation.maximum.length", Model.GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.ItemAddress_Province)]);
}
}
// Address Country - optional.
if (Country != null)
// Address Country - mandatory if any value populated.
if (RegionIdCountry != null)
{
responseData.SetControlValue(ControlNameSuffix + "Country", Country);
if (!StringUtil.IsEmpty(Country))
String controlName = ControlNameSuffix + nameof(RegionIdCountry);
if (!SysId.IsValid(RegionIdCountry.ToSysId()) && populated)
responseData.SetControlError(controlName, Model.Localiser["msg.validation.mandatory.value"]);
else if (SysId.IsValid(RegionIdCountry.ToSysId()))
{
if (StringUtil.GetLength(Country) > Model.GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.ItemAddress_Country))
responseData.SetControlError(ControlNameSuffix + "Country", Model.Localiser["msg.validation.maximum.length", Model.GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.ItemAddress_Country)]);
SaxRegion.Data region = model.Internals.GetRegion(RegionIdCountry.ToSysId());
if (region == null || region.RegionType != Sax.RegionType.Country)
responseData.SetControlError(controlName, Model.Localiser["msg.validation.invalid.value"]);
}
}
@@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Rendering;
using Sarand.Net.Standard.Base.App;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Core;
@@ -34,7 +35,9 @@ namespace Saxonite.Net.Core.Web.Admin.Models
public String OrganisationTypeCode { get; set; }
public String OrganisationCategoryCode { get; set; }
public String OrganisationSportId { get; set; }
public String OrganisationSportName { get; set; }
public String OrganisationRegionId { get; set; }
public String OrganisationRegionName { get; set; }
public String OrganisationStatusCategoryCode { get; set; }
}
public FilterData Filter { get; } = new FilterData();
@@ -75,7 +78,7 @@ namespace Saxonite.Net.Core.Web.Admin.Models
public String OrganisationCategoryValue { get; set; }
public Sax.OrganisationCategory OrganisationCategory { get { return (Sax.OrganisationCategory)OrganisationCategoryCodes.GetTypeForCode(OrganisationCategoryValue); } }
public String OrganisationSportId { get; set; }
public String OrganisationRegionIdCountry { get; set; }
public String OrganisationRegionIdPrimary { get; set; }
public String OrganisationAbout { get; set; }
public String OrganisationFacilities { get; set; }
// Common properties.
@@ -92,6 +95,11 @@ namespace Saxonite.Net.Core.Web.Admin.Models
// Address.
public ModelData_Address Address { get; }
//-------------------------------------------------------------------
// Images.
public List<IFormFile> OrganisationLogoImage { get; set; }
//-------------------------------------------------------------------
// Utilities.
public bool IsSportMandatory()
{
@@ -143,15 +151,15 @@ namespace Saxonite.Net.Core.Web.Admin.Models
}
}
// Organisation region.
if (OrganisationRegionIdCountry != null)
// Organisation primary region.
if (OrganisationRegionIdPrimary != null)
{
using (SaxRegion region = ReferenceMgr.GetRegionById(OrganisationRegionIdCountry.ToSysId()))
using (SaxRegion region = ReferenceMgr.GetRegionById(OrganisationRegionIdPrimary.ToSysId()))
{
if (region == null)
responseData.SetControlError(nameof(OrganisationRegionIdCountry), Localiser["msg.validation.invalid.value"]);
responseData.SetControlError(nameof(OrganisationRegionIdPrimary), Localiser["msg.validation.invalid.value"]);
else if (region.RegionType != Sax.RegionType.Country && region.RegionType != Sax.RegionType.Continent && region.RegionType != Sax.RegionType.World)
responseData.SetControlError(nameof(OrganisationRegionIdCountry), "Organisation region must be a country or international region");
responseData.SetControlError(nameof(OrganisationRegionIdPrimary), "Organisation region must be a country or international region");
}
if (!StringUtil.IsEmpty(OrganisationName))
@@ -161,7 +169,7 @@ namespace Saxonite.Net.Core.Web.Admin.Models
if (SysId.IsValid(OrganisationId.ToSysId()))
prmOrganisation.IdsExcluded.Add(OrganisationId.ToSysId());
prmOrganisation.NameFull = OrganisationName;
prmOrganisation.RegionIdsIncluded.Add(OrganisationRegionIdCountry.ToSysId());
prmOrganisation.RegionIdsIncluded.Add(OrganisationRegionIdPrimary.ToSysId());
prmOrganisation.StatusCat = SaxOrganisation.StatusCat.Any;
if (AccountMgr.GetOrganisationCount(prmOrganisation) > 0)
responseData.SetControlError(nameof(OrganisationName), Localiser["msg.validation.duplicate.value"]);
@@ -226,7 +234,7 @@ namespace Saxonite.Net.Core.Web.Admin.Models
// Validate address fields.
if (Address != null)
Address.ValidateAddressData(responseData);
Address.ValidateAddressData(this, responseData);
return !responseData.HasControlErrors();
}
@@ -35,7 +35,9 @@ namespace Saxonite.Net.Core.Web.Admin.Models
{
public String User { get; set; }
public String UserSportId { get; set; }
public String UserSportName { get; set; }
public String UserRegionId { get; set; }
public String UserRegionName { get; set; }
public String UserStatusCategoryCode { get; set; }
}
public FilterData Filter { get; } = new FilterData();
@@ -120,9 +120,15 @@
<data name="caption.contact.method" xml:space="preserve">
<value>Contact Method</value>
</data>
<data name="caption.image.upload" xml:space="preserve">
<value>Image Upload</value>
</data>
<data name="caption.organisation.address" xml:space="preserve">
<value>Organisation Address</value>
</data>
<data name="caption.organisation.images" xml:space="preserve">
<value>Organisation Images</value>
</data>
<data name="company.name" xml:space="preserve">
<value>Sportierre</value>
</data>
@@ -177,6 +183,9 @@
<data name="label.admin" xml:space="preserve">
<value>Admin</value>
</data>
<data name="label.alternatively" xml:space="preserve">
<value>Alternatively</value>
</data>
<data name="label.any" xml:space="preserve">
<value>Any</value>
</data>
@@ -258,6 +267,9 @@
<data name="label.forgotten.password" xml:space="preserve">
<value>Forgotten password?</value>
</data>
<data name="label.image" xml:space="preserve">
<value>Image</value>
</data>
<data name="label.images" xml:space="preserve">
<value>Images</value>
</data>
@@ -291,6 +303,9 @@
<data name="label.location" xml:space="preserve">
<value>Location</value>
</data>
<data name="label.logo" xml:space="preserve">
<value>Logo</value>
</data>
<data name="label.logs" xml:space="preserve">
<value>Logs</value>
</data>
@@ -342,6 +357,9 @@
<data name="label.online.today" xml:space="preserve">
<value>Online today</value>
</data>
<data name="label.organisation" xml:space="preserve">
<value>Organisation</value>
</data>
<data name="label.page.info" xml:space="preserve">
<value>Page {0} of {1}</value>
</data>
@@ -441,6 +459,9 @@
<data name="label.update" xml:space="preserve">
<value>update</value>
</data>
<data name="label.upload" xml:space="preserve">
<value>Upload</value>
</data>
<data name="label.user.roles" xml:space="preserve">
<value>User roles</value>
</data>
@@ -462,6 +483,9 @@
<data name="msg.data.refreshing" xml:space="preserve">
<value>Refreshing data. Please wait ...</value>
</data>
<data name="msg.drag.image.here" xml:space="preserve">
<value>Drag image here</value>
</data>
<data name="msg.error.data.incomplete" xml:space="preserve">
<value>Data is incomplete</value>
</data>
@@ -489,6 +513,33 @@
<data name="msg.something.gone.wrong" xml:space="preserve">
<value>Unfortunately, something has gone wrong.\n\nYou will be returned to the home page.</value>
</data>
<data name="msg.upload.file.select" xml:space="preserve">
<value>Please select a file to upload.</value>
</data>
<data name="msg.upload.file.size.max" xml:space="preserve">
<value>Maximum image file size is {0}.</value>
</data>
<data name="msg.upload.file.type.invalid" xml:space="preserve">
<value>Unsupported file type: {0}.</value>
</data>
<data name="msg.upload.file.uploading" xml:space="preserve">
<value>Uploading {0}.</value>
</data>
<data name="msg.upload.image.invalid" xml:space="preserve">
<value>Invalid image file uploaded</value>
</data>
<data name="msg.upload.image.invalid.content.type" xml:space="preserve">
<value>Invalid image content type.</value>
</data>
<data name="msg.upload.image.invalid.mime" xml:space="preserve">
<value>Invalid image mime type.</value>
</data>
<data name="msg.upload.image.resize.failed" xml:space="preserve">
<value>Image resize failed.</value>
</data>
<data name="msg.upload.image.single" xml:space="preserve">
<value>Only one image can be uploaded.</value>
</data>
<data name="msg.validation.duplicate.value" xml:space="preserve">
<value>Value is already in use</value>
</data>
@@ -38,7 +38,7 @@
</div>
<div class="col-sm">
<div class="sax-control">
<input type="text" name="ContactValue" class="ContactValue sax-input" />
<input type="text" name="ContactValue" class="ContactValue sax-input" maxlength="200" />
</div>
<div class="sax-message"></div>
</div>
@@ -97,3 +97,22 @@
</div>
</div>
</div>
@* Address country *@
<div class="sax-form-control AddressRegionIdCountry">
<div class="row">
<div class="col-sm-3">
<div class="sax-label">
<label><span>@Localiser["label.country"]</span>&nbsp;<span class="required">*</span></label>
</div>
</div>
<div class="col-sm">
<div class="sax-control row">
<input type="hidden" name="Address.RegionIdCountry" class="AddressRegionIdCountry" />
<div class="col"><input type="text" class="AddressRegionNameCountry sax-input" readonly="readonly" /> </div>
<div class="fixed"><button class="sax-button AddressRegionCountrySelect" style="min-width:auto;margin-left:4px;padding:4px 6px">@Localiser["label.select"]</button></div>
</div>
<div class="sax-message"></div>
</div>
</div>
</div>
@@ -49,7 +49,7 @@
<div class="col">
@* List of existing contact methods with actions to edit/remove. *@
<div class="ContactMethods">
<table class="sax-data"></table>
<table class="sax-data fullwidth"></table>
</div>
<table class="sax-panel-item-template">
<tr class="ContactMethod">
@@ -67,7 +67,7 @@
<div class="col-sm-7">
<div class="row">
@Html.HiddenFor(model => model.Filter.OrganisationSportId, new { @id = "", @class = "FilterOrganisationSportId" })
<div class="col"><input type="text" class="FilterOrganisationSportCaption sax-input" readonly="readonly" /> </div>
<div class="col"><input type="text" class="FilterOrganisationSportCaption sax-input" readonly="readonly" value="@Model.Filter.OrganisationSportName" /> </div>
<div class="fixed row">
<div class="sax-action FilterSportSelect"><img src="~/img/action/search24.png" alt="@(Localiser["label.search"])" title="@(Localiser["label.search"])" /></div>
<div class="sax-action FilterSportClear"><img src="~/img/action/delete24.png" alt="@(Localiser["label.clear"])" title="@(Localiser["label.clear"])" /></div>
@@ -81,7 +81,7 @@
<div class="col-sm-7">
<div class="row">
@Html.HiddenFor(model => model.Filter.OrganisationRegionId, new { @id = "", @class = "FilterOrganisationRegionId" })
<div class="col"><input type="text" class="FilterOrganisationRegionCaption sax-input" readonly="readonly" /> </div>
<div class="col"><input type="text" class="FilterOrganisationRegionCaption sax-input" readonly="readonly" value="@Model.Filter.OrganisationRegionName" /> </div>
<div class="fixed row">
<div class="sax-action FilterRegionSelect"><img src="~/img/action/search24.png" alt="@(Localiser["label.search"])" title="@(Localiser["label.search"])" /></div>
<div class="sax-action FilterRegionClear"><img src="~/img/action/delete24.png" alt="@(Localiser["label.clear"])" title="@(Localiser["label.clear"])" /></div>
@@ -144,12 +144,19 @@
</div>
<div class="sax-content">
<div class="row">
<div class="col-6 col-sm-4"><div class="OrganisationCategory"></div></div>
<div class="col-6 col-sm-4"><div class="OrganisationType"></div></div>
<div class="col-6 col-sm-4 text-left text-sm-right"><div class="OrganisationRegion"></div></div>
<div class="col-6 col-sm-4"><div class="OrganisationSport"></div></div>
<div class="col-6 col-sm-4"><div class="OrganisationMemberCount sax-action-text">@Localiser["label.members"]:&nbsp;<span class="MemberCount"></span></div></div>
<div class="col-6 col-sm-4 text-left text-sm-right"><div class="StatusDesc"></div></div>
<div class="fixed">
<img alt="" title="" class="OrganisationLogo" style="display:none;max-width:@(Sax.Config.Organisation.Logo.DisplayWidthMax_List + "px");max-height:@(Sax.Config.Organisation.Logo.DisplayHeightMax_List + "px");margin-right:8px;border:1px solid #c0c0c0;border-radius:2px;" />
</div>
<div class="col">
<div class="row">
<div class="col-6 col-sm-4"><div class="OrganisationCategory"></div></div>
<div class="col-6 col-sm-4"><div class="OrganisationType"></div></div>
<div class="col-6 col-sm-4 text-left text-sm-right"><div class="OrganisationRegion"></div></div>
<div class="col-6 col-sm-4"><div class="OrganisationSport"></div></div>
<div class="col-6 col-sm-4"><div class="OrganisationMemberCount sax-action-text">@Localiser["label.members"]:&nbsp;<span class="MemberCount"></span></div></div>
<div class="col-6 col-sm-4 text-left text-sm-right"><div class="StatusDesc sax-note"></div></div>
</div>
</div>
</div>
</div>
</div>
@@ -162,9 +169,19 @@
</div>
</div>
@* Organisation Id form - used in Ajax calls to identify organisation. *@
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmOrganisationId", @class = "sax-form" }))
{
@Html.HiddenFor(model => model.OrganisationId, new { @class = "OrganisationId" })
}
@* Organisation dialog and form. *@
<partial name="Panel-OrganisationDialog.cshtml" />
@* Organisation Activation dialog and form. *@
<partial name="Panel-ActivationDialog.cshtml" />
@* Organisation Address dialog, form and script. *@
<partial name="Panel-OrganisationAddressDialog.cshtml" />
@* Organisation Images dialog, form and script. *@
<partial name="Panel-OrganisationImagesDialog.cshtml" />
@* Select Item dialog and script. *@
<partial name="~/Views/Common/SelectItem.cshtml" />
</div>
<partial name="Panel-OrganisationDialog.cshtml" />
<partial name="Panel-OrganisationAddressDialog.cshtml" />
<partial name="~/Views/Common/SelectItem.cshtml" />
<partial name="Panel-ActivationDialog.cshtml" />
@@ -4,6 +4,8 @@
/* Organisations - Organisation Address dialog panel */
}
<script src="~/js/sax-org-add.js?@Model.HrefVersion"></script>
<div id="dlgOrganisationAddress" class="sax-dialog" title="@Localiser["caption.organisation.address"]">
<div class="spacer"></div>
@@ -16,18 +18,19 @@
<div class="row">
<div class="col-sm-3">
<div class="sax-label">
<label for="ifOrganisationName"><span>@Localiser["label.name"]</span>&nbsp;<span class="required">*</span></label>
<label for="ifOrganisationName"><span>@Localiser["label.organisation"]</span></label>
</div>
</div>
<div class="col-sm">
<div class="sax-control">
@Html.TextBoxFor(model => model.OrganisationName, new { @id = "ifOrganisationName", @class = "OrganisationName sax-input", @maxlength = @Model.GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.Organisation_Name), disabled = true })
<input type="text" id="ifOrganisationName" class="OrganisationName sax-input" maxlength="@Model.GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.Organisation_Name)" disabled="disabled" />
</div>
<div class="sax-message"></div>
</div>
</div>
</div>
@* Address controls *@
<partial name="~/Views/Common/Controls-ItemAddress.cshtml" />
}
@@ -10,10 +10,6 @@
sax.dlg.title.selectRegion = '@Localiser.GetJavascriptText("label.select.country")';
sax.dlg.title.selectSport = '@Localiser.GetJavascriptText("sport.caption.sport.select")';
</script>
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmOrganisationId", @class = "sax-form" }))
{
@Html.HiddenFor(model => model.OrganisationId, new { @class = "OrganisationId" })
}
<div id="dlgOrganisation" class="sax-dialog" title="">
<div class="spacer"></div>
@@ -94,19 +90,19 @@
</div>
</div>
@* Organisation country *@
<div class="sax-form-control OrganisationRegionIdCountry">
@* Organisation primary region *@
<div class="sax-form-control OrganisationRegionIdPrimary">
<div class="row">
<div class="col-sm-3">
<div class="sax-label">
<label for="ifOrganisationRegionCaptionCountry"><span>@Localiser["label.country"]</span>&nbsp;<span class="required">*</span></label>
<label for="ifOrganisationRegionNameCountry"><span>@Localiser["label.region"]</span>&nbsp;<span class="required">*</span></label>
</div>
</div>
<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" /> </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>
@Html.HiddenFor(model => model.OrganisationRegionIdPrimary, new { @id = "ifOrganisationRegionIdPrimary", @class = "OrganisationRegionIdPrimary" })
<div class="col"><input type="text" id="ifOrganisationRegionNamePrimary" class="OrganisationRegionNamePrimary sax-input" readonly="readonly" /> </div>
<div class="fixed"><button id="pbSelectOrganisationRegionPrimary" 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>
@@ -0,0 +1,125 @@
@model Model_Organisation
@inject SaxLocaliser Localiser
@{
/* Organisations - Organisation images dialog panel */
}
<style>
#dlgOrganisationImages .sax-panel-drop.OrganisationLogoImageDrop
{
padding: 4px 8px;
border: 1px solid #808080;
border-radius: 4px;
}
#dlgOrganisationImages .sax-panel-drop.OrganisationLogoImageDrop img
{
display: none;
max-width:@(Sax.Config.Organisation.Logo.DisplayWidthMax_Item + "px");
max-height:@(Sax.Config.Organisation.Logo.DisplayHeightMax_Item + "px");
margin-right: 8px;
border: 1px solid #b0b0b080;
border-radius: 4px;
}
#dlgOrganisationImages .sax-panel-drop.OrganisationLogoImageDrop *
{
/*pointer-events: none;*/
}
#dlgOrganisationImages .sax-panel-drop.OrganisationLogoImageDrop.sax-file-drag
{
background-color:#c0fff0;
border-color: darkgreen;
}
</style>
<script src="~/js/sax-org-img.js?@Model.HrefVersion"></script>
<script type="text/javascript">
sax.msg.uploadImageSingle = '@Localiser.GetJavascriptText("msg.upload.image.single")';
sax.msg.uploadFileSizeMax = '@Localiser.GetJavascriptText("msg.upload.file.size.max","{0}")';
sax.msg.uploadFileTypeInvalid = '@Localiser.GetJavascriptText("msg.upload.file.type.invalid","{0}")';
sax.msg.uploadingFile = '@Localiser.GetJavascriptText("msg.upload.file.uploading","{0}")';
sax.dlg.title.imageUpload = '@Localiser.GetJavascriptText("caption.image.upload")';
sax.msg.uploadFileSelect = '@Localiser.GetJavascriptText("msg.upload.file.select")';
</script>
<div id="dlgOrganisationImages" class="sax-dialog" title="@Localiser["caption.organisation.images"]">
<div class="spacer"></div>
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmOrganisationImages", @class = "sax-form", @onSubmit = "return false;" }))
{
@Html.HiddenFor(model => model.OrganisationId, new { @id = "", @class = "OrganisationId" })
@* Organisation name *@
<div class="sax-form-control OrganisationName">
<div class="row">
<div class="col-sm-3">
<div class="sax-label">
<label for="ifOrganisationName"><span>@Localiser["label.organisation"]</span></label>
</div>
</div>
<div class="col-sm">
<div class="sax-control">
<input type="text" id="ifOrganisationName" class="OrganisationName sax-input" maxlength="@Model.GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.Organisation_Name)" disabled="disabled" />
</div>
<div class="sax-message"></div>
</div>
</div>
</div>
@* Organisation Logo *@
<div class="sax-form-control OrganisationLogoImage">
<div class="row">
<div class="col-sm-3">
<div class="sax-label">
<label><span>@Localiser["label.logo"]</span></label>
</div>
</div>
<div class="col-sm">
<div class="sax-control">
<div class="OrganisationLogoImageDrop sax-panel-drop row">
<div class="fixed">
<div class=""><img src="" class="sax-contact-image OrganisationLogo" alt="" title="" /></div>
</div>
<div class="col">
@Localiser["msg.drag.image.here"]
<div class="DropMessage"></div>
<div class="UploadMessage"></div>
<div class="spacer4"></div>
@Localiser["label.alternatively"]:&nbsp;
<button class="SelectOrgLogoImage sax-button" style="min-width:auto;margin-left:4px;padding:4px 6px;z-index:999;">@Localiser["label.upload"]</button>
</div>
<div class="fixed">
<img id="" class="ImageUploadProgress" src="~/img/animated/progress-basketball-32.gif" style="display:none;margin:8px 4px;" />
</div>
</div>
</div>
<div class="sax-message"></div>
</div>
</div>
</div>
}
<div class="spacer"></div>
</div>
<div id="dlgSelectOrgLogoImage" class="sax-dialog" title="@Localiser.GetJavascriptText("caption.image.upload")">
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmSelectOrgLogoImage", @class = "sax-form", @onSubmit = "return false;" }))
{
<div class="spacer4"></div>
<div class="sax-form-control AccountOrgLogoImage">
<div class="row">
<div class="fixed"><div style="padding:0 12px;">@Localiser["label.image"]</div></div>
<div class="col"><input type="file" name="" class="OrganisationLogoImage fullwidth" style="" /></div>
</div>
<div class="sax-message"></div>
</div>
<div class="spacer2"></div>
<div class="row">
<div class="col"><div class="UploadMessage"></div></div>
<div class="fixed"><img id="" class="ImageUploadProgress" src="~/img/animated/progress-basketball-32.gif" style="display:none;margin:8px 4px;" /></div>
</div>
<div class="spacer2"></div>
}
</div>
+2 -2
View File
@@ -55,7 +55,7 @@
<div class="col-sm-7">
<div class="row">
@Html.HiddenFor(model => model.Filter.UserSportId, new { @id = "", @class = "FilterUserSportId" })
<div class="col"><input type="text" class="FilterUserSportCaption sax-input" readonly="readonly" ondblclick="sax.selectFilterSport()" /> </div>
<div class="col"><input type="text" class="FilterUserSportCaption sax-input" readonly="readonly" ondblclick="sax.selectFilterSport()" value="@Model.Filter.UserSportName" /> </div>
<div class="fixed row">
<div class="sax-action" onclick="sax.selectFilterSport();"><img src="~/img/action/search24.png" alt="@(Localiser["label.search"])" title="@(Localiser["label.search"])" /></div>
<div class="sax-action" onclick="sax.clearFilterSport();"><img src="~/img/action/delete24.png" alt="@(Localiser["label.clear"])" title="@(Localiser["label.clear"])" /></div>
@@ -69,7 +69,7 @@
<div class="col-sm-7">
<div class="row">
@Html.HiddenFor(model => model.Filter.UserRegionId, new { @id = "", @class = "FilterUserRegionId" })
<div class="col"><input type="text" class="FilterUserRegionCaption sax-input" readonly="readonly" ondblclick="sax.selectFilterRegion()" /> </div>
<div class="col"><input type="text" class="FilterUserRegionCaption sax-input" readonly="readonly" ondblclick="sax.selectFilterRegion()" value="@Model.Filter.UserRegionName" /> </div>
<div class="fixed row">
<div class="sax-action" onclick="sax.selectFilterRegion();"><img src="~/img/action/search24.png" alt="@(Localiser["label.search"])" title="@(Localiser["label.search"])" /></div>
<div class="sax-action" onclick="sax.clearFilterRegion();"><img src="~/img/action/delete24.png" alt="@(Localiser["label.clear"])" title="@(Localiser["label.clear"])" /></div>
@@ -36,6 +36,11 @@
font-weight: bold;
}
.sax-panel-filter .sax-header ul.nav.sax-burger
{
margin-top: 2px;
}
.sax-panel-filter .sax-header .sax-action
{
margin: 2px 0 0 8px;
@@ -50,8 +55,8 @@
.sax-panel-filter .sax-content
{
margin: 4px 8px;
padding: 4px 8px;
margin: 4px 4px;
padding: 4px 4px;
background-color: #f8f8f8;
}
@@ -67,6 +72,7 @@
{
min-width: 75%;
max-width: 90%;
width:90%;
}
.sax-panel-filter .sax-content .sax-button
@@ -80,7 +86,7 @@
.sax-results-paging
{
margin-right: 8px;
margin-right: 12px;
}
.sax-results-paging .sax-paging-info
Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

@@ -67,6 +67,11 @@
{
return (val || '').replace(/[[{}()*+?^$|\]\.\\]/g, "\\$&");
}
sax.haltEvent = function (evt)
{
evt.preventDefault();
evt.stopPropagation();
}
sax.debug = sax.debugMode ? win.console.log.bind(win.console) : function () { };
//--------------------------------------------------------------
@@ -0,0 +1,111 @@
/*
* Admin - Organisation Address scripts.
*/
(function (win, doc, undef)
{
"use strict";
let oa = sax.mdl.organisationAddress = { data: {}, ajax: {} };
let $pnl = oa.$pnl = {}, $frm = oa.$frm = {}, $dlg = oa.$dlg = {};
let mdlOrg = function () { return sax.mdl.organisations; }
//--------------------------------------------------------------
oa.updateItemAddress = function (item, $item)
{
oa.init();
$('.OrganisationId', $frm.orgId).val(item.id);
oa.ajax.updateItemAddr = oa.ajax.updateItemAddr || { url: sax.url.base + 'Organisation/Ajax/GetItem', formId: 'frmOrganisationId', callbackFn: oa.onUpdateItemAddress };
sax.doAjaxRequest(oa.ajax.updateItemAddr, 50);
}
oa.onUpdateItemAddress = function (response)
{
//sax.debug('onUpdateItemAddress', response);
if (!response.success) return;
// Address.
let item = response.organisation;
let addr = item.address || {};
let frm = $frm.orgAddr;
$('input.OrganisationId', frm).val(item.id);
$('.OrganisationName', frm).val(item.name);
$('input.AddressId', frm).val(addr.id);
$('input.AddressLine1', frm).val(addr.line1);
$('input.AddressLine2', frm).val(addr.line2);
$('input.AddressLine3', frm).val(addr.line3);
$('input.AddressTown', frm).val(addr.town);
$('input.AddressRegionIdProvince', frm).val(addr.regionIdProvince);
$('input.AddressProvince', frm).val(addr.regionNameProvince);
$('input.AddressPostalCode', frm).val(addr.postalCode);
$('input.AddressRegionIdCountry, input.AddressRegionNameCountry', frm).val('');
if (addr.regionIdCountry)
{
$('input.AddressRegionIdCountry', frm).val(addr.regionIdCountry);
$('input.AddressRegionNameCountry', frm).val(addr.regionNameCountry);
}
else if (item.regionPrimary.country)
{
$('input.AddressRegionIdCountry', frm).val(item.regionPrimary.id);
$('input.AddressRegionNameCountry', frm).val(item.regionPrimary.name);
}
sax.clearControlErrors(frm);
sax.openDialog($dlg.orgAddr, 640, 480);
}
//--------------------------------------------------------------
oa.selectOrgAddrRegionCountry = function ()
{
if (!mdlOrg().data.regions)
mdlOrg().populateRegions(oa.showSelectOrgAddrRegionCountry);
else oa.showSelectOrgAddrRegionCountry();
}
oa.showSelectOrgAddrRegionCountry = function ()
{
let regions = [];
for (let rgn of mdlOrg().data.regions)
if (rgn.regionType == 30) regions.push(rgn);
sax.data.selectItem.fn.selectItem({ caption: sax.dlg.title.selectCountry, itemId: $('input.AddressRegionIdCountry', $frm.orgAddr).val(), items: regions, fnCallback: oa.onOrgAddrRegionCountrySelected });
}
oa.onOrgAddrRegionCountrySelected = function (rgn)
{
//sax.debug('onRegionSelected', rgn);
let frm = $frm.orgAddr;
sax.clearControlError($('input.AddressRegionIdCountry', frm).val(rgn.id));
$('.AddressRegionNameCountry', frm).val(rgn.name);
}
//--------------------------------------------------------------
oa.storeItemAddress = function ()
{
oa.ajax.storeItemAddr = oa.ajax.storeItemAddr || { url: sax.url.base + 'Organisation/Ajax/StoreItem', formId: 'frmOrganisationAddress', callbackFn: oa.onStoreItemAddress };
sax.doAjaxRequest(oa.ajax.storeItemAddr, 50);
}
oa.onStoreItemAddress = function (response)
{
//sax.debug('onStoreItemAddress', response);
sax.refreshControlValues(response.controlValues, $frm.orgAddr);
if (!response.success) return;
$dlg.orgAddr.dialog('close');
mdlOrg().refreshItem(response.organisation);
}
//--------------------------------------------------------------
oa.init = function ()
{
if ($frm.orgId) return;
$frm.orgId = $('#frmOrganisationId');
// Organisation Address dialog.
var opt = sax.dlgOpts();
opt.buttons[sax.dlg.btn.ok] = function () { oa.storeItemAddress(); };
opt.buttons[sax.dlg.btn.cancel] = function () { $(this).dialog('close'); };
$dlg.orgAddr = $('#dlgOrganisationAddress').dialog(opt);
// Organisation Address form.
$frm.orgAddr = $('#frmOrganisationAddress');
$frm.orgAddr.on('input', '.sax-input, .sax-textarea', function () { sax.clearControlError(this); }).on('change', '.sax-select', function () { sax.clearControlError(this); });
$frm.orgAddr.on('dblclick', '.AddressRegionNameCountry', oa.selectOrgAddrRegionCountry).on('click', '.AddressRegionCountrySelect', oa.selectOrgAddrRegionCountry);
}
//--------------------------------------------------------------
}(window, window.document));
/* The End */
@@ -0,0 +1,143 @@
/*
* Admin - Organisation Images scripts.
*/
(function (win, doc, undef)
{
"use strict";
let oi = sax.mdl.organisationImages = { data: {}, ajax: {} };
let $pnl = oi.$pnl = {}, $frm = oi.$frm = {}, $dlg = oi.$dlg = {};
oi.classFileDrag = 'sax-file-drag';
let mdlOrg = function () { return sax.mdl.organisations; }
//--------------------------------------------------------------
oi.updateItemImages = function (item, $item)
{
oi.init();
$('.OrganisationId', $frm.orgId).val(item.id);
oi.ajax.getOrgImages = oi.ajax.getOrgImages || { url: sax.url.base + 'Organisation/Ajax/GetImages', formId: 'frmOrganisationId', callbackFn: oi.onUpdateItemImages };
sax.doAjaxRequest(oi.ajax.getOrgImages, 50);
}
oi.onUpdateItemImages = function (response)
{
//sax.debug('onUpdateItemImages', response);
if (!response.success) return;
oi.data.imageContentTypes = response.imageContentTypes;
let item = response.organisation;
let frm = $frm.orgImg;
$('.OrganisationId', frm).val(item.id);
$('.OrganisationName', frm).val(item.name);
$('img.OrganisationLogo', frm).prop('src', item.logoImageUrl).toggle(!!item.logoImageUrl);
sax.clearControlErrors(frm);
sax.openDialog($dlg.orgImg, 640, 480);
}
//--------------------------------------------------------------
// Drop organisation logo image.
oi.onDropOrgLogoImage = function (evt)
{
//sax.debug('onDropOrgLogoImage', evt);
let files = evt.originalEvent.dataTransfer.files;
if (files.length < 1) return;
if (files.length > 1) return sax.doAlert(sax.dlg.title.imageUpload, sax.msg.uploadImageSingle);
oi.onDropOrgLogoImageFile(files[0], $frm.orgImg);
}
oi.onDropOrgLogoImageFile = function (file, context)
{
//sax.debug('onDropOrgLogoImageFile', file, context);
if (file.size > sax.maxProfileImageSize) return sax.doAlert(sax.dlg.title.imageUpload, sax.msg.uploadFileSizeMax.format(sax.formatFileSize(sax.maxProfileImageSize)));
if ((oi.data.imageContentTypes || []).indexOf(file.type) < 0) return sax.doAlert(sax.dlg.title.imageUpload, sax.msg.uploadFileTypeInvalid.format(sax.getFileType(file)));
$(".UploadMessage", context).text(sax.msg.uploadingFile.format(file.name));
$('img.ImageUploadProgress', context).fadeIn(200);
sax.clearControlError($pnl.orgLogoImageDrag);
oi.data.orgLogoImageUploadContext = context;
oi.ajax.uploadOrgLogoImage = sax.ajax.uploadOrgLogoImage || { url: sax.url.base + 'Organisation/Ajax/UploadLogoImage', callbackFn: oi.handleOrgLogoImageUploadResponse, noWaitIcon: true };
let ajaxData = oi.ajax.uploadOrgLogoImage.formData = new FormData();
ajaxData.append("__RequestVerificationToken", $('#frmNavigate input[name="__RequestVerificationToken"]').val());
ajaxData.append("OrganisationId", $('.OrganisationId', $frm.orgImg).val());
ajaxData.append("OrganisationLogoImage", file);
sax.doAjaxRequest(oi.ajax.uploadOrgLogoImage, 50);
}
oi.handleOrgLogoImageUploadResponse = function (response)
{
//sax.debug('handleOrgLogoImageUploadResponse', response, context);
let context = oi.data.orgLogoImageUploadContext;
if (!response) return;
sax.refreshControlValues(response.controlValues, context);
$(".UploadMessage", context).empty();
$('img.ImageUploadProgress', context).hide();
if (response.success)
{
$dlg.selectOrgLogoImage.dialog('close');
$('img.OrganisationLogo', $pnl.orgLogo).prop('src', response.imageUrl).show();
}
}
//--------------------------------------------------------------
// Select organisation logo image.
oi.selectOrgLogoImage = function ()
{
let dlg = $dlg.selectOrgLogoImage;
$('.OrganisationLogoImage', dlg).val('');
sax.openDialog(dlg, 560, 240);
}
oi.uploadOrgLogoImage = function ()
{
let dlg = $dlg.selectOrgLogoImage;
let $fileCtrl = $('.OrganisationLogoImage', dlg);
if (!$fileCtrl.length || !$fileCtrl[0].files.length)
return sax.doAlert(sax.dlg.title.imageUpload, sax.msg.uploadFileSelect);
let file = $fileCtrl[0].files[0];
oi.onDropOrgLogoImageFile(file, dlg);
}
//--------------------------------------------------------------
oi.storeItemImages = function ()
{
oi.ajax.storeOrgImages = oi.ajax.storeOrgImages || { url: sax.url.base + 'Organisation/Ajax/StoreImages', formId: 'frmOrganisationImages', callbackFn: oi.onStoreItemImages };
sax.doAjaxRequest(oi.ajax.storeOrgImages, 50);
}
oi.onStoreItemImages = function (response)
{
//sax.debug('onStoreItemImages', response);
sax.refreshControlValues(response.controlValues, $frm.orgImg);
if (!response.success) return;
$dlg.orgImg.dialog('close');
mdlOrg().refreshItem(response.organisation);
}
//--------------------------------------------------------------
oi.init = function ()
{
if ($frm.orgId) return;
$frm.orgId = $('#frmOrganisationId');
// Organisation Images dialog and form.
var opt = sax.dlgOpts();
opt.buttons[sax.dlg.btn.ok] = function () { oi.storeItemImages(); };
opt.buttons[sax.dlg.btn.cancel] = function () { $(this).dialog('close'); };
$dlg.orgImg = $('#dlgOrganisationImages').dialog(opt);
$frm.orgImg = $('#frmOrganisationImages', $dlg.orgImg);
// Organisation logo.
$pnl.orgLogo = $('.sax-form-control.OrganisationLogoImage', $dlg.orgImg);
$pnl.orgLogoImgDrop = $('.sax-panel-drop.OrganisationLogoImageDrop', $pnl.orgLogo)
.on('dragenter', function (evt) { sax.haltEvent(evt); })
.on('dragover', function (evt) { sax.haltEvent(evt); if (!$pnl.orgLogoImgDrop.hasClass(oi.classFileDrag)) $pnl.orgLogoImgDrop.addClass(oi.classFileDrag); })
.on('dragleave', function (evt) { sax.haltEvent(evt); $pnl.orgLogoImgDrop.removeClass(oi.classFileDrag); })
.on('drop', function (evt) { sax.haltEvent(evt); $pnl.orgLogoImgDrop.removeClass(oi.classFileDrag); oi.onDropOrgLogoImage(evt); })
.on('click', '.sax-button.SelectOrgLogoImage', oi.selectOrgLogoImage);
// Select image dialog.
var opt = sax.dlgOpts();
opt.buttons[sax.dlg.btn.ok] = function () { oi.uploadOrgLogoImage(); };
opt.buttons[sax.dlg.btn.cancel] = function () { $(this).dialog('close'); };
$dlg.selectOrgLogoImage = $('#dlgSelectOrgLogoImage').dialog(opt);
}
//--------------------------------------------------------------
}(window, window.document));
/* The End */
+22 -64
View File
@@ -5,9 +5,8 @@
(function (win, doc, undef)
{
"use strict";
let op = sax.mdl.organisations = sax.mdl.organisations || { data: {}, ajax: {} };
let op = sax.mdl.organisations = { data: {}, ajax: {} };
let $pnl = op.$pnl = {}, $frm = op.$frm = {}, $dlg = op.$dlg = {};
sax.itemIdPrefix = 'Itm_';
//--------------------------------------------------------------
op.refreshResults = function (delay)
@@ -47,15 +46,21 @@
$items.append(op.populateItem(op.getItemTemplate(), items[itemIdx]));
$items.fadeIn(50);
}
op.getItemIdProp = function (id)
{
return 'Org_' + id;
}
op.populateItem = function ($item, item)
{
//sax.debug('populateItem', item);
if (!item) return;
$item.prop('id', sax.itemIdPrefix + item.id);
$item.prop('id', op.getItemIdProp(item.id));
$('img.OrganisationLogo', $item).prop('src', item.logoImageUrl).toggle(!!item.logoImageUrl);
$('.OrganisationName', $item).text(item.name);
$('.OrganisationType', $item).text(item.typeDesc);
$('.OrganisationCategory', $item).text(item.categoryDesc);
$('.OrganisationSport', $item).text(item.sportName);
$('.OrganisationRegion', $item).text(item.regionNameCountry);
$('.OrganisationRegion', $item).text(item.regionPrimary.name);
$('.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);
@@ -224,15 +229,15 @@
}
op.showSelectOrgRegion = function ()
{
sax.data.selectItem.fn.selectItem({ caption: sax.dlg.title.selectRegion, itemId: $('.OrganisationRegionIdCountry', $frm.org).val(), items: op.data.regions, fnCallback: op.onOrgRegionSelected });
sax.data.selectItem.fn.selectItem({ caption: sax.dlg.title.selectRegion, itemId: $('.OrganisationRegionIdPrimary', $frm.org).val(), items: op.data.regions, fnCallback: op.onOrgRegionSelected });
}
op.onOrgRegionSelected = function (rgn)
{
//sax.debug('onRegionSelected', rgn);
let frm = $frm.org;
$('.OrganisationRegionIdCountry', frm).val(rgn.id);
$('.OrganisationRegionCaptionCountry', frm).val(rgn.name);
sax.clearControlError($('.OrganisationRegionCaptionCountry', frm));
$('.OrganisationRegionIdPrimary', frm).val(rgn.id);
$('.OrganisationRegionNamePrimary', frm).val(rgn.name);
sax.clearControlError($('.OrganisationRegionIdPrimary', frm));
}
//--------------------------------------------------------------
@@ -251,7 +256,7 @@
op.clearItem = function ()
{
let frm = $frm.org;
$('.OrganisationId,.OrganisationSportId,.OrganisationRegionIdCountry,input[type="text"],textarea,select', frm).val('');
$('.OrganisationId,.OrganisationSportId,.OrganisationRegionIdPrimary,input[type="text"],textarea,select', frm).val('');
$pnl.tblconMths.empty();
$('.OrganisationStatus', frm).val(op.data.defaultStatusCode);
sax.clearControlErrors();
@@ -285,8 +290,8 @@
$('.OrganisationCategory', frm).val(item.categoryCode);
$('.OrganisationSportId', frm).val(item.sportId);
$('.OrganisationSportCaption', frm).val(item.sportName);
$('.OrganisationRegionIdCountry', frm).val(item.regionIdCountry);
$('.OrganisationRegionCaptionCountry', frm).val(item.regionNameCountry);
$('.OrganisationRegionIdPrimary', frm).val(item.regionPrimary.id);
$('.OrganisationRegionNamePrimary', frm).val(item.regionPrimary.name);
$('.OrganisationAbout', frm).val(item.about);
$('.OrganisationFacilities', frm).val(item.facilities);
$('.OrganisationNotes', frm).val(item.notes);
@@ -374,7 +379,7 @@
}
op.refreshItem = function (item)
{
var $item = $('#' + sax.itemIdPrefix + item.id);
var $item = $('#' + op.getItemIdProp(item.id));
if (!$item.length)
{
$item = op.getItemTemplate();
@@ -404,7 +409,7 @@
}
popItemValue('.OrganisationName', item.name);
popItemValue('.OrganisationSport', item.sportName);
popItemValue('.OrganisationRegion', item.regionNameCountry);
popItemValue('.OrganisationRegion', item.regionPrimary.name);
popItemValue('.OrganisationCategory', item.categoryDesc);
popItemValue('.OrganisationAddress', item.addressSummary);
let $orgMbrs = $('.OrganisationMembers', $dlg.activate).empty();
@@ -440,51 +445,12 @@
//--------------------------------------------------------------
op.updateItemImages = function (item, $item)
{
sax.debug('updateItemImages');
sax.mdl.organisationImages.updateItemImages(item, $item)
}
//--------------------------------------------------------------
op.updateItemAddress = function (item, $item)
{
sax.debug('updateItemAddress');
$('.OrganisationId', $frm.orgId).val(item.id);
op.ajax.updateItemAddr = op.ajax.updateItemAddr || { url: sax.url.base + 'Organisation/Ajax/GetItem', formId: 'frmOrganisationId', callbackFn: op.onUpdateItemAddress };
sax.doAjaxRequest(op.ajax.updateItemAddr, 50);
}
op.onUpdateItemAddress = function (response)
{
sax.debug('onUpdateItemAddress', response);
if (!response.success) return;
// Address.
let item = response.organisation;
let address = item.address || {};
let frm = $frm.orgAddr;
$('input.OrganisationId', frm).val(item.id);
$('.OrganisationName', frm).val(item.name);
$('input.AddressId', frm).val(address.id);
$('input.AddressLine1', frm).val(address.line1);
$('input.AddressLine2', frm).val(address.line2);
$('input.AddressLine3', frm).val(address.line3);
$('input.AddressTown', frm).val(address.town);
$('input.AddressProvince', frm).val(address.province);
$('input.AddressCountry', frm).val(address.country);
$('input.AddressPostalCode', frm).val(address.postalCode);
sax.clearControlErrors(frm);
sax.openDialog($dlg.orgAddr, 640, 480);
}
op.storeItemAddress = function ()
{
sax.debug('storeItemAddress');
op.ajax.storeItemAddr = op.ajax.storeItemAddr || { url: sax.url.base + 'Organisation/Ajax/StoreItem', formId: 'frmOrganisationAddress', callbackFn: op.onStoreItemAddress };
sax.doAjaxRequest(op.ajax.storeItemAddr, 50);
}
op.onStoreItemAddress = function (response)
{
sax.debug('onStoreItemAddress', response);
sax.refreshControlValues(response.controlValues, $frm.orgAddr);
if (!response.success) return;
$dlg.orgAddr.dialog('close');
op.refreshItem(response.organisation);
sax.mdl.organisationAddress.updateItemAddress(item, $item);
}
//--------------------------------------------------------------
@@ -512,7 +478,7 @@
$frm.org = $('#frmOrganisation');
$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);
$frm.org.on('dblclick', '.OrganisationRegionNamePrimary', op.selectOrgRegion).on('click', '#pbSelectOrganisationRegionPrimary', op.selectOrgRegion);
$frm.org.on('click', '.ItemContactMethods .sax-action.sax-add', op.addConMth);
$pnl.conMths = $('.ItemContactMethods', $frm.org);
$pnl.tblconMths = $('table.sax-data', $pnl.conMths);
@@ -523,18 +489,10 @@
opt.buttons[sax.dlg.btn.cancel] = function () { $(this).dialog('close'); };
$dlg.activate = $('#dlgOrganisationActivation').dialog(opt);
// Activate Organisation Address dialog and form.
var opt = sax.dlgOpts();
opt.buttons[sax.dlg.btn.ok] = function () { op.storeItemAddress(); };
opt.buttons[sax.dlg.btn.cancel] = function () { $(this).dialog('close'); };
$dlg.orgAddr = $('#dlgOrganisationAddress').dialog(opt);
$frm.orgAddr = $('#frmOrganisationAddress');
$frm.orgAddr.on('input', '.sax-input, .sax-textarea', function () { sax.clearControlError(this); }).on('change', '.sax-select', function () { sax.clearControlError(this); });
setTimeout(op.refreshResults, 250);
});
//--------------------------------------------------------------
}(window, window.document));
/* The End */