Start Date and Expiry Date for Module instances and Pages #3538

This is complete excluding Reporting and Notifications which can be added at a later date.  I just really wanted to get the schema and the functionality into place.
This commit is contained in:
Leigh Pointer 2023-12-31 12:21:38 +01:00
parent b0a079dce9
commit 233f40f3e9
16 changed files with 571 additions and 182 deletions

View File

@ -48,6 +48,18 @@
</select> </select>
</div> </div>
</div> </div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="effectiveDate" HelpText="The date that this module is active" ResourceKey="EffectiveDate">Effective Date: </Label>
<div class="col-sm-9">
<input type="date" id="effectiveDate" class="form-control" @bind="@_effectivedate" />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="expiryDate" HelpText="The date that this module expires" ResourceKey="ExpiryDate">Expiry Date: </Label>
<div class="col-sm-9">
<input type="date" id="expiryDate" class="form-control" @bind="@_expirydate" />
</div>
</div>
<div class="row mb-1 align-items-center"> <div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="allpages" HelpText="Indicate if this module should be displayed on all pages" ResourceKey="DisplayOnAllPages">Display On All Pages? </Label> <Label Class="col-sm-3" For="allpages" HelpText="Indicate if this module should be displayed on all pages" ResourceKey="DisplayOnAllPages">Display On All Pages? </Label>
<div class="col-sm-9"> <div class="col-sm-9">
@ -114,7 +126,7 @@
<AuditInfo CreatedBy="@createdby" CreatedOn="@createdon" ModifiedBy="@modifiedby" ModifiedOn="@modifiedon"></AuditInfo> <AuditInfo CreatedBy="@createdby" CreatedOn="@createdon" ModifiedBy="@modifiedby" ModifiedOn="@modifiedon"></AuditInfo>
</form> </form>
@code { @code {
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit; public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
public override string Title => "Module Settings"; public override string Title => "Module Settings";
@ -141,7 +153,8 @@
private DateTime createdon; private DateTime createdon;
private string modifiedby; private string modifiedby;
private DateTime modifiedon; private DateTime modifiedon;
private DateTime? _effectivedate = null;
private DateTime? _expirydate = null;
protected override void OnInitialized() protected override void OnInitialized()
{ {
_module = ModuleState.ModuleDefinition.Name; _module = ModuleState.ModuleDefinition.Name;
@ -156,6 +169,8 @@
createdon = ModuleState.CreatedOn; createdon = ModuleState.CreatedOn;
modifiedby = ModuleState.ModifiedBy; modifiedby = ModuleState.ModifiedBy;
modifiedon = ModuleState.ModifiedOn; modifiedon = ModuleState.ModifiedOn;
_effectivedate = ModuleState.EffectiveDate;
_expirydate = ModuleState.ExpiryDate;
if (ModuleState.ModuleDefinition != null) if (ModuleState.ModuleDefinition != null)
{ {
@ -214,12 +229,20 @@
var interop = new Interop(JSRuntime); var interop = new Interop(JSRuntime);
if (await interop.FormValid(form)) if (await interop.FormValid(form))
{ {
if (!string.IsNullOrEmpty(_title)) if (!string.IsNullOrEmpty(_title))
{ {
if (!ValidateEffectiveExpiryDates(_effectivedate, _expirydate))
{
AddModuleMessage(SharedLocalizer["Message.EffectiveExpiryDateError"], MessageType.Warning);
return;
}
var pagemodule = await PageModuleService.GetPageModuleAsync(ModuleState.PageModuleId); var pagemodule = await PageModuleService.GetPageModuleAsync(ModuleState.PageModuleId);
pagemodule.PageId = int.Parse(_pageId); pagemodule.PageId = int.Parse(_pageId);
pagemodule.Title = _title; pagemodule.Title = _title;
pagemodule.Pane = _pane; pagemodule.Pane = _pane;
pagemodule.EffectiveDate = _effectivedate;
pagemodule.ExpiryDate = _expirydate;
pagemodule.ContainerType = (_containerType != "-") ? _containerType : string.Empty; pagemodule.ContainerType = (_containerType != "-") ? _containerType : string.Empty;
if (!string.IsNullOrEmpty(pagemodule.ContainerType) && pagemodule.ContainerType == PageState.Page.DefaultContainerType) if (!string.IsNullOrEmpty(pagemodule.ContainerType) && pagemodule.ContainerType == PageState.Page.DefaultContainerType)
{ {
@ -269,5 +292,33 @@
AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning); AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
} }
} }
private bool ValidateEffectiveExpiryDates(DateTime? effectiveDate, DateTime? expiryDate)
{
// Check if both dates are null, in which case the validation passes
if (effectiveDate == DateTime.MinValue && expiryDate == DateTime.MinValue)
{
return true;
}
// Check if EffectiveDate is not null and ExpiryDate is null
if (effectiveDate != DateTime.MinValue && expiryDate == DateTime.MinValue)
{
return true;
}
// Check if EffectiveDate is null and ExpiryDate is not null
if (effectiveDate == DateTime.MinValue && expiryDate != DateTime.MinValue)
{
return true;
}
// Check if ExpiryDate is not null and EffectiveDate is after ExpiryDate
if (expiryDate != DateTime.MinValue && effectiveDate != DateTime.MinValue && effectiveDate > expiryDate)
{
return false;
}
// If none of the above conditions are met, validation passes
return true;
}
} }

View File

@ -119,6 +119,18 @@
<i class="@_icon"></i> <i class="@_icon"></i>
</div> </div>
</div> </div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="effectiveDate" HelpText="The date that this page is active" ResourceKey="EffectiveDate">Effective Date: </Label>
<div class="col-sm-9">
<input type="date" id="effectiveDate" class="form-control" @bind="@_effectivedate" />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="expiryDate" HelpText="The date that this page expires" ResourceKey="ExpiryDate">Expiry Date: </Label>
<div class="col-sm-9">
<input type="date" id="expiryDate" class="form-control" @bind="@_expirydate" />
</div>
</div>
<div class="row mb-1 align-items-center"> <div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="personalizable" HelpText="Select whether you would like users to be able to personalize this page with their own content" ResourceKey="Personalizable">Personalizable? </Label> <Label Class="col-sm-3" For="personalizable" HelpText="Select whether you would like users to be able to personalize this page with their own content" ResourceKey="Personalizable">Personalizable? </Label>
<div class="col-sm-9"> <div class="col-sm-9">
@ -233,6 +245,8 @@
protected Page _parent = null; protected Page _parent = null;
protected Dictionary<string, string> _icons; protected Dictionary<string, string> _icons;
private string _iconresources = ""; private string _iconresources = "";
private DateTime? _effectivedate = null;
private DateTime? _expirydate = null;
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
@ -265,6 +279,8 @@
_children.Add(p); _children.Add(p);
} }
} }
_effectivedate = PageState.Page.EffectiveDate;
_expirydate = PageState.Page.ExpiryDate;
ThemeSettings(); ThemeSettings();
_initialized = true; _initialized = true;
} }
@ -347,6 +363,11 @@
Page page = null; Page page = null;
try try
{ {
if (!ValidateEffectiveExpiryDates(_effectivedate, _expirydate))
{
AddModuleMessage(SharedLocalizer["Message.EffectiveExpiryDateError"], MessageType.Warning);
return;
}
if (!string.IsNullOrEmpty(_themetype) && !string.IsNullOrEmpty(_containertype)) if (!string.IsNullOrEmpty(_themetype) && !string.IsNullOrEmpty(_containertype))
{ {
page = new Page(); page = new Page();
@ -421,6 +442,8 @@
page.IsClickable = (_isclickable == null ? true : Boolean.Parse(_isclickable)); page.IsClickable = (_isclickable == null ? true : Boolean.Parse(_isclickable));
page.Url = _url; page.Url = _url;
page.IsPersonalizable = (_ispersonalizable == null ? false : Boolean.Parse(_ispersonalizable)); page.IsPersonalizable = (_ispersonalizable == null ? false : Boolean.Parse(_ispersonalizable));
page.EffectiveDate = _effectivedate;
page.ExpiryDate = _expirydate;
page.UserId = null; page.UserId = null;
// appearance // appearance
@ -490,4 +513,33 @@
{ {
_icon = NewIcon; _icon = NewIcon;
} }
private bool ValidateEffectiveExpiryDates(DateTime? effectiveDate, DateTime? expiryDate)
{
// Check if both dates are null, in which case the validation passes
if (effectiveDate == DateTime.MinValue && expiryDate == DateTime.MinValue)
{
return true;
}
// Check if EffectiveDate is not null and ExpiryDate is null
if (effectiveDate != DateTime.MinValue && expiryDate == DateTime.MinValue)
{
return true;
}
// Check if EffectiveDate is null and ExpiryDate is not null
if (effectiveDate == DateTime.MinValue && expiryDate != DateTime.MinValue)
{
return true;
}
// Check if ExpiryDate is not null and EffectiveDate is after ExpiryDate
if (expiryDate != DateTime.MinValue && effectiveDate != DateTime.MinValue && effectiveDate > expiryDate)
{
return false;
}
// If none of the above conditions are met, validation passes
return true;
}
} }

View File

@ -134,6 +134,18 @@
<i class="@_icon"></i> <i class="@_icon"></i>
</div> </div>
</div> </div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="effectiveDate" HelpText="The date that this page is active" ResourceKey="EffectiveDate">Effective Date: </Label>
<div class="col-sm-9">
<input type="date" id="effectiveDate" class="form-control" @bind="@_effectivedate" />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="expiryDate" HelpText="The date that this page expires" ResourceKey="ExpiryDate">Expiry Date: </Label>
<div class="col-sm-9">
<input type="date" id="expiryDate" class="form-control" @bind="@_expirydate" />
</div>
</div>
<div class="row mb-1 align-items-center"> <div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="personalizable" HelpText="Select whether you would like users to be able to personalize this page with their own content" ResourceKey="Personalizable">Personalizable? </Label> <Label Class="col-sm-3" For="personalizable" HelpText="Select whether you would like users to be able to personalize this page with their own content" ResourceKey="Personalizable">Personalizable? </Label>
<div class="col-sm-9"> <div class="col-sm-9">
@ -322,6 +334,8 @@
protected Page _parent = null; protected Page _parent = null;
protected Dictionary<string, string> _icons; protected Dictionary<string, string> _icons;
private string _iconresources = ""; private string _iconresources = "";
private DateTime? _effectivedate = null;
private DateTime? _expirydate = null;
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
@ -370,6 +384,8 @@
} }
_url = _page.Url; _url = _page.Url;
_icon = _page.Icon; _icon = _page.Icon;
_effectivedate = _page.EffectiveDate;
_expirydate = _page.ExpiryDate;
_ispersonalizable = _page.IsPersonalizable.ToString(); _ispersonalizable = _page.IsPersonalizable.ToString();
// appearance // appearance
@ -487,6 +503,11 @@
{ {
try try
{ {
if (!ValidateEffectiveExpiryDates(_effectivedate, _expirydate))
{
AddModuleMessage(SharedLocalizer["Message.EffectiveExpiryDateError"], MessageType.Warning);
return;
}
if (!string.IsNullOrEmpty(_themetype) && _containertype != "-") if (!string.IsNullOrEmpty(_themetype) && _containertype != "-")
{ {
string currentPath = _page.Path; string currentPath = _page.Path;
@ -563,6 +584,8 @@
_page.IsClickable = (_isclickable == null ? true : Boolean.Parse(_isclickable)); _page.IsClickable = (_isclickable == null ? true : Boolean.Parse(_isclickable));
_page.Url = _url; _page.Url = _url;
_page.Icon = _icon ?? string.Empty; _page.Icon = _icon ?? string.Empty;
_page.EffectiveDate = _effectivedate;
_page.ExpiryDate = _expirydate;
_page.IsPersonalizable = (_ispersonalizable != null && Boolean.Parse(_ispersonalizable)); _page.IsPersonalizable = (_ispersonalizable != null && Boolean.Parse(_ispersonalizable));
// appearance // appearance
@ -666,4 +689,33 @@
{ {
_icon = NewIcon; _icon = NewIcon;
} }
private bool ValidateEffectiveExpiryDates(DateTime? effectiveDate, DateTime? expiryDate)
{
// Check if both dates are null, in which case the validation passes
if (effectiveDate == DateTime.MinValue && expiryDate == DateTime.MinValue)
{
return true;
}
// Check if EffectiveDate is not null and ExpiryDate is null
if (effectiveDate != DateTime.MinValue && expiryDate == DateTime.MinValue)
{
return true;
}
// Check if EffectiveDate is null and ExpiryDate is not null
if (effectiveDate == DateTime.MinValue && expiryDate != DateTime.MinValue)
{
return true;
}
// Check if ExpiryDate is not null and EffectiveDate is after ExpiryDate
if (expiryDate != DateTime.MinValue && effectiveDate != DateTime.MinValue && effectiveDate > expiryDate)
{
return false;
}
// If none of the above conditions are met, validation passes
return true;
}
} }

View File

@ -34,13 +34,13 @@ else
<div class="row mb-1 align-items-center"> <div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="effectiveDate" HelpText="The date that this role assignment is active" ResourceKey="EffectiveDate">Effective Date: </Label> <Label Class="col-sm-3" For="effectiveDate" HelpText="The date that this role assignment is active" ResourceKey="EffectiveDate">Effective Date: </Label>
<div class="col-sm-9"> <div class="col-sm-9">
<input type="date" id="effectiveDate" class="form-control" @bind="@effectivedate" /> <input type="date" id="effectiveDate" class="form-control" @bind="@_effectivedate" />
</div> </div>
</div> </div>
<div class="row mb-1 align-items-center"> <div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="expiryDate" HelpText="The date that this role assignment expires" ResourceKey="ExpiryDate">Expiry Date: </Label> <Label Class="col-sm-3" For="expiryDate" HelpText="The date that this role assignment expires" ResourceKey="ExpiryDate">Expiry Date: </Label>
<div class="col-sm-9"> <div class="col-sm-9">
<input type="date" id="expiryDate" class="form-control" @bind="@expirydate" /> <input type="date" id="expiryDate" class="form-control" @bind="@_expirydate" />
</div> </div>
</div> </div>
@ -75,8 +75,8 @@ else
private string name = string.Empty; private string name = string.Empty;
private List<Role> roles; private List<Role> roles;
private int roleid = -1; private int roleid = -1;
private DateTime? effectivedate = null; private DateTime? _effectivedate = null;
private DateTime? expirydate = null; private DateTime? _expirydate = null;
private List<UserRole> userroles; private List<UserRole> userroles;
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit; public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
@ -127,11 +127,16 @@ else
{ {
if (roleid != -1) if (roleid != -1)
{ {
if (!ValidateEffectiveExpiryDates(_effectivedate,_expirydate))
{
AddModuleMessage(SharedLocalizer["Message.EffectiveExpiryDateError"], MessageType.Warning);
return;
}
var userrole = userroles.Where(item => item.UserId == userid && item.RoleId == roleid).FirstOrDefault(); var userrole = userroles.Where(item => item.UserId == userid && item.RoleId == roleid).FirstOrDefault();
if (userrole != null) if (userrole != null)
{ {
userrole.EffectiveDate = effectivedate; userrole.EffectiveDate = _effectivedate;
userrole.ExpiryDate = expirydate; userrole.ExpiryDate = _expirydate;
await UserRoleService.UpdateUserRoleAsync(userrole); await UserRoleService.UpdateUserRoleAsync(userrole);
} }
else else
@ -139,8 +144,8 @@ else
userrole = new UserRole(); userrole = new UserRole();
userrole.UserId = userid; userrole.UserId = userid;
userrole.RoleId = roleid; userrole.RoleId = roleid;
userrole.EffectiveDate = effectivedate; userrole.EffectiveDate = _effectivedate;
userrole.ExpiryDate = expirydate; userrole.ExpiryDate = _expirydate;
await UserRoleService.AddUserRoleAsync(userrole); await UserRoleService.AddUserRoleAsync(userrole);
} }
@ -177,4 +182,34 @@ else
AddModuleMessage(Localizer["Error.User.RemoveRole"], MessageType.Error); AddModuleMessage(Localizer["Error.User.RemoveRole"], MessageType.Error);
} }
} }
private bool ValidateEffectiveExpiryDates(DateTime? effectiveDate, DateTime? expiryDate)
{
// Check if both dates are null, in which case the validation passes
if (effectiveDate == DateTime.MinValue && expiryDate == DateTime.MinValue)
{
return true;
}
// Check if EffectiveDate is not null and ExpiryDate is null
if (effectiveDate != DateTime.MinValue && expiryDate == DateTime.MinValue)
{
return true;
}
// Check if EffectiveDate is null and ExpiryDate is not null
if (effectiveDate == DateTime.MinValue && expiryDate != DateTime.MinValue)
{
return true;
}
// Check if ExpiryDate is not null and EffectiveDate is after ExpiryDate
if (expiryDate != DateTime.MinValue && effectiveDate != DateTime.MinValue && effectiveDate > expiryDate)
{
return false;
}
// If none of the above conditions are met, validation passes
return true;
}
} }

