commit
d93862043a
2
LICENSE
2
LICENSE
|
@ -1,6 +1,6 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2018-2023 .NET Foundation
|
||||
Copyright (c) 2018-2024 .NET Foundation
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
|
@ -69,7 +69,7 @@
|
|||
<h2>@Localizer["ApplicationAdmin"]</h2><br />
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="username" HelpText="Provide a username for the primary user accountt" ResourceKey="Username">Username:</Label>
|
||||
<Label Class="col-sm-3" For="username" HelpText="Provide a username for the primary user account" ResourceKey="Username">Username:</Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="username" type="text" class="form-control" @bind="@_hostUsername" />
|
||||
</div>
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="runs-every" HelpText="Select how often you want the job to run" ResourceKey="RunsEvery">Runs Every: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="runs-every" class="form-control" @bind="@_interval" maxlength="4" required />
|
||||
<input id="runs-every" class="form-control mb-1" @bind="@_interval" maxlength="4" required />
|
||||
<select id="runs-every" class="form-select" @bind="@_frequency" required>
|
||||
<option value="m">@Localizer["Minute(s)"]</option>
|
||||
<option value="H">@Localizer["Hour(s)"]</option>
|
||||
|
@ -154,6 +154,11 @@
|
|||
|
||||
private async Task SaveJob()
|
||||
{
|
||||
if (!Utilities.ValidateEffectiveExpiryDates(_startDate, _endDate))
|
||||
{
|
||||
AddModuleMessage(Localizer["Message.StartEndDateError"], MessageType.Warning);
|
||||
return;
|
||||
}
|
||||
validated = true;
|
||||
var interop = new Interop(JSRuntime);
|
||||
if (await interop.FormValid(form))
|
||||
|
|
|
@ -13,13 +13,13 @@
|
|||
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="owner" HelpText="Enter the name of the organization who is developing this module. It should not contain spaces or punctuation." ResourceKey="OwnerName">Owner Name: </Label>
|
||||
<Label Class="col-sm-3" For="owner" HelpText="Enter the name of the organization who is developing this module. It should not contain spaces or punctuation or the word oqtane." ResourceKey="OwnerName">Owner Name: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="owner" class="form-control" @bind="@_owner" required />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="module" HelpText="Enter a name for this module. It should not contain spaces or punctuation." ResourceKey="ModuleName">Module Name: </Label>
|
||||
<Label Class="col-sm-3" For="module" HelpText="Enter a name for this module. It should not contain spaces or punctuation or the word oqtane." ResourceKey="ModuleName">Module Name: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="module" class="form-control" @bind="@_module" required />
|
||||
</div>
|
||||
|
|
|
@ -48,6 +48,18 @@
|
|||
</select>
|
||||
</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">
|
||||
<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">
|
||||
|
@ -114,7 +126,7 @@
|
|||
<AuditInfo CreatedBy="@createdby" CreatedOn="@createdon" ModifiedBy="@modifiedby" ModifiedOn="@modifiedon"></AuditInfo>
|
||||
</form>
|
||||
|
||||
@code {
|
||||
@code {
|
||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
|
||||
public override string Title => "Module Settings";
|
||||
|
||||
|
@ -141,7 +153,8 @@
|
|||
private DateTime createdon;
|
||||
private string modifiedby;
|
||||
private DateTime modifiedon;
|
||||
|
||||
private DateTime? _effectivedate = null;
|
||||
private DateTime? _expirydate = null;
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
_module = ModuleState.ModuleDefinition.Name;
|
||||
|
@ -156,6 +169,8 @@
|
|||
createdon = ModuleState.CreatedOn;
|
||||
modifiedby = ModuleState.ModifiedBy;
|
||||
modifiedon = ModuleState.ModifiedOn;
|
||||
_effectivedate = Utilities.UtcAsLocalDate(ModuleState.EffectiveDate);
|
||||
_expirydate = Utilities.UtcAsLocalDate(ModuleState.ExpiryDate);
|
||||
|
||||
if (ModuleState.ModuleDefinition != null)
|
||||
{
|
||||
|
@ -214,12 +229,20 @@
|
|||
var interop = new Interop(JSRuntime);
|
||||
if (await interop.FormValid(form))
|
||||
{
|
||||
|
||||
if (!string.IsNullOrEmpty(_title))
|
||||
{
|
||||
if (!Utilities.ValidateEffectiveExpiryDates(_effectivedate, _expirydate))
|
||||
{
|
||||
AddModuleMessage(SharedLocalizer["Message.EffectiveExpiryDateError"], MessageType.Warning);
|
||||
return;
|
||||
}
|
||||
var pagemodule = await PageModuleService.GetPageModuleAsync(ModuleState.PageModuleId);
|
||||
pagemodule.PageId = int.Parse(_pageId);
|
||||
pagemodule.Title = _title;
|
||||
pagemodule.Pane = _pane;
|
||||
pagemodule.EffectiveDate = Utilities.LocalDateAndTimeAsUtc(_effectivedate);
|
||||
pagemodule.ExpiryDate = Utilities.LocalDateAndTimeAsUtc(_expirydate);
|
||||
pagemodule.ContainerType = (_containerType != "-") ? _containerType : string.Empty;
|
||||
if (!string.IsNullOrEmpty(pagemodule.ContainerType) && pagemodule.ContainerType == PageState.Page.DefaultContainerType)
|
||||
{
|
||||
|
@ -269,5 +292,4 @@
|
|||
AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -119,6 +119,18 @@
|
|||
<i class="@_icon"></i>
|
||||
</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">
|
||||
<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">
|
||||
|
@ -233,6 +245,8 @@
|
|||
protected Page _parent = null;
|
||||
protected Dictionary<string, string> _icons;
|
||||
private string _iconresources = "";
|
||||
private DateTime? _effectivedate = null;
|
||||
private DateTime? _expirydate = null;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
|
@ -265,6 +279,8 @@
|
|||
_children.Add(p);
|
||||
}
|
||||
}
|
||||
_effectivedate = Utilities.UtcAsLocalDate(PageState.Page.EffectiveDate);
|
||||
_expirydate = Utilities.UtcAsLocalDate(PageState.Page.ExpiryDate);
|
||||
ThemeSettings();
|
||||
_initialized = true;
|
||||
}
|
||||
|
@ -274,18 +290,18 @@
|
|||
AddModuleMessage(Localizer["Error.Page.Load"], MessageType.Error);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Loading Page {Error}", ex.Message);
|
||||
AddModuleMessage(Localizer["Error.Page.Load"], MessageType.Error);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Loading Page {Error}", ex.Message);
|
||||
AddModuleMessage(Localizer["Error.Page.Load"], MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private async void ParentChanged(ChangeEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
_parentid = (string)e.Value;
|
||||
private async void ParentChanged(ChangeEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
_parentid = (string)e.Value;
|
||||
_children = new List<Page>();
|
||||
foreach (Page p in PageState.Pages.Where(item => (_parentid == "-1" && item.ParentId == null) || (item.ParentId == int.Parse(_parentid))))
|
||||
{
|
||||
|
@ -295,13 +311,13 @@
|
|||
}
|
||||
}
|
||||
StateHasChanged();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Loading Child Pages For Parent {PageId} {Error}", _parentid, ex.Message);
|
||||
AddModuleMessage(Localizer["Error.ChildPage.Load"], MessageType.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Loading Child Pages For Parent {PageId} {Error}", _parentid, ex.Message);
|
||||
AddModuleMessage(Localizer["Error.ChildPage.Load"], MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private void ThemeChanged(ChangeEventArgs e)
|
||||
{
|
||||
|
@ -318,109 +334,116 @@
|
|||
}
|
||||
}
|
||||
|
||||
private void ThemeSettings()
|
||||
{
|
||||
_themeSettingsType = null;
|
||||
private void ThemeSettings()
|
||||
{
|
||||
_themeSettingsType = null;
|
||||
var theme = PageState.Site.Themes.FirstOrDefault(item => item.Themes.Any(themecontrol => themecontrol.TypeName.Equals(_themetype)));
|
||||
if (theme != null && !string.IsNullOrEmpty(theme.ThemeSettingsType))
|
||||
{
|
||||
_themeSettingsType = Type.GetType(theme.ThemeSettingsType);
|
||||
if (_themeSettingsType != null)
|
||||
{
|
||||
ThemeSettingsComponent = builder =>
|
||||
{
|
||||
builder.OpenComponent(0, _themeSettingsType);
|
||||
builder.AddComponentReferenceCapture(1, inst => { _themeSettings = Convert.ChangeType(inst, _themeSettingsType); });
|
||||
builder.CloseComponent();
|
||||
};
|
||||
}
|
||||
_refresh = true;
|
||||
}
|
||||
}
|
||||
if (theme != null && !string.IsNullOrEmpty(theme.ThemeSettingsType))
|
||||
{
|
||||
_themeSettingsType = Type.GetType(theme.ThemeSettingsType);
|
||||
if (_themeSettingsType != null)
|
||||
{
|
||||
ThemeSettingsComponent = builder =>
|
||||
{
|
||||
builder.OpenComponent(0, _themeSettingsType);
|
||||
builder.AddComponentReferenceCapture(1, inst => { _themeSettings = Convert.ChangeType(inst, _themeSettingsType); });
|
||||
builder.CloseComponent();
|
||||
};
|
||||
}
|
||||
_refresh = true;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SavePage()
|
||||
{
|
||||
validated = true;
|
||||
var interop = new Interop(JSRuntime);
|
||||
if (await interop.FormValid(form))
|
||||
{
|
||||
Page page = null;
|
||||
try
|
||||
{
|
||||
private async Task SavePage()
|
||||
{
|
||||
validated = true;
|
||||
var interop = new Interop(JSRuntime);
|
||||
if (await interop.FormValid(form))
|
||||
{
|
||||
Page page = null;
|
||||
try
|
||||
{
|
||||
if (!Utilities.ValidateEffectiveExpiryDates(_effectivedate, _expirydate))
|
||||
{
|
||||
AddModuleMessage(SharedLocalizer["Message.EffectiveExpiryDateError"], MessageType.Warning);
|
||||
return;
|
||||
}
|
||||
if (!string.IsNullOrEmpty(_themetype) && !string.IsNullOrEmpty(_containertype))
|
||||
{
|
||||
page = new Page();
|
||||
page.SiteId = PageState.Page.SiteId;
|
||||
page.Name = _name;
|
||||
{
|
||||
page = new Page();
|
||||
page.SiteId = PageState.Page.SiteId;
|
||||
page.Name = _name;
|
||||
|
||||
if (string.IsNullOrEmpty(_path))
|
||||
{
|
||||
_path = _name;
|
||||
}
|
||||
if (_path.Contains("/"))
|
||||
{
|
||||
if (_path.EndsWith("/") && _path != "/")
|
||||
{
|
||||
_path = _path.Substring(0, _path.Length - 1);
|
||||
}
|
||||
_path = _path.Substring(_path.LastIndexOf("/") + 1);
|
||||
}
|
||||
if (string.IsNullOrEmpty(_path))
|
||||
{
|
||||
_path = _name;
|
||||
}
|
||||
if (_path.Contains("/"))
|
||||
{
|
||||
if (_path.EndsWith("/") && _path != "/")
|
||||
{
|
||||
_path = _path.Substring(0, _path.Length - 1);
|
||||
}
|
||||
_path = _path.Substring(_path.LastIndexOf("/") + 1);
|
||||
}
|
||||
|
||||
if (_parentid == "-1")
|
||||
{
|
||||
page.ParentId = null;
|
||||
page.Path = Utilities.GetFriendlyUrl(_path);
|
||||
}
|
||||
else
|
||||
{
|
||||
page.ParentId = Int32.Parse(_parentid);
|
||||
var parent = PageState.Pages.Where(item => item.PageId == page.ParentId).FirstOrDefault();
|
||||
if (parent.Path == string.Empty)
|
||||
{
|
||||
page.Path = Utilities.GetFriendlyUrl(parent.Name) + "/" + Utilities.GetFriendlyUrl(_path);
|
||||
}
|
||||
else
|
||||
{
|
||||
page.Path = parent.Path + "/" + Utilities.GetFriendlyUrl(_path);
|
||||
}
|
||||
}
|
||||
if (_parentid == "-1")
|
||||
{
|
||||
page.ParentId = null;
|
||||
page.Path = Utilities.GetFriendlyUrl(_path);
|
||||
}
|
||||
else
|
||||
{
|
||||
page.ParentId = Int32.Parse(_parentid);
|
||||
var parent = PageState.Pages.Where(item => item.PageId == page.ParentId).FirstOrDefault();
|
||||
if (parent.Path == string.Empty)
|
||||
{
|
||||
page.Path = Utilities.GetFriendlyUrl(parent.Name) + "/" + Utilities.GetFriendlyUrl(_path);
|
||||
}
|
||||
else
|
||||
{
|
||||
page.Path = parent.Path + "/" + Utilities.GetFriendlyUrl(_path);
|
||||
}
|
||||
}
|
||||
|
||||
var _pages = await PageService.GetPagesAsync(PageState.Site.SiteId);
|
||||
if (_pages.Any(item => item.Path == page.Path))
|
||||
{
|
||||
AddModuleMessage(string.Format(Localizer["Message.Page.Exists"], _path), MessageType.Warning);
|
||||
return;
|
||||
}
|
||||
var _pages = await PageService.GetPagesAsync(PageState.Site.SiteId);
|
||||
if (_pages.Any(item => item.Path == page.Path))
|
||||
{
|
||||
AddModuleMessage(string.Format(Localizer["Message.Page.Exists"], _path), MessageType.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
if (page.ParentId == null && Constants.ReservedRoutes.Contains(page.Name.ToLower()))
|
||||
{
|
||||
AddModuleMessage(string.Format(Localizer["Message.Page.Reserved"], page.Name), MessageType.Warning);
|
||||
return;
|
||||
}
|
||||
if (page.ParentId == null && Constants.ReservedRoutes.Contains(page.Name.ToLower()))
|
||||
{
|
||||
AddModuleMessage(string.Format(Localizer["Message.Page.Reserved"], page.Name), MessageType.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
Page child;
|
||||
switch (_insert)
|
||||
{
|
||||
case "<<":
|
||||
page.Order = 0;
|
||||
break;
|
||||
case "<":
|
||||
child = PageState.Pages.Where(item => item.PageId == _childid).FirstOrDefault();
|
||||
page.Order = child.Order - 1;
|
||||
break;
|
||||
case ">":
|
||||
child = PageState.Pages.Where(item => item.PageId == _childid).FirstOrDefault();
|
||||
page.Order = child.Order + 1;
|
||||
break;
|
||||
case ">>":
|
||||
page.Order = int.MaxValue;
|
||||
break;
|
||||
}
|
||||
Page child;
|
||||
switch (_insert)
|
||||
{
|
||||
case "<<":
|
||||
page.Order = 0;
|
||||
break;
|
||||
case "<":
|
||||
child = PageState.Pages.Where(item => item.PageId == _childid).FirstOrDefault();
|
||||
page.Order = child.Order - 1;
|
||||
break;
|
||||
case ">":
|
||||
child = PageState.Pages.Where(item => item.PageId == _childid).FirstOrDefault();
|
||||
page.Order = child.Order + 1;
|
||||
break;
|
||||
case ">>":
|
||||
page.Order = int.MaxValue;
|
||||
break;
|
||||
}
|
||||
|
||||
page.IsNavigation = (_isnavigation == null ? true : Boolean.Parse(_isnavigation));
|
||||
page.IsClickable = (_isclickable == null ? true : Boolean.Parse(_isclickable));
|
||||
page.IsNavigation = (_isnavigation == null ? true : Boolean.Parse(_isnavigation));
|
||||
page.IsClickable = (_isclickable == null ? true : Boolean.Parse(_isclickable));
|
||||
page.Url = _url;
|
||||
page.IsPersonalizable = (_ispersonalizable == null ? false : Boolean.Parse(_ispersonalizable));
|
||||
page.EffectiveDate = Utilities.LocalDateAndTimeAsUtc(_effectivedate);
|
||||
page.ExpiryDate = Utilities.LocalDateAndTimeAsUtc(_expirydate);
|
||||
page.UserId = null;
|
||||
|
||||
// appearance
|
||||
|
|
|
@ -134,6 +134,18 @@
|
|||
<i class="@_icon"></i>
|
||||
</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">
|
||||
<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">
|
||||
|
@ -322,6 +334,8 @@
|
|||
protected Page _parent = null;
|
||||
protected Dictionary<string, string> _icons;
|
||||
private string _iconresources = "";
|
||||
private DateTime? _effectivedate = null;
|
||||
private DateTime? _expirydate = null;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
|
@ -370,6 +384,8 @@
|
|||
}
|
||||
_url = _page.Url;
|
||||
_icon = _page.Icon;
|
||||
_effectivedate = Utilities.UtcAsLocalDate(_page.EffectiveDate);
|
||||
_expirydate = Utilities.UtcAsLocalDate(_page.ExpiryDate);
|
||||
_ispersonalizable = _page.IsPersonalizable.ToString();
|
||||
|
||||
// appearance
|
||||
|
@ -487,6 +503,11 @@
|
|||
{
|
||||
try
|
||||
{
|
||||
if (!Utilities.ValidateEffectiveExpiryDates(_effectivedate, _expirydate))
|
||||
{
|
||||
AddModuleMessage(SharedLocalizer["Message.EffectiveExpiryDateError"], MessageType.Warning);
|
||||
return;
|
||||
}
|
||||
if (!string.IsNullOrEmpty(_themetype) && _containertype != "-")
|
||||
{
|
||||
string currentPath = _page.Path;
|
||||
|
@ -563,6 +584,8 @@
|
|||
_page.IsClickable = (_isclickable == null ? true : Boolean.Parse(_isclickable));
|
||||
_page.Url = _url;
|
||||
_page.Icon = _icon ?? string.Empty;
|
||||
_page.EffectiveDate = Utilities.LocalDateAndTimeAsUtc(_effectivedate);
|
||||
_page.ExpiryDate = Utilities.LocalDateAndTimeAsUtc(_expirydate);
|
||||
_page.IsPersonalizable = (_ispersonalizable != null && Boolean.Parse(_ispersonalizable));
|
||||
|
||||
// appearance
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="order" HelpText="The index order of where this profile item should be displayed" ResourceKey="Order">Order: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="order" class="form-control" @bind="@_vieworder" min="0" max="99" type="number" required />
|
||||
<input id="order" class="form-control" @bind="@_vieworder" min="0" max="9999" type="number" required />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
|
@ -76,6 +76,12 @@
|
|||
<input id="validation" class="form-control" @bind="@_validation" maxlength="200" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="autocomplete" HelpText="The HTML autocomplete attribute allows you to specify browser behavior for automated user assistance in filling out form field values. Allowable values are blank (default), 'on', 'off', or any value from the standardized taxonomy defined for this attribute." ResourceKey="Autocomplete">Autocomplete: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="autocomplete" class="form-control" @bind="@_autocomplete" maxlength="30" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="private" HelpText="Should this profile item be visible to all users?" ResourceKey="Private">Private? </Label>
|
||||
<div class="col-sm-9">
|
||||
|
@ -89,7 +95,7 @@
|
|||
<br />
|
||||
<button type="button" class="btn btn-success" @onclick="SaveProfile">@SharedLocalizer["Save"]</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||
@if (PageState.QueryString.ContainsKey("id"))
|
||||
@if (PageState.QueryString.ContainsKey("id"))
|
||||
{
|
||||
<br />
|
||||
<br />
|
||||
|
@ -111,6 +117,7 @@
|
|||
private string _defaultvalue = string.Empty;
|
||||
private string _options = string.Empty;
|
||||
private string _validation = string.Empty;
|
||||
private string _autocomplete = string.Empty;
|
||||
private string _isrequired = "False";
|
||||
private string _isprivate = "False";
|
||||
private string createdby;
|
||||
|
@ -142,6 +149,7 @@
|
|||
_defaultvalue = profile.DefaultValue;
|
||||
_options = profile.Options;
|
||||
_validation = profile.Validation;
|
||||
_autocomplete = profile.Autocomplete;
|
||||
_isrequired = profile.IsRequired.ToString();
|
||||
_isprivate = profile.IsPrivate.ToString();
|
||||
createdby = profile.CreatedBy;
|
||||
|
@ -187,8 +195,10 @@
|
|||
profile.DefaultValue = _defaultvalue;
|
||||
profile.Options = _options;
|
||||
profile.Validation = _validation;
|
||||
profile.Autocomplete = _autocomplete;
|
||||
profile.IsRequired = (_isrequired == null ? false : Boolean.Parse(_isrequired));
|
||||
profile.IsPrivate = (_isprivate == null ? false : Boolean.Parse(_isprivate));
|
||||
|
||||
if (_profileid != -1)
|
||||
{
|
||||
profile = await ProfileService.UpdateProfileAsync(profile);
|
||||
|
|
|
@ -579,6 +579,11 @@
|
|||
if (logofileid != -1)
|
||||
{
|
||||
site.LogoFileId = logofileid;
|
||||
if (logofileid != _logofileid)
|
||||
{
|
||||
_logofileid = logofileid;
|
||||
refresh = true; // needs to be refreshed on client
|
||||
}
|
||||
}
|
||||
int? faviconFieldId = _faviconfilemanager.GetFileId();
|
||||
if (faviconFieldId == -1) faviconFieldId = null;
|
||||
|
@ -807,41 +812,55 @@
|
|||
}
|
||||
}
|
||||
|
||||
private async Task SaveAlias()
|
||||
{
|
||||
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
||||
{
|
||||
if (!string.IsNullOrEmpty(_aliasname))
|
||||
{
|
||||
var aliases = await AliasService.GetAliasesAsync();
|
||||
var alias = aliases.Where(item => item.Name == _aliasname).FirstOrDefault();
|
||||
bool unique = (alias == null || alias.AliasId == _aliasid);
|
||||
if (unique)
|
||||
{
|
||||
if (_aliasid == 0)
|
||||
{
|
||||
alias = new Alias { SiteId = PageState.Site.SiteId, TenantId = PageState.Site.TenantId, Name = _aliasname, IsDefault = bool.Parse(_defaultalias) };
|
||||
await AliasService.AddAliasAsync(alias);
|
||||
}
|
||||
else
|
||||
{
|
||||
alias = _aliases.Single(item => item.AliasId == _aliasid);
|
||||
alias.Name = _aliasname;
|
||||
alias.IsDefault = bool.Parse(_defaultalias);
|
||||
await AliasService.UpdateAliasAsync(alias);
|
||||
}
|
||||
}
|
||||
else // duplicate alias
|
||||
{
|
||||
AddModuleMessage(Localizer["Message.Aliases.Taken"], MessageType.Warning);
|
||||
}
|
||||
}
|
||||
await GetAliases();
|
||||
_aliasid = -1;
|
||||
_aliasname = "";
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
private async Task SaveAlias()
|
||||
{
|
||||
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
||||
{
|
||||
if (!string.IsNullOrEmpty(_aliasname))
|
||||
{
|
||||
var aliases = await AliasService.GetAliasesAsync();
|
||||
|
||||
int protocolIndex = _aliasname.IndexOf("://", StringComparison.OrdinalIgnoreCase);
|
||||
if (protocolIndex != -1)
|
||||
{
|
||||
_aliasname = _aliasname.Substring(protocolIndex + 3);
|
||||
}
|
||||
|
||||
var alias = aliases.FirstOrDefault(item => item.Name == _aliasname);
|
||||
|
||||
bool unique = (alias == null || alias.AliasId == _aliasid);
|
||||
|
||||
if (unique)
|
||||
{
|
||||
if (_aliasid == 0)
|
||||
{
|
||||
alias = new Alias { SiteId = PageState.Site.SiteId, TenantId = PageState.Site.TenantId, Name = _aliasname, IsDefault = bool.Parse(_defaultalias) };
|
||||
await AliasService.AddAliasAsync(alias);
|
||||
}
|
||||
else
|
||||
{
|
||||
alias = _aliases.SingleOrDefault(item => item.AliasId == _aliasid);
|
||||
if (alias != null)
|
||||
{
|
||||
alias.Name = _aliasname;
|
||||
alias.IsDefault = bool.Parse(_defaultalias);
|
||||
await AliasService.UpdateAliasAsync(alias);
|
||||
}
|
||||
}
|
||||
|
||||
await GetAliases();
|
||||
_aliasid = -1;
|
||||
_aliasname = "";
|
||||
StateHasChanged();
|
||||
}
|
||||
else // Duplicate alias
|
||||
{
|
||||
AddModuleMessage(Localizer["Message.Aliases.Taken"], MessageType.Warning);
|
||||
await ScrollToPageTop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task CancelAlias()
|
||||
{
|
||||
|
|
|
@ -48,11 +48,25 @@ else
|
|||
|
||||
private void Edit(string name)
|
||||
{
|
||||
NavigationManager.NavigateTo(PageState.Uri.Scheme + "://" + name + "/admin/site", true);
|
||||
if (PageState.Alias.Name == name)
|
||||
{
|
||||
NavigationManager.NavigateTo("/admin/site");
|
||||
}
|
||||
else
|
||||
{
|
||||
NavigationManager.NavigateTo(PageState.Uri.Scheme + "://" + name + "/admin/site", true);
|
||||
}
|
||||
}
|
||||
|
||||
private void Browse(string name)
|
||||
{
|
||||
NavigationManager.NavigateTo(PageState.Uri.Scheme + "://" + name, true);
|
||||
if (PageState.Alias.Name == name)
|
||||
{
|
||||
NavigationManager.NavigateTo("/");
|
||||
}
|
||||
else
|
||||
{
|
||||
NavigationManager.NavigateTo(PageState.Uri.Scheme + "://" + name, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -103,44 +103,91 @@
|
|||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="@p.Name" HelpText="@p.Description">@p.Title</Label>
|
||||
<div class="col-sm-9">
|
||||
@if (!string.IsNullOrEmpty(p.Options))
|
||||
@if (!string.IsNullOrEmpty(p.Options))
|
||||
{
|
||||
<select id="@p.Name" class="form-select" @onchange="@(e => ProfileChanged(e, p.Name))">
|
||||
@foreach (var option in p.Options.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
|
||||
{
|
||||
@if (GetProfileValue(p.Name, "") == option || (GetProfileValue(p.Name, "") == "" && p.DefaultValue == option))
|
||||
@if (!string.IsNullOrEmpty(p.Autocomplete))
|
||||
{
|
||||
<select id="@p.Name" class="form-select" @onchange="@(e => ProfileChanged(e, p.Name))" autocomplete="@p.Autocomplete">
|
||||
@foreach (var option in p.Options.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
|
||||
{
|
||||
<option value="@option" selected>@option</option>
|
||||
@if (GetProfileValue(p.Name, "") == option || (GetProfileValue(p.Name, "") == "" && p.DefaultValue == option))
|
||||
{
|
||||
<option value="@option" selected>@option</option>
|
||||
}
|
||||
else
|
||||
{
|
||||
<option value="@option">@option</option>
|
||||
}
|
||||
}
|
||||
else
|
||||
</select>
|
||||
}
|
||||
else
|
||||
{
|
||||
<select id="@p.Name" class="form-select" @onchange="@(e => ProfileChanged(e, p.Name))">
|
||||
@foreach (var option in p.Options.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
|
||||
{
|
||||
<option value="@option">@option</option>
|
||||
@if (GetProfileValue(p.Name, "") == option || (GetProfileValue(p.Name, "") == "" && p.DefaultValue == option))
|
||||
{
|
||||
<option value="@option" selected>@option</option>
|
||||
}
|
||||
else
|
||||
{
|
||||
<option value="@option">@option</option>
|
||||
}
|
||||
}
|
||||
}
|
||||
</select>
|
||||
</select>
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@if (p.Rows == 1)
|
||||
{
|
||||
@if (p.IsRequired)
|
||||
if (!string.IsNullOrEmpty(p.Autocomplete))
|
||||
{
|
||||
<input id="@p.Name" class="form-control" maxlength="@p.MaxLength" value="@GetProfileValue(p.Name, p.DefaultValue)" required @onchange="@(e => ProfileChanged(e, p.Name))" />
|
||||
@if (p.IsRequired)
|
||||
{
|
||||
<input id="@p.Name" class="form-control" maxlength="@p.MaxLength" value="@GetProfileValue(p.Name, p.DefaultValue)" required @onchange="@(e => ProfileChanged(e, p.Name))" autocomplete="@p.Autocomplete" />
|
||||
}
|
||||
else
|
||||
{
|
||||
<input id="@p.Name" class="form-control" maxlength="@p.MaxLength" value="@GetProfileValue(p.Name, p.DefaultValue)" @onchange="@(e => ProfileChanged(e, p.Name))" autocomplete="@p.Autocomplete" />
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
<input id="@p.Name" class="form-control" maxlength="@p.MaxLength" value="@GetProfileValue(p.Name, p.DefaultValue)" @onchange="@(e => ProfileChanged(e, p.Name))" />
|
||||
@if (p.IsRequired)
|
||||
{
|
||||
<input id="@p.Name" class="form-control" maxlength="@p.MaxLength" value="@GetProfileValue(p.Name, p.DefaultValue)" required @onchange="@(e => ProfileChanged(e, p.Name))" />
|
||||
}
|
||||
else
|
||||
{
|
||||
<input id="@p.Name" class="form-control" maxlength="@p.MaxLength" value="@GetProfileValue(p.Name, p.DefaultValue)" @onchange="@(e => ProfileChanged(e, p.Name))" />
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@if (p.IsRequired)
|
||||
if (!string.IsNullOrEmpty(p.Autocomplete))
|
||||
{
|
||||
<textarea id="@p.Name" class="form-control" maxlength="@p.MaxLength" rows="@p.Rows" value="@GetProfileValue(p.Name, p.DefaultValue)" required @onchange="@(e => ProfileChanged(e, p.Name))"></textarea>
|
||||
@if (p.IsRequired)
|
||||
{
|
||||
<textarea id="@p.Name" class="form-control" maxlength="@p.MaxLength" rows="@p.Rows" value="@GetProfileValue(p.Name, p.DefaultValue)" required @onchange="@(e => ProfileChanged(e, p.Name))" autocomplete="@p.Autocomplete"></textarea>
|
||||
}
|
||||
else
|
||||
{
|
||||
<textarea id="@p.Name" class="form-control" maxlength="@p.MaxLength" rows="@p.Rows" value="@GetProfileValue(p.Name, p.DefaultValue)" @onchange="@(e => ProfileChanged(e, p.Name))" autocomplete="@p.Autocomplete"></textarea>
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
<textarea id="@p.Name" class="form-control" maxlength="@p.MaxLength" rows="@p.Rows" value="@GetProfileValue(p.Name, p.DefaultValue)" @onchange="@(e => ProfileChanged(e, p.Name))"></textarea>
|
||||
@if (p.IsRequired)
|
||||
{
|
||||
<textarea id="@p.Name" class="form-control" maxlength="@p.MaxLength" rows="@p.Rows" value="@GetProfileValue(p.Name, p.DefaultValue)" required @onchange="@(e => ProfileChanged(e, p.Name))"></textarea>
|
||||
}
|
||||
else
|
||||
{
|
||||
<textarea id="@p.Name" class="form-control" maxlength="@p.MaxLength" rows="@p.Rows" value="@GetProfileValue(p.Name, p.DefaultValue)" @onchange="@(e => ProfileChanged(e, p.Name))"></textarea>
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -360,10 +407,11 @@
|
|||
photofileid = -1;
|
||||
photo = null;
|
||||
}
|
||||
var sitesettings = await SettingService.GetSiteSettingsAsync(SiteState.Alias.SiteId);
|
||||
_ImageFiles = SettingService.GetSetting(settings, "ImageFiles", Constants.ImageFiles);
|
||||
|
||||
settings = await SettingService.GetUserSettingsAsync(PageState.User.UserId);
|
||||
var sitesettings = await SettingService.GetSiteSettingsAsync(PageState.Site.SiteId);
|
||||
_ImageFiles = SettingService.GetSetting(settings, "ImageFiles", Constants.ImageFiles);
|
||||
_ImageFiles = (string.IsNullOrEmpty(_ImageFiles)) ? Constants.ImageFiles : _ImageFiles;
|
||||
|
||||
await LoadNotificationsAsync();
|
||||
|
||||
|
@ -561,12 +609,12 @@
|
|||
await NotificationService.DeleteNotificationAsync(Notification.NotificationId);
|
||||
}
|
||||
await logger.LogInformation("Notification Deleted {Notification}", Notification);
|
||||
}
|
||||
}
|
||||
await logger.LogInformation("Notifications Permanently Deleted");
|
||||
await LoadNotificationsAsync();
|
||||
ModuleInstance.HideProgressIndicator();
|
||||
|
||||
StateHasChanged();
|
||||
StateHasChanged();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -574,21 +622,19 @@
|
|||
AddModuleMessage(ex.Message, MessageType.Error);
|
||||
ModuleInstance.HideProgressIndicator();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void TogglePassword()
|
||||
{
|
||||
if (_passwordtype == "password")
|
||||
{
|
||||
_passwordtype = "text";
|
||||
_togglepassword = SharedLocalizer["HidePassword"];
|
||||
}
|
||||
else
|
||||
{
|
||||
_passwordtype = "password";
|
||||
_togglepassword = SharedLocalizer["ShowPassword"];
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
if (_passwordtype == "password")
|
||||
{
|
||||
_passwordtype = "text";
|
||||
_togglepassword = SharedLocalizer["HidePassword"];
|
||||
}
|
||||
else
|
||||
{
|
||||
_passwordtype = "password";
|
||||
_togglepassword = SharedLocalizer["ShowPassword"];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,13 +34,13 @@ else
|
|||
<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>
|
||||
<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 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>
|
||||
<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>
|
||||
|
||||
|
@ -60,8 +60,8 @@ else
|
|||
</Header>
|
||||
<Row>
|
||||
<td>@context.Role.Name</td>
|
||||
<td>@context.EffectiveDate</td>
|
||||
<td>@context.ExpiryDate</td>
|
||||
<td>@Utilities.UtcAsLocalDate(context.EffectiveDate)</td>
|
||||
<td>@Utilities.UtcAsLocalDate(context.ExpiryDate)</td>
|
||||
<td>
|
||||
<ActionDialog Header="Remove Role" Message="@string.Format(Localizer["Confirm.User.RemoveRole"], context.Role.Name)" Action="Delete" Security="SecurityAccessLevel.Edit" Class="btn btn-danger" OnClick="@(async () => await DeleteUserRole(context.UserRoleId))" Disabled="@(context.Role.IsAutoAssigned || (context.Role.Name == RoleNames.Host && userid == PageState.User.UserId))" ResourceKey="DeleteUserRole" />
|
||||
</td>
|
||||
|
@ -75,8 +75,8 @@ else
|
|||
private string name = string.Empty;
|
||||
private List<Role> roles;
|
||||
private int roleid = -1;
|
||||
private DateTime? effectivedate = null;
|
||||
private DateTime? expirydate = null;
|
||||
private DateTime? _effectivedate = null;
|
||||
private DateTime? _expirydate = null;
|
||||
private List<UserRole> userroles;
|
||||
|
||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
|
||||
|
@ -92,7 +92,7 @@ else
|
|||
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
||||
{
|
||||
roles = await RoleService.GetRolesAsync(PageState.Site.SiteId, true);
|
||||
roles.RemoveAll(item => item.Name == RoleNames.Everyone || item.Name == RoleNames.Unauthenticated);
|
||||
roles.RemoveAll(item => item.Name == RoleNames.Everyone || item.Name == RoleNames.Unauthenticated);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -113,6 +113,7 @@ else
|
|||
try
|
||||
{
|
||||
userroles = await UserRoleService.GetUserRolesAsync(PageState.Site.SiteId, userid);
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -127,11 +128,16 @@ else
|
|||
{
|
||||
if (roleid != -1)
|
||||
{
|
||||
if (!Utilities.ValidateEffectiveExpiryDates(_effectivedate, _expirydate))
|
||||
{
|
||||
AddModuleMessage(SharedLocalizer["Message.EffectiveExpiryDateError"], MessageType.Warning);
|
||||
return;
|
||||
}
|
||||
var userrole = userroles.Where(item => item.UserId == userid && item.RoleId == roleid).FirstOrDefault();
|
||||
if (userrole != null)
|
||||
{
|
||||
userrole.EffectiveDate = effectivedate;
|
||||
userrole.ExpiryDate = expirydate;
|
||||
userrole.EffectiveDate = _effectivedate;
|
||||
userrole.ExpiryDate = _expirydate;
|
||||
await UserRoleService.UpdateUserRoleAsync(userrole);
|
||||
}
|
||||
else
|
||||
|
@ -139,15 +145,15 @@ else
|
|||
userrole = new UserRole();
|
||||
userrole.UserId = userid;
|
||||
userrole.RoleId = roleid;
|
||||
userrole.EffectiveDate = effectivedate;
|
||||
userrole.ExpiryDate = expirydate;
|
||||
userrole.EffectiveDate = Utilities.UtcAsLocalDate(_effectivedate);
|
||||
userrole.ExpiryDate = Utilities.UtcAsLocalDate(_expirydate);
|
||||
await UserRoleService.AddUserRoleAsync(userrole);
|
||||
}
|
||||
|
||||
await logger.LogInformation("User Assigned To Role {UserRole}", userrole);
|
||||
AddModuleMessage(Localizer["Success.User.AssignRole"], MessageType.Success);
|
||||
await GetUserRoles();
|
||||
StateHasChanged();
|
||||
StateHasChanged();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
@inject IFolderService FolderService
|
||||
@inject IFileService FileService
|
||||
@inject ISettingService SettingService
|
||||
@inject IUserService UserService
|
||||
@inject IStringLocalizer<FileManager> Localizer
|
||||
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
||||
|
||||
|
@ -344,7 +345,7 @@
|
|||
_message = string.Empty;
|
||||
var interop = new Interop(JSRuntime);
|
||||
var uploads = await interop.GetFiles(_fileinputid);
|
||||
|
||||
|
||||
if (uploads.Length > 0)
|
||||
{
|
||||
string restricted = "";
|
||||
|
@ -370,7 +371,12 @@
|
|||
// upload the files
|
||||
var posturl = Utilities.TenantUrl(PageState.Alias, "/api/file/upload");
|
||||
var folder = (Folder == Constants.PackagesFolder) ? Folder : FolderId.ToString();
|
||||
await interop.UploadFiles(posturl, folder, _guid, SiteState.AntiForgeryToken);
|
||||
var jwt = "";
|
||||
if (PageState.Runtime == Shared.Runtime.Hybrid)
|
||||
{
|
||||
jwt = await UserService.GetTokenAsync();
|
||||
}
|
||||
await interop.UploadFiles(posturl, folder, _guid, SiteState.AntiForgeryToken, jwt);
|
||||
|
||||
// uploading is asynchronous so we need to poll to determine if uploads are completed
|
||||
var success = true;
|
||||
|
|
|
@ -162,27 +162,31 @@
|
|||
_richhtml = Content;
|
||||
_rawhtml = Content;
|
||||
_originalrawhtml = _rawhtml; // preserve for comparison later
|
||||
_originalrichhtml = "";
|
||||
}
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
await base.OnAfterRenderAsync(firstRender);
|
||||
|
||||
var interop = new RichTextEditorInterop(JSRuntime);
|
||||
|
||||
if (firstRender)
|
||||
if (AllowRichText)
|
||||
{
|
||||
await interop.CreateEditor(
|
||||
_editorElement,
|
||||
_toolBar,
|
||||
ReadOnly,
|
||||
Placeholder,
|
||||
Theme,
|
||||
DebugLevel);
|
||||
var interop = new RichTextEditorInterop(JSRuntime);
|
||||
|
||||
if (firstRender)
|
||||
{
|
||||
await interop.CreateEditor(
|
||||
_editorElement,
|
||||
_toolBar,
|
||||
ReadOnly,
|
||||
Placeholder,
|
||||
Theme,
|
||||
DebugLevel);
|
||||
}
|
||||
|
||||
await interop.LoadEditorContent(_editorElement, _richhtml);
|
||||
|
||||
if (AllowRichText)
|
||||
if (string.IsNullOrEmpty(_originalrichhtml))
|
||||
{
|
||||
// preserve a copy of the rich text content (Quill sanitizes content so we need to retrieve it from the editor)
|
||||
_originalrichhtml = await interop.GetHtml(_editorElement);
|
||||
|
@ -256,7 +260,8 @@
|
|||
{
|
||||
var interop = new RichTextEditorInterop(JSRuntime);
|
||||
await interop.InsertImage(_editorElement, file.Url, ((!string.IsNullOrEmpty(file.Description)) ? file.Description : file.Name));
|
||||
_richfilemanager = false;
|
||||
_richhtml = await interop.GetHtml(_editorElement);
|
||||
_richfilemanager = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -15,17 +15,20 @@
|
|||
}
|
||||
|
||||
@code {
|
||||
private string content = "";
|
||||
private string content = "";
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
try
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
var htmltext = await HtmlTextService.GetHtmlTextAsync(ModuleState.ModuleId);
|
||||
if (htmltext != null)
|
||||
if (ShouldRender())
|
||||
{
|
||||
content = htmltext.Content;
|
||||
content = Utilities.FormatContent(content, PageState.Alias, "render");
|
||||
var htmltext = await HtmlTextService.GetHtmlTextAsync(ModuleState.ModuleId);
|
||||
if (htmltext != null)
|
||||
{
|
||||
content = htmltext.Content;
|
||||
content = Utilities.FormatContent(content, PageState.Alias, "render");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
|
@ -113,6 +113,11 @@ namespace Oqtane.Modules
|
|||
}
|
||||
}
|
||||
|
||||
protected override bool ShouldRender()
|
||||
{
|
||||
return PageState?.RenderId == ModuleState?.RenderId;
|
||||
}
|
||||
|
||||
// path method
|
||||
|
||||
public string ModulePath()
|
||||
|
@ -266,6 +271,7 @@ namespace Oqtane.Modules
|
|||
|
||||
public void AddModuleMessage(string message, MessageType type, string position)
|
||||
{
|
||||
ClearModuleMessage();
|
||||
ModuleInstance.AddModuleMessage(message, type, position);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<TargetFramework>net8.0</TargetFramework>
|
||||
<OutputType>Exe</OutputType>
|
||||
<Configurations>Debug;Release</Configurations>
|
||||
<Version>5.0.1</Version>
|
||||
<Version>5.0.2</Version>
|
||||
<Product>Oqtane</Product>
|
||||
<Authors>Shaun Walker</Authors>
|
||||
<Company>.NET Foundation</Company>
|
||||
|
@ -12,7 +12,7 @@
|
|||
<Copyright>.NET Foundation</Copyright>
|
||||
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
||||
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.1</PackageReleaseNotes>
|
||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.2</PackageReleaseNotes>
|
||||
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
||||
<RepositoryType>Git</RepositoryType>
|
||||
<RootNamespace>Oqtane</RootNamespace>
|
||||
|
@ -21,10 +21,10 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="8.0.0" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="8.0.1" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.0" />
|
||||
<PackageReference Include="System.Net.Http.Json" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Localization" Version="2.2.0" />
|
||||
|
|
|
@ -192,4 +192,7 @@
|
|||
<data name="Once" xml:space="preserve">
|
||||
<value>Execute Once</value>
|
||||
</data>
|
||||
<data name="Message.StartEndDateError" xml:space="preserve">
|
||||
<value>Start Date cannot be after End Date.</value>
|
||||
</data>
|
||||
</root>
|
|
@ -130,16 +130,16 @@
|
|||
<value>Please Note That The Module Creator Is Only Intended To Be Used In A Development Environment</value>
|
||||
</data>
|
||||
<data name="Message.Require.ValidName" xml:space="preserve">
|
||||
<value>You Must Provide A Valid Owner Name And Module Name ( ie. No Punctuation Or Spaces And The Values Cannot Be The Same ) And Choose A Template</value>
|
||||
<value>You Must Provide A Valid Owner Name And Module Name ( ie. No Punctuation Or Spaces And The Values Cannot Be The Same Or Contain The Word "Oqtane" ) And Choose A Template</value>
|
||||
</data>
|
||||
<data name="Message.Require.ValidDescription" xml:space="preserve">
|
||||
<value>You Must Provide A Valid Description (ie. No Punctuation)</value>
|
||||
</data>
|
||||
<data name="OwnerName.HelpText" xml:space="preserve">
|
||||
<value>Enter the name of the organization who is developing this module. It should not contain spaces or punctuation.</value>
|
||||
<value>Enter the name of the organization who is developing this module. It should not contain spaces or punctuation or contain the word "oqtane".</value>
|
||||
</data>
|
||||
<data name="ModuleName.HelpText" xml:space="preserve">
|
||||
<value>Enter a name for this module. It should not contain spaces or punctuation.</value>
|
||||
<value>Enter a name for this module. It should not contain spaces or punctuation or contain the word "oqtane".</value>
|
||||
</data>
|
||||
<data name="Description.HelpText" xml:space="preserve">
|
||||
<value>Enter a short description for the module</value>
|
||||
|
@ -171,4 +171,4 @@
|
|||
<data name="Success.Module.Create" xml:space="preserve">
|
||||
<value>The Source Code For Your Module Has Been Created At The Location Specified Below And Must Be Compiled In Order To Make It Functional. Once It Has Been Compiled You Must <a href={0}>Restart</a> Your Application To Activate The Module.</value>
|
||||
</data>
|
||||
</root>
|
||||
</root>
|
||||
|
|
|
@ -165,4 +165,16 @@
|
|||
<data name="Pane.Text" xml:space="preserve">
|
||||
<value>Pane:</value>
|
||||
</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>
|
|
@ -255,4 +255,16 @@
|
|||
<data name="Theme.Heading" xml:space="preserve">
|
||||
<value>Theme Settings</value>
|
||||
</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>
|
|
@ -285,4 +285,16 @@
|
|||
<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>
|
||||
</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>
|
|
@ -1,4 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
@ -195,4 +195,10 @@
|
|||
<data name="Rows.Text" xml:space="preserve">
|
||||
<value>Rows: </value>
|
||||
</data>
|
||||
<data name="Autocomplete.HelpText" xml:space="preserve">
|
||||
<value>The HTML autocomplete attribute allows you to specify browser behavior for automated user assistance in filling out form field values. Allowable values are blank (default), 'on', 'off', or any value from the standardized taxonomy defined for this attribute.</value>
|
||||
</data>
|
||||
<data name="Autocomplete.Text" xml:space="preserve">
|
||||
<value>Autocomplete: </value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
|
@ -438,4 +438,7 @@
|
|||
<data name="Test" xml:space="preserve">
|
||||
<value>Test</value>
|
||||
</data>
|
||||
<data name="Message.EffectiveExpiryDateError" xml:space="preserve">
|
||||
<value>Effective Date cannot be after Expiry Date.</value>
|
||||
</data>
|
||||
</root>
|
|
@ -5,7 +5,7 @@ using System.Threading.Tasks;
|
|||
namespace Oqtane.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Service to retreive and store modules (<see cref="Module"/>)
|
||||
/// Service to retrieve and store modules (<see cref="Module"/>)
|
||||
/// </summary>
|
||||
public interface IModuleService
|
||||
{
|
||||
|
|
|
@ -5,7 +5,7 @@ using System.Threading.Tasks;
|
|||
namespace Oqtane.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Service to store and retreive notifications (<see cref="Notification"/>)
|
||||
/// Service to store and retrieve notifications (<see cref="Notification"/>)
|
||||
/// </summary>
|
||||
public interface INotificationService
|
||||
{
|
||||
|
|
|
@ -4,7 +4,7 @@ using System.Threading.Tasks;
|
|||
namespace Oqtane.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Service to store and retreive a <see cref="PageModule"/>
|
||||
/// Service to store and retrieve a <see cref="PageModule"/>
|
||||
/// </summary>
|
||||
public interface IPageModuleService
|
||||
{
|
||||
|
|
|
@ -5,7 +5,7 @@ using System.Threading.Tasks;
|
|||
namespace Oqtane.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Service to store and retreive <see cref="Profile"/> entries
|
||||
/// Service to store and retrieve <see cref="Profile"/> entries
|
||||
/// </summary>
|
||||
public interface IProfileService
|
||||
{
|
||||
|
|
|
@ -7,7 +7,7 @@ using System.Threading.Tasks;
|
|||
namespace Oqtane.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Service to store and retreive <see cref="Site"/> entries
|
||||
/// Service to store and retrieve <see cref="Site"/> entries
|
||||
/// </summary>
|
||||
public interface ISiteService
|
||||
{
|
||||
|
|
|
@ -5,7 +5,7 @@ using System.Threading.Tasks;
|
|||
namespace Oqtane.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Service to retreive <see cref="SiteTemplate"/> entries
|
||||
/// Service to retrieve <see cref="SiteTemplate"/> entries
|
||||
/// </summary>
|
||||
public interface ISiteTemplateService
|
||||
{
|
||||
|
|
|
@ -17,7 +17,7 @@ namespace Oqtane.Services
|
|||
Task<List<Theme>> GetThemesAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Returns a specific thenme
|
||||
/// Returns a specific theme
|
||||
/// </summary>
|
||||
/// <param name="themeId"></param>
|
||||
/// <param name="siteId"></param>
|
||||
|
@ -56,7 +56,7 @@ namespace Oqtane.Services
|
|||
List<ThemeControl> GetContainerControls(List<Theme> themes, string themeControlType);
|
||||
|
||||
/// <summary>
|
||||
/// Updates a existing theem
|
||||
/// Updates a existing theme
|
||||
/// </summary>
|
||||
/// <param name="theme"></param>
|
||||
/// <returns></returns>
|
||||
|
|
|
@ -242,7 +242,7 @@ namespace Oqtane.Services
|
|||
|
||||
private async Task Log(string uri, string method, string status, string message, params object[] args)
|
||||
{
|
||||
if (_siteState.Alias != null && !uri.StartsWith(CreateApiUrl("Log")))
|
||||
if (_siteState?.Alias != null && !uri.StartsWith(CreateApiUrl("Log")))
|
||||
{
|
||||
var log = new Log();
|
||||
log.SiteId = _siteState.Alias.SiteId;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Oqtane.Models;
|
||||
|
||||
namespace Oqtane.Themes
|
||||
|
@ -8,5 +8,9 @@ namespace Oqtane.Themes
|
|||
[CascadingParameter]
|
||||
protected Module ModuleState { get; set; }
|
||||
|
||||
protected override bool ShouldRender()
|
||||
{
|
||||
return PageState?.RenderId == ModuleState?.RenderId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,11 +56,12 @@ namespace Oqtane.Themes.Controls
|
|||
var url = route.PathAndQuery;
|
||||
|
||||
// verify if anonymous users can access page
|
||||
if (!UserSecurity.IsAuthorized(null, PermissionNames.View, PageState.Page.PermissionList))
|
||||
if (!UserSecurity.IsAuthorized(null, PermissionNames.View, PageState.Page.PermissionList) || !Utilities.IsPageModuleVisible(PageState.Page.EffectiveDate, PageState.Page.ExpiryDate))
|
||||
{
|
||||
url = PageState.Alias.Path;
|
||||
}
|
||||
|
||||
|
||||
if (PageState.Runtime == Shared.Runtime.Hybrid)
|
||||
{
|
||||
// hybrid apps utilize an interactive logout
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
@namespace Oqtane.UI
|
||||
@inject SiteState SiteState
|
||||
|
||||
@if (_visible)
|
||||
@if (ComponentType != null && _visible)
|
||||
{
|
||||
<a id="@ModuleState.PageModuleId.ToString()"></a>
|
||||
<CascadingValue Value="@ModuleState">
|
||||
|
@ -17,12 +17,11 @@
|
|||
<DynamicComponent Type="@ComponentType"></DynamicComponent>
|
||||
}
|
||||
</CascadingValue>
|
||||
|
||||
}
|
||||
|
||||
@code {
|
||||
private bool _visible = true;
|
||||
private bool _useadminborder = false;
|
||||
private bool _visible = true;
|
||||
private bool _useadminborder = false;
|
||||
public Type ComponentType { get; set; }
|
||||
|
||||
[CascadingParameter]
|
||||
|
@ -31,12 +30,17 @@
|
|||
[Parameter]
|
||||
public Module ModuleState { get; set; }
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
((INotifyPropertyChanged)SiteState.Properties).PropertyChanged += PropertyChanged;
|
||||
}
|
||||
|
||||
protected override void OnParametersSet()
|
||||
protected override bool ShouldRender()
|
||||
{
|
||||
return PageState?.RenderId == ModuleState?.RenderId;
|
||||
}
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
((INotifyPropertyChanged)SiteState.Properties).PropertyChanged += PropertyChanged;
|
||||
}
|
||||
|
||||
protected override void OnParametersSet()
|
||||
{
|
||||
string container = ModuleState.ContainerType;
|
||||
if (PageState.ModuleId != -1 && PageState.Route.Action != "" && ModuleState.UseAdminContainer)
|
||||
|
@ -53,7 +57,10 @@
|
|||
_useadminborder = false;
|
||||
}
|
||||
|
||||
ComponentType = Type.GetType(container) ?? Type.GetType(Constants.DefaultContainer);
|
||||
if (ShouldRender())
|
||||
{
|
||||
ComponentType = Type.GetType(container) ?? Type.GetType(Constants.DefaultContainer);
|
||||
}
|
||||
}
|
||||
|
||||
private void PropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
|
@ -72,6 +79,4 @@
|
|||
{
|
||||
((INotifyPropertyChanged)SiteState.Properties).PropertyChanged -= PropertyChanged;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -198,13 +198,13 @@ namespace Oqtane.UI
|
|||
}
|
||||
}
|
||||
|
||||
public Task UploadFiles(string posturl, string folder, string id, string antiforgerytoken)
|
||||
public Task UploadFiles(string posturl, string folder, string id, string antiforgerytoken, string jwt)
|
||||
{
|
||||
try
|
||||
{
|
||||
_jsRuntime.InvokeVoidAsync(
|
||||
"Oqtane.Interop.uploadFiles",
|
||||
posturl, folder, id, antiforgerytoken);
|
||||
posturl, folder, id, antiforgerytoken, jwt);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
catch
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
@if (CurrentException is null)
|
||||
{
|
||||
if (_messagePosition == "top")
|
||||
if (_message != "" && _messagePosition == "top")
|
||||
{
|
||||
<ModuleMessage Message="@_message" Type="@_messageType" />
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
|||
<div class="app-progress-indicator"></div>
|
||||
}
|
||||
}
|
||||
if (_messagePosition == "bottom")
|
||||
if (_message != "" && _messagePosition == "bottom")
|
||||
{
|
||||
<ModuleMessage Message="@_message" Type="@_messageType" />
|
||||
}
|
||||
|
@ -48,27 +48,35 @@ else
|
|||
|
||||
private ModuleMessage ModuleMessage { get; set; }
|
||||
|
||||
protected override bool ShouldRender()
|
||||
{
|
||||
return PageState?.RenderId == ModuleState?.RenderId;
|
||||
}
|
||||
|
||||
protected override void OnParametersSet()
|
||||
{
|
||||
_message = "";
|
||||
if (!string.IsNullOrEmpty(ModuleState.ModuleType))
|
||||
if (ShouldRender())
|
||||
{
|
||||
ModuleType = Type.GetType(ModuleState.ModuleType);
|
||||
if (ModuleType != null)
|
||||
if (!string.IsNullOrEmpty(ModuleState.ModuleType))
|
||||
{
|
||||
ModuleParameters = new Dictionary<string, object> { { "ModuleInstance", this } };
|
||||
return;
|
||||
ModuleType = Type.GetType(ModuleState.ModuleType);
|
||||
if (ModuleType != null)
|
||||
{
|
||||
ModuleParameters = new Dictionary<string, object> { { "ModuleInstance", this } };
|
||||
return;
|
||||
}
|
||||
// module does not exist with typename specified
|
||||
_message = string.Format(Localizer["Error.Module.InvalidName"], Utilities.GetTypeNameLastSegment(ModuleState.ModuleType, 0));
|
||||
_messageType = MessageType.Error;
|
||||
_messagePosition = "top";
|
||||
}
|
||||
else
|
||||
{
|
||||
_message = string.Format(Localizer["Error.Module.InvalidType"], ModuleState.ModuleDefinitionName);
|
||||
_messageType = MessageType.Error;
|
||||
_messagePosition = "top";
|
||||
}
|
||||
// module does not exist with typename specified
|
||||
_message = string.Format(Localizer["Error.Module.InvalidName"], Utilities.GetTypeNameLastSegment(ModuleState.ModuleType, 0));
|
||||
_messageType = MessageType.Error;
|
||||
_messagePosition = "top";
|
||||
}
|
||||
else
|
||||
{
|
||||
_message = string.Format(Localizer["Error.Module.InvalidType"], ModuleState.ModuleDefinitionName);
|
||||
_messageType = MessageType.Error;
|
||||
_messagePosition = "top";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Oqtane.Models;
|
||||
|
||||
namespace Oqtane.UI
|
||||
|
@ -25,6 +23,7 @@ namespace Oqtane.UI
|
|||
public string RemoteIPAddress { get; set; }
|
||||
public string ReturnUrl { get; set; }
|
||||
public bool IsInternalNavigation { get; set; }
|
||||
public Guid RenderId { get; set; }
|
||||
|
||||
public List<Page> Pages
|
||||
{
|
||||
|
|
|
@ -45,6 +45,12 @@ else
|
|||
{
|
||||
foreach (Module module in PageState.Modules.Where(item => item.PageId == PageState.Page.PageId))
|
||||
{
|
||||
// set renderid - this allows the framework to determine which components should be rendered when PageState changes
|
||||
if (module.RenderId != PageState.RenderId)
|
||||
{
|
||||
module.RenderId = PageState.RenderId;
|
||||
}
|
||||
|
||||
var pane = module.Pane;
|
||||
if (module.ModuleId == PageState.ModuleId && PageState.Action != Constants.DefaultAction)
|
||||
{
|
||||
|
@ -95,7 +101,7 @@ else
|
|||
|
||||
if (authorized)
|
||||
{
|
||||
CreateComponent(builder, module);
|
||||
CreateComponent(builder, module, module.PageModuleId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -106,7 +112,7 @@ else
|
|||
// check if user is authorized to view module
|
||||
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, module.PermissionList))
|
||||
{
|
||||
CreateComponent(builder, module);
|
||||
CreateComponent(builder, module, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -115,11 +121,14 @@ else
|
|||
};
|
||||
}
|
||||
|
||||
private void CreateComponent(RenderTreeBuilder builder, Module module)
|
||||
private void CreateComponent(RenderTreeBuilder builder, Module module, int key)
|
||||
{
|
||||
builder.OpenComponent(0, Type.GetType(Constants.ContainerComponent));
|
||||
builder.AddAttribute(1, "ModuleState", module);
|
||||
builder.SetKey(module.PageModuleId);
|
||||
if (key != -1)
|
||||
{
|
||||
builder.SetKey(module.PageModuleId);
|
||||
}
|
||||
builder.CloseComponent();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -262,7 +262,7 @@
|
|||
if (page != null)
|
||||
{
|
||||
// check if user is authorized to view page
|
||||
if (UserSecurity.IsAuthorized(user, PermissionNames.View, page.PermissionList))
|
||||
if (UserSecurity.IsAuthorized(user, PermissionNames.View, page.PermissionList) && (Utilities.IsPageModuleVisible(page.EffectiveDate, page.ExpiryDate) || UserSecurity.IsAuthorized(user, PermissionNames.Edit, page.PermissionList)))
|
||||
{
|
||||
// load additional metadata for current page
|
||||
page = ProcessPage(page, site, user, SiteState.Alias);
|
||||
|
@ -289,12 +289,22 @@
|
|||
VisitorId = VisitorId,
|
||||
RemoteIPAddress = SiteState.RemoteIPAddress,
|
||||
ReturnUrl = returnurl,
|
||||
IsInternalNavigation = _isInternalNavigation
|
||||
IsInternalNavigation = _isInternalNavigation,
|
||||
RenderId = Guid.NewGuid()
|
||||
};
|
||||
|
||||
OnStateChange?.Invoke(_pagestate);
|
||||
await ScrollToFragment(_pagestate.Uri);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Need to redirect 404 as page doesnot exist in a Permission or Timeframe
|
||||
if (route.PagePath != "404")
|
||||
{
|
||||
// redirect to 404 page
|
||||
NavigationManager.NavigateTo(Utilities.NavigateUrl(SiteState.Alias.Path, "404", ""));
|
||||
}
|
||||
}
|
||||
}
|
||||
else // page not found
|
||||
{
|
||||
|
@ -307,7 +317,7 @@
|
|||
}
|
||||
else // not mapped
|
||||
{
|
||||
if (user == null)
|
||||
if (user == null && Utilities.IsPageModuleVisible(page.EffectiveDate, page.ExpiryDate))
|
||||
{
|
||||
// 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)));
|
||||
|
|
|
@ -75,6 +75,14 @@ namespace Oqtane.Database.MySQL
|
|||
return dr;
|
||||
}
|
||||
|
||||
public override string RewriteName(string name, bool isQuery)
|
||||
{
|
||||
if (name.ToLower() == "rows" && isQuery)
|
||||
{
|
||||
name = $"`{name}`"; // escape reserved word in SQL query
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
public override DbContextOptionsBuilder UseDatabase(DbContextOptionsBuilder optionsBuilder, string connectionString)
|
||||
{
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Version>5.0.1</Version>
|
||||
<Version>5.0.2</Version>
|
||||
<Product>Oqtane</Product>
|
||||
<Authors>Shaun Walker</Authors>
|
||||
<Company>.NET Foundation</Company>
|
||||
|
@ -10,7 +10,7 @@
|
|||
<Copyright>.NET Foundation</Copyright>
|
||||
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
||||
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.1</PackageReleaseNotes>
|
||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.2</PackageReleaseNotes>
|
||||
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
||||
<RepositoryType>Git</RepositoryType>
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
|
@ -33,8 +33,8 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MySql.EntityFrameworkCore" Version="8.0.0-preview" />
|
||||
<PackageReference Include="MySql.Data" Version="8.2.0" />
|
||||
<PackageReference Include="MySql.EntityFrameworkCore" Version="8.0.0" />
|
||||
<PackageReference Include="MySql.Data" Version="8.3.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Version>5.0.1</Version>
|
||||
<Version>5.0.2</Version>
|
||||
<Product>Oqtane</Product>
|
||||
<Authors>Shaun Walker</Authors>
|
||||
<Company>.NET Foundation</Company>
|
||||
|
@ -10,7 +10,7 @@
|
|||
<Copyright>.NET Foundation</Copyright>
|
||||
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
||||
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.1</PackageReleaseNotes>
|
||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.2</PackageReleaseNotes>
|
||||
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
||||
<RepositoryType>Git</RepositoryType>
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
|
@ -33,8 +33,8 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="EFCore.NamingConventions" Version="8.0.0-rc.2" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="8.0.0" />
|
||||
<PackageReference Include="EFCore.NamingConventions" Version="8.0.2" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="8.0.1" />
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
@ -87,6 +87,11 @@ namespace Oqtane.Database.PostgreSQL
|
|||
return _rewriter.RewriteName(name);
|
||||
}
|
||||
|
||||
public override string RewriteName(string name, bool isQuery)
|
||||
{
|
||||
return _rewriter.RewriteName(name);
|
||||
}
|
||||
|
||||
public override string RewriteValue(string value, string type)
|
||||
{
|
||||
if (type == "bool")
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Version>5.0.1</Version>
|
||||
<Version>5.0.2</Version>
|
||||
<Product>Oqtane</Product>
|
||||
<Authors>Shaun Walker</Authors>
|
||||
<Company>.NET Foundation</Company>
|
||||
|
@ -10,7 +10,7 @@
|
|||
<Copyright>.NET Foundation</Copyright>
|
||||
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
||||
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.1</PackageReleaseNotes>
|
||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.2</PackageReleaseNotes>
|
||||
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
||||
<RepositoryType>Git</RepositoryType>
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
|
@ -33,7 +33,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Version>5.0.1</Version>
|
||||
<Version>5.0.2</Version>
|
||||
<Product>Oqtane</Product>
|
||||
<Authors>Shaun Walker</Authors>
|
||||
<Company>.NET Foundation</Company>
|
||||
|
@ -10,7 +10,7 @@
|
|||
<Copyright>.NET Foundation</Copyright>
|
||||
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
||||
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.1</PackageReleaseNotes>
|
||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.2</PackageReleaseNotes>
|
||||
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
||||
<RepositoryType>Git</RepositoryType>
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
|
@ -33,7 +33,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<!-- <TargetFrameworks>net8.0-android;net8.0-ios;net8.0-maccatalyst</TargetFrameworks> -->
|
||||
<!-- <TargetFrameworks>$(TargetFrameworks);net8.0-tizen</TargetFrameworks> -->
|
||||
<OutputType>Exe</OutputType>
|
||||
<Version>5.0.1</Version>
|
||||
<Version>5.0.2</Version>
|
||||
<Product>Oqtane</Product>
|
||||
<Authors>Shaun Walker</Authors>
|
||||
<Company>.NET Foundation</Company>
|
||||
|
@ -14,7 +14,7 @@
|
|||
<Copyright>.NET Foundation</Copyright>
|
||||
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
||||
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.1</PackageReleaseNotes>
|
||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.2</PackageReleaseNotes>
|
||||
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
||||
<RepositoryType>Git</RepositoryType>
|
||||
<RootNamespace>Oqtane.Maui</RootNamespace>
|
||||
|
@ -31,7 +31,7 @@
|
|||
<ApplicationIdGuid>0E29FC31-1B83-48ED-B6E0-9F3C67B775D4</ApplicationIdGuid>
|
||||
|
||||
<!-- Versions -->
|
||||
<ApplicationDisplayVersion>5.0.1</ApplicationDisplayVersion>
|
||||
<ApplicationDisplayVersion>5.0.2</ApplicationDisplayVersion>
|
||||
<ApplicationVersion>1</ApplicationVersion>
|
||||
|
||||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">14.2</SupportedOSPlatformVersion>
|
||||
|
@ -65,11 +65,11 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Localization" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="8.0.1" />
|
||||
<PackageReference Include="System.Net.Http.Json" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.Maui.Controls" Version="8.0.3" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebView.Maui" Version="8.0.3" />
|
||||
|
|
|
@ -213,3 +213,18 @@ app {
|
|||
right: 0.75rem;
|
||||
top: 0.5rem;
|
||||
}
|
||||
|
||||
/* Oqtane Control Styles */
|
||||
|
||||
/* Pager */
|
||||
.app-pager-pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.app-sort-th {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.app-fas {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
|
|
@ -27,14 +27,8 @@ Oqtane.Interop = {
|
|||
document.title = title;
|
||||
}
|
||||
},
|
||||
includeMeta: function (id, attribute, name, content, key) {
|
||||
var meta;
|
||||
if (id !== "" && key === "id") {
|
||||
meta = document.getElementById(id);
|
||||
}
|
||||
else {
|
||||
meta = document.querySelector("meta[" + attribute + "=\"" + CSS.escape(name) + "\"]");
|
||||
}
|
||||
includeMeta: function (id, attribute, name, content) {
|
||||
var meta = document.querySelector("meta[" + attribute + "=\"" + CSS.escape(name) + "\"]");
|
||||
if (meta === null) {
|
||||
meta = document.createElement("meta");
|
||||
meta.setAttribute(attribute, name);
|
||||
|
@ -119,13 +113,26 @@ Oqtane.Interop = {
|
|||
this.includeLink(links[i].id, links[i].rel, links[i].href, links[i].type, links[i].integrity, links[i].crossorigin, links[i].insertbefore);
|
||||
}
|
||||
},
|
||||
includeScript: function (id, src, integrity, crossorigin, content, location) {
|
||||
var script = document.querySelector("script[src=\"" + CSS.escape(src) + "\"]");
|
||||
includeScript: function (id, src, integrity, crossorigin, type, content, location) {
|
||||
var script;
|
||||
if (src !== "") {
|
||||
script = document.querySelector("script[src=\"" + CSS.escape(src) + "\"]");
|
||||
}
|
||||
else {
|
||||
script = document.getElementById(id);
|
||||
}
|
||||
if (script !== null) {
|
||||
script.remove();
|
||||
script = null;
|
||||
}
|
||||
if (script === null) {
|
||||
script = document.createElement("script");
|
||||
if (id !== "") {
|
||||
script.id = id;
|
||||
}
|
||||
if (type !== "") {
|
||||
script.type = type;
|
||||
}
|
||||
if (src !== "") {
|
||||
script.src = src;
|
||||
if (integrity !== "") {
|
||||
|
@ -141,43 +148,22 @@ Oqtane.Interop = {
|
|||
script.async = false;
|
||||
this.addScript(script, location)
|
||||
.then(() => {
|
||||
console.log(src + ' loaded');
|
||||
if (src !== "") {
|
||||
console.log(src + ' loaded');
|
||||
}
|
||||
else {
|
||||
console.log(id + ' loaded');
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
console.error(src + ' failed');
|
||||
if (src !== "") {
|
||||
console.error(src + ' failed');
|
||||
}
|
||||
else {
|
||||
console.error(id + ' failed');
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
if (script.id !== id) {
|
||||
script.setAttribute('id', id);
|
||||
}
|
||||
if (src !== "") {
|
||||
if (script.src !== this.getAbsoluteUrl(src)) {
|
||||
script.removeAttribute('integrity');
|
||||
script.removeAttribute('crossorigin');
|
||||
script.src = src;
|
||||
}
|
||||
if (integrity !== "") {
|
||||
if (script.integrity !== integrity) {
|
||||
script.setAttribute('integrity', integrity);
|
||||
}
|
||||
} else {
|
||||
script.removeAttribute('integrity');
|
||||
}
|
||||
if (crossorigin !== "") {
|
||||
if (script.crossOrigin !== crossorigin) {
|
||||
script.setAttribute('crossorigin', crossorigin);
|
||||
}
|
||||
} else {
|
||||
script.removeAttribute('crossorigin');
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (script.innerHTML !== content) {
|
||||
script.innerHTML = content;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
addScript: function (script, location) {
|
||||
if (location === 'head') {
|
||||
|
@ -229,6 +215,10 @@ Oqtane.Interop = {
|
|||
if (path === scripts[s].href && scripts[s].es6module === true) {
|
||||
element.type = "module";
|
||||
}
|
||||
if (path === scripts[s].href && scripts[s].location === 'body') {
|
||||
document.body.appendChild(element);
|
||||
return false; // return false to bypass default DOM insertion mechanism
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -289,19 +279,21 @@ Oqtane.Interop = {
|
|||
var fileinput = document.getElementById(id);
|
||||
if (fileinput !== null) {
|
||||
for (var i = 0; i < fileinput.files.length; i++) {
|
||||
files.push(fileinput.files[i].name);
|
||||
files.push(fileinput.files[i].name + ":" + fileinput.files[i].size);
|
||||
}
|
||||
}
|
||||
return files;
|
||||
},
|
||||
uploadFiles: function (posturl, folder, id, antiforgerytoken) {
|
||||
var fileinput = document.getElementById(id + 'FileInput');
|
||||
uploadFiles: function (posturl, folder, id, antiforgerytoken, jwt) {
|
||||
var fileinput = document.getElementById('FileInput_' + id);
|
||||
var files = fileinput.files;
|
||||
var progressinfo = document.getElementById(id + 'ProgressInfo');
|
||||
var progressbar = document.getElementById(id + 'ProgressBar');
|
||||
var progressinfo = document.getElementById('ProgressInfo_' + id);
|
||||
var progressbar = document.getElementById('ProgressBar_' + id);
|
||||
|
||||
progressinfo.setAttribute("style", "display: inline;");
|
||||
progressbar.setAttribute("style", "width: 200px; display: inline;");
|
||||
if (progressinfo !== null && progressbar !== null) {
|
||||
progressinfo.setAttribute("style", "display: inline;");
|
||||
progressbar.setAttribute("style", "width: 100%; display: inline;");
|
||||
}
|
||||
|
||||
for (var i = 0; i < files.length; i++) {
|
||||
var FileChunk = [];
|
||||
|
@ -331,22 +323,34 @@ Oqtane.Interop = {
|
|||
data.append('formfile', Chunk, FileName);
|
||||
var request = new XMLHttpRequest();
|
||||
request.open('POST', posturl, true);
|
||||
if (jwt !== "") {
|
||||
request.setRequestHeader('Authorization', 'Bearer ' + jwt);
|
||||
request.withCredentials = true;
|
||||
}
|
||||
request.upload.onloadstart = function (e) {
|
||||
progressinfo.innerHTML = file.name + ' 0%';
|
||||
progressbar.value = 0;
|
||||
if (progressinfo !== null && progressbar !== null) {
|
||||
progressinfo.innerHTML = file.name + ' 0%';
|
||||
progressbar.value = 0;
|
||||
}
|
||||
};
|
||||
request.upload.onprogress = function (e) {
|
||||
var percent = Math.ceil((e.loaded / e.total) * 100);
|
||||
progressinfo.innerHTML = file.name + '[' + PartCount + '] ' + percent + '%';
|
||||
progressbar.value = (percent / 100);
|
||||
if (progressinfo !== null && progressbar !== null) {
|
||||
var percent = Math.ceil((e.loaded / e.total) * 100);
|
||||
progressinfo.innerHTML = file.name + '[' + PartCount + '] ' + percent + '%';
|
||||
progressbar.value = (percent / 100);
|
||||
}
|
||||
};
|
||||
request.upload.onloadend = function (e) {
|
||||
progressinfo.innerHTML = file.name + ' 100%';
|
||||
progressbar.value = 1;
|
||||
if (progressinfo !== null && progressbar !== null) {
|
||||
progressinfo.innerHTML = file.name + ' 100%';
|
||||
progressbar.value = 1;
|
||||
}
|
||||
};
|
||||
request.upload.onerror = function () {
|
||||
progressinfo.innerHTML = file.name + ' Error: ' + xhr.status;
|
||||
progressbar.value = 0;
|
||||
request.upload.onerror = function() {
|
||||
if (progressinfo !== null && progressbar !== null) {
|
||||
progressinfo.innerHTML = file.name + ' Error: ' + request.statusText;
|
||||
progressbar.value = 0;
|
||||
}
|
||||
};
|
||||
request.send(data);
|
||||
}
|
||||
|
@ -356,10 +360,15 @@ Oqtane.Interop = {
|
|||
}
|
||||
}
|
||||
},
|
||||
refreshBrowser: function (reload, wait) {
|
||||
setInterval(function () {
|
||||
window.location.reload(reload);
|
||||
}, wait * 1000);
|
||||
refreshBrowser: function (verify, wait) {
|
||||
async function attemptReload (verify) {
|
||||
if (verify) {
|
||||
await fetch('');
|
||||
}
|
||||
window.location.reload();
|
||||
}
|
||||
attemptReload(verify);
|
||||
setInterval(attemptReload, wait * 1000);
|
||||
},
|
||||
redirectBrowser: function (url, wait) {
|
||||
setInterval(function () {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>Oqtane.Client</id>
|
||||
<version>5.0.1</version>
|
||||
<version>5.0.2</version>
|
||||
<authors>Shaun Walker</authors>
|
||||
<owners>.NET Foundation</owners>
|
||||
<title>Oqtane Framework</title>
|
||||
|
@ -12,14 +12,13 @@
|
|||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<license type="expression">MIT</license>
|
||||
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.1</releaseNotes>
|
||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.2</releaseNotes>
|
||||
<icon>icon.png</icon>
|
||||
<tags>oqtane</tags>
|
||||
</metadata>
|
||||
<files>
|
||||
<file src="..\Oqtane.Client\bin\Release\net8.0\Oqtane.Client.dll" target="lib\net8.0" />
|
||||
<file src="..\Oqtane.Client\bin\Release\net8.0\Oqtane.Client.pdb" target="lib\net8.0" />
|
||||
<file src="..\Oqtane.Server\bin\Release\net8.0\Oqtane.Licensing.Client.Oqtane.dll" target="lib\net8.0" />
|
||||
<file src="icon.png" target="" />
|
||||
</files>
|
||||
</package>
|
|
@ -2,7 +2,7 @@
|
|||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>Oqtane.Framework</id>
|
||||
<version>5.0.1</version>
|
||||
<version>5.0.2</version>
|
||||
<authors>Shaun Walker</authors>
|
||||
<owners>.NET Foundation</owners>
|
||||
<title>Oqtane Framework</title>
|
||||
|
@ -11,8 +11,8 @@
|
|||
<copyright>.NET Foundation</copyright>
|
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<license type="expression">MIT</license>
|
||||
<projectUrl>https://github.com/oqtane/oqtane.framework/releases/download/v5.0.1/Oqtane.Framework.5.0.1.Upgrade.zip</projectUrl>
|
||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.1</releaseNotes>
|
||||
<projectUrl>https://github.com/oqtane/oqtane.framework/releases/download/v5.0.2/Oqtane.Framework.5.0.2.Upgrade.zip</projectUrl>
|
||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.2</releaseNotes>
|
||||
<icon>icon.png</icon>
|
||||
<tags>oqtane framework</tags>
|
||||
</metadata>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>Oqtane.Server</id>
|
||||
<version>5.0.1</version>
|
||||
<version>5.0.2</version>
|
||||
<authors>Shaun Walker</authors>
|
||||
<owners>.NET Foundation</owners>
|
||||
<title>Oqtane Framework</title>
|
||||
|
@ -12,7 +12,7 @@
|
|||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<license type="expression">MIT</license>
|
||||
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.1</releaseNotes>
|
||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.2</releaseNotes>
|
||||
<icon>icon.png</icon>
|
||||
<tags>oqtane</tags>
|
||||
</metadata>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>Oqtane.Shared</id>
|
||||
<version>5.0.1</version>
|
||||
<version>5.0.2</version>
|
||||
<authors>Shaun Walker</authors>
|
||||
<owners>.NET Foundation</owners>
|
||||
<title>Oqtane Framework</title>
|
||||
|
@ -12,14 +12,13 @@
|
|||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<license type="expression">MIT</license>
|
||||
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.1</releaseNotes>
|
||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.2</releaseNotes>
|
||||
<icon>icon.png</icon>
|
||||
<tags>oqtane</tags>
|
||||
</metadata>
|
||||
<files>
|
||||
<file src="..\Oqtane.Shared\bin\Release\net8.0\Oqtane.Shared.dll" target="lib\net8.0" />
|
||||
<file src="..\Oqtane.Shared\bin\Release\net8.0\Oqtane.Shared.pdb" target="lib\net8.0" />
|
||||
<file src="..\Oqtane.Server\bin\Release\net8.0\Oqtane.Licensing.Shared.Oqtane.dll" target="lib\net8.0" />
|
||||
<file src="icon.png" target="" />
|
||||
</files>
|
||||
</package>
|
|
@ -2,7 +2,7 @@
|
|||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>Oqtane.Updater</id>
|
||||
<version>5.0.1</version>
|
||||
<version>5.0.2</version>
|
||||
<authors>Shaun Walker</authors>
|
||||
<owners>.NET Foundation</owners>
|
||||
<title>Oqtane Framework</title>
|
||||
|
@ -12,7 +12,7 @@
|
|||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<license type="expression">MIT</license>
|
||||
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.1</releaseNotes>
|
||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.2</releaseNotes>
|
||||
<icon>icon.png</icon>
|
||||
<tags>oqtane</tags>
|
||||
</metadata>
|
||||
|
|
|
@ -1 +1 @@
|
|||
Compress-Archive -Path "..\Oqtane.Server\bin\Release\net8.0\publish\*" -DestinationPath "Oqtane.Framework.5.0.1.Install.zip" -Force
|
||||
Compress-Archive -Path "..\Oqtane.Server\bin\Release\net8.0\publish\*" -DestinationPath "Oqtane.Framework.5.0.2.Install.zip" -Force
|
|
@ -1 +1 @@
|
|||
Compress-Archive -Path "..\Oqtane.Server\bin\Release\net8.0\publish\*" -DestinationPath "Oqtane.Framework.5.0.1.Upgrade.zip" -Force
|
||||
Compress-Archive -Path "..\Oqtane.Server\bin\Release\net8.0\publish\*" -DestinationPath "Oqtane.Framework.5.0.2.Upgrade.zip" -Force
|
|
@ -20,6 +20,7 @@ using SixLabors.ImageSharp;
|
|||
using SixLabors.ImageSharp.Processing;
|
||||
using SixLabors.ImageSharp.Formats.Png;
|
||||
using System.Net.Http;
|
||||
using Microsoft.AspNetCore.Cors;
|
||||
|
||||
// ReSharper disable StringIndexOfIsCultureSpecific.1
|
||||
|
||||
|
@ -288,7 +289,8 @@ namespace Oqtane.Controllers
|
|||
folder = _folders.GetFolder(FolderId);
|
||||
}
|
||||
|
||||
var _UploadableFiles = (_settingRepository.GetSetting(EntityNames.Site, _alias.SiteId, "UploadableFiles")?.SettingValue ?? Constants.UploadableFiles) ?? Constants.UploadableFiles;
|
||||
var _UploadableFiles = _settingRepository.GetSetting(EntityNames.Site, _alias.SiteId, "UploadableFiles")?.SettingValue;
|
||||
_UploadableFiles = (string.IsNullOrEmpty(_UploadableFiles)) ? Constants.UploadableFiles : _UploadableFiles;
|
||||
|
||||
if (folder != null && folder.SiteId == _alias.SiteId && _userPermissions.IsAuthorized(User, PermissionNames.Edit, folder.PermissionList))
|
||||
{
|
||||
|
@ -357,17 +359,18 @@ namespace Oqtane.Controllers
|
|||
}
|
||||
|
||||
// POST api/<controller>/upload
|
||||
[EnableCors(Constants.MauiCorsPolicy)]
|
||||
[HttpPost("upload")]
|
||||
public async Task UploadFile(string folder, IFormFile formfile)
|
||||
{
|
||||
if (formfile.Length <= 0)
|
||||
if (formfile == null || formfile.Length <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the UploadableFiles extensions
|
||||
string uploadfilesSetting = _settingRepository.GetSetting(EntityNames.Site, _alias.SiteId, "UploadableFiles")?.SettingValue;
|
||||
string _UploadableFiles = uploadfilesSetting ?? Constants.UploadableFiles;
|
||||
string _UploadableFiles = _settingRepository.GetSetting(EntityNames.Site, _alias.SiteId, "UploadableFiles")?.SettingValue;
|
||||
_UploadableFiles = (string.IsNullOrEmpty(_UploadableFiles)) ? Constants.UploadableFiles : _UploadableFiles;
|
||||
|
||||
// ensure filename is valid
|
||||
string token = ".part_";
|
||||
|
@ -612,7 +615,9 @@ namespace Oqtane.Controllers
|
|||
{
|
||||
var file = _files.GetFile(id);
|
||||
|
||||
var _ImageFiles = (_settingRepository.GetSetting(EntityNames.Site, _alias.SiteId, "ImageFiles")?.SettingValue ?? Constants.ImageFiles) ?? Constants.ImageFiles;
|
||||
var _ImageFiles = _settingRepository.GetSetting(EntityNames.Site, _alias.SiteId, "ImageFiles")?.SettingValue;
|
||||
_ImageFiles = (string.IsNullOrEmpty(_ImageFiles)) ? Constants.ImageFiles : _ImageFiles;
|
||||
|
||||
if (file != null && file.Folder.SiteId == _alias.SiteId && _userPermissions.IsAuthorized(User, PermissionNames.View, file.Folder.PermissionList))
|
||||
{
|
||||
if (_ImageFiles.Split(',').Contains(file.Extension.ToLower()))
|
||||
|
@ -779,7 +784,9 @@ namespace Oqtane.Controllers
|
|||
private Models.File CreateFile(string filename, int folderid, string filepath)
|
||||
{
|
||||
var file = _files.GetFile(folderid, filename);
|
||||
var _ImageFiles = (_settingRepository.GetSetting(EntityNames.Site, _alias.SiteId, "ImageFiles")?.SettingValue ?? Constants.ImageFiles) ?? Constants.ImageFiles;
|
||||
|
||||
var _ImageFiles = _settingRepository.GetSetting(EntityNames.Site, _alias.SiteId, "ImageFiles")?.SettingValue;
|
||||
_ImageFiles = (string.IsNullOrEmpty(_ImageFiles)) ? Constants.ImageFiles : _ImageFiles;
|
||||
|
||||
int size = 0;
|
||||
var folder = _folders.GetFolder(folderid, false);
|
||||
|
|
|
@ -75,6 +75,8 @@ namespace Oqtane.Controllers
|
|||
module.Pane = pagemodule.Pane;
|
||||
module.Order = pagemodule.Order;
|
||||
module.ContainerType = pagemodule.ContainerType;
|
||||
module.EffectiveDate = pagemodule.EffectiveDate;
|
||||
module.ExpiryDate = pagemodule.ExpiryDate;
|
||||
|
||||
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/"))
|
||||
{
|
||||
_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 });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,8 @@ using System.Globalization;
|
|||
using Microsoft.Extensions.Caching.Memory;
|
||||
using Oqtane.Extensions;
|
||||
using System;
|
||||
using Oqtane.UI;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Internal;
|
||||
|
||||
namespace Oqtane.Controllers
|
||||
{
|
||||
|
@ -97,7 +99,7 @@ namespace Oqtane.Controllers
|
|||
site.Pages = new List<Page>();
|
||||
foreach (Page page in _pages.GetPages(site.SiteId))
|
||||
{
|
||||
if (!page.IsDeleted && _userPermissions.IsAuthorized(User, PermissionNames.View, page.PermissionList))
|
||||
if (!page.IsDeleted && _userPermissions.IsAuthorized(User, PermissionNames.View, page.PermissionList) && (Utilities.IsPageModuleVisible(page.EffectiveDate, page.ExpiryDate) || _userPermissions.IsAuthorized(User, PermissionNames.Edit, page.PermissionList)))
|
||||
{
|
||||
page.Settings = settings.Where(item => item.EntityId == page.PageId)
|
||||
.Where(item => !item.IsPrivate || _userPermissions.IsAuthorized(User, PermissionNames.Edit, page.PermissionList))
|
||||
|
@ -105,46 +107,53 @@ namespace Oqtane.Controllers
|
|||
site.Pages.Add(page);
|
||||
}
|
||||
}
|
||||
|
||||
site.Pages = GetPagesHierarchy(site.Pages);
|
||||
|
||||
// modules
|
||||
List<ModuleDefinition> moduledefinitions = _moduleDefinitions.GetModuleDefinitions(site.SiteId).ToList();
|
||||
settings = _settings.GetSettings(EntityNames.Module).ToList();
|
||||
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(Utilities.IsPageModuleVisible(pagemodule.EffectiveDate, pagemodule.ExpiryDate) || _userPermissions.IsAuthorized(User, PermissionNames.Edit, pagemodule.Module.PermissionList))
|
||||
{
|
||||
Module module = new Module();
|
||||
module.SiteId = pagemodule.Module.SiteId;
|
||||
module.ModuleDefinitionName = pagemodule.Module.ModuleDefinitionName;
|
||||
module.AllPages = pagemodule.Module.AllPages;
|
||||
module.PermissionList = pagemodule.Module.PermissionList;
|
||||
module.CreatedBy = pagemodule.Module.CreatedBy;
|
||||
module.CreatedOn = pagemodule.Module.CreatedOn;
|
||||
module.ModifiedBy = pagemodule.Module.ModifiedBy;
|
||||
module.ModifiedOn = pagemodule.Module.ModifiedOn;
|
||||
module.DeletedBy = pagemodule.DeletedBy;
|
||||
module.DeletedOn = pagemodule.DeletedOn;
|
||||
module.IsDeleted = pagemodule.IsDeleted;
|
||||
Module module = new Module
|
||||
{
|
||||
SiteId = pagemodule.Module.SiteId,
|
||||
ModuleDefinitionName = pagemodule.Module.ModuleDefinitionName,
|
||||
AllPages = pagemodule.Module.AllPages,
|
||||
PermissionList = pagemodule.Module.PermissionList,
|
||||
CreatedBy = pagemodule.Module.CreatedBy,
|
||||
CreatedOn = pagemodule.Module.CreatedOn,
|
||||
ModifiedBy = pagemodule.Module.ModifiedBy,
|
||||
ModifiedOn = pagemodule.Module.ModifiedOn,
|
||||
DeletedBy = pagemodule.DeletedBy,
|
||||
DeletedOn = pagemodule.DeletedOn,
|
||||
IsDeleted = pagemodule.IsDeleted,
|
||||
|
||||
module.PageModuleId = pagemodule.PageModuleId;
|
||||
module.ModuleId = pagemodule.ModuleId;
|
||||
module.PageId = pagemodule.PageId;
|
||||
module.Title = pagemodule.Title;
|
||||
module.Pane = pagemodule.Pane;
|
||||
module.Order = pagemodule.Order;
|
||||
module.ContainerType = pagemodule.ContainerType;
|
||||
PageModuleId = pagemodule.PageModuleId,
|
||||
ModuleId = pagemodule.ModuleId,
|
||||
PageId = pagemodule.PageId,
|
||||
Title = pagemodule.Title,
|
||||
Pane = pagemodule.Pane,
|
||||
Order = pagemodule.Order,
|
||||
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))
|
||||
.ToDictionary(setting => setting.SettingName, setting => setting.SettingValue);
|
||||
.ToDictionary(setting => setting.SettingName, setting => setting.SettingValue)
|
||||
};
|
||||
|
||||
site.Modules.Add(module);
|
||||
}
|
||||
}
|
||||
|
||||
site.Modules = site.Modules.OrderBy(item => item.PageId).ThenBy(item => item.Pane).ThenBy(item => item.Order).ToList();
|
||||
|
||||
// languages
|
||||
|
|
|
@ -66,6 +66,11 @@ namespace Oqtane.Databases
|
|||
return name;
|
||||
}
|
||||
|
||||
public virtual string RewriteName(string name, bool isQuery)
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public virtual string RewriteValue(string value, string type)
|
||||
{
|
||||
return value;
|
||||
|
|
|
@ -28,6 +28,8 @@ namespace Oqtane.Databases.Interfaces
|
|||
|
||||
public string RewriteName(string name);
|
||||
|
||||
public string RewriteName(string name, bool isQuery);
|
||||
|
||||
public string RewriteValue(string value, string type);
|
||||
|
||||
public void UpdateIdentityStoreTableNames(ModelBuilder builder);
|
||||
|
|
|
@ -205,6 +205,10 @@ namespace Oqtane.Extensions
|
|||
{
|
||||
email = item[emailClaimType].ToString().ToLower();
|
||||
}
|
||||
else
|
||||
{
|
||||
id = ""; // if email is not valid we will assume id is not valid
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!string.IsNullOrEmpty(id))
|
||||
|
@ -290,6 +294,10 @@ namespace Oqtane.Extensions
|
|||
{
|
||||
email = context.Principal.FindFirstValue(emailClaimType);
|
||||
}
|
||||
else
|
||||
{
|
||||
id = ""; // if email is not valid we will assume id is not valid
|
||||
}
|
||||
}
|
||||
|
||||
// validate user
|
||||
|
@ -610,23 +618,27 @@ namespace Oqtane.Extensions
|
|||
|
||||
private static bool EmailValid(string email, string domainfilter)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(email) && email.Contains("@") && email.Contains("."))
|
||||
if (!string.IsNullOrEmpty(email))
|
||||
{
|
||||
var domains = domainfilter.ToLower().Split(',', StringSplitOptions.RemoveEmptyEntries);
|
||||
foreach (var domain in domains)
|
||||
if (email.Contains("@") && email.Contains("."))
|
||||
{
|
||||
if (domain.StartsWith("!"))
|
||||
var domains = domainfilter.ToLower().Split(',', StringSplitOptions.RemoveEmptyEntries);
|
||||
foreach (var domain in domains)
|
||||
{
|
||||
if (email.ToLower().Contains(domain.Substring(1))) return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!email.ToLower().Contains(domain)) return false;
|
||||
if (domain.StartsWith("!"))
|
||||
{
|
||||
if (email.ToLower().Contains(domain.Substring(1))) return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!email.ToLower().Contains(domain)) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
return (string.IsNullOrEmpty(domainfilter)); // email is optional unless domain filter is specified
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Loader;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
|
@ -29,16 +26,14 @@ namespace Oqtane.Infrastructure
|
|||
{
|
||||
private readonly IConfigManager _config;
|
||||
private readonly IServiceScopeFactory _serviceScopeFactory;
|
||||
private readonly IWebHostEnvironment _environment;
|
||||
private readonly IMemoryCache _cache;
|
||||
private readonly IConfigManager _configManager;
|
||||
private readonly ILogger<DatabaseManager> _filelogger;
|
||||
|
||||
public DatabaseManager(IConfigManager config, IServiceScopeFactory serviceScopeFactory, IWebHostEnvironment environment, IMemoryCache cache, IConfigManager configManager, ILogger<DatabaseManager> filelogger)
|
||||
public DatabaseManager(IConfigManager config, IServiceScopeFactory serviceScopeFactory, IMemoryCache cache, IConfigManager configManager, ILogger<DatabaseManager> filelogger)
|
||||
{
|
||||
_config = config;
|
||||
_serviceScopeFactory = serviceScopeFactory;
|
||||
_environment = environment;
|
||||
_cache = cache;
|
||||
_configManager = configManager;
|
||||
_filelogger = filelogger;
|
||||
|
@ -216,19 +211,27 @@ namespace Oqtane.Infrastructure
|
|||
// get database type
|
||||
var type = Type.GetType(databaseType);
|
||||
|
||||
// create database object from type
|
||||
var database = Activator.CreateInstance(type) as IDatabase;
|
||||
|
||||
// create data directory if does not exist
|
||||
var dataDirectory = AppDomain.CurrentDomain.GetData(Constants.DataDirectory)?.ToString();
|
||||
if (!Directory.Exists(dataDirectory)) Directory.CreateDirectory(dataDirectory ?? String.Empty);
|
||||
|
||||
var dbOptions = new DbContextOptionsBuilder().UseOqtaneDatabase(database, NormalizeConnectionString(install.ConnectionString)).Options;
|
||||
using (var dbc = new DbContext(dbOptions))
|
||||
if (type != null)
|
||||
{
|
||||
// create empty database if it does not exist
|
||||
dbc.Database.EnsureCreated();
|
||||
result.Success = true;
|
||||
// create database object from type
|
||||
var database = Activator.CreateInstance(type) as IDatabase;
|
||||
|
||||
// create data directory if does not exist
|
||||
var dataDirectory = AppDomain.CurrentDomain.GetData(Constants.DataDirectory)?.ToString();
|
||||
if (!Directory.Exists(dataDirectory)) Directory.CreateDirectory(dataDirectory ?? String.Empty);
|
||||
|
||||
var dbOptions = new DbContextOptionsBuilder().UseOqtaneDatabase(database, NormalizeConnectionString(install.ConnectionString)).Options;
|
||||
using (var dbc = new DbContext(dbOptions))
|
||||
{
|
||||
// create empty database if it does not exist
|
||||
dbc.Database.EnsureCreated();
|
||||
result.Success = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Message = $"The Database Provider {databaseType} Does Not Exist. If This Is A Development Environment Please Ensure You Have Performed A Full Compilation Of All Projects In The Oqtane Solution Prior To Running The Application.";
|
||||
_filelogger.LogError(Utilities.LogMessage(this, result.Message));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
|
@ -137,16 +137,20 @@ namespace Oqtane.Infrastructure
|
|||
// register assembly
|
||||
if (Path.GetExtension(filename) == ".dll")
|
||||
{
|
||||
// if package version was not installed previously
|
||||
if (!File.Exists(Path.Combine(sourceFolder, name + ".log")))
|
||||
// do not register licensing assemblies
|
||||
if (!Path.GetFileName(filename).StartsWith("Oqtane.Licensing."))
|
||||
{
|
||||
if (assemblies.ContainsKey(Path.GetFileName(filename)))
|
||||
// if package version was not installed previously
|
||||
if (!File.Exists(Path.Combine(sourceFolder, name + ".log")))
|
||||
{
|
||||
assemblies[Path.GetFileName(filename)] += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
assemblies.Add(Path.GetFileName(filename), 1);
|
||||
if (assemblies.ContainsKey(Path.GetFileName(filename)))
|
||||
{
|
||||
assemblies[Path.GetFileName(filename)] += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
assemblies.Add(Path.GetFileName(filename), 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -255,22 +259,26 @@ namespace Oqtane.Infrastructure
|
|||
// delete assets
|
||||
if (Path.GetExtension(filepath) == ".dll")
|
||||
{
|
||||
// use assembly log to determine if assembly is used in other packages
|
||||
if (assemblies.ContainsKey(Path.GetFileName(filepath)))
|
||||
// do not remove licensing assemblies
|
||||
if (!Path.GetFileName(filepath).StartsWith("Oqtane.Licensing."))
|
||||
{
|
||||
if (assemblies[Path.GetFileName(filepath)] == 1)
|
||||
// use assembly log to determine if assembly is used in other packages
|
||||
if (assemblies.ContainsKey(Path.GetFileName(filepath)))
|
||||
{
|
||||
if (assemblies[Path.GetFileName(filepath)] == 1)
|
||||
{
|
||||
DeleteFile(filepath);
|
||||
assemblies.Remove(Path.GetFileName(filepath));
|
||||
}
|
||||
else
|
||||
{
|
||||
assemblies[Path.GetFileName(filepath)] -= 1;
|
||||
}
|
||||
}
|
||||
else // does not exist in assembly log
|
||||
{
|
||||
DeleteFile(filepath);
|
||||
assemblies.Remove(Path.GetFileName(filepath));
|
||||
}
|
||||
else
|
||||
{
|
||||
assemblies[Path.GetFileName(filepath)] -= 1;
|
||||
}
|
||||
}
|
||||
else // does not exist in assembly log
|
||||
{
|
||||
DeleteFile(filepath);
|
||||
}
|
||||
}
|
||||
else // not an assembly
|
||||
|
|
|
@ -68,7 +68,7 @@ namespace Oqtane.SiteTemplates
|
|||
new Permission(PermissionNames.View, RoleNames.Admin, true),
|
||||
new Permission(PermissionNames.Edit, RoleNames.Admin, true)
|
||||
},
|
||||
Content = "<p>Copyright (c) 2018-2023 .NET Foundation</p>" +
|
||||
Content = "<p>Copyright (c) 2018-2024 .NET Foundation</p>" +
|
||||
"<p>Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:</p>" +
|
||||
"<p>The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.</p>" +
|
||||
"<p>THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.</p>"
|
||||
|
|
|
@ -50,6 +50,11 @@ namespace Oqtane.Migrations.EntityBuilders
|
|||
return ActiveDatabase.RewriteName(name);
|
||||
}
|
||||
|
||||
private string RewriteName(string name, bool isQuery)
|
||||
{
|
||||
return ActiveDatabase.RewriteName(name, isQuery);
|
||||
}
|
||||
|
||||
private string RewriteValue(string value, string type)
|
||||
{
|
||||
return ActiveDatabase.RewriteValue(value, type);
|
||||
|
@ -394,7 +399,7 @@ namespace Oqtane.Migrations.EntityBuilders
|
|||
|
||||
public void UpdateColumn(string columnName, string value, string type, string condition)
|
||||
{
|
||||
var updateSql = $"UPDATE {RewriteSqlEntityTableName(EntityTableName)} SET {RewriteName(columnName)} = {RewriteValue(value, type)} ";
|
||||
var updateSql = $"UPDATE {RewriteSqlEntityTableName(EntityTableName)} SET {RewriteName(columnName, true)} = {RewriteValue(value, type)} ";
|
||||
if (!string.IsNullOrEmpty(condition))
|
||||
{
|
||||
updateSql += $"WHERE {condition}";
|
||||
|
|
|
@ -14,7 +14,12 @@ namespace Oqtane.Migrations
|
|||
|
||||
protected string RewriteName(string name)
|
||||
{
|
||||
return ActiveDatabase.RewriteName(name);
|
||||
return ActiveDatabase.RewriteName(name, false);
|
||||
}
|
||||
|
||||
protected string RewriteName(string name, bool isQuery)
|
||||
{
|
||||
return ActiveDatabase.RewriteName(name, isQuery);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
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.03")]
|
||||
public class AddProfileAutocomplete : MultiDatabaseMigration
|
||||
{
|
||||
public AddProfileAutocomplete(IDatabase database) : base(database)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
var profileEntityBuilder = new ProfileEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||
profileEntityBuilder.AddStringColumn("Autocomplete", 50, true);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
// not implemented
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Configurations>Debug;Release</Configurations>
|
||||
<Version>5.0.1</Version>
|
||||
<Version>5.0.2</Version>
|
||||
<Product>Oqtane</Product>
|
||||
<Authors>Shaun Walker</Authors>
|
||||
<Company>.NET Foundation</Company>
|
||||
|
@ -11,7 +11,7 @@
|
|||
<Copyright>.NET Foundation</Copyright>
|
||||
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
||||
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.1</PackageReleaseNotes>
|
||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.2</PackageReleaseNotes>
|
||||
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
||||
<RepositoryType>Git</RepositoryType>
|
||||
<RootNamespace>Oqtane</RootNamespace>
|
||||
|
@ -33,21 +33,20 @@
|
|||
<EmbeddedResource Include="Scripts\MigrateTenant.sql" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.Data.SqlClient" Version="5.2.0-preview3.23201.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.0">
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.Data.SqlClient" Version="5.2.0-preview4.23342.2" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.1">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="8.0.1" />
|
||||
<PackageReference Include="SixLabors.ImageSharp" Version="2.1.0" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.Data.Sqlite.Core" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.Data.Sqlite.Core" Version="8.0.1" />
|
||||
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="2.1.7" />
|
||||
<PackageReference Include="Oqtane.Licensing" Version="5.0.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Oqtane.Client\Oqtane.Client.csproj" />
|
||||
|
|
|
@ -228,7 +228,7 @@ namespace Oqtane.Repository
|
|||
// build list of scripts for site
|
||||
if (moduledefinition.Resources != null)
|
||||
{
|
||||
foreach (var resource in moduledefinition.Resources.Where(item => item.Level == ResourceLevel.Site))
|
||||
foreach (var resource in moduledefinition.Resources.Where(item => item.ResourceType == ResourceType.Script && item.Level == ResourceLevel.Site))
|
||||
{
|
||||
if (!serverState.Scripts.Contains(resource))
|
||||
{
|
||||
|
|
|
@ -200,7 +200,7 @@ namespace Oqtane.Repository
|
|||
// build list of scripts for site
|
||||
if (theme.Resources != null)
|
||||
{
|
||||
foreach (var resource in theme.Resources.Where(item => item.Level == ResourceLevel.Site))
|
||||
foreach (var resource in theme.Resources.Where(item => item.ResourceType == ResourceType.Script && item.Level == ResourceLevel.Site))
|
||||
{
|
||||
if (!serverState.Scripts.Contains(resource))
|
||||
{
|
||||
|
|
|
@ -131,6 +131,16 @@ namespace Oqtane
|
|||
.WithSiteIdentity()
|
||||
.WithSiteAuthentication();
|
||||
|
||||
services.AddCors(options =>
|
||||
{
|
||||
options.AddPolicy(Constants.MauiCorsPolicy,
|
||||
policy =>
|
||||
{
|
||||
policy.WithOrigins("https://0.0.0.0", "http://0.0.0.0", "app://0.0.0.0")
|
||||
.AllowAnyHeader().AllowCredentials();
|
||||
});
|
||||
});
|
||||
|
||||
services.AddMvc(options =>
|
||||
{
|
||||
options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
|
||||
|
@ -180,6 +190,7 @@ namespace Oqtane
|
|||
app.UseJwtAuthorization();
|
||||
app.UseBlazorFrameworkFiles();
|
||||
app.UseRouting();
|
||||
app.UseCors();
|
||||
app.UseAuthentication();
|
||||
app.UseAuthorization();
|
||||
|
||||
|
|
|
@ -13,10 +13,10 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="8.0.0" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="8.0.1" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="8.0.1" />
|
||||
<PackageReference Include="System.Net.Http.Json" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Localization" Version="2.2.0" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -15,5 +15,12 @@ namespace [Owner].Module.[Module].Repository
|
|||
{
|
||||
// ContextBase handles multi-tenant database connections
|
||||
}
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder builder)
|
||||
{
|
||||
base.OnModelCreating(builder);
|
||||
|
||||
builder.Entity<Models.[Module]>().ToTable(ActiveDatabase.RewriteName("[Owner][Module]"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,10 +19,10 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="8.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -12,10 +12,10 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="8.0.0" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="8.0.1" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="8.0.1" />
|
||||
<PackageReference Include="System.Net.Http.Json" Version="8.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
@ -284,7 +284,7 @@ Oqtane.Interop = {
|
|||
}
|
||||
return files;
|
||||
},
|
||||
uploadFiles: function (posturl, folder, id, antiforgerytoken) {
|
||||
uploadFiles: function (posturl, folder, id, antiforgerytoken, jwt) {
|
||||
var fileinput = document.getElementById('FileInput_' + id);
|
||||
var files = fileinput.files;
|
||||
var progressinfo = document.getElementById('ProgressInfo_' + id);
|
||||
|
@ -323,6 +323,10 @@ Oqtane.Interop = {
|
|||
data.append('formfile', Chunk, FileName);
|
||||
var request = new XMLHttpRequest();
|
||||
request.open('POST', posturl, true);
|
||||
if (jwt !== "") {
|
||||
request.setRequestHeader('Authorization', 'Bearer ' + jwt);
|
||||
request.withCredentials = true;
|
||||
}
|
||||
request.upload.onloadstart = function (e) {
|
||||
if (progressinfo !== null && progressbar !== null) {
|
||||
progressinfo.innerHTML = file.name + ' 0%';
|
||||
|
@ -344,7 +348,7 @@ Oqtane.Interop = {
|
|||
};
|
||||
request.upload.onerror = function() {
|
||||
if (progressinfo !== null && progressbar !== null) {
|
||||
progressinfo.innerHTML = file.name + ' Error: ' + xhr.status;
|
||||
progressinfo.innerHTML = file.name + ' Error: ' + request.statusText;
|
||||
progressbar.value = 0;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -2,6 +2,6 @@
|
|||
|
||||
This folder contains special attributes for the API Code Generator.
|
||||
|
||||
The idea is that only items marked with special attributes are valide public APIs, and only these will be documented in the public docs
|
||||
The idea is that only items marked with special attributes are valid public APIs, and only these will be documented in the public docs
|
||||
|
||||
As of 2020, all APIs are documented, and only these marked as `[PrivateApi]` will be excluded. In future, we may reverse this to only document things marked as `[PublicApi]`.
|
||||
As of 2020, all APIs are documented, and only these marked as `[PrivateApi]` will be excluded. In future, we may reverse this to only document things marked as `[PublicApi]`.
|
||||
|
|
|
@ -75,16 +75,24 @@ namespace Oqtane.Models
|
|||
[NotMapped]
|
||||
public string ContainerType { get; set; }
|
||||
|
||||
[NotMapped]
|
||||
public DateTime? EffectiveDate { get; set; }
|
||||
|
||||
[NotMapped]
|
||||
public DateTime? ExpiryDate { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region SiteRouter properties
|
||||
|
||||
|
||||
[NotMapped]
|
||||
public string ModuleType { get; set; }
|
||||
[NotMapped]
|
||||
public int PaneModuleIndex { get; set; }
|
||||
[NotMapped]
|
||||
public int PaneModuleCount { get; set; }
|
||||
[NotMapped]
|
||||
public Guid RenderId { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
|
|
|
@ -82,6 +82,14 @@ namespace Oqtane.Models
|
|||
public bool IsNavigation { get; set; }
|
||||
public bool IsClickable { 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; }
|
||||
|
||||
#region IDeletable Properties
|
||||
|
|
|
@ -41,7 +41,14 @@ namespace Oqtane.Models
|
|||
/// Reference to a Razor Container which wraps this module instance.
|
||||
/// </summary>
|
||||
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
|
||||
|
||||
public string DeletedBy { get; set; }
|
||||
|
|
|
@ -78,5 +78,11 @@ namespace Oqtane.Models
|
|||
/// Optional number of rows (textarea)
|
||||
/// </summary>
|
||||
public int Rows { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Autocomplete setting for the property.
|
||||
/// If set, enable autocomplete for the corresponding input field.
|
||||
/// </summary>
|
||||
public string Autocomplete { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Configurations>Debug;Release</Configurations>
|
||||
<Version>5.0.1</Version>
|
||||
<Version>5.0.2</Version>
|
||||
<Product>Oqtane</Product>
|
||||
<Authors>Shaun Walker</Authors>
|
||||
<Company>.NET Foundation</Company>
|
||||
|
@ -11,7 +11,7 @@
|
|||
<Copyright>.NET Foundation</Copyright>
|
||||
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
||||
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.1</PackageReleaseNotes>
|
||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.2</PackageReleaseNotes>
|
||||
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
||||
<RepositoryType>Git</RepositoryType>
|
||||
<RootNamespace>Oqtane</RootNamespace>
|
||||
|
@ -19,11 +19,11 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.0" />
|
||||
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
|
||||
<PackageReference Include="System.Text.Json" Version="8.0.0" />
|
||||
<PackageReference Include="System.Text.Json" Version="8.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -1,14 +1,11 @@
|
|||
using System;
|
||||
using Oqtane.Models;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Oqtane.Shared
|
||||
{
|
||||
public class Constants
|
||||
{
|
||||
public static readonly string Version = "5.0.1";
|
||||
public const string ReleaseVersions = "1.0.0,1.0.1,1.0.2,1.0.3,1.0.4,2.0.0,2.0.1,2.0.2,2.1.0,2.2.0,2.3.0,2.3.1,3.0.0,3.0.1,3.0.2,3.0.3,3.1.0,3.1.1,3.1.2,3.1.3,3.1.4,3.2.0,3.2.1,3.3.0,3.3.1,3.4.0,3.4.1,3.4.2,3.4.3,4.0.0,4.0.1,4.0.2,4.0.3,4.0.4,4.0.5,4.0.6,5.0.0,5.0.1";
|
||||
public static readonly string Version = "5.0.2";
|
||||
public const string ReleaseVersions = "1.0.0,1.0.1,1.0.2,1.0.3,1.0.4,2.0.0,2.0.1,2.0.2,2.1.0,2.2.0,2.3.0,2.3.1,3.0.0,3.0.1,3.0.2,3.0.3,3.1.0,3.1.1,3.1.2,3.1.3,3.1.4,3.2.0,3.2.1,3.3.0,3.3.1,3.4.0,3.4.1,3.4.2,3.4.3,4.0.0,4.0.1,4.0.2,4.0.3,4.0.4,4.0.5,4.0.6,5.0.0,5.0.1,5.0.2";
|
||||
public const string PackageId = "Oqtane.Framework";
|
||||
public const string ClientId = "Oqtane.Client";
|
||||
public const string UpdaterPackageId = "Oqtane.Updater";
|
||||
|
@ -80,6 +77,8 @@ namespace Oqtane.Shared
|
|||
|
||||
public static readonly string MauiUserAgent = "MAUI";
|
||||
public static readonly string MauiAliasPath = "Alias-Path";
|
||||
public const string MauiCorsPolicy = "MauiCorsPolicy"; // must be a constant to be used with an attribute
|
||||
|
||||
public static readonly string VisitorCookiePrefix = "APP_VISITOR_";
|
||||
|
||||
// Obsolete constants
|
||||
|
|
|
@ -572,7 +572,55 @@ namespace Oqtane.Shared
|
|||
|
||||
return (localDateTime?.Date, localTime);
|
||||
}
|
||||
public static bool IsPageModuleVisible(DateTime? effectiveDate, DateTime? expiryDate)
|
||||
{
|
||||
DateTime currentUtcTime = DateTime.UtcNow;
|
||||
|
||||
if (effectiveDate.HasValue && expiryDate.HasValue)
|
||||
{
|
||||
return currentUtcTime >= effectiveDate.Value && currentUtcTime <= expiryDate.Value;
|
||||
}
|
||||
else if (effectiveDate.HasValue)
|
||||
{
|
||||
return currentUtcTime >= effectiveDate.Value;
|
||||
}
|
||||
else if (expiryDate.HasValue)
|
||||
{
|
||||
// Include equality check here
|
||||
return currentUtcTime <= expiryDate.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
public static bool ValidateEffectiveExpiryDates(DateTime? effectiveDate, DateTime? expiryDate)
|
||||
{
|
||||
// Treat DateTime.MinValue as null
|
||||
effectiveDate ??= DateTime.MinValue;
|
||||
expiryDate ??= DateTime.MinValue;
|
||||
|
||||
// Check if both effectiveDate and expiryDate have values
|
||||
if (effectiveDate != DateTime.MinValue && expiryDate != DateTime.MinValue)
|
||||
{
|
||||
return effectiveDate <= expiryDate;
|
||||
}
|
||||
// Check if only effectiveDate has a value
|
||||
else if (effectiveDate != DateTime.MinValue)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// Check if only expiryDate has a value
|
||||
else if (expiryDate != DateTime.MinValue)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// If neither effectiveDate nor expiryDate has a value, consider the page/module visible
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
[Obsolete("ContentUrl(Alias alias, int fileId) is deprecated. Use FileUrl(Alias alias, int fileId) instead.", false)]
|
||||
public static string ContentUrl(Alias alias, int fileId)
|
||||
{
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<OutputType>Exe</OutputType>
|
||||
<Version>5.0.1</Version>
|
||||
<Version>5.0.2</Version>
|
||||
<Product>Oqtane</Product>
|
||||
<Authors>Shaun Walker</Authors>
|
||||
<Company>.NET Foundation</Company>
|
||||
|
@ -11,7 +11,7 @@
|
|||
<Copyright>.NET Foundation</Copyright>
|
||||
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
||||
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.1</PackageReleaseNotes>
|
||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.2</PackageReleaseNotes>
|
||||
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
||||
<RepositoryType>Git</RepositoryType>
|
||||
<RootNamespace>Oqtane</RootNamespace>
|
||||
|
|
22
README.md
22
README.md
|
@ -1,6 +1,6 @@
|
|||
# Latest Release
|
||||
|
||||
[5.0.0](https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.0) was released on Nov 16, 2023 and is a major release targeted at .NET 8. This release includes 45 pull requests by 4 different contributors, pushing the total number of project commits all-time to over 4300. The Oqtane framework continues to evolve at a rapid pace to meet the needs of .NET developers.
|
||||
[5.0.1](https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.1) was released on Dec 21, 2023 and is a major release targeted at .NET 8. This release includes 67 pull requests by 6 different contributors, pushing the total number of project commits all-time to over 4400. The Oqtane framework continues to evolve at a rapid pace to meet the needs of .NET developers.
|
||||
|
||||
[](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2Foqtane%2Foqtane.framework%2Fmaster%2Fazuredeploy.json)
|
||||
|
||||
|
@ -19,10 +19,18 @@ Please note that this project is owned by the .NET Foundation and is governed by
|
|||
**Using Version 5:**
|
||||
|
||||
- Install **[.NET 8 SDK](https://dotnet.microsoft.com/download/dotnet/8.0)**.
|
||||
|
||||
|
||||
- Install the latest edition (v17.8 or higher) of [Visual Studio 2022](https://visualstudio.microsoft.com/downloads) with the **ASP.NET and web development** workload enabled. Oqtane works with ALL editions of Visual Studio from Community to Enterprise. If you wish to use LocalDB for development ( not a requirement as Oqtane supports SQLite, mySQL, and PostgreSQL ) you must also install the **Data storage and processing**.
|
||||
|
||||
- clone the Oqtane dev branch source code to your local system. Open the **Oqtane.sln** solution file and Build the solution. Make sure you specify Oqtane.Server as the Startup Project and then Run the application.
|
||||
- Clone the Oqtane dev branch source code to your local system.
|
||||
|
||||
- Open the **Oqtane.sln** solution file.
|
||||
|
||||
- **Important:** Build the solution.
|
||||
|
||||
- Make sure you specify Oqtane.Server as the Startup Project
|
||||
|
||||
- Run the application.
|
||||
|
||||
**Installing an official release:**
|
||||
|
||||
|
@ -39,6 +47,11 @@ Please note that this project is owned by the .NET Foundation and is governed by
|
|||
|
||||
- If you are getting started with Oqtane, a [series of videos](https://www.youtube.com/watch?v=JPfUZPlRRCE&list=PLYhXmd7yV0elLNLfQwZBUlM7ZSMYPTZ_f) are available which explain how to install the product, interact with the user interface, and develop custom modules.
|
||||
|
||||
# Oqtane Marketplace
|
||||
|
||||
Explore and enhance your Oqtane experience by visiting the Oqtane Marketplace. Discover a variety of modules, themes, and extensions contributed by the community. [Visit Oqtane Marketplace](https://www.oqtane.net)
|
||||
|
||||
|
||||
# Documentation
|
||||
There is a separate [Documentation repository](https://github.com/oqtane/oqtane.docs) which contains a variety of types of documentation for Oqtane, including API documentation that is auto generated using Docfx. The contents of the repository is published to Githib Pages and is available at [https://docs.oqtane.org](https://docs.oqtane.org/)
|
||||
|
||||
|
@ -53,6 +66,9 @@ Backlog (TBD)
|
|||
5.1.0 (Q1 2024)
|
||||
- [ ] Full Stack Blazor (Static Server-Side Rendering)
|
||||
|
||||
[5.0.1](https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.1) (Dec 21, 2023)
|
||||
- [x] Stabilization improvements
|
||||
|
||||
[5.0.0](https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.0) (Nov 16, 2023)
|
||||
- [x] Migration to .NET 8
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user