This commit is contained in:
2021-08-09 14:18:08 +01:00
parent 0d7be69e1e
commit 5e5ef7190b
84 changed files with 2449 additions and 1717 deletions
@@ -52,6 +52,8 @@ namespace Saxonite.Net.Core.Web.Base.Consoles
private class ActivityData_Web : IndexResults.ActivityData private class ActivityData_Web : IndexResults.ActivityData
{ {
public ActivityData_Web(ItemId itemId, DateTime effectiveOn) : base(itemId, effectiveOn) { } public ActivityData_Web(ItemId itemId, DateTime effectiveOn) : base(itemId, effectiveOn) { }
public void SetOrganisation(SysId organisationId, String organisation) { OrganisationId = organisationId; Organisation = organisation; }
public void SetAuthor(SysId userAccountId, String author) { UserAccountIdAuthor = userAccountId; Author = author; }
public void SetCaption(String caption) { Caption = caption; } public void SetCaption(String caption) { Caption = caption; }
public void SetBlurb(String blurb) { Blurb = blurb; } public void SetBlurb(String blurb) { Blurb = blurb; }
public void SetSport(SysId sportId, String sportName) { SportId = sportId; SportName = sportName; } public void SetSport(SysId sportId, String sportName) { SportId = sportId; SportName = sportName; }
@@ -134,7 +136,7 @@ namespace Saxonite.Net.Core.Web.Base.Consoles
private void PopulateActivityDetails(IndexContext context, List<ActivityData_Web> activities) private void PopulateActivityDetails(IndexContext context, List<ActivityData_Web> activities)
{ {
PopulateUserActivityDetails(context, activities); PopulateUserActivityDetails(context, activities);
PopulateJournalistArticleDetails(context, activities); PopulateArticleDetails(context, activities);
PopulateOrganisationOpportunitiesDetails(context, activities); PopulateOrganisationOpportunitiesDetails(context, activities);
} }
@@ -187,34 +189,42 @@ namespace Saxonite.Net.Core.Web.Base.Consoles
} }
//------------------------------------------------------------------- //-------------------------------------------------------------------
// Journalist Article details. // Article details.
private void PopulateJournalistArticleDetails(IndexContext context, List<ActivityData_Web> activities) private void PopulateArticleDetails(IndexContext context, List<ActivityData_Web> activities)
{ {
// Extract article Ids. // Extract article Ids.
List<SysId> articleIds = activities.FindAll(item => item.ItemId.Type == (int)Sax.DataItemType.JournalistArticle).Select(ItemId => ItemId.ItemId.Id).ToList(); List<SysId> articleIds = activities.FindAll(item => item.ItemId.Type == (int)Sax.DataItemType.Article).Select(ItemId => ItemId.ItemId.Id).ToList();
if (articleIds.IsEmpty()) return; if (articleIds.IsEmpty()) return;
// Article columns - limit to essential information. // Article columns - limit to essential information.
ColumnDfn colId = Internals.ActivityMgr.GetJournalistArticleColumnDfn(SaxJournalistArticle.Column.Id); ColumnDfn colId = Internals.ActivityMgr.GetArticleColumnDfn(SaxArticle.Column.Id);
ColumnDfn colHeadline = Internals.ActivityMgr.GetJournalistArticleColumnDfn(SaxJournalistArticle.Column.Headline); ColumnDfn colOrganisationId = Internals.ActivityMgr.GetArticleColumnDfn(SaxArticle.Column.OrganisationId);
ColumnDfn colSummary = Internals.ActivityMgr.GetJournalistArticleColumnDfn(SaxJournalistArticle.Column.Summary); ColumnDfn colOrganisation = Internals.ActivityMgr.GetArticleColumnDfn(SaxArticle.Column.Organisation_Name);
ColumnDfn colSportId = Internals.ActivityMgr.GetJournalistArticleColumnDfn(SaxJournalistArticle.Column.SportIdPrimary); ColumnDfn colAuthorId = Internals.ActivityMgr.GetArticleColumnDfn(SaxArticle.Column.UserAccountIdAuthor);
ColumnDfn colSportName = Internals.ActivityMgr.GetJournalistArticleColumnDfn(SaxJournalistArticle.Column.Sport_Name); ColumnDfn colAuthor = Internals.ActivityMgr.GetArticleColumnDfn(SaxArticle.Column.Author_DisplayName);
ColumnDfn colRegionId = Internals.ActivityMgr.GetJournalistArticleColumnDfn(SaxJournalistArticle.Column.RegionIdPrimary); ColumnDfn colHeadline = Internals.ActivityMgr.GetArticleColumnDfn(SaxArticle.Column.Headline);
ColumnDfn colRegionName = Internals.ActivityMgr.GetJournalistArticleColumnDfn(SaxJournalistArticle.Column.Region_Name); ColumnDfn colSummary = Internals.ActivityMgr.GetArticleColumnDfn(SaxArticle.Column.Summary);
List<ColumnDfn> columns = new List<ColumnDfn>() { colId, colHeadline, colSummary, colSportId, colSportName, colRegionId, colRegionName }; ColumnDfn colSportId = Internals.ActivityMgr.GetArticleColumnDfn(SaxArticle.Column.SportIdPrimary);
ColumnDfn colSportName = Internals.ActivityMgr.GetArticleColumnDfn(SaxArticle.Column.Sport_Name);
ColumnDfn colRegionId = Internals.ActivityMgr.GetArticleColumnDfn(SaxArticle.Column.RegionIdPrimary);
ColumnDfn colRegionName = Internals.ActivityMgr.GetArticleColumnDfn(SaxArticle.Column.Region_Name);
List<ColumnDfn> columns = new List<ColumnDfn>() { colId, colOrganisationId, colOrganisation, colAuthor, colAuthorId, colHeadline, colSummary, colSportId, colSportName, colRegionId, colRegionName };
// Article filter. // Article filter.
SaxJournalistArticle.Params prmArticle = new SaxJournalistArticle.Params(); SaxArticle.Params prmArticle = new SaxArticle.Params();
prmArticle.IdsIncluded.AddRange(articleIds); prmArticle.IdsIncluded.AddRange(articleIds);
prmArticle.StatusCat = SaxJournalistArticle.StatusCat.ActiveOnly; prmArticle.StatusCat = SaxArticle.StatusCat.ActiveOnly;
using (DbResultSet dbResultSet = Internals.ActivityMgr.ExecuteJournalistArticleQuery(columns, prmArticle)) using (DbResultSet dbResultSet = Internals.ActivityMgr.ExecuteArticleQuery(columns, prmArticle))
{ {
while (dbResultSet != null && dbResultSet.NextRecord()) while (dbResultSet != null && dbResultSet.NextRecord())
{ {
NamedValue.Map values = dbResultSet.GetRecordValues(); NamedValue.Map values = dbResultSet.GetRecordValues();
ItemId itemId = new ItemId((short)Sax.DataItemType.JournalistArticle, new SysId(values.GetLong(colId.DataName))); ItemId itemId = new ItemId((short)Sax.DataItemType.Article, new SysId(values.GetLong(colId.DataName)));
SysId organisationId = new SysId(values.GetLong(colOrganisationId.DataName));
String organisation = values.GetString(colOrganisation.DataName);
SysId authorId = new SysId(values.GetLong(colAuthorId.DataName));
String author = values.GetString(colAuthor.DataName);
String headline = values.GetString(colHeadline.DataName); String headline = values.GetString(colHeadline.DataName);
String summary = values.GetString(colSummary.DataName); String summary = values.GetString(colSummary.DataName);
SysId sportId = new SysId(values.GetLong(colSportId.DataName)); SysId sportId = new SysId(values.GetLong(colSportId.DataName));
@@ -225,6 +235,9 @@ namespace Saxonite.Net.Core.Web.Base.Consoles
// Populate to corresponding activities. // Populate to corresponding activities.
foreach (ActivityData_Web activity in activities.FindAll(item => item.ItemId.Equals(itemId))) foreach (ActivityData_Web activity in activities.FindAll(item => item.ItemId.Equals(itemId)))
{ {
activity.SetOrganisation(organisationId, organisation);
activity.SetAuthor(authorId, author);
activity.SetCaption(headline);
activity.SetCaption(headline); activity.SetCaption(headline);
activity.SetBlurb(summary); activity.SetBlurb(summary);
activity.SetSport(sportId, sportName); activity.SetSport(sportId, sportName);
@@ -244,6 +257,8 @@ namespace Saxonite.Net.Core.Web.Base.Consoles
// Opportunity columns - limit to essential information. // Opportunity columns - limit to essential information.
ColumnDfn colId = Internals.ActivityMgr.GetOrganisationOpportunityColumnDfn(SaxOrganisationOpportunity.Column.Id); ColumnDfn colId = Internals.ActivityMgr.GetOrganisationOpportunityColumnDfn(SaxOrganisationOpportunity.Column.Id);
ColumnDfn colOrganisationId = Internals.ActivityMgr.GetOrganisationOpportunityColumnDfn(SaxOrganisationOpportunity.Column.OrganisationId);
ColumnDfn colOrganisation= Internals.ActivityMgr.GetOrganisationOpportunityColumnDfn(SaxOrganisationOpportunity.Column.Organisation_Name);
ColumnDfn colPosition = Internals.ActivityMgr.GetOrganisationOpportunityColumnDfn(SaxOrganisationOpportunity.Column.Position); ColumnDfn colPosition = Internals.ActivityMgr.GetOrganisationOpportunityColumnDfn(SaxOrganisationOpportunity.Column.Position);
ColumnDfn colOutline = Internals.ActivityMgr.GetOrganisationOpportunityColumnDfn(SaxOrganisationOpportunity.Column.Outline); ColumnDfn colOutline = Internals.ActivityMgr.GetOrganisationOpportunityColumnDfn(SaxOrganisationOpportunity.Column.Outline);
ColumnDfn colSportId = Internals.ActivityMgr.GetOrganisationOpportunityColumnDfn(SaxOrganisationOpportunity.Column.SportIdPrimary); ColumnDfn colSportId = Internals.ActivityMgr.GetOrganisationOpportunityColumnDfn(SaxOrganisationOpportunity.Column.SportIdPrimary);
@@ -263,8 +278,10 @@ namespace Saxonite.Net.Core.Web.Base.Consoles
{ {
NamedValue.Map values = dbResultSet.GetRecordValues(); NamedValue.Map values = dbResultSet.GetRecordValues();
ItemId itemId = new ItemId((short)Sax.DataItemType.OrganisationOpportunity, new SysId(values.GetLong(colId.DataName))); ItemId itemId = new ItemId((short)Sax.DataItemType.OrganisationOpportunity, new SysId(values.GetLong(colId.DataName)));
String headline = values.GetString(colPosition.DataName); SysId organisationId = new SysId(values.GetLong(colOrganisationId.DataName));
String summary = values.GetString(colOutline.DataName); String organisation = values.GetString(colOrganisation.DataName);
String position = values.GetString(colPosition.DataName);
String outline = values.GetString(colOutline.DataName);
SysId sportId = new SysId(values.GetLong(colSportId.DataName)); SysId sportId = new SysId(values.GetLong(colSportId.DataName));
String sportName = values.GetString(colSportName.DataName); String sportName = values.GetString(colSportName.DataName);
SysId regionId = new SysId(values.GetLong(colRegionId.DataName)); SysId regionId = new SysId(values.GetLong(colRegionId.DataName));
@@ -273,8 +290,9 @@ namespace Saxonite.Net.Core.Web.Base.Consoles
// Populate to corresponding activities. // Populate to corresponding activities.
foreach (ActivityData_Web activity in activities.FindAll(item => item.ItemId.Equals(itemId))) foreach (ActivityData_Web activity in activities.FindAll(item => item.ItemId.Equals(itemId)))
{ {
activity.SetCaption(headline); activity.SetOrganisation(organisationId, organisation);
activity.SetBlurb(summary); activity.SetCaption(position);
activity.SetBlurb(outline);
activity.SetSport(sportId, sportName); activity.SetSport(sportId, sportName);
activity.SetRegion(regionId, regionName); activity.SetRegion(regionId, regionName);
} }
@@ -63,7 +63,7 @@ namespace Saxonite.Net.Core.Web.Base.Controllers
protected SaxApplication_Web App { get { return SaxApplication_Web.WebApp; } } protected SaxApplication_Web App { get { return SaxApplication_Web.WebApp; } }
public SaxAppConfig AppConfig { get { return App.AppConfig; } } public SaxAppConfig AppConfig { get { return App.AppConfig; } }
public SaxSessionContext SessionContext { get { return App.SessionContext; } } public SaxSessionContext SessionContext { get { return App.SessionContext; } }
protected SaxLocaliser Localiser { get; } public SaxLocaliser Localiser { get; }
/// <summary> /// <summary>
/// Indicate whether session data should be stored by action. /// Indicate whether session data should be stored by action.
/// <para>Any action that might modify the session data must store it.</para> /// <para>Any action that might modify the session data must store it.</para>
@@ -202,7 +202,16 @@ namespace Saxonite.Net.Core.Web.Base.Controllers
//------------------------------------------------------------------- //-------------------------------------------------------------------
// Parameters. // Parameters.
//------------------------------------------------------------------- //-------------------------------------------------------------------
public String EncryptParameters(NameValueCollection parameters, String base64IV, String base64Key) // Online Request Password encryption parameters (key & IV) are defined in
// the base Controller so that they can be shared with the Adnin application.
// NB IV value is generated from the key and fixed so that it doesn't change when the application restarts.
// IV Must be regenerated if key is changed.
protected static String Base64Key_RequestPassword_Online { get; } = SacsEncryptionHelper.EncodePlainKey("{~Saxonite@@Request^Password=}", SacsEncryptionHelper.KeyLength);
//private static String Base64IV_RequestPassword_Generated_Online { get; } = SacsEncryptionHelper.InitSymmetricEncryptionIV(Base64Key_RequestPassword_Online);
protected static String Base64IV_RequestPassword_Online { get; } = "1VAWYTW6d72n/6HDNhbqow==";
//-------------------------------------------------------------------
public static String EncryptParameters(NameValueCollection parameters, String base64IV, String base64Key)
{ {
String fn = nameof(ControllerBase) + ".EncryptParameters"; String fn = nameof(ControllerBase) + ".EncryptParameters";
try try
@@ -219,7 +228,7 @@ namespace Saxonite.Net.Core.Web.Base.Controllers
// Serialise parameters as if in a URL query string - so that they can be deserialised in DecryptParameters() below. // Serialise parameters as if in a URL query string - so that they can be deserialised in DecryptParameters() below.
string queryString = String.Join("&", paramKeys.Select(a => a + "=" + HttpUtility.UrlEncode(parametersToEncrypt[a]))); string queryString = String.Join("&", paramKeys.Select(a => a + "=" + HttpUtility.UrlEncode(parametersToEncrypt[a])));
String encrypted = SacsEncryptionHelper.Encrypt(queryString, base64IV, base64Key); String encrypted = SacsEncryptionHelper.Encrypt(queryString, base64IV, base64Key);
if (DebugMode) if (SacsSystem.DebugMode)
{ {
SaLogger.Debug(fn + " Encrypted: " + encrypted); SaLogger.Debug(fn + " Encrypted: " + encrypted);
NameValueCollection decryptedParams = DecryptParameters(encrypted, base64IV, base64Key); NameValueCollection decryptedParams = DecryptParameters(encrypted, base64IV, base64Key);
@@ -229,10 +238,10 @@ namespace Saxonite.Net.Core.Web.Base.Controllers
catch (Exception exc) { SaLogger.Warn(fn + " " + ExceptionUtil.GetErrorStateMessage(exc)); } catch (Exception exc) { SaLogger.Warn(fn + " " + ExceptionUtil.GetErrorStateMessage(exc)); }
return ""; return "";
} }
public NameValueCollection DecryptParameters(String encrypted, String base64IV, String base64Key) public static NameValueCollection DecryptParameters(String encrypted, String base64IV, String base64Key)
{ {
String fn = nameof(ControllerBase) + ".DecryptParameters"; String fn = nameof(ControllerBase) + ".DecryptParameters";
if (DebugMode) SaLogger.Debug(fn + " \n\tEncrypted: " + encrypted + "\n\tIV: " + base64IV + "\n\tKey: " + base64Key); if (SacsSystem.DebugMode) SaLogger.Debug(fn + " \n\tEncrypted: " + encrypted + "\n\tIV: " + base64IV + "\n\tKey: " + base64Key);
try try
{ {
String queryString = SacsEncryptionHelper.Decrypt(encrypted, base64IV, base64Key); String queryString = SacsEncryptionHelper.Decrypt(encrypted, base64IV, base64Key);
@@ -368,13 +377,19 @@ namespace Saxonite.Net.Core.Web.Base.Controllers
} }
//------------------------------------------------------------------- //-------------------------------------------------------------------
// Response data.
// Null values are ignored by JSON serialisation.
// - See Saxonite.Net.Core.Web.Base.App.SaxStartup.ConfigureServices()
// - Ref. config.services.AddMvc(...).AddJsonOptions(options => { options.JsonSerializerOptions.IgnoreNullValues = true; });
//-------------------------------------------------------------------
// Base response data - for simple responses.
public class AjaxResponse_Base public class AjaxResponse_Base
{ {
// Response status. // Response status.
public bool Success { get; set; } = false; public bool? Success { get; set; } = null;
public bool Error { get; set; } = false; public bool? Error { get; set; } = null;
public bool SessionExpired { get; protected set; } = false; public bool? SessionExpired { get; protected set; } = null;
public bool GoHome { get; protected set; } = false; public bool? GoHome { get; protected set; } = null;
public AjaxResponse_Base SetSessionExpired(String title, String text) public AjaxResponse_Base SetSessionExpired(String title, String text)
{ {
SessionExpired = true; SessionExpired = true;
@@ -415,7 +430,7 @@ namespace Saxonite.Net.Core.Web.Base.Controllers
} }
//--------------------------------------------------------------- //---------------------------------------------------------------
// Item data. /// <summary>Item data - Common properties for data items.</summary>
public class ItemData_Base public class ItemData_Base
{ {
// Common item properties. // Common item properties.
@@ -437,6 +452,15 @@ namespace Saxonite.Net.Core.Web.Base.Controllers
/// <summary>Updated on date - formatted per locale</summary> /// <summary>Updated on date - formatted per locale</summary>
public String UpdatedOnFmt { get; set; } public String UpdatedOnFmt { get; set; }
} }
/// <summary>
/// Item data with just Id and name.
/// <para>- Id is String to allow for obfuscated values.</para>
/// </summary>
public class ItemIdName
{
public String Id { get; set; }
public String Name { get; set; }
}
//--------------------------------------------------------------- //---------------------------------------------------------------
// Form data. // Form data.
@@ -453,7 +477,7 @@ namespace Saxonite.Net.Core.Web.Base.Controllers
public String Error { get; set; } public String Error { get; set; }
} }
private readonly Dictionary<String, FormControlValue> controlValues = new Dictionary<String, FormControlValue>(); private readonly Dictionary<String, FormControlValue> controlValues = new Dictionary<String, FormControlValue>();
public List<FormControlValue> ControlValues { get { return controlValues.Values.ToList(); } } public List<FormControlValue> ControlValues { get { return controlValues.Count > 0 ? controlValues.Values.ToList() : null; } }
public void SetControlValue(String controlName, String value, String error = null) public void SetControlValue(String controlName, String value, String error = null)
{ {
if (controlValues.ContainsKey(controlName)) if (controlValues.ContainsKey(controlName))
@@ -500,7 +524,6 @@ namespace Saxonite.Net.Core.Web.Base.Controllers
public String Message { get; set; } public String Message { get; set; }
} }
public NotificationData Notification { get; private set; } public NotificationData Notification { get; private set; }
public bool HasNotification { get { return Notification != null; } }
public AjaxResponse_Data SetNotification(String title, String message) public AjaxResponse_Data SetNotification(String title, String message)
{ {
Notification = new NotificationData() { Title = title, Message = message }; Notification = new NotificationData() { Title = title, Message = message };
@@ -191,12 +191,7 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
if (AccountMgr.UpdateUserAccount(organisationMember.UserAccount, DbUpdateInfo)) if (AccountMgr.UpdateUserAccount(organisationMember.UserAccount, DbUpdateInfo))
{ {
// Send activation email. // Send activation email.
SaEmailData emailData = new SaEmailData(); if (SendAccountActivatedEmail(this, organisationMember.UserAccount))
emailData.Config = EmailConfig;
emailData.AddressesTo.Add(organisationMember.UserAccount.EmailAddress);
emailData.Subject = Localiser["user.activate.email.subject"];
PopulateAccountActivatedEmailBody(emailData, organisationMember.UserAccount);
if (EmailConsole.SendEmail(emailData))
SaLogger.Info(fn + " User Activation email sent to " + organisationMember.UserAccount.EmailAddress, true); 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 send User Activation email to " + organisationMember.UserAccount.EmailAddress);
} }
@@ -218,18 +213,33 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
} }
//------------------------------------------------------------------- //-------------------------------------------------------------------
private void PopulateAccountActivatedEmailBody(SaEmailData emailData, SaxUserAccount userAccount) /// <summary>
/// Generate the User Activation email.
/// <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)
{
SaEmailData emailData = new SaEmailData();
emailData.Config = controller.EmailConfig;
emailData.AddressesTo.Add(userAccount.EmailAddress);
emailData.Subject = controller.Localiser["user.activate.email.subject"];
PopulateAccountActivatedEmailBody(controller, emailData, userAccount);
return controller.EmailConsole.SendEmail(emailData);
}
private static void PopulateAccountActivatedEmailBody(SaxController_Admin controller, SaEmailData emailData, SaxUserAccount userAccount)
{ {
// Will need to handle culture (language/country) as and when introduced. // Will need to handle culture (language/country) as and when introduced.
emailData.MessageBody = SaxResourceHelper.GetTextResource(SaxResourceHelper.TextResource.Email_Security_AccountActivated_Html); emailData.MessageBody = SaxResourceHelper.GetTextResource(SaxResourceHelper.TextResource.Email_Security_AccountActivated_Html);
emailData.HtmlBody = true; emailData.HtmlBody = true;
// Replace dynamic tags. // Replace dynamic tags.
EmailConsole.ReplaceDynamicEmailBodyTags(emailData, null, userAccount); controller.EmailConsole.ReplaceDynamicEmailBodyTags(emailData, null, userAccount);
// Replace dynamic tag for link back to change password page. // Replace dynamic tag for link back to change password page.
SaEmailConsole.ReplaceDynamicEmailTag(emailData, "[#Link.RequestPassword]", SecurityController.GenerateRequestPasswordLink(this, userAccount.Id, userAccount.EmailAddress, "", AppConfig.URL.Online.Root)); SaEmailConsole.ReplaceDynamicEmailTag(emailData, "[#Link.RequestPassword]", SecurityController.GenerateRequestPasswordLink(controller, userAccount.Id, userAccount.EmailAddress, "", true));
SaEmailConsole.ReplaceDynamicEmailTag(emailData, "[#Link.ExpiresMinutes]", SecurityController.GetRequestPasswordEmailLinkExpiresMinutes(this).ToString()); SaEmailConsole.ReplaceDynamicEmailTag(emailData, "[#Link.SignIn]", controller.AppConfig.URL.Online.Root + "Security/SignIn");
SaEmailConsole.ReplaceDynamicEmailTag(emailData, "[#Link.ExpiresMinutes]", SecurityController.GetRequestPasswordEmailLinkExpiresMinutes(controller).ToString());
} }
//------------------------------------------------------------------- //-------------------------------------------------------------------
@@ -146,7 +146,7 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
NamedValue.Map values = resultSet.GetRecordValues(); NamedValue.Map values = resultSet.GetRecordValues();
OrganisationData_List organisationData = new OrganisationData_List() OrganisationData_List organisationData = new OrganisationData_List()
{ {
Id = values.GetString(colId.DataName), Id = values.GetLong(colId.DataName).ToString(),
Name = values.GetString(colName.DataName), Name = values.GetString(colName.DataName),
TypeCode = values.GetString(colOrganisationType.DataName), TypeCode = values.GetString(colOrganisationType.DataName),
TypeDesc = OrganisationTypeCodes.GetDescForCode(values.GetString(colOrganisationType.DataName)), TypeDesc = OrganisationTypeCodes.GetDescForCode(values.GetString(colOrganisationType.DataName)),
@@ -337,13 +337,7 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
SaLogger.Warn(fn + " Unable to send password request email to " + model.EmailAddress + " - account is not 'Admin'"); SaLogger.Warn(fn + " Unable to send password request email to " + model.EmailAddress + " - account is not 'Admin'");
else else
{ {
// Send password request email. if (SendRequestPasswordEmail(this, userAccount, false))
SaEmailData emailData = new SaEmailData();
emailData.Config = EmailConfig;
emailData.AddressesTo.Add(model.EmailAddress);
emailData.Subject = Localiser["security.caption.request.password"];
PopulateRequestPasswordEmailBody(emailData, userAccount);
if (EmailConsole.SendEmail(emailData))
SaLogger.Info(fn + " Password request email sent to " + model.EmailAddress, true); SaLogger.Info(fn + " Password request email sent to " + model.EmailAddress, true);
else SaLogger.Warn(fn + " Failed to send password request email to " + model.EmailAddress); else SaLogger.Warn(fn + " Failed to send password request email to " + model.EmailAddress);
} }
@@ -354,18 +348,28 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
return Json(responseData); return Json(responseData);
} }
private void PopulateRequestPasswordEmailBody(SaEmailData emailData, SaxUserAccount userAccount) public static bool SendRequestPasswordEmail(SaxController_Admin controller, SaxUserAccount userAccount, bool onlineContext)
{
// Send password request email.
SaEmailData emailData = new SaEmailData();
emailData.Config = controller.EmailConfig;
emailData.AddressesTo.Add(userAccount.EmailAddress);
emailData.Subject = controller.Localiser["security.caption.request.password"];
PopulateRequestPasswordEmailBody(controller, emailData, userAccount, onlineContext);
return controller.EmailConsole.SendEmail(emailData);
}
private static void PopulateRequestPasswordEmailBody(SaxController_Admin controller, SaEmailData emailData, SaxUserAccount userAccount, bool onlineContext)
{ {
// Will need to handle culture (language/country) as and when introduced. // Will need to handle culture (language/country) as and when introduced.
emailData.MessageBody = SaxResourceHelper.GetTextResource(SaxResourceHelper.TextResource.Email_Security_RequestPassword_Html); emailData.MessageBody = SaxResourceHelper.GetTextResource(SaxResourceHelper.TextResource.Email_Security_RequestPassword_Html);
emailData.HtmlBody = true; emailData.HtmlBody = true;
// Replace dynamic tags. // Replace dynamic tags.
EmailConsole.ReplaceDynamicEmailBodyTags(emailData, null, userAccount); controller.EmailConsole.ReplaceDynamicEmailBodyTags(emailData, null, userAccount);
// Replace dynamic tag for link back to change password page. // Replace dynamic tag for link back to change password page.
SaEmailConsole.ReplaceDynamicEmailTag(emailData, "[#Link.RequestPassword]", GenerateRequestPasswordLink(this, userAccount.Id, userAccount.EmailAddress, "", GetRedirectLocation(RedirectLocation.WebAppBase))); SaEmailConsole.ReplaceDynamicEmailTag(emailData, "[#Link.RequestPassword]", GenerateRequestPasswordLink(controller, userAccount.Id, userAccount.EmailAddress, "", onlineContext));
SaEmailConsole.ReplaceDynamicEmailTag(emailData, "[#Link.ExpiresMinutes]", GetRequestPasswordEmailLinkExpiresMinutes(this).ToString()); SaEmailConsole.ReplaceDynamicEmailTag(emailData, "[#Link.ExpiresMinutes]", GetRequestPasswordEmailLinkExpiresMinutes(controller).ToString());
} }
//------------------------------------------------------------------- //-------------------------------------------------------------------
@@ -377,11 +381,20 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
private static String ParamName_Token { get; } = "tok"; private static String ParamName_Token { get; } = "tok";
// NB IV value is generated from the key and fixed so that it doesn't change when the application restarts. // NB IV value is generated from the key and fixed so that it doesn't change when the application restarts.
// IV Must be regenerated if key is changed. // IV Must be regenerated if key is changed.
private static String Base64Key_RequestPassword { get; } = SacsEncryptionHelper.EncodePlainKey("{~Saxonite@@Request^Password=}", SacsEncryptionHelper.KeyLength); private static String Base64Key_RequestPassword_Admin { get; } = SacsEncryptionHelper.EncodePlainKey("{~Saxonite@@Request^Password=}", SacsEncryptionHelper.KeyLength);
private static String Base64IV_RequestPassword_Generated { get; } = SacsEncryptionHelper.InitSymmetricEncryptionIV(Base64Key_RequestPassword); //private static String Base64IV_RequestPassword_Generated { get; } = SacsEncryptionHelper.InitSymmetricEncryptionIV(Base64Key_RequestPassword);
private static String Base64IV_RequestPassword { get; } = "1VAWYTW6d72n/6HDNhbqow=="; private static String Base64IV_RequestPassword_Admin { get; } = "1VAWYTW6d72n/6HDNhbqow==";
internal static String GenerateRequestPasswordLink(SaxController_Admin controller, SysId userAccountId, String emailAddress, String requestPasswordToken, String baseUrl) /// <summary>
/// Generate Request Password link.
/// <para>NB For an Online application request (from teh ASdmin system), must ensure that the URL and encryption parameters are switched.</para>
/// </summary>
internal static String GenerateRequestPasswordLink(SaxController_Admin controller, SysId userAccountId, String emailAddress, String requestPasswordToken, bool onlineContext)
{ {
// Base URL.
String baseUrl = onlineContext ? controller.AppConfig.URL.Online.Root : controller.GetRedirectLocation(RedirectLocation.WebAppBase);
String requestPassword_Base64Key = onlineContext ? Base64Key_RequestPassword_Online : Base64Key_RequestPassword_Admin;
String requestPassword_ase64IV = onlineContext ? Base64IV_RequestPassword_Online : Base64IV_RequestPassword_Admin;
NameValueCollection parameters = new NameValueCollection(); NameValueCollection parameters = new NameValueCollection();
parameters.Add(ParamName_UserAccountId, SysId.ToString(userAccountId)); parameters.Add(ParamName_UserAccountId, SysId.ToString(userAccountId));
parameters.Add(ParamName_EmailAddress, emailAddress); parameters.Add(ParamName_EmailAddress, emailAddress);
@@ -389,7 +402,7 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
parameters.Add(ParamName_Token, requestPasswordToken); parameters.Add(ParamName_Token, requestPasswordToken);
String link = String link =
baseUrl + "Security/ChangePassword?" + baseUrl + "Security/ChangePassword?" +
ParamName_RequestPasswordEncrypted + "=" + HttpUtility.UrlEncode(controller.EncryptParameters(parameters, Base64IV_RequestPassword, Base64Key_RequestPassword)); ParamName_RequestPasswordEncrypted + "=" + HttpUtility.UrlEncode(EncryptParameters(parameters, requestPassword_ase64IV, requestPassword_Base64Key));
return link; return link;
} }
internal static int GetRequestPasswordEmailLinkExpiresMinutes(SaxController_Admin controller) internal static int GetRequestPasswordEmailLinkExpiresMinutes(SaxController_Admin controller)
@@ -442,7 +455,7 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
RequestPasswordParams requestPasswordParams = new RequestPasswordParams(); RequestPasswordParams requestPasswordParams = new RequestPasswordParams();
if (!StringUtil.IsEmpty(encryptedParams)) if (!StringUtil.IsEmpty(encryptedParams))
{ {
NameValueCollection linkParams = DecryptParameters(encryptedParams, Base64IV_RequestPassword, Base64Key_RequestPassword); NameValueCollection linkParams = DecryptParameters(encryptedParams, Base64IV_RequestPassword_Admin, Base64Key_RequestPassword_Admin);
requestPasswordParams.UserAccountId = new SysId(StringUtil.ToInt(linkParams.Get(ParamName_UserAccountId))); requestPasswordParams.UserAccountId = new SysId(StringUtil.ToInt(linkParams.Get(ParamName_UserAccountId)));
requestPasswordParams.EmailAddress = linkParams.Get(ParamName_EmailAddress); requestPasswordParams.EmailAddress = linkParams.Get(ParamName_EmailAddress);
requestPasswordParams.ExpiresAt = DateUtil.ParseXmlDateTime(linkParams.Get(ParamName_ExpiresAt)); requestPasswordParams.ExpiresAt = DateUtil.ParseXmlDateTime(linkParams.Get(ParamName_ExpiresAt));
@@ -19,18 +19,15 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
{ {
//------------------------------------------------------------------- //-------------------------------------------------------------------
// User data. // User data.
private class UserData_List private class UserData_List : AjaxResponse_Data.ItemData_Base
{ {
public String Id { get; set; }
public String EmailAddress { get; set; } public String EmailAddress { get; set; }
public String DisplayName { get; set; } public String DisplayName { get; set; }
public String Title { get; set; } public String Title { get; set; }
public String FirstName { get; set; } public String FirstName { get; set; }
public String LastName { get; set; } public String LastName { get; set; }
public int UserRoleCount { get; set; } public int UserRoleCount { get; set; }
public bool SystemAdmin { get; set; } public bool? SystemAdmin { get; set; } = null;
public String StatusCode { get; set; }
public String StatusDesc { get; set; }
} }
private class UserData_Full : UserData_List private class UserData_Full : UserData_List
{ {
@@ -45,6 +42,7 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
data.FirstName = user.FirstName; data.FirstName = user.FirstName;
data.LastName = user.LastName; data.LastName = user.LastName;
data.UserRoleCount = userRoles?.GetUserRolesByStatus(SaStatus.Active).Count ?? 0; data.UserRoleCount = userRoles?.GetUserRolesByStatus(SaStatus.Active).Count ?? 0;
data.SystemAdmin = (userRoles != null && userRoles.Exists(item => item.UserRole == Sax.UserRole.SystemAdmin) ? true : (bool?)null);
data.StatusCode = user.StatusCode; data.StatusCode = user.StatusCode;
data.StatusDesc = user.StatusDesc; data.StatusDesc = user.StatusDesc;
} }
@@ -95,9 +93,10 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
String messageTitle = Localiser["user.caption.users"]; String messageTitle = Localiser["user.caption.users"];
AjaxResponse_UserList responseData = new AjaxResponse_UserList(model); AjaxResponse_UserList responseData = new AjaxResponse_UserList(model);
// Validate session. // Validate session and referrer.
if (!ValidUserSession) if (!ValidReferer) return Forbid();
return GetAjaxResult_InvalidSession(responseData); if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
RefreshModel(model);
// Reference data - user roles. // Reference data - user roles.
foreach (TypeCodeDesc userRole in UserRoleCodes) foreach (TypeCodeDesc userRole in UserRoleCodes)
@@ -187,9 +186,10 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
String messageTitle = Localiser["user.caption.user"]; String messageTitle = Localiser["user.caption.user"];
AjaxResponse_User responseData = new AjaxResponse_User(model); AjaxResponse_User responseData = new AjaxResponse_User(model);
// Validate session. // Validate session and referrer.
if (!ValidUserSession) if (!ValidReferer) return Forbid();
return GetAjaxResult_InvalidSession(responseData); if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
RefreshModel(model);
// Identify item. // Identify item.
SysId userAccountId = model.UserAccountId.ToSysId(); SysId userAccountId = model.UserAccountId.ToSysId();
@@ -222,9 +222,10 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
AjaxResponse_User responseData = new AjaxResponse_User(model); AjaxResponse_User responseData = new AjaxResponse_User(model);
StoreSessionData = false; StoreSessionData = false;
// Validate session. // Validate session and referrer.
if (!ValidUserSession) if (!ValidReferer) return Forbid();
return GetAjaxResult_InvalidSession(responseData); if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
RefreshModel(model);
// Identify user. // Identify user.
if (StringUtil.IsEmpty(model.UserEmailAddress)) if (StringUtil.IsEmpty(model.UserEmailAddress))
@@ -259,9 +260,10 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
String messageTitle = Localiser["user.caption.user"]; String messageTitle = Localiser["user.caption.user"];
AjaxResponse_User responseData = new AjaxResponse_User(model); AjaxResponse_User responseData = new AjaxResponse_User(model);
// Validate session. // Validate session and referrer.
if (!ValidUserSession) if (!ValidReferer) return Forbid();
return GetAjaxResult_InvalidSession(responseData); if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
RefreshModel(model);
// Validate item properties. // Validate item properties.
model.ValidateUserData(responseData); model.ValidateUserData(responseData);
@@ -367,6 +369,72 @@ namespace Saxonite.Net.Core.Web.Admin.Controllers
return Json(responseData); return Json(responseData);
} }
//-------------------------------------------------------------------
// Send User Emails ajax request.
//-------------------------------------------------------------------
[HttpPost]
[Route("User/Ajax/SendEmails")]
public IActionResult Ajax_SendEmails(Model_User model)
{
String fn = GetType().Name + ".Ajax_SendEmails";
String messageTitle = Localiser["label.emails"];
AjaxResponse_User responseData = new AjaxResponse_User(model);
// Validate session and referrer.
if (!ValidReferer) return Forbid();
if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
RefreshModel(model);
// Retrieve user.
SysId userAccountId = model.UserAccountId.ToSysId();
SaxUserAccount userAccount = AccountMgr.GetUserAccountById(userAccountId);
if (userAccount == null)
{
SaLogger.Warn(fn + " Failed to retrieve user for Id: '" + model.UserAccountId + "'");
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
}
// User roles.
List<SaxUserRole> userRoles = GetUserRoles(userAccount.Id, SaxUserRole.StatusCat.Any);
bool systemAdmin = userRoles.Exists(item => item.UserRole == Sax.UserRole.SystemAdmin);
// Email types to send.
bool sendAcountActivationOnline = StringUtil.ToBool(model.UserEmailAcountActivationOnline);
bool sendRequestPasswordOnline = StringUtil.ToBool(model.UserEmailRequestPasswordOnline);
bool sendRequestPasswordAdmin = StringUtil.ToBool(model.UserEmailRequestPasswordAdmin);
if (!sendAcountActivationOnline && !sendRequestPasswordOnline && !sendRequestPasswordAdmin)
return Json(responseData.SetMessage(messageTitle, Localiser["msg.validation.select.option"]));
if (sendRequestPasswordAdmin && !systemAdmin)
return Json(responseData.SetMessage(messageTitle, Localiser["user.msg.not.system.admin"]));
// Send emails.
int emailsSentCount = 0;
if (sendAcountActivationOnline)
{
if (!OrganisationController.SendAccountActivatedEmail(this, userAccount))
return Json(responseData.SetMessage(messageTitle, "Failed to send Online Accoutn Activation email."));
emailsSentCount++;
}
if (sendRequestPasswordOnline)
{
if (!SecurityController.SendRequestPasswordEmail(this, userAccount, true))
return Json(responseData.SetMessage(messageTitle, "Failed to send Online Request Password email."));
emailsSentCount++;
}
if (sendRequestPasswordAdmin)
{
if (!SecurityController.SendRequestPasswordEmail(this, userAccount, false))
return Json(responseData.SetMessage(messageTitle, "Failed to send Admin Request Password email."));
emailsSentCount++;
}
// Construct response.
PopulateUserResponseData(responseData.user, userAccount, userRoles.GetUserRolesByStatus(SaStatus.Active));
responseData.SetNotification(messageTitle, "Emails sent: " + emailsSentCount);
responseData.Success = true;
return Json(responseData);
}
//------------------------------------------------------------------- //-------------------------------------------------------------------
} }
//======================================================================= //=======================================================================
@@ -1,6 +1,7 @@
using Sarand.Net.Standard.Base.App; using Sarand.Net.Standard.Base.App;
using Sarand.Net.Standard.Base.Bus; using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Core; using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Helpers;
using Sarand.Net.Standard.Base.Utils; using Sarand.Net.Standard.Base.Utils;
using Saxonite.Base.App; using Saxonite.Base.App;
using Saxonite.Net.Core.Web.Base.App; using Saxonite.Net.Core.Web.Base.App;
@@ -57,6 +58,10 @@ namespace Saxonite.Net.Core.Web.Admin.Models
} }
public String UserStatusCode { get; set; } public String UserStatusCode { get; set; }
public SaStatus UserStatus { get { return SacsSystem.GetStatusForCode(UserStatusCode); } } public SaStatus UserStatus { get { return SacsSystem.GetStatusForCode(UserStatusCode); } }
// User emails.
public String UserEmailAcountActivationOnline { get; set; }
public String UserEmailRequestPasswordOnline { get; set; }
public String UserEmailRequestPasswordAdmin { get; set; }
//------------------------------------------------------------------- //-------------------------------------------------------------------
// Validation. // Validation.
@@ -73,6 +78,8 @@ namespace Saxonite.Net.Core.Web.Admin.Models
responseData.SetControlError(nameof(UserEmailAddress), Localiser["msg.validation.mandatory.value"]); responseData.SetControlError(nameof(UserEmailAddress), Localiser["msg.validation.mandatory.value"]);
else if (StringUtil.GetLength(UserEmailAddress) > GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.UserAccount_EmailAddress)) else if (StringUtil.GetLength(UserEmailAddress) > GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.UserAccount_EmailAddress))
responseData.SetControlError(nameof(UserEmailAddress), Localiser["msg.validation.maximum.length", GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.UserAccount_EmailAddress)]); responseData.SetControlError(nameof(UserEmailAddress), Localiser["msg.validation.maximum.length", GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.UserAccount_EmailAddress)]);
else if (!SacsDataValidationHelper.IsValidEmailAddress(UserEmailAddress))
responseData.SetControlError(nameof(UserEmailAddress), Localiser["msg.validation.invalid.value"]);
else else
{ {
// Check for duplicate email address. // Check for duplicate email address.
@@ -201,6 +201,12 @@
<data name="label.email.address" xml:space="preserve"> <data name="label.email.address" xml:space="preserve">
<value>Email address</value> <value>Email address</value>
</data> </data>
<data name="label.email.types" xml:space="preserve">
<value>Email types</value>
</data>
<data name="label.emails" xml:space="preserve">
<value>Emails</value>
</data>
<data name="label.filename" xml:space="preserve"> <data name="label.filename" xml:space="preserve">
<value>Filename</value> <value>Filename</value>
</data> </data>
@@ -390,6 +396,9 @@
<data name="msg.validation.maximum.length" xml:space="preserve"> <data name="msg.validation.maximum.length" xml:space="preserve">
<value>Value must not exceed {0} characters</value> <value>Value must not exceed {0} characters</value>
</data> </data>
<data name="msg.validation.select.option" xml:space="preserve">
<value>At least one option must be selected.</value>
</data>
<data name="organisation.activate.intro" xml:space="preserve"> <data name="organisation.activate.intro" xml:space="preserve">
<value>On activation, the Organisation will become visible on the platform and authorised members will be able to post content associated with the organisation.</value> <value>On activation, the Organisation will become visible on the platform and authorised members will be able to post content associated with the organisation.</value>
</data> </data>
@@ -522,6 +531,9 @@
<data name="user.activate.email.subject" xml:space="preserve"> <data name="user.activate.email.subject" xml:space="preserve">
<value>Account Activation</value> <value>Account Activation</value>
</data> </data>
<data name="user.caption.select.user.emails" xml:space="preserve">
<value>Select User Emails</value>
</data>
<data name="user.caption.select.user.roles" xml:space="preserve"> <data name="user.caption.select.user.roles" xml:space="preserve">
<value>Select User Roles</value> <value>Select User Roles</value>
</data> </data>
@@ -537,4 +549,19 @@
<data name="user.caption.users" xml:space="preserve"> <data name="user.caption.users" xml:space="preserve">
<value>Users</value> <value>Users</value>
</data> </data>
<data name="user.email.account.activation.online" xml:space="preserve">
<value>Account activation - Online</value>
</data>
<data name="user.email.request.password.admin" xml:space="preserve">
<value>Request password - Admin</value>
</data>
<data name="user.email.request.password.online" xml:space="preserve">
<value>Request password - Online</value>
</data>
<data name="user.emails.intro" xml:space="preserve">
<value>Select the types of email to be sent.</value>
</data>
<data name="user.msg.not.system.admin" xml:space="preserve">
<value>User is not system admin.</value>
</data>
</root> </root>
@@ -181,7 +181,7 @@
@* Footer *@ @* Footer *@
<footer id="sax-page-footer" class="border-top footer text-muted"> <footer id="sax-page-footer" class="border-top footer text-muted">
<div class="container"> <div class="container">
@(Model.CopyrightNotice) - @Localiser["company.name"] @(Model.InstanceVersion) - <a asp-area="" asp-controller="Home" asp-action="">Home</a> @(Model.CopyrightNotice) - @Localiser["company.name"] @(Model.InstanceVersion)
</div> </div>
</footer> </footer>
+50 -5
View File
@@ -5,41 +5,80 @@
ViewData["Title"] = "Users"; ViewData["Title"] = "Users";
} }
<div class=""> <div class="sax-panel Users">
<script type="text/javascript">
sax.lbl.refresh = '@(Localiser.GetJavascriptText("label.refresh"))';
sax.lbl.create = '@(Localiser.GetJavascriptText("label.create"))';
sax.lbl.edit = '@(Localiser.GetJavascriptText("label.edit"))';
sax.lbl.emails= '@(Localiser.GetJavascriptText("label.emails"))';
</script>
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmUserFilter", @class = "sax-form", @onSubmit = "return false;" })) @using (@Html.BeginForm(FormMethod.Post, new { @id = "frmUserFilter", @class = "sax-form", @onSubmit = "return false;" }))
{ {
@* Filter Panel *@
<div class="sax-panel-filter"> <div class="sax-panel-filter">
@* Header - Page caption, paging controls, actions. *@
<div class="sax-header row"> <div class="sax-header row">
<div class="col"><div class="sax-caption">@Localiser["user.caption.users"]</div></div> <div class="col"><div class="sax-caption">@Localiser["user.caption.users"]</div></div>
<div class="fixed row"> <div class="fixed row">
<div> <div class="col">
<partial name="~/Views/Common/ResultsPaging.cshtml" /> <partial name="~/Views/Common/ResultsPaging.cshtml" />
</div> </div>
<div class="sax-action sax-results-refresh"><img src="~/img/action/refresh24.png" alt="@(Localiser["label.refresh"])" title="@(Localiser["label.refresh"])" /></div> <div class="fixed">
<div class="sax-action sax-item-create"><img src="~/img/action/add24.png" alt="@(Localiser["label.create"])" title="@(Localiser["label.create"])" /></div> @* Burger menu *@
<ul class="nav navbar-nav navbar-dark navbar-right sax-burger">
<li class="dropdown-toggle caret-off">
<a href="#" class="dropdown" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><span class="navbar-toggler-icon"></span></a>
<ul class="dropdown-menu dropdown-menu-right sax-dropdown-menu">@* Menu items will be inserted here. *@</ul>
</li>
</ul>
</div>
</div> </div>
</div> </div>
<div class="sax-content"> <div class="sax-content">
<div class="row"> <div class="row">
@* User filter - email, name etc. *@
<div class="col-sm-5 sax-label text-left text-sm-right">@Localiser["user.caption.user"]</div> <div class="col-sm-5 sax-label text-left text-sm-right">@Localiser["user.caption.user"]</div>
<div class="col-sm-7">@Html.TextBoxFor(model => model.Filter.User, new { @id = "ifFilterUser", @class = "FilterUser", @maxlength = "32" })</div> <div class="col-sm-7">@Html.TextBoxFor(model => model.Filter.User, new { @id = "ifFilterUser", @class = "FilterUser", @maxlength = "32" })</div>
</div> </div>
</div> </div>
@* Filter element templates *@
<div class="sax-panel-item-template">
@* Burger dropdown item template - ul is ignored *@
<ul class="sax-dropdown-menu UserFilter">
<li class="sax-dropdown-item sax-action"><div class="sax-label">XXX</div></li>
</ul>
</div>
</div> </div>
} }
@* Results Panel *@
<div class="sax-panel-results"> <div class="sax-panel-results">
<div class="sax-panel-messages"></div> <div class="sax-panel-messages"></div>
<div class="sax-panel-item-list"></div> <div class="sax-panel-item-list"></div>
@* Element templates *@
<div class="sax-panel-item-template"> <div class="sax-panel-item-template">
@* User item template *@
<div class="sax-panel-item User"> <div class="sax-panel-item User">
<div class="sax-header row"> <div class="sax-header row">
<div class="col"> <div class="col">
@* User email *@
<div class="sax-caption"><div class="sax-action UserEmailAddress"></div></div> <div class="sax-caption"><div class="sax-action UserEmailAddress"></div></div>
</div> </div>
<div class="fixed sax-actions"> <div class="fixed sax-actions">
<div class="sax-action sax-item-update"><img src="~/img/action/edit24.png" alt="@(Localiser["label.update"])" title="@(Localiser["label.update"])" /></div> @* Burger menu *@
<ul class="nav navbar-nav navbar-light navbar-right sax-burger">
<li class="dropdown-toggle caret-off">
<a href="#" class="dropdown" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><span class="navbar-toggler-icon"></span></a>
<ul class="dropdown-menu dropdown-menu-right sax-dropdown-menu">@* Menu items will be inserted here. *@</ul>
</li>
</ul>
</div> </div>
</div> </div>
<div class="sax-content"> <div class="sax-content">
@@ -54,6 +93,12 @@
</div> </div>
</div> </div>
</div> </div>
@* Burger dropdown item template - ul is ignored *@
<ul class="sax-dropdown-menu User">
<li class="sax-dropdown-item sax-action"><div class="sax-label">XXX</div></li>
</ul>
</div> </div>
</div> </div>
@@ -8,6 +8,7 @@
sax.dlg.title.createUser = '@Localiser.GetJavascriptText("user.caption.user.create")'; sax.dlg.title.createUser = '@Localiser.GetJavascriptText("user.caption.user.create")';
sax.dlg.title.updateUser = '@Localiser.GetJavascriptText("user.caption.user.update")'; sax.dlg.title.updateUser = '@Localiser.GetJavascriptText("user.caption.user.update")';
sax.dlg.title.selectUserRoles = '@Localiser.GetJavascriptText("user.caption.select.user.roles")'; sax.dlg.title.selectUserRoles = '@Localiser.GetJavascriptText("user.caption.select.user.roles")';
sax.dlg.title.selectUserEmails = '@Localiser.GetJavascriptText("user.caption.select.user.emails")';
sax.data.userRoleCodeDelim = '@Model.UserRoleCodeDelim'; sax.data.userRoleCodeDelim = '@Model.UserRoleCodeDelim';
</script> </script>
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmUserId", @class = "sax-form" })) @using (@Html.BeginForm(FormMethod.Post, new { @id = "frmUserId", @class = "sax-form" }))
@@ -31,6 +32,7 @@
<div class="sax-message"></div> <div class="sax-message"></div>
</div> </div>
/* Title */
<div class="sax-form-control UserTitle"> <div class="sax-form-control UserTitle">
<div class="sax-label"> <div class="sax-label">
<label for="cbUserTitle"><span><span class="required"></span> @Localiser["label.title"]</span></label> <label for="cbUserTitle"><span><span class="required"></span> @Localiser["label.title"]</span></label>
@@ -89,6 +91,57 @@
} }
<partial name="~/Views/Common/SelectCode.cshtml" /> </div>
<partial name="~/Views/Common/SelectCode.cshtml" />
<div id="dlgUserEmails" class="sax-dialog" title="">
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmUserEmails", @class = "sax-form", @onSubmit = "return false;" }))
{
@Html.HiddenFor(model => model.UserAccountId, new { @class = "UserAccountId" })
<div class="sax-para">@Localiser["user.emails.intro"]</div>
@* User email *@
<div class="sax-form-control UserEmailAddress">
<div class="sax-label">
<label><span>@Localiser["label.email.address"]</span></label>
</div>
<div class="sax-control">
<input type="text" class="UserEmailAddress sax-input" readonly="readonly" />
</div>
<div class="sax-message"></div>
</div>
@* User display name *@
<div class="sax-form-control UserDisplayName">
<div class="sax-label">
<label ><span>@Localiser["label.name"]</span></label>
</div>
<div class="sax-control">
<input type="text" class="UserDisplayName sax-input" readonly="readonly" />
</div>
<div class="sax-message"></div>
</div>
@* User emails *@
<div class="sax-form-control UserEmailTypes">
<div class="sax-label">
<label for="chkUserEmailRequestPasswordAdmin"><span>@Localiser["label.email.types"]</span></label>
</div>
<div class="sax-control">
<div class="AcountActivationOnlineOption">
<input type="checkbox" id="chkUserEmailAcountActivationOnline" class="UserEmailAcountActivationOnline" name="UserEmailAcountActivationOnline" value="1" />&nbsp;<span onclick="$('#chkUserEmailAcountActivationOnline').click()">@Localiser["user.email.account.activation.online"]</span>
</div>
<div class="RequestPasswordOnlineOption">
<input type="checkbox" id="chkUserEmailRequestPasswordOnline" class="UserEmailRequestPasswordOnline" name="UserEmailRequestPasswordOnline" value="1" />&nbsp;<span onclick="$('#chkUserEmailRequestPasswordOnline').click()">@Localiser["user.email.request.password.online"]</span>
</div>
<div class="RequestPasswordAdminOption">
<input type="checkbox" id="chkUserEmailRequestPasswordAdmin" class="UserEmailRequestPasswordAdmin" name="UserEmailRequestPasswordAdmin" value="1" />&nbsp;<span onclick="$('#chkUserEmailRequestPasswordAdmin').click()">@Localiser["user.email.request.password.admin"]</span>
</div>
</div>
<div class="sax-message"></div>
</div>
}
</div> </div>
+11 -3
View File
@@ -77,7 +77,7 @@ html
body body
{ {
/* Margin bottom by footer height */ /* Margin bottom by footer height */
margin-bottom: 60px; margin-bottom: 40px;
} }
.footer .footer
@@ -88,8 +88,8 @@ body
padding: 0 2%; padding: 0 2%;
white-space: nowrap; white-space: nowrap;
/* Set the fixed height of the footer here */ /* Set the fixed height of the footer here */
height: 60px; height: 40px;
line-height: 60px; /* Vertically center the text there */ line-height: 38px; /* Vertically center the text there */
} }
/* Header */ /* Header */
@@ -122,6 +122,14 @@ button.accept-policy
line-height: inherit; line-height: inherit;
} }
/* Footer */
#sax-page-footer div,
#sax-page-footer a
{
font-size:0.75rem;
}
/* Information */ /* Information */
.sax-para .sax-para
+1 -1
View File
@@ -23,7 +23,7 @@
} }
sax.handleDbSchemaResponse = function (response) sax.handleDbSchemaResponse = function (response)
{ {
sax.debug('handleDbSchemaResponse', response); //sax.debug('handleDbSchemaResponse', response);
delete sax.awaitingRefreshResponse; delete sax.awaitingRefreshResponse;
var $results = $('.sax-panel-results.DbSchema'); var $results = $('.sax-panel-results.DbSchema');
var $msgs = $('.sax-panel-messages', $results).hide().empty(); var $msgs = $('.sax-panel-messages', $results).hide().empty();
+10 -10
View File
@@ -263,16 +263,16 @@
var $hdr = $('.heading', $not).css({ 'background-color': 'rgba(247,217,0,0.7)' }); var $hdr = $('.heading', $not).css({ 'background-color': 'rgba(247,217,0,0.7)' });
$('.title', $not).html(title); $('.title', $not).html(title);
$('.message', $not).html(msg); $('.message', $not).html(msg);
var $bdy = $('.sax-page-body'); var $bdy = $('#sax-page-body');
sax.debug(sax.topMargin($bdy)); //sax.debug(sax.topMargin($bdy));
var fbr = $bdy[0].getBoundingClientRect(); var fbr = $bdy[0].getBoundingClientRect();
var fn = function () { $hdr.delay(2000).animate({ backgroundColor: '#f0f0f0' }, 1000); }; var fn = function () { $hdr.delay(1500).animate({ backgroundColor: '#f0f0f0' }, 500); };
$not.css({ 'top': Math.max(0, fbr.top - sax.topMargin($bdy)), 'right': $win.width() - fbr.right }).slideDown(500, fn); $not.css({ 'top': Math.max(0, fbr.top - sax.topMargin($bdy)), 'right': $win.width() - fbr.right }).slideDown(500, fn);
sax.toNotification = setTimeout(sax.hideNotification, 6000); sax.toNotification = setTimeout(sax.hideNotification, 4000);
} }
sax.hideNotification = function () sax.hideNotification = function ()
{ {
wwin.clearTimeout(sax.toNotification); win.clearTimeout(sax.toNotification);
$('#sax-notification').slideUp(500); $('#sax-notification').slideUp(500);
} }
sax.doPleaseWait = function () sax.doPleaseWait = function ()
@@ -360,7 +360,7 @@
} }
sax.doKeepLoggedIn = function () sax.doKeepLoggedIn = function ()
{ {
sax.debug('KeepLoggedIn Calling'); //sax.debug('KeepLoggedIn Calling');
var onKeepLoggedIn = function (response) var onKeepLoggedIn = function (response)
{ {
sax.debug('KeepLoggedIn Responded', response); sax.debug('KeepLoggedIn Responded', response);
@@ -370,19 +370,19 @@
} }
sax.configureSessionRefresh = function () sax.configureSessionRefresh = function ()
{ {
sax.debug('SessionRefresh Configuring'); //sax.debug('SessionRefresh Configuring');
$(document).on('mousedown mousemove touchstart scroll keydown', sax.triggeRefreshSession); $(document).on('mousedown mousemove touchstart scroll keydown', sax.triggeRefreshSession);
} }
sax.triggeRefreshSession = function () sax.triggeRefreshSession = function ()
{ {
sax.session = sax.session || { refresh: {} }; //sax.session = sax.session || { refresh: {} };
let ssr = sax.session.refresh; let ssr = sax.session.refresh;
win.clearTimeout(ssr.timeout); win.clearTimeout(ssr.timeout);
ssr.timeout = setTimeout(function () { sax.refreshSession(); }, 150000); ssr.timeout = setTimeout(function () { sax.refreshSession(); }, 150000);
} }
sax.refreshSession = function () sax.refreshSession = function ()
{ {
sax.debug('sax.refreshSession'); //sax.debug('sax.refreshSession');
sax.doKeepLoggedIn(); sax.doKeepLoggedIn();
} }
@@ -400,7 +400,7 @@
} }
sax.setControlError = function (sel, error) sax.setControlError = function (sel, error)
{ {
sax.debug(sel, error); //sax.debug(sel, error);
var $ctrl = $(sel).closest('.sax-form-control').addClass('sax-error'); var $ctrl = $(sel).closest('.sax-form-control').addClass('sax-error');
$('.sax-message', $ctrl).text(error); $('.sax-message', $ctrl).text(error);
} }
@@ -151,7 +151,7 @@
} }
sax.onUpdateItem = function (response) sax.onUpdateItem = function (response)
{ {
sax.debug('onUpdateItem', response); //sax.debug('onUpdateItem', response);
let $frm = sax.$frm.member; let $frm = sax.$frm.member;
$('.UserOrganisationId,input[type="text"],textarea,select', $frm).val(''); $('.UserOrganisationId,input[type="text"],textarea,select', $frm).val('');
if (!response.success) return; if (!response.success) return;
@@ -85,7 +85,7 @@
} }
sax.onParentRegionSelected = function (rgn) sax.onParentRegionSelected = function (rgn)
{ {
sax.debug('onParentRegionSelected', rgn); //sax.debug('onParentRegionSelected', rgn);
let $frm = sax.$frm.region; let $frm = sax.$frm.region;
$('.RegionIdParent', $frm).val(rgn.id); $('.RegionIdParent', $frm).val(rgn.id);
$('.ParentRegion', $frm).val(rgn.name); $('.ParentRegion', $frm).val(rgn.name);
@@ -115,7 +115,7 @@
} }
sax.onUpdateItem = function (response) sax.onUpdateItem = function (response)
{ {
sax.debug('onUpdateItem', response); //sax.debug('onUpdateItem', response);
let $frm = sax.$frm.region; let $frm = sax.$frm.region;
$('.RegionId,input[type="text"],textarea,select', $frm).val(''); $('.RegionId,input[type="text"],textarea,select', $frm).val('');
if (!response.success) return; if (!response.success) return;
@@ -15,7 +15,7 @@
} }
sax.onSignin = function (response) sax.onSignin = function (response)
{ {
sax.debug(response); //sax.debug(response);
sax.refreshControlValues(response.controlValues); sax.refreshControlValues(response.controlValues);
if (!response.success) return; if (!response.success) return;
sax.goToPage(''); sax.goToPage('');
@@ -31,7 +31,7 @@
} }
so.fn.doRefreshResults = function (response) so.fn.doRefreshResults = function (response)
{ {
sax.debug('so.doRefreshResults', response); //sax.debug('so.doRefreshResults', response);
sax.refreshPaging(response, '#frmSelectOrganisationFilter', so.fn.refreshOrganisations); sax.refreshPaging(response, '#frmSelectOrganisationFilter', so.fn.refreshOrganisations);
if (!response.success) return; if (!response.success) return;
let $results = $('.sax-selection-results.Organisations', so.$dlg).empty().hide(); let $results = $('.sax-selection-results.Organisations', so.$dlg).empty().hide();
@@ -22,7 +22,7 @@
} }
sax.doRefreshResults = function (response) sax.doRefreshResults = function (response)
{ {
sax.debug('doRefreshResults', response); //sax.debug('doRefreshResults', response);
delete sax.awaitingRefreshResponse; delete sax.awaitingRefreshResponse;
sax.refreshControlValues(response.controlValues); sax.refreshControlValues(response.controlValues);
var $results = $('.sax-panel-results'); var $results = $('.sax-panel-results');
@@ -0,0 +1,19 @@
/*
* Admin - System Logs page scripts.
*/
(function (win, doc, undef)
{
"use strict";
sax.itemIdPrefix = 'Itm_';
//--------------------------------------------------------------
//--------------------------------------------------------------
$(function ()
{
});
}(window, window.document));
/* The End */
+119 -66
View File
@@ -5,20 +5,21 @@
(function (win, doc, undef) (function (win, doc, undef)
{ {
"use strict"; "use strict";
let $pnl = sax.$pnl, $frm = sax.$frm, $dlg = sax.$dlg;
sax.itemIdPrefix = 'Itm_'; sax.itemIdPrefix = 'Itm_';
sax.userAccount = {}; sax.userAccount = {};
//-------------------------------------------------------------- //--------------------------------------------------------------
sax.refreshResults = function (delay) sax.refreshResults = function (delay)
{ {
var $results = $('.sax-panel-results');
if (!sax.awaitingRefreshResponse) if (!sax.awaitingRefreshResponse)
{ {
var $items = $('.sax-panel-item-list', $results).fadeOut(200).empty(); $('.sax-burger', $pnl.filter).hide();
var $msgs = $('.sax-panel-messages', $results).hide().empty().append($('<div class="sax-message">' + sax.msg.dataQuerying + '</div>')).fadeIn(200); var $items = $('.sax-panel-item-list', $pnl.results).fadeOut(200).empty();
var $msgs = $('.sax-panel-messages', $pnl.results).hide().empty().append($('<div class="sax-message">' + sax.msg.dataQuerying + '</div>')).fadeIn(200);
} }
sax.ajaxRefreshResults = sax.ajaxRefreshResults || { url: sax.url.base + 'User/Ajax/GetList', formId: 'frmUserFilter', callbackFn: sax.doRefreshResults }; sax.ajax.refreshResults = sax.ajax.refreshResults || { url: sax.url.base + 'User/Ajax/GetList', formId: 'frmUserFilter', callbackFn: sax.doRefreshResults };
sax.doAjaxRequest(sax.ajaxRefreshResults, delay || 50); sax.doAjaxRequest(sax.ajax.refreshResults, delay || 50);
sax.awaitingRefreshResponse = true; sax.awaitingRefreshResponse = true;
} }
sax.doRefreshResults = function (response) sax.doRefreshResults = function (response)
@@ -26,10 +27,8 @@
//sax.debug('doRefreshResults', response); //sax.debug('doRefreshResults', response);
delete sax.awaitingRefreshResponse; delete sax.awaitingRefreshResponse;
sax.refreshControlValues(response.controlValues); sax.refreshControlValues(response.controlValues);
var $results = $('.sax-panel-results'); var $msgs = $('.sax-panel-messages', $pnl.results).hide().empty();
var $msgs = $('.sax-panel-messages', $results).hide().empty(); var $items = $('.sax-panel-item-list', $pnl.results).hide().empty();
var $items = $('.sax-panel-item-list', $results).hide().empty();
var $tmpl = $('.sax-panel-item-template .sax-panel-item.User', $results);
sax.refreshPaging(response, '#frmUserFilter', sax.refreshResults); sax.refreshPaging(response, '#frmUserFilter', sax.refreshResults);
if (!response.success) return; if (!response.success) return;
// Reference data - Roles. // Reference data - Roles.
@@ -39,21 +38,19 @@
if (response.defaultStatusCode) sax.data.defaultStatusCode = response.defaultStatusCode; if (response.defaultStatusCode) sax.data.defaultStatusCode = response.defaultStatusCode;
if (response.statuses) if (response.statuses)
sax.populateSelectCodeDesc('#cbUserStatus', response.statuses); sax.populateSelectCodeDesc('#cbUserStatus', response.statuses);
// Menu.
var $bgr = $('.sax-burger', $pnl.filter).hide();
var $mnu = $('ul.sax-dropdown-menu', $bgr).empty();
$mnu.append(sax.getFilterMenuOption(sax.lbl.refresh, function () { sax.refreshResults(); }));
$mnu.append(sax.getFilterMenuOption(sax.lbl.create, function () { sax.createItem(); }));
$bgr.toggle(!!$('.sax-dropdown-item', $mnu).length);
// Items. // Items.
var items = response.users; var items = response.users;
if (!items.length) if (!items.length)
return $msgs.append($('<div class="sax-message">' + sax.msg.dataNoneFound + '</div>')).fadeIn(500); return $msgs.append($('<div class="sax-message">' + sax.msg.dataNoneFound + '</div>')).fadeIn(500);
for (let itemIdx = 0; itemIdx < items.length; itemIdx++) for (let itemIdx = 0; itemIdx < items.length; itemIdx++)
{ $items.append(sax.populateItem(sax.getItemTemplate(), items[itemIdx]));
let item = items[itemIdx];
let $item = $tmpl.clone();
sax.populateItem($item, item);
$items.append($item);
}
$items.fadeIn(50); $items.fadeIn(50);
// Reference data.
if (response.userRoles && response.userRoles.length)
sax.data.userRoles = response.userRoles;
} }
sax.populateItem = function ($item, item) sax.populateItem = function ($item, item)
{ {
@@ -66,9 +63,44 @@
$('.UserLastName', $item).text(item.lastName); $('.UserLastName', $item).text(item.lastName);
$('.UserRoleCount', $item).text(item.userRoleCount); $('.UserRoleCount', $item).text(item.userRoleCount);
$('.StatusDesc', $item).text(item.statusDesc); $('.StatusDesc', $item).text(item.statusDesc);
$('.sax-caption .sax-action, .sax-actions .sax-item-update', $item).off('click').on('click', function () { sax.updateItem(item.id) }) $('.sax-caption .sax-action').toggleClass('sax-action', !item.deleted);
$item.off('dblclick').on('dblclick', function () { sax.updateItem(item.id) }) let $mnu = $('ul.sax-dropdown-menu', $item);
$('.sax-panel-results .sax-panel-messages').hide().empty(); if (!item.deleted)
{
$mnu.append(sax.getItemMenuOption(sax.lbl.edit, function () { sax.updateItem(item) }));
$('.sax-header .sax-action.sax-item-update', $item).off('click').on('click', function () { sax.updateItem(item) });
$item.off('dblclick').on('dblclick', function () { sax.updateItem(item) });
$mnu.append(sax.getItemMenuOption(sax.lbl.emails, function () { sax.userEmails(item) }));
}
$('.sax-burger', $item).toggle(!!$('.sax-dropdown-item', $mnu).length);
$('.sax-panel-messages', $pnl.results).hide().empty();
return $item;
}
//--------------------------------------------------------------
sax.getFilterDropdownTemplate = function ()
{
return $('.sax-panel-item-template .sax-dropdown-menu.UserFilter li.sax-dropdown-item', $pnl.filter).clone();
}
sax.getItemTemplate = function ()
{
return $('.sax-panel-item-template .sax-panel-item.User', $pnl.results).clone();
}
sax.getItemDropdownTemplate = function ()
{
return $('.sax-panel-item-template .sax-dropdown-menu.User li.sax-dropdown-item', $pnl.results).clone();
}
sax.getFilterMenuOption = function (lbl, fn)
{
return sax.getMenuOption(sax.getFilterDropdownTemplate(), lbl, fn);
}
sax.getItemMenuOption = function (lbl, fn)
{
return sax.getMenuOption(sax.getItemDropdownTemplate(), lbl, fn);
}
sax.getMenuOption = function ($opt, lbl, fn)
{
return $opt.find('div.sax-label').text(lbl).end().on('click', fn);
} }
//-------------------------------------------------------------- //--------------------------------------------------------------
@@ -104,91 +136,112 @@
//-------------------------------------------------------------- //--------------------------------------------------------------
sax.createItem = function () sax.createItem = function ()
{ {
let $frm = sax.$frm.user; let frm = $frm.user;
$('.UserAccountId,.UserRoleCodes,input[type="text"],textarea,select', $frm).val(''); $('.UserAccountId,.UserRoleCodes,input[type="text"],textarea,select', frm).val('');
$('.UserStatus', $frm).val(sax.data.defaultStatusCode); $('.UserStatus', frm).val(sax.data.defaultStatusCode);
sax.clearControlErrors(); sax.clearControlErrors();
sax.userAccount = { userRoleCodes: [] }; sax.userAccount = { userRoleCodes: [] };
sax.$dlg.user.dialog('option', 'title', sax.dlg.title.createUser); $dlg.user.dialog('option', 'title', sax.dlg.title.createUser);
sax.openDialog(sax.$dlg.user, 600, 600); sax.openDialog($dlg.user, 600, 600);
}
sax.doCreateItem = function ()
{
sax.storeItem();
} }
//-------------------------------------------------------------- //--------------------------------------------------------------
sax.updateItem = function (id) sax.updateItem = function (item)
{ {
$('.UserAccountId', sax.$frm.userId).val(id); $('.UserAccountId', $frm.userId).val(item.id);
sax.ajaxUpdateItem = sax.ajaxUpdateItem || { url: sax.url.base + 'User/Ajax/GetItem', formId: 'frmUserId', callbackFn: sax.onUpdateItem }; sax.ajax.updateItem = sax.ajax.updateItem || { url: sax.url.base + 'User/Ajax/GetItem', formId: 'frmUserId', callbackFn: sax.onUpdateItem };
sax.doAjaxRequest(sax.ajaxUpdateItem, 50); sax.doAjaxRequest(sax.ajax.updateItem, 50);
} }
sax.onUpdateItem = function (response) sax.onUpdateItem = function (response)
{ {
//sax.debug('onUpdateItem', response); //sax.debug('onUpdateItem', response);
let $frm = sax.$frm.user; let frm = $frm.user;
$('.UserAccountId,input[type="text"],textarea,select', $frm).val(''); $('.UserAccountId,input[type="text"],textarea,select', frm).val('');
sax.clearControlErrors(); sax.clearControlErrors();
if (!response.success) return; if (!response.success) return;
let item = sax.userAccount = response.user; let item = sax.userAccount = response.user;
$('.UserAccountId', $frm).val(item.id); $('.UserAccountId', frm).val(item.id);
$('.UserEmailAddress', $frm).val(item.emailAddress); $('.UserEmailAddress', frm).val(item.emailAddress);
$('.UserTitle', $frm).val(item.title); $('.UserTitle', frm).val(item.title);
$('.UserFirstName', $frm).val(item.firstName); $('.UserFirstName', frm).val(item.firstName);
$('.UserLastName', $frm).val(item.lastName); $('.UserLastName', frm).val(item.lastName);
$('.UserRoles', $frm).val(sax.getSelectedUserRoleDescs().join('\n')); $('.UserRoles', frm).val(sax.getSelectedUserRoleDescs().join('\n'));
$('#ifUserRoleCodes').val(item.userRoleCodes.join(sax.data.userRoleCodeDelim)); $('#ifUserRoleCodes').val(item.userRoleCodes.join(sax.data.userRoleCodeDelim));
$('.UserStatus', $frm).val(item.statusCode); $('.UserStatus', frm).val(item.statusCode);
sax.$dlg.user.dialog('option', 'title', sax.dlg.title.updateUser); $dlg.user.dialog('option', 'title', sax.dlg.title.updateUser);
sax.openDialog(sax.$dlg.user, 600, 600); sax.openDialog($dlg.user, 600, 600);
}
sax.doUpdateItem = function ()
{
sax.storeItem();
} }
//-------------------------------------------------------------- //--------------------------------------------------------------
sax.storeItem = function () sax.storeItem = function ()
{ {
sax.ajaxStoreItem = sax.ajaxStoreItem || { url: sax.url.base + 'User/Ajax/StoreItem', formId: 'frmUser', callbackFn: sax.onStoreItem }; sax.ajax.storeItem = sax.ajax.storeItem || { url: sax.url.base + 'User/Ajax/StoreItem', formId: 'frmUser', callbackFn: sax.onStoreItem };
sax.doAjaxRequest(sax.ajaxStoreItem, 50); sax.doAjaxRequest(sax.ajax.storeItem, 50);
} }
sax.onStoreItem = function (response) sax.onStoreItem = function (response)
{ {
//sax.debug('onStoreItem', response); //sax.debug('onStoreItem', response);
sax.refreshControlValues(response.controlValues); sax.refreshControlValues(response.controlValues);
if (!response.success) return; if (!response.success) return;
sax.$dlg.user.dialog('close'); $dlg.user.dialog('close');
var item = response.user; var item = response.user;
var $item = $('#' + sax.itemIdPrefix + item.id); var $item = $('#' + sax.itemIdPrefix + item.id);
if (!$item.length) if (!$item.length)
{ {
var $results = $('.sax-panel-results'); $item = sax.getItemTemplate();
$item = $('.sax-panel-item-template .sax-panel-item.User', $results).clone(); $('.sax-panel-item-list', $pnl.results).prepend($item).show();
$('.sax-panel-item-list', $results).prepend($item).show();
} }
sax.populateItem($item, item) $item.replaceWith(sax.populateItem(sax.getItemTemplate(), item));
}
//--------------------------------------------------------------
sax.userEmails = function (item)
{
sax.debug('userEmails', item);
let frm = $frm.emailsl
$('.UserAccountId', frm).val(item.id);
$('.UserEmailAddress', frm).val(item.emailAddress);
$('.UserDisplayName', frm).val(item.displayName);
$('.RequestPasswordAdminOption', frm).toggle(item.systemAdmin);
$('input[type="checkbox"]', frm).prop('checked', false);
$dlg.emails.dialog('option', { 'title': sax.dlg.title.selectUserEmails });
sax.openDialog($dlg.emails, 600, 600);
}
sax.sendUserEmails = function ()
{
sax.ajax.sendEmails = sax.ajax.sendEmails || { url: sax.url.base + 'User/Ajax/SendEmails', formId: 'frmUserEmails', callbackFn: sax.onUserEmails };
sax.doAjaxRequest(sax.ajax.sendEmails, 50);
}
sax.onUserEmails = function (response)
{
if (!response || !response.success) return;
$dlg.emails.dialog('close');
} }
//-------------------------------------------------------------- //--------------------------------------------------------------
$(function () $(function ()
{ {
$('.sax-action.sax-item-create').on('click', function () { sax.createItem(); }); $pnl.filter = $('.sax-panel-filter');
$('.sax-action.sax-results-refresh').on('click', function () { sax.refreshResults(); }); $pnl.results = $('.sax-panel-results');
$('.sax-input').on('input', function () { sax.clearControlError(this); });
$('.sax-select').on('click', function () { sax.clearControlError(this); });
sax.$frm.filter = $('#frmUserFilter'); $frm.filter = $('#frmUserFilter');
$('.FilterUser', sax.$frm.filter).on('input', function () { sax.refreshResults(250); }); $('.FilterUser', $frm.filter).on('input', function () { sax.refreshResults(250); });
sax.$frm.userId = $('#frmUserId'); $frm.userId = $('#frmUserId');
sax.$frm.user = $('#frmUser'); $frm.user = $('#frmUser');
$('.sax-input, .sax-textarea', $frm.user).on('input', function () { sax.clearControlError(this); });
$('.sax-select', $frm.user).on('change', function () { sax.clearControlError(this); });
$frm.emails = $('#frmUserEmails');
var opt = sax.dlgOpts(); var opt = sax.dlgOpts();
opt.buttons[sax.dlg.btn.ok] = function () { sax.doCreateItem(); }; opt.buttons[sax.dlg.btn.ok] = function () { sax.storeItem(); };
opt.buttons[sax.dlg.btn.cancel] = function () { $(this).dialog('close'); }; opt.buttons[sax.dlg.btn.cancel] = function () { $(this).dialog('close'); };
sax.$dlg.user = $('#dlgUser').dialog(opt); $dlg.user = $('#dlgUser').dialog(opt);
opt = sax.dlgOpts();
opt.buttons[sax.dlg.btn.ok] = function () { sax.sendUserEmails(); };
opt.buttons[sax.dlg.btn.cancel] = function () { $(this).dialog('close'); };
$dlg.emails = $('#dlgUserEmails').dialog(opt);
setTimeout(sax.refreshResults, 250); setTimeout(sax.refreshResults, 250);
}); });
@@ -159,6 +159,18 @@
<data name="activity.caption.activity" xml:space="preserve"> <data name="activity.caption.activity" xml:space="preserve">
<value>Activity</value> <value>Activity</value>
</data> </data>
<data name="article.caption.article" xml:space="preserve">
<value>Article</value>
</data>
<data name="article.caption.article.create" xml:space="preserve">
<value>Create Article</value>
</data>
<data name="article.caption.article.update" xml:space="preserve">
<value>Update Article</value>
</data>
<data name="article.caption.articles" xml:space="preserve">
<value>Articles</value>
</data>
<data name="company.name" xml:space="preserve"> <data name="company.name" xml:space="preserve">
<value>Solum Forti</value> <value>Solum Forti</value>
</data> </data>
@@ -198,18 +210,6 @@
<data name="home.organisation.request.para2" xml:space="preserve"> <data name="home.organisation.request.para2" xml:space="preserve">
<value>Sign-up now with a few details and we'll let you know when you can login and get going.</value> <value>Sign-up now with a few details and we'll let you know when you can login and get going.</value>
</data> </data>
<data name="journalist.caption.article" xml:space="preserve">
<value>Article</value>
</data>
<data name="journalist.caption.article.create" xml:space="preserve">
<value>Create Article</value>
</data>
<data name="journalist.caption.article.update" xml:space="preserve">
<value>Update Article</value>
</data>
<data name="journalist.caption.articles" xml:space="preserve">
<value>Articles</value>
</data>
<data name="label.account" xml:space="preserve"> <data name="label.account" xml:space="preserve">
<value>My Account</value> <value>My Account</value>
</data> </data>
@@ -88,10 +88,9 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
String messageTitle = Localiser["account.caption.profile.contact"]; String messageTitle = Localiser["account.caption.profile.contact"];
// Validate session and referrer. // Validate session and referrer.
if (!ValidReferer) if (!ValidReferer) return Forbid();
return Forbid(); if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
if (!ValidUserSession) RefreshModel(model);
return GetAjaxResult_InvalidSession(responseData);
// Retrieve user details. // Retrieve user details.
SaxUserAccount userAccount = AccountMgr.GetUserAccountById(SessionData.User.UserAccountId); SaxUserAccount userAccount = AccountMgr.GetUserAccountById(SessionData.User.UserAccountId);
@@ -140,10 +139,9 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
String messageTitle = Localiser["account.caption.profile.contact"]; String messageTitle = Localiser["account.caption.profile.contact"];
// Validate session and referrer. // Validate session and referrer.
if (!ValidReferer) if (!ValidReferer) return Forbid();
return Forbid(); if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
if (!ValidUserSession) RefreshModel(model);
return GetAjaxResult_InvalidSession(responseData);
// Validate number of images. // Validate number of images.
if (model.AccountContactImage.IsEmpty()) if (model.AccountContactImage.IsEmpty())
@@ -229,10 +227,9 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
String messageTitle = Localiser["account.caption.profile.contact"]; String messageTitle = Localiser["account.caption.profile.contact"];
// Validate session and referrer. // Validate session and referrer.
if (!ValidReferer) if (!ValidReferer) return Forbid();
return Forbid(); if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
if (!ValidUserSession) RefreshModel(model);
return GetAjaxResult_InvalidSession(responseData);
// Validate data. // Validate data.
model.ValidateContactDetails(responseData); model.ValidateContactDetails(responseData);
@@ -55,6 +55,7 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
// Validate session and referrer. // Validate session and referrer.
if (!ValidReferer) return Forbid(); if (!ValidReferer) return Forbid();
if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData); if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
RefreshModel(model);
// Query organisations that user is a member of. // Query organisations that user is a member of.
SaxUserOrganisation.Params prmUserOrganisation = new SaxUserOrganisation.Params(); SaxUserOrganisation.Params prmUserOrganisation = new SaxUserOrganisation.Params();
@@ -75,10 +75,9 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
String messageTitle = Localiser["account.caption.profile.sports"]; String messageTitle = Localiser["account.caption.profile.sports"];
// Validate session and referrer. // Validate session and referrer.
if (!ValidReferer) if (!ValidReferer) return Forbid();
return Forbid(); if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
if (!ValidUserSession) RefreshModel(model);
return GetAjaxResult_InvalidSession(responseData);
// Item filter. // Item filter.
SaxUserSport.Params prmUserSport = new SaxUserSport.Params(); SaxUserSport.Params prmUserSport = new SaxUserSport.Params();
@@ -153,10 +152,9 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
AjaxResponse_ProfileSport responseData = new AjaxResponse_ProfileSport(model); AjaxResponse_ProfileSport responseData = new AjaxResponse_ProfileSport(model);
// Validate session and referrer. // Validate session and referrer.
if (!ValidReferer) if (!ValidReferer) return Forbid();
return Forbid(); if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
if (!ValidUserSession) RefreshModel(model);
return GetAjaxResult_InvalidSession(responseData);
// Identify item. // Identify item.
SysId userSportId = model.UserSportId.ToSysId(); SysId userSportId = model.UserSportId.ToSysId();
@@ -197,10 +195,9 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
AjaxResponse_ProfileSport responseData = new AjaxResponse_ProfileSport(model); AjaxResponse_ProfileSport responseData = new AjaxResponse_ProfileSport(model);
// Validate session and referrer. // Validate session and referrer.
if (!ValidReferer) if (!ValidReferer) return Forbid();
return Forbid(); if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
if (!ValidUserSession) RefreshModel(model);
return GetAjaxResult_InvalidSession(responseData);
// Validate item properties. // Validate item properties.
model.ValidateProfileSportData(responseData); model.ValidateProfileSportData(responseData);
@@ -11,6 +11,7 @@ using Saxonite.Net.Core.Web.Online.Models;
using Saxonite.Net.Standard.Base.App; using Saxonite.Net.Standard.Base.App;
using Saxonite.Net.Standard.Base.Bus; using Saxonite.Net.Standard.Base.Bus;
using Saxonite.Net.Standard.Base.Consoles; using Saxonite.Net.Standard.Base.Consoles;
using Saxonite.Net.Standard.Base.Mgr;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@@ -49,16 +50,16 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
/// <summary>Article activity info. </summary> /// <summary>Article activity info. </summary>
private class ActivityResponseData_Article private class ActivityResponseData_Article
{ {
public ActivityResponseData_Article(SaxController_Online controller, SaxModel_Online model, SaxJournalistArticle article) public ActivityResponseData_Article(SaxController_Online controller, SaxModel_Online model, SaxArticle article)
{ {
Author = model.GetUserAccountDisplayName(article.UserAccountIdJournalist); Author = model.GetUserAccountDisplayName(article.UserAccountIdAuthor);
Headline = article.Headline; Headline = article.Headline;
Summary = article.Summary; Summary = article.Summary;
Sport = model.GetSportCaption(article.SportIdPrimary); Sport = model.GetSportCaption(article.SportIdPrimary);
Region = model.GetRegionCaption(article.RegionIdPrimary); Region = model.GetRegionCaption(article.RegionIdPrimary);
PublishedOnFmt = model.Localiser.FormatDate(article.PublishedAt); PublishedOnFmt = model.Localiser.FormatDate(article.PublishedAt);
SaxJournalistArticle.ContentData content = SaxJournalistArticle.ExtractContent(article.BodyData); SaxArticle.ContentData content = SaxArticle.ExtractContent(article.BodyData);
foreach (SaxJournalistArticle.ContentData.SegmentData segment in content.Segments) foreach (SaxArticle.ContentData.SegmentData segment in content.Segments)
Content.Segments.Add(new ContentData.SegmentData(controller, segment)); Content.Segments.Add(new ContentData.SegmentData(controller, segment));
} }
public String Organisation { get; set; } public String Organisation { get; set; }
@@ -72,7 +73,7 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
{ {
public class SegmentData public class SegmentData
{ {
public SegmentData(SaxController_Online controller, SaxJournalistArticle.ContentData.SegmentData segment) public SegmentData(SaxController_Online controller, SaxArticle.ContentData.SegmentData segment)
{ {
if (segment.Body.IsValid()) if (segment.Body.IsValid())
{ {
@@ -82,7 +83,7 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
else if (segment.Image.IsValid()) else if (segment.Image.IsValid())
{ {
Image = new ImageData(); Image = new ImageData();
Image.Link = JournalistController.GetArticleImageLink(controller, segment.Image.ItemImageId); Image.Link = ArticleController.GetArticleImageLink(controller, segment.Image.ItemImageId);
} }
} }
public class BodyData public class BodyData
@@ -140,10 +141,9 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
AjaxResponse_ActivityList responseData = new AjaxResponse_ActivityList(); AjaxResponse_ActivityList responseData = new AjaxResponse_ActivityList();
// Validate session and referrer. // Validate session and referrer.
if (!ValidReferer) if (!ValidReferer) return Forbid();
return Forbid(); if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
if (!ValidUserSession) RefreshModel(model);
return GetAjaxResult_InvalidSession(responseData);
SaxSessionData_Online sessionData = SessionData_Online; SaxSessionData_Online sessionData = SessionData_Online;
// User context. // User context.
@@ -167,12 +167,14 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
activityItemIds.Add(itemData.ItemId); activityItemIds.Add(itemData.ItemId);
ActivityResponseData activityData = new ActivityResponseData(); ActivityResponseData activityData = new ActivityResponseData();
activityData.ItemType = itemData.ItemId.Type; activityData.ItemType = itemData.ItemId.Type;
if (itemData.ItemId.Type == (int)Sax.DataItemType.JournalistArticle) if (itemData.ItemId.Type == (int)Sax.DataItemType.Article)
activityData.ItemTypeClass = "Article"; activityData.ItemTypeClass = "Article";
else if (itemData.ItemId.Type == (int)Sax.DataItemType.OrganisationOpportunity) else if (itemData.ItemId.Type == (int)Sax.DataItemType.OrganisationOpportunity)
activityData.ItemTypeClass = "Opportunity"; activityData.ItemTypeClass = "Opportunity";
// ToDo Mask activity index Id with cross-reference stored in session data. // ToDo Mask activity index Id with cross-reference stored in session data.
activityData.ItemIdx = SysId.ToLong(itemData.ItemId.Id); activityData.ItemIdx = SysId.ToLong(itemData.ItemId.Id);
activityData.Organisation = itemData.Organisation;
activityData.Author = itemData.Author;
activityData.Caption = itemData.Caption; activityData.Caption = itemData.Caption;
activityData.Blurb = itemData.Blurb; activityData.Blurb = itemData.Blurb;
activityData.Sport = Localiser.GetSportName(itemData.SportId, itemData.SportName); activityData.Sport = Localiser.GetSportName(itemData.SportId, itemData.SportName);
@@ -211,10 +213,9 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
AjaxResponse_ActivityInfo responseData = new AjaxResponse_ActivityInfo(); AjaxResponse_ActivityInfo responseData = new AjaxResponse_ActivityInfo();
// Validate session and referrer. // Validate session and referrer.
if (!ValidReferer) if (!ValidReferer) return Forbid();
return Forbid(); if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
if (!ValidUserSession) RefreshModel(model);
return GetAjaxResult_InvalidSession(responseData);
SaxSessionData_Online sessionData = SessionData_Online; SaxSessionData_Online sessionData = SessionData_Online;
// Identify activity. // Identify activity.
@@ -222,18 +223,18 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
SysId itemId = model.ActivityIdx.ToSysId(); SysId itemId = model.ActivityIdx.ToSysId();
if (itemType <= 0 || !SysId.IsValid(itemId)) if (itemType <= 0 || !SysId.IsValid(itemId))
{ {
SaLogger.Warn(fn + " Activity type/Id inncorrectly specified." + getLogSuffix()); SaLogger.Warn(fn + " Activity type/Id inncorrectly specified." + GetLogSuffix());
return Json(responseData); return Json(responseData);
} }
// Retrieve activity details. // Retrieve activity details.
if (itemType == Sax.DataItemType.JournalistArticle) if (itemType == Sax.DataItemType.Article)
{ {
// Journalist article. // Article.
SaxJournalistArticle article = ActivityMgr.GetJournalistArticleById(itemId); SaxArticle article = ActivityMgr.GetArticleById(itemId);
if (article == null) if (article == null)
{ {
SaLogger.Warn(fn + " Article not found for Activity Id: " + itemId.ToString() + "." + getLogSuffix()); SaLogger.Warn(fn + " Article not found for Activity Id: " + itemId.ToString() + "." + GetLogSuffix());
return Json(responseData); return Json(responseData);
} }
responseData.Article = new ActivityResponseData_Article(this, model, article); responseData.Article = new ActivityResponseData_Article(this, model, article);
@@ -244,7 +245,7 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
SaxOrganisationOpportunity opportunity = ActivityMgr.GetOrganisationOpportunityById(itemId); SaxOrganisationOpportunity opportunity = ActivityMgr.GetOrganisationOpportunityById(itemId);
if (opportunity == null) if (opportunity == null)
{ {
SaLogger.Warn(fn + " Opportunity not found for Activity Id: " + itemId.ToString() + "." + getLogSuffix()); SaLogger.Warn(fn + " Opportunity not found for Activity Id: " + itemId.ToString() + "." + GetLogSuffix());
return Json(responseData); return Json(responseData);
} }
responseData.Opportunity = new ActivityResponseData_Opportunity(model, opportunity); responseData.Opportunity = new ActivityResponseData_Opportunity(model, opportunity);
@@ -253,7 +254,7 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
// Record activty viewing. // Record activty viewing.
if (!ActivityConsole.RecordUserActivityViewed(SessionData.User.UserAccountId, new ItemId((short)itemType, itemId), DbUpdateInfo)) if (!ActivityConsole.RecordUserActivityViewed(SessionData.User.UserAccountId, new ItemId((short)itemType, itemId), DbUpdateInfo))
{ {
SaLogger.Warn(fn + " Failed to record Activity Viewing: " + ActivityConsole.ErrorStateMessage + "." + getLogSuffix()); SaLogger.Warn(fn + " Failed to record Activity Viewing: " + ActivityConsole.ErrorStateMessage + "." + GetLogSuffix());
return Json(responseData); return Json(responseData);
} }
@@ -280,10 +281,9 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
AjaxResponse_ActivityReaction responseData = new AjaxResponse_ActivityReaction(); AjaxResponse_ActivityReaction responseData = new AjaxResponse_ActivityReaction();
// Validate session and referrer. // Validate session and referrer.
if (!ValidReferer) if (!ValidReferer) return Forbid();
return Forbid(); if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
if (!ValidUserSession) RefreshModel(model);
return GetAjaxResult_InvalidSession(responseData);
SaxSessionData_Online sessionData = SessionData_Online; SaxSessionData_Online sessionData = SessionData_Online;
// Identify activity. // Identify activity.
@@ -291,14 +291,14 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
SysId itemId = model.ActivityIdx.ToSysId(); SysId itemId = model.ActivityIdx.ToSysId();
if (itemType <= 0 || !SysId.IsValid(itemId)) if (itemType <= 0 || !SysId.IsValid(itemId))
{ {
SaLogger.Warn(fn + " Activity type/Id inncorrectly specified." + getLogSuffix()); SaLogger.Warn(fn + " Activity type/Id inncorrectly specified." + GetLogSuffix());
return Json(responseData); return Json(responseData);
} }
// Record activity reaction. // Record activity reaction.
if (!ActivityConsole.RecordUserActivityReaction(SessionData.User.UserAccountId, new ItemId((short)itemType, itemId), model.GetActivityReaction(), DbUpdateInfo)) if (!ActivityConsole.RecordUserActivityReaction(SessionData.User.UserAccountId, new ItemId((short)itemType, itemId), model.GetActivityReaction(), DbUpdateInfo))
{ {
SaLogger.Warn(fn + " Failed to record Activity Reaction: " + ActivityConsole.ErrorStateMessage + "." + getLogSuffix()); SaLogger.Warn(fn + " Failed to record Activity Reaction: " + ActivityConsole.ErrorStateMessage + "." + GetLogSuffix());
return Json(responseData); return Json(responseData);
} }
@@ -11,6 +11,7 @@ using Saxonite.Net.Core.Web.Online.Models;
using Saxonite.Net.Standard.Base.App; using Saxonite.Net.Standard.Base.App;
using Saxonite.Net.Standard.Base.Bus; using Saxonite.Net.Standard.Base.Bus;
using Saxonite.Net.Standard.Base.Consoles; using Saxonite.Net.Standard.Base.Consoles;
using Saxonite.Net.Standard.Base.Mgr;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Specialized; using System.Collections.Specialized;
@@ -21,12 +22,12 @@ using System.Threading.Tasks;
namespace Saxonite.Net.Core.Web.Online.Controllers namespace Saxonite.Net.Core.Web.Online.Controllers
{ {
//======================================================================= //=======================================================================
// Online Journalist Controller - Ajax actions. // Online Article Controller - Ajax actions.
//======================================================================= //=======================================================================
partial class JournalistController partial class ArticleController
{ {
//------------------------------------------------------------------- //-------------------------------------------------------------------
// Journalist Article Content data. // Article Content data.
private class ArticleContentData private class ArticleContentData
{ {
public List<ArticleContentSegmentData> Segments { get; } = new List<ArticleContentSegmentData>(); public List<ArticleContentSegmentData> Segments { get; } = new List<ArticleContentSegmentData>();
@@ -48,10 +49,11 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
} }
//------------------------------------------------------------------- //-------------------------------------------------------------------
// Journalist Article data. // Article data.
private class ArticleData_List private class ArticleData_List
{ {
public String Id { get; set; } public String Id { get; set; }
public String OrganisationId { get; set; }
public String Headline { get; set; } public String Headline { get; set; }
public String Summary { get; set; } public String Summary { get; set; }
public String RegionCaptionPrimary { get; set; } public String RegionCaptionPrimary { get; set; }
@@ -70,9 +72,10 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
public String PublishedOn_Calendar { get; set; } public String PublishedOn_Calendar { get; set; }
public ArticleContentData Content { get; } = new ArticleContentData(); public ArticleContentData Content { get; } = new ArticleContentData();
} }
private void PopulateArticleResponseData(Model_Journalist model, SaxJournalistArticle article, ArticleData_List data) private void PopulateArticleResponseData(Model_Article model, SaxArticle article, ArticleData_List data)
{ {
data.Id = SysId.ToString(article.Id); data.Id = SysId.ToString(article.Id);
data.OrganisationId = SysId.ToString(article.OrganisationId);
data.Headline = article.Headline; data.Headline = article.Headline;
data.Summary = article.Summary; data.Summary = article.Summary;
data.RegionCaptionPrimary = model.GetRegionCaption(article.RegionIdPrimary); data.RegionCaptionPrimary = model.GetRegionCaption(article.RegionIdPrimary);
@@ -82,7 +85,7 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
data.StatusCode = article.StatusCode; data.StatusCode = article.StatusCode;
data.StatusDesc = article.StatusDesc; data.StatusDesc = article.StatusDesc;
} }
private void PopulateArticleResponseData(Model_Journalist model, SaxJournalistArticle article, ArticleData_Full data) private void PopulateArticleResponseData(Model_Article model, SaxArticle article, ArticleData_Full data)
{ {
PopulateArticleResponseData(model, article, data as ArticleData_List); PopulateArticleResponseData(model, article, data as ArticleData_List);
data.RegionIdPrimary = SysId.ToString(article.RegionIdPrimary); data.RegionIdPrimary = SysId.ToString(article.RegionIdPrimary);
@@ -92,7 +95,7 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
data.PublishedOn_Calendar = model.FormatDateForForm(article.PublishedAt); data.PublishedOn_Calendar = model.FormatDateForForm(article.PublishedAt);
// Article content. // Article content.
SaxJournalistArticle.ContentData articleContent = SaxJournalistArticle.ExtractContent(article.BodyData); SaxArticle.ContentData articleContent = SaxArticle.ExtractContent(article.BodyData);
foreach (var contentSegment in articleContent.Segments) foreach (var contentSegment in articleContent.Segments)
{ {
var segmentData = new ArticleContentSegmentData(); var segmentData = new ArticleContentSegmentData();
@@ -114,48 +117,83 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
//------------------------------------------------------------------- //-------------------------------------------------------------------
// Get Article List ajax request. // Get Article List ajax request.
//------------------------------------------------------------------- //-------------------------------------------------------------------
private class OrganisationData : AjaxResponse_Data.ItemIdName { }
private class AjaxResponse_ArticleList : AjaxResponse_Data private class AjaxResponse_ArticleList : AjaxResponse_Data
{ {
// Construction. // Construction.
public AjaxResponse_ArticleList(SaxModel_Online model) : base(model) { } public AjaxResponse_ArticleList(SaxModel_Online model) : base(model) { }
// Article list. // Article list.
public List<ArticleData_List> Articles { get; } = new List<ArticleData_List>(); 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; }
} }
//------------------------------------------------------------------- //-------------------------------------------------------------------
[HttpPost] [HttpPost]
[Route("Journalist/Ajax/GetArticleList")] [Route("Article/Ajax/GetList")]
public IActionResult Ajax_GetArticleList(Model_Journalist model) [Route("Article/Ajax/GetArticles")]
public IActionResult Ajax_GetArticleList(Model_Article model)
{ {
String fn = GetType().Name + ".Ajax_GetArticleList"; String fn = GetType().Name + ".Ajax_GetArticleList";
String messageTitle = Localiser["journalist.caption.articles"]; String messageTitle = Localiser["article.caption.articles"];
AjaxResponse_ArticleList responseData = new AjaxResponse_ArticleList(model); AjaxResponse_ArticleList responseData = new AjaxResponse_ArticleList(model);
// Validate session and referrer. // Validate session and referrer.
if (!ValidReferer) return Forbid(); if (!ValidReferer) return Forbid();
if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData); if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
if (!UserIsJournalist) return GetAjaxResult_GoHome(responseData);
SaxSessionData_Online sessionData = SessionData_Online; SaxSessionData_Online sessionData = SessionData_Online;
SysId userAccountId = SessionData.User.UserAccountId;
RefreshModel(model);
// Organisations that the user has rights to author articles for.
foreach (SaxAccountMgr.OrganisationIdName organisation in AccountMgr.GetOrganisationsForUserRole(userAccountId, Sax.OrganisationRole.ArticleAdmin))
{
if (responseData.Organisations == null) responseData.Organisations = new List<OrganisationData>();
OrganisationData organisationData = new OrganisationData()
{
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. // Item filter.
SaxJournalistArticle.Params prmArticle = new SaxJournalistArticle.Params(); SaxArticle.Params prmArticle = new SaxArticle.Params();
prmArticle.UserAccountIdsJournalistIncluded.Add(sessionData.User.UserAccountId); prmArticle.UserAccountIdsAuthorIncluded.Add(sessionData.User.UserAccountId);
if (SysId.IsValid(organisationIdFilter))
prmArticle.OrganisationIdsIncluded.Add(organisationIdFilter);
prmArticle.ArticleFilter = model.Filter.Article; prmArticle.ArticleFilter = model.Filter.Article;
prmArticle.StatusCat = SaxJournalistArticle.StatusCat.NotDeleted; prmArticle.StatusCat = SaxArticle.StatusCat.NotDeleted;
model.Paging.ItemTotal = (ulong)ActivityMgr.GetJournalistArticleCount(prmArticle); model.Paging.ItemTotal = (ulong)ActivityMgr.GetArticleCount(prmArticle);
model.PopulatePagingTo(prmArticle.ResultsPaging); model.PopulatePagingTo(prmArticle.ResultsPaging);
// Item columns. // Item columns.
ColumnDfn colId = ActivityMgr.GetJournalistArticleColumnDfn(SaxJournalistArticle.Column.Id); ColumnDfn colId = ActivityMgr.GetArticleColumnDfn(SaxArticle.Column.Id);
ColumnDfn colHeadline = ActivityMgr.GetJournalistArticleColumnDfn(SaxJournalistArticle.Column.Headline); ColumnDfn colOrganisationId = ActivityMgr.GetArticleColumnDfn(SaxArticle.Column.OrganisationId);
ColumnDfn colSummary = ActivityMgr.GetJournalistArticleColumnDfn(SaxJournalistArticle.Column.Summary); ColumnDfn colHeadline = ActivityMgr.GetArticleColumnDfn(SaxArticle.Column.Headline);
ColumnDfn colRegionIdPrimary = ActivityMgr.GetJournalistArticleColumnDfn(SaxJournalistArticle.Column.RegionIdPrimary); ColumnDfn colSummary = ActivityMgr.GetArticleColumnDfn(SaxArticle.Column.Summary);
ColumnDfn colSportIdPrimary = ActivityMgr.GetJournalistArticleColumnDfn(SaxJournalistArticle.Column.SportIdPrimary); ColumnDfn colRegionIdPrimary = ActivityMgr.GetArticleColumnDfn(SaxArticle.Column.RegionIdPrimary);
ColumnDfn colPublishedOn = ActivityMgr.GetJournalistArticleColumnDfn(SaxJournalistArticle.Column.PublishedAt_Date); ColumnDfn colSportIdPrimary = ActivityMgr.GetArticleColumnDfn(SaxArticle.Column.SportIdPrimary);
ColumnDfn colStatus = ActivityMgr.GetJournalistArticleColumnDfn(SaxJournalistArticle.Column.Status); ColumnDfn colPublishedOn = ActivityMgr.GetArticleColumnDfn(SaxArticle.Column.PublishedAt_Date);
ColumnDfn colCreatedOn = ActivityMgr.GetJournalistArticleColumnDfn(SaxJournalistArticle.Column.CreateOn_Date); ColumnDfn colStatus = ActivityMgr.GetArticleColumnDfn(SaxArticle.Column.Status);
ColumnDfn colCreatedOn = ActivityMgr.GetArticleColumnDfn(SaxArticle.Column.CreateOn_Date);
List<ColumnDfn> columns = new List<ColumnDfn>() List<ColumnDfn> columns = new List<ColumnDfn>()
{ {
colId, colHeadline, colSummary, colId, colOrganisationId, colHeadline, colSummary,
colRegionIdPrimary, colSportIdPrimary, colPublishedOn, colRegionIdPrimary, colSportIdPrimary, colPublishedOn,
colStatus, colCreatedOn colStatus, colCreatedOn
}; };
@@ -165,7 +203,7 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
prmArticle.SortColumns.Add(colCreatedOn); prmArticle.SortColumns.Add(colCreatedOn);
// Query items. // Query items.
using (DbResultSet resultSet = ActivityMgr.ExecuteJournalistArticleQuery(columns, prmArticle)) using (DbResultSet resultSet = ActivityMgr.ExecuteArticleQuery(columns, prmArticle))
{ {
while (resultSet != null && resultSet.HasRows && resultSet.NextRecord()) while (resultSet != null && resultSet.HasRows && resultSet.NextRecord())
{ {
@@ -173,6 +211,7 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
ArticleData_List articleData = new ArticleData_List() ArticleData_List articleData = new ArticleData_List()
{ {
Id = values.GetString(colId.DataName), Id = values.GetString(colId.DataName),
OrganisationId = values.GetString(colOrganisationId.DataName),
Headline = values.GetString(colHeadline.DataName), Headline = values.GetString(colHeadline.DataName),
Summary = values.GetString(colSummary.DataName), Summary = values.GetString(colSummary.DataName),
RegionCaptionPrimary = model.GetRegionCaption(values.GetString(colRegionIdPrimary.DataName).ToSysId()), RegionCaptionPrimary = model.GetRegionCaption(values.GetString(colRegionIdPrimary.DataName).ToSysId()),
@@ -206,20 +245,20 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
} }
//------------------------------------------------------------------- //-------------------------------------------------------------------
[HttpPost] [HttpPost]
[Route("Journalist/Ajax/GetArticle")] [Route("Article/Ajax/Get")]
public IActionResult Ajax_GetArticle(Model_Journalist model) [Route("Article/Ajax/GetItem")]
[Route("Article/Ajax/GetArticle")]
public IActionResult Ajax_GetArticle(Model_Article model)
{ {
String fn = GetType().Name + ".Ajax_GetArticle"; String fn = GetType().Name + ".Ajax_GetArticle";
String messageTitle = Localiser["journalist.caption.article"]; String messageTitle = Localiser["article.caption.article"];
AjaxResponse_Article responseData = new AjaxResponse_Article(model); AjaxResponse_Article responseData = new AjaxResponse_Article(model);
// Validate session and referrer. // Validate session and referrer.
if (!ValidReferer) if (!ValidReferer) return Forbid();
return Forbid(); if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
if (!ValidUserSession) SysId userAccountId = SessionData.User.UserAccountId;
return GetAjaxResult_InvalidSession(responseData); RefreshModel(model);
if (!UserIsJournalist)
return GetAjaxResult_GoHome(responseData);
// Identify item. // Identify item.
SysId articleId = model.ArticleId.ToSysId(); SysId articleId = model.ArticleId.ToSysId();
@@ -227,16 +266,21 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.specified"])); return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.specified"]));
// Retrieve item. // Retrieve item.
SaxJournalistArticle article = ActivityMgr.GetJournalistArticleById(articleId); SaxArticle article = ActivityMgr.GetArticleById(articleId);
if (article == null) if (article == null)
{ {
SaLogger.Warn(fn + " Failed to retrieve Journalist Article for Id: '" + model.ArticleId + "'"); SaLogger.Warn(fn + " Failed to retrieve Article for Id: '" + model.ArticleId + "'");
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"])); 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. // Delete upload images.
SaxItemImage.Params prmItemImage = new SaxItemImage.Params(); SaxItemImage.Params prmItemImage = new SaxItemImage.Params();
prmItemImage.ItemIdsIncluded.Add(new ItemId((short)Sax.DataItemType.JournalistArticle, articleId)); prmItemImage.ItemIdsIncluded.Add(new ItemId((short)Sax.DataItemType.Article, articleId));
prmItemImage.ImageTypesIncluded.Add(Sax.ImageType.ArticleUpload); prmItemImage.ImageTypesIncluded.Add(Sax.ImageType.ArticleUpload);
prmItemImage.StatusCat = SaxItemImage.StatusCat.NotDeleted; prmItemImage.StatusCat = SaxItemImage.StatusCat.NotDeleted;
foreach (SaxItemImage itemImage in ItemDataMgr.GetItemImageList(prmItemImage)) foreach (SaxItemImage itemImage in ItemDataMgr.GetItemImageList(prmItemImage))
@@ -254,7 +298,7 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
} }
//------------------------------------------------------------------- //-------------------------------------------------------------------
// Journalist - Upload Article Image. // Article - Upload Image.
//------------------------------------------------------------------- //-------------------------------------------------------------------
private class AjaxResponse_UploadArticleImage : AjaxResponse_Data private class AjaxResponse_UploadArticleImage : AjaxResponse_Data
{ {
@@ -266,17 +310,18 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
} }
// Ajax request. // Ajax request.
[HttpPost] [HttpPost]
[Route("Journalist/Ajax/UploadArticleImage")] [Route("Article/Ajax/UploadImage")]
public IActionResult UploadArticleImage(Model_Journalist model) public IActionResult UploadArticleImage(Model_Article model)
{ {
String fn = GetType().Name + ".UploadArticleImage"; String fn = GetType().Name + ".UploadArticleImage";
AjaxResponse_UploadArticleImage responseData = new AjaxResponse_UploadArticleImage(model); AjaxResponse_UploadArticleImage responseData = new AjaxResponse_UploadArticleImage(model);
String messageTitle = Localiser["journalist.caption.article"]; String messageTitle = Localiser["article.caption.article"];
// Validate session and referrer. // Validate session and referrer.
if (!ValidReferer) return Forbid(); if (!ValidReferer) return Forbid();
if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData); if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
SaxSessionData_Online sessionData = SessionData_Online; SaxSessionData_Online sessionData = SessionData_Online;
RefreshModel(model);
// Validate number of images. // Validate number of images.
if (model.ArticleImage.IsEmpty()) if (model.ArticleImage.IsEmpty())
@@ -307,7 +352,7 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
// Image belongs to the article. // 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. // If the article doesn't yet exist, it will need to be uploaded to the user first and later transferred.
SysId articleId = model.ArticleId.ToSysId(); SysId articleId = model.ArticleId.ToSysId();
ItemId articleItemId = new ItemId((short)Sax.DataItemType.JournalistArticle, articleId); ItemId articleItemId = new ItemId((short)Sax.DataItemType.Article, articleId);
ItemId userItemId = new ItemId((short)Sax.DataItemType.UserAccount, sessionData.User.UserAccountId); ItemId userItemId = new ItemId((short)Sax.DataItemType.UserAccount, sessionData.User.UserAccountId);
ItemId imageItemId = SysId.IsValid(articleId) ? articleItemId : userItemId; ItemId imageItemId = SysId.IsValid(articleId) ? articleItemId : userItemId;
@@ -369,35 +414,59 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
} }
public static String GetArticleImageLink(SaxController_Online controller, SysId itemImageId) public static String GetArticleImageLink(SaxController_Online controller, SysId itemImageId)
{ {
String imageLink = "Image/Journalist/Article?"; String imageLink = "Image/Article?";
NameValueCollection parameters = new NameValueCollection(); NameValueCollection parameters = new NameValueCollection();
parameters.Add(ImageController.ParamName_ItemImageId, SysId.ToString(itemImageId)); parameters.Add(ImageController.ParamName_ItemImageId, SysId.ToString(itemImageId));
return imageLink + ImageController.ParamName_JournalistArticleImageEncrypted + "=" + SaxController_Online.EncryptOnlineParams(controller, parameters); return imageLink + ImageController.ParamName_ArticleImageEncrypted + "=" + SaxController_Online.EncryptOnlineParams(controller, parameters);
} }
//------------------------------------------------------------------- //-------------------------------------------------------------------
// Store Article ajax request. // Store Article ajax request.
//------------------------------------------------------------------- //-------------------------------------------------------------------
[HttpPost] [HttpPost]
[Route("Journalist/Ajax/StoreArticle")] [Route("Article/Ajax/Store")]
public IActionResult Ajax_StoreArticle(Model_Journalist model) [Route("Article/Ajax/StoreItem")]
[Route("Article/Ajax/StoreArticle")]
public IActionResult Ajax_StoreArticle(Model_Article model)
{ {
String fn = GetType().Name + ".Ajax_StoreArticle"; String fn = GetType().Name + ".Ajax_StoreArticle";
String messageTitle = Localiser["journalist.caption.article"]; String messageTitle = Localiser["article.caption.article"];
AjaxResponse_Article responseData = new AjaxResponse_Article(model); AjaxResponse_Article responseData = new AjaxResponse_Article(model);
// Validate session and referrer. // Validate session and referrer.
if (!ValidReferer) return Forbid(); if (!ValidReferer) return Forbid();
if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData); if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
if (!UserIsJournalist) return GetAjaxResult_GoHome(responseData);
SaxSessionData_Online sessionData = SessionData_Online; SaxSessionData_Online sessionData = SessionData_Online;
RefreshModel(model);
// Validate item properties. // Validate item properties.
model.ValidateArticleData(responseData); model.ValidateArticleData(responseData);
if (responseData.HasControlErrors()) if (responseData.HasControlErrors())
return Json(responseData); return Json(responseData);
// Validate Article against Id against 'Exists' flag. // Validate User & Organisation.
SysId userAccountId = SessionData.User.UserAccountId;
SysId organisationId = model.ExtractSysId(model.ArticleOrganisationId);
if (SysId.IsValid(organisationId))
{
// Organisation specified - User must have Article Admin role.
if (!AccountMgr.UserHasOrganisationRole(userAccountId, organisationId, 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"]));
}
}
else
{
// Organisation not specified - User must be a Journalist.
if (!UserIsJournalist)
{
SaLogger.Warn(fn + " User is not a Journalist for non-organisation article." + GetLogSuffix());
return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"]));
}
}
// Validate item Id against 'Exists' flag.
SysId articleId = model.ArticleId.ToSysId(); SysId articleId = model.ArticleId.ToSysId();
bool articleExists = StringUtil.ToBool(model.ArticleExists); bool articleExists = StringUtil.ToBool(model.ArticleExists);
if (articleExists && !SysId.IsValid(articleId)) if (articleExists && !SysId.IsValid(articleId))
@@ -412,16 +481,30 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
} }
// Retrieve existing item. // Retrieve existing item.
SaxJournalistArticle article = ActivityMgr.GetJournalistArticleById(articleId); SaxArticle article = ActivityMgr.GetArticleById(articleId);
if (article == null && SysId.IsValid(articleId)) if (article == null && SysId.IsValid(articleId))
{ {
SaLogger.Warn(fn + " Failed to retrieve article for Id: '" + model.ArticleId + "'"); SaLogger.Warn(fn + " Failed to retrieve article for Id: '" + model.ArticleId + "'");
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"])); return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.id.not.found"]));
} }
if (article != null)
{
// Validate existing article.
if (SysId.ToLong(article.UserAccountIdAuthor) != SysId.ToLong(userAccountId))
{
SaLogger.Warn(fn + " Inconsistent Article Author." + GetLogSuffix());
return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"]));
}
if (SysId.ToLong(article.OrganisationId) != SysId.ToLong(organisationId))
{
SaLogger.Warn(fn + " Inconsistent Article Organisation." + GetLogSuffix());
return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"]));
}
}
// Create new item if required. // Create new item if required.
if (article == null) if (article == null)
article = ActivityMgr.CreateJournalistArticle(sessionData.User.UserAccountId); article = ActivityMgr.CreateArticle(sessionData.User.UserAccountId, organisationId);
// Populate item properties. // Populate item properties.
if (model.ArticleRegionId != null) if (model.ArticleRegionId != null)
@@ -451,7 +534,7 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
// If Article doesn't yet exist, create it now so that images can be assigned. // If Article doesn't yet exist, create it now so that images can be assigned.
if (!SysId.IsValid(article.Id)) if (!SysId.IsValid(article.Id))
{ {
if (!ActivityMgr.InsertJournalistArticle(article, DbUpdateInfo)) if (!ActivityMgr.InsertArticle(article, DbUpdateInfo))
{ {
SaLogger.Warn(fn + " Failed to insert article: " + ActivityMgr.ErrorStateMessage); SaLogger.Warn(fn + " Failed to insert article: " + ActivityMgr.ErrorStateMessage);
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.insert.failed"])); return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.insert.failed"]));
@@ -461,7 +544,7 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
// Content. // Content.
if (model.ArticleContentSegmentBodies != null) if (model.ArticleContentSegmentBodies != null)
{ {
SaxJournalistArticle.ContentData articleContent = new SaxJournalistArticle.ContentData(); SaxArticle.ContentData articleContent = new SaxArticle.ContentData();
for (int segmentIdx = 0; segmentIdx < model.ArticleContentSegmentBodies.Count; segmentIdx++) for (int segmentIdx = 0; segmentIdx < model.ArticleContentSegmentBodies.Count; segmentIdx++)
{ {
String segmentBody = model.ArticleContentSegmentBodies[segmentIdx]; String segmentBody = model.ArticleContentSegmentBodies[segmentIdx];
@@ -505,11 +588,11 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
SaLogger.Warn(fn + " Failed to identify article image. ItemImageId: " + itemImageId.ToInt() + ". SessionIdx: " + sessionData.SessionIdx + ". ImageIdx: " + imageIdx + "."); SaLogger.Warn(fn + " Failed to identify article image. ItemImageId: " + itemImageId.ToInt() + ". SessionIdx: " + sessionData.SessionIdx + ". ImageIdx: " + imageIdx + ".");
} }
} }
article.BodyData = SaxJournalistArticle.GetContentData(articleContent); article.BodyData = SaxArticle.GetContentData(articleContent);
} }
// Update the Article. // Update the Article.
if (!ActivityMgr.UpdateJournalistArticle(article, DbUpdateInfo)) if (!ActivityMgr.UpdateArticle(article, DbUpdateInfo))
{ {
SaLogger.Warn(fn + " Failed to update article [Id:" + SysId.ToString(article.Id) + "]: " + ActivityMgr.ErrorStateMessage); SaLogger.Warn(fn + " Failed to update article [Id:" + SysId.ToString(article.Id) + "]: " + ActivityMgr.ErrorStateMessage);
return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.update.failed"])); return Json(responseData.SetMessage(messageTitle, Localiser["msg.error.item.update.failed"]));
@@ -1,7 +1,11 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Sarand.Net.Standard.Base.Bus;
using Saxonite.Net.Core.Web.Base.App; using Saxonite.Net.Core.Web.Base.App;
using Saxonite.Net.Core.Web.Online.Models; using Saxonite.Net.Core.Web.Online.Models;
using Saxonite.Net.Standard.Base.App;
using Saxonite.Net.Standard.Base.Bus;
using Saxonite.Net.Standard.Base.Mgr;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@@ -12,11 +16,11 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
//======================================================================= //=======================================================================
// Online Journalist Controller. // Online Journalist Controller.
//======================================================================= //=======================================================================
public partial class JournalistController : SaxController_Online public partial class ArticleController : SaxController_Online
{ {
//------------------------------------------------------------------- //-------------------------------------------------------------------
// Construction. // Construction.
public JournalistController(SaxLocaliser localiser, ILogger<HomeController> logger) : public ArticleController(SaxLocaliser localiser, ILogger<HomeController> logger) :
base(localiser, logger) base(localiser, logger)
{ {
} }
@@ -26,25 +30,24 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
public IActionResult Index() public IActionResult Index()
{ {
// Validate session. // Validate session.
if (!ValidUserSession || !UserIsJournalist) if (!ValidUserSession)
return RedirectToAction("", ""); return RedirectToAction("", "");
// No 'Index' view as yet - default to 'Articles' view. // User must either be a Journalist or have Article Admin rights with at least one organisation.
//Model_Journalist model = new Model_Journalist(Localiser); List<SaxAccountMgr.OrganisationIdName> organisations = AccountMgr.GetOrganisationsForUserRole(SessionData.User.UserAccountId, Sax.OrganisationRole.ArticleAdmin);
//return View(model); if (organisations.Count < 1 && !UserIsJournalist)
return RedirectToAction("Articles", "Journalist");
}
//-------------------------------------------------------------------
[HttpGet]
public IActionResult Articles()
{
// Validate session.
if (!ValidUserSession || !UserIsJournalist)
return RedirectToAction("", ""); return RedirectToAction("", "");
// Paging. // Model.
Model_Journalist model = new Model_Journalist(Localiser); Model_Article model = new Model_Article(Localiser);
model.UserCanAuthorOrganisationArticles = organisations.Count > 0;
model.UserCanAuthorJournalistArticles = UserIsJournalist;
if (organisations.Count > 0)
{
// Default filter to first organisation.
model.Filter.OrganisationId = model.EncryptId(organisations[0].Id);
model.Filter.OrganisationCaption = organisations[0].Name;
}
model.Paging.PageNo = 1; model.Paging.PageNo = 1;
model.Paging.PageLength = 6; model.Paging.PageLength = 6;
@@ -92,10 +92,8 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
String fn = GetType().Name + ".GetAccountContactImage"; String fn = GetType().Name + ".GetAccountContactImage";
// Validate session and referrer. // Validate session and referrer.
if (!ValidReferer) if (!ValidReferer) return Forbid();
return Forbid(); if (!ValidUserSession) return Forbid();
if (!ValidUserSession)
return Forbid();
ItemId userItemId = new ItemId((short)Sax.DataItemType.UserAccount, userAccountId); ItemId userItemId = new ItemId((short)Sax.DataItemType.UserAccount, userAccountId);
// Retrieve account contact images. // Retrieve account contact images.
@@ -120,28 +118,29 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
} }
//------------------------------------------------------------------- //-------------------------------------------------------------------
// Journalist Article image // Article image
//------------------------------------------------------------------- //-------------------------------------------------------------------
public static String ParamName_JournalistArticleImageEncrypted { get; } = "jaie"; public static String ParamName_ArticleImageEncrypted { get; } = "aie";
public static String ParamName_ItemImageId { get; } = "iii"; public static String ParamName_ItemImageId { get; } = "iii";
/// <summary> /// <summary>
/// Get the specified Journalist Article Image. /// Get the specified Article Image.
/// <para>Method parameter name (aie) must match name of encrypted parameter.</para>
/// <para>Encrypted parameters:</para> /// <para>Encrypted parameters:</para>
/// <para>- iii: item Image Id.</para> /// <para>- iii: item Image Id.</para>
/// </summary> /// </summary>
[HttpGet] [HttpGet]
[Route("Image/Journalist/Article")] [Route("Image/Article")]
public IActionResult GetJournalistArticleImage(String jaie) public IActionResult GetArticleImage(String aie)
{ {
String fn = GetType().Name + ".GetJournalistArticleImage"; String fn = GetType().Name + ".GetArticleImage";
// Validate session and referrer. // Validate session and referrer.
if (!ValidReferer) return Forbid(); if (!ValidReferer) return Forbid();
if (!ValidUserSession) return Forbid(); if (!ValidUserSession) return Forbid();
ItemId userItemId = new ItemId((short)Sax.DataItemType.UserAccount, SessionData.User.UserAccountId); ItemId userItemId = new ItemId((short)Sax.DataItemType.UserAccount, SessionData.User.UserAccountId);
// EXtract encrypted parameters. // Extract encrypted parameters.
NameValueCollection parameters = ExtractOnlineParams(jaie); NameValueCollection parameters = ExtractOnlineParams(aie);
if (parameters.Count<1) return Forbid(); if (parameters.Count<1) return Forbid();
// Item Image. // Item Image.
@@ -102,6 +102,7 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
// Validate session and referrer. // Validate session and referrer.
if (!ValidReferer) return Forbid(); if (!ValidReferer) return Forbid();
if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData); if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
RefreshModel(model);
// Organisation. // Organisation.
SysId organisationId = model.Filter.OrganisationId.ToSysId(); SysId organisationId = model.Filter.OrganisationId.ToSysId();
@@ -167,7 +168,7 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
NamedValue.Map values = resultSet.GetRecordValues(); NamedValue.Map values = resultSet.GetRecordValues();
MemberData_List memberData = new MemberData_List() MemberData_List memberData = new MemberData_List()
{ {
Id = values.GetString(colId.DataName), Id = values.GetLong(colId.DataName).ToString(),
UserAccountId = values.GetString(colUserAccountId.DataName), UserAccountId = values.GetString(colUserAccountId.DataName),
EmailAddress = values.GetString(colEmailAddress.DataName), EmailAddress = values.GetString(colEmailAddress.DataName),
DisplayName = AccountMgr.GetUserOrganisationDataValue(colDisplayName, values).ToString(), DisplayName = AccountMgr.GetUserOrganisationDataValue(colDisplayName, values).ToString(),
@@ -222,6 +223,7 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
// Validate session and referrer. // Validate session and referrer.
if (!ValidReferer) return Forbid(); if (!ValidReferer) return Forbid();
if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData); if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
RefreshModel(model);
// Identify item. // Identify item.
SysId memberId = model.MemberId.ToSysId(); SysId memberId = model.MemberId.ToSysId();
@@ -295,6 +297,7 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
// Validate session and referrer. // Validate session and referrer.
if (!ValidReferer) return Forbid(); if (!ValidReferer) return Forbid();
if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData); if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
RefreshModel(model);
// Validate item properties. // Validate item properties.
model.ValidateMemberData(responseData); model.ValidateMemberData(responseData);
@@ -519,6 +522,7 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
// Validate session and referrer. // Validate session and referrer.
if (!ValidReferer) return Forbid(); if (!ValidReferer) return Forbid();
if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData); if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
RefreshModel(model);
// Record disposable items as they are created so all can be disposed when needed. // Record disposable items as they are created so all can be disposed when needed.
using (DisposableCollection<SacsHierarchyItem> disposableItems = new DisposableCollection<SacsHierarchyItem>()) using (DisposableCollection<SacsHierarchyItem> disposableItems = new DisposableCollection<SacsHierarchyItem>())
@@ -609,6 +613,7 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
// Replace dynamic tag for link back to change password page. // Replace dynamic tag for link back to change password page.
SaEmailConsole.ReplaceDynamicEmailTag(emailData, "[#Link.RequestPassword]", SecurityController.GenerateRequestPasswordLink(this, userAccount.Id, userAccount.EmailAddress, "")); SaEmailConsole.ReplaceDynamicEmailTag(emailData, "[#Link.RequestPassword]", SecurityController.GenerateRequestPasswordLink(this, userAccount.Id, userAccount.EmailAddress, ""));
SaEmailConsole.ReplaceDynamicEmailTag(emailData, "[#Link.SignIn]", GetRedirectLocation(RedirectLocation.WebAppBase) + "Security/SignIn");
SaEmailConsole.ReplaceDynamicEmailTag(emailData, "[#Link.ExpiresMinutes]", SecurityController.GetRequestPasswordEmailLinkExpiresMinutes(this).ToString()); SaEmailConsole.ReplaceDynamicEmailTag(emailData, "[#Link.ExpiresMinutes]", SecurityController.GetRequestPasswordEmailLinkExpiresMinutes(this).ToString());
} }
@@ -633,6 +638,7 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
// Validate session and referrer. // Validate session and referrer.
if (!ValidReferer) return Forbid(); if (!ValidReferer) return Forbid();
if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData); if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
RefreshModel(model);
// Record disposable items as they are created so all can be disposed when needed. // Record disposable items as they are created so all can be disposed when needed.
using (DisposableCollection<SacsHierarchyItem> disposableItems = new DisposableCollection<SacsHierarchyItem>()) using (DisposableCollection<SacsHierarchyItem> disposableItems = new DisposableCollection<SacsHierarchyItem>())
@@ -92,10 +92,9 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
AjaxResponse_OpportunityList responseData = new AjaxResponse_OpportunityList(model); AjaxResponse_OpportunityList responseData = new AjaxResponse_OpportunityList(model);
// Validate session and referrer. // Validate session and referrer.
if (!ValidReferer) if (!ValidReferer) return Forbid();
return Forbid(); if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
if (!ValidUserSession) RefreshModel(model);
return GetAjaxResult_InvalidSession(responseData);
// Organisation. // Organisation.
SysId organisationId = model.Filter.OrganisationId.ToSysId(); SysId organisationId = model.Filter.OrganisationId.ToSysId();
@@ -170,7 +169,7 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
NamedValue.Map values = resultSet.GetRecordValues(); NamedValue.Map values = resultSet.GetRecordValues();
OpportunityData_List opportunityData = new OpportunityData_List() OpportunityData_List opportunityData = new OpportunityData_List()
{ {
Id = values.GetString(colId.DataName), Id = values.GetLong(colId.DataName).ToString(),
TypeCode = values.GetString(colOpportunityTypeCode.DataName), TypeCode = values.GetString(colOpportunityTypeCode.DataName),
TypeDesc = Localiser.GetOpportunityTypeCaption((Sax.OpportunityType)OpportunityTypeCodes.GetTypeForCode(values.GetString(colOpportunityTypeCode.DataName))), TypeDesc = Localiser.GetOpportunityTypeCaption((Sax.OpportunityType)OpportunityTypeCodes.GetTypeForCode(values.GetString(colOpportunityTypeCode.DataName))),
Position = values.GetString(colPosition.DataName), Position = values.GetString(colPosition.DataName),
@@ -218,10 +217,9 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
AjaxResponse_Opportunity responseData = new AjaxResponse_Opportunity(model); AjaxResponse_Opportunity responseData = new AjaxResponse_Opportunity(model);
// Validate session and referrer. // Validate session and referrer.
if (!ValidReferer) if (!ValidReferer) return Forbid();
return Forbid(); if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
if (!ValidUserSession) RefreshModel(model);
return GetAjaxResult_InvalidSession(responseData);
// Identify item. // Identify item.
SysId opportunityId = model.OpportunityId.ToSysId(); SysId opportunityId = model.OpportunityId.ToSysId();
@@ -271,10 +269,9 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
AjaxResponse_Opportunity responseData = new AjaxResponse_Opportunity(model); AjaxResponse_Opportunity responseData = new AjaxResponse_Opportunity(model);
// Validate session and referrer. // Validate session and referrer.
if (!ValidReferer) if (!ValidReferer) return Forbid();
return Forbid(); if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
if (!ValidUserSession) RefreshModel(model);
return GetAjaxResult_InvalidSession(responseData);
// Validate item properties. // Validate item properties.
model.ValidateOpportunityData(responseData); model.ValidateOpportunityData(responseData);
@@ -41,8 +41,7 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
AjaxResponse_RequestOrganisation responseData = new AjaxResponse_RequestOrganisation(model); AjaxResponse_RequestOrganisation responseData = new AjaxResponse_RequestOrganisation(model);
// Validate session and referrer. User does not need to be logged in. // Validate session and referrer. User does not need to be logged in.
if (!ValidReferer) if (!ValidReferer) return Forbid();
return Forbid();
SaxSessionData_Online sessionData = SessionData_Online; SaxSessionData_Online sessionData = SessionData_Online;
if (!model.ValidateOrganisationRequestData(responseData)) if (!model.ValidateOrganisationRequestData(responseData))
@@ -52,13 +51,13 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
SaxRegion regionCountry = Internals.GetRegion(model.OrganisationRegionIdCountry.ToSysId()); SaxRegion regionCountry = Internals.GetRegion(model.OrganisationRegionIdCountry.ToSysId());
if (SysId.IsValid(model.OrganisationRegionIdCountry.ToSysId()) && regionCountry == null) if (SysId.IsValid(model.OrganisationRegionIdCountry.ToSysId()) && regionCountry == null)
{ {
SaLogger.Warn(fn + " Country region not found. Id: " + model.OrganisationRegionIdCountry + ". " + getLogSuffix()); SaLogger.Warn(fn + " Country region not found. Id: " + model.OrganisationRegionIdCountry + ". " + GetLogSuffix());
return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"])); return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"]));
} }
SaxRegion regionProvince = Internals.GetRegion(model.OrganisationAddressRegionIdProvince.ToSysId()); SaxRegion regionProvince = Internals.GetRegion(model.OrganisationAddressRegionIdProvince.ToSysId());
if (SysId.IsValid(model.OrganisationAddressRegionIdProvince.ToSysId()) && regionProvince == null) if (SysId.IsValid(model.OrganisationAddressRegionIdProvince.ToSysId()) && regionProvince == null)
{ {
SaLogger.Warn(fn + " Province region not found. Id: " + model.OrganisationAddressRegionIdProvince + ". " + getLogSuffix()); SaLogger.Warn(fn + " Province region not found. Id: " + model.OrganisationAddressRegionIdProvince + ". " + GetLogSuffix());
return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"])); return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"]));
} }
@@ -71,7 +70,7 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
// hence 'System' error response and nothing more specific. // hence 'System' error response and nothing more specific.
if (!StringUtil.IsEmpty(model.ContactEmailAddress)) if (!StringUtil.IsEmpty(model.ContactEmailAddress))
{ {
SaLogger.Warn(fn + " Contact Email supplied when user logged in. " + getLogSuffix()); SaLogger.Warn(fn + " Contact Email supplied when user logged in. " + GetLogSuffix());
return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"])); return Json(responseData.SetGoHome(messageTitle, Localiser["msg.error.system"]));
} }
// Retrieve user account. // Retrieve user account.
@@ -52,10 +52,9 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
AjaxResponse_OrganisationList responseData = new AjaxResponse_OrganisationList(model); AjaxResponse_OrganisationList responseData = new AjaxResponse_OrganisationList(model);
// Validate session and referrer. // Validate session and referrer.
if (!ValidReferer) if (!ValidReferer) return Forbid();
return Forbid(); if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
if (!ValidUserSession) RefreshModel(model);
return GetAjaxResult_InvalidSession(responseData);
// Query columns. // Query columns.
ColumnDfn colOrganisationId = AccountMgr.GetOrganisationColumnDfn(SaxOrganisation.Column.Id); ColumnDfn colOrganisationId = AccountMgr.GetOrganisationColumnDfn(SaxOrganisation.Column.Id);
@@ -126,10 +125,9 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
AjaxResponse_MemberOrganisationList responseData = new AjaxResponse_MemberOrganisationList(model); AjaxResponse_MemberOrganisationList responseData = new AjaxResponse_MemberOrganisationList(model);
// Validate session and referrer. // Validate session and referrer.
if (!ValidReferer) if (!ValidReferer) return Forbid();
return Forbid(); if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
if (!ValidUserSession) RefreshModel(model);
return GetAjaxResult_InvalidSession(responseData);
// Query columns. // Query columns.
ColumnDfn colOrganisationId = AccountMgr.GetUserOrganisationColumnDfn(SaxUserOrganisation.Column.OrganisationId); ColumnDfn colOrganisationId = AccountMgr.GetUserOrganisationColumnDfn(SaxUserOrganisation.Column.OrganisationId);
@@ -43,8 +43,7 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
AjaxResponse_SportList responseData = new AjaxResponse_SportList(); AjaxResponse_SportList responseData = new AjaxResponse_SportList();
// Validate session and referrer. // Validate session and referrer.
if (!ValidReferer) if (!ValidReferer) return Forbid();
return Forbid();
// User doesn't have to be logged in, eg. to register organisation. // User doesn't have to be logged in, eg. to register organisation.
//if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData); //if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
@@ -75,9 +74,8 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
AjaxResponse_RegionList responseData = new AjaxResponse_RegionList(); AjaxResponse_RegionList responseData = new AjaxResponse_RegionList();
// Validate session and referrer. // Validate session and referrer.
if (!ValidReferer) if (!ValidReferer) return Forbid();
return Forbid(); // User doesn't have to be logged in to query regions, eg. for organisation request.
// User doesn't have to be logged in, eg. to register organisation.
//if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData); //if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
// Populate regions. // Populate regions.
@@ -258,7 +258,13 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
//------------------------------------------------------------------- //-------------------------------------------------------------------
// Logging. // Logging.
//------------------------------------------------------------------- //-------------------------------------------------------------------
protected String getLogSuffix() /// <summary>
/// Log suffix:
/// <para>- User's email address.</para>
/// <para>- Prefixed with space.</para>
/// </summary>
/// <returns></returns>
protected String GetLogSuffix()
{ {
List<String> logSuffix = new List<string>(); List<String> logSuffix = new List<string>();
SaxSessionData_Online sessionData = SessionData_Online; SaxSessionData_Online sessionData = SessionData_Online;
@@ -43,8 +43,7 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
String messageTitle = Localiser["signin.caption"]; String messageTitle = Localiser["signin.caption"];
// Validate referrer. // Validate referrer.
if (!ValidReferer) if (!ValidReferer) return Forbid();
return Forbid();
// Validate Sign-in data. // Validate Sign-in data.
model.ValidateSignInData(responseData); model.ValidateSignInData(responseData);
@@ -81,10 +80,9 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
AjaxResponse_KeepLoggedIn responseData = new AjaxResponse_KeepLoggedIn(); AjaxResponse_KeepLoggedIn responseData = new AjaxResponse_KeepLoggedIn();
// Validate session and referrer. // Validate session and referrer.
if (!ValidReferer) if (!ValidReferer) return Forbid();
return Forbid(); if (!ValidUserSession) return Json(responseData.SetGoHome());
if (!ValidUserSession) RefreshModel(model);
return Json(responseData.SetGoHome());
if (!AppConfig.Security.SignIn.KeepLoggedIn.Allowed) if (!AppConfig.Security.SignIn.KeepLoggedIn.Allowed)
return Json(responseData); return Json(responseData);
@@ -155,10 +153,9 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
String messageTitle = Localiser["signin.caption.signout"]; String messageTitle = Localiser["signin.caption.signout"];
// Validate session and referrer. // Validate session and referrer.
if (!ValidReferer) if (!ValidReferer) return Forbid();
return Forbid(); if (!ValidUserSession) return Json(responseData.SetSessionExpired(messageTitle, Localiser["security.msg.warn.sessionExpired"]));
if (!ValidUserSession) RefreshModel(model);
return Json(responseData.SetSessionExpired(messageTitle, Localiser["security.msg.warn.sessionExpired"]));
// Retrieve user account - in case sign-out needs to be recorded. // Retrieve user account - in case sign-out needs to be recorded.
SaxUserAccount userAccount = AccountMgr.GetUserAccountById(SessionData_Online.User.UserAccountId); SaxUserAccount userAccount = AccountMgr.GetUserAccountById(SessionData_Online.User.UserAccountId);
@@ -194,8 +191,7 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
public ActionResult Ajax_ScorePassword(Model_Security model) public ActionResult Ajax_ScorePassword(Model_Security model)
{ {
// Validate referrer. // Validate referrer.
if (!ValidReferer) if (!ValidReferer) return Forbid();
return Forbid();
// No need to store the session data for this request. // No need to store the session data for this request.
StoreSessionData = false; StoreSessionData = false;
@@ -225,8 +221,7 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
String messageTitle = Localiser["security.caption.change.password"]; String messageTitle = Localiser["security.caption.change.password"];
// Validate referrer. // Validate referrer.
if (!ValidReferer) if (!ValidReferer) return Forbid();
return Forbid();
// If 'Request Password' encrypted params (from email link) are present, // If 'Request Password' encrypted params (from email link) are present,
// Session is not required and password can be set directly against the user. // Session is not required and password can be set directly against the user.
@@ -324,8 +319,7 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
String messageTitle = Localiser["security.caption.request.password"]; String messageTitle = Localiser["security.caption.request.password"];
// Validate referrer. // Validate referrer.
if (!ValidReferer) if (!ValidReferer) return Forbid();
return Forbid();
// Validate data. // Validate data.
model.ValidateRequestPasswordData(responseData); model.ValidateRequestPasswordData(responseData);
@@ -378,11 +372,8 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
private static String ParamName_EmailAddress { get; } = "ema"; private static String ParamName_EmailAddress { get; } = "ema";
private static String ParamName_ExpiresAt { get; } = "exp"; private static String ParamName_ExpiresAt { get; } = "exp";
private static String ParamName_Token { get; } = "tok"; private static String ParamName_Token { get; } = "tok";
// NB IV value is generated from the key and fixed so that it doesn't change when the application restarts. // Request Password encryption parameters (key & IV) are defined in the base Controller
// IV Must be regenerated if key is changed. // so that they can be shared with the Adnin application.
private static String Base64Key_RequestPassword { get; } = SacsEncryptionHelper.EncodePlainKey("{~Saxonite@@Request^Password=}", SacsEncryptionHelper.KeyLength);
private static String Base64IV_RequestPassword_Generated { get; } = SacsEncryptionHelper.InitSymmetricEncryptionIV(Base64Key_RequestPassword);
private static String Base64IV_RequestPassword { get; } = "1VAWYTW6d72n/6HDNhbqow==";
internal static String GenerateRequestPasswordLink(SaxController_Online controller, SysId userAccountId, String emailAddress, String requestPasswordToken) internal static String GenerateRequestPasswordLink(SaxController_Online controller, SysId userAccountId, String emailAddress, String requestPasswordToken)
{ {
NameValueCollection parameters = new NameValueCollection(); NameValueCollection parameters = new NameValueCollection();
@@ -392,7 +383,7 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
parameters.Add(ParamName_Token, requestPasswordToken); parameters.Add(ParamName_Token, requestPasswordToken);
String link = String link =
controller.GetRedirectLocation(RedirectLocation.WebAppBase) + "Security/ChangePassword?" + controller.GetRedirectLocation(RedirectLocation.WebAppBase) + "Security/ChangePassword?" +
ParamName_RequestPasswordEncrypted + "=" + HttpUtility.UrlEncode(controller.EncryptParameters(parameters, Base64IV_RequestPassword, Base64Key_RequestPassword)); ParamName_RequestPasswordEncrypted + "=" + HttpUtility.UrlEncode(EncryptParameters(parameters, Base64IV_RequestPassword_Online, Base64Key_RequestPassword_Online));
return link; return link;
} }
internal static int GetRequestPasswordEmailLinkExpiresMinutes(SaxController_Online controller) internal static int GetRequestPasswordEmailLinkExpiresMinutes(SaxController_Online controller)
@@ -445,7 +436,7 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
RequestPasswordParams requestPasswordParams = new RequestPasswordParams(); RequestPasswordParams requestPasswordParams = new RequestPasswordParams();
if (!StringUtil.IsEmpty(encryptedParams)) if (!StringUtil.IsEmpty(encryptedParams))
{ {
NameValueCollection linkParams = DecryptParameters(encryptedParams, Base64IV_RequestPassword, Base64Key_RequestPassword); NameValueCollection linkParams = DecryptParameters(encryptedParams, Base64IV_RequestPassword_Online, Base64Key_RequestPassword_Online);
requestPasswordParams.UserAccountId = new SysId(StringUtil.ToInt(linkParams.Get(ParamName_UserAccountId))); requestPasswordParams.UserAccountId = new SysId(StringUtil.ToInt(linkParams.Get(ParamName_UserAccountId)));
requestPasswordParams.EmailAddress = linkParams.Get(ParamName_EmailAddress); requestPasswordParams.EmailAddress = linkParams.Get(ParamName_EmailAddress);
requestPasswordParams.ExpiresAt = DateUtil.ParseXmlDateTime(linkParams.Get(ParamName_ExpiresAt)); requestPasswordParams.ExpiresAt = DateUtil.ParseXmlDateTime(linkParams.Get(ParamName_ExpiresAt));
@@ -15,29 +15,45 @@ using System.Threading.Tasks;
namespace Saxonite.Net.Core.Web.Online.Models namespace Saxonite.Net.Core.Web.Online.Models
{ {
//======================================================================= //=======================================================================
public class Model_Journalist : SaxModel_Online public class Model_Article : SaxModel_Online
{ {
//------------------------------------------------------------------- //-------------------------------------------------------------------
// Construction. // Construction.
public Model_Journalist(SaxLocaliser localiser) : public Model_Article(SaxLocaliser localiser) :
base(localiser) base(localiser)
{ {
AdditionalFiles_CSS.Add("css/sax-jrn-art.css"); AdditionalFiles_CSS.Add("css/sax-art.css");
AdditionalFiles_JS.Add("js/sax-jrn-art.js"); AdditionalFiles_JS.Add("js/sax-art.js");
} }
//------------------------------------------------------------------- //-------------------------------------------------------------------
// List configuration. // List configuration.
public class FilterData public class FilterData
{ {
public String OrganisationId { get; set; }
public String OrganisationCaption { get; set; }
public String Article { get; set; } public String Article { get; set; }
} }
public FilterData Filter { get; } = new FilterData(); public FilterData Filter { get; } = new FilterData();
/// <summary>
/// User has rights to author articles for at least one organisation.
/// <para>- Output only - not returned with form data.</para>
/// <para>- Only populated for initial page construction.</para>
/// </summary>
public bool UserCanAuthorOrganisationArticles { get; set; }
/// <summary>
/// User has rights to author articles as a journalist.
/// <para>- Output only - not returned with form data.</para>
/// <para>- Only populated for initial page construction.</para>
/// </summary>
public bool UserCanAuthorJournalistArticles { get; set; }
//------------------------------------------------------------------- //-------------------------------------------------------------------
// Article properties. // Article properties.
public String ArticleId { get; set; } public String ArticleId { get; set; }
public String ArticleExists { get; set; } public String ArticleExists { get; set; }
// Organisation.
public String ArticleOrganisationId { get; set; }
// Sport. // Sport.
public String ArticleSportId { get; set; } public String ArticleSportId { get; set; }
public String ArticleSportCaption { get; set; } public String ArticleSportCaption { get; set; }
@@ -75,8 +91,8 @@ namespace Saxonite.Net.Core.Web.Online.Models
responseData.SetControlValue(nameof(ArticleHeadline), ArticleHeadline); responseData.SetControlValue(nameof(ArticleHeadline), ArticleHeadline);
if (StringUtil.IsEmpty(ArticleHeadline)) if (StringUtil.IsEmpty(ArticleHeadline))
responseData.SetControlError(nameof(ArticleHeadline), Localiser["msg.validation.mandatory.value"]); responseData.SetControlError(nameof(ArticleHeadline), Localiser["msg.validation.mandatory.value"]);
else if (StringUtil.GetLength(ArticleHeadline) > GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.JournalistArticle_Headline)) else if (StringUtil.GetLength(ArticleHeadline) > GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.Article_Headline))
responseData.SetControlError(nameof(ArticleHeadline), Localiser["msg.validation.maximum.length", GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.JournalistArticle_Headline)]); responseData.SetControlError(nameof(ArticleHeadline), Localiser["msg.validation.maximum.length", GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.Article_Headline)]);
} }
// Article summary. // Article summary.
@@ -85,8 +101,8 @@ namespace Saxonite.Net.Core.Web.Online.Models
responseData.SetControlValue(nameof(ArticleSummary), ArticleSummary); responseData.SetControlValue(nameof(ArticleSummary), ArticleSummary);
if (StringUtil.IsEmpty(ArticleSummary)) if (StringUtil.IsEmpty(ArticleSummary))
responseData.SetControlError(nameof(ArticleSummary), Localiser["msg.validation.mandatory.value"]); responseData.SetControlError(nameof(ArticleSummary), Localiser["msg.validation.mandatory.value"]);
else if (StringUtil.GetLength(ArticleSummary) > GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.JournalistArticle_Summary)) else if (StringUtil.GetLength(ArticleSummary) > GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.Article_Summary))
responseData.SetControlError(nameof(ArticleSummary), Localiser["msg.validation.maximum.length", GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.JournalistArticle_Summary)]); responseData.SetControlError(nameof(ArticleSummary), Localiser["msg.validation.maximum.length", GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.Article_Summary)]);
} }
// Article sport. // Article sport.
@@ -123,7 +139,7 @@ namespace Saxonite.Net.Core.Web.Online.Models
{ {
if (StringUtil.IsEmpty(ArticleStatusCode)) if (StringUtil.IsEmpty(ArticleStatusCode))
responseData.SetControlError(nameof(ArticleStatusCode), Localiser["msg.validation.mandatory.value"]); responseData.SetControlError(nameof(ArticleStatusCode), Localiser["msg.validation.mandatory.value"]);
else if (!SaxJournalistArticle.ValidStatuses.Contains(ArticleStatus)) else if (!SaxArticle.ValidStatuses.Contains(ArticleStatus))
responseData.SetControlError(nameof(ArticleStatusCode), Localiser["msg.validation.invalid.value"]); responseData.SetControlError(nameof(ArticleStatusCode), Localiser["msg.validation.invalid.value"]);
} }
@@ -1,11 +1,16 @@
using Sarand.Net.Standard.Base.Bus; using Sarand.Net.Standard.Base.App;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Helpers;
using Sarand.Net.Standard.Base.Utils;
using Saxonite.Net.Core.Web.Base.App; using Saxonite.Net.Core.Web.Base.App;
using Saxonite.Net.Core.Web.Base.Controllers;
using Saxonite.Net.Core.Web.Base.Models; using Saxonite.Net.Core.Web.Base.Models;
using Saxonite.Net.Core.Web.Online.App; using Saxonite.Net.Core.Web.Online.App;
using Saxonite.Net.Standard.Base.App; using Saxonite.Net.Standard.Base.App;
using Saxonite.Net.Standard.Base.Bus; using Saxonite.Net.Standard.Base.Bus;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
@@ -16,10 +21,9 @@ namespace Saxonite.Net.Core.Web.Online.Models
{ {
//------------------------------------------------------------------- //-------------------------------------------------------------------
// Data members. // Data members.
private bool userCanManageOrganisationMembers = false; private bool? userCanManageOrganisationMembers = null;
private bool userCanManageOrganisationMembersChecked = false; private bool? userCanManageOrganisationArticles = null;
private bool userCanManageOrganisationOpportunities = false; private bool? userCanManageOrganisationOpportunities = null;
private bool userCanManageOrganisationOpportunitiesChecked = false;
//------------------------------------------------------------------- //-------------------------------------------------------------------
// Protected construction. // Protected construction.
@@ -30,14 +34,19 @@ namespace Saxonite.Net.Core.Web.Online.Models
//------------------------------------------------------------------- //-------------------------------------------------------------------
// Session. // Session.
//-------------------------------------------------------------------
public SaxSessionData_Online SessionData_Online { get { return SessionData as SaxSessionData_Online; } } public SaxSessionData_Online SessionData_Online { get { return SessionData as SaxSessionData_Online; } }
// Menu options.
public bool MembersAllowed { get { return UserCanManageOrganisationMembers; } }
public bool ArticlesAllowed { get { return UserIsJournalist || UserCanManageOrganisationArticles; } }
public bool OpportunitiesAllowed { get { return UserCanManageOrganisationOpportunities; } }
// Security profile. // Security profile.
public bool UserIsJournalist { get { return SessionData != null && SessionData.User != null && SessionData.User.IsJournalist; } } public bool UserIsJournalist { get { return SessionData != null && SessionData.User != null && SessionData.User.IsJournalist; } }
public bool UserCanManageOrganisationMembers public bool UserCanManageOrganisationMembers
{ {
get get
{ {
if (!userCanManageOrganisationMembersChecked && ValidUserSession) if (userCanManageOrganisationMembers == null && ValidUserSession)
{ {
SaxUserOrganisation.Params prmUserOrganisation = new SaxUserOrganisation.Params(); SaxUserOrganisation.Params prmUserOrganisation = new SaxUserOrganisation.Params();
prmUserOrganisation.UserAccountIdsIncluded.Add(SessionData.User.UserAccountId); prmUserOrganisation.UserAccountIdsIncluded.Add(SessionData.User.UserAccountId);
@@ -45,16 +54,31 @@ namespace Saxonite.Net.Core.Web.Online.Models
prmUserOrganisation.OrganisationRoles.Add(Sax.OrganisationRole.OpportunityAdmin); prmUserOrganisation.OrganisationRoles.Add(Sax.OrganisationRole.OpportunityAdmin);
prmUserOrganisation.StatusCat = SaxUserOrganisation.StatusCat.ActiveOnly; prmUserOrganisation.StatusCat = SaxUserOrganisation.StatusCat.ActiveOnly;
userCanManageOrganisationMembers = (AccountMgr.GetUserOrganisationCount(prmUserOrganisation) > 0); userCanManageOrganisationMembers = (AccountMgr.GetUserOrganisationCount(prmUserOrganisation) > 0);
userCanManageOrganisationMembersChecked = true;
} }
return userCanManageOrganisationMembers; return userCanManageOrganisationMembers == true ? true : false;
}
}
public bool UserCanManageOrganisationArticles
{
get
{
if (userCanManageOrganisationArticles == null && ValidUserSession)
{
SaxUserOrganisation.Params prmUserOrganisation = new SaxUserOrganisation.Params();
prmUserOrganisation.UserAccountIdsIncluded.Add(SessionData.User.UserAccountId);
prmUserOrganisation.OrganisationMembersOnly = true;
prmUserOrganisation.OrganisationRoles.Add(Sax.OrganisationRole.ArticleAdmin);
prmUserOrganisation.StatusCat = SaxUserOrganisation.StatusCat.ActiveOnly;
userCanManageOrganisationArticles = (AccountMgr.GetUserOrganisationCount(prmUserOrganisation) > 0);
}
return userCanManageOrganisationArticles == true ? true : false;
} }
} }
public bool UserCanManageOrganisationOpportunities public bool UserCanManageOrganisationOpportunities
{ {
get get
{ {
if (!userCanManageOrganisationOpportunitiesChecked && ValidUserSession) if (userCanManageOrganisationOpportunities == null && ValidUserSession)
{ {
SaxUserOrganisation.Params prmUserOrganisation = new SaxUserOrganisation.Params(); SaxUserOrganisation.Params prmUserOrganisation = new SaxUserOrganisation.Params();
prmUserOrganisation.UserAccountIdsIncluded.Add(SessionData.User.UserAccountId); prmUserOrganisation.UserAccountIdsIncluded.Add(SessionData.User.UserAccountId);
@@ -62,12 +86,57 @@ namespace Saxonite.Net.Core.Web.Online.Models
prmUserOrganisation.OrganisationRoles.Add(Sax.OrganisationRole.OpportunityAdmin); prmUserOrganisation.OrganisationRoles.Add(Sax.OrganisationRole.OpportunityAdmin);
prmUserOrganisation.StatusCat = SaxUserOrganisation.StatusCat.ActiveOnly; prmUserOrganisation.StatusCat = SaxUserOrganisation.StatusCat.ActiveOnly;
userCanManageOrganisationOpportunities = (AccountMgr.GetUserOrganisationCount(prmUserOrganisation) > 0); userCanManageOrganisationOpportunities = (AccountMgr.GetUserOrganisationCount(prmUserOrganisation) > 0);
userCanManageOrganisationOpportunitiesChecked = true;
} }
return userCanManageOrganisationOpportunities; return userCanManageOrganisationOpportunities == true ? true : false;
} }
} }
//-------------------------------------------------------------------
// Item Id Obfuscation.
//-------------------------------------------------------------------
public SysId ExtractSysId(String idx)
{
String fn = GetType().Name + ".ExtractSysId";
if (StringUtil.IsEmpty(idx)) return null;
// Numeric values are assumed to be unencrypted Ids.
if (StringUtil.IsNumeric(idx))
return idx.ToSysId();
try
{
// Attempt to decrypt.
SysId id = DecryptId(idx);
if (SysId.IsValid(id))
return id;
}
catch (Exception exc)
{
SaLogger.Warn(fn + " " + ExceptionUtil.GetErrorStateMessage(exc));
}
return null;
}
//-------------------------------------------------------------------
// Id encryption.
// To obfuscate Id values that are sent to and from the browser.
// NB IV value can be reset evert time the application restarts.
public static String Base64Key_IdObfuscation = SacsEncryptionHelper.EncodePlainKey("|SaxOnIte.Onl1n3-iD+0bfuscAtion|", SacsEncryptionHelper.KeyLength);
public static String Base64IV_IdObfuscation = SacsEncryptionHelper.InitSymmetricEncryptionIV(Base64Key_IdObfuscation);
public static String ParamName_IdObfuscation_Id { get; } = "iob";
public String EncryptId(SysId id)
{
NameValueCollection idObfuscationParams = new NameValueCollection();
idObfuscationParams.Add(ParamName_IdObfuscation_Id, SysId.ToString(id));
return SaxController_Base.EncryptParameters(idObfuscationParams, Base64IV_IdObfuscation, Base64Key_IdObfuscation);
}
public SysId DecryptId(String encryptedParams)
{
NameValueCollection idObfuscationParams = SaxController_Base.DecryptParameters(encryptedParams, Base64IV_IdObfuscation, Base64Key_IdObfuscation);
return idObfuscationParams.Get(ParamName_IdObfuscation_Id).ToSysId();
}
//------------------------------------------------------------------- //-------------------------------------------------------------------
// Reference Data. // Reference Data.
//------------------------------------------------------------------- //-------------------------------------------------------------------
@@ -1,4 +1,4 @@
@model Model_Journalist @model Model_Article
@inject SaxLocaliser Localiser @inject SaxLocaliser Localiser
@{ @{
ViewData["Title"] = "Journalist - Articles"; ViewData["Title"] = "Journalist - Articles";
@@ -10,7 +10,7 @@
{ {
<div class="sax-panel-filter"> <div class="sax-panel-filter">
<div class="sax-header row"> <div class="sax-header row">
<div class="col"><div class="sax-caption">@Localiser["journalist.caption.articles"]</div></div> <div class="col"><div class="sax-caption">@Localiser["article.caption.articles"]</div></div>
<div class="fixed row"> <div class="fixed row">
<div> <div>
<partial name="~/Views/Common/ResultsPaging.cshtml" /> <partial name="~/Views/Common/ResultsPaging.cshtml" />
@@ -20,6 +20,17 @@
</div> </div>
</div> </div>
<div class="sax-content"> <div class="sax-content">
@if (Model.UserCanAuthorOrganisationArticles)
{
<div class="sax-control row OrganisationFilter">
<div class="col-sm-4"><div class="sax-label text-left text-sm-right">@Localiser["label.organisation"]</div></div>
<div class="col-sm-8 row">
@Html.HiddenFor(model => model.Filter.OrganisationId, new { @id = "ifFilterOrganisationId", @class = "FilterOrganisationId" })
<div class="col"><input type="text" id="ifFilterOrganisation" class="FilterOrganisation sax-input" readonly="readonly" value="@(Model.Filter.OrganisationCaption)" /></div>
<div class="fixed"><button class="sax-button" onclick="sax.selectFilterOrganisation()">@Localiser["label.select"]</button></div>
</div>
</div>
}
<div class="row"> <div class="row">
<div class="col-sm-4"><div class="sax-label text-left text-sm-right">@Localiser["label.search"]</div></div> <div class="col-sm-4"><div class="sax-label text-left text-sm-right">@Localiser["label.search"]</div></div>
<div class="col-sm-8"><input type="search" name="Filter.Article" id="ifArticleFilter" class="ArticleFilter sax-input" maxlength="64" /></div> <div class="col-sm-8"><input type="search" name="Filter.Article" id="ifArticleFilter" class="ArticleFilter sax-input" maxlength="64" /></div>
@@ -59,5 +70,6 @@
</div> </div>
<partial name="~/Views/Common/OrganisationSelect.cshtml" />
<partial name="Panel-ArticleDialog.cshtml" /> <partial name="Panel-ArticleDialog.cshtml" />
@@ -1,12 +1,12 @@
@model Model_Journalist @model Model_Article
@inject SaxLocaliser Localiser @inject SaxLocaliser Localiser
@{ @{
/* Articles - Article dialog panel */ /* Articles - Article dialog panel */
} }
<script type="text/javascript"> <script type="text/javascript">
sax.dlg.title.createArticle = '@Localiser.GetJavascriptText("journalist.caption.article.create")'; sax.dlg.title.createArticle = '@Localiser.GetJavascriptText("article.caption.article.create")';
sax.dlg.title.updateArticle = '@Localiser.GetJavascriptText("journalist.caption.article.update")'; sax.dlg.title.updateArticle = '@Localiser.GetJavascriptText("article.caption.article.update")';
sax.dlg.title.selectRegion = '@Localiser.GetJavascriptText("reference.caption.region.select")'; sax.dlg.title.selectRegion = '@Localiser.GetJavascriptText("reference.caption.region.select")';
sax.dlg.title.selectSport = '@Localiser.GetJavascriptText("reference.caption.sport.select")'; sax.dlg.title.selectSport = '@Localiser.GetJavascriptText("reference.caption.sport.select")';
</script> </script>
@@ -20,18 +20,35 @@
{ {
@Html.HiddenFor(model => model.ArticleId, new { @id = "ifArticleId", @class = "ArticleId" }) @Html.HiddenFor(model => model.ArticleId, new { @id = "ifArticleId", @class = "ArticleId" })
@Html.HiddenFor(model => model.ArticleExists, new { @id = "ifArticleExists", @class = "ArticleExists" }) @Html.HiddenFor(model => model.ArticleExists, new { @id = "ifArticleExists", @class = "ArticleExists" })
@Html.HiddenFor(model => model.ArticleOrganisationId, new { @id = "ifArticleOrganisationId", @class = "ArticleOrganisationId" })
<div class="sax-article ArticleHeader"> <div class="sax-article ArticleHeader">
<div class="sax-article-panel sax-article-header"> <div class="sax-article-panel sax-article-header">
@* Organisation *@
<div class="sax-form-control ArticleOrganisation">
<div class="row">
<div class="col-sm-4">
<div class="sax-label right pt4 pr8">
<label for="ifArticleOrganisation"><span>@Localiser["label.organisation"]</span></label>
</div>
</div>
<div class="col-sm">
<div class="sax-control">
<input type="text" id="ifArticleOrganisation" class="ArticleOrganisation sax-input" readonly="readonly" />
</div>
</div>
</div>
</div>
@* Article headline *@ @* Article headline *@
<div class="sax-form-control ArticleHeadline"> <div class="sax-form-control ArticleHeadline">
<div class="sax-label"> <div class="sax-label">
<label for="ifArticleHeadline"><span><span class="required">*</span> @Localiser["label.headline"]</span></label> <label for="ifArticleHeadline"><span>@Localiser["label.headline"]</span><span class="required">&nbsp;*</span></label>
</div> </div>
<div class="sax-control"> <div class="sax-control">
@Html.TextBoxFor(model => model.ArticleHeadline, new { @id = "ifArticleHeadline", @class = "ArticleHeadline sax-input", @maxlength = @Model.GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.JournalistArticle_Headline) }) @Html.TextBoxFor(model => model.ArticleHeadline, new { @id = "ifArticleHeadline", @class = "ArticleHeadline sax-input", @maxlength = @Model.GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.Article_Headline) })
</div> </div>
<div class="sax-message"></div> <div class="sax-message"></div>
</div> </div>
@@ -39,10 +56,10 @@
@* Article summary *@ @* Article summary *@
<div class="sax-form-control ArticleSummary"> <div class="sax-form-control ArticleSummary">
<div class="sax-label"> <div class="sax-label">
<label for="ifArticleSummary"><span><span class="required">*</span> @Localiser["label.summary"]</span></label> <label for="ifArticleSummary"><span>@Localiser["label.summary"]</span><span class="required">&nbsp;*</span></label>
</div> </div>
<div class="sax-control"> <div class="sax-control">
@Html.TextAreaFor(model => model.ArticleSummary, new { @id = "ifArticleSummary", @class = "ArticleSummary sax-textarea", @rows = 6, @maxlength = @Model.GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.JournalistArticle_Summary) }) @Html.TextAreaFor(model => model.ArticleSummary, new { @id = "ifArticleSummary", @class = "ArticleSummary sax-textarea", @rows = 6, @maxlength = @Model.GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.Article_Summary) })
</div> </div>
<div class="sax-message"></div> <div class="sax-message"></div>
</div> </div>
@@ -50,7 +67,7 @@
@* Sport *@ @* Sport *@
<div class="sax-form-control ArticleSportId"> <div class="sax-form-control ArticleSportId">
<div class="sax-label"> <div class="sax-label">
<label for="ifArticleSportId"><span><span class="required">*</span> @Localiser["label.sport"]</span></label> <label for="ifArticleSportId"><span>@Localiser["label.sport"]</span><span class="required">&nbsp;*</span></label>
</div> </div>
<div class="sax-control row"> <div class="sax-control row">
@Html.HiddenFor(model => model.ArticleSportId, new { @id = "ifArticleSportId", @class = "ArticleSportId" }) @Html.HiddenFor(model => model.ArticleSportId, new { @id = "ifArticleSportId", @class = "ArticleSportId" })
@@ -63,7 +80,7 @@
@* Region *@ @* Region *@
<div class="sax-form-control ArticleRegionId"> <div class="sax-form-control ArticleRegionId">
<div class="sax-label"> <div class="sax-label">
<label for="ifArticleRegionId"><span><span class="required">*</span> @Localiser["label.region"]</span></label> <label for="ifArticleRegionId"><span>@Localiser["label.region"]</span><span class="required">&nbsp;*</span></label>
</div> </div>
<div class="sax-control row"> <div class="sax-control row">
@Html.HiddenFor(model => model.ArticleRegionId, new { @id = "ifArticleRegionId", @class = "ArticleRegionId" }) @Html.HiddenFor(model => model.ArticleRegionId, new { @id = "ifArticleRegionId", @class = "ArticleRegionId" })
@@ -107,7 +124,7 @@
<div class="sax-panel-file-drop row"> <div class="sax-panel-file-drop row">
<div class="col">Drop image here</div> <div class="col">Drop image here</div>
<div class="fixed"> <div class="fixed">
<img id="" class="ContactImageUploadProgress" src="~/img/animated/progress-basketball-32.gif" style="display:none;margin:8px 4px;" /> <img class="ContactImageUploadProgress" src="~/img/animated/progress-basketball-32.gif" style="display:none;margin:8px 4px;" />
</div> </div>
</div> </div>
@* Segment details *@ @* Segment details *@
@@ -138,7 +155,7 @@
<div id="dlgSelectArticleImage" class="sax-dialog"> <div id="dlgSelectArticleImage" class="sax-dialog">
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmSelectArticleImage", @class = "sax-form", @onSubmit = "return false;" })) @using (@Html.BeginForm(FormMethod.Post, new { @id = "frmSelectArticleImage", @class = "sax-form", @onSubmit = "return false;" }))
{ {
<input type="hidden" id="" class="SegmentIdx" /> <input type="hidden" class="SegmentIdx" />
<div class="spacer4"></div> <div class="spacer4"></div>
<div class="sax-form-control ArticleImage"> <div class="sax-form-control ArticleImage">
<div class="row"> <div class="row">
@@ -150,7 +167,7 @@
<div class="spacer2"></div> <div class="spacer2"></div>
<div class="row"> <div class="row">
<div class="col"><div class="UploadMessage"></div></div> <div class="col"><div class="UploadMessage"></div></div>
<div class="fixed"><img id="" class="ArticleImageUploadProgress" src="~/img/animated/progress-basketball-32.gif" style="display:none;margin:8px 4px;" /></div> <div class="fixed"><img class="ArticleImageUploadProgress" src="~/img/animated/progress-basketball-32.gif" style="display:none;margin:8px 4px;" /></div>
</div> </div>
<div class="spacer2"></div> <div class="spacer2"></div>
} }
@@ -22,7 +22,7 @@
<input type="hidden" class="FilterPageNo" name="DataPageNo" value="0" /> <input type="hidden" class="FilterPageNo" name="DataPageNo" value="0" />
<div class="row"> <div class="row">
<div class="col-sm-5 sax-label text-left text-sm-right">@Localiser["label.search"]</div> <div class="col-sm-5 sax-label text-left text-sm-right">@Localiser["label.search"]</div>
<div class="col-sm-7"><input type="search" id="" class="sax-input FilterOrganisation" name="Filter.Organisation" maxlength="32" autocomplete="off" /></div> <div class="col-sm-7"><input type="search" class="sax-input FilterOrganisation" name="Filter.Organisation" maxlength="32" autocomplete="off" /></div>
</div> </div>
} }
@@ -55,7 +55,12 @@ else
<div class="sax-panel-item Activity"> <div class="sax-panel-item Activity">
<div class="sax-header row"> <div class="sax-header row">
<div class="col"> <div class="col">
<div class="sax-caption"><div class="sax-action ActivityCaption"></div></div> <div class="sax-caption">
<div class="row">
<div class="col"><div class="sax-action ActivityCaption"></div></div>
<div class="col right"><div class="sax-action ActivityOrganisation"></div></div>
</div>
</div>
</div> </div>
<div class="fixed sax-actions"> <div class="fixed sax-actions">
</div> </div>
@@ -21,7 +21,7 @@
<div class="col-sm-4"><div class="sax-label text-left text-sm-right">@Localiser["label.organisation"]</div></div> <div class="col-sm-4"><div class="sax-label text-left text-sm-right">@Localiser["label.organisation"]</div></div>
<div class="col-sm-8 row"> <div class="col-sm-8 row">
@Html.HiddenFor(model => model.Filter.OrganisationId, new { @id = "ifFilterOrganisationId", @class = "FilterOrganisationId" }) @Html.HiddenFor(model => model.Filter.OrganisationId, new { @id = "ifFilterOrganisationId", @class = "FilterOrganisationId" })
<div class="col"><input type="text" id="ifFilterOrganisation" class="FilterOrganisation sax-input" value="@(Model.Filter.OrganisationCaption)" /></div> <div class="col"><input type="text" id="ifFilterOrganisation" class="FilterOrganisation sax-input" readonly="readonly" value="@(Model.Filter.OrganisationCaption)" /></div>
<div class="fixed"><button class="sax-button" onclick="sax.selectFilterOrganisation()">@Localiser["label.select"]</button></div> <div class="fixed"><button class="sax-button" onclick="sax.selectFilterOrganisation()">@Localiser["label.select"]</button></div>
</div> </div>
</div> </div>
@@ -64,6 +64,6 @@
</div> </div>
<partial name="Panel-OpportunityDialog.cshtml" />
<partial name="~/Views/Common/OrganisationSelect.cshtml" /> <partial name="~/Views/Common/OrganisationSelect.cshtml" />
<partial name="Panel-OpportunityDialog.cshtml" />
@@ -129,15 +129,15 @@
</a> </a>
<div class="dropdown-menu" aria-labelledby="navbarDropdown"> <div class="dropdown-menu" aria-labelledby="navbarDropdown">
<div class="dropdown-item text-dark sax-action" onclick="sax.goToPage('Account/Profile');">@Localiser["account.caption.profile"]</div> <div class="dropdown-item text-dark sax-action" onclick="sax.goToPage('Account/Profile');">@Localiser["account.caption.profile"]</div>
@if (Model.UserIsJournalist) @if (Model.ArticlesAllowed)
{ {
<div class="dropdown-item text-dark sax-action" onclick="sax.goToPage('Journalist/Articles');">@Localiser["journalist.caption.articles"]</div> <div class="dropdown-item text-dark sax-action" onclick="sax.goToPage('Article/Index');">@Localiser["article.caption.articles"]</div>
} }
@if (Model.UserCanManageOrganisationMembers) @if (Model.MembersAllowed)
{ {
<div class="dropdown-item text-dark sax-action" onclick="sax.goToPage('Organisation/Members');">@Localiser["label.members"]</div> <div class="dropdown-item text-dark sax-action" onclick="sax.goToPage('Organisation/Members');">@Localiser["label.members"]</div>
} }
@if (Model.UserCanManageOrganisationOpportunities) @if (Model.OpportunitiesAllowed)
{ {
<div class="dropdown-item text-dark sax-action" onclick="sax.goToPage('Organisation/Opportunities');">@Localiser["label.opportunities"]</div> <div class="dropdown-item text-dark sax-action" onclick="sax.goToPage('Organisation/Opportunities');">@Localiser["label.opportunities"]</div>
} }
@@ -273,7 +273,7 @@
} }
sax.onRefreshProfileOrganisationsInfo = function (response) sax.onRefreshProfileOrganisationsInfo = function (response)
{ {
sax.debug('onRefreshProfileOrganisationsInfo', response); //sax.debug('onRefreshProfileOrganisationsInfo', response);
if (!response || !response.success) return; if (!response || !response.success) return;
var $section = $('.sax-panel-section.ProfileOrganisations'); var $section = $('.sax-panel-section.ProfileOrganisations');
$('.sax-message', $section).stop(true, false).fadeOut(200).empty(); $('.sax-message', $section).stop(true, false).fadeOut(200).empty();
@@ -1,5 +1,5 @@
/* /*
* Journalist - Articles page scripts. * Article page scripts.
*/ */
(function (win, doc, undef) (function (win, doc, undef)
@@ -8,18 +8,18 @@
sax.itemIdPrefix = 'Itm_'; sax.itemIdPrefix = 'Itm_';
sax.segIdPrefix = 'Seg_'; sax.segIdPrefix = 'Seg_';
sax.classFileDrag = 'sax-file-drag'; sax.classFileDrag = 'sax-file-drag';
let $pnl = sax.$pnl, $frm = sax.$frm;
let ac = sax.articleContent = sax.articleContent || {}; let ac = sax.articleContent = sax.articleContent || {};
//-------------------------------------------------------------- //--------------------------------------------------------------
sax.refreshResults = function (delay) sax.refreshResults = function (delay)
{ {
var $results = $('.sax-panel-results');
if (!sax.awaitingRefreshResponse) if (!sax.awaitingRefreshResponse)
{ {
var $items = $('.sax-panel-item-list', $results).fadeOut(200).empty(); var $items = $('.sax-panel-item-list', $pnl.results).fadeOut(200).empty();
var $msgs = $('.sax-panel-messages', $results).hide().empty().append($('<div class="sax-message">' + sax.msg.dataQuerying + '</div>')).fadeIn(200); var $msgs = $('.sax-panel-messages', $pnl.results).hide().empty().append($('<div class="sax-message">' + sax.msg.dataQuerying + '</div>')).fadeIn(200);
} }
sax.ajaxRefreshResults = sax.ajaxRefreshResults || { url: sax.url.base + 'Journalist/Ajax/GetArticleList', formId: 'frmArticleFilter', callbackFn: sax.doRefreshResults }; sax.ajaxRefreshResults = sax.ajaxRefreshResults || { url: sax.url.base + 'Article/Ajax/GetList', formId: 'frmArticleFilter', callbackFn: sax.doRefreshResults };
sax.doAjaxRequest(sax.ajaxRefreshResults, delay || 50); sax.doAjaxRequest(sax.ajaxRefreshResults, delay || 50);
sax.awaitingRefreshResponse = true; sax.awaitingRefreshResponse = true;
} }
@@ -28,11 +28,11 @@
//sax.debug('doRefreshResults', response); //sax.debug('doRefreshResults', response);
delete sax.awaitingRefreshResponse; delete sax.awaitingRefreshResponse;
sax.refreshControlValues(response.controlValues); sax.refreshControlValues(response.controlValues);
var $results = $('.sax-panel-results'); var $msgs = $('.sax-panel-messages', $pnl.results).hide().empty();
var $msgs = $('.sax-panel-messages', $results).hide().empty(); var $items = $('.sax-panel-item-list', $pnl.results).hide().empty();
var $items = $('.sax-panel-item-list', $results).hide().empty(); var $tmpl = $('.sax-panel-item-template .sax-panel-item', $pnl.results);
var $tmpl = $('.sax-panel-item-template .sax-panel-item', $results);
if (!response.success) return; if (!response.success) return;
sax.data.articleOrganisations = response.organisations;
sax.refreshPaging(response); sax.refreshPaging(response);
var items = response.articles; var items = response.articles;
if (!items.length) if (!items.length)
@@ -60,7 +60,26 @@
$('.ArticleStatusDesc', $item).text(item.statusDesc); $('.ArticleStatusDesc', $item).text(item.statusDesc);
$('.sax-caption .sax-action, .sax-actions .sax-action.sax-item-update', $item).off('click').on('click', function () { sax.updateItem(item.id) }) $('.sax-caption .sax-action, .sax-actions .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) }) $item.off('dblclick').on('dblclick', function () { sax.updateItem(item.id) })
$('.sax-panel-results .sax-panel-messages').hide().empty(); $('.sax-panel-messages', $pnl.results).hide().empty();
}
//--------------------------------------------------------------
sax.selectFilterOrganisation = function ()
{
if (!sax.data.articleOrganisations || !sax.data.articleOrganisations.length) return;
sax.showSelectOrganisation();
}
sax.showSelectOrganisation = function ()
{
//sax.debug('sax.selectFilterOrganisation', sax.data.articleOrganisations);
sax.selectOrganisation.fn.selectOrganisation({ caption: sax.dlg.title.selectOrganisation, items: sax.data.articleOrganisations, fnCallback: sax.onOrganisationSelected });
}
sax.onOrganisationSelected = function (id, name)
{
//sax.debug('sax.onOrganisationSelected', id, name);
$('#frmArticleFilter #ifFilterOrganisationId, #frmArticle #ifArticleOrganisationId').val(id);
$('#frmArticleFilter #ifFilterOrganisation').val(name);
sax.refreshResults(50);
} }
//-------------------------------------------------------------- //--------------------------------------------------------------
@@ -245,13 +264,13 @@
if (file.type != 'image/jpg' && file.type != 'image/jpeg' && file.type != 'image/png') return sax.doAlert(sax.dlg.title.imageUpload, sax.msg.uploadFileTypeInvalid.format(sax.getFileType(file))); if (file.type != 'image/jpg' && file.type != 'image/jpeg' && file.type != 'image/png') return sax.doAlert(sax.dlg.title.imageUpload, sax.msg.uploadFileTypeInvalid.format(sax.getFileType(file)));
$(".UploadMessage", context).text(sax.msg.uploadingFile.format(file.name)); $(".UploadMessage", context).text(sax.msg.uploadingFile.format(file.name));
$('img.ArticleImageUploadProgress', context).fadeIn(200); $('img.ArticleImageUploadProgress', context).fadeIn(200);
sax.clearControlError(sax.$pnl.contactImageDrag); sax.clearControlError();
sax.data.contactImageUploadContext = context; sax.data.contactImageUploadContext = context;
sax.ajax.uploadArticleImage = sax.ajax.uploadArticleImage || { url: sax.url.base + 'Journalist/Ajax/UploadArticleImage', callbackFn: sax.handleArticleImageUploadResponse, noWaitIcon: true }; sax.ajax.uploadArticleImage = sax.ajax.uploadArticleImage || { url: sax.url.base + 'Article/Ajax/UploadImage', callbackFn: sax.handleArticleImageUploadResponse, noWaitIcon: true };
sax.ajax.uploadArticleImage.formData = new FormData(); sax.ajax.uploadArticleImage.formData = new FormData();
sax.ajax.uploadArticleImage.formData.append("__RequestVerificationToken", $('#frmNavigate input[name="__RequestVerificationToken"]').val()); sax.ajax.uploadArticleImage.formData.append("__RequestVerificationToken", $('#frmNavigate input[name="__RequestVerificationToken"]').val());
sax.ajax.uploadArticleImage.formData.append("ArticleId", $('#ifArticleId', sax.$frm.article).val()); sax.ajax.uploadArticleImage.formData.append("ArticleId", $('#ifArticleId', $frm.article).val());
sax.ajax.uploadArticleImage.formData.append("ArticleImage", file); sax.ajax.uploadArticleImage.formData.append("ArticleImage", file);
sax.doAjaxRequest(sax.ajax.uploadArticleImage, 50); sax.doAjaxRequest(sax.ajax.uploadArticleImage, 50);
} }
@@ -275,9 +294,21 @@
sax.createItem = function () sax.createItem = function ()
{ {
sax.clearItem(); sax.clearItem();
let orgId = $('#ifFilterOrganisationId', $frm.filter).val();
$('#ifArticleOrganisationId', $frm.article).val(orgId);
$('#ifArticleOrganisation', $frm.article).val($('#ifFilterOrganisation', $frm.filter).val());
$('.sax-form-control.ArticleOrganisation', $frm.article).toggle(!!orgId);
sax.populateArticleContent({}); sax.populateArticleContent({});
sax.openArticleDialog(sax.dlg.title.createArticle); sax.openArticleDialog(sax.dlg.title.createArticle);
} }
sax.clearItem = function ()
{
let frm = $frm.article;
$('#ifArticleId,#ifArticleExists,#ifArticleOrganisationId,#ifArticleRegionId,#ifArticleSportId,input[type="text"],textarea,select', frm).val('');
$('#chkArticlePublish', frm).prop("checked", false);
$('.sax-input.sax-calendar.ArticlePublishOn', frm).datepicker('setDate', 'today');
sax.clearControlErrors();
}
sax.openArticleDialog = function (title) sax.openArticleDialog = function (title)
{ {
sax.clearControlErrors(); sax.clearControlErrors();
@@ -285,24 +316,12 @@
sax.$dlg.article.dialog('option', 'title', title); sax.$dlg.article.dialog('option', 'title', title);
sax.openDialog(sax.$dlg.article, 600, 800); sax.openDialog(sax.$dlg.article, 600, 800);
} }
sax.clearItem = function ()
{
let $frm = sax.$frm.article;
$('#ifArticleId,#ifArticleExists,#ifArticleRegionId,#ifArticleSportId,input[type="text"],textarea,select', $frm).val('');
$('#chkArticlePublish', $frm).prop("checked", false);
$('.sax-input.sax-calendar.ArticlePublishOn', $frm).datepicker('setDate', 'today');
sax.clearControlErrors();
}
sax.doCreateItem = function ()
{
sax.storeItem();
}
//-------------------------------------------------------------- //--------------------------------------------------------------
sax.updateItem = function (id) sax.updateItem = function (id)
{ {
$('.ArticleId', sax.$frm.articleId).val(id); $('.ArticleId', $frm.articleId).val(id);
sax.ajaxUpdateItem = sax.ajaxUpdateItem || { url: sax.url.base + 'Journalist/Ajax/GetArticle', formId: 'frmArticleId', callbackFn: sax.onUpdateItem }; sax.ajaxUpdateItem = sax.ajaxUpdateItem || { url: sax.url.base + 'Article/Ajax/GetItem', formId: 'frmArticleId', callbackFn: sax.onUpdateItem };
sax.doAjaxRequest(sax.ajaxUpdateItem, 50); sax.doAjaxRequest(sax.ajaxUpdateItem, 50);
} }
sax.onUpdateItem = function (response) sax.onUpdateItem = function (response)
@@ -310,28 +329,24 @@
//sax.debug('onUpdateItem', response); //sax.debug('onUpdateItem', response);
sax.clearItem(); sax.clearItem();
if (!response.success) return; if (!response.success) return;
let $frm = sax.$frm.article; let frm = $frm.article;
let item = response.article; let item = response.article;
$('#ifArticleId', $frm).val(item.id); $('#ifArticleId', frm).val(item.id);
$('#ifArticleExists', $frm).val(1); $('#ifArticleExists', frm).val(1);
$('#ifArticleHeadline', $frm).val(item.headline); $('#ifArticleHeadline', frm).val(item.headline);
$('#ifArticleSummary', $frm).val(item.summary); $('#ifArticleSummary', frm).val(item.summary);
$('#ifArticleRegionId', $frm).val(item.regionIdPrimary); $('#ifArticleRegionId', frm).val(item.regionIdPrimary);
$('#ifArticleRegionCaption', $frm).val(item.regionCaptionPrimary); $('#ifArticleRegionCaption', frm).val(item.regionCaptionPrimary);
$('#ifArticleSportId', $frm).val(item.sportIdPrimary); $('#ifArticleSportId', frm).val(item.sportIdPrimary);
$('#ifArticleSportCaption', $frm).val(item.sportCaptionPrimary); $('#ifArticleSportCaption', frm).val(item.sportCaptionPrimary);
if (item.published) if (item.published)
$('span.ArticlePublishedOn', $frm).text(item.publishedOnFmt); $('span.ArticlePublishedOn', frm).text(item.publishedOnFmt);
$('div.ArticlePublish', $frm).toggle(!item.published); $('div.ArticlePublish', frm).toggle(!item.published);
$('div.ArticlePublished', $frm).toggle(!!item.published); $('div.ArticlePublished', frm).toggle(!!item.published);
$('#cbArticleStatusCode', $frm).val(item.statusCode); $('#cbArticleStatusCode', frm).val(item.statusCode);
sax.populateArticleContent(item.content); sax.populateArticleContent(item.content);
sax.openArticleDialog(sax.dlg.title.updateArticle); sax.openArticleDialog(sax.dlg.title.updateArticle);
} }
sax.doUpdateItem = function ()
{
sax.storeItem();
}
//-------------------------------------------------------------- //--------------------------------------------------------------
sax.switchArticleHeader = function () sax.switchArticleHeader = function ()
@@ -368,7 +383,7 @@
//-------------------------------------------------------------- //--------------------------------------------------------------
sax.storeItem = function () sax.storeItem = function ()
{ {
sax.ajaxStoreItem = sax.ajaxStoreItem || { url: sax.url.base + 'Journalist/Ajax/StoreArticle', formId: 'frmArticle', callbackFn: sax.onStoreItem }; sax.ajaxStoreItem = sax.ajaxStoreItem || { url: sax.url.base + 'Article/Ajax/StoreItem', formId: 'frmArticle', callbackFn: sax.onStoreItem };
sax.doAjaxRequest(sax.ajaxStoreItem, 50); sax.doAjaxRequest(sax.ajaxStoreItem, 50);
} }
sax.onStoreItem = function (response) sax.onStoreItem = function (response)
@@ -382,9 +397,8 @@
var $item = $('#' + sax.itemIdPrefix + item.id); var $item = $('#' + sax.itemIdPrefix + item.id);
if (!$item.length) if (!$item.length)
{ {
var $results = $('.sax-panel-results'); $item = $('.sax-panel-item-template .sax-panel-item', $pnl.results).clone();
$item = $('.sax-panel-item-template .sax-panel-item', $results).clone(); $('.sax-panel-item-list', $pnl.results).prepend($item).show();
$('.sax-panel-item-list', $results).prepend($item).show();
} }
sax.populateItem($item, item) sax.populateItem($item, item)
} }
@@ -392,20 +406,23 @@
//-------------------------------------------------------------- //--------------------------------------------------------------
$(function () $(function ()
{ {
sax.$frm.filter = $('#frmArticleFilter'); $pnl.filter = $('.sax-panel-filter');
$('.sax-panel-filter .sax-action.sax-item-create').on('click', function () { sax.createItem(); }); $pnl.results= $('.sax-panel-results');
$('.sax-panel-filter .sax-action.sax-results-refresh').on('click', function () { sax.refreshResults(); });
$('.ArticleFilter', sax.$frm.filter).on('input', function () { sax.refreshResults(250); }).on('keypress', function (event) $frm.filter = $('#frmArticleFilter');
$('.sax-action.sax-item-create', $pnl.filter).on('click', function () { sax.createItem(); });
$('.sax-action.sax-results-refresh', $pnl.filter).on('click', function () { sax.refreshResults(); });
$('.ArticleFilter', $frm.filter).on('input', function () { sax.refreshResults(250); }).on('keypress', function (event)
{ {
if (event.keyCode == 13) setTimeout(sax.refreshResults, 50); if (event.keyCode == 13) setTimeout(sax.refreshResults, 50);
}); });
sax.$frm.articleId = $('#frmArticleId'); $frm.articleId = $('#frmArticleId');
sax.$frm.article = $('#frmArticle'); $frm.article = $('#frmArticle');
$('.sax-input', sax.$frm.article).on('input', function () { sax.clearControlError(this); }); $('.sax-input', $frm.article).on('input', function () { sax.clearControlError(this); });
var opt = sax.dlgOpts(); var opt = sax.dlgOpts();
opt.buttons[sax.dlg.btn.cancel] = { text: sax.dlg.btn.cancel, class: "floatr", click: function () { $(this).dialog('close'); } }; opt.buttons[sax.dlg.btn.cancel] = { text: sax.dlg.btn.cancel, class: "floatr", click: function () { $(this).dialog('close'); } };
opt.buttons[sax.dlg.btn.ok] = { text: sax.dlg.btn.ok, class: "floatr", click: function () { sax.doCreateItem(); } }; opt.buttons[sax.dlg.btn.ok] = { text: sax.dlg.btn.ok, class: "floatr", click: function () { sax.storeItem(); } };
opt.buttons['Header'] = { text: 'Header', class: "floatl", click: function () { sax.switchArticleHeader(); } }; opt.buttons['Header'] = { text: 'Header', class: "floatl", click: function () { sax.switchArticleHeader(); } };
opt.buttons['Content'] = { text: 'Content', class: "floatl", click: function () { sax.switchArticleContent(); } }; opt.buttons['Content'] = { text: 'Content', class: "floatl", click: function () { sax.switchArticleContent(); } };
sax.$dlg.article = $('#dlgArticle').dialog(opt); sax.$dlg.article = $('#dlgArticle').dialog(opt);
+3 -1
View File
@@ -44,9 +44,11 @@
} }
sax.populateItem = function ($item, item) sax.populateItem = function ($item, item)
{ {
//sax.debug('populateItem', item); sax.debug('populateItem', item);
if (!item) return; if (!item) return;
$item.prop('id', sax.itemIdPrefix + item.itemIdx).addClass(item.itemTypeClass).toggleClass('sax-activity-reaction-' + item.reaction, !!item.reaction); $item.prop('id', sax.itemIdPrefix + item.itemIdx).addClass(item.itemTypeClass).toggleClass('sax-activity-reaction-' + item.reaction, !!item.reaction);
$('.ActivityOrganisation', $item).text(item.organisation);
$('.ActivityAuthor', $item).text(item.author);
$('.ActivityCaption', $item).text(item.caption); $('.ActivityCaption', $item).text(item.caption);
$('.ActivityBlurb', $item).text(item.blurb); $('.ActivityBlurb', $item).text(item.blurb);
$('.ActivitySport', $item).text(item.sport); $('.ActivitySport', $item).text(item.sport);
@@ -35,7 +35,7 @@
} }
sax.doRefreshResults = function (response) sax.doRefreshResults = function (response)
{ {
sax.debug('doRefreshResults', response); //sax.debug('doRefreshResults', response);
delete sax.awaitingRefreshResponse; delete sax.awaitingRefreshResponse;
sax.refreshControlValues(response.controlValues); sax.refreshControlValues(response.controlValues);
let $mnu = $('.sax-burger ul.sax-dropdown-menu', sax.$pnl.filter).empty(); let $mnu = $('.sax-burger ul.sax-dropdown-menu', sax.$pnl.filter).empty();
@@ -201,7 +201,7 @@
} }
sax.updateMemberRoles = function (memberRoleCodes) sax.updateMemberRoles = function (memberRoleCodes)
{ {
sax.debug('updateMemberRoles', memberRoleCodes); //sax.debug('updateMemberRoles', memberRoleCodes);
let $frm = sax.$frm.member; let $frm = sax.$frm.member;
sax.member.roleCodes = memberRoleCodes; sax.member.roleCodes = memberRoleCodes;
$('.MemberRoleCodes',$frm).val(memberRoleCodes.join(sax.data.memberRoleCodeDelim)); $('.MemberRoleCodes',$frm).val(memberRoleCodes.join(sax.data.memberRoleCodeDelim));
@@ -230,7 +230,7 @@
} }
sax.onStoreItem = function (response) sax.onStoreItem = function (response)
{ {
sax.debug('onStoreItem', response); //sax.debug('onStoreItem', response);
sax.refreshControlValues(response.controlValues); sax.refreshControlValues(response.controlValues);
if (!response.success) return; if (!response.success) return;
let $frm = sax.$frm.member; let $frm = sax.$frm.member;
@@ -26,7 +26,7 @@
} }
or.fn.handleRequestOrganisationResponse = function (response) or.fn.handleRequestOrganisationResponse = function (response)
{ {
sax.debug('or.handleRequestOrganisationResponse', response); //sax.debug('or.handleRequestOrganisationResponse', response);
if (!response) return; if (!response) return;
sax.refreshControlValues(response.controlValues, or.$frm); sax.refreshControlValues(response.controlValues, or.$frm);
if (!response.success) return; if (!response.success) return;
@@ -6,7 +6,7 @@
{ {
"use strict"; "use strict";
let so = sax.selectOrganisation; let so = sax.selectOrganisation;
so.data = {}; so.fn = {}; so.itemIdPrefix = 'Org_'; so.data = {}; so.fn = {};
//-------------------------------------------------------------- //--------------------------------------------------------------
/* /*
@@ -52,7 +52,8 @@
{ {
let item = items[itemIdx]; let item = items[itemIdx];
if (!so.fn.matchesFilter(item)) continue; if (!so.fn.matchesFilter(item)) continue;
let $item = $tmpl.clone().prop('id', so.itemIdPrefix + item.id).on('click', function () { so.fn.onClickOrganisation(item); }).on('dblclick', function () { so.fn.onDblClickOrganisation(item); }); let $item = $tmpl.clone();
$item.on('click', function () { so.fn.onClickOrganisation(item, $item); }).on('dblclick', function () { so.fn.onDblClickOrganisation(item, $item); });
$('.Name', $item).text(item.name); $('.Name', $item).text(item.name);
so.$results.append($item); so.$results.append($item);
} }
@@ -69,16 +70,16 @@
} }
return true; return true;
} }
so.fn.onClickOrganisation = function (item) so.fn.onClickOrganisation = function (item, $item)
{ {
//sax.debug('onClickOrganisation', item); //sax.debug('onClickOrganisation', item, $item);
so.data.item = item; so.data.item = item;
$('.sax-panel-item.Organisation', so.$dlg).removeClass('sel'); $('.sax-panel-item.Organisation', so.$dlg).removeClass('sel');
$('.sax-panel-item.Organisation#' + so.itemIdPrefix + item.id, so.$dlg).addClass('sel'); $item.addClass('sel');
} }
so.fn.onDblClickOrganisation = function (item) so.fn.onDblClickOrganisation = function (item, $item)
{ {
//sax.debug('onDblClickCode', item); //sax.debug('onDblClickCode', item, $item);
so.data.item = item; so.data.item = item;
so.fn.confirmSelection(); so.fn.confirmSelection();
} }
@@ -99,7 +100,6 @@
delete so.data.item; delete so.data.item;
} }
//-------------------------------------------------------------- //--------------------------------------------------------------
so.fn.init = function () so.fn.init = function ()
{ {
@@ -33,7 +33,7 @@
{ {
if (!response || !response.success) return; if (!response || !response.success) return;
sr.regions = response.regions; sr.regions = response.regions;
sax.debug(sr.cfg); //sax.debug(sr.cfg);
sr.fn.showSelectRegion(); sr.fn.showSelectRegion();
} }
sr.fn.showSelectRegion = function () sr.fn.showSelectRegion = function ()
+5 -1
View File
@@ -18,7 +18,7 @@ namespace Saxonite.Net.Standard.Base.App
//------------------------------------------------------------------- //-------------------------------------------------------------------
public static class Version public static class Version
{ {
private static String version { get; } = "1.1.3.0"; private static String version { get; } = "1.1.4.0";
// Retrieve version. // Retrieve version.
public static String GetFullVersion () { return version; } public static String GetFullVersion () { return version; }
public static String GetAppVersion () public static String GetAppVersion ()
@@ -40,6 +40,10 @@ namespace Saxonite.Net.Standard.Base.App
//------------------------------------------------------------------- //-------------------------------------------------------------------
// Version history. // Version history.
//------------------------------------------------------------------- //-------------------------------------------------------------------
// 1.1.4 9-Aug-2021 Organisation Articles.
// - Journalist Article renamed Article and Organisation Id added.
// - Online Organisation Articles.
// - Admin Send Emails for User.
// 1.1.3 23-Jul-2021 Online Members. // 1.1.3 23-Jul-2021 Online Members.
// - Online Members. // - Online Members.
// - Admin organisation activation. // - Admin organisation activation.
+3 -3
View File
@@ -145,7 +145,7 @@ namespace Saxonite.Net.Standard.Base.App
// Activty data. // Activty data.
ActivityIndex = 200, ActivityIndex = 200,
UserActivity = 202, UserActivity = 202,
JournalistArticle = 210, Article = 210,
OrganisationOpportunity = 220, OrganisationOpportunity = 220,
OrganisationEvent = 225, OrganisationEvent = 225,
// Item link components. // Item link components.
@@ -234,9 +234,9 @@ namespace Saxonite.Net.Standard.Base.App
Avatar = 100, Avatar = 100,
/// <summary>User's profile image, uploaded awaiting confirmation.</summary> /// <summary>User's profile image, uploaded awaiting confirmation.</summary>
AvatarUpload = 101, AvatarUpload = 101,
/// <summary>Journalist Article image.</summary> /// <summary>Article image.</summary>
Article = 200, Article = 200,
/// <summary>Journalist Article image uploaded, awaiting confirmation.</summary> /// <summary>Article image uploaded, awaiting confirmation.</summary>
ArticleUpload = 201, ArticleUpload = 201,
} }
+68 -66
View File
@@ -6,7 +6,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// Code generated by Sarand Database Utilities Wed 14-Jul-2021 14:06:01 // Code generated by Sarand Database Utilities Fri 6-Aug-2021 19:02:06
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
namespace Saxonite.Base.App namespace Saxonite.Base.App
{ {
@@ -18,10 +18,10 @@ namespace Saxonite.Base.App
{ {
Unknown = 0, Unknown = 0,
ActivityIndex, ActivityIndex,
Article,
ItemAddress, ItemAddress,
ItemImage, ItemImage,
ItemSport, ItemSport,
JournalistArticle,
Organisation, Organisation,
OrganisationOpportunity, OrganisationOpportunity,
Region, Region,
@@ -53,6 +53,24 @@ namespace Saxonite.Base.App
ActivityIndex_UpdateOn, ActivityIndex_UpdateOn,
ActivityIndex_UpdateBy, ActivityIndex_UpdateBy,
ActivityIndex_UpdateHost, ActivityIndex_UpdateHost,
Article_Id,
Article_UserAccountIdAuthor,
Article_OrganisationId,
Article_SportIdPrimary,
Article_RegionIdPrimary,
Article_Headline,
Article_Summary,
Article_BodyData,
Article_PublishedAt,
Article_Notes,
Article_Flags,
Article_Status,
Article_CreateOn,
Article_CreateBy,
Article_CreateHost,
Article_UpdateOn,
Article_UpdateBy,
Article_UpdateHost,
ItemAddress_Id, ItemAddress_Id,
ItemAddress_ItemType, ItemAddress_ItemType,
ItemAddress_ItemId, ItemAddress_ItemId,
@@ -121,23 +139,6 @@ namespace Saxonite.Base.App
ItemSport_UpdateOn, ItemSport_UpdateOn,
ItemSport_UpdateBy, ItemSport_UpdateBy,
ItemSport_UpdateHost, ItemSport_UpdateHost,
JournalistArticle_Id,
JournalistArticle_UserAccountIdJournalist,
JournalistArticle_SportIdPrimary,
JournalistArticle_RegionIdPrimary,
JournalistArticle_Headline,
JournalistArticle_Summary,
JournalistArticle_BodyData,
JournalistArticle_PublishedAt,
JournalistArticle_Notes,
JournalistArticle_Flags,
JournalistArticle_Status,
JournalistArticle_CreateOn,
JournalistArticle_CreateBy,
JournalistArticle_CreateHost,
JournalistArticle_UpdateOn,
JournalistArticle_UpdateBy,
JournalistArticle_UpdateHost,
Organisation_Id, Organisation_Id,
Organisation_Name, Organisation_Name,
Organisation_OrganisationType, Organisation_OrganisationType,
@@ -305,7 +306,7 @@ namespace Saxonite.Base.App
//------------------------------------------------------------------- //-------------------------------------------------------------------
// Data members. // Data members.
private static readonly int tableCount = 15; private static readonly int tableCount = 15;
private static readonly int columnCount = 261; private static readonly int columnCount = 262;
private static ulong maxTextLen = 0; private static ulong maxTextLen = 0;
//------------------------------------------------------------------- //-------------------------------------------------------------------
@@ -452,10 +453,10 @@ namespace Saxonite.Base.App
private static readonly String[] tables = private static readonly String[] tables =
{ {
"ActivityIndex", "ActivityIndex",
"Article",
"ItemAddress", "ItemAddress",
"ItemImage", "ItemImage",
"ItemSport", "ItemSport",
"JournalistArticle",
"Organisation", "Organisation",
"OrganisationOpportunity", "OrganisationOpportunity",
"Region", "Region",
@@ -506,32 +507,18 @@ namespace Saxonite.Base.App
new ColumnDfn(1,"UpdateOn",9,93,false,23), new ColumnDfn(1,"UpdateOn",9,93,false,23),
new ColumnDfn(1,"UpdateBy",4,4,false,10), new ColumnDfn(1,"UpdateBy",4,4,false,10),
new ColumnDfn(1,"UpdateHost",0,12,false,100), new ColumnDfn(1,"UpdateHost",0,12,false,100),
new ColumnDfn(2,"Id",5,-5,true,19), new ColumnDfn(2,"Id",4,4,true,10),
new ColumnDfn(2,"ItemType",3,5,false,5), new ColumnDfn(2,"UserAccountIdAuthor",4,4,false,10),
new ColumnDfn(2,"ItemId",4,4,false,10), new ColumnDfn(2,"OrganisationId",4,4,false,10),
new ColumnDfn(2,"AddressType",3,5,false,5), new ColumnDfn(2,"SportIdPrimary",4,4,false,10),
new ColumnDfn(2,"Caption",0,-9,false,200), new ColumnDfn(2,"RegionIdPrimary",4,4,false,10),
new ColumnDfn(2,"Line1",0,-9,false,200), new ColumnDfn(2,"Headline",0,-9,false,200),
new ColumnDfn(2,"Line2",0,-9,false,200), new ColumnDfn(2,"Summary",0,-9,false,2000),
new ColumnDfn(2,"Line3",0,-9,false,200), new ColumnDfn(2,"BodyData",0,-9,false,0),
new ColumnDfn(2,"Town",0,-9,false,100), new ColumnDfn(2,"PublishedAt",9,93,false,16),
new ColumnDfn(2,"Province",0,-9,false,100),
new ColumnDfn(2,"RegionIdProvince",4,4,false,10),
new ColumnDfn(2,"Country",0,-9,false,100),
new ColumnDfn(2,"RegionIdCountry",4,4,false,10),
new ColumnDfn(2,"PostalCode",0,-9,false,32),
new ColumnDfn(2,"PhoneMain",0,-9,false,100),
new ColumnDfn(2,"LocationSource",0,12,false,100),
new ColumnDfn(2,"LocationStoredAt",9,93,false,16),
new ColumnDfn(2,"LocationUpdateRequired",1,-7,false,1),
new ColumnDfn(2,"LocationData",0,-9,false,4000),
new ColumnDfn(2,"LocationFormattedAddress",0,-9,false,4000),
new ColumnDfn(2,"LocationLatitude",8,3,false,9),
new ColumnDfn(2,"LocationLongitude",8,3,false,9),
new ColumnDfn(2,"LocationAltitude",8,3,false,9),
new ColumnDfn(2,"Notes",0,-9,false,2000), new ColumnDfn(2,"Notes",0,-9,false,2000),
new ColumnDfn(2,"Flags",3,5,false,5), new ColumnDfn(2,"Flags",3,5,false,5),
new ColumnDfn(2,"Status",0,1,false,3), new ColumnDfn(2,"Status",0,12,false,3),
new ColumnDfn(2,"CreateOn",9,93,false,23), new ColumnDfn(2,"CreateOn",9,93,false,23),
new ColumnDfn(2,"CreateBy",4,4,false,10), new ColumnDfn(2,"CreateBy",4,4,false,10),
new ColumnDfn(2,"CreateHost",0,12,false,100), new ColumnDfn(2,"CreateHost",0,12,false,100),
@@ -541,30 +528,48 @@ namespace Saxonite.Base.App
new ColumnDfn(3,"Id",5,-5,true,19), new ColumnDfn(3,"Id",5,-5,true,19),
new ColumnDfn(3,"ItemType",3,5,false,5), new ColumnDfn(3,"ItemType",3,5,false,5),
new ColumnDfn(3,"ItemId",4,4,false,10), new ColumnDfn(3,"ItemId",4,4,false,10),
new ColumnDfn(3,"ImageType",3,5,false,5), new ColumnDfn(3,"AddressType",3,5,false,5),
new ColumnDfn(3,"ImageSeq",2,-6,false,3), new ColumnDfn(3,"Caption",0,-9,false,200),
new ColumnDfn(3,"SessionUid",5,-5,false,19), new ColumnDfn(3,"Line1",0,-9,false,200),
new ColumnDfn(3,"ImageUid",4,4,false,10), new ColumnDfn(3,"Line2",0,-9,false,200),
new ColumnDfn(3,"Filename",0,-9,false,1024), new ColumnDfn(3,"Line3",0,-9,false,200),
new ColumnDfn(3,"Mime",0,12,false,64), new ColumnDfn(3,"Town",0,-9,false,100),
new ColumnDfn(3,"ContentType",0,12,false,128), new ColumnDfn(3,"Province",0,-9,false,100),
new ColumnDfn(3,"Width",4,4,false,10), new ColumnDfn(3,"RegionIdProvince",4,4,false,10),
new ColumnDfn(3,"Height",4,4,false,10), new ColumnDfn(3,"Country",0,-9,false,100),
new ColumnDfn(3,"ImageData",10,-3,false,0), new ColumnDfn(3,"RegionIdCountry",4,4,false,10),
new ColumnDfn(3,"PostalCode",0,-9,false,32),
new ColumnDfn(3,"PhoneMain",0,-9,false,100),
new ColumnDfn(3,"LocationSource",0,12,false,100),
new ColumnDfn(3,"LocationStoredAt",9,93,false,16),
new ColumnDfn(3,"LocationUpdateRequired",1,-7,false,1),
new ColumnDfn(3,"LocationData",0,-9,false,4000),
new ColumnDfn(3,"LocationFormattedAddress",0,-9,false,4000),
new ColumnDfn(3,"LocationLatitude",8,3,false,9),
new ColumnDfn(3,"LocationLongitude",8,3,false,9),
new ColumnDfn(3,"LocationAltitude",8,3,false,9),
new ColumnDfn(3,"Notes",0,-9,false,2000), new ColumnDfn(3,"Notes",0,-9,false,2000),
new ColumnDfn(3,"Flags",3,5,false,5), new ColumnDfn(3,"Flags",3,5,false,5),
new ColumnDfn(3,"Status",0,12,false,3), new ColumnDfn(3,"Status",0,1,false,3),
new ColumnDfn(3,"CreateOn",9,93,false,23), new ColumnDfn(3,"CreateOn",9,93,false,23),
new ColumnDfn(3,"CreateBy",4,4,false,10), new ColumnDfn(3,"CreateBy",4,4,false,10),
new ColumnDfn(3,"CreateHost",0,12,false,100), new ColumnDfn(3,"CreateHost",0,12,false,100),
new ColumnDfn(3,"UpdateOn",9,93,false,23), new ColumnDfn(3,"UpdateOn",9,93,false,23),
new ColumnDfn(3,"UpdateBy",4,4,false,10), new ColumnDfn(3,"UpdateBy",4,4,false,10),
new ColumnDfn(3,"UpdateHost",0,12,false,100), new ColumnDfn(3,"UpdateHost",0,12,false,100),
new ColumnDfn(4,"Id",4,4,true,10), new ColumnDfn(4,"Id",5,-5,true,19),
new ColumnDfn(4,"ItemType",3,5,false,5), new ColumnDfn(4,"ItemType",3,5,false,5),
new ColumnDfn(4,"ItemId",4,4,false,10), new ColumnDfn(4,"ItemId",4,4,false,10),
new ColumnDfn(4,"SportId",4,4,false,10), new ColumnDfn(4,"ImageType",3,5,false,5),
new ColumnDfn(4,"ItemSportData",0,-9,false,0), new ColumnDfn(4,"ImageSeq",2,-6,false,3),
new ColumnDfn(4,"SessionUid",5,-5,false,19),
new ColumnDfn(4,"ImageUid",4,4,false,10),
new ColumnDfn(4,"Filename",0,-9,false,1024),
new ColumnDfn(4,"Mime",0,12,false,64),
new ColumnDfn(4,"ContentType",0,12,false,128),
new ColumnDfn(4,"Width",4,4,false,10),
new ColumnDfn(4,"Height",4,4,false,10),
new ColumnDfn(4,"ImageData",10,-3,false,0),
new ColumnDfn(4,"Notes",0,-9,false,2000), new ColumnDfn(4,"Notes",0,-9,false,2000),
new ColumnDfn(4,"Flags",3,5,false,5), new ColumnDfn(4,"Flags",3,5,false,5),
new ColumnDfn(4,"Status",0,12,false,3), new ColumnDfn(4,"Status",0,12,false,3),
@@ -575,13 +580,10 @@ namespace Saxonite.Base.App
new ColumnDfn(4,"UpdateBy",4,4,false,10), new ColumnDfn(4,"UpdateBy",4,4,false,10),
new ColumnDfn(4,"UpdateHost",0,12,false,100), new ColumnDfn(4,"UpdateHost",0,12,false,100),
new ColumnDfn(5,"Id",4,4,true,10), new ColumnDfn(5,"Id",4,4,true,10),
new ColumnDfn(5,"UserAccountIdJournalist",4,4,false,10), new ColumnDfn(5,"ItemType",3,5,false,5),
new ColumnDfn(5,"SportIdPrimary",4,4,false,10), new ColumnDfn(5,"ItemId",4,4,false,10),
new ColumnDfn(5,"RegionIdPrimary",4,4,false,10), new ColumnDfn(5,"SportId",4,4,false,10),
new ColumnDfn(5,"Headline",0,-9,false,200), new ColumnDfn(5,"ItemSportData",0,-9,false,0),
new ColumnDfn(5,"Summary",0,-9,false,2000),
new ColumnDfn(5,"BodyData",0,-9,false,0),
new ColumnDfn(5,"PublishedAt",9,93,false,16),
new ColumnDfn(5,"Notes",0,-9,false,2000), new ColumnDfn(5,"Notes",0,-9,false,2000),
new ColumnDfn(5,"Flags",3,5,false,5), new ColumnDfn(5,"Flags",3,5,false,5),
new ColumnDfn(5,"Status",0,12,false,3), new ColumnDfn(5,"Status",0,12,false,3),
@@ -52,7 +52,7 @@ namespace Saxonite.Net.Standard.Base.App
// Activty data. // Activty data.
dataItemTypeCodes.Add(Sax.DataItemType.ActivityIndex, "ActivityIndex", "Activity Index"); dataItemTypeCodes.Add(Sax.DataItemType.ActivityIndex, "ActivityIndex", "Activity Index");
dataItemTypeCodes.Add(Sax.DataItemType.UserActivity, "UserActivity", "User Activity"); dataItemTypeCodes.Add(Sax.DataItemType.UserActivity, "UserActivity", "User Activity");
dataItemTypeCodes.Add(Sax.DataItemType.JournalistArticle, "JournalistArticle", "Journalist Article"); dataItemTypeCodes.Add(Sax.DataItemType.Article, "Article", "Article");
dataItemTypeCodes.Add(Sax.DataItemType.OrganisationOpportunity, "OrganisationOpportunity", "Organisation Opportunity"); dataItemTypeCodes.Add(Sax.DataItemType.OrganisationOpportunity, "OrganisationOpportunity", "Organisation Opportunity");
dataItemTypeCodes.Add(Sax.DataItemType.OrganisationEvent, "OrganisationEvent", "Organisation Event"); dataItemTypeCodes.Add(Sax.DataItemType.OrganisationEvent, "OrganisationEvent", "Organisation Event");
// Item link components. // Item link components.
@@ -29,7 +29,7 @@ namespace Saxonite.Net.Standard.Base.Bus
UserActivity_ViewedAtLast, UserActivity_ViewedAtLast,
UserActivity_Reaction, UserActivity_Reaction,
UserActivity_ReactedAtLast, UserActivity_ReactedAtLast,
// Journalist Article. // Article.
Article_Headline, Article_Headline,
Article_Summary, Article_Summary,
// Organisation opportunity. // Organisation opportunity.
@@ -11,9 +11,9 @@ using System.Xml.Linq;
namespace Saxonite.Net.Standard.Base.Bus namespace Saxonite.Net.Standard.Base.Bus
{ {
//======================================================================= //=======================================================================
// Journalist Article - Content data. // Article - Content data.
//======================================================================= //=======================================================================
partial class SaxJournalistArticle partial class SaxArticle
{ {
//------------------------------------------------------------------- //-------------------------------------------------------------------
// Definitions. // Definitions.
@@ -8,9 +8,9 @@ using System.Text;
namespace Saxonite.Net.Standard.Base.Bus namespace Saxonite.Net.Standard.Base.Bus
{ {
//======================================================================= //=======================================================================
// Journalist Article. // Article.
//======================================================================= //=======================================================================
public abstract partial class SaxJournalistArticle : SacsHierarchyItem public abstract partial class SaxArticle : SacsHierarchyItem
{ {
//------------------------------------------------------------------- //-------------------------------------------------------------------
// Columns. // Columns.
@@ -18,12 +18,15 @@ namespace Saxonite.Net.Standard.Base.Bus
{ {
Pos, Pos,
Id, Id,
// Journalist. // Author.
UserAccountIdJournalist, UserAccountIdAuthor,
Journalist_DisplayName, Author_DisplayName,
Journalist_Title, Author_Title,
Journalist_FirstName, Author_FirstName,
Journalist_LastName, Author_LastName,
// Organisation.
OrganisationId,
Organisation_Name,
// Sport. // Sport.
SportIdPrimary, SportIdPrimary,
Sport_Name, Sport_Name,
@@ -50,7 +53,8 @@ namespace Saxonite.Net.Standard.Base.Bus
/// <summary>Properties other than common.</summary> /// <summary>Properties other than common.</summary>
public class DataProperties public class DataProperties
{ {
public SysId UserAccountIdJournalist { get; set; } public SysId UserAccountIdAuthor { get; set; }
public SysId OrganisationId { get; set; }
public String Headline { get; set; } = String.Empty; public String Headline { get; set; } = String.Empty;
public String Summary { get; set; } = String.Empty; public String Summary { get; set; } = String.Empty;
public SysId SportIdPrimary { get; set; } public SysId SportIdPrimary { get; set; }
@@ -71,10 +75,15 @@ namespace Saxonite.Net.Standard.Base.Bus
Status = DefaultStatus; Status = DefaultStatus;
} }
// Properties. // Properties.
public SysId UserAccountIdJournalist public SysId UserAccountIdAuthor
{ {
get { return data.UserAccountIdJournalist; } get { return data.UserAccountIdAuthor; }
set { CheckChanged(data.UserAccountIdJournalist, value); data.UserAccountIdJournalist = value; } set { CheckChanged(data.UserAccountIdAuthor, value); data.UserAccountIdAuthor = value; }
}
public SysId OrganisationId
{
get { return data.OrganisationId; }
set { CheckChanged(data.OrganisationId, value); data.OrganisationId = value; }
} }
public SysId SportIdPrimary public SysId SportIdPrimary
{ {
@@ -109,7 +118,8 @@ namespace Saxonite.Net.Standard.Base.Bus
// Population. // Population.
internal void PopulateFrom(Data data) internal void PopulateFrom(Data data)
{ {
UserAccountIdJournalist = data.UserAccountIdJournalist; UserAccountIdAuthor = data.UserAccountIdAuthor;
OrganisationId = data.OrganisationId;
SportIdPrimary = data.SportIdPrimary; SportIdPrimary = data.SportIdPrimary;
RegionIdPrimary = data.RegionIdPrimary; RegionIdPrimary = data.RegionIdPrimary;
Headline = data.Headline; Headline = data.Headline;
@@ -131,7 +141,8 @@ namespace Saxonite.Net.Standard.Base.Bus
public new class ErrField : SacsHierarchyItem.ErrField public new class ErrField : SacsHierarchyItem.ErrField
{ {
// Identifies the field that has invalid data. // Identifies the field that has invalid data.
public ValidValue UserAccountIdJournalist { get; set; } = ValidValue.Valid; public ValidValue UserAccountIdAuthor { get; set; } = ValidValue.Valid;
public ValidValue OrganisationId { get; set; } = ValidValue.Valid;
public ValidValue SportIdPrimary { get; set; } = ValidValue.Valid; public ValidValue SportIdPrimary { get; set; } = ValidValue.Valid;
public ValidValue RegionIdPrimary { get; set; } = ValidValue.Valid; public ValidValue RegionIdPrimary { get; set; } = ValidValue.Valid;
public ValidValue Headline { get; set; } = ValidValue.Valid; public ValidValue Headline { get; set; } = ValidValue.Valid;
@@ -146,10 +157,11 @@ namespace Saxonite.Net.Standard.Base.Bus
//------------------------------------------------------------------- //-------------------------------------------------------------------
// Construction. // Construction.
protected SaxJournalistArticle(SysId id, SysId UserAccountIdJournalist) : base(id) protected SaxArticle(SysId id, SysId UserAccountIdAuthor, SysId organisationId) : base(id)
{ {
base.SetData(data); base.SetData(data);
this.UserAccountIdJournalist = UserAccountIdJournalist; this.UserAccountIdAuthor = UserAccountIdAuthor;
this.OrganisationId = organisationId;
Status = DefaultStatus; Status = DefaultStatus;
} }
@@ -175,7 +187,7 @@ namespace Saxonite.Net.Standard.Base.Bus
// Utilities. // Utilities.
public ItemId GetItemId() public ItemId GetItemId()
{ {
return new ItemId((short)Sax.DataItemType.JournalistArticle, Id); return new ItemId((short)Sax.DataItemType.Article, Id);
} }
//------------------------------------------------------------------- //-------------------------------------------------------------------
@@ -187,14 +199,21 @@ namespace Saxonite.Net.Standard.Base.Bus
// Properties that cannot be changed if previously specified. // Properties that cannot be changed if previously specified.
if (SysId.IsValid(Id) && SysId.ToInt(Id) != SysId.ToInt(data.Id)) if (SysId.IsValid(Id) && SysId.ToInt(Id) != SysId.ToInt(data.Id))
throw new NotSupportedException(fn + " Id cannot be changed"); throw new NotSupportedException(fn + " Id cannot be changed");
if (SysId.IsValid(UserAccountIdJournalist) && SysId.ToInt(UserAccountIdJournalist) != SysId.ToInt(data.UserAccountIdJournalist)) if (SysId.IsValid(UserAccountIdAuthor) && SysId.ToInt(UserAccountIdAuthor) != SysId.ToInt(data.UserAccountIdAuthor))
throw new NotSupportedException(fn + " UserAccountIdJournalist cannot be changed"); throw new NotSupportedException(fn + " UserAccountIdAuthor cannot be changed");
if (SysId.IsValid(OrganisationId) && SysId.ToInt(OrganisationId) != SysId.ToInt(data.OrganisationId))
throw new NotSupportedException(fn + " OrganisationId cannot be changed");
this.data.PopulateFrom(data); this.data.PopulateFrom(data);
} }
public SysId UserAccountIdJournalist public SysId UserAccountIdAuthor
{ {
get { return data.UserAccountIdJournalist; } get { return data.UserAccountIdAuthor; }
protected set { data.UserAccountIdJournalist = value; } protected set { data.UserAccountIdAuthor = value; }
}
public SysId OrganisationId
{
get { return data.OrganisationId; }
protected set { data.OrganisationId = value; }
} }
public String Headline public String Headline
{ {
@@ -254,7 +273,8 @@ namespace Saxonite.Net.Standard.Base.Bus
// List filtering. // List filtering.
public List<SysId> IdsIncluded { get; } = new List<SysId>(); public List<SysId> IdsIncluded { get; } = new List<SysId>();
public List<SysId> IdsExcluded { get; } = new List<SysId>(); public List<SysId> IdsExcluded { get; } = new List<SysId>();
public List<SysId> UserAccountIdsJournalistIncluded { get; } = new List<SysId>(); public List<SysId> UserAccountIdsAuthorIncluded { get; } = new List<SysId>();
public List<SysId> OrganisationIdsIncluded { get; } = new List<SysId>();
public List<SysId> SportIdsIncluded { get; set; } = new List<SysId>(); public List<SysId> SportIdsIncluded { get; set; } = new List<SysId>();
public List<SysId> RegionIdsIncluded { get; } = new List<SysId>(); public List<SysId> RegionIdsIncluded { get; } = new List<SysId>();
public String HeadlinePartial { get; set; } public String HeadlinePartial { get; set; }
@@ -270,7 +290,7 @@ namespace Saxonite.Net.Standard.Base.Bus
} }
//======================================================================= //=======================================================================
// Item list extension methods. // Item list extension methods.
public static class SaxJournalistArticleList public static class SaxAuthorArticleList
{ {
} }
@@ -58,6 +58,10 @@ namespace Saxonite.Net.Standard.Base.Consoles
} }
public ItemId ItemId { get; } public ItemId ItemId { get; }
public DateTime EffectiveOn { get; } public DateTime EffectiveOn { get; }
public SysId OrganisationId { get; set; }
public String Organisation { get; set; }
public SysId UserAccountIdAuthor { get; set; }
public String Author { get; set; }
public String Caption { get; protected set; } public String Caption { get; protected set; }
public String Blurb { get; protected set; } public String Blurb { get; protected set; }
public SysId SportId { get; protected set; } public SysId SportId { get; protected set; }
@@ -78,7 +82,7 @@ namespace Saxonite.Net.Standard.Base.Consoles
private SaxInternals internals = null; private SaxInternals internals = null;
private readonly List<Sax.DataItemType> validActivityItemTypes = new List<Sax.DataItemType>() private readonly List<Sax.DataItemType> validActivityItemTypes = new List<Sax.DataItemType>()
{ {
Sax.DataItemType.JournalistArticle, Sax.DataItemType.Article,
Sax.DataItemType.OrganisationOpportunity, Sax.DataItemType.OrganisationOpportunity,
}; };
@@ -111,9 +115,9 @@ namespace Saxonite.Net.Standard.Base.Consoles
// Store Activity Index for Specific activities. // Store Activity Index for Specific activities.
//------------------------------------------------------------------- //-------------------------------------------------------------------
/// <summary> /// <summary>
/// Store the Activity Index for a Journalist Article. /// Store the Activity Index for an Article.
/// </summary> /// </summary>
public bool StoreActivityIndex(SaxJournalistArticle article, DbUpdateInfo dbUpdateInfo) public bool StoreActivityIndex(SaxArticle article, DbUpdateInfo dbUpdateInfo)
{ {
ClearErrorState(); ClearErrorState();
@@ -139,7 +143,7 @@ namespace Saxonite.Net.Standard.Base.Consoles
} }
return ClearActivityIndex(article.GetItemId(), dbUpdateInfo); return ClearActivityIndex(article.GetItemId(), dbUpdateInfo);
} }
public bool ClearActivityIndex(SaxJournalistArticle article, DbUpdateInfo dbUpdateInfo) public bool ClearActivityIndex(SaxArticle article, DbUpdateInfo dbUpdateInfo)
{ {
return ClearActivityIndex(article.GetItemId(), dbUpdateInfo); return ClearActivityIndex(article.GetItemId(), dbUpdateInfo);
} }
@@ -2,6 +2,7 @@
using Sarand.Net.Standard.Base.Bus; using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Core; using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Dbas; using Sarand.Net.Standard.Base.Dbas;
using Sarand.Net.Standard.Base.Helpers;
using Sarand.Net.Standard.Base.Utils; using Sarand.Net.Standard.Base.Utils;
using Saxonite.Base.App; using Saxonite.Base.App;
using Saxonite.Net.Standard.Base.Bus; using Saxonite.Net.Standard.Base.Bus;
@@ -80,10 +81,18 @@ namespace Saxonite.Net.Standard.Base.Mgr
ClearErrorState(); ClearErrorState();
// Email address. // Email address.
if (errField.EmailAddress != SacsHierarchyItem.ValidValue.Ignore && !IsValidValue(data.EmailAddress, "email", (long)SaxDbDfn_Core.GetColTextLen(SaxDbDfn_Core.ColumnIdx.UserAccount_EmailAddress), true)) if (errField.EmailAddress != SacsHierarchyItem.ValidValue.Ignore)
{ {
errField.EmailAddress = SacsHierarchyItem.ValidValue.Invalid; if (!IsValidValue(data.EmailAddress, "email", (long)SaxDbDfn_Core.GetColTextLen(SaxDbDfn_Core.ColumnIdx.UserAccount_EmailAddress), true))
return false; {
errField.EmailAddress = SacsHierarchyItem.ValidValue.Invalid;
return false;
}
if (!SacsDataValidationHelper.IsValidEmailAddress(data.EmailAddress))
{
errField.EmailAddress = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState("Invalid email address");
}
} }
// Title. // Title.
if (errField.Title != SacsHierarchyItem.ValidValue.Ignore && !IsValidValue(data.Title, "Title", (long)SaxDbDfn_Core.GetColTextLen(SaxDbDfn_Core.ColumnIdx.UserAccount_Title))) if (errField.Title != SacsHierarchyItem.ValidValue.Ignore && !IsValidValue(data.Title, "Title", (long)SaxDbDfn_Core.GetColTextLen(SaxDbDfn_Core.ColumnIdx.UserAccount_Title)))
@@ -2,6 +2,7 @@
using Sarand.Net.Standard.Base.Bus; using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Core; using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Dbas; using Sarand.Net.Standard.Base.Dbas;
using Sarand.Net.Standard.Base.Utils;
using Saxonite.Base.App; using Saxonite.Base.App;
using Saxonite.Net.Standard.Base.App; using Saxonite.Net.Standard.Base.App;
using Saxonite.Net.Standard.Base.Bus; using Saxonite.Net.Standard.Base.Bus;
@@ -32,6 +33,7 @@ namespace Saxonite.Net.Standard.Base.Mgr
prmUserOrganisation.StatusCat = statusCat; prmUserOrganisation.StatusCat = statusCat;
return GetUserOrganisationCount(prmUserOrganisation) > 0; return GetUserOrganisationCount(prmUserOrganisation) > 0;
} }
/// <summary> /// <summary>
/// Does the user have the specified role with the organisation. /// Does the user have the specified role with the organisation.
/// </summary> /// </summary>
@@ -40,6 +42,7 @@ namespace Saxonite.Net.Standard.Base.Mgr
if (!SysId.IsValid(userAccountId) || !SysId.IsValid(organisationId) || organisationRole <= 0) return false; if (!SysId.IsValid(userAccountId) || !SysId.IsValid(organisationId) || organisationRole <= 0) return false;
return GetOrganisationRolesForUser(userAccountId, organisationId, statusCat).Contains(organisationRole); return GetOrganisationRolesForUser(userAccountId, organisationId, statusCat).Contains(organisationRole);
} }
/// <summary> /// <summary>
/// Retrieve the roles that a user has with the organisation. /// Retrieve the roles that a user has with the organisation.
/// </summary> /// </summary>
@@ -57,6 +60,53 @@ namespace Saxonite.Net.Standard.Base.Mgr
return organisationRoles; return organisationRoles;
} }
public class OrganisationIdName
{
public SysId Id { get; internal set; }
public String Name { get; internal set; }
}
/// <summary>
/// Get list of organisation Ids that the user has the specified role with.
/// </summary>
public List<OrganisationIdName> GetOrganisationsForUserRole(SysId userAccountId, Sax.OrganisationRole organisationRole, SaxUserOrganisation.StatusCat statusCat = SaxUserOrganisation.StatusCat.ActiveOnly)
{
List<OrganisationIdName> organisationsData = new List<OrganisationIdName>();
String organisationRoleCode = Internals.OrganisationRoleCodes.GetCodeForType(organisationRole);
if (!SysId.IsValid(userAccountId) || StringUtil.IsEmpty(organisationRoleCode)) return organisationsData;
// Columns.
ColumnDfn colOrganisationId = GetUserOrganisationColumnDfn(SaxUserOrganisation.Column.OrganisationId);
ColumnDfn colOrganisationName = GetUserOrganisationColumnDfn(SaxUserOrganisation.Column.Organisation_Name);
// Filter.
SaxUserOrganisation.Params prmUserOrganisation = new SaxUserOrganisation.Params();
prmUserOrganisation.UserAccountIdsIncluded.Add(userAccountId);
prmUserOrganisation.OrganisationStatusCat = SaxOrganisation.StatusCat.ActiveOnly;
prmUserOrganisation.OrganisationMembersOnly = true;
prmUserOrganisation.OrganisationRoles.Add(organisationRole);
prmUserOrganisation.StatusCat = statusCat;
prmUserOrganisation.SortColumns.Add(colOrganisationName);
// Query.
using (DbResultSet resultSet = ExecuteUserOrganisationQuery(new List<ColumnDfn>() { colOrganisationId, colOrganisationName }, prmUserOrganisation))
{
while (resultSet != null && resultSet.NextRecord())
{
NamedValue.Map values = resultSet.GetRecordValues();
SysId organisationId = new SysId(values.GetLong(colOrganisationId.DataName));
String organisationName = values.GetString(colOrganisationName.DataName);
if (SysId.IsValid(organisationId) && !StringUtil.IsEmpty(organisationName))
{
OrganisationIdName organisationData = new OrganisationIdName()
{
Id = organisationId,
Name = organisationName
};
organisationsData.Add(organisationData);
}
}
}
return organisationsData;
}
//------------------------------------------------------------------- //-------------------------------------------------------------------
// Create item. // Create item.
public abstract SaxUserOrganisation CreateUserOrganisation(SysId userAccountId, SysId OrganisationId); public abstract SaxUserOrganisation CreateUserOrganisation(SysId userAccountId, SysId OrganisationId);
@@ -15,56 +15,56 @@ namespace Saxonite.Net.Standard.Base.Mgr
partial class SaxActivityMgr partial class SaxActivityMgr
{ {
//******************************************************************* //*******************************************************************
// Activity Mgr - Journalist Article // Activity Mgr - Article
//******************************************************************* //*******************************************************************
// Utilities. // Utilities.
//------------------------------------------------------------------- //-------------------------------------------------------------------
// Create item. // Create item.
public abstract SaxJournalistArticle CreateJournalistArticle(SysId userAccountIdJournalist); public abstract SaxArticle CreateArticle(SysId userAccountIdAuthor, SysId organisationId);
//------------------------------------------------------------------- //-------------------------------------------------------------------
// Item exists. // Item exists.
public bool JournalistArticleExistsById(SysId id) public bool ArticleExistsById(SysId id)
{ {
ClearErrorState(); ClearErrorState();
if (!SysId.IsValid(id)) return false; if (!SysId.IsValid(id)) return false;
SaxJournalistArticle.Params prmJournalistArticle = new SaxJournalistArticle.Params(); SaxArticle.Params prmArticle = new SaxArticle.Params();
prmJournalistArticle.IdsIncluded.Add(id); prmArticle.IdsIncluded.Add(id);
prmJournalistArticle.StatusCat = SaxJournalistArticle.StatusCat.Any; prmArticle.StatusCat = SaxArticle.StatusCat.Any;
return GetJournalistArticleCount(prmJournalistArticle) == 1; return GetArticleCount(prmArticle) == 1;
} }
//------------------------------------------------------------------- //-------------------------------------------------------------------
// Retrieve individual items. // Retrieve individual items.
public abstract SaxJournalistArticle GetJournalistArticle(SaxJournalistArticle.Params prmJournalistArticle); public abstract SaxArticle GetArticle(SaxArticle.Params prmArticle);
public SaxJournalistArticle GetJournalistArticleById(SysId id) public SaxArticle GetArticleById(SysId id)
{ {
ClearErrorState(); ClearErrorState();
if (!SysId.IsValid(id)) return null; if (!SysId.IsValid(id)) return null;
SaxJournalistArticle.Params prmJournalistArticle = new SaxJournalistArticle.Params(); SaxArticle.Params prmArticle = new SaxArticle.Params();
prmJournalistArticle.IdsIncluded.Add(id); prmArticle.IdsIncluded.Add(id);
prmJournalistArticle.StatusCat = SaxJournalistArticle.StatusCat.Any; prmArticle.StatusCat = SaxArticle.StatusCat.Any;
return GetJournalistArticle(prmJournalistArticle); return GetArticle(prmArticle);
} }
//------------------------------------------------------------------- //-------------------------------------------------------------------
// Validate item data. // Validate item data.
public bool IsValidJournalistArticle(SaxJournalistArticle journalistArticle) public bool IsValidArticle(SaxArticle article)
{ {
ClearErrorState(); ClearErrorState();
if (journalistArticle == null) return SetErrorState(ErrorMessage.ItemNotSpecified); if (article == null) return SetErrorState(ErrorMessage.ItemNotSpecified);
return IsValidJournalistArticleData(journalistArticle.GetData(), new SaxJournalistArticle.ErrField()); return IsValidArticleData(article.GetData(), new SaxArticle.ErrField());
} }
public virtual bool IsValidJournalistArticleData(SaxJournalistArticle.Data data, SaxJournalistArticle.ErrField errField) public virtual bool IsValidArticleData(SaxArticle.Data data, SaxArticle.ErrField errField)
{ {
ClearErrorState(); ClearErrorState();
// User Account - Journalist. // User Account - Author.
if (errField.UserAccountIdJournalist != SacsHierarchyItem.ValidValue.Ignore && !SysId.IsValid(data.UserAccountIdJournalist)) if (errField.UserAccountIdAuthor != SacsHierarchyItem.ValidValue.Ignore && !SysId.IsValid(data.UserAccountIdAuthor))
{ {
errField.UserAccountIdJournalist = SacsHierarchyItem.ValidValue.Invalid; errField.UserAccountIdAuthor = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState("User must be specified"); return SetErrorState("Author must be specified");
} }
// Primary Sport. // Primary Sport.
if (errField.SportIdPrimary != SacsHierarchyItem.ValidValue.Ignore && !SysId.IsValid(data.SportIdPrimary)) if (errField.SportIdPrimary != SacsHierarchyItem.ValidValue.Ignore && !SysId.IsValid(data.SportIdPrimary))
@@ -80,32 +80,32 @@ namespace Saxonite.Net.Standard.Base.Mgr
} }
// Headline. // Headline.
if (errField.Headline != SacsHierarchyItem.ValidValue.Ignore && !IsValidValue(data.Headline, "headline", (long)SaxDbDfn_Core.GetColTextLen(SaxDbDfn_Core.ColumnIdx.JournalistArticle_Headline), true)) if (errField.Headline != SacsHierarchyItem.ValidValue.Ignore && !IsValidValue(data.Headline, "headline", (long)SaxDbDfn_Core.GetColTextLen(SaxDbDfn_Core.ColumnIdx.Article_Headline), true))
{ {
errField.Headline = SacsHierarchyItem.ValidValue.Invalid; errField.Headline = SacsHierarchyItem.ValidValue.Invalid;
return false; return false;
} }
// Summary. // Summary.
if (errField.Summary != SacsHierarchyItem.ValidValue.Ignore && !IsValidValue(data.Summary, "summary", (long)SaxDbDfn_Core.GetColTextLen(SaxDbDfn_Core.ColumnIdx.JournalistArticle_Summary), true)) if (errField.Summary != SacsHierarchyItem.ValidValue.Ignore && !IsValidValue(data.Summary, "summary", (long)SaxDbDfn_Core.GetColTextLen(SaxDbDfn_Core.ColumnIdx.Article_Summary), true))
{ {
errField.Summary = SacsHierarchyItem.ValidValue.Invalid; errField.Summary = SacsHierarchyItem.ValidValue.Invalid;
return false; return false;
} }
// Common properties. // Common properties.
if (errField.Notes != SacsHierarchyItem.ValidValue.Ignore && !IsValidValue(data.Notes, "notes", (long)SaxDbDfn_Core.GetColTextLen(SaxDbDfn_Core.ColumnIdx.JournalistArticle_Notes))) if (errField.Notes != SacsHierarchyItem.ValidValue.Ignore && !IsValidValue(data.Notes, "notes", (long)SaxDbDfn_Core.GetColTextLen(SaxDbDfn_Core.ColumnIdx.Article_Notes)))
{ {
errField.Notes = SacsHierarchyItem.ValidValue.Invalid; errField.Notes = SacsHierarchyItem.ValidValue.Invalid;
return false; return false;
} }
if (errField.Status != SacsHierarchyItem.ValidValue.Ignore) if (errField.Status != SacsHierarchyItem.ValidValue.Ignore)
{ {
if (!IsValidValue(data.StatusCode, "status", (long)SaxDbDfn_Core.GetColTextLen(SaxDbDfn_Core.ColumnIdx.JournalistArticle_Status), true, true)) if (!IsValidValue(data.StatusCode, "status", (long)SaxDbDfn_Core.GetColTextLen(SaxDbDfn_Core.ColumnIdx.Article_Status), true, true))
{ {
errField.Status = SacsHierarchyItem.ValidValue.Invalid; errField.Status = SacsHierarchyItem.ValidValue.Invalid;
return false; return false;
} }
if (!SaxJournalistArticle.ValidStatuses.Contains(data.Status)) if (!SaxArticle.ValidStatuses.Contains(data.Status))
{ {
errField.Status = SacsHierarchyItem.ValidValue.Invalid; errField.Status = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState(ErrorMessage.InvalidStatus); return SetErrorState(ErrorMessage.InvalidStatus);
@@ -117,17 +117,41 @@ namespace Saxonite.Net.Standard.Base.Mgr
if (!data.IsStatusDeleted) if (!data.IsStatusDeleted)
{ {
// User Account - Journalist. // User Account - Author.
if (errField.UserAccountIdJournalist != SacsHierarchyItem.ValidValue.Ignore && SysId.IsValid(data.UserAccountIdJournalist)) if (errField.UserAccountIdAuthor != SacsHierarchyItem.ValidValue.Ignore && SysId.IsValid(data.UserAccountIdAuthor))
{ {
SaxUserAccount.Params prmUserAccount = new SaxUserAccount.Params(); if (SysId.IsValid(data.OrganisationId))
prmUserAccount.IdsIncluded.Add(data.UserAccountIdJournalist);
prmUserAccount.ActiveRoles.Add(App.Sax.UserRole.Journalist);
prmUserAccount.StatusCat = SaxUserAccount.StatusCat.NotDeleted;
if (AccountMgr.GetUserAccountCount(prmUserAccount) < 1)
{ {
errField.UserAccountIdJournalist = SacsHierarchyItem.ValidValue.Invalid; // Validate user.
return SetErrorState("User must be active Journalist"); if (!AccountMgr.UserAccountExistsById(data.UserAccountIdAuthor))
{
errField.UserAccountIdAuthor = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState("Invalid Author specified");
}
}
else
{
// Organisation not specified - user must be a journalist.
SaxUserAccount.Params prmUserAccount = new SaxUserAccount.Params();
prmUserAccount.IdsIncluded.Add(data.UserAccountIdAuthor);
prmUserAccount.ActiveRoles.Add(App.Sax.UserRole.Journalist);
prmUserAccount.StatusCat = SaxUserAccount.StatusCat.NotDeleted;
if (AccountMgr.GetUserAccountCount(prmUserAccount) < 1)
{
errField.UserAccountIdAuthor = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState("User must be active Journalist");
}
}
}
// Organisation.
if (errField.OrganisationId != SacsHierarchyItem.ValidValue.Ignore && SysId.IsValid(data.OrganisationId))
{
// Validate organisation.
if (!AccountMgr.OrganisationExistsById(data.OrganisationId))
{
errField.OrganisationId = SacsHierarchyItem.ValidValue.Invalid;
return SetErrorState("Invalid Organisation specified");
} }
} }
@@ -163,48 +187,48 @@ namespace Saxonite.Net.Standard.Base.Mgr
} }
//------------------------------------------------------------------- //-------------------------------------------------------------------
// JournalistArticle database interface. // Article database interface.
public abstract bool InsertJournalistArticle(SaxJournalistArticle journalistArticle, DbUpdateInfo dbUpdateInfo); public abstract bool InsertArticle(SaxArticle article, DbUpdateInfo dbUpdateInfo);
public abstract bool UpdateJournalistArticle(SaxJournalistArticle journalistArticle, DbUpdateInfo dbUpdateInfo); public abstract bool UpdateArticle(SaxArticle article, DbUpdateInfo dbUpdateInfo);
public virtual bool JournalistArticleCanBeDeleted(SaxJournalistArticle journalistArticle) public virtual bool ArticleCanBeDeleted(SaxArticle article)
{ {
ClearErrorState(); ClearErrorState();
return true; return true;
} }
public abstract bool DeleteJournalistArticle(SaxJournalistArticle journalistArticle, DbUpdateInfo dbUpdateInfo); public abstract bool DeleteArticle(SaxArticle article, DbUpdateInfo dbUpdateInfo);
//------------------------------------------------------------------- //-------------------------------------------------------------------
// JournalistArticle list: // Article list:
public abstract ColumnDfn GetJournalistArticleColumnDfn(SaxJournalistArticle.Column columnId, String caption = "", int width = 0); public abstract ColumnDfn GetArticleColumnDfn(SaxArticle.Column columnId, String caption = "", int width = 0);
public abstract List<String> GetJournalistArticleQueryFilter(SaxJournalistArticle.Params prmJournalistArticle); public abstract List<String> GetArticleQueryFilter(SaxArticle.Params prmArticle);
public abstract long GetJournalistArticleCount(SaxJournalistArticle.Params prmJournalistArticle); public abstract long GetArticleCount(SaxArticle.Params prmArticle);
public abstract List<SaxJournalistArticle> GetJournalistArticleList(SaxJournalistArticle.Params prmJournalistArticle); public abstract List<SaxArticle> GetArticleList(SaxArticle.Params prmArticle);
public abstract DbResultSet ExecuteJournalistArticleQuery(List<ColumnDfn> columns, SaxJournalistArticle.Params prmJournalistArticle); public abstract DbResultSet ExecuteArticleQuery(List<ColumnDfn> columns, SaxArticle.Params prmArticle);
//------------------------------------------------------------------- //-------------------------------------------------------------------
/// <summary> /// <summary>
/// Extract and format result set data value where specific handling is required. /// Extract and format result set data value where specific handling is required.
/// <para>Where response is an invalid data value, format value using column.FormatValue(values).</para> /// <para>Where response is an invalid data value, format value using column.FormatValue(values).</para>
/// </summary> /// </summary>
public virtual DataValue GetJournalistArticleDataValue(ColumnDfn column, NamedValue.Map values) public virtual DataValue GetArticleDataValue(ColumnDfn column, NamedValue.Map values)
{ {
DataValue value = new DataValue(); DataValue value = new DataValue();
switch ((SaxJournalistArticle.Column)column.Id) switch ((SaxArticle.Column)column.Id)
{ {
//----------------------------------------------------------- //-----------------------------------------------------------
// Journalist display name. // Author display name.
case SaxJournalistArticle.Column.Journalist_DisplayName: case SaxArticle.Column.Author_DisplayName:
{ {
String userTitle = values.GetValue(GetJournalistArticleColumnDfn(SaxJournalistArticle.Column.Journalist_Title).DataName).ToString(); String userTitle = values.GetValue(GetArticleColumnDfn(SaxArticle.Column.Author_Title).DataName).ToString();
String userFirstName = values.GetValue(GetJournalistArticleColumnDfn(SaxJournalistArticle.Column.Journalist_FirstName).DataName).ToString(); String userFirstName = values.GetValue(GetArticleColumnDfn(SaxArticle.Column.Author_FirstName).DataName).ToString();
String userLastName = values.GetValue(GetJournalistArticleColumnDfn(SaxJournalistArticle.Column.Journalist_LastName).DataName).ToString(); String userLastName = values.GetValue(GetArticleColumnDfn(SaxArticle.Column.Author_LastName).DataName).ToString();
value = new DataValue(SaxUserAccount.GetDisplayName(userTitle, userFirstName, userLastName)); value = new DataValue(SaxUserAccount.GetDisplayName(userTitle, userFirstName, userLastName));
} }
break; break;
//----------------------------------------------------------- //-----------------------------------------------------------
// Summary - limit to 200 chars. // Summary - limit to 200 chars.
case SaxJournalistArticle.Column.Summary: case SaxArticle.Column.Summary:
{ {
value = new DataValue(SacsHierarchyItem.FormatForDisplay(values.GetValue(column.DataName).ToString(), 200)); value = new DataValue(SacsHierarchyItem.FormatForDisplay(values.GetValue(column.DataName).ToString(), 200));
} }
@@ -212,7 +236,7 @@ namespace Saxonite.Net.Standard.Base.Mgr
//----------------------------------------------------------- //-----------------------------------------------------------
// Notes - limit to 200 chars. // Notes - limit to 200 chars.
case SaxJournalistArticle.Column.Notes: case SaxArticle.Column.Notes:
{ {
value = new DataValue(SacsHierarchyItem.FormatForDisplay(values.GetValue(column.DataName).ToString(), 200)); value = new DataValue(SacsHierarchyItem.FormatForDisplay(values.GetValue(column.DataName).ToString(), 200));
} }
@@ -220,15 +244,15 @@ namespace Saxonite.Net.Standard.Base.Mgr
//----------------------------------------------------------- //-----------------------------------------------------------
// Status. // Status.
case SaxJournalistArticle.Column.Status_Desc: case SaxArticle.Column.Status_Desc:
case SaxJournalistArticle.Column.Status_Ind: case SaxArticle.Column.Status_Ind:
{ {
String statusCode = values.GetValue(column.DataName).ToString(); String statusCode = values.GetValue(column.DataName).ToString();
SaStatus status = SacsSystem.GetStatusForCode(statusCode); SaStatus status = SacsSystem.GetStatusForCode(statusCode);
if (column.Id == (int)SaxJournalistArticle.Column.Status_Desc) if (column.Id == (int)SaxArticle.Column.Status_Desc)
value = new DataValue(SacsSystem.GetStatusDesc(status)); value = new DataValue(SacsSystem.GetStatusDesc(status));
else if (column.Id == (int)SaxJournalistArticle.Column.Status_Ind) else if (column.Id == (int)SaxArticle.Column.Status_Ind)
value = new DataValue(SaxJournalistArticle.GetStatusTriState(status)); value = new DataValue(SaxArticle.GetStatusTriState(status));
} }
break; break;
@@ -16,6 +16,7 @@
<div class="sax-para">Follow <span style="font-weight:bold;"><a href="[#Link.RequestPassword]">this link</a></span> to set a password against your account.</div> <div class="sax-para">Follow <span style="font-weight:bold;"><a href="[#Link.RequestPassword]">this link</a></span> to set a password against your account.</div>
<div class="sax-para">Once that's been done you'll be able to sign-in and participate on the platform.</div> <div class="sax-para">Once that's been done you'll be able to sign-in and participate on the platform.</div>
<div class="sax-para">The link will expire in [#Link.ExpiresMinutes] minutes.</div> <div class="sax-para">The link will expire in [#Link.ExpiresMinutes] minutes.</div>
<div class="sax-para">Alternatively, go the the <a href="[#Link.SignIn]">Sign-in</a> page and submit a 'Request Password' from there.</div>
<div class="sax-para">Thank you.</div> <div class="sax-para">Thank you.</div>
</div> </div>
</div> </div>
@@ -8,7 +8,7 @@ using System.Text;
namespace Saxonite.Net.Standard.Dbas.Bus namespace Saxonite.Net.Standard.Dbas.Bus
{ {
//======================================================================= //=======================================================================
public class SaxJournalistArticle_Dbas : SaxJournalistArticle public class SaxArticle_Dbas : SaxArticle
{ {
//------------------------------------------------------------------- //-------------------------------------------------------------------
// Data members. // Data members.
@@ -16,8 +16,8 @@ namespace Saxonite.Net.Standard.Dbas.Bus
//------------------------------------------------------------------- //-------------------------------------------------------------------
// Construction. // Construction.
public SaxJournalistArticle_Dbas(ISacsDatabase database, SysId id, SysId userAccountIdJournalist, UInt16 flags) : public SaxArticle_Dbas(ISacsDatabase database, SysId id, SysId userAccountIdAuthor, SysId organisationId, UInt16 flags) :
base(id, userAccountIdJournalist) base(id, userAccountIdAuthor, organisationId)
{ {
this.database = database; this.database = database;
Flags = flags; Flags = flags;
@@ -9,7 +9,7 @@ using System.Data.Common;
using System.Linq; using System.Linq;
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// Code generated by Sarand Database Utilities Wed 14-Jul-2021 14:06:01 // Code generated by Sarand Database Utilities Fri 6-Aug-2021 19:02:06
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
namespace Saxonite.Net.Standard.Dbas.Internal namespace Saxonite.Net.Standard.Dbas.Internal
{ {
@@ -9,18 +9,19 @@ using System.Data.Common;
using System.Linq; using System.Linq;
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// Code generated by Sarand Database Utilities Wed 14-Jul-2021 14:06:01 // Code generated by Sarand Database Utilities Fri 6-Aug-2021 19:02:06
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
namespace Saxonite.Net.Standard.Dbas.Internal namespace Saxonite.Net.Standard.Dbas.Internal
{ {
internal class JournalistArticle_Db : SaxDbDataItem internal class Article_Db : SaxDbDataItem
{ {
//------------------------------------------------------------------- //-------------------------------------------------------------------
// Column definitions. // Column definitions.
public class ColumnsData public class ColumnsData
{ {
public ColumnDataInt32 _Id { get; } = new ColumnDataInt32("Id", true); public ColumnDataInt32 _Id { get; } = new ColumnDataInt32("Id", true);
public ColumnDataInt32 _UserAccountIdJournalist { get; } = new ColumnDataInt32("UserAccountIdJournalist"); public ColumnDataInt32 _UserAccountIdAuthor { get; } = new ColumnDataInt32("UserAccountIdAuthor");
public ColumnDataInt32 _OrganisationId { get; } = new ColumnDataInt32("OrganisationId");
public ColumnDataInt32 _SportIdPrimary { get; } = new ColumnDataInt32("SportIdPrimary"); public ColumnDataInt32 _SportIdPrimary { get; } = new ColumnDataInt32("SportIdPrimary");
public ColumnDataInt32 _RegionIdPrimary { get; } = new ColumnDataInt32("RegionIdPrimary"); public ColumnDataInt32 _RegionIdPrimary { get; } = new ColumnDataInt32("RegionIdPrimary");
public ColumnDataString _Headline { get; } = new ColumnDataString("Headline"); public ColumnDataString _Headline { get; } = new ColumnDataString("Headline");
@@ -43,7 +44,8 @@ namespace Saxonite.Net.Standard.Dbas.Internal
protected static List<String> fields { get; } = new List<String>() protected static List<String> fields { get; } = new List<String>()
{ {
"Id", "Id",
"UserAccountIdJournalist", "UserAccountIdAuthor",
"OrganisationId",
"SportIdPrimary", "SportIdPrimary",
"RegionIdPrimary", "RegionIdPrimary",
"Headline", "Headline",
@@ -77,14 +79,14 @@ namespace Saxonite.Net.Standard.Dbas.Internal
//------------------------------------------------------------------- //-------------------------------------------------------------------
// Construction. // Construction.
internal JournalistArticle_Db (IDatabaseInfo dbInfo) : base(dbInfo) internal Article_Db (IDatabaseInfo dbInfo) : base(dbInfo)
{ {
} }
//------------------------------------------------------------------- //-------------------------------------------------------------------
// Properties. // Properties.
public override String SchemaName { get; } = "dbo"; public override String SchemaName { get; } = "dbo";
public override String TableName { get; } = "JournalistArticle"; public override String TableName { get; } = "Article";
public String TableNameFmt { get { return (!String.IsNullOrEmpty(SchemaName) ? "[" + SchemaName + "]." : "") + "[" + TableName + "]"; } } public String TableNameFmt { get { return (!String.IsNullOrEmpty(SchemaName) ? "[" + SchemaName + "]." : "") + "[" + TableName + "]"; } }
public static List<String> Fields { get { return new List<String>(fields); } } public static List<String> Fields { get { return new List<String>(fields); } }
public static List<String> FieldsId { get { return new List<String>(fieldsId); } } public static List<String> FieldsId { get { return new List<String>(fieldsId); } }
@@ -92,7 +94,8 @@ namespace Saxonite.Net.Standard.Dbas.Internal
// Columns. // Columns.
public ColumnsData Cols { get; } = new ColumnsData(); public ColumnsData Cols { get; } = new ColumnsData();
public Int32 _Id { get { return Cols._Id.Value; } set { Cols._Id.Value = value; } } public Int32 _Id { get { return Cols._Id.Value; } set { Cols._Id.Value = value; } }
public Int32 _UserAccountIdJournalist { get { return Cols._UserAccountIdJournalist.Value; } set { Cols._UserAccountIdJournalist.Value = value; } } public Int32 _UserAccountIdAuthor { get { return Cols._UserAccountIdAuthor.Value; } set { Cols._UserAccountIdAuthor.Value = value; } }
public Int32 _OrganisationId { get { return Cols._OrganisationId.Value; } set { Cols._OrganisationId.Value = value; } }
public Int32 _SportIdPrimary { get { return Cols._SportIdPrimary.Value; } set { Cols._SportIdPrimary.Value = value; } } public Int32 _SportIdPrimary { get { return Cols._SportIdPrimary.Value; } set { Cols._SportIdPrimary.Value = value; } }
public Int32 _RegionIdPrimary { get { return Cols._RegionIdPrimary.Value; } set { Cols._RegionIdPrimary.Value = value; } } public Int32 _RegionIdPrimary { get { return Cols._RegionIdPrimary.Value; } set { Cols._RegionIdPrimary.Value = value; } }
public String _Headline { get { return Cols._Headline.Value; } set { Cols._Headline.Value = value; } } public String _Headline { get { return Cols._Headline.Value; } set { Cols._Headline.Value = value; } }
@@ -130,7 +133,8 @@ namespace Saxonite.Net.Standard.Dbas.Internal
public override void PopulateFrom (DbDataReader dbDataReader) public override void PopulateFrom (DbDataReader dbDataReader)
{ {
_Id = GetFieldInt32(dbDataReader, "Id", _Id); _Id = GetFieldInt32(dbDataReader, "Id", _Id);
_UserAccountIdJournalist = GetFieldInt32(dbDataReader, "UserAccountIdJournalist", _UserAccountIdJournalist); _UserAccountIdAuthor = GetFieldInt32(dbDataReader, "UserAccountIdAuthor", _UserAccountIdAuthor);
_OrganisationId = GetFieldInt32(dbDataReader, "OrganisationId", _OrganisationId);
_SportIdPrimary = GetFieldInt32(dbDataReader, "SportIdPrimary", _SportIdPrimary); _SportIdPrimary = GetFieldInt32(dbDataReader, "SportIdPrimary", _SportIdPrimary);
_RegionIdPrimary = GetFieldInt32(dbDataReader, "RegionIdPrimary", _RegionIdPrimary); _RegionIdPrimary = GetFieldInt32(dbDataReader, "RegionIdPrimary", _RegionIdPrimary);
_Headline = GetFieldString(dbDataReader, "Headline", _Headline); _Headline = GetFieldString(dbDataReader, "Headline", _Headline);
@@ -167,7 +171,8 @@ namespace Saxonite.Net.Standard.Dbas.Internal
Log(GetType().Name + ".ExecuteInsertCommand", dbCommand.CommandText); Log(GetType().Name + ".ExecuteInsertCommand", dbCommand.CommandText);
// Populate parameters. // Populate parameters.
dbCommand.Parameters.Clear(); dbCommand.Parameters.Clear();
if (columnNames.ContainsCI("UserAccountIdJournalist")) AddCommandParameter(dbCommand, "@UserAccountIdJournalist", _UserAccountIdJournalist); if (columnNames.ContainsCI("UserAccountIdAuthor")) AddCommandParameter(dbCommand, "@UserAccountIdAuthor", _UserAccountIdAuthor);
if (columnNames.ContainsCI("OrganisationId")) AddCommandParameter(dbCommand, "@OrganisationId", _OrganisationId);
if (columnNames.ContainsCI("SportIdPrimary")) AddCommandParameter(dbCommand, "@SportIdPrimary", _SportIdPrimary); if (columnNames.ContainsCI("SportIdPrimary")) AddCommandParameter(dbCommand, "@SportIdPrimary", _SportIdPrimary);
if (columnNames.ContainsCI("RegionIdPrimary")) AddCommandParameter(dbCommand, "@RegionIdPrimary", _RegionIdPrimary); if (columnNames.ContainsCI("RegionIdPrimary")) AddCommandParameter(dbCommand, "@RegionIdPrimary", _RegionIdPrimary);
if (columnNames.ContainsCI("Headline")) AddCommandParameter(dbCommand, "@Headline", _Headline); if (columnNames.ContainsCI("Headline")) AddCommandParameter(dbCommand, "@Headline", _Headline);
@@ -219,7 +224,8 @@ namespace Saxonite.Net.Standard.Dbas.Internal
Log(GetType().Name + ".ExecuteUpdateCommand", dbCommand.CommandText); Log(GetType().Name + ".ExecuteUpdateCommand", dbCommand.CommandText);
// Populate parameters. // Populate parameters.
dbCommand.Parameters.Clear(); dbCommand.Parameters.Clear();
if (columnNames.ContainsCI("UserAccountIdJournalist")) AddCommandParameter(dbCommand, "@UserAccountIdJournalist", _UserAccountIdJournalist); if (columnNames.ContainsCI("UserAccountIdAuthor")) AddCommandParameter(dbCommand, "@UserAccountIdAuthor", _UserAccountIdAuthor);
if (columnNames.ContainsCI("OrganisationId")) AddCommandParameter(dbCommand, "@OrganisationId", _OrganisationId);
if (columnNames.ContainsCI("SportIdPrimary")) AddCommandParameter(dbCommand, "@SportIdPrimary", _SportIdPrimary); if (columnNames.ContainsCI("SportIdPrimary")) AddCommandParameter(dbCommand, "@SportIdPrimary", _SportIdPrimary);
if (columnNames.ContainsCI("RegionIdPrimary")) AddCommandParameter(dbCommand, "@RegionIdPrimary", _RegionIdPrimary); if (columnNames.ContainsCI("RegionIdPrimary")) AddCommandParameter(dbCommand, "@RegionIdPrimary", _RegionIdPrimary);
if (columnNames.ContainsCI("Headline")) AddCommandParameter(dbCommand, "@Headline", _Headline); if (columnNames.ContainsCI("Headline")) AddCommandParameter(dbCommand, "@Headline", _Headline);
@@ -9,7 +9,7 @@ using System.Data.Common;
using System.Linq; using System.Linq;
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// Code generated by Sarand Database Utilities Wed 14-Jul-2021 14:06:01 // Code generated by Sarand Database Utilities Fri 6-Aug-2021 19:02:06
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
namespace Saxonite.Net.Standard.Dbas.Internal namespace Saxonite.Net.Standard.Dbas.Internal
{ {
@@ -9,7 +9,7 @@ using System.Data.Common;
using System.Linq; using System.Linq;
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// Code generated by Sarand Database Utilities Wed 14-Jul-2021 14:06:01 // Code generated by Sarand Database Utilities Fri 6-Aug-2021 19:02:06
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
namespace Saxonite.Net.Standard.Dbas.Internal namespace Saxonite.Net.Standard.Dbas.Internal
{ {
@@ -9,7 +9,7 @@ using System.Data.Common;
using System.Linq; using System.Linq;
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// Code generated by Sarand Database Utilities Wed 14-Jul-2021 14:06:01 // Code generated by Sarand Database Utilities Fri 6-Aug-2021 19:02:06
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
namespace Saxonite.Net.Standard.Dbas.Internal namespace Saxonite.Net.Standard.Dbas.Internal
{ {
@@ -9,7 +9,7 @@ using System.Data.Common;
using System.Linq; using System.Linq;
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// Code generated by Sarand Database Utilities Wed 14-Jul-2021 14:06:01 // Code generated by Sarand Database Utilities Fri 6-Aug-2021 19:02:06
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
namespace Saxonite.Net.Standard.Dbas.Internal namespace Saxonite.Net.Standard.Dbas.Internal
{ {
@@ -9,7 +9,7 @@ using System.Data.Common;
using System.Linq; using System.Linq;
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// Code generated by Sarand Database Utilities Wed 14-Jul-2021 14:06:01 // Code generated by Sarand Database Utilities Fri 6-Aug-2021 19:02:06
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
namespace Saxonite.Net.Standard.Dbas.Internal namespace Saxonite.Net.Standard.Dbas.Internal
{ {
@@ -9,7 +9,7 @@ using System.Data.Common;
using System.Linq; using System.Linq;
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// Code generated by Sarand Database Utilities Wed 14-Jul-2021 14:06:01 // Code generated by Sarand Database Utilities Fri 6-Aug-2021 19:02:06
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
namespace Saxonite.Net.Standard.Dbas.Internal namespace Saxonite.Net.Standard.Dbas.Internal
{ {
@@ -9,7 +9,7 @@ using System.Data.Common;
using System.Linq; using System.Linq;
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// Code generated by Sarand Database Utilities Wed 14-Jul-2021 14:06:01 // Code generated by Sarand Database Utilities Fri 6-Aug-2021 19:02:06
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
namespace Saxonite.Net.Standard.Dbas.Internal namespace Saxonite.Net.Standard.Dbas.Internal
{ {
@@ -9,7 +9,7 @@ using System.Data.Common;
using System.Linq; using System.Linq;
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// Code generated by Sarand Database Utilities Wed 14-Jul-2021 14:06:01 // Code generated by Sarand Database Utilities Fri 6-Aug-2021 19:02:06
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
namespace Saxonite.Net.Standard.Dbas.Internal namespace Saxonite.Net.Standard.Dbas.Internal
{ {
@@ -9,7 +9,7 @@ using System.Data.Common;
using System.Linq; using System.Linq;
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// Code generated by Sarand Database Utilities Wed 14-Jul-2021 14:06:01 // Code generated by Sarand Database Utilities Fri 6-Aug-2021 19:02:06
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
namespace Saxonite.Net.Standard.Dbas.Internal namespace Saxonite.Net.Standard.Dbas.Internal
{ {
@@ -9,7 +9,7 @@ using System.Data.Common;
using System.Linq; using System.Linq;
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// Code generated by Sarand Database Utilities Wed 14-Jul-2021 14:06:01 // Code generated by Sarand Database Utilities Fri 6-Aug-2021 19:02:06
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
namespace Saxonite.Net.Standard.Dbas.Internal namespace Saxonite.Net.Standard.Dbas.Internal
{ {
@@ -9,7 +9,7 @@ using System.Data.Common;
using System.Linq; using System.Linq;
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// Code generated by Sarand Database Utilities Wed 14-Jul-2021 14:06:01 // Code generated by Sarand Database Utilities Fri 6-Aug-2021 19:02:06
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
namespace Saxonite.Net.Standard.Dbas.Internal namespace Saxonite.Net.Standard.Dbas.Internal
{ {
@@ -9,7 +9,7 @@ using System.Data.Common;
using System.Linq; using System.Linq;
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// Code generated by Sarand Database Utilities Wed 14-Jul-2021 14:06:01 // Code generated by Sarand Database Utilities Fri 6-Aug-2021 19:02:06
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
namespace Saxonite.Net.Standard.Dbas.Internal namespace Saxonite.Net.Standard.Dbas.Internal
{ {
@@ -9,7 +9,7 @@ using System.Data.Common;
using System.Linq; using System.Linq;
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// Code generated by Sarand Database Utilities Wed 14-Jul-2021 14:06:01 // Code generated by Sarand Database Utilities Fri 6-Aug-2021 19:02:06
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
namespace Saxonite.Net.Standard.Dbas.Internal namespace Saxonite.Net.Standard.Dbas.Internal
{ {
@@ -241,7 +241,7 @@ namespace Saxonite.Net.Standard.Dbas.Mgr
public static String aliasActivityIndex { get; } = "ActIdx"; public static String aliasActivityIndex { get; } = "ActIdx";
public static String aliasActivityIndex_UserActivity { get; } = "ActIdx_UsrAct"; public static String aliasActivityIndex_UserActivity { get; } = "ActIdx_UsrAct";
private static String prefixActivityIndex_UserActivity { get; } = aliasActivityIndex_UserActivity + "_"; private static String prefixActivityIndex_UserActivity { get; } = aliasActivityIndex_UserActivity + "_";
public static String aliasActivityIndex_Article { get; } = "ActIdx_JrnArt"; public static String aliasActivityIndex_Article { get; } = "ActIdx_Art";
private static String prefixActivityIndex_Article { get; } = aliasActivityIndex_Article + "_"; private static String prefixActivityIndex_Article { get; } = aliasActivityIndex_Article + "_";
public static String aliasActivityIndex_Opportunity { get; } = "ActIdx_OrgOpp"; public static String aliasActivityIndex_Opportunity { get; } = "ActIdx_OrgOpp";
private static String prefixActivityIndex_Opportunity { get; } = aliasActivityIndex_Opportunity + "_"; private static String prefixActivityIndex_Opportunity { get; } = aliasActivityIndex_Opportunity + "_";
@@ -318,11 +318,11 @@ namespace Saxonite.Net.Standard.Dbas.Mgr
//----------------------------------------------------------- //-----------------------------------------------------------
// Article. // Article.
case SaxActivityIndex.Column.Article_Headline: case SaxActivityIndex.Column.Article_Headline:
SetActivityIndexColDfn(columnDfn, "Headline", 160, SaxDbDfn_Core.ColumnIdx.JournalistArticle_Headline, ColumnAlignment.Left, DataValue.DataType.String, aliasActivityIndex_Article, prefixActivityIndex_Article); SetActivityIndexColDfn(columnDfn, "Headline", 160, SaxDbDfn_Core.ColumnIdx.Article_Headline, ColumnAlignment.Left, DataValue.DataType.String, aliasActivityIndex_Article, prefixActivityIndex_Article);
columnDfn.ReadOnly = true; columnDfn.ReadOnly = true;
break; break;
case SaxActivityIndex.Column.Article_Summary: case SaxActivityIndex.Column.Article_Summary:
SetActivityIndexColDfn(columnDfn, "Summary", 240, SaxDbDfn_Core.ColumnIdx.JournalistArticle_Summary, ColumnAlignment.Left, DataValue.DataType.String, aliasActivityIndex_Article, prefixActivityIndex_Article); SetActivityIndexColDfn(columnDfn, "Summary", 240, SaxDbDfn_Core.ColumnIdx.Article_Summary, ColumnAlignment.Left, DataValue.DataType.String, aliasActivityIndex_Article, prefixActivityIndex_Article);
columnDfn.ReadOnly = true; columnDfn.ReadOnly = true;
break; break;
@@ -596,13 +596,13 @@ namespace Saxonite.Net.Standard.Dbas.Mgr
if (columns.HasId(SaxActivityIndex.Column.Article_Headline) || columns.HasId(SaxActivityIndex.Column.Article_Summary)) if (columns.HasId(SaxActivityIndex.Column.Article_Headline) || columns.HasId(SaxActivityIndex.Column.Article_Summary))
{ {
DbQueryJoin joinArticle = new DbQueryJoin(DbJoinType.LeftOuter); DbQueryJoin joinArticle = new DbQueryJoin(DbJoinType.LeftOuter);
joinArticle.Table = new StringPair(SaxDbDfn_Core.GetTableName(SaxDbDfn_Core.TableIdx.JournalistArticle), aliasActivityIndex_Article); joinArticle.Table = new StringPair(SaxDbDfn_Core.GetTableName(SaxDbDfn_Core.TableIdx.Article), aliasActivityIndex_Article);
joinArticle.Filters.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.ActivityIndex_ItemType, aliasActivityIndex) + "=" + ((int)Sax.DataItemType.JournalistArticle).ToString()); joinArticle.Filters.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.ActivityIndex_ItemType, aliasActivityIndex) + "=" + ((int)Sax.DataItemType.Article).ToString());
joinArticle.Filters.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.JournalistArticle_Id, aliasActivityIndex_Article) + "=" + SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.ActivityIndex_ItemId, aliasActivityIndex)); joinArticle.Filters.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.Article_Id, aliasActivityIndex_Article) + "=" + SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.ActivityIndex_ItemId, aliasActivityIndex));
query.Joins.Add(joinArticle); query.Joins.Add(joinArticle);
List<SaxDbDfn_Core.ColumnIdx> cols = new List<SaxDbDfn_Core.ColumnIdx>(); List<SaxDbDfn_Core.ColumnIdx> cols = new List<SaxDbDfn_Core.ColumnIdx>();
cols.Add(SaxDbDfn_Core.ColumnIdx.JournalistArticle_Headline); cols.Add(SaxDbDfn_Core.ColumnIdx.Article_Headline);
cols.Add(SaxDbDfn_Core.ColumnIdx.JournalistArticle_Summary); cols.Add(SaxDbDfn_Core.ColumnIdx.Article_Summary);
foreach (var col in cols) foreach (var col in cols)
query.Columns.Add(SaxDbDfn_Core.GetColumnNameQual(col, aliasActivityIndex_Article), prefixActivityIndex_Article + SaxDbDfn_Core.GetColumnName(col, false)); query.Columns.Add(SaxDbDfn_Core.GetColumnNameQual(col, aliasActivityIndex_Article), prefixActivityIndex_Article + SaxDbDfn_Core.GetColumnName(col, false));
} }
@@ -0,0 +1,692 @@
using Sarand.Net.Standard.Dbas.Data;
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 Saxonite.Base.App;
using Saxonite.Net.Standard.Dbas.Bus;
using Saxonite.Net.Standard.Dbas.Internal;
using Saxonite.Net.Standard.Base.App;
using Saxonite.Net.Standard.Base.Bus;
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Text;
using Sarand.Net.Standard.Base.Utils;
using System.Linq;
namespace Saxonite.Net.Standard.Dbas.Mgr
{
//=======================================================================
partial class SaxActivityMgr_Dbas
{
//*******************************************************************
// Activity Mgr - Article
//*******************************************************************
// Utilities.
private List<StringPair> GetLogProperties(SaxArticle article)
{
return new List<StringPair>()
{
new StringPair("Id", SysId.ToString(article.Id)),
new StringPair("UserAccountIdAuthor", SysId.ToString(article.UserAccountIdAuthor)),
new StringPair("OrganisationId", SysId.ToString(article.OrganisationId)),
new StringPair("Headline", StringUtil.Left(article.Headline,32)),
new StringPair("Status", article.StatusCode)
};
}
//-------------------------------------------------------------------
// Create item.
public override SaxArticle CreateArticle(SysId userAccountIdAuthor, SysId organisationId)
{
ClearErrorState();
return new SaxArticle_Dbas(CoreDatabase, null, userAccountIdAuthor, organisationId, 0);
}
private SaxArticle_Dbas CreateArticle(Article_Db dbArticle)
{
ClearErrorState();
SaxArticle_Dbas article = new SaxArticle_Dbas(CoreDatabase, new SysId(dbArticle._Id), new SysId(dbArticle._UserAccountIdAuthor), new SysId(dbArticle._OrganisationId), (UInt16)dbArticle._Flags);
PopulateFrom(dbArticle, article);
return article;
}
//-------------------------------------------------------------------
// Get item.
public override SaxArticle GetArticle(SaxArticle.Params prm)
{
ClearErrorState();
return GetArticle(GetArticleQueryFilter(prm).Concat(" And ", "(", ")"));
}
private SaxArticle GetArticle(String filter)
{
ClearErrorState();
long count = GetArticleCount(filter);
if (count == 0) return null;
if (count != 1)
{
SetErrorState("Multiple items found");
return null;
}
SaxArticle article = null;
// Query data.
using (var dbConnection = CoreDatabase.CreateConnection())
using (var dbCommand = dbConnection.CreateCommand())
{
try
{
dbConnection.Open();
Article_Db dbArticle = new Article_Db(CoreDbInfo);
dbArticle.PopulateFrom(dbCommand, aliasArticle, filter);
article = CreateArticle(dbArticle);
}
catch (Exception exc)
{
SetErrorState("Database query exception");
SaLogger.Warn(GetType().Name + ".GetArticle\n\tQuery: " + dbCommand.CommandText + "\n\t" + ExceptionUtil.GetLogMessage(exc));
}
}
return article;
}
//-------------------------------------------------------------------
// Validate item.
public override bool IsValidArticleData(SaxArticle.Data data, SaxArticle.ErrField errField)
{
ClearErrorState();
if (!base.IsValidArticleData(data, errField)) return false;
return true;
}
//-------------------------------------------------------------------
// Insert item.
public override bool InsertArticle(SaxArticle article, DbUpdateInfo dbUpdateInfo)
{
String fn = GetType().Name + ".InsertArticle";
ClearErrorState();
if (!IsValidArticle(article)) return false;
if (SysId.IsValid(article.Id)) return SetErrorState(ErrorMessage.ValiditemId);
using (var dbConnection = CoreDatabase.CreateConnection())
using (var dbCommand = dbConnection.CreateCommand())
{
try
{
dbConnection.Open();
Article_Db dbArticle = new Article_Db(CoreDbInfo);
PopulateTo(dbArticle, article, dbUpdateInfo);
if (Article_Db.FieldsNonId.Contains("Id"))
{
// Generate next Id.
// ToDo dbArticle._Id = CoreDatabase.GetNextIdFromTable("Article");
}
dbArticle.ExecuteInsertCommand(dbCommand);
article.Id = new SysId(dbArticle._Id);
article.Changed = false;
if (DebugMode) SaLogger.Debug(fn + " Inserted. " + GetLogProperties(article).Concat(": ").Concat("", "\n\t"));
}
catch (Exception exc) { SetErrorState(exc.Message); }
}
return !HasErrorState();
}
//-------------------------------------------------------------------
// Update item.
public override bool UpdateArticle(SaxArticle article, DbUpdateInfo dbUpdateInfo)
{
String fn = GetType().Name + ".UpdateArticle";
ClearErrorState();
if (!IsValidArticle(article)) return false;
if (!SysId.IsValid(article.Id)) return SetErrorState(ErrorMessage.InvalidItemId);
if (!article.Changed)
{
if (DebugMode) SaLogger.Debug(fn + " Data not changed. " + GetLogProperties(article).Concat(": ").Concat("", "\n\t"));
return true;
}
using (var dbConnection = CoreDatabase.CreateConnection())
using (var dbCommand = dbConnection.CreateCommand())
{
try
{
// Retrieve item.
dbConnection.Open();
Article_Db dbArticle = new Article_Db(CoreDbInfo);
dbArticle.PopulateFrom(dbCommand, aliasArticle, "Id=" + SysId.ToString(article.Id));
// ToDo SaxUpdateLogItemMonitor_Article updateLogMonitor = new SaxUpdateLogItemMonitor_Article(SessionContext, CreateArticle(dbArticle), dbUpdateInfo);
// Update item.
PopulateTo(dbArticle, article, dbUpdateInfo);
dbArticle.ExecuteUpdateCommand(dbCommand);
article.Changed = false;
if (DebugMode) SaLogger.Debug(fn + " Updated. " + GetLogProperties(article).Concat(": ").Concat("", "\n\t"));
// Record updates.
// ToDo updateLogMonitor.RecordUpdatedValues(article);
// ToDo updateLogMonitor.LogUpdates();
}
catch (Exception exc) { SetErrorState(exc.Message); }
}
return !HasErrorState();
}
//-------------------------------------------------------------------
// Delete item.
public override bool ArticleCanBeDeleted(SaxArticle article)
{
ClearErrorState();
if (!base.ArticleCanBeDeleted(article)) return false;
return true;
}
public override bool DeleteArticle(SaxArticle article, DbUpdateInfo dbUpdateInfo)
{
String fn = GetType().Name + ".DeleteArticle";
ClearErrorState();
if (!ArticleCanBeDeleted(article)) return false;
// Articles are logically deleted by changing the status.
article.Status = SaStatus.Deleted;
return UpdateArticle(article, dbUpdateInfo);
/*
* Physical deletion.
using (var dbConnection = CoreDatabase.CreateConnection())
using (var dbCommand = dbConnection.CreateCommand())
{
try
{
// Retrieve item.
dbConnection.Open();
Article_Db dbArticle = new Article_Db(CoreDbInfo);
dbArticle.PopulateFrom(dbCommand, aliasArticle, "Id=" + article.Id.ToString());
// Delete item.
dbCommand.CommandType = System.Data.CommandType.Text;
dbCommand.CommandText = "DELETE FROM " + SaxDbDfn_Core.GetTableName(SaxDbDfn_Core.TableIdx.Article) + " WHERE Id=" + SysId.ToString(article.Id) + ";";
dbCommand.ExecuteNonQuery();
article.Changed = false;
if (DebugMode) SaLogger.Debug(fn + " Deleted. " + GetLogProperties(article).Concat(": ").Concat("", "\n\t"));
}
catch (Exception exc) { SetErrorState(exc.Message); }
}
return !HasErrorState();
*/
}
//-------------------------------------------------------------------
// Copy data properties to and from database.
private void PopulateTo(Article_Db dbArticle, SaxArticle article, DbUpdateInfo dbUpdateInfo)
{
dbArticle._Id = SysId.ToInt(article.Id);
dbArticle._UserAccountIdAuthor = SysId.ToInt(article.UserAccountIdAuthor);
dbArticle._OrganisationId = SysId.ToInt(article.OrganisationId);
dbArticle._SportIdPrimary = SysId.ToInt(article.SportIdPrimary);
dbArticle._RegionIdPrimary = SysId.ToInt(article.RegionIdPrimary);
dbArticle._Headline = article.Headline;
dbArticle._Summary = article.Summary;
dbArticle._BodyData = article.BodyData;
dbArticle._PublishedAt = article.PublishedAt;
dbArticle._Notes = article.Notes;
dbArticle._Status = SacsSystem.GetStatusCode(article.Status);
dbArticle._Flags = (short)article.Flags;
if (!SysId.IsValid(article.Id))
{
dbArticle._CreateOn = DateTime.Now;
dbArticle._CreateBy = dbUpdateInfo.UserId.ToInt();
dbArticle._CreateHost = dbUpdateInfo.Host;
}
dbArticle._UpdateOn = DateTime.Now;
dbArticle._UpdateBy = dbUpdateInfo.UserId.ToInt();
dbArticle._UpdateHost = dbUpdateInfo.Host;
}
private void PopulateFrom(Article_Db dbArticle, SaxArticle article)
{
//article.Id = new SysId(dbArticle._Id);
//article.UserAccountIdAuthor = new SysId(dbArticle._UserAccountIdAuthor);
//article.OrganisationId = new SysId(dbArticle._OrganisationId);
article.SportIdPrimary = new SysId(dbArticle._SportIdPrimary);
article.RegionIdPrimary = new SysId(dbArticle._RegionIdPrimary);
article.Headline = dbArticle._Headline;
article.Summary = dbArticle._Summary;
article.BodyData = dbArticle._BodyData;
article.PublishedAt = dbArticle._PublishedAt;
article.Notes = dbArticle._Notes;
article.Status = SacsSystem.GetStatusForCode(dbArticle._Status);
article.SetCreateStamp(dbArticle._CreateOn, new SysId(dbArticle._CreateBy), dbArticle._CreateHost);
article.SetUpdateStamp(dbArticle._UpdateOn, new SysId(dbArticle._UpdateBy), dbArticle._UpdateHost);
article.AcceptChanges();
}
//-------------------------------------------------------------------
// Item column definitions.
private static readonly String aliasArticle = "Art";
private static readonly String aliasArticle_Author = "Art_Auth";
private static readonly String prefixArticle_Author = "Art_Jrn_";
private static readonly String aliasArticle_Organisation = "Art_Org";
private static readonly String prefixArticle_Organisation = "Art_Org_";
private static readonly String aliasArticle_Sport = "Art_Spt";
private static readonly String prefixArticle_Sport = "Art_Spt_";
private static readonly String aliasArticle_Region = "Art_Rgn";
private static readonly String prefixArticle_Region = "Art_Rgn_";
private void SetArticleColDfn
(ColumnDfn col, String caption, int width, SaxDbDfn_Core.ColumnIdx dbCol,
ColumnAlignment align = ColumnAlignment.Default, DataValue.DataType dataType = DataValue.DataType.String,
String alias = "", String prefix = "")
{
if (String.IsNullOrEmpty(alias) && SaxDbDfn_Core.GetTableForColumn(dbCol) == SaxDbDfn_Core.TableIdx.Article)
alias = aliasArticle;
col.Set(caption, width, (int)dbCol, prefix + SaxDbDfn_Core.GetColumnName(dbCol, false), SaxDbDfn_Core.GetColumnNameQual(dbCol, alias), dataType, align);
if (dataType == DataValue.DataType.String && dbCol != SaxDbDfn_Core.ColumnIdx.Unknown)
col.MaxLength = (int)SaxDbDfn_Core.GetColTextLen(dbCol);
}
public override ColumnDfn GetArticleColumnDfn(SaxArticle.Column columnId, string caption = "", int width = 0)
{
ColumnDfn columnDfn = new ColumnDfn((int)columnId, caption, width);
switch (columnId)
{
//-----------------------------------------------------------
case SaxArticle.Column.Pos:
SetArticleColDfn(columnDfn, "Pos", 60, SaxDbDfn_Core.ColumnIdx.Unknown, ColumnAlignment.Right);
columnDfn.SortMode = ColumnDfn.ColumnSortMode.Off;
columnDfn.ReadOnly = true;
columnDfn.Resizable = false;
break;
case SaxArticle.Column.Id:
SetArticleColDfn(columnDfn, "Id", 80, SaxDbDfn_Core.ColumnIdx.Article_Id, ColumnAlignment.Right, DataValue.DataType.Long);
columnDfn.ReadOnly = true;
break;
//-----------------------------------------------------------
// Organisation.
case SaxArticle.Column.OrganisationId:
SetArticleColDfn(columnDfn, "Organisation Id", 80, SaxDbDfn_Core.ColumnIdx.Article_OrganisationId, ColumnAlignment.Right, DataValue.DataType.Long);
columnDfn.ReadOnly = true;
break;
case SaxArticle.Column.Organisation_Name:
SetArticleColDfn(columnDfn, "Organisation", 120, SaxDbDfn_Core.ColumnIdx.Organisation_Name, ColumnAlignment.Left, DataValue.DataType.String, aliasArticle_Organisation, prefixArticle_Organisation);
columnDfn.ReadOnly = true;
break;
//-----------------------------------------------------------
// Author.
case SaxArticle.Column.UserAccountIdAuthor:
SetArticleColDfn(columnDfn, "Author Id", 80, SaxDbDfn_Core.ColumnIdx.Article_UserAccountIdAuthor, ColumnAlignment.Right, DataValue.DataType.Long);
columnDfn.ReadOnly = true;
break;
case SaxArticle.Column.Author_DisplayName:
SetArticleColDfn(columnDfn, "Author", 120, SaxDbDfn_Core.ColumnIdx.Unknown);
columnDfn.ReadOnly = true;
break;
case SaxArticle.Column.Author_Title:
SetArticleColDfn(columnDfn, "Author title", 80, SaxDbDfn_Core.ColumnIdx.UserAccount_Title, ColumnAlignment.Left, DataValue.DataType.String, aliasArticle_Author, prefixArticle_Author);
columnDfn.ReadOnly = true;
break;
case SaxArticle.Column.Author_FirstName:
SetArticleColDfn(columnDfn, "Author first name", 100, SaxDbDfn_Core.ColumnIdx.UserAccount_FirstName, ColumnAlignment.Left, DataValue.DataType.String, aliasArticle_Author, prefixArticle_Author);
columnDfn.ReadOnly = true;
break;
case SaxArticle.Column.Author_LastName:
SetArticleColDfn(columnDfn, "Author last name", 100, SaxDbDfn_Core.ColumnIdx.UserAccount_LastName, ColumnAlignment.Left, DataValue.DataType.String, aliasArticle_Author, prefixArticle_Author);
columnDfn.ReadOnly = true;
break;
//-----------------------------------------------------------
// Sport.
case SaxArticle.Column.SportIdPrimary:
SetArticleColDfn(columnDfn, "Sport Id", 80, SaxDbDfn_Core.ColumnIdx.Article_SportIdPrimary, ColumnAlignment.Right, DataValue.DataType.Long);
columnDfn.ReadOnly = true;
break;
case SaxArticle.Column.Sport_Name:
SetArticleColDfn(columnDfn, "Sport", 100, SaxDbDfn_Core.ColumnIdx.Sport_Name, ColumnAlignment.Left, DataValue.DataType.String, aliasArticle_Sport, prefixArticle_Sport);
columnDfn.ReadOnly = true;
break;
//-----------------------------------------------------------
// Region.
case SaxArticle.Column.RegionIdPrimary:
SetArticleColDfn(columnDfn, "Region Id", 80, SaxDbDfn_Core.ColumnIdx.Article_RegionIdPrimary, ColumnAlignment.Right, DataValue.DataType.Long);
columnDfn.ReadOnly = true;
break;
case SaxArticle.Column.Region_Name:
SetArticleColDfn(columnDfn, "Region", 100, SaxDbDfn_Core.ColumnIdx.Region_Name, ColumnAlignment.Left, DataValue.DataType.String, aliasArticle_Region, prefixArticle_Region);
columnDfn.ReadOnly = true;
break;
//-----------------------------------------------------------
// Article.
case SaxArticle.Column.Headline:
SetArticleColDfn(columnDfn, "Headline", 200, SaxDbDfn_Core.ColumnIdx.Article_Headline);
break;
case SaxArticle.Column.Summary:
SetArticleColDfn(columnDfn, "Summary", 200, SaxDbDfn_Core.ColumnIdx.Article_Summary);
break;
case SaxArticle.Column.PublishedAt_Date:
SetArticleColDfn(columnDfn, "Published", 80, SaxDbDfn_Core.ColumnIdx.Article_PublishedAt, ColumnAlignment.Center, DataValue.DataType.Date);
columnDfn.ReadOnly = true;
break;
case SaxArticle.Column.PublishedAt_DateTime:
SetArticleColDfn(columnDfn, "Published", 100, SaxDbDfn_Core.ColumnIdx.Article_PublishedAt, ColumnAlignment.Center, DataValue.DataType.DateTime);
columnDfn.ReadOnly = true;
break;
//-----------------------------------------------------------
// Derived properties.
//-----------------------------------------------------------
// Common properties.
case SaxArticle.Column.Notes:
SetArticleColDfn(columnDfn, "Notes", 240, SaxDbDfn_Core.ColumnIdx.Article_Notes);
break;
case SaxArticle.Column.Flags:
SetArticleColDfn(columnDfn, "Flags", 60, SaxDbDfn_Core.ColumnIdx.Article_Flags, ColumnAlignment.Center, DataValue.DataType.Long);
break;
case SaxArticle.Column.Status:
SetArticleColDfn(columnDfn, "Status", 80, SaxDbDfn_Core.ColumnIdx.Article_Status, ColumnAlignment.Center);
break;
case SaxArticle.Column.Status_Desc:
SetArticleColDfn(columnDfn, "Status", 90, SaxDbDfn_Core.ColumnIdx.Article_Status, ColumnAlignment.Center);
break;
case SaxArticle.Column.Status_Ind:
SetArticleColDfn(columnDfn, "Status", 80, SaxDbDfn_Core.ColumnIdx.Article_Status, ColumnAlignment.Center, DataValue.DataType.TriState);
columnDfn.TriStateFormat = ColumnTriStateFormat.Lights;
break;
case SaxArticle.Column.CreateOn_Date:
SetArticleColDfn(columnDfn, "Created", 80, SaxDbDfn_Core.ColumnIdx.Article_CreateOn, ColumnAlignment.Center, DataValue.DataType.Date);
columnDfn.ReadOnly = true;
break;
case SaxArticle.Column.UpdateOn_Date:
SetArticleColDfn(columnDfn, "Updated", 80, SaxDbDfn_Core.ColumnIdx.Article_UpdateOn, ColumnAlignment.Center, DataValue.DataType.Date);
columnDfn.ReadOnly = true;
break;
//-----------------------------------------------------------
}
if (!String.IsNullOrEmpty(caption))
columnDfn.Caption = caption;
if (width > 0)
columnDfn.Width = width;
return columnDfn;
}
//-------------------------------------------------------------------
// Item query filter.
public override List<string> GetArticleQueryFilter(SaxArticle.Params prm)
{
List<String> filter = new List<String>();
// Item Ids.
String idsIncluded = prm.IdsIncluded.Concat(",");
if (!idsIncluded.IsEmpty())
filter.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.Article_Id, aliasArticle) + " IN (" + idsIncluded + ")");
String idsExcluded = prm.IdsExcluded.Concat(",");
if (!idsExcluded.IsEmpty())
filter.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.Article_Id, aliasArticle) + " NOT IN (" + idsExcluded + ")");
// Author User Account.
String userAccountIdsIncluded = prm.UserAccountIdsAuthorIncluded.Concat(",");
if (!userAccountIdsIncluded.IsEmpty())
filter.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.Article_UserAccountIdAuthor, aliasArticle) + " IN (" + userAccountIdsIncluded + ")");
// Organisations.
String organisationIdsIncluded = prm.OrganisationIdsIncluded.Concat(",");
if (!organisationIdsIncluded.IsEmpty())
filter.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.Article_OrganisationId, aliasArticle) + " IN (" + organisationIdsIncluded + ")");
// Sport Ids.
String sportIdsIncluded = prm.SportIdsIncluded.Concat(",");
if (!sportIdsIncluded.IsEmpty())
filter.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.Article_SportIdPrimary, aliasArticle) + " IN (" + sportIdsIncluded + ")");
// Region Ids.
String regionIdsIncluded = prm.RegionIdsIncluded.Concat(",");
if (!regionIdsIncluded.IsEmpty())
filter.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.Article_RegionIdPrimary, aliasArticle) + " IN (" + regionIdsIncluded + ")");
// Headline.
if (!StringUtil.IsEmpty(prm.HeadlinePartial))
filter.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.Article_Headline, aliasArticle) + " Like '%" + DbQuery.FormatForLike(prm.HeadlinePartial, true) + "%'");
// Summary.
if (!StringUtil.IsEmpty(prm.SummaryPartial))
filter.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.Article_Summary, aliasArticle) + " Like '%" + DbQuery.FormatForLike(prm.SummaryPartial, true) + "%'");
// Article.
if (!StringUtil.IsEmpty(prm.ArticleFilter))
{
// Split filter into words.
List<String> filterWords = prm.ArticleFilter.Split((char[])null).ToList();
filterWords.RemoveDuplicatesCI();
filterWords.RemoveBlanks();
foreach (String filterWord in filterWords)
{
List<String> articleFilter = new List<String>();
articleFilter.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.Article_Headline, aliasArticle) + " Like '%" + DbQuery.FormatForLike(filterWord, true) + "%'");
articleFilter.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.Article_Summary, aliasArticle) + " Like '%" + DbQuery.FormatForLike(filterWord, true) + "%'");
filter.Add(articleFilter.Concat(" OR ", "(", ")"));
}
}
// Notes.
if (!StringUtil.IsEmpty(prm.NotesPartial))
filter.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.Article_Notes, aliasArticle) + " LIKE '%" + DbQuery.FormatForLike(prm.NotesPartial) + "%'");
// Status.
if (prm.StatusCat != SaxArticle.StatusCat.Any)
filter.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.Article_Status, aliasArticle) + GetArticleStatusCatFilterCondition(prm.StatusCat));
if (filter.Count < 1) filter.Add("1=1");
return filter;
}
internal static String GetArticleStatusCatFilterCondition(SaxArticle.StatusCat statusCat)
{
if (statusCat == SaxArticle.StatusCat.ActiveOnly)
return "='" + SacsSystem.GetStatusCode(SaStatus.Active) + "'";
if (statusCat == SaxArticle.StatusCat.InactiveOnly)
return "='" + SacsSystem.GetStatusCode(SaStatus.Inactive) + "'";
if (statusCat == SaxArticle.StatusCat.NotDeleted)
return "!='" + SacsSystem.GetStatusCode(SaStatus.Deleted) + "'";
if (statusCat == SaxArticle.StatusCat.DeletedOnly)
return "='" + SacsSystem.GetStatusCode(SaStatus.Deleted) + "'";
return "";
}
// Item sort columns.
public List<String> GetArticleSortColumns(SaxArticle.Params prm)
{
// Sort sequence:
List<String> sortColumnNames = new List<String>();
foreach (var columnDfn in prm.SortColumns)
{
// Need to ensure correct alias used for Article columns in case of conflict.
String sortCol = String.Empty;
if (SaxDbDfn_Core.GetTableForColumn((SaxDbDfn_Core.ColumnIdx)columnDfn.DbColumn) == SaxDbDfn_Core.TableIdx.Article)
{
sortCol = SaxDbDfn_Core.GetColumnNameQual((SaxDbDfn_Core.ColumnIdx)columnDfn.DbColumn, aliasArticle);
}
else
{
sortCol = columnDfn.DataName;
if (!StringUtil.IsEmpty(columnDfn.SortDataName))
sortCol = columnDfn.SortDataName;
}
if (!sortCol.IsEmpty())
{
DbOrderByNullMode orderByNullMode = DbOrderByNullMode.Default; // eSaOrderByDemoteNulls, eSaOrderByPromoteNulls
sortColumnNames.Add(DbQuery.FormatForOrderBy(sortCol, columnDfn.SortAscending, orderByNullMode).Concat(", "));
}
}
sortColumnNames.RemoveBlanks();
if (sortColumnNames.IsEmpty())
{
// Default sort columns.
sortColumnNames.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.Article_Id, aliasArticle) + " ASC");
}
return sortColumnNames;
}
//-------------------------------------------------------------------
// Item count.
private long GetArticleCount(String filter)
{
ClearErrorState();
return CoreDatabase.GetRowCount(SaxDbDfn_Core.GetTableName(SaxDbDfn_Core.TableIdx.Article) + " As " + aliasArticle, filter);
}
public override long GetArticleCount(SaxArticle.Params prm)
{
ClearErrorState();
return GetArticleCount(GetArticleQueryFilter(prm).Concat(" AND ", "(", ")"));
}
//-------------------------------------------------------------------
// Item list.
public override List<SaxArticle> GetArticleList(SaxArticle.Params prm)
{
List<SaxArticle> userActivitys = new List<SaxArticle>();
DbQuery qry = new DbQuery(CoreDatabase.DbmsType);
qry.Tables.Add(SaxDbDfn_Core.GetTableName(SaxDbDfn_Core.TableIdx.Article), aliasArticle);
Article_Db dbArticle = new Article_Db(CoreDbInfo);
qry.Columns.AddRange(dbArticle.ExistingColumnNames);
qry.Filters.AddRange(GetArticleQueryFilter(prm));
qry.OrderBy.AddRange(GetArticleSortColumns(prm));
// Query data.
using (var dbConnection = CoreDatabase.CreateConnection())
using (var dbCommand = dbConnection.CreateCommand())
{
try
{
dbConnection.Open();
dbCommand.CommandText = qry.BuildQuery(prm.ResultsPaging);
using (DbDataReader dbDataReader = dbCommand.ExecuteReader())
{
while (dbDataReader.Read())
{
dbArticle = new Article_Db(CoreDbInfo);
dbArticle.PopulateFrom(dbDataReader);
userActivitys.Add(CreateArticle(dbArticle));
}
}
}
catch (Exception exc)
{
SaLogger.Warn(GetType().Name + ".GetArticleList\n\tQuery: " + dbCommand.CommandText + "\n\t" + ExceptionUtil.GetLogMessage(exc));
}
}
return userActivitys;
}
//-------------------------------------------------------------------
// Item query execution.
public override DbResultSet ExecuteArticleQuery(List<ColumnDfn> columns, SaxArticle.Params prm)
{
ClearErrorState();
//---------------------------------------------------------------------
// Construct query.
DbQuery query = new DbQuery(CoreDatabase.DbmsType);
query.Tables.Add(SaxDbDfn_Core.GetTableName(SaxDbDfn_Core.TableIdx.Article), aliasArticle);
// Add columns as defined in query list.
if (columns.HasId(SaxArticle.Column.Id))
query.Columns.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.Article_Id, aliasArticle));
bool hasUserAccountCols = (columns.HasId(SaxArticle.Column.Author_DisplayName) || columns.HasId(SaxArticle.Column.Author_Title) || columns.HasId(SaxArticle.Column.Author_FirstName) || columns.HasId(SaxArticle.Column.Author_LastName));
if (columns.HasId(SaxArticle.Column.UserAccountIdAuthor) || hasUserAccountCols)
query.Columns.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.Article_UserAccountIdAuthor, aliasArticle));
bool hasOrganisationCols = (columns.HasId(SaxArticle.Column.Organisation_Name));
if (columns.HasId(SaxArticle.Column.OrganisationId) || hasOrganisationCols)
query.Columns.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.Article_OrganisationId, aliasArticle));
bool hasSportCols = (columns.HasId(SaxArticle.Column.Sport_Name));
if (columns.HasId(SaxArticle.Column.SportIdPrimary) || hasSportCols)
query.Columns.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.Article_SportIdPrimary, aliasArticle));
bool hasRegionCols = (columns.HasId(SaxArticle.Column.Region_Name));
if (columns.HasId(SaxArticle.Column.RegionIdPrimary) || hasRegionCols)
query.Columns.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.Article_RegionIdPrimary, aliasArticle));
if (columns.HasId(SaxArticle.Column.Headline))
query.Columns.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.Article_Headline, aliasArticle));
if (columns.HasId(SaxArticle.Column.Summary))
query.Columns.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.Article_Summary, aliasArticle));
if (columns.HasId(SaxArticle.Column.PublishedAt_Date) || columns.HasId(SaxArticle.Column.PublishedAt_DateTime))
query.Columns.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.Article_PublishedAt, aliasArticle));
// Common properties.
if (columns.HasId(SaxArticle.Column.Notes))
query.Columns.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.Article_Notes, aliasArticle));
if (columns.HasId(SaxArticle.Column.Flags))
query.Columns.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.Article_Flags, aliasArticle));
if (columns.HasId(SaxArticle.Column.Status) || columns.HasId(SaxArticle.Column.Status_Desc) || columns.HasId(SaxArticle.Column.Status_Ind))
query.Columns.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.Article_Status, aliasArticle));
if (columns.HasId(SaxArticle.Column.CreateOn_Date))
query.Columns.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.Article_CreateOn, aliasArticle));
if (columns.HasId(SaxArticle.Column.UpdateOn_Date))
query.Columns.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.Article_UpdateOn, aliasArticle));
//---------------------------------------------------------------------
// User Account.
if (hasUserAccountCols)
{
DbQueryJoin joinUserAccount = new DbQueryJoin(DbJoinType.LeftOuter);
joinUserAccount.Table = new StringPair(SaxDbDfn_Core.GetTableName(SaxDbDfn_Core.TableIdx.UserAccount), aliasArticle_Author);
joinUserAccount.Filters.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.UserAccount_Id, aliasArticle_Author) + "=" + SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.Article_UserAccountIdAuthor, aliasArticle));
query.Joins.Add(joinUserAccount);
List<SaxDbDfn_Core.ColumnIdx> cols = new List<SaxDbDfn_Core.ColumnIdx>();
cols.Add(SaxDbDfn_Core.ColumnIdx.UserAccount_Title);
cols.Add(SaxDbDfn_Core.ColumnIdx.UserAccount_FirstName);
cols.Add(SaxDbDfn_Core.ColumnIdx.UserAccount_LastName);
foreach (var col in cols)
query.Columns.Add(SaxDbDfn_Core.GetColumnNameQual(col, aliasArticle_Author), prefixArticle_Author + SaxDbDfn_Core.GetColumnName(col, false));
}
//---------------------------------------------------------------------
// Organisation.
if (hasOrganisationCols)
{
DbQueryJoin joinOrganisation = new DbQueryJoin(DbJoinType.LeftOuter);
joinOrganisation.Table = new StringPair(SaxDbDfn_Core.GetTableName(SaxDbDfn_Core.TableIdx.Organisation), aliasArticle_Organisation);
joinOrganisation.Filters.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.Organisation_Id, aliasArticle_Organisation) + "=" + SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.Article_OrganisationId, aliasArticle));
query.Joins.Add(joinOrganisation);
List<SaxDbDfn_Core.ColumnIdx> cols = new List<SaxDbDfn_Core.ColumnIdx>();
cols.Add(SaxDbDfn_Core.ColumnIdx.Organisation_Name);
foreach (var col in cols)
query.Columns.Add(SaxDbDfn_Core.GetColumnNameQual(col, aliasArticle_Organisation), prefixArticle_Organisation + SaxDbDfn_Core.GetColumnName(col, false));
}
//---------------------------------------------------------------------
// Primary Sport.
if (hasSportCols)
{
DbQueryJoin joinSport = new DbQueryJoin(DbJoinType.LeftOuter);
joinSport.Table = new StringPair(SaxDbDfn_Core.GetTableName(SaxDbDfn_Core.TableIdx.Sport), aliasArticle_Sport);
joinSport.Filters.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.Sport_Id, aliasArticle_Sport) + "=" + SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.Article_SportIdPrimary, aliasArticle));
query.Joins.Add(joinSport);
List<SaxDbDfn_Core.ColumnIdx> cols = new List<SaxDbDfn_Core.ColumnIdx>();
cols.Add(SaxDbDfn_Core.ColumnIdx.Sport_Name);
foreach (var col in cols)
query.Columns.Add(SaxDbDfn_Core.GetColumnNameQual(col, aliasArticle_Sport), prefixArticle_Sport + SaxDbDfn_Core.GetColumnName(col, false));
}
//---------------------------------------------------------------------
// Primary Region.
if (hasRegionCols)
{
DbQueryJoin joinRegion = new DbQueryJoin(DbJoinType.LeftOuter);
joinRegion.Table = new StringPair(SaxDbDfn_Core.GetTableName(SaxDbDfn_Core.TableIdx.Region), aliasArticle_Region);
joinRegion.Filters.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.Region_Id, aliasArticle_Region) + "=" + SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.Article_RegionIdPrimary, aliasArticle));
query.Joins.Add(joinRegion);
List<SaxDbDfn_Core.ColumnIdx> cols = new List<SaxDbDfn_Core.ColumnIdx>();
cols.Add(SaxDbDfn_Core.ColumnIdx.Region_Name);
foreach (var col in cols)
query.Columns.Add(SaxDbDfn_Core.GetColumnNameQual(col, aliasArticle_Region), prefixArticle_Region + SaxDbDfn_Core.GetColumnName(col, false));
}
//---------------------------------------------------------------------
// Populate filter.
query.Filters.AddRange(GetArticleQueryFilter(prm));
if (prm.IdsIncluded.Count != 1)
{
// Configure sort sequence.
foreach (String sortColumn in GetArticleSortColumns(prm))
query.OrderBy.Add(sortColumn);
}
//---------------------------------------------------------------------
//return new DbResultSet_DataTableReader(db, query.BuildQuery(prm.ResultsPaging));
return DbResultSet_DataReader.ExecuteQuery(CoreDatabase, query.BuildQuery(prm.ResultsPaging));
}
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -1,654 +0,0 @@
using Sarand.Net.Standard.Dbas.Data;
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 Saxonite.Base.App;
using Saxonite.Net.Standard.Dbas.Bus;
using Saxonite.Net.Standard.Dbas.Internal;
using Saxonite.Net.Standard.Base.App;
using Saxonite.Net.Standard.Base.Bus;
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Text;
using Sarand.Net.Standard.Base.Utils;
using System.Linq;
namespace Saxonite.Net.Standard.Dbas.Mgr
{
//=======================================================================
partial class SaxActivityMgr_Dbas
{
//*******************************************************************
// Activity Mgr - JournalistArticle
//*******************************************************************
// Utilities.
private List<StringPair> GetLogProperties(SaxJournalistArticle journalistArticle)
{
return new List<StringPair>()
{
new StringPair("Id", SysId.ToString(journalistArticle.Id)),
new StringPair("UserAccountIdJournalist", SysId.ToString(journalistArticle.UserAccountIdJournalist)),
new StringPair("Headline", StringUtil.Left(journalistArticle.Headline,32)),
new StringPair("Status", journalistArticle.StatusCode)
};
}
//-------------------------------------------------------------------
// Create item.
public override SaxJournalistArticle CreateJournalistArticle(SysId userAccountIdJournalist)
{
ClearErrorState();
return new SaxJournalistArticle_Dbas(CoreDatabase, null, userAccountIdJournalist, 0);
}
private SaxJournalistArticle_Dbas CreateJournalistArticle(JournalistArticle_Db dbJournalistArticle)
{
ClearErrorState();
SaxJournalistArticle_Dbas journalistArticle = new SaxJournalistArticle_Dbas(CoreDatabase, new SysId(dbJournalistArticle._Id), new SysId(dbJournalistArticle._UserAccountIdJournalist), (UInt16)dbJournalistArticle._Flags);
PopulateFrom(dbJournalistArticle, journalistArticle);
return journalistArticle;
}
//-------------------------------------------------------------------
// Get item.
public override SaxJournalistArticle GetJournalistArticle(SaxJournalistArticle.Params prm)
{
ClearErrorState();
return GetJournalistArticle(GetJournalistArticleQueryFilter(prm).Concat(" And ", "(", ")"));
}
private SaxJournalistArticle GetJournalistArticle(String filter)
{
ClearErrorState();
long count = GetJournalistArticleCount(filter);
if (count == 0) return null;
if (count != 1)
{
SetErrorState("Multiple items found");
return null;
}
SaxJournalistArticle journalistArticle = null;
// Query data.
using (var dbConnection = CoreDatabase.CreateConnection())
using (var dbCommand = dbConnection.CreateCommand())
{
try
{
dbConnection.Open();
JournalistArticle_Db dbJournalistArticle = new JournalistArticle_Db(CoreDbInfo);
dbJournalistArticle.PopulateFrom(dbCommand, aliasJournalistArticle, filter);
journalistArticle = CreateJournalistArticle(dbJournalistArticle);
}
catch (Exception exc)
{
SetErrorState("Database query exception");
SaLogger.Warn(GetType().Name + ".GetJournalistArticle\n\tQuery: " + dbCommand.CommandText + "\n\t" + ExceptionUtil.GetLogMessage(exc));
}
}
return journalistArticle;
}
//-------------------------------------------------------------------
// Validate item.
public override bool IsValidJournalistArticleData(SaxJournalistArticle.Data data, SaxJournalistArticle.ErrField errField)
{
ClearErrorState();
if (!base.IsValidJournalistArticleData(data, errField)) return false;
return true;
}
//-------------------------------------------------------------------
// Insert item.
public override bool InsertJournalistArticle(SaxJournalistArticle journalistArticle, DbUpdateInfo dbUpdateInfo)
{
String fn = GetType().Name + ".InsertJournalistArticle";
ClearErrorState();
if (!IsValidJournalistArticle(journalistArticle)) return false;
if (SysId.IsValid(journalistArticle.Id)) return SetErrorState(ErrorMessage.ValiditemId);
using (var dbConnection = CoreDatabase.CreateConnection())
using (var dbCommand = dbConnection.CreateCommand())
{
try
{
dbConnection.Open();
JournalistArticle_Db dbJournalistArticle = new JournalistArticle_Db(CoreDbInfo);
PopulateTo(dbJournalistArticle, journalistArticle, dbUpdateInfo);
if (JournalistArticle_Db.FieldsNonId.Contains("Id"))
{
// Generate next Id.
// ToDo dbJournalistArticle._Id = CoreDatabase.GetNextIdFromTable("JournalistArticle");
}
dbJournalistArticle.ExecuteInsertCommand(dbCommand);
journalistArticle.Id = new SysId(dbJournalistArticle._Id);
journalistArticle.Changed = false;
if (DebugMode) SaLogger.Debug(fn + " Inserted. " + GetLogProperties(journalistArticle).Concat(": ").Concat("", "\n\t"));
}
catch (Exception exc) { SetErrorState(exc.Message); }
}
return !HasErrorState();
}
//-------------------------------------------------------------------
// Update item.
public override bool UpdateJournalistArticle(SaxJournalistArticle journalistArticle, DbUpdateInfo dbUpdateInfo)
{
String fn = GetType().Name + ".UpdateJournalistArticle";
ClearErrorState();
if (!IsValidJournalistArticle(journalistArticle)) return false;
if (!SysId.IsValid(journalistArticle.Id)) return SetErrorState(ErrorMessage.InvalidItemId);
if (!journalistArticle.Changed)
{
if (DebugMode) SaLogger.Debug(fn + " Data not changed. " + GetLogProperties(journalistArticle).Concat(": ").Concat("", "\n\t"));
return true;
}
using (var dbConnection = CoreDatabase.CreateConnection())
using (var dbCommand = dbConnection.CreateCommand())
{
try
{
// Retrieve item.
dbConnection.Open();
JournalistArticle_Db dbJournalistArticle = new JournalistArticle_Db(CoreDbInfo);
dbJournalistArticle.PopulateFrom(dbCommand, aliasJournalistArticle, "Id=" + SysId.ToString(journalistArticle.Id));
// ToDo SaxUpdateLogItemMonitor_JournalistArticle updateLogMonitor = new SaxUpdateLogItemMonitor_JournalistArticle(SessionContext, CreateJournalistArticle(dbJournalistArticle), dbUpdateInfo);
// Update item.
PopulateTo(dbJournalistArticle, journalistArticle, dbUpdateInfo);
dbJournalistArticle.ExecuteUpdateCommand(dbCommand);
journalistArticle.Changed = false;
if (DebugMode) SaLogger.Debug(fn + " Updated. " + GetLogProperties(journalistArticle).Concat(": ").Concat("", "\n\t"));
// Record updates.
// ToDo updateLogMonitor.RecordUpdatedValues(journalistArticle);
// ToDo updateLogMonitor.LogUpdates();
}
catch (Exception exc) { SetErrorState(exc.Message); }
}
return !HasErrorState();
}
//-------------------------------------------------------------------
// Delete item.
public override bool JournalistArticleCanBeDeleted(SaxJournalistArticle journalistArticle)
{
ClearErrorState();
if (!base.JournalistArticleCanBeDeleted(journalistArticle)) return false;
return true;
}
public override bool DeleteJournalistArticle(SaxJournalistArticle journalistArticle, DbUpdateInfo dbUpdateInfo)
{
String fn = GetType().Name + ".DeleteJournalistArticle";
ClearErrorState();
if (!JournalistArticleCanBeDeleted(journalistArticle)) return false;
// Journalist Articles are logically deleted by changing the status.
journalistArticle.Status = SaStatus.Deleted;
return UpdateJournalistArticle(journalistArticle, dbUpdateInfo);
/*
* Physical deletion.
using (var dbConnection = CoreDatabase.CreateConnection())
using (var dbCommand = dbConnection.CreateCommand())
{
try
{
// Retrieve item.
dbConnection.Open();
JournalistArticle_Db dbJournalistArticle = new JournalistArticle_Db(CoreDbInfo);
dbJournalistArticle.PopulateFrom(dbCommand, aliasJournalistArticle, "Id=" + journalistArticle.Id.ToString());
// Delete item.
dbCommand.CommandType = System.Data.CommandType.Text;
dbCommand.CommandText = "DELETE FROM " + SaxDbDfn_Core.GetTableName(SaxDbDfn_Core.TableIdx.JournalistArticle) + " WHERE Id=" + SysId.ToString(journalistArticle.Id) + ";";
dbCommand.ExecuteNonQuery();
journalistArticle.Changed = false;
if (DebugMode) SaLogger.Debug(fn + " Deleted. " + GetLogProperties(journalistArticle).Concat(": ").Concat("", "\n\t"));
}
catch (Exception exc) { SetErrorState(exc.Message); }
}
return !HasErrorState();
*/
}
//-------------------------------------------------------------------
// Copy data properties to and from database.
private void PopulateTo(JournalistArticle_Db dbJournalistArticle, SaxJournalistArticle journalistArticle, DbUpdateInfo dbUpdateInfo)
{
dbJournalistArticle._Id = SysId.ToInt(journalistArticle.Id);
dbJournalistArticle._UserAccountIdJournalist = SysId.ToInt(journalistArticle.UserAccountIdJournalist);
dbJournalistArticle._SportIdPrimary = SysId.ToInt(journalistArticle.SportIdPrimary);
dbJournalistArticle._RegionIdPrimary = SysId.ToInt(journalistArticle.RegionIdPrimary);
dbJournalistArticle._Headline = journalistArticle.Headline;
dbJournalistArticle._Summary = journalistArticle.Summary;
dbJournalistArticle._BodyData = journalistArticle.BodyData;
dbJournalistArticle._PublishedAt = journalistArticle.PublishedAt;
dbJournalistArticle._Notes = journalistArticle.Notes;
dbJournalistArticle._Status = SacsSystem.GetStatusCode(journalistArticle.Status);
dbJournalistArticle._Flags = (short)journalistArticle.Flags;
if (!SysId.IsValid(journalistArticle.Id))
{
dbJournalistArticle._CreateOn = DateTime.Now;
dbJournalistArticle._CreateBy = dbUpdateInfo.UserId.ToInt();
dbJournalistArticle._CreateHost = dbUpdateInfo.Host;
}
dbJournalistArticle._UpdateOn = DateTime.Now;
dbJournalistArticle._UpdateBy = dbUpdateInfo.UserId.ToInt();
dbJournalistArticle._UpdateHost = dbUpdateInfo.Host;
}
private void PopulateFrom(JournalistArticle_Db dbJournalistArticle, SaxJournalistArticle journalistArticle)
{
//journalistArticle.Id = new SysId(dbJournalistArticle._Id);
//journalistArticle.UserAccountIdJournalist = new SysId(dbJournalistArticle._UserAccountIdJournalist);
journalistArticle.SportIdPrimary = new SysId(dbJournalistArticle._SportIdPrimary);
journalistArticle.RegionIdPrimary = new SysId(dbJournalistArticle._RegionIdPrimary);
journalistArticle.Headline = dbJournalistArticle._Headline;
journalistArticle.Summary = dbJournalistArticle._Summary;
journalistArticle.BodyData = dbJournalistArticle._BodyData;
journalistArticle.PublishedAt = dbJournalistArticle._PublishedAt;
journalistArticle.Notes = dbJournalistArticle._Notes;
journalistArticle.Status = SacsSystem.GetStatusForCode(dbJournalistArticle._Status);
journalistArticle.SetCreateStamp(dbJournalistArticle._CreateOn, new SysId(dbJournalistArticle._CreateBy), dbJournalistArticle._CreateHost);
journalistArticle.SetUpdateStamp(dbJournalistArticle._UpdateOn, new SysId(dbJournalistArticle._UpdateBy), dbJournalistArticle._UpdateHost);
journalistArticle.AcceptChanges();
}
//-------------------------------------------------------------------
// Item column definitions.
private static readonly String aliasJournalistArticle = "Sprt";
private static readonly String aliasJournalistArticle_Journalist = "JrnArt_Jrn";
private static readonly String prefixJournalistArticle_Jourlalist = "JrnArt_Jrn_";
private static readonly String aliasJournalistArticle_Sport = "JrnArt_Spt";
private static readonly String prefixJournalistArticle_Sport = "JrnArt_Spt_";
private static readonly String aliasJournalistArticle_Region = "JrnArt_Rgn";
private static readonly String prefixJournalistArticle_Region = "JrnArt_Rgn_";
private void SetJournalistArticleColDfn
(ColumnDfn col, String caption, int width, SaxDbDfn_Core.ColumnIdx dbCol,
ColumnAlignment align = ColumnAlignment.Default, DataValue.DataType dataType = DataValue.DataType.String,
String alias = "", String prefix = "")
{
if (String.IsNullOrEmpty(alias) && SaxDbDfn_Core.GetTableForColumn(dbCol) == SaxDbDfn_Core.TableIdx.JournalistArticle)
alias = aliasJournalistArticle;
col.Set(caption, width, (int)dbCol, prefix + SaxDbDfn_Core.GetColumnName(dbCol, false), SaxDbDfn_Core.GetColumnNameQual(dbCol, alias), dataType, align);
if (dataType == DataValue.DataType.String && dbCol != SaxDbDfn_Core.ColumnIdx.Unknown)
col.MaxLength = (int)SaxDbDfn_Core.GetColTextLen(dbCol);
}
public override ColumnDfn GetJournalistArticleColumnDfn(SaxJournalistArticle.Column columnId, string caption = "", int width = 0)
{
ColumnDfn columnDfn = new ColumnDfn((int)columnId, caption, width);
switch (columnId)
{
//-----------------------------------------------------------
case SaxJournalistArticle.Column.Pos:
SetJournalistArticleColDfn(columnDfn, "Pos", 60, SaxDbDfn_Core.ColumnIdx.Unknown, ColumnAlignment.Right);
columnDfn.SortMode = ColumnDfn.ColumnSortMode.Off;
columnDfn.ReadOnly = true;
columnDfn.Resizable = false;
break;
case SaxJournalistArticle.Column.Id:
SetJournalistArticleColDfn(columnDfn, "Id", 80, SaxDbDfn_Core.ColumnIdx.JournalistArticle_Id, ColumnAlignment.Right, DataValue.DataType.Long);
columnDfn.ReadOnly = true;
break;
//-----------------------------------------------------------
// Journalist.
case SaxJournalistArticle.Column.UserAccountIdJournalist:
SetJournalistArticleColDfn(columnDfn, "Journalist Id", 80, SaxDbDfn_Core.ColumnIdx.JournalistArticle_UserAccountIdJournalist, ColumnAlignment.Right, DataValue.DataType.Long);
columnDfn.ReadOnly = true;
break;
case SaxJournalistArticle.Column.Journalist_DisplayName:
SetJournalistArticleColDfn(columnDfn, "Journalist", 120, SaxDbDfn_Core.ColumnIdx.Unknown);
columnDfn.ReadOnly = true;
break;
case SaxJournalistArticle.Column.Journalist_Title:
SetJournalistArticleColDfn(columnDfn, "Journalist Title", 80, SaxDbDfn_Core.ColumnIdx.UserAccount_Title, ColumnAlignment.Left, DataValue.DataType.String, aliasJournalistArticle_Journalist, prefixJournalistArticle_Jourlalist);
columnDfn.ReadOnly = true;
break;
case SaxJournalistArticle.Column.Journalist_FirstName:
SetJournalistArticleColDfn(columnDfn, "Journalist First Name", 100, SaxDbDfn_Core.ColumnIdx.UserAccount_FirstName, ColumnAlignment.Left, DataValue.DataType.String, aliasJournalistArticle_Journalist, prefixJournalistArticle_Jourlalist);
columnDfn.ReadOnly = true;
break;
case SaxJournalistArticle.Column.Journalist_LastName:
SetJournalistArticleColDfn(columnDfn, "Journalist Last Name", 100, SaxDbDfn_Core.ColumnIdx.UserAccount_LastName, ColumnAlignment.Left, DataValue.DataType.String, aliasJournalistArticle_Journalist, prefixJournalistArticle_Jourlalist);
columnDfn.ReadOnly = true;
break;
//-----------------------------------------------------------
// Sport.
case SaxJournalistArticle.Column.SportIdPrimary:
SetJournalistArticleColDfn(columnDfn, "Sport Id", 80, SaxDbDfn_Core.ColumnIdx.JournalistArticle_SportIdPrimary, ColumnAlignment.Right, DataValue.DataType.Long);
columnDfn.ReadOnly = true;
break;
case SaxJournalistArticle.Column.Sport_Name:
SetJournalistArticleColDfn(columnDfn, "Sport", 100, SaxDbDfn_Core.ColumnIdx.Sport_Name, ColumnAlignment.Left, DataValue.DataType.String, aliasJournalistArticle_Sport, prefixJournalistArticle_Sport);
columnDfn.ReadOnly = true;
break;
//-----------------------------------------------------------
// Region.
case SaxJournalistArticle.Column.RegionIdPrimary:
SetJournalistArticleColDfn(columnDfn, "Region Id", 80, SaxDbDfn_Core.ColumnIdx.JournalistArticle_RegionIdPrimary, ColumnAlignment.Right, DataValue.DataType.Long);
columnDfn.ReadOnly = true;
break;
case SaxJournalistArticle.Column.Region_Name:
SetJournalistArticleColDfn(columnDfn, "Region", 100, SaxDbDfn_Core.ColumnIdx.Region_Name, ColumnAlignment.Left, DataValue.DataType.String, aliasJournalistArticle_Region, prefixJournalistArticle_Region);
columnDfn.ReadOnly = true;
break;
//-----------------------------------------------------------
// Article.
case SaxJournalistArticle.Column.Headline:
SetJournalistArticleColDfn(columnDfn, "Headline", 200, SaxDbDfn_Core.ColumnIdx.JournalistArticle_Headline);
break;
case SaxJournalistArticle.Column.Summary:
SetJournalistArticleColDfn(columnDfn, "Summary", 200, SaxDbDfn_Core.ColumnIdx.JournalistArticle_Summary);
break;
case SaxJournalistArticle.Column.PublishedAt_Date:
SetJournalistArticleColDfn(columnDfn, "Published", 80, SaxDbDfn_Core.ColumnIdx.JournalistArticle_PublishedAt, ColumnAlignment.Center, DataValue.DataType.Date);
columnDfn.ReadOnly = true;
break;
case SaxJournalistArticle.Column.PublishedAt_DateTime:
SetJournalistArticleColDfn(columnDfn, "Published", 100, SaxDbDfn_Core.ColumnIdx.JournalistArticle_PublishedAt, ColumnAlignment.Center, DataValue.DataType.DateTime);
columnDfn.ReadOnly = true;
break;
//-----------------------------------------------------------
// Derived properties.
//-----------------------------------------------------------
// Common properties.
case SaxJournalistArticle.Column.Notes:
SetJournalistArticleColDfn(columnDfn, "Notes", 240, SaxDbDfn_Core.ColumnIdx.JournalistArticle_Notes);
break;
case SaxJournalistArticle.Column.Flags:
SetJournalistArticleColDfn(columnDfn, "Flags", 60, SaxDbDfn_Core.ColumnIdx.JournalistArticle_Flags, ColumnAlignment.Center, DataValue.DataType.Long);
break;
case SaxJournalistArticle.Column.Status:
SetJournalistArticleColDfn(columnDfn, "Status", 80, SaxDbDfn_Core.ColumnIdx.JournalistArticle_Status, ColumnAlignment.Center);
break;
case SaxJournalistArticle.Column.Status_Desc:
SetJournalistArticleColDfn(columnDfn, "Status", 90, SaxDbDfn_Core.ColumnIdx.JournalistArticle_Status, ColumnAlignment.Center);
break;
case SaxJournalistArticle.Column.Status_Ind:
SetJournalistArticleColDfn(columnDfn, "Status", 80, SaxDbDfn_Core.ColumnIdx.JournalistArticle_Status, ColumnAlignment.Center, DataValue.DataType.TriState);
columnDfn.TriStateFormat = ColumnTriStateFormat.Lights;
break;
case SaxJournalistArticle.Column.CreateOn_Date:
SetJournalistArticleColDfn(columnDfn, "Created", 80, SaxDbDfn_Core.ColumnIdx.JournalistArticle_CreateOn, ColumnAlignment.Center, DataValue.DataType.Date);
columnDfn.ReadOnly = true;
break;
case SaxJournalistArticle.Column.UpdateOn_Date:
SetJournalistArticleColDfn(columnDfn, "Updated", 80, SaxDbDfn_Core.ColumnIdx.JournalistArticle_UpdateOn, ColumnAlignment.Center, DataValue.DataType.Date);
columnDfn.ReadOnly = true;
break;
//-----------------------------------------------------------
}
if (!String.IsNullOrEmpty(caption))
columnDfn.Caption = caption;
if (width > 0)
columnDfn.Width = width;
return columnDfn;
}
//-------------------------------------------------------------------
// Item query filter.
public override List<string> GetJournalistArticleQueryFilter(SaxJournalistArticle.Params prm)
{
List<String> filter = new List<String>();
// Item Ids.
String idsIncluded = prm.IdsIncluded.Concat(",");
if (!idsIncluded.IsEmpty())
filter.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.JournalistArticle_Id, aliasJournalistArticle) + " IN (" + idsIncluded + ")");
String idsExcluded = prm.IdsExcluded.Concat(",");
if (!idsExcluded.IsEmpty())
filter.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.JournalistArticle_Id, aliasJournalistArticle) + " NOT IN (" + idsExcluded + ")");
// User Account Ids.
String userAccountIdsIncluded = prm.UserAccountIdsJournalistIncluded.Concat(",");
if (!userAccountIdsIncluded.IsEmpty())
filter.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.JournalistArticle_UserAccountIdJournalist, aliasJournalistArticle) + " IN (" + userAccountIdsIncluded + ")");
// Sport Ids.
String sportIdsIncluded = prm.SportIdsIncluded.Concat(",");
if (!sportIdsIncluded.IsEmpty())
filter.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.JournalistArticle_SportIdPrimary, aliasJournalistArticle) + " IN (" + sportIdsIncluded + ")");
// Region Ids.
String regionIdsIncluded = prm.RegionIdsIncluded.Concat(",");
if (!regionIdsIncluded.IsEmpty())
filter.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.JournalistArticle_RegionIdPrimary, aliasJournalistArticle) + " IN (" + regionIdsIncluded + ")");
// Headline.
if (!StringUtil.IsEmpty(prm.HeadlinePartial))
filter.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.JournalistArticle_Headline, aliasJournalistArticle) + " Like '%" + DbQuery.FormatForLike(prm.HeadlinePartial, true) + "%'");
// Summary.
if (!StringUtil.IsEmpty(prm.SummaryPartial))
filter.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.JournalistArticle_Summary, aliasJournalistArticle) + " Like '%" + DbQuery.FormatForLike(prm.SummaryPartial, true) + "%'");
// Article.
if (!StringUtil.IsEmpty(prm.ArticleFilter))
{
// Split filter into words.
List<String> filterWords = prm.ArticleFilter.Split((char[])null).ToList();
filterWords.RemoveDuplicatesCI();
filterWords.RemoveBlanks();
foreach (String filterWord in filterWords)
{
List<String> articleFilter = new List<String>();
articleFilter.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.JournalistArticle_Headline, aliasJournalistArticle) + " Like '%" + DbQuery.FormatForLike(filterWord, true) + "%'");
articleFilter.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.JournalistArticle_Summary, aliasJournalistArticle) + " Like '%" + DbQuery.FormatForLike(filterWord, true) + "%'");
filter.Add(articleFilter.Concat(" OR ", "(", ")"));
}
}
// Notes.
if (!StringUtil.IsEmpty(prm.NotesPartial))
filter.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.JournalistArticle_Notes, aliasJournalistArticle) + " LIKE '%" + DbQuery.FormatForLike(prm.NotesPartial) + "%'");
// Status.
if (prm.StatusCat != SaxJournalistArticle.StatusCat.Any)
filter.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.JournalistArticle_Status, aliasJournalistArticle) + GetJournalistArticleStatusCatFilterCondition(prm.StatusCat));
if (filter.Count < 1) filter.Add("1=1");
return filter;
}
internal static String GetJournalistArticleStatusCatFilterCondition(SaxJournalistArticle.StatusCat statusCat)
{
if (statusCat == SaxJournalistArticle.StatusCat.ActiveOnly)
return "='" + SacsSystem.GetStatusCode(SaStatus.Active) + "'";
if (statusCat == SaxJournalistArticle.StatusCat.InactiveOnly)
return "='" + SacsSystem.GetStatusCode(SaStatus.Inactive) + "'";
if (statusCat == SaxJournalistArticle.StatusCat.NotDeleted)
return "!='" + SacsSystem.GetStatusCode(SaStatus.Deleted) + "'";
if (statusCat == SaxJournalistArticle.StatusCat.DeletedOnly)
return "='" + SacsSystem.GetStatusCode(SaStatus.Deleted) + "'";
return "";
}
// Item sort columns.
public List<String> GetJournalistArticleSortColumns(SaxJournalistArticle.Params prm)
{
// Sort sequence:
List<String> sortColumnNames = new List<String>();
foreach (var columnDfn in prm.SortColumns)
{
// Need to ensure correct alias used for JournalistArticle columns in case of conflict.
String sortCol = String.Empty;
if (SaxDbDfn_Core.GetTableForColumn((SaxDbDfn_Core.ColumnIdx)columnDfn.DbColumn) == SaxDbDfn_Core.TableIdx.JournalistArticle)
{
sortCol = SaxDbDfn_Core.GetColumnNameQual((SaxDbDfn_Core.ColumnIdx)columnDfn.DbColumn, aliasJournalistArticle);
}
else
{
sortCol = columnDfn.DataName;
if (!StringUtil.IsEmpty(columnDfn.SortDataName))
sortCol = columnDfn.SortDataName;
}
if (!sortCol.IsEmpty())
{
DbOrderByNullMode orderByNullMode = DbOrderByNullMode.Default; // eSaOrderByDemoteNulls, eSaOrderByPromoteNulls
sortColumnNames.Add(DbQuery.FormatForOrderBy(sortCol, columnDfn.SortAscending, orderByNullMode).Concat(", "));
}
}
sortColumnNames.RemoveBlanks();
if (sortColumnNames.IsEmpty())
{
// Default sort columns.
sortColumnNames.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.JournalistArticle_Id, aliasJournalistArticle) + " ASC");
}
return sortColumnNames;
}
//-------------------------------------------------------------------
// Item count.
private long GetJournalistArticleCount(String filter)
{
ClearErrorState();
return CoreDatabase.GetRowCount(SaxDbDfn_Core.GetTableName(SaxDbDfn_Core.TableIdx.JournalistArticle) + " As " + aliasJournalistArticle, filter);
}
public override long GetJournalistArticleCount(SaxJournalistArticle.Params prm)
{
ClearErrorState();
return GetJournalistArticleCount(GetJournalistArticleQueryFilter(prm).Concat(" AND ", "(", ")"));
}
//-------------------------------------------------------------------
// Item list.
public override List<SaxJournalistArticle> GetJournalistArticleList(SaxJournalistArticle.Params prm)
{
List<SaxJournalistArticle> userActivitys = new List<SaxJournalistArticle>();
DbQuery qry = new DbQuery(CoreDatabase.DbmsType);
qry.Tables.Add(SaxDbDfn_Core.GetTableName(SaxDbDfn_Core.TableIdx.JournalistArticle), aliasJournalistArticle);
JournalistArticle_Db dbJournalistArticle = new JournalistArticle_Db(CoreDbInfo);
qry.Columns.AddRange(dbJournalistArticle.ExistingColumnNames);
qry.Filters.AddRange(GetJournalistArticleQueryFilter(prm));
qry.OrderBy.AddRange(GetJournalistArticleSortColumns(prm));
// Query data.
using (var dbConnection = CoreDatabase.CreateConnection())
using (var dbCommand = dbConnection.CreateCommand())
{
try
{
dbConnection.Open();
dbCommand.CommandText = qry.BuildQuery(prm.ResultsPaging);
using (DbDataReader dbDataReader = dbCommand.ExecuteReader())
{
while (dbDataReader.Read())
{
dbJournalistArticle = new JournalistArticle_Db(CoreDbInfo);
dbJournalistArticle.PopulateFrom(dbDataReader);
userActivitys.Add(CreateJournalistArticle(dbJournalistArticle));
}
}
}
catch (Exception exc)
{
SaLogger.Warn(GetType().Name + ".GetJournalistArticleList\n\tQuery: " + dbCommand.CommandText + "\n\t" + ExceptionUtil.GetLogMessage(exc));
}
}
return userActivitys;
}
//-------------------------------------------------------------------
// Item query execution.
public override DbResultSet ExecuteJournalistArticleQuery(List<ColumnDfn> columns, SaxJournalistArticle.Params prm)
{
ClearErrorState();
//---------------------------------------------------------------------
// Construct query.
DbQuery query = new DbQuery(CoreDatabase.DbmsType);
query.Tables.Add(SaxDbDfn_Core.GetTableName(SaxDbDfn_Core.TableIdx.JournalistArticle), aliasJournalistArticle);
// Add columns as defined in query list.
if (columns.HasId(SaxJournalistArticle.Column.Id))
query.Columns.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.JournalistArticle_Id, aliasJournalistArticle));
bool hasUserAccountCols = (columns.HasId(SaxJournalistArticle.Column.Journalist_DisplayName) || columns.HasId(SaxJournalistArticle.Column.Journalist_Title) || columns.HasId(SaxJournalistArticle.Column.Journalist_FirstName) || columns.HasId(SaxJournalistArticle.Column.Journalist_LastName));
if (columns.HasId(SaxJournalistArticle.Column.UserAccountIdJournalist) || hasUserAccountCols)
query.Columns.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.JournalistArticle_UserAccountIdJournalist, aliasJournalistArticle));
bool hasSportCols = (columns.HasId(SaxJournalistArticle.Column.Sport_Name));
if (columns.HasId(SaxJournalistArticle.Column.SportIdPrimary) || hasSportCols)
query.Columns.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.JournalistArticle_SportIdPrimary, aliasJournalistArticle));
bool hasRegionCols = (columns.HasId(SaxJournalistArticle.Column.Region_Name));
if (columns.HasId(SaxJournalistArticle.Column.RegionIdPrimary) || hasRegionCols)
query.Columns.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.JournalistArticle_RegionIdPrimary, aliasJournalistArticle));
if (columns.HasId(SaxJournalistArticle.Column.Headline))
query.Columns.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.JournalistArticle_Headline, aliasJournalistArticle));
if (columns.HasId(SaxJournalistArticle.Column.Summary))
query.Columns.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.JournalistArticle_Summary, aliasJournalistArticle));
if (columns.HasId(SaxJournalistArticle.Column.PublishedAt_Date) || columns.HasId(SaxJournalistArticle.Column.PublishedAt_DateTime))
query.Columns.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.JournalistArticle_PublishedAt, aliasJournalistArticle));
// Common properties.
if (columns.HasId(SaxJournalistArticle.Column.Notes))
query.Columns.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.JournalistArticle_Notes, aliasJournalistArticle));
if (columns.HasId(SaxJournalistArticle.Column.Flags))
query.Columns.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.JournalistArticle_Flags, aliasJournalistArticle));
if (columns.HasId(SaxJournalistArticle.Column.Status) || columns.HasId(SaxJournalistArticle.Column.Status_Desc) || columns.HasId(SaxJournalistArticle.Column.Status_Ind))
query.Columns.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.JournalistArticle_Status, aliasJournalistArticle));
if (columns.HasId(SaxJournalistArticle.Column.CreateOn_Date))
query.Columns.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.JournalistArticle_CreateOn, aliasJournalistArticle));
if (columns.HasId(SaxJournalistArticle.Column.UpdateOn_Date))
query.Columns.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.JournalistArticle_UpdateOn, aliasJournalistArticle));
//---------------------------------------------------------------------
// User Account.
if (hasUserAccountCols)
{
DbQueryJoin joinUserAccount = new DbQueryJoin(DbJoinType.LeftOuter);
joinUserAccount.Table = new StringPair(SaxDbDfn_Core.GetTableName(SaxDbDfn_Core.TableIdx.UserAccount), aliasJournalistArticle_Journalist);
joinUserAccount.Filters.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.UserAccount_Id, aliasJournalistArticle_Journalist) + "=" + SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.JournalistArticle_UserAccountIdJournalist, aliasJournalistArticle));
query.Joins.Add(joinUserAccount);
List<SaxDbDfn_Core.ColumnIdx> cols = new List<SaxDbDfn_Core.ColumnIdx>();
cols.Add(SaxDbDfn_Core.ColumnIdx.UserAccount_Title);
cols.Add(SaxDbDfn_Core.ColumnIdx.UserAccount_FirstName);
cols.Add(SaxDbDfn_Core.ColumnIdx.UserAccount_LastName);
foreach (var col in cols)
query.Columns.Add(SaxDbDfn_Core.GetColumnNameQual(col, aliasJournalistArticle_Journalist), prefixJournalistArticle_Jourlalist + SaxDbDfn_Core.GetColumnName(col, false));
}
//---------------------------------------------------------------------
// Primary Sport.
if (hasSportCols)
{
DbQueryJoin joinSport = new DbQueryJoin(DbJoinType.LeftOuter);
joinSport.Table = new StringPair(SaxDbDfn_Core.GetTableName(SaxDbDfn_Core.TableIdx.Sport), aliasJournalistArticle_Sport);
joinSport.Filters.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.Sport_Id, aliasJournalistArticle_Sport) + "=" + SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.JournalistArticle_SportIdPrimary, aliasJournalistArticle));
query.Joins.Add(joinSport);
List<SaxDbDfn_Core.ColumnIdx> cols = new List<SaxDbDfn_Core.ColumnIdx>();
cols.Add(SaxDbDfn_Core.ColumnIdx.Sport_Name);
foreach (var col in cols)
query.Columns.Add(SaxDbDfn_Core.GetColumnNameQual(col, aliasJournalistArticle_Sport), prefixJournalistArticle_Sport + SaxDbDfn_Core.GetColumnName(col, false));
}
//---------------------------------------------------------------------
// Primary Region.
if (hasRegionCols)
{
DbQueryJoin joinRegion = new DbQueryJoin(DbJoinType.LeftOuter);
joinRegion.Table = new StringPair(SaxDbDfn_Core.GetTableName(SaxDbDfn_Core.TableIdx.Region), aliasJournalistArticle_Region);
joinRegion.Filters.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.Region_Id, aliasJournalistArticle_Region) + "=" + SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.JournalistArticle_RegionIdPrimary, aliasJournalistArticle));
query.Joins.Add(joinRegion);
List<SaxDbDfn_Core.ColumnIdx> cols = new List<SaxDbDfn_Core.ColumnIdx>();
cols.Add(SaxDbDfn_Core.ColumnIdx.Region_Name);
foreach (var col in cols)
query.Columns.Add(SaxDbDfn_Core.GetColumnNameQual(col, aliasJournalistArticle_Region), prefixJournalistArticle_Region + SaxDbDfn_Core.GetColumnName(col, false));
}
//---------------------------------------------------------------------
// Populate filter.
query.Filters.AddRange(GetJournalistArticleQueryFilter(prm));
if (prm.IdsIncluded.Count != 1)
{
// Configure sort sequence.
foreach (String sortColumn in GetJournalistArticleSortColumns(prm))
query.OrderBy.Add(sortColumn);
}
//---------------------------------------------------------------------
//return new DbResultSet_DataTableReader(db, query.BuildQuery(prm.ResultsPaging));
return DbResultSet_DataReader.ExecuteQuery(CoreDatabase, query.BuildQuery(prm.ResultsPaging));
}
//-------------------------------------------------------------------
}
//=======================================================================
}
@@ -256,7 +256,7 @@
<Clustered>false</Clustered> <Clustered>false</Clustered>
<Nullable>false</Nullable> <Nullable>false</Nullable>
<Pages>1</Pages> <Pages>1</Pages>
<UniqueValues>7</UniqueValues> <UniqueValues>8</UniqueValues>
<HasColumns>false</HasColumns> <HasColumns>false</HasColumns>
<Columns> <Columns>
<DbDfnIndexColumn> <DbDfnIndexColumn>
@@ -343,6 +343,391 @@
</DbDfnIndex> </DbDfnIndex>
</Indices> </Indices>
</DbDfnTable> </DbDfnTable>
<DbDfnTable>
<Schema>dbo</Schema>
<Name>Article</Name>
<Remarks />
<Columns>
<DbDfnColumn>
<Schema>dbo</Schema>
<Table>Article</Table>
<Pos>1</Pos>
<Name>Id</Name>
<DataType>Int</DataType>
<DataTypeName />
<DataTypeNative>4</DataTypeNative>
<DataTypeNameNative>int</DataTypeNameNative>
<IsIdentity>true</IsIdentity>
<Size>10</Size>
<BufferLen>4</BufferLen>
<DecimalDigits>0</DecimalDigits>
<Nullable>NoNulls</Nullable>
<IsNullable>false</IsNullable>
<Remarks />
</DbDfnColumn>
<DbDfnColumn>
<Schema>dbo</Schema>
<Table>Article</Table>
<Pos>2</Pos>
<Name>UserAccountIdAuthor</Name>
<DataType>Int</DataType>
<DataTypeName />
<DataTypeNative>4</DataTypeNative>
<DataTypeNameNative>int</DataTypeNameNative>
<IsIdentity>false</IsIdentity>
<Size>10</Size>
<BufferLen>4</BufferLen>
<DecimalDigits>0</DecimalDigits>
<Nullable>NoNulls</Nullable>
<IsNullable>false</IsNullable>
<Remarks />
</DbDfnColumn>
<DbDfnColumn>
<Schema>dbo</Schema>
<Table>Article</Table>
<Pos>3</Pos>
<Name>OrganisationId</Name>
<DataType>Int</DataType>
<DataTypeName />
<DataTypeNative>4</DataTypeNative>
<DataTypeNameNative>int</DataTypeNameNative>
<IsIdentity>false</IsIdentity>
<Size>10</Size>
<BufferLen>4</BufferLen>
<DecimalDigits>0</DecimalDigits>
<Nullable>Nullable</Nullable>
<IsNullable>true</IsNullable>
<Remarks />
</DbDfnColumn>
<DbDfnColumn>
<Schema>dbo</Schema>
<Table>Article</Table>
<Pos>4</Pos>
<Name>SportIdPrimary</Name>
<DataType>Int</DataType>
<DataTypeName />
<DataTypeNative>4</DataTypeNative>
<DataTypeNameNative>int</DataTypeNameNative>
<IsIdentity>false</IsIdentity>
<Size>10</Size>
<BufferLen>4</BufferLen>
<DecimalDigits>0</DecimalDigits>
<Nullable>NoNulls</Nullable>
<IsNullable>false</IsNullable>
<Remarks />
</DbDfnColumn>
<DbDfnColumn>
<Schema>dbo</Schema>
<Table>Article</Table>
<Pos>5</Pos>
<Name>RegionIdPrimary</Name>
<DataType>Int</DataType>
<DataTypeName />
<DataTypeNative>4</DataTypeNative>
<DataTypeNameNative>int</DataTypeNameNative>
<IsIdentity>false</IsIdentity>
<Size>10</Size>
<BufferLen>4</BufferLen>
<DecimalDigits>0</DecimalDigits>
<Nullable>NoNulls</Nullable>
<IsNullable>false</IsNullable>
<Remarks />
</DbDfnColumn>
<DbDfnColumn>
<Schema>dbo</Schema>
<Table>Article</Table>
<Pos>6</Pos>
<Name>Headline</Name>
<DataType>VarChar</DataType>
<DataTypeName />
<DataTypeNative>-9</DataTypeNative>
<DataTypeNameNative>nvarchar</DataTypeNameNative>
<IsIdentity>false</IsIdentity>
<Size>200</Size>
<BufferLen>400</BufferLen>
<DecimalDigits>0</DecimalDigits>
<Nullable>NoNulls</Nullable>
<IsNullable>false</IsNullable>
<Remarks />
</DbDfnColumn>
<DbDfnColumn>
<Schema>dbo</Schema>
<Table>Article</Table>
<Pos>7</Pos>
<Name>Summary</Name>
<DataType>VarChar</DataType>
<DataTypeName />
<DataTypeNative>-9</DataTypeNative>
<DataTypeNameNative>nvarchar</DataTypeNameNative>
<IsIdentity>false</IsIdentity>
<Size>2000</Size>
<BufferLen>4000</BufferLen>
<DecimalDigits>0</DecimalDigits>
<Nullable>NoNulls</Nullable>
<IsNullable>false</IsNullable>
<Remarks />
</DbDfnColumn>
<DbDfnColumn>
<Schema>dbo</Schema>
<Table>Article</Table>
<Pos>8</Pos>
<Name>BodyData</Name>
<DataType>VarChar</DataType>
<DataTypeName />
<DataTypeNative>-9</DataTypeNative>
<DataTypeNameNative>nvarchar</DataTypeNameNative>
<IsIdentity>false</IsIdentity>
<Size>0</Size>
<BufferLen>0</BufferLen>
<DecimalDigits>0</DecimalDigits>
<Nullable>NoNulls</Nullable>
<IsNullable>false</IsNullable>
<Remarks />
</DbDfnColumn>
<DbDfnColumn>
<Schema>dbo</Schema>
<Table>Article</Table>
<Pos>9</Pos>
<Name>PublishedAt</Name>
<DataType>DateTime</DataType>
<DataTypeName />
<DataTypeNative>93</DataTypeNative>
<DataTypeNameNative>smalldatetime</DataTypeNameNative>
<IsIdentity>false</IsIdentity>
<Size>16</Size>
<BufferLen>16</BufferLen>
<DecimalDigits>0</DecimalDigits>
<Nullable>Nullable</Nullable>
<IsNullable>true</IsNullable>
<Remarks />
</DbDfnColumn>
<DbDfnColumn>
<Schema>dbo</Schema>
<Table>Article</Table>
<Pos>10</Pos>
<Name>Notes</Name>
<DataType>VarChar</DataType>
<DataTypeName />
<DataTypeNative>-9</DataTypeNative>
<DataTypeNameNative>nvarchar</DataTypeNameNative>
<IsIdentity>false</IsIdentity>
<Size>2000</Size>
<BufferLen>4000</BufferLen>
<DecimalDigits>0</DecimalDigits>
<Nullable>NoNulls</Nullable>
<IsNullable>false</IsNullable>
<Remarks />
</DbDfnColumn>
<DbDfnColumn>
<Schema>dbo</Schema>
<Table>Article</Table>
<Pos>11</Pos>
<Name>Flags</Name>
<DataType>SmallInt</DataType>
<DataTypeName />
<DataTypeNative>5</DataTypeNative>
<DataTypeNameNative>smallint</DataTypeNameNative>
<IsIdentity>false</IsIdentity>
<Size>5</Size>
<BufferLen>2</BufferLen>
<DecimalDigits>0</DecimalDigits>
<Nullable>NoNulls</Nullable>
<IsNullable>false</IsNullable>
<Remarks />
</DbDfnColumn>
<DbDfnColumn>
<Schema>dbo</Schema>
<Table>Article</Table>
<Pos>12</Pos>
<Name>Status</Name>
<DataType>VarChar</DataType>
<DataTypeName />
<DataTypeNative>12</DataTypeNative>
<DataTypeNameNative>varchar</DataTypeNameNative>
<IsIdentity>false</IsIdentity>
<Size>3</Size>
<BufferLen>3</BufferLen>
<DecimalDigits>0</DecimalDigits>
<Nullable>NoNulls</Nullable>
<IsNullable>false</IsNullable>
<Remarks />
</DbDfnColumn>
<DbDfnColumn>
<Schema>dbo</Schema>
<Table>Article</Table>
<Pos>13</Pos>
<Name>CreateOn</Name>
<DataType>DateTime</DataType>
<DataTypeName />
<DataTypeNative>93</DataTypeNative>
<DataTypeNameNative>datetime</DataTypeNameNative>
<IsIdentity>false</IsIdentity>
<Size>23</Size>
<BufferLen>16</BufferLen>
<DecimalDigits>3</DecimalDigits>
<Nullable>NoNulls</Nullable>
<IsNullable>false</IsNullable>
<Remarks />
</DbDfnColumn>
<DbDfnColumn>
<Schema>dbo</Schema>
<Table>Article</Table>
<Pos>14</Pos>
<Name>CreateBy</Name>
<DataType>Int</DataType>
<DataTypeName />
<DataTypeNative>4</DataTypeNative>
<DataTypeNameNative>int</DataTypeNameNative>
<IsIdentity>false</IsIdentity>
<Size>10</Size>
<BufferLen>4</BufferLen>
<DecimalDigits>0</DecimalDigits>
<Nullable>NoNulls</Nullable>
<IsNullable>false</IsNullable>
<Remarks />
</DbDfnColumn>
<DbDfnColumn>
<Schema>dbo</Schema>
<Table>Article</Table>
<Pos>15</Pos>
<Name>CreateHost</Name>
<DataType>VarChar</DataType>
<DataTypeName />
<DataTypeNative>12</DataTypeNative>
<DataTypeNameNative>varchar</DataTypeNameNative>
<IsIdentity>false</IsIdentity>
<Size>100</Size>
<BufferLen>100</BufferLen>
<DecimalDigits>0</DecimalDigits>
<Nullable>NoNulls</Nullable>
<IsNullable>false</IsNullable>
<Remarks />
</DbDfnColumn>
<DbDfnColumn>
<Schema>dbo</Schema>
<Table>Article</Table>
<Pos>16</Pos>
<Name>UpdateOn</Name>
<DataType>DateTime</DataType>
<DataTypeName />
<DataTypeNative>93</DataTypeNative>
<DataTypeNameNative>datetime</DataTypeNameNative>
<IsIdentity>false</IsIdentity>
<Size>23</Size>
<BufferLen>16</BufferLen>
<DecimalDigits>3</DecimalDigits>
<Nullable>NoNulls</Nullable>
<IsNullable>false</IsNullable>
<Remarks />
</DbDfnColumn>
<DbDfnColumn>
<Schema>dbo</Schema>
<Table>Article</Table>
<Pos>17</Pos>
<Name>UpdateBy</Name>
<DataType>Int</DataType>
<DataTypeName />
<DataTypeNative>4</DataTypeNative>
<DataTypeNameNative>int</DataTypeNameNative>
<IsIdentity>false</IsIdentity>
<Size>10</Size>
<BufferLen>4</BufferLen>
<DecimalDigits>0</DecimalDigits>
<Nullable>NoNulls</Nullable>
<IsNullable>false</IsNullable>
<Remarks />
</DbDfnColumn>
<DbDfnColumn>
<Schema>dbo</Schema>
<Table>Article</Table>
<Pos>18</Pos>
<Name>UpdateHost</Name>
<DataType>VarChar</DataType>
<DataTypeName />
<DataTypeNative>12</DataTypeNative>
<DataTypeNameNative>varchar</DataTypeNameNative>
<IsIdentity>false</IsIdentity>
<Size>100</Size>
<BufferLen>100</BufferLen>
<DecimalDigits>0</DecimalDigits>
<Nullable>NoNulls</Nullable>
<IsNullable>false</IsNullable>
<Remarks />
</DbDfnColumn>
</Columns>
<Indices>
<DbDfnIndex>
<Schema>dbo</Schema>
<Table>Article</Table>
<Name>PK_Article</Name>
<IndexType>1</IndexType>
<Unique>true</Unique>
<Primary>false</Primary>
<Clustered>false</Clustered>
<Nullable>false</Nullable>
<Pages>2</Pages>
<UniqueValues>9</UniqueValues>
<HasColumns>false</HasColumns>
<Columns>
<DbDfnIndexColumn>
<Seq>1</Seq>
<Name>Id</Name>
<Ascend>true</Ascend>
</DbDfnIndexColumn>
</Columns>
</DbDfnIndex>
<DbDfnIndex>
<Schema>dbo</Schema>
<Table>Article</Table>
<Name>IDX_Article_Sport_Region_Published</Name>
<IndexType>3</IndexType>
<Unique>false</Unique>
<Primary>false</Primary>
<Clustered>false</Clustered>
<Nullable>false</Nullable>
<Pages>0</Pages>
<UniqueValues>0</UniqueValues>
<HasColumns>false</HasColumns>
<Columns>
<DbDfnIndexColumn>
<Seq>1</Seq>
<Name>SportIdPrimary</Name>
<Ascend>true</Ascend>
</DbDfnIndexColumn>
<DbDfnIndexColumn>
<Seq>2</Seq>
<Name>RegionIdPrimary</Name>
<Ascend>true</Ascend>
</DbDfnIndexColumn>
<DbDfnIndexColumn>
<Seq>3</Seq>
<Name>PublishedAt</Name>
<Ascend>true</Ascend>
</DbDfnIndexColumn>
</Columns>
</DbDfnIndex>
<DbDfnIndex>
<Schema>dbo</Schema>
<Table>Article</Table>
<Name>IDX_Article_User</Name>
<IndexType>3</IndexType>
<Unique>false</Unique>
<Primary>false</Primary>
<Clustered>false</Clustered>
<Nullable>false</Nullable>
<Pages>0</Pages>
<UniqueValues>0</UniqueValues>
<HasColumns>false</HasColumns>
<Columns>
<DbDfnIndexColumn>
<Seq>1</Seq>
<Name>UserAccountIdAuthor</Name>
<Ascend>true</Ascend>
</DbDfnIndexColumn>
</Columns>
</DbDfnIndex>
</Indices>
</DbDfnTable>
<DbDfnTable> <DbDfnTable>
<Schema>dbo</Schema> <Schema>dbo</Schema>
<Name>ItemAddress</Name> <Name>ItemAddress</Name>
@@ -904,7 +1289,7 @@
<Clustered>false</Clustered> <Clustered>false</Clustered>
<Nullable>false</Nullable> <Nullable>false</Nullable>
<Pages>1</Pages> <Pages>1</Pages>
<UniqueValues>2</UniqueValues> <UniqueValues>3</UniqueValues>
<HasColumns>false</HasColumns> <HasColumns>false</HasColumns>
<Columns> <Columns>
<DbDfnIndexColumn> <DbDfnIndexColumn>
@@ -1332,7 +1717,7 @@
<Clustered>false</Clustered> <Clustered>false</Clustered>
<Nullable>false</Nullable> <Nullable>false</Nullable>
<Pages>1</Pages> <Pages>1</Pages>
<UniqueValues>7</UniqueValues> <UniqueValues>9</UniqueValues>
<HasColumns>false</HasColumns> <HasColumns>false</HasColumns>
<Columns> <Columns>
<DbDfnIndexColumn> <DbDfnIndexColumn>
@@ -1741,374 +2126,6 @@
</DbDfnIndex> </DbDfnIndex>
</Indices> </Indices>
</DbDfnTable> </DbDfnTable>
<DbDfnTable>
<Schema>dbo</Schema>
<Name>JournalistArticle</Name>
<Remarks />
<Columns>
<DbDfnColumn>
<Schema>dbo</Schema>
<Table>JournalistArticle</Table>
<Pos>1</Pos>
<Name>Id</Name>
<DataType>Int</DataType>
<DataTypeName />
<DataTypeNative>4</DataTypeNative>
<DataTypeNameNative>int</DataTypeNameNative>
<IsIdentity>true</IsIdentity>
<Size>10</Size>
<BufferLen>4</BufferLen>
<DecimalDigits>0</DecimalDigits>
<Nullable>NoNulls</Nullable>
<IsNullable>false</IsNullable>
<Remarks />
</DbDfnColumn>
<DbDfnColumn>
<Schema>dbo</Schema>
<Table>JournalistArticle</Table>
<Pos>2</Pos>
<Name>UserAccountIdJournalist</Name>
<DataType>Int</DataType>
<DataTypeName />
<DataTypeNative>4</DataTypeNative>
<DataTypeNameNative>int</DataTypeNameNative>
<IsIdentity>false</IsIdentity>
<Size>10</Size>
<BufferLen>4</BufferLen>
<DecimalDigits>0</DecimalDigits>
<Nullable>NoNulls</Nullable>
<IsNullable>false</IsNullable>
<Remarks />
</DbDfnColumn>
<DbDfnColumn>
<Schema>dbo</Schema>
<Table>JournalistArticle</Table>
<Pos>3</Pos>
<Name>SportIdPrimary</Name>
<DataType>Int</DataType>
<DataTypeName />
<DataTypeNative>4</DataTypeNative>
<DataTypeNameNative>int</DataTypeNameNative>
<IsIdentity>false</IsIdentity>
<Size>10</Size>
<BufferLen>4</BufferLen>
<DecimalDigits>0</DecimalDigits>
<Nullable>NoNulls</Nullable>
<IsNullable>false</IsNullable>
<Remarks />
</DbDfnColumn>
<DbDfnColumn>
<Schema>dbo</Schema>
<Table>JournalistArticle</Table>
<Pos>4</Pos>
<Name>RegionIdPrimary</Name>
<DataType>Int</DataType>
<DataTypeName />
<DataTypeNative>4</DataTypeNative>
<DataTypeNameNative>int</DataTypeNameNative>
<IsIdentity>false</IsIdentity>
<Size>10</Size>
<BufferLen>4</BufferLen>
<DecimalDigits>0</DecimalDigits>
<Nullable>NoNulls</Nullable>
<IsNullable>false</IsNullable>
<Remarks />
</DbDfnColumn>
<DbDfnColumn>
<Schema>dbo</Schema>
<Table>JournalistArticle</Table>
<Pos>5</Pos>
<Name>Headline</Name>
<DataType>VarChar</DataType>
<DataTypeName />
<DataTypeNative>-9</DataTypeNative>
<DataTypeNameNative>nvarchar</DataTypeNameNative>
<IsIdentity>false</IsIdentity>
<Size>200</Size>
<BufferLen>400</BufferLen>
<DecimalDigits>0</DecimalDigits>
<Nullable>NoNulls</Nullable>
<IsNullable>false</IsNullable>
<Remarks />
</DbDfnColumn>
<DbDfnColumn>
<Schema>dbo</Schema>
<Table>JournalistArticle</Table>
<Pos>6</Pos>
<Name>Summary</Name>
<DataType>VarChar</DataType>
<DataTypeName />
<DataTypeNative>-9</DataTypeNative>
<DataTypeNameNative>nvarchar</DataTypeNameNative>
<IsIdentity>false</IsIdentity>
<Size>2000</Size>
<BufferLen>4000</BufferLen>
<DecimalDigits>0</DecimalDigits>
<Nullable>NoNulls</Nullable>
<IsNullable>false</IsNullable>
<Remarks />
</DbDfnColumn>
<DbDfnColumn>
<Schema>dbo</Schema>
<Table>JournalistArticle</Table>
<Pos>7</Pos>
<Name>BodyData</Name>
<DataType>VarChar</DataType>
<DataTypeName />
<DataTypeNative>-9</DataTypeNative>
<DataTypeNameNative>nvarchar</DataTypeNameNative>
<IsIdentity>false</IsIdentity>
<Size>0</Size>
<BufferLen>0</BufferLen>
<DecimalDigits>0</DecimalDigits>
<Nullable>NoNulls</Nullable>
<IsNullable>false</IsNullable>
<Remarks />
</DbDfnColumn>
<DbDfnColumn>
<Schema>dbo</Schema>
<Table>JournalistArticle</Table>
<Pos>8</Pos>
<Name>PublishedAt</Name>
<DataType>DateTime</DataType>
<DataTypeName />
<DataTypeNative>93</DataTypeNative>
<DataTypeNameNative>smalldatetime</DataTypeNameNative>
<IsIdentity>false</IsIdentity>
<Size>16</Size>
<BufferLen>16</BufferLen>
<DecimalDigits>0</DecimalDigits>
<Nullable>Nullable</Nullable>
<IsNullable>true</IsNullable>
<Remarks />
</DbDfnColumn>
<DbDfnColumn>
<Schema>dbo</Schema>
<Table>JournalistArticle</Table>
<Pos>9</Pos>
<Name>Notes</Name>
<DataType>VarChar</DataType>
<DataTypeName />
<DataTypeNative>-9</DataTypeNative>
<DataTypeNameNative>nvarchar</DataTypeNameNative>
<IsIdentity>false</IsIdentity>
<Size>2000</Size>
<BufferLen>4000</BufferLen>
<DecimalDigits>0</DecimalDigits>
<Nullable>NoNulls</Nullable>
<IsNullable>false</IsNullable>
<Remarks />
</DbDfnColumn>
<DbDfnColumn>
<Schema>dbo</Schema>
<Table>JournalistArticle</Table>
<Pos>10</Pos>
<Name>Flags</Name>
<DataType>SmallInt</DataType>
<DataTypeName />
<DataTypeNative>5</DataTypeNative>
<DataTypeNameNative>smallint</DataTypeNameNative>
<IsIdentity>false</IsIdentity>
<Size>5</Size>
<BufferLen>2</BufferLen>
<DecimalDigits>0</DecimalDigits>
<Nullable>NoNulls</Nullable>
<IsNullable>false</IsNullable>
<Remarks />
</DbDfnColumn>
<DbDfnColumn>
<Schema>dbo</Schema>
<Table>JournalistArticle</Table>
<Pos>11</Pos>
<Name>Status</Name>
<DataType>VarChar</DataType>
<DataTypeName />
<DataTypeNative>12</DataTypeNative>
<DataTypeNameNative>varchar</DataTypeNameNative>
<IsIdentity>false</IsIdentity>
<Size>3</Size>
<BufferLen>3</BufferLen>
<DecimalDigits>0</DecimalDigits>
<Nullable>NoNulls</Nullable>
<IsNullable>false</IsNullable>
<Remarks />
</DbDfnColumn>
<DbDfnColumn>
<Schema>dbo</Schema>
<Table>JournalistArticle</Table>
<Pos>12</Pos>
<Name>CreateOn</Name>
<DataType>DateTime</DataType>
<DataTypeName />
<DataTypeNative>93</DataTypeNative>
<DataTypeNameNative>datetime</DataTypeNameNative>
<IsIdentity>false</IsIdentity>
<Size>23</Size>
<BufferLen>16</BufferLen>
<DecimalDigits>3</DecimalDigits>
<Nullable>NoNulls</Nullable>
<IsNullable>false</IsNullable>
<Remarks />
</DbDfnColumn>
<DbDfnColumn>
<Schema>dbo</Schema>
<Table>JournalistArticle</Table>
<Pos>13</Pos>
<Name>CreateBy</Name>
<DataType>Int</DataType>
<DataTypeName />
<DataTypeNative>4</DataTypeNative>
<DataTypeNameNative>int</DataTypeNameNative>
<IsIdentity>false</IsIdentity>
<Size>10</Size>
<BufferLen>4</BufferLen>
<DecimalDigits>0</DecimalDigits>
<Nullable>NoNulls</Nullable>
<IsNullable>false</IsNullable>
<Remarks />
</DbDfnColumn>
<DbDfnColumn>
<Schema>dbo</Schema>
<Table>JournalistArticle</Table>
<Pos>14</Pos>
<Name>CreateHost</Name>
<DataType>VarChar</DataType>
<DataTypeName />
<DataTypeNative>12</DataTypeNative>
<DataTypeNameNative>varchar</DataTypeNameNative>
<IsIdentity>false</IsIdentity>
<Size>100</Size>
<BufferLen>100</BufferLen>
<DecimalDigits>0</DecimalDigits>
<Nullable>NoNulls</Nullable>
<IsNullable>false</IsNullable>
<Remarks />
</DbDfnColumn>
<DbDfnColumn>
<Schema>dbo</Schema>
<Table>JournalistArticle</Table>
<Pos>15</Pos>
<Name>UpdateOn</Name>
<DataType>DateTime</DataType>
<DataTypeName />
<DataTypeNative>93</DataTypeNative>
<DataTypeNameNative>datetime</DataTypeNameNative>
<IsIdentity>false</IsIdentity>
<Size>23</Size>
<BufferLen>16</BufferLen>
<DecimalDigits>3</DecimalDigits>
<Nullable>NoNulls</Nullable>
<IsNullable>false</IsNullable>
<Remarks />
</DbDfnColumn>
<DbDfnColumn>
<Schema>dbo</Schema>
<Table>JournalistArticle</Table>
<Pos>16</Pos>
<Name>UpdateBy</Name>
<DataType>Int</DataType>
<DataTypeName />
<DataTypeNative>4</DataTypeNative>
<DataTypeNameNative>int</DataTypeNameNative>
<IsIdentity>false</IsIdentity>
<Size>10</Size>
<BufferLen>4</BufferLen>
<DecimalDigits>0</DecimalDigits>
<Nullable>NoNulls</Nullable>
<IsNullable>false</IsNullable>
<Remarks />
</DbDfnColumn>
<DbDfnColumn>
<Schema>dbo</Schema>
<Table>JournalistArticle</Table>
<Pos>17</Pos>
<Name>UpdateHost</Name>
<DataType>VarChar</DataType>
<DataTypeName />
<DataTypeNative>12</DataTypeNative>
<DataTypeNameNative>varchar</DataTypeNameNative>
<IsIdentity>false</IsIdentity>
<Size>100</Size>
<BufferLen>100</BufferLen>
<DecimalDigits>0</DecimalDigits>
<Nullable>NoNulls</Nullable>
<IsNullable>false</IsNullable>
<Remarks />
</DbDfnColumn>
</Columns>
<Indices>
<DbDfnIndex>
<Schema>dbo</Schema>
<Table>JournalistArticle</Table>
<Name>PK_JournalistArticle</Name>
<IndexType>1</IndexType>
<Unique>true</Unique>
<Primary>false</Primary>
<Clustered>false</Clustered>
<Nullable>false</Nullable>
<Pages>1</Pages>
<UniqueValues>8</UniqueValues>
<HasColumns>false</HasColumns>
<Columns>
<DbDfnIndexColumn>
<Seq>1</Seq>
<Name>Id</Name>
<Ascend>true</Ascend>
</DbDfnIndexColumn>
</Columns>
</DbDfnIndex>
<DbDfnIndex>
<Schema>dbo</Schema>
<Table>JournalistArticle</Table>
<Name>IDX_JournalistArticle_Sport_Region_Published</Name>
<IndexType>3</IndexType>
<Unique>false</Unique>
<Primary>false</Primary>
<Clustered>false</Clustered>
<Nullable>false</Nullable>
<Pages>0</Pages>
<UniqueValues>0</UniqueValues>
<HasColumns>false</HasColumns>
<Columns>
<DbDfnIndexColumn>
<Seq>1</Seq>
<Name>SportIdPrimary</Name>
<Ascend>true</Ascend>
</DbDfnIndexColumn>
<DbDfnIndexColumn>
<Seq>2</Seq>
<Name>RegionIdPrimary</Name>
<Ascend>true</Ascend>
</DbDfnIndexColumn>
<DbDfnIndexColumn>
<Seq>3</Seq>
<Name>PublishedAt</Name>
<Ascend>true</Ascend>
</DbDfnIndexColumn>
</Columns>
</DbDfnIndex>
<DbDfnIndex>
<Schema>dbo</Schema>
<Table>JournalistArticle</Table>
<Name>IDX_JournalistArticle_User</Name>
<IndexType>3</IndexType>
<Unique>false</Unique>
<Primary>false</Primary>
<Clustered>false</Clustered>
<Nullable>false</Nullable>
<Pages>0</Pages>
<UniqueValues>0</UniqueValues>
<HasColumns>false</HasColumns>
<Columns>
<DbDfnIndexColumn>
<Seq>1</Seq>
<Name>UserAccountIdJournalist</Name>
<Ascend>true</Ascend>
</DbDfnIndexColumn>
</Columns>
</DbDfnIndex>
</Indices>
</DbDfnTable>
<DbDfnTable> <DbDfnTable>
<Schema>dbo</Schema> <Schema>dbo</Schema>
<Name>Organisation</Name> <Name>Organisation</Name>
@@ -4011,7 +4028,7 @@
<Clustered>false</Clustered> <Clustered>false</Clustered>
<Nullable>false</Nullable> <Nullable>false</Nullable>
<Pages>1</Pages> <Pages>1</Pages>
<UniqueValues>7</UniqueValues> <UniqueValues>8</UniqueValues>
<HasColumns>false</HasColumns> <HasColumns>false</HasColumns>
<Columns> <Columns>
<DbDfnIndexColumn> <DbDfnIndexColumn>
@@ -4474,7 +4491,7 @@
<Clustered>false</Clustered> <Clustered>false</Clustered>
<Nullable>false</Nullable> <Nullable>false</Nullable>
<Pages>1</Pages> <Pages>1</Pages>
<UniqueValues>10</UniqueValues> <UniqueValues>11</UniqueValues>
<HasColumns>false</HasColumns> <HasColumns>false</HasColumns>
<Columns> <Columns>
<DbDfnIndexColumn> <DbDfnIndexColumn>
@@ -4858,7 +4875,7 @@
<Clustered>false</Clustered> <Clustered>false</Clustered>
<Nullable>false</Nullable> <Nullable>false</Nullable>
<Pages>1</Pages> <Pages>1</Pages>
<UniqueValues>8</UniqueValues> <UniqueValues>10</UniqueValues>
<HasColumns>false</HasColumns> <HasColumns>false</HasColumns>
<Columns> <Columns>
<DbDfnIndexColumn> <DbDfnIndexColumn>
@@ -5641,7 +5658,7 @@
<Clustered>false</Clustered> <Clustered>false</Clustered>
<Nullable>false</Nullable> <Nullable>false</Nullable>
<Pages>1</Pages> <Pages>1</Pages>
<UniqueValues>5</UniqueValues> <UniqueValues>7</UniqueValues>
<HasColumns>false</HasColumns> <HasColumns>false</HasColumns>
<Columns> <Columns>
<DbDfnIndexColumn> <DbDfnIndexColumn>