View File

@ -165,4 +165,16 @@
<data name="Pane.Text" xml:space="preserve"> <data name="Pane.Text" xml:space="preserve">
<value>Pane:</value> <value>Pane:</value>
</data> </data>
<data name="EffectiveDate.HelpText" xml:space="preserve">
<value>The date that this module is active</value>
</data>
<data name="EffectiveDate.Text" xml:space="preserve">
<value>Effective Date: </value>
</data>
<data name="ExpiryDate.HelpText" xml:space="preserve">
<value>The date that this module expires</value>
</data>
<data name="ExpiryDate.Text" xml:space="preserve">
<value>Expiry Date: </value>
</data>
</root> </root>

View File

@ -255,4 +255,16 @@
<data name="Theme.Heading" xml:space="preserve"> <data name="Theme.Heading" xml:space="preserve">
<value>Theme Settings</value> <value>Theme Settings</value>
</data> </data>
<data name="EffectiveDate.HelpText" xml:space="preserve">
<value>The date that this page is active</value>
</data>
<data name="EffectiveDate.Text" xml:space="preserve">
<value>Effective Date: </value>
</data>
<data name="ExpiryDate.HelpText" xml:space="preserve">
<value>The date that this page expires</value>
</data>
<data name="ExpiryDate.Text" xml:space="preserve">
<value>Expiry Date: </value>
</data>
</root> </root>

