1.2.11.12 Online Events

This commit is contained in:
2024-08-20 17:51:32 +01:00
parent 780e6778e5
commit 41db4e63d4
158 changed files with 6945 additions and 666 deletions
@@ -273,6 +273,9 @@
<data name="label.account" xml:space="preserve">
<value>My Account</value>
</data>
<data name="label.actions" xml:space="preserve">
<value>Actions</value>
</data>
<data name="label.activate" xml:space="preserve">
<value>Activate</value>
</data>
@@ -345,6 +348,9 @@
<data name="label.contacts" xml:space="preserve">
<value>Contacts</value>
</data>
<data name="label.copy" xml:space="preserve">
<value>Copy</value>
</data>
<data name="label.country" xml:space="preserve">
<value>Country</value>
</data>
@@ -396,6 +402,9 @@
<data name="label.email.address" xml:space="preserve">
<value>Email address</value>
</data>
<data name="label.ends" xml:space="preserve">
<value>Ends</value>
</data>
<data name="label.events" xml:space="preserve">
<value>Events</value>
</data>
@@ -423,6 +432,9 @@
<data name="label.feedback" xml:space="preserve">
<value>Feedback</value>
</data>
<data name="label.finishes" xml:space="preserve">
<value>Finishes</value>
</data>
<data name="label.first" xml:space="preserve">
<value>First</value>
</data>
@@ -645,6 +657,9 @@
<data name="label.sports.available" xml:space="preserve">
<value>Available sports</value>
</data>
<data name="label.starts" xml:space="preserve">
<value>Starts</value>
</data>
<data name="label.strength" xml:space="preserve">
<value>Strength</value>
</data>
@@ -675,6 +690,9 @@
<data name="label.type" xml:space="preserve">
<value>Type</value>
</data>
<data name="label.until" xml:space="preserve">
<value>Until</value>
</data>
<data name="label.update" xml:space="preserve">
<value>Update</value>
</data>
@@ -61,9 +61,9 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
data.About = userAccount.About;
data.Gender = (byte)userAccount.Gender;
data.GenderCaption = Localiser.GetGenderCaption(userAccount.Gender);
data.DobDay = (byte)userAccount.DateOfBirthDay;
data.DobMonth = (byte)userAccount.DateOfBirthMonth;
data.DobYear = (short)userAccount.DateOfBirthYear;
data.DobDay = (byte)(userAccount.DateOfBirthDay ?? 0);
data.DobMonth = (byte)(userAccount.DateOfBirthMonth ?? 0);
data.DobYear = (short)(userAccount.DateOfBirthYear ?? 0);
if (ItemDataMgr.ItemHasActiveImage(userAccount.GetItemId(), Sax.ImageType.Avatar))
data.HasImage = true;
// Regions.
@@ -205,18 +205,28 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
imageData = fileStream.ToArray();
}
// Validate content type.
if (StringUtil.IsEmpty(file.ContentType) || !SaxItemImage.GetValidContentTypes(Sax.DataItemType.UserAccount).ContainsCI(file.ContentType))
return Json(responseData.SetControlError("AccountContactImage", Localiser["msg.upload.image.invalid.content.type"]));
Sarand.Net.Standard.Base.Core.Sacs.MimeType mimeTypeExpected = SacsContentTypeHelper.GetMimeTypeFromContentType(file.ContentType);
// Validate the image.
ImageUtils.ImageConfig imageConfig = ImageUtils.VerifyImageData(imageData);
ImageUtils.ImageConfig imageConfig = null;
if (mimeTypeExpected == Sarand.Net.Standard.Base.Core.Sacs.MimeType.Svg)
imageConfig = ImageUtils.VerifySvgImageData(imageData);
else
imageConfig = ImageUtils.VerifyImageData(imageData);
if (!imageConfig.ValidImage)
return Json(responseData.SetControlError("AccountContactImage", Localiser["msg.upload.image.invalid"]));
// Validate mime type.
if (!SaxItemImage.GetValidMimeTypes(Sax.DataItemType.UserAccount).Contains(imageConfig.MimeType))
return Json(responseData.SetControlError("AccountContactImage", Localiser["msg.upload.image.invalid.mime"]));
// Validate content type.
if (StringUtil.IsEmpty(file.ContentType) || !SaxItemImage.GetValidContentTypes(Sax.DataItemType.UserAccount).ContainsCI(file.ContentType))
return Json(responseData.SetControlError("AccountContactImage", Localiser["msg.upload.image.invalid.content.type"]));
if (imageConfig.MimeType != mimeTypeExpected)
{
SaLogger.Warn($"{SysUtil.Fn} Image upload - inconsistent Mime. Filename: {file.FileName}. Mime: {imageConfig.MimeType}. Expected Mime: {mimeTypeExpected}.");
return Json(responseData.SetControlError("OrganisationLogoImage", Localiser["msg.upload.image.invalid"]));
}
// Resize the image if required.
if (!ImageUtils.ConstrainImage(imageConfig, Sax.Config.User.Image.WidthMax, Sax.Config.User.Image.HeightMax))
@@ -444,18 +444,28 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
imageData = fileStream.ToArray();
}
// Validate content type.
if (StringUtil.IsEmpty(file.ContentType) || !SaxItemImage.GetValidContentTypes(Sax.DataItemType.Article).ContainsCI(file.ContentType))
return Json(responseData.SetControlError("ArticleImage", Localiser["msg.upload.image.invalid.content.type"]));
Sarand.Net.Standard.Base.Core.Sacs.MimeType mimeTypeExpected = SacsContentTypeHelper.GetMimeTypeFromContentType(file.ContentType);
// Validate the image.
ImageUtils.ImageConfig imageConfig = ImageUtils.VerifyImageData(imageData);
ImageUtils.ImageConfig imageConfig = null;
if (mimeTypeExpected == Sarand.Net.Standard.Base.Core.Sacs.MimeType.Svg)
imageConfig = ImageUtils.VerifySvgImageData(imageData);
else
imageConfig = ImageUtils.VerifyImageData(imageData);
if (!imageConfig.ValidImage)
return Json(responseData.SetControlError("ArticleImage", Localiser["msg.upload.image.invalid"]));
// Validate mime type.
if (!SaxItemImage.GetValidMimeTypes(Sax.DataItemType.Article).Contains(imageConfig.MimeType))
return Json(responseData.SetControlError("ArticleImage", Localiser["msg.upload.image.invalid.mime"]));
// Validate content type.
if (StringUtil.IsEmpty(file.ContentType) || !SaxItemImage.GetValidContentTypes(Sax.DataItemType.Article).ContainsCI(file.ContentType))
return Json(responseData.SetControlError("ArticleImage", Localiser["msg.upload.image.invalid.content.type"]));
if (imageConfig.MimeType != mimeTypeExpected)
{
SaLogger.Warn($"{SysUtil.Fn} Image upload - inconsistent Mime. Filename: {file.FileName}. Mime: {imageConfig.MimeType}. Expected Mime: {mimeTypeExpected}.");
return Json(responseData.SetControlError("OrganisationLogoImage", Localiser["msg.upload.image.invalid"]));
}
// Resize the image if required.
if (!ImageUtils.ConstrainImage(imageConfig, Sax.Config.Articles.Images.WidthMax, Sax.Config.Articles.Images.HeightMax))
@@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Diagnostics;
using Sarand.Net.Standard.Base.App;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Core;
@@ -23,12 +24,14 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
// Organisation Event data.
private class EventListData : AjaxResponse_Data.ItemData_Base
{
public String EventDateFmt { get; set; }
public String EventTimeFmt { get; set; }
public String EventAtDateFmt { get; set; }
public String EventAtTimeFmt { get; set; }
public String EventToDateFmt { get; set; }
public String EventToTimeFmt { get; set; }
public String Duration { get; set; }
public String TypeCode { get; set; }
public String TypeDesc { get; set; }
public String Summary { get; set; }
public String Details { get; set; }
public String SportCaptionPrimary { get; set; }
public String RegionCaptionCountry { get; set; }
public String PublishedOnFmt { get; set; }
@@ -36,9 +39,13 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
}
private class EventItemData : EventListData
{
public String EventOn_Calendar { get; set; }
public String EventOn_YYYYMMDD { get; set; }
public String EventAt_Calendar { get; set; }
public String EventAt_YYYYMMDD { get; set; }
public String EventAt_HHMM { get; set; }
public String EventTo_Calendar { get; set; }
public String EventTo_YYYYMMDD { get; set; }
public String EventTo_HHMM { get; set; }
public String Details { get; set; }
public String SportIdPrimary { get; set; }
public String RegionIdCountry { get; set; }
public String PublishedOn_YYYYMMDD { get; set; }
@@ -47,30 +54,51 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
private void PopulateEventResponseListData(Model_Organisation_Events model, SaxOrganisationEvent organisationEvent, EventListData data)
{
data.Id = model.EncryptId(organisationEvent.Id);
data.EventDateFmt = Localiser.FormatDate(organisationEvent.EventAt);
data.EventTimeFmt = DateUtil.Format(organisationEvent.EventAt, "HH:mm");
// 'At' date/time.
data.EventAtDateFmt = Localiser.FormatDate(organisationEvent.EventAt);
if (organisationEvent.HasValidEventAtTime())
data.EventAtTimeFmt = DateUtil.Format(organisationEvent.EventAt, "HH:mm");
// 'To' date/time.
data.EventToDateFmt = Localiser.FormatDate(organisationEvent.EventTo);
if (organisationEvent.HasValidEventToTime())
data.EventToTimeFmt = DateUtil.Format(organisationEvent.EventTo, "HH:mm");
// Event properties.
if (DateUtil.IsValid(organisationEvent.EventTo) && organisationEvent.EventTo > organisationEvent.EventAt)
data.Duration = DateUtil.FormatNumberOfSeconds(((DateTime)organisationEvent.EventTo - organisationEvent.EventAt).TotalSeconds);
data.TypeCode = EventTypeCodes.GetCodeForType(organisationEvent.EventType);
data.TypeDesc = Localiser.GetEventTypeCaption(organisationEvent.EventType);
data.Summary = organisationEvent.Summary;
data.Details = organisationEvent.Details;
data.SportCaptionPrimary = model.GetSportCaption(organisationEvent.SportIdPrimary);
data.RegionCaptionCountry = model.GetRegionCaption(organisationEvent.RegionIdCountry);
data.CreatedOnFmt = Localiser.FormatDate(organisationEvent.CreateStamp.On);
data.PublishedOnFmt = Localiser.FormatDate(organisationEvent.PublishedAt);
data.ExpiresOnFmt = Localiser.FormatDate(organisationEvent.ExpiresAt);
if (DateUtil.IsValid(organisationEvent.PublishedAt))
data.PublishedOnFmt = Localiser.FormatDate(organisationEvent.PublishedAt);
if (DateUtil.IsValid(organisationEvent.ExpiresAt))
data.ExpiresOnFmt = Localiser.FormatDate(organisationEvent.ExpiresAt);
data.StatusCode = organisationEvent.StatusCode;
data.StatusDesc = organisationEvent.StatusDesc;
}
private void PopulateEventResponseItemData(Model_Organisation_Events model, SaxOrganisationEvent organisationEvent, EventItemData data)
{
PopulateEventResponseListData(model, organisationEvent, data as EventListData);
data.EventOn_Calendar = model.FormatDateForForm(organisationEvent.EventAt);
data.EventOn_YYYYMMDD = DateUtil.Format(organisationEvent.EventAt, "yyyyMMdd");
data.EventAt_HHMM = DateUtil.Format(organisationEvent.EventAt, "HH:mm");
// 'At' date/time.
data.EventAt_Calendar = model.FormatDateForForm(organisationEvent.EventAt);
data.EventAt_YYYYMMDD = DateUtil.Format(organisationEvent.EventAt, "yyyyMMdd");
if (organisationEvent.HasValidEventAtTime())
data.EventAt_HHMM = DateUtil.Format(organisationEvent.EventAt, "HH:mm");
// 'To' date/time.
data.EventTo_Calendar = model.FormatDateForForm(organisationEvent.EventTo);
data.EventTo_YYYYMMDD = DateUtil.Format(organisationEvent.EventTo, "yyyyMMdd");
if (organisationEvent.HasValidEventToTime())
data.EventTo_HHMM = DateUtil.Format(organisationEvent.EventTo, "HH:mm");
// Event properties.
data.Details = organisationEvent.Details;
data.RegionIdCountry = model.GetEncryptedRegionId(organisationEvent.RegionIdCountry);
data.SportIdPrimary = model.GetEncryptedSportId(organisationEvent.SportIdPrimary);
data.PublishedOn_YYYYMMDD = DateUtil.Format(organisationEvent.PublishedAt, "yyyyMMdd");
data.ExpiresOn_YYYYMMDD = DateUtil.Format(organisationEvent.ExpiresAt, "yyyyMMdd");
if (DateUtil.IsValid(organisationEvent.PublishedAt))
data.PublishedOn_YYYYMMDD = DateUtil.Format(organisationEvent.PublishedAt, "yyyyMMdd");
if (DateUtil.IsValid(organisationEvent.ExpiresAt))
data.ExpiresOn_YYYYMMDD = DateUtil.Format(organisationEvent.ExpiresAt, "yyyyMMdd");
}
//-------------------------------------------------------------------
@@ -101,6 +129,7 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
public OrganisationData Organisation { get; } = new OrganisationData();
// Reference data.
public List<CodeDesc> EventTypes { get; } = new List<CodeDesc>();
public String EventTypeDefault { get; set; }
}
//-------------------------------------------------------------------
[HttpPost]
@@ -140,6 +169,8 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
// Reference data - organisationEvent types.
foreach (TypeCodeDesc eventType in EventTypeCodes)
responseData.EventTypes.Add(eventType.Code, Localiser.GetEventTypeCaption((Sax.EventType)eventType.Type));
// ToDo: Organisation default Event Type.
responseData.EventTypeDefault = EventTypeCodes.GetCodeForType(Sax.EventType.Playing);
// User organisation.
SaxUserOrganisation.Params prmUserOrganisation = new SaxUserOrganisation.Params();
@@ -170,17 +201,34 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
SaxOrganisationEvent.Params prmEvent = new SaxOrganisationEvent.Params();
prmEvent.UserAccountIdsIncluded.Add(userAccountId);
prmEvent.OrganisationIdsIncluded.Add(organisationId);
switch (model.Filter.Period.PeriodType)
{
case Model_Organisation_Events.PeriodType.FromThisMonth:
prmEvent.EventFrom = DateUtil.StartOfMonth(DateTime.Today);
break;
case Model_Organisation_Events.PeriodType.FromLastMonth:
prmEvent.EventFrom = DateUtil.StartOfMonth(DateUtil.IncrementMonth(DateTime.Today, -1));
break;
case Model_Organisation_Events.PeriodType.FromNextMonth:
prmEvent.EventFrom = DateUtil.StartOfMonth(DateUtil.IncrementMonth(DateTime.Today, 1));
break;
case Model_Organisation_Events.PeriodType.FromThisWeek:
default:
prmEvent.EventFrom = DateUtil.StartOfWorkingWeek(DateTime.Today);
break;
}
prmEvent.EventFilter = model.Filter.Event;
prmEvent.StatusCat = SaxOrganisationEvent.StatusCat.NotDeleted;
prmEvent.SortColumns.Add(ActivityMgr.GetOrganisationEventColumnDfn(SaxOrganisationEvent.Column.EventAt_DateTime));
model.Paging.ItemTotal = (ulong)ActivityMgr.GetOrganisationEventCount(prmEvent);
model.PopulatePagingTo(prmEvent.ResultsPaging);
// Item columns.
ColumnDfn colId = ActivityMgr.GetOrganisationEventColumnDfn(SaxOrganisationEvent.Column.Id);
ColumnDfn colEventAt = ActivityMgr.GetOrganisationEventColumnDfn(SaxOrganisationEvent.Column.EventAt_DateTime);
ColumnDfn colEventTo = ActivityMgr.GetOrganisationEventColumnDfn(SaxOrganisationEvent.Column.EventTo_DateTime);
ColumnDfn colEventTypeCode = ActivityMgr.GetOrganisationEventColumnDfn(SaxOrganisationEvent.Column.EventTypeCode);
ColumnDfn colSummary = ActivityMgr.GetOrganisationEventColumnDfn(SaxOrganisationEvent.Column.Summary);
ColumnDfn colDetails = ActivityMgr.GetOrganisationEventColumnDfn(SaxOrganisationEvent.Column.Details);
ColumnDfn colRegionId = ActivityMgr.GetOrganisationEventColumnDfn(SaxOrganisationEvent.Column.RegionIdCountry);
ColumnDfn colRegionName = ActivityMgr.GetOrganisationEventColumnDfn(SaxOrganisationEvent.Column.Region_Name);
ColumnDfn colSportId = ActivityMgr.GetOrganisationEventColumnDfn(SaxOrganisationEvent.Column.SportIdPrimary);
@@ -191,7 +239,7 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
ColumnDfn colCreatedOn = ActivityMgr.GetOrganisationEventColumnDfn(SaxOrganisationEvent.Column.CreateOn_Date);
List<ColumnDfn> columns = new List<ColumnDfn>()
{
colId, colEventAt, colEventTypeCode, colSummary, colDetails,
colId, colEventAt, colEventTo, colEventTypeCode, colSummary,
colRegionId, colRegionName, colSportId, colSportName,
colPublishedOn, colExpiresOn,
colStatus, colCreatedOn
@@ -207,15 +255,15 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
while (resultSet != null && resultSet.HasRows && resultSet.NextRecord())
{
NamedValue.Map values = resultSet.GetRecordValues();
DateTime eventAt = values.GetDateTime(colEventAt.DataName);
DateTime? eventTo = values.GetDateTime(colEventTo.DataName);
EventListData eventData = new EventListData()
{
Id = model.EncryptId(new SysId(values.GetLong(colId.DataName))),
EventDateFmt = Localiser.FormatDate(values.GetDateTime(colEventAt.DataName)),
EventTimeFmt = DateUtil.Format(values.GetDateTime(colEventAt.DataName), "HH:mm"),
EventAtDateFmt = Localiser.FormatDate(values.GetDateTime(colEventAt.DataName)),
TypeCode = values.GetString(colEventTypeCode.DataName),
TypeDesc = Localiser.GetEventTypeCaption((Sax.EventType)EventTypeCodes.GetTypeForCode(values.GetString(colEventTypeCode.DataName))),
Summary = ActivityMgr.GetOrganisationEventDataValue(colSummary, values).AsString(),
Details = ActivityMgr.GetOrganisationEventDataValue(colDetails, values).AsString(),
RegionCaptionCountry = model.GetRegionCaption(values.GetString(colRegionId.DataName).ToSysId()),
SportCaptionPrimary = model.GetSportCaption(values.GetString(colSportId.DataName).ToSysId()),
CreatedOnFmt = Localiser.FormatDate(values.GetDateTime(colCreatedOn.DataName)),
@@ -224,6 +272,14 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
StatusCode = values.GetString(colStatus.DataName),
StatusDesc = SacsSystem.GetStatusDescForCode(values.GetString(colStatus.DataName))
};
if (SaxOrganisationEvent.HasValidEventTime(eventAt))
eventData.EventAtTimeFmt = DateUtil.Format(eventAt, "HH:mm");
if (DateUtil.IsValid(eventTo) && eventAt.Date != ((DateTime)eventTo).Date)
eventData.EventToDateFmt = Localiser.FormatDate(eventTo);
if (SaxOrganisationEvent.HasValidEventTime(eventTo))
eventData.EventToTimeFmt = DateUtil.Format(eventTo, "HH:mm");
if (DateUtil.IsValid(eventTo) && eventTo > eventAt)
eventData.EventAtTimeFmt = DateUtil.FormatNumberOfSeconds(((DateTime)eventTo - eventAt).TotalSeconds);
responseData.Events.Add(eventData);
}
}
@@ -254,7 +310,7 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
public IActionResult Ajax_GetEvent(Model_Organisation_Events model)
{
String fn = GetType().Name + ".Ajax_GetEvent";
String messageTitle = Localiser["organisation.caption.organisationEvent"];
String messageTitle = Localiser["organisation.caption.event"];
AjaxResponse_Event responseData = new AjaxResponse_Event(model);
// Validate session and referrer.
@@ -309,7 +365,7 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
public IActionResult Ajax_StoreEvent(Model_Organisation_Events model)
{
String fn = GetType().Name + ".Ajax_StoreEvent";
String messageTitle = Localiser["organisation.caption.organisationEvent"];
String messageTitle = Localiser["organisation.caption.event"];
AjaxResponse_Event responseData = new AjaxResponse_Event(model);
// Validate session and referrer.
@@ -388,11 +444,33 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
organisationEvent.SportIdPrimary = model.ExtractSysId(model.EventSportIdPrimary);
if (model.EventRegionIdCountry != null)
organisationEvent.RegionIdCountry = model.ExtractSysId(model.EventRegionIdCountry);
if (model.EventDate != null)
if (model.EventAtDate != null)
{
organisationEvent.EventAt = model.ParseDateFromForm(model.EventDate);
if (!StringUtil.IsEmpty(model.EventTime))
organisationEvent.EventAt = DateUtil.SetTime(organisationEvent.EventAt, DateUtil.ParseExact(model.EventTime, "HH:mm"));
// 'At' date.
organisationEvent.EventAt = model.ParseDateFromForm(model.EventAtDate);
if (model.EventAtTimeSet && !StringUtil.IsBlank(model.EventAtTime))
{
// For midnight (00:00) set +1 minute so that the value is treated as a valid start time.
if (model.EventAtTime.Equals("00:00"))
model.EventAtTime = "00:01";
organisationEvent.EventAt = DateUtil.SetTime(organisationEvent.EventAt, DateUtil.ParseExact(model.EventAtTime, "HH:mm"));
}
if (model.EventToDateSet || model.EventToTimeSet)
{
// 'To' date.
organisationEvent.EventTo = organisationEvent.EventAt;
if (model.EventToDate != null && model.EventToDateSet)
organisationEvent.EventTo = model.ParseDateFromForm(model.EventToDate);
// 'To' time.
if (model.EventAtTimeSet && model.EventToTimeSet && !StringUtil.IsBlank(model.EventToTime))
{
// For midnight (00:00) set +1 minute so that the value is treated as a valid finish time.
if (model.EventToTime.Equals("00:00"))
model.EventToTime = "00:01";
organisationEvent.EventTo = DateUtil.SetTime(organisationEvent.EventTo ?? organisationEvent.EventAt, DateUtil.ParseExact(model.EventToTime, "HH:mm"));
}
}
else organisationEvent.EventTo = null;
}
if (model.EventTypeCode != null)
organisationEvent.EventType = (Sax.EventType)EventTypeCodes.GetTypeForCode(model.EventTypeCode);
@@ -132,7 +132,7 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
OrganisationData organisationData = null;
// Roles (any) required for organisation list.
List <Sax.OrganisationRole> requiredRoles = new List<Sax.OrganisationRole>() { Sax.OrganisationRole.Admin };
List<Sax.OrganisationRole> requiredRoles = new List<Sax.OrganisationRole>() { Sax.OrganisationRole.Admin };
if (organisationRole > 0)
requiredRoles.Add(organisationRole);
@@ -141,9 +141,14 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
prmUserOrganisation.UserAccountIdsIncluded.Add(SessionUserAccountId);
prmUserOrganisation.OrganisationStatusCat = SaxOrganisation.StatusCat.ActiveOnly;
prmUserOrganisation.OrganisationMembersOnly = true;
prmUserOrganisation.OrganisationRolesAny.AddRange(requiredRoles);
prmUserOrganisation.OrganisationRolesAny.UnionWith(requiredRoles);
prmUserOrganisation.StatusCat = SaxUserOrganisation.StatusCat.ActiveOnly;
if (organisationRole == Sax.OrganisationRole.ScheduleAdmin)
{
prmUserOrganisation.OrganisationHasScheduledEvents = true;
}
// Restrict to specified Organisation.
if (SysId.IsValid(filterOrganisationId))
{
@@ -154,6 +159,10 @@ namespace Saxonite.Net.Core.Web.Online.Controllers
prmUserOrganisation.OrganisationIdsIncluded.Clear();
}
// Clear 'Scheduled Events' flag if no organisations available.
if (prmUserOrganisation.OrganisationHasScheduledEvents && AccountMgr.GetUserOrganisationCount(prmUserOrganisation) < 1)
prmUserOrganisation.OrganisationHasScheduledEvents = false;
// Pick the first valid Organisation.
ColumnDfn colOrganisationId = AccountMgr.GetUserOrganisationColumnDfn(SaxUserOrganisation.Column.OrganisationId);
ColumnDfn colOrganisationName = AccountMgr.GetUserOrganisationColumnDfn(SaxUserOrganisation.Column.Organisation_Name);
@@ -1,4 +1,6 @@
using Sarand.Net.Standard.Base.App;
using Microsoft.AspNetCore.Mvc.Rendering;
using NPOI.SS.Formula.Functions;
using Sarand.Net.Standard.Base.App;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Utils;
@@ -16,12 +18,23 @@ namespace Saxonite.Net.Core.Web.Online.Models
//=======================================================================
public class Model_Organisation_Events : SaxModel_Online
{
//-------------------------------------------------------------------
// Definitions.
public enum PeriodType
{
FromThisWeek,
FromThisMonth,
FromLastMonth,
FromNextMonth,
Past,
}
//-------------------------------------------------------------------
// Construction.
public Model_Organisation_Events(SaxLocaliser localiser) :
base(localiser)
{
//AdditionalFiles_CSS.Add("css/sax-org-evt.css");
AdditionalFiles_CSS.Add("css/sax-org-evt.css");
AdditionalFiles_JS.Add("js/sax-org-evt.js");
}
@@ -31,6 +44,14 @@ namespace Saxonite.Net.Core.Web.Online.Models
{
public String OrganisationId { get; set; }
public String OrganisationCaption { get; set; }
public class PeriodData
{
public String Type { get; set; }
public PeriodType PeriodType { get { return EnumUtil.ParseEnum(Type, PeriodType.FromThisWeek); } }
public String FromDate { get; set; }
public String ToDate { get; set; }
}
public PeriodData Period { get; } = new PeriodData();
public String Event { get; set; }
}
public EventFilterData Filter { get; } = new EventFilterData();
@@ -46,14 +67,36 @@ namespace Saxonite.Net.Core.Web.Online.Models
// Region.
public String EventRegionIdCountry { get; set; }
// Event Content.
public String EventDate { get; set; }
public String EventTime { get; set; }
public String EventAtDate { get; set; }
public bool EventAtTimeSet { get; set; }
public String EventAtTime { get; set; }
public String EventDuration { get; set; }
public String EventDurationType { get; set; }
public String EventToDate { get; set; }
public bool EventToDateSet { get; set; }
public String EventToTime { get; set; }
public bool EventToTimeSet { get; set; }
public String EventTypeCode { get; set; }
public String EventSummary { get; set; }
public String EventDetails { get; set; }
public String EventStatusCode { get; set; }
public SaStatus EventStatus { get { return SacsSystem.GetStatusForCode(EventStatusCode); } }
//-------------------------------------------------------------------
// Period types.
public IEnumerable<SelectListItem> EventPeriodTypesForDropdown
{
get
{
List<SelectListItem> values = new List<SelectListItem>();
values.Add(new SelectListItem("From this week", PeriodType.FromThisWeek.ToString(), true));
values.Add(new SelectListItem("From this month", PeriodType.FromThisMonth.ToString()));
values.Add(new SelectListItem("From last month", PeriodType.FromLastMonth.ToString()));
values.Add(new SelectListItem("From next month", PeriodType.FromNextMonth.ToString()));
return values;
}
}
//-------------------------------------------------------------------
// Validation.
//-------------------------------------------------------------------
@@ -63,64 +106,125 @@ namespace Saxonite.Net.Core.Web.Online.Models
// Event type.
if (EventTypeCode != null)
{
String controlName = nameof(EventTypeCode);
if (StringUtil.IsEmpty(EventTypeCode))
responseData.SetControlError(nameof(EventTypeCode), Localiser["msg.validation.mandatory.value"]);
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
}
// Event date.
if (EventDate != null)
// Event At date.
if (EventAtDate != null)
{
DateTime eventOn = ParseDateFromForm(EventDate);
String controlName = nameof(EventAtDate);
DateTime eventOn = ParseDateFromForm(EventAtDate);
if (!DateUtil.IsValid(eventOn))
responseData.SetControlError(nameof(EventDate), Localiser["msg.validation.mandatory.value"]);
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
}
// Event time.
if (EventTime != null)
// Event At Time Set flag.
if (EventAtTimeSet)
{
String controlName = nameof(EventAtTime);
if (StringUtil.IsBlank(EventAtTime))
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
}
// Event At time.
if (EventAtTime != null && EventAtTimeSet)
{
String controlName = nameof(EventAtTime);
DateTime eventAt = DateUtil.ParseExact(EventAtTime, "HH:mm");
if (StringUtil.IsBlank(EventAtTime))
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
else if (!DateUtil.IsValid(eventAt))
responseData.SetControlError(controlName, Localiser["msg.validation.invalid.value"]);
}
// Event duration.
if (EventDuration != null)
{
String controlName = nameof(EventDuration);
}
// Event duration type.
if (EventDurationType != null)
{
String controlName = nameof(EventDurationType);
}
// Event To date.
if (EventToDate != null && EventToDateSet)
{
String controlName = nameof(EventToDate);
DateTime eventOn = ParseDateFromForm(EventToDate);
if (!DateUtil.IsValid(eventOn))
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
}
// Event To Time Set flag.
if (EventToTimeSet)
{
String controlName = nameof(EventToTime);
if (StringUtil.IsBlank(EventToTime))
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
}
// Event To time.
if (EventToTime != null && EventToTimeSet)
{
String controlName = nameof(EventToTime);
DateTime eventTo = DateUtil.ParseExact(EventToTime, "HH:mm");
if (StringUtil.IsBlank(EventToTime))
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
else if (!DateUtil.IsValid(eventTo))
responseData.SetControlError(controlName, Localiser["msg.validation.invalid.value"]);
}
// Event summary.
if (EventSummary != null)
{
responseData.SetControlValue(nameof(EventSummary), EventSummary);
String controlName = nameof(EventSummary);
responseData.SetControlValue(controlName, EventSummary);
if (StringUtil.IsEmpty(EventSummary))
responseData.SetControlError(nameof(EventSummary), Localiser["msg.validation.mandatory.value"]);
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
else if (StringUtil.GetLength(EventSummary) > GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.OrganisationEvent_Summary))
responseData.SetControlError(nameof(EventSummary), Localiser["msg.validation.maximum.length", GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.OrganisationEvent_Summary)]);
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.OrganisationEvent_Summary)]);
}
// Event details.
if (EventDetails != null)
{
responseData.SetControlValue(nameof(EventDetails), EventDetails);
String controlName = nameof(EventDetails);
responseData.SetControlValue(controlName, EventDetails);
if (StringUtil.GetLength(EventDetails) > GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.OrganisationEvent_Details))
responseData.SetControlError(nameof(EventDetails), Localiser["msg.validation.maximum.length", GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.OrganisationEvent_Details)]);
responseData.SetControlError(controlName, Localiser["msg.validation.maximum.length", GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.OrganisationEvent_Details)]);
}
// Event sport.
if (EventSportIdPrimary != null)
{
String controlName = "EventSportPrimary";
SysId articleSportId = ExtractSysId(EventSportIdPrimary);
if (!SysId.IsValid(articleSportId))
responseData.SetControlError("EventSportPrimary", Localiser["msg.validation.mandatory.value"]);
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
}
// Event region.
if (EventRegionIdCountry != null)
{
String controlName = "EventRegionCountry";
SysId articleRegionId = ExtractSysId(EventRegionIdCountry);
if (!SysId.IsValid(articleRegionId))
responseData.SetControlError("EventRegionCountry", Localiser["msg.validation.mandatory.value"]);
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
}
// Event status.
if (EventStatusCode != null)
{
String controlName = nameof(EventStatus);
if (StringUtil.IsEmpty(EventStatusCode))
responseData.SetControlError(nameof(EventStatus), Localiser["msg.validation.mandatory.value"]);
responseData.SetControlError(controlName, Localiser["msg.validation.mandatory.value"]);
else if (!SaxOrganisationEvent.ValidStatuses.Contains(EventStatus))
responseData.SetControlError(nameof(EventStatus), Localiser["msg.validation.invalid.value"]);
responseData.SetControlError(controlName, Localiser["msg.validation.invalid.value"]);
}
return !responseData.HasControlErrors();
@@ -10,7 +10,8 @@
<ItemGroup>
<PackageReference Include="jQuery.UI.Combined" Version="1.13.2" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="6.0.30" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="6.0.31" />
<PackageReference Include="Moment.js" Version="2.30.1" />
<PackageReference Include="System.Collections.Specialized" Version="4.3.0" />
</ItemGroup>
@@ -34,6 +35,10 @@
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Update="wwwroot\css\sax-org-evt.css">
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Update="wwwroot\rjs\sax-rjs.css">
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
@@ -8,6 +8,7 @@
<script type="text/javascript">
sax.lbl.edit = '@(Localiser.GetJavascriptText("label.edit"))';
sax.lbl.copy = '@(Localiser.GetJavascriptText("label.copy"))';
</script>
@* Filter Form *@
@@ -31,16 +32,18 @@
</div>
<div class="sax-content">
<div class="sax-control row">
<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-3"><div class="sax-label text-left text-sm-right">@Localiser["label.organisation"]</div></div>
<div class="col-sm-9 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 SelectFilterOrganisation">@Localiser["label.select"]</button></div>
</div>
</div>
<div class="sax-control row">
<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" id="ifEventFilter" name="Filter.Event" class="EventFilter sax-input" maxlength="64" autocomplete="off" /></div>
<div class="col-sm-3"><div class="sax-label text-left text-sm-right">@Localiser["label.period"]</div></div>
<div class="col-sm-3">@Html.DropDownListFor(model => model.Filter.Period.Type, Model.EventPeriodTypesForDropdown, new { @id = "cbFilterPeriodType", @class = "FilterPeriodType sax-select" })</div>
<div class="col-sm-3"><div class="sax-label text-left text-sm-right">@Localiser["label.search"]</div></div>
<div class="col-sm-3"><input type="search" id="ifEventFilter" name="Filter.Event" class="EventFilter sax-input" maxlength="64" autocomplete="off" /></div>
</div>
</div>
@@ -59,40 +62,46 @@
@* Results Panel *@
<div class="sax-panel-results">
<div class="sax-panel-messages"></div>
<div class="sax-panel-item-list"></div>
<div class="sax-panel-item-table">
<div class="sax-panel-info" style="min-height:120px;max-height:100%;overflow-y:auto;">
<table class="sax-item-list">
<thead>
<tr>
<th class="center">@Localiser["label.date"]</th>
<th class="center">@Localiser["label.time"]</th>
<th class="">@Localiser["label.summary"]</th>
<th class="center">@Localiser["label.published"]</th>
<th class="center">@Localiser["label.actions"]</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
@* Element templates *@
<div class="sax-panel-item-template">
@* Item template *@
<div class="sax-panel-item Event">
<div class="sax-header row">
<div class="col">
<div class="sax-caption"><div class="sax-action"><span class="EventDate"></span><span class=""></span></div></div>
</div>
<div class="fixed sax-actions">
@* 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 class="sax-content">
<div class="row">
<div class="col-sm-12"><div class="EventSummary"></div></div>
<div class="col-sm-6"><div class="EventRegionCaption sax-note"></div></div>
<div class="col-sm-6 right"><div class="EventSportCaption sax-note"></div></div>
</div>
<div class="row">
<div class="col-sm-4"><div class="sax-note">@Localiser["label.created"]:&nbsp;<span class="EventCreatedOn"></span></div></div>
<div class="col-sm-4"><div class="EventPublished sax-note">@Localiser["label.published"]:&nbsp;<span class="EventPublishedOn"></span></div></div>
<div class="col-sm-4 right"><div class="EventStatusDesc sax-note"></div></div>
</div>
</div>
</div>
<table>
<tr class="sax-row-item Event">
<td><div class="EventAtDate center"></div></td>
<td><div class="EventAtTime center"></div></td>
<td><div class="EventSummary pointer"></div></td>
<td><div class="EventPublishedOn center"></div></td>
<td>
<div class="EventActions center">
@* 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>
</td>
</tr>
</table>
@* Burger dropdown item template - ul is ignored *@
<ul class="sax-dropdown-menu Event">
@@ -2,6 +2,11 @@
@inject SaxLocaliser Localiser
@{
/* Organisation Events - Event dialog panel */
//Model.AdditionalFiles_CSS.Add("lib/jquery-timepicker/jquery.timepicker.min.css");
//Model.AdditionalFiles_JS.Add("lib/jquery-timepicker/jquery.timepicker.min.js");
//Model.AdditionalFiles_CSS.Add("lib/bootstrap4-datetimepicker/bootstrap-datetimepicker.min.css");
//Model.AdditionalFiles_JS.Add("lib/moment.js/moment.min.js");
//Model.AdditionalFiles_JS.Add("lib/bootstrap4-datetimepicker/bootstrap-datetimepicker.min.js");
}
<script type="text/javascript">
@@ -41,19 +46,79 @@
</div>
</div>
@* Event date and time *@
<div class="sax-form-control EventDate">
@* Event At date and time *@
<div class="sax-form-control EventAtDate">
<div class="row">
<div class="col-sm-3">
<div class="sax-label">
<label for="ifEventDate"><span>@Localiser["label.occurs"]</span><span class="required">&nbsp;*</span></label>
<label for="ifEventAtDate"><span>@Localiser["label.occurs"]</span><span class="required">&nbsp;*</span></label>
</div>
</div>
<div class="col-sm">
<div class="sax-control">
<input id="ifEventDate" name="EventDate" class="EventDate sax-input sax-calendar" readonly="readonly" />
<div class="row">
<div class="col-sm">
<div class="sax-control">
<input id="ifEventAtDate" name="EventAtDate" class="EventAtDate sax-input sax-calendar" readonly="readonly" />
</div>
<div class="sax-message"></div>
</div>
<div class="col-sm">
<div class="row">
<div class="col pl-sm-4 pt-2">
@Html.CheckBoxFor(model => model.EventAtTimeSet, new { @id = "chkEventAtTimeSet", @class = "sax-checkbox" })
&nbsp;
<span class="sax-label pointer" onclick="$('#chkEventAtTimeSet').click()">@Localiser["label.starts"]</span>
</div>
<div class="col">
<div class="sax-control">
<input type="time" id="ifEventAtTime" name="EventAtTime" class="EventAtTime sax-input" />
</div>
<div class="sax-message"></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
@* Event To date and time *@
<div class="sax-form-control EventToDate">
<div class="row">
<div class="col-sm-3 row">
<div class="col">
<div class="sax-label"><span>@Localiser["label.until"]</span></div>
</div>
<div class="fixed">
<div class="pt-2 pr-2">
@Html.CheckBoxFor(model => model.EventToDateSet, new { @id = "chkEventToDateSet", @class = "sax-checkbox" })
</div>
</div>
</div>
<div class="col-sm">
<div class="row">
<div class="col-sm">
<div class="sax-control">
<input id="ifEventToDate" name="EventToDate" class="EventToDate sax-input sax-calendar" readonly="readonly" />
</div>
<div class="sax-message"></div>
</div>
<div class="col-sm">
<div class="row">
<div class="col pl-sm-4 pt-2">
@Html.CheckBoxFor(model => model.EventToTimeSet, new { @id = "chkEventToTimeSet", @class = "sax-checkbox" })
&nbsp;
<span class="sax-label pointer" onclick="$('#chkEventToTimeSet').click()">@Localiser["label.finishes"]</span>
</div>
<div class="col">
<div class="sax-control">
<input type="time" id="ifEventToTime" name="EventToTime" class="EventToTime sax-input" />
</div>
<div class="sax-message"></div>
</div>
</div>
</div>
</div>
<div class="sax-message"></div>
</div>
</div>
</div>
@@ -64,7 +129,13 @@
<label for="ifEventSummary"><span>@Localiser["label.summary"]</span><span class="required">&nbsp;*</span></label>
</div>
<div class="sax-control">
@Html.TextAreaFor(model => model.EventSummary, new { @id = "ifEventSummary", @class = "EventSummary sax-textarea", @rows = 3, @maxlength = @Model.GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.OrganisationEvent_Summary) })
@Html.TextAreaFor(model => model.EventSummary, new
{
@id = "ifEventSummary",
@class = "EventSummary sax-textarea",
@rows = 3,
@maxlength = @Model.GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.OrganisationEvent_Summary)
})
</div>
<div class="sax-message"></div>
</div>
@@ -86,6 +86,8 @@
/* Contact image */
.sax-profile .sax-contact-image.AccountContact
{
min-width: 48px;
min-height: 48px;
max-width: 160px;
max-height: 160px;
margin: 0 8px;
+78 -21
View File
@@ -62,7 +62,7 @@
.sax-panel-filter > .sax-content .sax-label
{
padding: 2px 12px 2px 0;
padding: 6px 12px 2px 0;
text-align: right;
}
@@ -98,20 +98,20 @@
background-color: #e0e0e0;
}
/* Panel header - Burger */
/* Nav - Burger menu */
.sax-header ul.nav.sax-burger
ul.nav.sax-burger
{
margin: 0;
}
.sax-header ul.nav.sax-burger ul.sax-dropdown-menu
ul.nav.sax-burger ul.sax-dropdown-menu
{
padding: 4px 8px 4px 4px;
box-shadow: 0 0 8px 2px #80808080;
}
.sax-header ul.nav.sax-burger ul.sax-dropdown-menu li.sax-action.sax-dropdown-item
ul.nav.sax-burger ul.sax-dropdown-menu li.sax-action.sax-dropdown-item
{
margin: 2px 4px 2px 0;
padding: 2px 4px 2px 30px;
@@ -119,84 +119,89 @@
background-position: left center;
}
.sax-header ul.nav.sax-burger ul.sax-dropdown-menu li.sax-action.sax-dropdown-item.sax-refresh
ul.nav.sax-burger ul.sax-dropdown-menu li.sax-action.sax-dropdown-item.sax-refresh
{
background-image: url('../img/action/refresh24.png');
}
.sax-header ul.nav.sax-burger ul.sax-dropdown-menu li.sax-action.sax-dropdown-item.sax-info
ul.nav.sax-burger ul.sax-dropdown-menu li.sax-action.sax-dropdown-item.sax-info
{
background-image: url('../img/action/info24.png');
}
.sax-header ul.nav.sax-burger ul.sax-dropdown-menu li.sax-action.sax-dropdown-item.sax-add
ul.nav.sax-burger ul.sax-dropdown-menu li.sax-action.sax-dropdown-item.sax-add
{
background-image: url('../img/action/add24.png');
}
.sax-header ul.nav.sax-burger ul.sax-dropdown-menu li.sax-action.sax-dropdown-item.sax-edit
ul.nav.sax-burger ul.sax-dropdown-menu li.sax-action.sax-dropdown-item.sax-edit
{
background-image: url('../img/action/edit24.png');
}
.sax-header ul.nav.sax-burger ul.sax-dropdown-menu li.sax-action.sax-dropdown-item.sax-remove
ul.nav.sax-burger ul.sax-dropdown-menu li.sax-action.sax-dropdown-item.sax-copy
{
background-image: url('../img/action/copy24.png');
}
ul.nav.sax-burger ul.sax-dropdown-menu li.sax-action.sax-dropdown-item.sax-remove
{
background-image: url('../img/action/delete24.png');
}
.sax-header ul.nav.sax-burger ul.sax-dropdown-menu li.sax-action.sax-dropdown-item.sax-experience
ul.nav.sax-burger ul.sax-dropdown-menu li.sax-action.sax-dropdown-item.sax-experience
{
background-image: url('../img/action/trophy24.png');
}
.sax-header ul.nav.sax-burger ul.sax-dropdown-menu li.sax-action.sax-dropdown-item.sax-user
ul.nav.sax-burger ul.sax-dropdown-menu li.sax-action.sax-dropdown-item.sax-user
{
background-image: url('../img/action/user24.png');
}
.sax-header ul.nav.sax-burger ul.sax-dropdown-menu li.sax-action.sax-dropdown-item.sax-users
ul.nav.sax-burger ul.sax-dropdown-menu li.sax-action.sax-dropdown-item.sax-users
{
background-image: url('../img/action/users24.png');
}
.sax-header ul.nav.sax-burger ul.sax-dropdown-menu li.sax-action.sax-dropdown-item.sax-mail
ul.nav.sax-burger ul.sax-dropdown-menu li.sax-action.sax-dropdown-item.sax-mail
{
background-image: url('../img/action/mail24.png');
}
.sax-header ul.nav.sax-burger ul.sax-dropdown-menu li.sax-action.sax-dropdown-item.sax-location
ul.nav.sax-burger ul.sax-dropdown-menu li.sax-action.sax-dropdown-item.sax-location
{
background-image: url('../img/action/location-24.png');
}
.sax-header ul.nav.sax-burger ul.sax-dropdown-menu li.sax-action.sax-dropdown-item.sax-image
ul.nav.sax-burger ul.sax-dropdown-menu li.sax-action.sax-dropdown-item.sax-image
{
background-image: url('../img/action/image-24.png');
}
.sax-header ul.nav.sax-burger ul.sax-dropdown-menu li.sax-action.sax-dropdown-item.sax-process
ul.nav.sax-burger ul.sax-dropdown-menu li.sax-action.sax-dropdown-item.sax-process
{
background-image: url('../img/action/process24.png');
}
.sax-header ul.nav.sax-burger ul.sax-dropdown-menu li.sax-action.sax-dropdown-item.sax-close
ul.nav.sax-burger ul.sax-dropdown-menu li.sax-action.sax-dropdown-item.sax-close
{
background-image: url('../img/action/prev24.png');
}
.sax-header ul.nav.sax-burger ul.sax-dropdown-menu li.sax-action.sax-dropdown-item:hover
ul.nav.sax-burger ul.sax-dropdown-menu li.sax-action.sax-dropdown-item:hover
{
background-color: #f8f8f8;
box-shadow: none;
}
.sax-header ul.nav.sax-burger ul.sax-dropdown-menu li.sax-action.sax-dropdown-item .sax-label
ul.nav.sax-burger ul.sax-dropdown-menu li.sax-action.sax-dropdown-item .sax-label
{
margin: 0;
padding: 0 0 0 4px;
}
.sax-header ul.nav.sax-burger ul.sax-dropdown-menu li.sax-action.sax-dropdown-item:hover .sax-label
ul.nav.sax-burger ul.sax-dropdown-menu li.sax-action.sax-dropdown-item:hover .sax-label
{
background-color: #f8f8f8;
box-shadow: 0 0 2px 1px #80808080;
@@ -251,6 +256,58 @@
background-image: url("../img/icon/error-18.png");
}
/* Item List table */
.sax-item-list-table-prefix, .sax-item-list-table-suffix
{
width: 100%;
height: 12px;
}
table.sax-item-list
{
width: 100%;
border-spacing: 0;
border-collapse: separate;
overflow: auto;
}
table.sax-item-list thead tr
{
}
table.sax-item-list thead th
{
position: sticky;
top: 0;
padding: 4px 2px 2px 2px;
z-index: 1;
background-color: #f8f8f8;
border-bottom:1px solid #d0d0d0;
}
table.sax-item-list tbody th
{
position: sticky;
left: 0;
background-color: #f8f8f8;
}
table.sax-item-list tbody tr:hover
{
background-color: lightyellow;
}
table.sax-item-list tbody tr.sax-sel
{
background-color: palegreen;
}
table.sax-item-list tbody td
{
padding: 0 2px;
}
/* Item */
.sax-panel-item-template
@@ -136,7 +136,7 @@
.sax-form .sax-form-control .sax-caption,
.sax-form .sax-form-control .sax-label
{
margin: 0 0 4px 0;
margin: 4px 0 2px 0;
font-size: 1rem;
line-height: 1.25;
}
@@ -195,9 +195,9 @@
.sax-form .sax-input:read-only, .sax-form .sax-textarea:read-only, .sax-form .sax-select:disabled
{
color: #202020;
color: #404040;
opacity: 1;
background-color: #f8f8f8;
background-color: #f0f0f0;
}
.sax-form .sax-form-control.sax-error .sax-input, .sax-form .sax-form-control.sax-error .sax-textarea, .sax-form .sax-form-control.sax-error .sax-select
@@ -0,0 +1,12 @@
/*
Organisation Events stylesheet.
*/
/* Item Burger */
.dropdown-menu.sax-dropdown-menu
{
left: -18px !important;
}
/* The End */
@@ -1,5 +1,5 @@
/*
Admin - Code Selection stylesheet.
Organisation selection stylesheet.
*/
/* Panels */
@@ -139,6 +139,22 @@
}
});
}
sax.initTimePickers = function (sel, opt)
{
if (window.jQuery().timepicker)
{
opt = opt || {};
opt.format = opt.format || 'H:i';
$(sel).timepicker(opt);
return;
}
if (window.jQuery().datetimepicker)
{
opt = opt || {};
opt.format = opt.format || 'HH:mm';
return $(sel).datetimepicker(opt);
}
}
sax.refreshPaging = function (response, context, refreshFn)
{
if (sax.mdl.resultsPaging.fn.refreshPaging)
+104 -29
View File
@@ -5,7 +5,7 @@
{
"use strict";
let oe = sax.OrgEvt = { data: {}, fn: {} };
let $pnl = oe.$pnl = {}, $frm = oe.$frm = {}, $dlg = oe.$dlg = {};
let $pnl = oe.$pnl = {}, $frm = oe.$frm = {}, $ctrl = oe.$ctrl = {}, $dlg = oe.$dlg = {};
//--------------------------------------------------------------
oe.refreshResults = function (delay)
{
@@ -13,8 +13,8 @@
if (!sax.awaitingRefreshResponse)
{
$('.sax-burger', $pnl.filter).hide();
$('.sax-panel-item-list', $pnl.results).fadeOut(200).empty();
$('.sax-panel-messages', $pnl.results).hide().empty().append($('<div class="sax-message">' + sax.msg.dataQuerying + '</div>')).fadeIn(200);
$('tbody tr', $pnl.table).remove();
$pnl.msgs.hide().empty();//.append($('<div class="sax-message">' + sax.msg.dataQuerying + '</div>')).fadeIn(200);
}
sax.ajax.refreshResults = sax.ajax.refreshResults || { url: sax.url.base + 'Organisation/Ajax/GetEventList', formId: 'frmEventFilter', callbackFn: oe.doRefreshResults };
sax.doAjaxRequest(sax.ajax.refreshResults, delay || 50);
@@ -25,13 +25,14 @@
//sax.debug('doRefreshResults', response);
delete sax.awaitingRefreshResponse;
sax.refreshControlValues(response.controlValues);
var $msgs = $('.sax-panel-messages', $pnl.results).hide().empty();
var $items = $('.sax-panel-item-list', $pnl.results).hide().empty();
$pnl.msgs.hide().empty();
$('tbody tr', $pnl.table).remove();
if (!response.success) return;
oe.data.organisation = response.organisation;
// Reference data - Event types.
if (response.eventTypes)
sax.populateSelectCodeDesc('#cbEventType', response.eventTypes);
oe.data.eventTypeDefault = response.eventTypeDefault;
// Menu.
let $bgr = $('.sax-burger', $pnl.filter);
let $mnu = $('ul.sax-dropdown-menu', $bgr).empty();
@@ -42,28 +43,28 @@
// Items.
var items = response.events;
if (!items.length)
return $msgs.append($('<div class="sax-message">' + sax.msg.dataNoneFound + '</div>')).fadeIn(500);
return $pnl.msgs.append($('<div class="sax-message">' + sax.msg.dataNoneFound + '</div>')).fadeIn(500);
for (let itemIdx = 0; itemIdx < items.length; itemIdx++)
$items.append(oe.populateItem(oe.getItemTemplate(), items[itemIdx]));
$items.fadeIn(50);
$pnl.table.append(oe.populateItem(oe.getItemRowTemplate(), items[itemIdx]));
}
oe.populateItem = function ($item, item)
{
if (!item) return;
$('.sax-panel-results .sax-panel-messages').hide().empty();
$('.EventType', $item).text(item.typeDesc);
$('.EventDate', $item).text(item.eventDateFmt);
$('.EventTime', $item).text(item.eventTimeFmt);
$('.EventAtDate', $item).text(item.eventAtDateFmt);
$('.EventAtTime', $item).text(item.eventAtTimeFmt || '');
$('.EventToDate', $item).text(item.eventToDateFmt || item.eventAtDateFmt);
$('.EventToTime', $item).text(item.eventToTimeFmt || '');
$('.EventSummary', $item).text(item.summary);
$('.EventDetails', $item).text(item.details);
$('.EventDetails', $item).text(item.details || '');
$('.EventSportCaption', $item).text(item.sportCaptionPrimary);
$('.EventRegionCaption', $item).text(item.regionCaptionCountry);
$('.EventCreatedOn', $item).text(item.createdOnFmt);
$('.EventPublishedOn', $item).text(item.publishedOnFmt);
$('.EventPublishedOn', $item).text(item.publishedOnFmt || '');
$('.EventPublished', $item).toggle(!!item.publishedOnFmt);
$('.EventExpiresOn', $item).text(item.expiresOnFmt);
$('.EventExpiresOn', $item).text(item.expiresOnFmt || '');
$('.EventExpires', $item).toggle(!!item.expiresOnFmt);
$('.EventStatusDesc', $item).text(item.statusDesc).addClass('sax-status-' + item.statusCode.toLowerCase());
$('.EventStatusDesc', $item).text(item.statusDesc).removeClass(function (idx, name) { return (name.match(/(^|\s)sax-status-\S+/g) || []).join(' '); }).addClass('sax-status-' + item.statusCode.toLowerCase());
let $bgr = $('.sax-burger', $item);
let $mnu = $('ul.sax-dropdown-menu', $bgr).empty();
@@ -72,8 +73,10 @@
if (sax.data.userCanManageEvents)
{
let fnUpd = function () { oe.updateItem(item, $item) };
let fnCopy = function () { oe.copyItem(item, $item) };
$mnu.append(oe.getItemMenuOption(sax.lbl.edit, fnUpd, 'sax-edit'));
$('.sax-caption .sax-action', $item).off('click').on('click', fnUpd);
$mnu.append(oe.getItemMenuOption(sax.lbl.copy, fnCopy, 'sax-copy'));
$('td div.EventSummary,.sax-caption .sax-action', $item).off('click').on('click', fnUpd);
$item.off('dblclick').on('dblclick', fnUpd);
}
}
@@ -86,9 +89,9 @@
{
return $('.sax-panel-item-template .sax-dropdown-menu.Events li.sax-dropdown-item', sax.$pnl.filter).clone();
}
oe.getItemTemplate = function ()
oe.getItemRowTemplate = function ()
{
return $('.sax-panel-item-template .sax-panel-item.Event', sax.$pnl.results).clone();
return $('.sax-panel-item-template table tr.sax-row-item.Event', sax.$pnl.results).clone();
}
oe.getItemDropdownTemplate = function ()
{
@@ -162,7 +165,7 @@
{
if (!sax.data.userCanManageEvents) return;
oe.clearItem();
$('#cbEventType', $frm.evt).prepend($("<option>", { value: '', selected: true }));
$('#cbEventType', $frm.evt).prepend($("<option>", { value: '' })).val(oe.data.eventTypeDefault || '');
$('#ifEventSportIdPrimary', $frm.evt).val(oe.data.organisation.sportId);
$('#ifEventSportCaptionPrimary', $frm.evt).val(oe.data.organisation.sportName);
$('#ifEventRegionIdCountry', $frm.evt).val(oe.data.organisation.regionId);
@@ -175,7 +178,9 @@
delete oe.$item;
$('#ifEventId,#ifEventExists,#ifEventSportIdPrimary,#ifEventRegionIdCountry,input[type="text"],textarea,select', $frm.evt).val('');
$('#cbEventType', $frm.evt).find('option[value=""]').remove();
$('.EventDate', $frm.evt).datepicker('setDate', 'today');
$('.EventAtDate,.EventToDate', $frm.evt).datepicker('setDate', 'today');
$('.sax-checkbox').prop('checked', false);
$('input[type="time"]', $frm.evt).val('12:00').prop('readonly', true);
sax.clearControlErrors();
}
//--------------------------------------------------------------
@@ -195,8 +200,29 @@
let item = response.event;
$('#ifEventId', $frm.evt).val(item.id);
$('#ifEventExists', $frm.evt).val(1);
oe.populateItemForm(item);
$dlg.event.dialog('option', 'title', sax.dlg.title.updateEvent);
sax.openDialog($dlg.event, 600, 600);
}
oe.populateItemForm = function (item)
{
$('#cbEventType', $frm.evt).val(item.typeCode);
$('#ifEventDate', $frm.evt).val(item.eventOn_Calendar);
$ctrl.atDate.val(item.eventAt_Calendar);
if (!!item.eventAt_HHMM)
{
$ctrl.atTimeSet.prop('checked', true);
$ctrl.atTime.val(item.eventAt_HHMM).prop('readonly', false);
}
$ctrl.toDateSet.prop('checked', !!item.eventTo_Calendar);
$ctrl.toDate.val(item.eventTo_Calendar);
if (!!item.eventTo_HHMM)
{
$ctrl.toTimeSet.prop('checked', true);
$ctrl.toTime.val(item.eventTo_HHMM).prop('readonly', false);
}
oe.onAtTimeSetChange();
oe.onToDateSetChange();
oe.onToTimeSetChange();
$('#ifEventSummary', $frm.evt).val(item.summary);
$('#ifEventDetails', $frm.evt).val(item.details);
$('#ifEventSportIdPrimary', $frm.evt).val(item.sportIdPrimary);
@@ -205,10 +231,48 @@
$('#ifEventRegionCaptionCountry', $frm.evt).val(item.regionCaptionCountry);
$('#cbEventStatusCode', $frm.evt).val(item.statusCode);
sax.clearControlErrors();
$dlg.event.dialog('option', 'title', sax.dlg.title.updateEvent);
}
//--------------------------------------------------------------
oe.copyItem = function (item, $item)
{
if (!sax.data.userCanManageEvents) return;
oe.clearItem();
delete oe.$item;
$('.EventId', $frm.evtId).val(item.id);
sax.ajax.copyItem = sax.ajax.copyItem || { url: sax.url.base + 'Organisation/Ajax/GetEvent', formId: 'frmEventId', callbackFn: oe.onCopyItem };
sax.doAjaxRequest(sax.ajax.copyItem, 50);
}
oe.onCopyItem = function (response)
{
//sax.debug('onCopyItem', response);
if (!response.success) return;
oe.populateItemForm(response.event);
$dlg.event.dialog('option', 'title', sax.dlg.title.createEvent);
sax.openDialog($dlg.event, 600, 600);
}
//--------------------------------------------------------------
oe.onAtTimeSetChange = function ()
{
let atTimeSet = !!$ctrl.atTimeSet.prop('checked');
$ctrl.atTime.prop('readonly', !atTimeSet);
if (!atTimeSet) $ctrl.toTimeSet.prop('checked', false).prop('readonly', true).trigger('change');
else $ctrl.toTimeSet.prop('readonly', false);
}
oe.onToDateSetChange = function ()
{
let toDateSet = !!$ctrl.toDateSet.prop('checked');
$ctrl.toDate.datepicker('option', 'disabled', !toDateSet);
if (toDateSet && !$ctrl.toDate.val())
$ctrl.toDate.val($ctrl.atDate.val());
}
oe.onToTimeSetChange = function ()
{
if (!!$ctrl.toTimeSet.prop('readonly'))
$ctrl.toTimeSet.prop('checked', false);
let toTimeSet = !!$ctrl.toTimeSet.prop('checked');
$ctrl.toTime.prop('readonly', !toTimeSet);
}
//--------------------------------------------------------------
oe.storeItem = function ()
{
sax.ajax.storeItem = sax.ajax.storeItem || { url: sax.url.base + 'Organisation/Ajax/StoreEvent', formId: 'frmEvent', callbackFn: oe.onStoreItem };
@@ -224,8 +288,8 @@
var item = response.event;
if (!oe.$item || oe.$item.length != 1)
{
oe.$item = $('.sax-panel-item-template .sax-panel-item', $pnl.results).clone();
$('.sax-panel-item-list', $pnl.results).prepend(oe.$item).show();
oe.$item = oe.getItemRowTemplate();
$('tbody', $pnl.table).prepend(oe.$item);
}
oe.populateItem(oe.$item, item)
}
@@ -235,24 +299,35 @@
$pnl.events = $('.sax-panel.Events');
$pnl.filter = $('.sax-panel-filter', $pnl.events);
$pnl.results = $('.sax-panel-results', $pnl.events);
$pnl.msgs = $('.sax-panel-messages', $pnl.results);
$pnl.table = $('.sax-item-list', $pnl.results);
$frm.filter = $('#frmEventFilter', $pnl.events);
$frm.filter.on('change', '.FilterPeriodType', function () { oe.refreshResults(250); });
$('.EventFilter', $frm.filter).on('input', function () { oe.refreshResults(250); }).on('keypress', function (event)
{
if (event.keyCode == 13) setTimeout(oe.refreshResults, 50);
});
$frm.filter.on('dblclick', 'input.FilterOrganisation', oe.selectFilterOrganisation).on('click', 'button.SelectFilterOrganisation', oe.selectFilterOrganisation);
$frm.evtId = $('#frmEventId');
$frm.evt = $('#frmEvent');
$('.sax-input', $frm.evt).on('input', function () { sax.clearControlError(this); });
sax.initCalendars('#frmEvent .sax-input.sax-calendar', { maxDate: '+700' });
$frm.evt.on('dblclick', 'input.EventSportCaptionPrimary', oe.selectSportPrimary).on('click', 'button.SelectEventSportPrimary', oe.selectSportPrimary);
$frm.evt.on('dblclick', 'input.EventRegionCaptionCountry', oe.selectRegionCountry).on('click', 'button.SelectEventRegionCountry', oe.selectRegionCountry);
var opt = sax.dlgOpts();
opt.buttons[sax.dlg.btn.ok] = function () { oe.storeItem(); };
opt.buttons[sax.dlg.btn.cancel] = function () { $(this).dialog('close'); };
$dlg.event = $('#dlgEvent').dialog(opt);
$frm.evt = $('#frmEvent');
$('.sax-input', $frm.evt).on('input', function () { sax.clearControlError(this); });
sax.initCalendars('#frmEvent .sax-input.sax-calendar', { maxDate: '+700' });
$ctrl.atDate = $('#ifEventAtDate', $frm.evt);
$ctrl.atTimeSet = $('.sax-checkbox#chkEventAtTimeSet', $frm.evt).on('change', oe.onAtTimeSetChange);
$ctrl.atTime = $('#ifEventAtTime', $frm.evt);
$ctrl.toDateSet = $('.sax-checkbox#chkEventToDateSet', $frm.evt).on('change', oe.onToDateSetChange);
$ctrl.toDate = $('#ifEventToDate', $frm.evt);
$ctrl.toTimeSet = $('.sax-checkbox#chkEventToTimeSet', $frm.evt).on('change', oe.onToTimeSetChange);
$ctrl.toTime = $('#ifEventToTime', $frm.evt);
$frm.evt.on('dblclick', 'input.EventSportCaptionPrimary', oe.selectSportPrimary).on('click', 'button.SelectEventSportPrimary', oe.selectSportPrimary);
$frm.evt.on('dblclick', 'input.EventRegionCaptionCountry', oe.selectRegionCountry).on('click', 'button.SelectEventRegionCountry', oe.selectRegionCountry);
setTimeout(oe.refreshResults, 250);
});
//--------------------------------------------------------------
@@ -54,7 +54,7 @@
$('.MemberDisplayName', $item).text(item.displayName);
$('.MemberRoles', $item).text(item.memberRoles);
$('.MemberAdminComment', $item).text(item.adminComment);
$('.MemberStatus', $item).text(item.statusDesc).addClass('sax-status-' + item.statusCode.toLowerCase());
$('.MemberStatus', $item).text(item.statusDesc).removeClass(function (idx, name) { return (name.match(/(^|\s)sax-status-\S+/g) || []).join(' '); }).addClass('sax-status-' + item.statusCode.toLowerCase());
let $bgr = $('.sax-burger', $item);
let $mnu = $('ul.sax-dropdown-menu', $bgr).empty();
if (sax.data.userCanManageMembers)
@@ -61,7 +61,7 @@
$('.OpportunityPublished', $item).toggle(!!item.publishedOnFmt);
$('.OpportunityExpiresOn', $item).text(item.expiresOnFmt);
$('.OpportunityExpires', $item).toggle(!!item.expiresOnFmt);
$('.OpportunityStatusDesc', $item).text(item.statusDesc).addClass('sax-status-' + item.statusCode.toLowerCase());
$('.OpportunityStatusDesc', $item).text(item.statusDesc).removeClass(function (idx, name) { return (name.match(/(^|\s)sax-status-\S+/g) || []).join(' '); }).addClass('sax-status-' + item.statusCode.toLowerCase());
let $bgr = $('.sax-burger', $item);
let $mnu = $('ul.sax-dropdown-menu', $bgr).empty();
@@ -0,0 +1,262 @@
.sr-only, .bootstrap-datetimepicker-widget .btn[data-action="incrementHours"]::after, .bootstrap-datetimepicker-widget .btn[data-action="incrementMinutes"]::after, .bootstrap-datetimepicker-widget .btn[data-action="decrementHours"]::after, .bootstrap-datetimepicker-widget .btn[data-action="decrementMinutes"]::after, .bootstrap-datetimepicker-widget .btn[data-action="showHours"]::after, .bootstrap-datetimepicker-widget .btn[data-action="showMinutes"]::after, .bootstrap-datetimepicker-widget .btn[data-action="togglePeriod"]::after, .bootstrap-datetimepicker-widget .btn[data-action="clear"]::after, .bootstrap-datetimepicker-widget .btn[data-action="today"]::after, .bootstrap-datetimepicker-widget .picker-switch::after, .bootstrap-datetimepicker-widget table th.prev::after, .bootstrap-datetimepicker-widget table th.next::after {
position: absolute;
width: 1px;
height: 1px;
margin: -1px;
padding: 0;
overflow: hidden;
clip: rect(0, 0, 0, 0);
border: 0;
}
/*!
* Datetimepicker for Bootstrap 3
* ! version : 4.7.14
* https://github.com/Eonasdan/bootstrap-datetimepicker/
*/
.bootstrap-datetimepicker-widget {
list-style: none;
}
.bootstrap-datetimepicker-widget.dropdown-menu {
margin: 2px 0;
padding: 4px;
width: 19em;
}
@media (min-width: 540px) {
.bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs {
width: 38em;
}
}
@media (min-width: 720px) {
.bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs {
width: 38em;
}
}
@media (min-width: 960px) {
.bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs {
width: 38em;
}
}
.bootstrap-datetimepicker-widget.dropdown-menu:before, .bootstrap-datetimepicker-widget.dropdown-menu:after {
content: '';
display: inline-block;
position: absolute;
}
.bootstrap-datetimepicker-widget.dropdown-menu.bottom:before {
border-left: 7px solid transparent;
border-right: 7px solid transparent;
border-bottom: 7px solid #ccc;
border-bottom-color: rgba(0, 0, 0, 0.2);
top: -7px;
left: 7px;
}
.bootstrap-datetimepicker-widget.dropdown-menu.bottom:after {
border-left: 6px solid transparent;
border-right: 6px solid transparent;
border-bottom: 6px solid white;
top: -6px;
left: 8px;
}
.bootstrap-datetimepicker-widget.dropdown-menu.top:before {
border-left: 7px solid transparent;
border-right: 7px solid transparent;
border-top: 7px solid #ccc;
border-top-color: rgba(0, 0, 0, 0.2);
bottom: -7px;
left: 6px;
}
.bootstrap-datetimepicker-widget.dropdown-menu.top:after {
border-left: 6px solid transparent;
border-right: 6px solid transparent;
border-top: 6px solid white;
bottom: -6px;
left: 7px;
}
.bootstrap-datetimepicker-widget.dropdown-menu.pull-right:before {
left: auto;
right: 6px;
}
.bootstrap-datetimepicker-widget.dropdown-menu.pull-right:after {
left: auto;
right: 7px;
}
.bootstrap-datetimepicker-widget .list-unstyled {
margin: 0;
}
.bootstrap-datetimepicker-widget a[data-action] {
padding: 6px 0;
}
.bootstrap-datetimepicker-widget a[data-action]:active {
box-shadow: none;
}
.bootstrap-datetimepicker-widget .timepicker-hour, .bootstrap-datetimepicker-widget .timepicker-minute, .bootstrap-datetimepicker-widget .timepicker-second {
width: 54px;
font-weight: bold;
font-size: 1.2em;
margin: 0;
}
.bootstrap-datetimepicker-widget button[data-action] {
padding: 6px;
}
.bootstrap-datetimepicker-widget .btn[data-action="incrementHours"]::after {
content: "Increment Hours";
}
.bootstrap-datetimepicker-widget .btn[data-action="incrementMinutes"]::after {
content: "Increment Minutes";
}
.bootstrap-datetimepicker-widget .btn[data-action="decrementHours"]::after {
content: "Decrement Hours";
}
.bootstrap-datetimepicker-widget .btn[data-action="decrementMinutes"]::after {
content: "Decrement Minutes";
}
.bootstrap-datetimepicker-widget .btn[data-action="showHours"]::after {
content: "Show Hours";
}
.bootstrap-datetimepicker-widget .btn[data-action="showMinutes"]::after {
content: "Show Minutes";
}
.bootstrap-datetimepicker-widget .btn[data-action="togglePeriod"]::after {
content: "Toggle AM/PM";
}
.bootstrap-datetimepicker-widget .btn[data-action="clear"]::after {
content: "Clear the picker";
}
.bootstrap-datetimepicker-widget .btn[data-action="today"]::after {
content: "Set the date to today";
}
.bootstrap-datetimepicker-widget .picker-switch {
text-align: center;
}
.bootstrap-datetimepicker-widget .picker-switch::after {
content: "Toggle Date and Time Screens";
}
.bootstrap-datetimepicker-widget .picker-switch td {
padding: 0;
margin: 0;
height: auto;
width: auto;
line-height: inherit;
}
.bootstrap-datetimepicker-widget .picker-switch td span {
line-height: 2.5;
height: 2.5em;
width: 100%;
}
.bootstrap-datetimepicker-widget table {
width: 100%;
margin: 0;
}
.bootstrap-datetimepicker-widget table td, .bootstrap-datetimepicker-widget table th {
text-align: center;
border-radius: 0.25rem;
}
.bootstrap-datetimepicker-widget table th {
height: 20px;
line-height: 20px;
width: 20px;
}
.bootstrap-datetimepicker-widget table th.picker-switch {
width: 145px;
}
.bootstrap-datetimepicker-widget table th.disabled, .bootstrap-datetimepicker-widget table th.disabled:hover {
background: none;
color: #636c72;
cursor: not-allowed;
}
.bootstrap-datetimepicker-widget table th.prev::after {
content: "Previous Month";
}
.bootstrap-datetimepicker-widget table th.next::after {
content: "Next Month";
}
.bootstrap-datetimepicker-widget table thead tr:first-child th {
cursor: pointer;
}
.bootstrap-datetimepicker-widget table thead tr:first-child th:hover {
background: #eceeef;
}
.bootstrap-datetimepicker-widget table td {
height: 54px;
line-height: 54px;
width: 54px;
}
.bootstrap-datetimepicker-widget table td.cw {
font-size: .8em;
height: 20px;
line-height: 20px;
color: #636c72;
}
.bootstrap-datetimepicker-widget table td.day {
height: 20px;
line-height: 20px;
width: 20px;
padding: 5px;
}
.bootstrap-datetimepicker-widget table td.day:hover, .bootstrap-datetimepicker-widget table td.hour:hover, .bootstrap-datetimepicker-widget table td.minute:hover, .bootstrap-datetimepicker-widget table td.second:hover {
background: #eceeef;
cursor: pointer;
}
.bootstrap-datetimepicker-widget table td.old, .bootstrap-datetimepicker-widget table td.new {
color: #636c72;
}
.bootstrap-datetimepicker-widget table td.today {
position: relative;
}
.bootstrap-datetimepicker-widget table td.today:before {
content: '';
display: inline-block;
border: solid transparent;
border-width: 0 0 7px 7px;
border-bottom-color: #0275d8;
border-top-color: rgba(0, 0, 0, 0.2);
position: absolute;
bottom: 4px;
right: 4px;
}
.bootstrap-datetimepicker-widget table td.active, .bootstrap-datetimepicker-widget table td.active:hover {
background-color: #0275d8;
color: #fff;
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
}
.bootstrap-datetimepicker-widget table td.active.today:before {
border-bottom-color: #fff;
}
.bootstrap-datetimepicker-widget table td.disabled, .bootstrap-datetimepicker-widget table td.disabled:hover {
background: none;
color: #636c72;
cursor: not-allowed;
}
.bootstrap-datetimepicker-widget table td span {
display: inline-block;
width: 54px;
height: 54px;
line-height: 54px;
margin: 2px 1.5px;
cursor: pointer;
border-radius: 0.25rem;
}
.bootstrap-datetimepicker-widget table td span:hover {
background: #eceeef;
}
.bootstrap-datetimepicker-widget table td span.active {
background-color: #0275d8;
color: #fff;
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
}
.bootstrap-datetimepicker-widget table td span.old {
color: #636c72;
}
.bootstrap-datetimepicker-widget table td span.disabled, .bootstrap-datetimepicker-widget table td span.disabled:hover {
background: none;
color: #636c72;
cursor: not-allowed;
}
.bootstrap-datetimepicker-widget.usetwentyfour td.hour {
height: 27px;
line-height: 27px;
}
.input-group.date .input-group-addon {
cursor: pointer;
}
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,67 @@
.ui-timepicker-wrapper {
overflow-y: auto;
max-height: 150px;
width: auto;
background: #fff;
border: 1px solid #ddd;
-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);
-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);
box-shadow:0 5px 10px rgba(0,0,0,0.2);
outline: none;
z-index: 10052;
margin: 0;
}
.ui-timepicker-wrapper .ui-timepicker-list li {
padding-right: 20px;
}
.ui-timepicker-list {
margin: 0;
padding: 0;
list-style: none;
}
.ui-timepicker-duration {
margin-left: 5px; color: #888;
}
.ui-timepicker-list:hover .ui-timepicker-duration {
color: #888;
}
.ui-timepicker-list li {
padding: 3px 0 3px 5px;
cursor: pointer;
white-space: nowrap;
color: #000;
list-style: none;
margin: 0;
}
.ui-timepicker-list:hover .ui-timepicker-selected {
background: #fff; color: #000;
}
li.ui-timepicker-selected,
.ui-timepicker-list li:hover,
.ui-timepicker-list .ui-timepicker-selected:hover {
background: #1980EC; color: #fff;
}
li.ui-timepicker-selected .ui-timepicker-duration,
.ui-timepicker-list li:hover .ui-timepicker-duration {
color: #ccc;
}
.ui-timepicker-list li.ui-timepicker-disabled,
.ui-timepicker-list li.ui-timepicker-disabled:hover,
.ui-timepicker-list li.ui-timepicker-selected.ui-timepicker-disabled {
color: #888;
cursor: default;
}
.ui-timepicker-list li.ui-timepicker-disabled:hover,
.ui-timepicker-list li.ui-timepicker-selected.ui-timepicker-disabled {
background: #f2f2f2;
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,67 @@
.ui-timepicker-wrapper {
overflow-y: auto;
max-height: 150px;
width: auto;
background: #fff;
border: 1px solid #ddd;
-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);
-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);
box-shadow:0 5px 10px rgba(0,0,0,0.2);
outline: none;
z-index: 10052;
margin: 0;
}
.ui-timepicker-wrapper .ui-timepicker-list li {
padding-right: 20px;
}
.ui-timepicker-list {
margin: 0;
padding: 0;
list-style: none;
}
.ui-timepicker-duration {
margin-left: 5px; color: #888;
}
.ui-timepicker-list:hover .ui-timepicker-duration {
color: #888;
}
.ui-timepicker-list li {
padding: 3px 0 3px 5px;
cursor: pointer;
white-space: nowrap;
color: #000;
list-style: none;
margin: 0;
}
.ui-timepicker-list:hover .ui-timepicker-selected {
background: #fff; color: #000;
}
li.ui-timepicker-selected,
.ui-timepicker-list li:hover,
.ui-timepicker-list .ui-timepicker-selected:hover {
background: #1980EC; color: #fff;
}
li.ui-timepicker-selected .ui-timepicker-duration,
.ui-timepicker-list li:hover .ui-timepicker-duration {
color: #ccc;
}
.ui-timepicker-list li.ui-timepicker-disabled,
.ui-timepicker-list li.ui-timepicker-disabled:hover,
.ui-timepicker-list li.ui-timepicker-selected.ui-timepicker-disabled {
color: #888;
cursor: default;
}
.ui-timepicker-list li.ui-timepicker-disabled:hover,
.ui-timepicker-list li.ui-timepicker-selected.ui-timepicker-disabled {
background: #f2f2f2;
}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long