View File

@ -285,4 +285,16 @@
<data name="ThemeChanged.Message" xml:space="preserve"> <data name="ThemeChanged.Message" xml:space="preserve">
<value>Please Note That Overriding The Default Site Theme With An Unrelated Page Theme May Result In Compatibility Issues For Your Site</value> <value>Please Note That Overriding The Default Site Theme With An Unrelated Page Theme May Result In Compatibility Issues For Your Site</value>
</data> </data>
<data name="EffectiveDate.HelpText" xml:space="preserve">
<value>The date that this page is active</value>
</data>
<data name="EffectiveDate.Text" xml:space="preserve">
<value>Effective Date: </value>
</data>
<data name="ExpiryDate.HelpText" xml:space="preserve">
<value>The date that this page expires</value>
</data>
<data name="ExpiryDate.Text" xml:space="preserve">
<value>Expiry Date: </value>
</data>
</root> </root>

View File

@ -438,4 +438,7 @@
<data name="Test" xml:space="preserve"> <data name="Test" xml:space="preserve">
<value>Test</value> <value>Test</value>
</data> </data>
<data name="Message.EffectiveExpiryDateError" xml:space="preserve">
<value>Effective Date cannot be after Expiry Date.</value>
</data>
</root> </root>

View File

@ -259,10 +259,18 @@
} }
} }
if (page != null) bool isAdminOrHost = false;
if(user != null)
{
isAdminOrHost = user.Roles.Contains(RoleNames.Host) || user.Roles.Contains(RoleNames.Admin);
}
if (page != null && (isAdminOrHost || IsPageModuleVisible(page.EffectiveDate, page.ExpiryDate)))
{ {
// check if user is authorized to view page // check if user is authorized to view page
if (UserSecurity.IsAuthorized(user, PermissionNames.View, page.PermissionList)) if (UserSecurity.IsAuthorized(user, PermissionNames.View, page.PermissionList))
{
if (isAdminOrHost || IsPageModuleVisible(page.EffectiveDate, page.ExpiryDate))
{ {
// load additional metadata for current page // load additional metadata for current page
page = ProcessPage(page, site, user, SiteState.Alias); page = ProcessPage(page, site, user, SiteState.Alias);
@ -296,6 +304,7 @@
await ScrollToFragment(_pagestate.Uri); await ScrollToFragment(_pagestate.Uri);
} }
} }
}
else // page not found else // page not found
{ {
// look for url mapping // look for url mapping
@ -307,7 +316,7 @@
} }
else // not mapped else // not mapped
{ {
if (user == null) if (user == null && IsPageModuleVisible(page.EffectiveDate, page.ExpiryDate))
{ {
// redirect to login page if user not logged in as they may need to be authenticated // redirect to login page if user not logged in as they may need to be authenticated
NavigationManager.NavigateTo(Utilities.NavigateUrl(SiteState.Alias.Path, "login", "?returnurl=" + WebUtility.UrlEncode(route.PathAndQuery))); NavigationManager.NavigateTo(Utilities.NavigateUrl(SiteState.Alias.Path, "login", "?returnurl=" + WebUtility.UrlEncode(route.PathAndQuery)));
@ -578,4 +587,29 @@
} }
} }
} }
private bool IsPageModuleVisible(DateTime? effectiveDate, DateTime? expiryDate)
{
DateTime currentUtcTime = DateTime.UtcNow;
// Check if either effectiveDate or expiryDate is provided
if (effectiveDate.HasValue && expiryDate.HasValue)
{
return currentUtcTime >= effectiveDate.Value && currentUtcTime <= expiryDate.Value;
}
// Check if only effectiveDate is provided
else if (effectiveDate.HasValue)
{
return currentUtcTime >= effectiveDate.Value;
}
// Check if only expiryDate is provided
else if (expiryDate.HasValue)
{
return currentUtcTime <= expiryDate.Value;
}
// If neither effectiveDate nor expiryDate is provided, consider the page/module visible
else
{
return true;
}
}
} }

View File

@ -75,6 +75,8 @@ namespace Oqtane.Controllers
module.Pane = pagemodule.Pane; module.Pane = pagemodule.Pane;
module.Order = pagemodule.Order; module.Order = pagemodule.Order;
module.ContainerType = pagemodule.ContainerType; module.ContainerType = pagemodule.ContainerType;
module.EffectiveDate = pagemodule.EffectiveDate;
module.ExpiryDate = pagemodule.ExpiryDate;
module.ModuleDefinition = _moduleDefinitions.FilterModuleDefinition(moduledefinitions.Find(item => item.ModuleDefinitionName == module.ModuleDefinitionName)); module.ModuleDefinition = _moduleDefinitions.FilterModuleDefinition(moduledefinitions.Find(item => item.ModuleDefinitionName == module.ModuleDefinitionName));
@ -169,7 +171,7 @@ namespace Oqtane.Controllers
{ {
if (!pageModules.Exists(item => item.ModuleId == module.ModuleId && item.PageId == page.PageId) && !page.Path.StartsWith("admin/")) if (!pageModules.Exists(item => item.ModuleId == module.ModuleId && item.PageId == page.PageId) && !page.Path.StartsWith("admin/"))
{ {
_pageModules.AddPageModule(new PageModule { PageId = page.PageId, ModuleId = pageModule.ModuleId, Title = pageModule.Title, Pane = pageModule.Pane, Order = pageModule.Order, ContainerType = pageModule.ContainerType }); _pageModules.AddPageModule(new PageModule { PageId = page.PageId, ModuleId = pageModule.ModuleId, Title = pageModule.Title, Pane = pageModule.Pane, Order = pageModule.Order, ContainerType = pageModule.ContainerType, EffectiveDate = pageModule.EffectiveDate, ExpiryDate = pageModule.ExpiryDate });
} }
} }
} }

View File

@ -13,6 +13,8 @@ using System.Globalization;
using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Caching.Memory;
using Oqtane.Extensions; using Oqtane.Extensions;
using System; using System;
using Oqtane.UI;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
namespace Oqtane.Controllers namespace Oqtane.Controllers
{ {
@ -92,59 +94,71 @@ namespace Oqtane.Controllers
site.UploadableFiles = site.Settings.ContainsKey("UploadableFiles") && !string.IsNullOrEmpty(site.Settings["UploadableFiles"]) site.UploadableFiles = site.Settings.ContainsKey("UploadableFiles") && !string.IsNullOrEmpty(site.Settings["UploadableFiles"])
? site.Settings["UploadableFiles"] : Constants.UploadableFiles; ? site.Settings["UploadableFiles"] : Constants.UploadableFiles;
var modelsUser = _userPermissions.GetUser(User);
var isAdminOrHost = modelsUser.Roles.Contains(RoleNames.Host) || modelsUser.Roles.Contains(RoleNames.Admin);
// pages // pages
List<Setting> settings = _settings.GetSettings(EntityNames.Page).ToList(); List<Setting> settings = _settings.GetSettings(EntityNames.Page).ToList();
site.Pages = new List<Page>(); site.Pages = new List<Page>();
foreach (Page page in _pages.GetPages(site.SiteId)) foreach (Page page in _pages.GetPages(site.SiteId).Where(p => !p.IsDeleted && _userPermissions.IsAuthorized(User, PermissionNames.View, p.PermissionList)))
{ {
if (!page.IsDeleted && _userPermissions.IsAuthorized(User, PermissionNames.View, page.PermissionList)) if (isAdminOrHost || IsPageModuleVisible(page.EffectiveDate, page.ExpiryDate))
{ {
page.Settings = settings.Where(item => item.EntityId == page.PageId) page.Settings = settings
.Where(item => item.EntityId == page.PageId)
.Where(item => !item.IsPrivate || _userPermissions.IsAuthorized(User, PermissionNames.Edit, page.PermissionList)) .Where(item => !item.IsPrivate || _userPermissions.IsAuthorized(User, PermissionNames.Edit, page.PermissionList))
.ToDictionary(setting => setting.SettingName, setting => setting.SettingValue); .ToDictionary(setting => setting.SettingName, setting => setting.SettingValue);
site.Pages.Add(page); site.Pages.Add(page);
} }
} }
site.Pages = GetPagesHierarchy(site.Pages); site.Pages = GetPagesHierarchy(site.Pages);
// modules // modules
List<ModuleDefinition> moduledefinitions = _moduleDefinitions.GetModuleDefinitions(site.SiteId).ToList(); List<ModuleDefinition> moduledefinitions = _moduleDefinitions.GetModuleDefinitions(site.SiteId).ToList();
settings = _settings.GetSettings(EntityNames.Module).ToList(); settings = _settings.GetSettings(EntityNames.Module).ToList();
site.Modules = new List<Module>(); site.Modules = new List<Module>();
foreach (PageModule pagemodule in _pageModules.GetPageModules(site.SiteId)) foreach (PageModule pagemodule in _pageModules.GetPageModules(site.SiteId).Where(pm => !pm.IsDeleted && _userPermissions.IsAuthorized(User, PermissionNames.View, pm.Module.PermissionList)))
{ {
if (!pagemodule.IsDeleted && _userPermissions.IsAuthorized(User, PermissionNames.View, pagemodule.Module.PermissionList)) if (isAdminOrHost || IsPageModuleVisible(pagemodule.EffectiveDate, pagemodule.ExpiryDate))
{ {
Module module = new Module(); Module module = new Module
module.SiteId = pagemodule.Module.SiteId; {
module.ModuleDefinitionName = pagemodule.Module.ModuleDefinitionName; SiteId = pagemodule.Module.SiteId,
module.AllPages = pagemodule.Module.AllPages; ModuleDefinitionName = pagemodule.Module.ModuleDefinitionName,
module.PermissionList = pagemodule.Module.PermissionList; AllPages = pagemodule.Module.AllPages,
module.CreatedBy = pagemodule.Module.CreatedBy; PermissionList = pagemodule.Module.PermissionList,
module.CreatedOn = pagemodule.Module.CreatedOn; CreatedBy = pagemodule.Module.CreatedBy,
module.ModifiedBy = pagemodule.Module.ModifiedBy; CreatedOn = pagemodule.Module.CreatedOn,
module.ModifiedOn = pagemodule.Module.ModifiedOn; ModifiedBy = pagemodule.Module.ModifiedBy,
module.DeletedBy = pagemodule.DeletedBy; ModifiedOn = pagemodule.Module.ModifiedOn,
module.DeletedOn = pagemodule.DeletedOn; DeletedBy = pagemodule.DeletedBy,
module.IsDeleted = pagemodule.IsDeleted; DeletedOn = pagemodule.DeletedOn,
IsDeleted = pagemodule.IsDeleted,
module.PageModuleId = pagemodule.PageModuleId; PageModuleId = pagemodule.PageModuleId,
module.ModuleId = pagemodule.ModuleId; ModuleId = pagemodule.ModuleId,
module.PageId = pagemodule.PageId; PageId = pagemodule.PageId,
module.Title = pagemodule.Title; Title = pagemodule.Title,
module.Pane = pagemodule.Pane; Pane = pagemodule.Pane,
module.Order = pagemodule.Order; Order = pagemodule.Order,
module.ContainerType = pagemodule.ContainerType; ContainerType = pagemodule.ContainerType,
EffectiveDate = pagemodule.EffectiveDate,
ExpiryDate = pagemodule.ExpiryDate,
module.ModuleDefinition = _moduleDefinitions.FilterModuleDefinition(moduledefinitions.Find(item => item.ModuleDefinitionName == module.ModuleDefinitionName)); ModuleDefinition = _moduleDefinitions.FilterModuleDefinition(moduledefinitions.Find(item => item.ModuleDefinitionName == pagemodule.Module.ModuleDefinitionName)),
module.Settings = settings.Where(item => item.EntityId == pagemodule.ModuleId) Settings = settings
.Where(item => item.EntityId == pagemodule.ModuleId)
.Where(item => !item.IsPrivate || _userPermissions.IsAuthorized(User, PermissionNames.Edit, pagemodule.Module.PermissionList)) .Where(item => !item.IsPrivate || _userPermissions.IsAuthorized(User, PermissionNames.Edit, pagemodule.Module.PermissionList))
.ToDictionary(setting => setting.SettingName, setting => setting.SettingValue); .ToDictionary(setting => setting.SettingName, setting => setting.SettingValue)
};
site.Modules.Add(module); site.Modules.Add(module);
} }
} }
site.Modules = site.Modules.OrderBy(item => item.PageId).ThenBy(item => item.Pane).ThenBy(item => item.Order).ToList(); site.Modules = site.Modules.OrderBy(item => item.PageId).ThenBy(item => item.Pane).ThenBy(item => item.Order).ToList();
// languages // languages
@ -277,5 +291,30 @@ namespace Oqtane.Controllers
} }
return hierarchy; return hierarchy;
} }
private bool IsPageModuleVisible(DateTime? effectiveDate, DateTime? expiryDate)
{
DateTime currentUtcTime = DateTime.UtcNow;
// Check if either effectiveDate or expiryDate is provided
if (effectiveDate.HasValue && expiryDate.HasValue)
{
return currentUtcTime >= effectiveDate.Value && currentUtcTime <= expiryDate.Value;
}
// Check if only effectiveDate is provided
else if (effectiveDate.HasValue)
{
return currentUtcTime >= effectiveDate.Value;
}
// Check if only expiryDate is provided
else if (expiryDate.HasValue)
{
return currentUtcTime <= expiryDate.Value;
}
// If neither effectiveDate nor expiryDate is provided, consider the page/module visible
else
{
return true;
}
}
} }
} }

View File

@ -0,0 +1,32 @@
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Microsoft.EntityFrameworkCore.Migrations;
using Oqtane.Databases.Interfaces;
using Oqtane.Migrations.EntityBuilders;
using Oqtane.Repository;
namespace Oqtane.Migrations.Tenant
{
[DbContext(typeof(TenantDBContext))]
[Migration("Tenant.05.01.00.01")]
public class AddPageEffectiveExpiryDate : MultiDatabaseMigration
{
public AddPageEffectiveExpiryDate(IDatabase database) : base(database)
{
}
protected override void Up(MigrationBuilder migrationBuilder)
{
var pageEntityBuilder = new PageEntityBuilder(migrationBuilder, ActiveDatabase);;
pageEntityBuilder.AddDateTimeColumn("EffectiveDate", true);
pageEntityBuilder.AddDateTimeColumn("ExpiryDate", true);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
var pageEntityBuilder = new PageEntityBuilder(migrationBuilder, ActiveDatabase);
pageEntityBuilder.DropColumn("EffectiveDate");
pageEntityBuilder.DropColumn("ExpiryDate");
}
}
}

View File

@ -0,0 +1,32 @@
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Microsoft.EntityFrameworkCore.Migrations;
using Oqtane.Databases.Interfaces;
using Oqtane.Migrations.EntityBuilders;
using Oqtane.Repository;
namespace Oqtane.Migrations.Tenant
{
[DbContext(typeof(TenantDBContext))]
[Migration("Tenant.05.01.00.02")]
public class AddPageModuleEffectiveExpiryDate : MultiDatabaseMigration
{
public AddPageModuleEffectiveExpiryDate(IDatabase database) : base(database)
{
}
protected override void Up(MigrationBuilder migrationBuilder)
{
var pageModuleEntityBuilder = new PageModuleEntityBuilder(migrationBuilder, ActiveDatabase);;
pageModuleEntityBuilder.AddDateTimeColumn("EffectiveDate", true);
pageModuleEntityBuilder.AddDateTimeColumn("ExpiryDate", true);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
var pageModuleEntityBuilder = new PageModuleEntityBuilder(migrationBuilder, ActiveDatabase);
pageModuleEntityBuilder.DropColumn("EffectiveDate");
pageModuleEntityBuilder.DropColumn("ExpiryDate");
}
}
}

View File

@ -75,6 +75,12 @@ namespace Oqtane.Models
[NotMapped] [NotMapped]
public string ContainerType { get; set; } public string ContainerType { get; set; }
[NotMapped]
public DateTime? EffectiveDate { get; set; }
[NotMapped]
public DateTime? ExpiryDate { get; set; }
#endregion #endregion
#region SiteRouter properties #region SiteRouter properties

View File

@ -82,6 +82,14 @@ namespace Oqtane.Models
public bool IsNavigation { get; set; } public bool IsNavigation { get; set; }
public bool IsClickable { get; set; } public bool IsClickable { get; set; }
public int? UserId { get; set; } public int? UserId { get; set; }
/// <summary>
/// Start of when this assignment is valid. See also <see cref="ExpiryDate"/>
/// </summary>
public DateTime? EffectiveDate { get; set; }
/// <summary>
/// End of when this assignment is valid. See also <see cref="EffectiveDate"/>
/// </summary>
public DateTime? ExpiryDate { get; set; }
public bool IsPersonalizable { get; set; } public bool IsPersonalizable { get; set; }
#region IDeletable Properties #region IDeletable Properties

View File

@ -41,7 +41,14 @@ namespace Oqtane.Models
/// Reference to a Razor Container which wraps this module instance. /// Reference to a Razor Container which wraps this module instance.
/// </summary> /// </summary>
public string ContainerType { get; set; } public string ContainerType { get; set; }
/// <summary>
/// Start of when this assignment is valid. See also <see cref="ExpiryDate"/>
/// </summary>
public DateTime? EffectiveDate { get; set; }
/// <summary>
/// End of when this assignment is valid. See also <see cref="EffectiveDate"/>
/// </summary>
public DateTime? ExpiryDate { get; set; }
#region IDeletable Properties #region IDeletable Properties
public string DeletedBy { get; set; } public string DeletedBy { get; set; }