Merge branch 'oqtane:dev' into refs

This commit is contained in:
Tonći Vatavuk 2022-02-08 19:55:34 +01:00 committed by GitHub
commit 4eed2193f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 963 additions and 722 deletions

View File

@ -62,10 +62,6 @@
{
SiteState.Alias = _installation.Alias;
}
else
{
_installation.Message = "Site Not Configured Correctly - No Matching Alias Exists For Host Name";
}
_initialized = true;
}

View File

@ -110,7 +110,7 @@
</div>
</div>
}
<NavLink class="btn btn-secondary" href="@NavigateUrl(PageState.Page.Path, "level=" + PageState.QueryString["level"] + "&function=" + PageState.QueryString["function"] + "&rows=" + PageState.QueryString["rows"] + "&page=" + PageState.QueryString["page"])">@SharedLocalizer["Cancel"]</NavLink>
<NavLink class="btn btn-secondary" href="@CloseUrl()">@SharedLocalizer["Cancel"]</NavLink>
@code {
private bool _initialized = false;
@ -188,4 +188,16 @@
AddModuleMessage(Localizer["Error.Log.Load"], MessageType.Error);
}
}
private string CloseUrl()
{
if (!PageState.QueryString.ContainsKey("level"))
{
return NavigateUrl();
}
else
{
return NavigateUrl(PageState.Page.Path, "level=" + PageState.QueryString["level"] + "&function=" + PageState.QueryString["function"] + "&rows=" + PageState.QueryString["rows"] + "&page=" + PageState.QueryString["page"]);
}
}
}

View File

@ -95,6 +95,12 @@
<input id="title" class="form-control" @bind="@_title" />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="meta" HelpText="Optionally enter meta tags (in exactly the form you want them to be included in the page output)." ResourceKey="Meta">Meta: </Label>
<div class="col-sm-9">
<textarea id="meta" class="form-control" @bind="@_meta" rows="3"></textarea>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="theme" HelpText="Select the theme for this page" ResourceKey="Theme">Theme: </Label>
<div class="col-sm-9">
@ -156,220 +162,222 @@
</form>
@code {
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
private List<Theme> _themeList;
private List<ThemeControl> _themes = new List<ThemeControl>();
private List<ThemeControl> _containers = new List<ThemeControl>();
private List<Page> _pageList;
private string _name;
private string _title;
private string _path = string.Empty;
private string _parentid = "-1";
private string _insert = ">>";
private List<Page> _children;
private int _childid = -1;
private string _isnavigation = "True";
private string _isclickable = "True";
private string _url;
private string _ispersonalizable = "False";
private string _themetype = string.Empty;
private string _containertype = string.Empty;
private string _icon = string.Empty;
private string _permissions = string.Empty;
private PermissionGrid _permissionGrid;
private Type _themeSettingsType;
private object _themeSettings;
private RenderFragment ThemeSettingsComponent { get; set; }
private bool _refresh = false;
private ElementReference form;
private bool validated = false;
private List<Theme> _themeList;
private List<ThemeControl> _themes = new List<ThemeControl>();
private List<ThemeControl> _containers = new List<ThemeControl>();
private List<Page> _pageList;
private string _name;
private string _title;
private string _meta;
private string _path = string.Empty;
private string _parentid = "-1";
private string _insert = ">>";
private List<Page> _children;
private int _childid = -1;
private string _isnavigation = "True";
private string _isclickable = "True";
private string _url;
private string _ispersonalizable = "False";
private string _themetype = string.Empty;
private string _containertype = string.Empty;
private string _icon = string.Empty;
private string _permissions = string.Empty;
private PermissionGrid _permissionGrid;
private Type _themeSettingsType;
private object _themeSettings;
private RenderFragment ThemeSettingsComponent { get; set; }
private bool _refresh = false;
private ElementReference form;
private bool validated = false;
protected override async Task OnInitializedAsync()
{
try
{
_themeList = await ThemeService.GetThemesAsync();
_themes = ThemeService.GetThemeControls(_themeList);
_themetype = PageState.Site.DefaultThemeType;
_containers = ThemeService.GetContainerControls(_themeList, _themetype);
_containertype = PageState.Site.DefaultContainerType;
_pageList = PageState.Pages;
_children = PageState.Pages.Where(item => item.ParentId == null).ToList();
_permissions = string.Empty;
ThemeSettings();
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Initializing Page {Error}", ex.Message);
AddModuleMessage(Localizer["Error.Page.Initialize"], MessageType.Error);
}
}
protected override async Task OnInitializedAsync()
{
try
{
_themeList = await ThemeService.GetThemesAsync();
_themes = ThemeService.GetThemeControls(_themeList);
_themetype = PageState.Site.DefaultThemeType;
_containers = ThemeService.GetContainerControls(_themeList, _themetype);
_containertype = PageState.Site.DefaultContainerType;
_pageList = PageState.Pages;
_children = PageState.Pages.Where(item => item.ParentId == null).ToList();
_permissions = string.Empty;
ThemeSettings();
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Initializing Page {Error}", ex.Message);
AddModuleMessage(Localizer["Error.Page.Initialize"], MessageType.Error);
}
}
private async void ParentChanged(ChangeEventArgs e)
{
try
{
_parentid = (string)e.Value;
_children = new List<Page>();
if (_parentid == "-1")
{
foreach (Page p in PageState.Pages.Where(item => item.ParentId == null))
{
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, p.Permissions))
{
_children.Add(p);
}
}
}
else
{
foreach (Page p in PageState.Pages.Where(item => item.ParentId == int.Parse(_parentid)))
{
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, p.Permissions))
{
_children.Add(p);
}
}
}
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);
}
}
private async void ParentChanged(ChangeEventArgs e)
{
try
{
_parentid = (string)e.Value;
_children = new List<Page>();
if (_parentid == "-1")
{
foreach (Page p in PageState.Pages.Where(item => item.ParentId == null))
{
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, p.Permissions))
{
_children.Add(p);
}
}
}
else
{
foreach (Page p in PageState.Pages.Where(item => item.ParentId == int.Parse(_parentid)))
{
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, p.Permissions))
{
_children.Add(p);
}
}
}
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);
}
}
private async void ThemeChanged(ChangeEventArgs e)
{
try
{
_themetype = (string)e.Value;
_containers = ThemeService.GetContainerControls(_themeList, _themetype);
_containertype = "-";
ThemeSettings();
StateHasChanged();
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Loading Pane Layouts For Theme {ThemeType} {Error}", _themetype, ex.Message);
AddModuleMessage(Localizer["Error.Pane.Load"], MessageType.Error);
}
}
private async void ThemeChanged(ChangeEventArgs e)
{
try
{
_themetype = (string)e.Value;
_containers = ThemeService.GetContainerControls(_themeList, _themetype);
_containertype = "-";
ThemeSettings();
StateHasChanged();
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Loading Pane Layouts For Theme {ThemeType} {Error}", _themetype, ex.Message);
AddModuleMessage(Localizer["Error.Pane.Load"], MessageType.Error);
}
}
private void ThemeSettings()
{
_themeSettingsType = null;
var theme = _themeList.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;
}
}
private void ThemeSettings()
{
_themeSettingsType = null;
var theme = _themeList.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;
}
}
private async Task SavePage()
{
validated = true;
var interop = new Interop(JSRuntime);
if (await interop.FormValid(form))
{
Page page = null;
try
{
if (!string.IsNullOrEmpty(_themetype) && _containertype != "-")
{
page = new Page();
page.SiteId = PageState.Page.SiteId;
page.Name = _name;
page.Title = _title;
private async Task SavePage()
{
validated = true;
var interop = new Interop(JSRuntime);
if (await interop.FormValid(form))
{
Page page = null;
try
{
if (!string.IsNullOrEmpty(_themetype) && _containertype != "-")
{
page = new Page();
page.SiteId = PageState.Page.SiteId;
page.Name = _name;
page.Title = _title;
if (string.IsNullOrEmpty(_path))
{
_path = _name;
}
if (_path.Contains("/"))
{
_path = _path.Substring(_path.LastIndexOf("/") + 1);
}
if (string.IsNullOrEmpty(_path))
{
_path = _name;
}
if (_path.Contains("/"))
{
_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);
}
}
if(PagePathIsDeleted(page.Path, page.SiteId, _pageList))
{
AddModuleMessage(string.Format(Localizer["Message.Page.Deleted"], _path), MessageType.Warning);
return;
}
if(PagePathIsDeleted(page.Path, page.SiteId, _pageList))
{
AddModuleMessage(string.Format(Localizer["Message.Page.Deleted"], _path), MessageType.Warning);
return;
}
if (!PagePathIsUnique(page.Path, page.SiteId, _pageList))
{
AddModuleMessage(string.Format(Localizer["Message.Page.Exists"], _path), MessageType.Warning);
return;
}
if (!PagePathIsUnique(page.Path, page.SiteId, _pageList))
{
AddModuleMessage(string.Format(Localizer["Message.Page.Exists"], _path), 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.Url = _url;
page.ThemeType = (_themetype != "-") ? _themetype : string.Empty;
if (!string.IsNullOrEmpty(page.ThemeType) && page.ThemeType == PageState.Site.DefaultThemeType)
{
page.ThemeType = string.Empty;
}
page.DefaultContainerType = (_containertype != "-") ? _containertype : string.Empty;
if (!string.IsNullOrEmpty(page.DefaultContainerType) && page.DefaultContainerType == PageState.Site.DefaultContainerType)
{
page.DefaultContainerType = string.Empty;
}
page.Icon = (_icon == null ? string.Empty : _icon);
page.Permissions = _permissionGrid.GetPermissions();
page.IsPersonalizable = (_ispersonalizable == null ? false : Boolean.Parse(_ispersonalizable));
page.UserId = null;
page.IsNavigation = (_isnavigation == null ? true : Boolean.Parse(_isnavigation));
page.IsClickable = (_isclickable == null ? true : Boolean.Parse(_isclickable));
page.Url = _url;
page.ThemeType = (_themetype != "-") ? _themetype : string.Empty;
if (!string.IsNullOrEmpty(page.ThemeType) && page.ThemeType == PageState.Site.DefaultThemeType)
{
page.ThemeType = string.Empty;
}
page.DefaultContainerType = (_containertype != "-") ? _containertype : string.Empty;
if (!string.IsNullOrEmpty(page.DefaultContainerType) && page.DefaultContainerType == PageState.Site.DefaultContainerType)
{
page.DefaultContainerType = string.Empty;
}
page.Icon = (_icon == null ? string.Empty : _icon);
page.Permissions = _permissionGrid.GetPermissions();
page.IsPersonalizable = (_ispersonalizable == null ? false : Boolean.Parse(_ispersonalizable));
page.UserId = null;
page.Meta = _meta;
page = await PageService.AddPageAsync(page);
await PageService.UpdatePageOrderAsync(page.SiteId, page.PageId, page.ParentId);

View File

@ -102,6 +102,12 @@
<input id="title" class="form-control" @bind="@_title" maxlength="200"/>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="meta" HelpText="Optionally enter meta tags (in exactly the form you want them to be included in the page output)." ResourceKey="Meta">Meta: </Label>
<div class="col-sm-9">
<textarea id="meta" class="form-control" @bind="@_meta" rows="3"></textarea>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="theme" HelpText="Select the theme for this page" ResourceKey="Theme">Theme: </Label>
<div class="col-sm-9">
@ -200,6 +206,7 @@
private int _pageId;
private string _name;
private string _title;
private string _meta;
private string _path;
private string _currentparentid;
private string _parentid = "-1";
@ -243,6 +250,7 @@
{
_name = page.Name;
_title = page.Title;
_meta = page.Meta;
_path = page.Path;
_pageModules = PageState.Modules.Where(m => m.PageId == page.PageId && m.IsDeleted == false).ToList();
@ -313,77 +321,77 @@
_pageModules.RemoveAll(item => item.PageModuleId == pagemodule.PageModuleId);
StateHasChanged();
NavigationManager.NavigateTo(NavigationManager.Uri + "&tab=PageModules");
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Deleting Module {Title} {Error}", module.Title, ex.Message);
AddModuleMessage(Localizer["Error.Module.Delete"], MessageType.Error);
}
}
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Deleting Module {Title} {Error}", module.Title, ex.Message);
AddModuleMessage(Localizer["Error.Module.Delete"], MessageType.Error);
}
}
private async void ParentChanged(ChangeEventArgs e)
{
try
{
_parentid = (string)e.Value;
_children = new List<Page>();
if (_parentid == "-1")
{
foreach (Page p in PageState.Pages.Where(item => item.ParentId == null))
{
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, p.Permissions))
{
_children.Add(p);
}
}
}
else
{
foreach (Page p in PageState.Pages.Where(item => item.ParentId == int.Parse(_parentid)))
{
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, p.Permissions))
{
_children.Add(p);
}
}
}
if (_parentid == _currentparentid)
{
_insert = "=";
}
else
{
_insert = ">>";
}
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);
}
}
private async void ParentChanged(ChangeEventArgs e)
{
try
{
_parentid = (string)e.Value;
_children = new List<Page>();
if (_parentid == "-1")
{
foreach (Page p in PageState.Pages.Where(item => item.ParentId == null))
{
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, p.Permissions))
{
_children.Add(p);
}
}
}
else
{
foreach (Page p in PageState.Pages.Where(item => item.ParentId == int.Parse(_parentid)))
{
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, p.Permissions))
{
_children.Add(p);
}
}
}
if (_parentid == _currentparentid)
{
_insert = "=";
}
else
{
_insert = ">>";
}
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);
}
}
private async void ThemeChanged(ChangeEventArgs e)
{
try
{
_themetype = (string)e.Value;
_containers = ThemeService.GetContainerControls(_themeList, _themetype);
_containertype = "-";
ThemeSettings();
StateHasChanged();
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Loading Pane Layouts For Theme {ThemeType} {Error}", _themetype, ex.Message);
AddModuleMessage(Localizer["Error.Pane.Load"], MessageType.Error);
}
}
private async void ThemeChanged(ChangeEventArgs e)
{
try
{
_themetype = (string)e.Value;
_containers = ThemeService.GetContainerControls(_themeList, _themetype);
_containertype = "-";
ThemeSettings();
StateHasChanged();
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Loading Pane Layouts For Theme {ThemeType} {Error}", _themetype, ex.Message);
AddModuleMessage(Localizer["Error.Pane.Load"], MessageType.Error);
}
}
private void ThemeSettings()
{
_themeSettingsType = null;
private void ThemeSettings()
{
_themeSettingsType = null;
if (PageState.QueryString.ContainsKey("cp")) // can only be displayed if invoked from Control Panel
{
var theme = _themeList.FirstOrDefault(item => item.Themes.Any(themecontrol => themecontrol.TypeName.Equals(_themetype)));
@ -402,97 +410,98 @@
_refresh = true;
}
}
}
}
private async Task SavePage()
{
validated = true;
var interop = new Interop(JSRuntime);
if (await interop.FormValid(form))
{
Page page = null;
try
{
if (!string.IsNullOrEmpty(_themetype) && _containertype != "-")
{
page = PageState.Pages.FirstOrDefault(item => item.PageId == _pageId);
string currentPath = page.Path;
private async Task SavePage()
{
validated = true;
var interop = new Interop(JSRuntime);
if (await interop.FormValid(form))
{
Page page = null;
try
{
if (!string.IsNullOrEmpty(_themetype) && _containertype != "-")
{
page = PageState.Pages.FirstOrDefault(item => item.PageId == _pageId);
string currentPath = page.Path;
page.Name = _name;
page.Title = _title;
page.Name = _name;
page.Title = _title;
if (string.IsNullOrEmpty(_path))
{
_path = _name;
}
if (_path.Contains("/"))
{
_path = _path.Substring(_path.LastIndexOf("/") + 1);
}
if (string.IsNullOrEmpty(_path))
{
_path = _name;
}
if (_path.Contains("/"))
{
_path = _path.Substring(_path.LastIndexOf("/") + 1);
}
if (_parentid == "-1")
{
page.ParentId = null;
page.Path = Utilities.GetFriendlyUrl(_path);
}
else
{
page.ParentId = Int32.Parse(_parentid);
Page parent = PageState.Pages.FirstOrDefault(item => item.PageId == page.ParentId);
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);
Page parent = PageState.Pages.FirstOrDefault(item => item.PageId == page.ParentId);
if (parent.Path == string.Empty)
{
page.Path = Utilities.GetFriendlyUrl(parent.Name) + "/" + Utilities.GetFriendlyUrl(_path);
}
else
{
page.Path = parent.Path + "/" + Utilities.GetFriendlyUrl(_path);
}
}
if (!PagePathIsUnique(page.Path, page.SiteId, page.PageId, _pageList))
{
AddModuleMessage(string.Format(Localizer["Mesage.Page.PathExists"], _path), MessageType.Warning);
return;
}
if (!PagePathIsUnique(page.Path, page.SiteId, page.PageId, _pageList))
{
AddModuleMessage(string.Format(Localizer["Mesage.Page.PathExists"], _path), MessageType.Warning);
return;
}
if (_insert != "=")
{
Page child;
switch (_insert)
{
case "<<":
page.Order = 0;
break;
case "<":
child = PageState.Pages.FirstOrDefault(item => item.PageId == _childid);
if (child != null) page.Order = child.Order - 1;
break;
case ">":
child = PageState.Pages.FirstOrDefault(item => item.PageId == _childid);
if (child != null) page.Order = child.Order + 1;
break;
case ">>":
page.Order = int.MaxValue;
break;
}
}
page.IsNavigation = (_isnavigation == null || Boolean.Parse(_isnavigation));
page.IsClickable = (_isclickable == null ? true : Boolean.Parse(_isclickable));
page.Url = _url;
page.ThemeType = (_themetype != "-") ? _themetype : string.Empty;
if (!string.IsNullOrEmpty(page.ThemeType) && page.ThemeType == PageState.Site.DefaultThemeType)
{
page.ThemeType = string.Empty;
}
page.DefaultContainerType = (_containertype != "-") ? _containertype : string.Empty;
if (!string.IsNullOrEmpty(page.DefaultContainerType) && page.DefaultContainerType == PageState.Site.DefaultContainerType)
{
page.DefaultContainerType = string.Empty;
}
page.Icon = _icon ?? string.Empty;
page.Permissions = _permissionGrid.GetPermissions();
page.IsPersonalizable = (_ispersonalizable != null && Boolean.Parse(_ispersonalizable));
page.UserId = null;
if (_insert != "=")
{
Page child;
switch (_insert)
{
case "<<":
page.Order = 0;
break;
case "<":
child = PageState.Pages.FirstOrDefault(item => item.PageId == _childid);
if (child != null) page.Order = child.Order - 1;
break;
case ">":
child = PageState.Pages.FirstOrDefault(item => item.PageId == _childid);
if (child != null) page.Order = child.Order + 1;
break;
case ">>":
page.Order = int.MaxValue;
break;
}
}
page.IsNavigation = (_isnavigation == null || Boolean.Parse(_isnavigation));
page.IsClickable = (_isclickable == null ? true : Boolean.Parse(_isclickable));
page.Url = _url;
page.ThemeType = (_themetype != "-") ? _themetype : string.Empty;
if (!string.IsNullOrEmpty(page.ThemeType) && page.ThemeType == PageState.Site.DefaultThemeType)
{
page.ThemeType = string.Empty;
}
page.DefaultContainerType = (_containertype != "-") ? _containertype : string.Empty;
if (!string.IsNullOrEmpty(page.DefaultContainerType) && page.DefaultContainerType == PageState.Site.DefaultContainerType)
{
page.DefaultContainerType = string.Empty;
}
page.Icon = _icon ?? string.Empty;
page.Permissions = _permissionGrid.GetPermissions();
page.IsPersonalizable = (_ispersonalizable != null && Boolean.Parse(_ispersonalizable));
page.UserId = null;
page.Meta = _meta;
page = await PageService.UpdatePageAsync(page);
await PageService.UpdatePageOrderAsync(page.SiteId, page.PageId, page.ParentId);

View File

@ -25,7 +25,7 @@
<th>@Localizer["DeletedOn"]</th>
</Header>
<Row>
<td><button type="button" @onclick="@(() => RestorePage(context))" class="btn btn-info" title="Restore">Restore</button></td>
<td><button type="button" @onclick="@(() => RestorePage(context))" class="btn btn-success" title="Restore">Restore</button></td>
<td><ActionDialog Header="Delete Page" Message="@string.Format(Localizer["Confirm.Page.Delete"], context.Name)" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeletePage(context))" ResourceKey="DeletePage" /></td>
<td>@context.Name</td>
<td>@context.DeletedBy</td>
@ -56,7 +56,7 @@
<th>@Localizer["DeletedOn"]</th>
</Header>
<Row>
<td><button type="button" @onclick="@(() => RestoreModule(context))" class="btn btn-info" title="Restore">@Localizer["Restore"]</button></td>
<td><button type="button" @onclick="@(() => RestoreModule(context))" class="btn btn-success" title="Restore">@Localizer["Restore"]</button></td>
<td><ActionDialog Header="Delete Module" Message="@string.Format(Localizer["Confirm.Module.Delete"], context.Title)" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteModule(context))" ResourceKey="DeleteModule" /></td>
<td>@PageState.Pages.Find(item => item.PageId == context.PageId).Name</td>
<td>@context.Title</td>

View File

@ -70,7 +70,7 @@
</div>
}
<NavLink class="btn btn-secondary" href="@NavigateUrl(PageState.Page.Path, "type=" + PageState.QueryString["type"] + "&days=" + PageState.QueryString["days"] + "&page=" + PageState.QueryString["page"])">@SharedLocalizer["Cancel"]</NavLink>
<NavLink class="btn btn-secondary" href="@CloseUrl()">@SharedLocalizer["Cancel"]</NavLink>
@code {
private bool _initialized = false;
@ -125,4 +125,16 @@
AddModuleMessage(Localizer["Error.LoadVisitor"], MessageType.Error);
}
}
private string CloseUrl()
{
if (!PageState.QueryString.ContainsKey("type"))
{
return NavigateUrl();
}
else
{
return NavigateUrl(PageState.Page.Path, "type=" + PageState.QueryString["type"] + "&days=" + PageState.QueryString["days"] + "&page=" + PageState.QueryString["page"]);
}
}
}

View File

@ -71,11 +71,11 @@
</div>
@if (ReadOnly)
{
<textarea class="form-control" placeholder="@Placeholder" @bind="@_content" rows="10" readonly></textarea>
<textarea class="form-control" placeholder="@Placeholder" @bind="@_rawhtml" rows="10" readonly></textarea>
}
else
{
<textarea class="form-control" placeholder="@Placeholder" @bind="@_content" rows="10"></textarea>
<textarea class="form-control" placeholder="@Placeholder" @bind="@_rawhtml" rows="10"></textarea>
}
</TabPanel>
</TabStrip>
@ -83,110 +83,121 @@
</div>
@code {
private ElementReference _editorElement;
private ElementReference _toolBar;
private bool _filemanagervisible = false;
private FileManager _fileManager;
private string _content = string.Empty;
private string _original = string.Empty;
private string _message = string.Empty;
private ElementReference _editorElement;
private ElementReference _toolBar;
private bool _filemanagervisible = false;
private FileManager _fileManager;
private string _richhtml = string.Empty;
private string _originalrichhtml = string.Empty;
private string _rawhtml = string.Empty;
private string _originalrawhtml = string.Empty;
private string _message = string.Empty;
[Parameter]
public string Content { get; set; }
[Parameter]
public string Content { get; set; }
[Parameter]
public bool ReadOnly { get; set; } = false;
[Parameter]
public bool ReadOnly { get; set; } = false;
[Parameter]
public string Placeholder { get; set; } = "Enter Your Content...";
[Parameter]
public string Placeholder { get; set; } = "Enter Your Content...";
// parameters only applicable to rich text editor
[Parameter]
public RenderFragment ToolbarContent { get; set; }
// parameters only applicable to rich text editor
[Parameter]
public RenderFragment ToolbarContent { get; set; }
[Parameter]
public string Theme { get; set; } = "snow";
[Parameter]
public string Theme { get; set; } = "snow";
[Parameter]
public string DebugLevel { get; set; } = "info";
[Parameter]
public string DebugLevel { get; set; } = "info";
[Parameter]
public bool AllowFileManagement { get; set; } = true;
[Parameter]
public bool AllowFileManagement { get; set; } = true;
public override List<Resource> Resources => new List<Resource>()
public override List<Resource> Resources => new List<Resource>()
{
new Resource { ResourceType = ResourceType.Script, Bundle = "Quill", Url = "js/quill.min.js" },
new Resource { ResourceType = ResourceType.Script, Bundle = "Quill", Url = "js/quill-blot-formatter.min.js" },
new Resource { ResourceType = ResourceType.Script, Bundle = "Quill", Url = "js/quill-interop.js" }
};
protected override async Task OnParametersSetAsync()
{
_content = Content; // raw HTML
await RefreshRichText();
}
protected override void OnParametersSet()
{
_richhtml = Content;
_rawhtml = Content;
_originalrawhtml = _rawhtml; // preserve for comparison later
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
protected override async Task OnAfterRenderAsync(bool firstRender)
{
await base.OnAfterRenderAsync(firstRender);
var interop = new RichTextEditorInterop(JSRuntime);
if (firstRender)
{
await interop.CreateEditor(
_editorElement,
_toolBar,
ReadOnly,
Placeholder,
Theme,
DebugLevel);
await interop.LoadEditorContent(_editorElement, _richhtml);
// 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);
}
else
{
await interop.LoadEditorContent(_editorElement, _richhtml);
}
}
public void CloseFileManager()
{
_filemanagervisible = false;
_message = string.Empty;
StateHasChanged();
}
public void RefreshRichText()
{
_richhtml = _rawhtml;
StateHasChanged();
}
public async Task RefreshRawHtml()
{
var interop = new RichTextEditorInterop(JSRuntime);
_rawhtml = await interop.GetHtml(_editorElement);
StateHasChanged();
}
public async Task<string> GetHtml()
{
// evaluate raw html content as first priority
if (_rawhtml != _originalrawhtml)
{
return _rawhtml;
}
else
{
// return rich text content if it has changed
var interop = new RichTextEditorInterop(JSRuntime);
await base.OnAfterRenderAsync(firstRender);
await interop.CreateEditor(
_editorElement,
_toolBar,
ReadOnly,
Placeholder,
Theme,
DebugLevel);
await interop.LoadEditorContent(_editorElement, Content);
_content = Content; // raw HTML
// preserve a copy of the rich text content ( Quill sanitizes content so we need to retrieve it from the editor )
_original = await interop.GetHtml(_editorElement);
}
}
public void CloseFileManager()
{
_filemanagervisible = false;
_message = string.Empty;
StateHasChanged();
}
public async Task RefreshRichText()
{
var interop = new RichTextEditorInterop(JSRuntime);
await interop.LoadEditorContent(_editorElement, _content);
}
public async Task RefreshRawHtml()
{
var interop = new RichTextEditorInterop(JSRuntime);
_content = await interop.GetHtml(_editorElement);
StateHasChanged();
}
public async Task<string> GetHtml()
{
// get rich text content
var interop = new RichTextEditorInterop(JSRuntime);
string content = await interop.GetHtml(_editorElement);
if (_original != content)
{
// rich text content has changed - return it
return content;
}
else
{
// return raw html content
return _content;
}
var richhtml = await interop.GetHtml(_editorElement);
if (richhtml != _originalrichhtml)
{
return richhtml;
}
else
{
// return original raw html content
return _originalrawhtml;
}
}
}
public async Task InsertImage()
@ -212,23 +223,4 @@
}
StateHasChanged();
}
// other rich text editor methods which can be used by developers
public async Task<string> GetText()
{
var interop = new RichTextEditorInterop(JSRuntime);
return await interop.GetText(_editorElement);
}
public async Task<string> GetContent()
{
var interop = new RichTextEditorInterop(JSRuntime);
return await interop.GetContent(_editorElement);
}
public async Task EnableEditor(bool mode)
{
var interop = new RichTextEditorInterop(JSRuntime);
await interop.EnableEditor(_editorElement, mode);
}
}

View File

@ -9,95 +9,186 @@
@inject IStringLocalizer<Edit> Localizer
@inject IStringLocalizer<SharedResources> SharedLocalizer
@if (_content != null)
{
<RichTextEditor Content="@_content" AllowFileManagement="@_allowfilemanagement" @ref="@RichTextEditorHtml"></RichTextEditor>
<button type="button" class="btn btn-success" @onclick="SaveContent">@SharedLocalizer["Save"]</button>
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
@if (!string.IsNullOrEmpty(_content))
{
<br />
<br />
<AuditInfo CreatedBy="@_createdby" CreatedOn="@_createdon" ModifiedBy="@_modifiedby" ModifiedOn="@_modifiedon"></AuditInfo>
}
}
<TabStrip>
<TabPanel Name="Edit" Heading="Edit" ResourceKey="Edit">
@if (_content != null)
{
<RichTextEditor Content="@_content" AllowFileManagement="@_allowfilemanagement" @ref="@RichTextEditorHtml"></RichTextEditor>
<br />
<button type="button" class="btn btn-success" @onclick="SaveContent">@SharedLocalizer["Save"]</button>
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
@if (!string.IsNullOrEmpty(_content))
{
<br />
<br />
<AuditInfo CreatedBy="@_createdby" CreatedOn="@_createdon" ModifiedBy="@_modifiedby" ModifiedOn="@_modifiedon"></AuditInfo>
}
}
</TabPanel>
<TabPanel Name="Versions" Heading="Versions" ResourceKey="Versions">
<Pager Items="@_htmltexts">
<Header>
<th style="width: 1px;">&nbsp;</th>
<th style="width: 1px;">&nbsp;</th>
<th style="width: 1px;">&nbsp;</th>
<th>@SharedLocalizer["CreatedOn"]</th>
<th>@SharedLocalizer["CreatedBy"]</th>
</Header>
<Row>
<td><ActionLink Action="View" Security="SecurityAccessLevel.Edit" OnClick="@(async () => await View(context))" ResourceKey="View" /></td>
<td><ActionDialog Header="Restore Version" Message="@string.Format(Localizer["Confirm.Restore"], context.CreatedOn)" Action="Restore" Security="SecurityAccessLevel.Edit" Class="btn btn-success" OnClick="@(async () => await Restore(context))" ResourceKey="Restore" /></td>
<td><ActionDialog Header="Delete Version" Message="@string.Format(Localizer["Confirm.Delete"], context.CreatedOn)" Action="Delete" Security="SecurityAccessLevel.Edit" Class="btn btn-danger" OnClick="@(async () => await Delete(context))" ResourceKey="Delete" /></td>
<td>@context.CreatedOn</td>
<td>@context.CreatedBy</td>
</Row>
</Pager>
@((MarkupString)_view)
</TabPanel>
</TabStrip>
@code {
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
public override string Title => "Edit Html/Text";
public override string Title => "Edit Html/Text";
public override List<Resource> Resources => new List<Resource>()
{
public override List<Resource> Resources => new List<Resource>()
{
new Resource { ResourceType = ResourceType.Stylesheet, Url = ModulePath() + "Module.css" },
new Resource { ResourceType = ResourceType.Stylesheet, Url = "css/quill/quill.bubble.css" },
new Resource { ResourceType = ResourceType.Stylesheet, Url = "css/quill/quill.snow.css" }
};
private RichTextEditor RichTextEditorHtml;
private bool _allowfilemanagement;
private string _content = null;
private string _createdby;
private DateTime _createdon;
private string _modifiedby;
private DateTime _modifiedon;
private RichTextEditor RichTextEditorHtml;
private bool _allowfilemanagement;
private string _content = null;
private string _createdby;
private DateTime _createdon;
private string _modifiedby;
private DateTime _modifiedon;
private List<Models.HtmlText> _htmltexts;
private string _view = "";
protected override async Task OnInitializedAsync()
{
try
{
_allowfilemanagement = bool.Parse(SettingService.GetSetting(ModuleState.Settings, "AllowFileManagement", "true"));
protected override async Task OnInitializedAsync()
{
try
{
_allowfilemanagement = bool.Parse(SettingService.GetSetting(ModuleState.Settings, "AllowFileManagement", "true"));
await LoadContent();
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Loading Content {Error}", ex.Message);
AddModuleMessage(Localizer["Error.Content.Load"], MessageType.Error);
}
}
var htmltext = await HtmlTextService.GetHtmlTextAsync(ModuleState.ModuleId);
if (htmltext != null)
{
_content = htmltext.Content;
_content = Utilities.FormatContent(_content, PageState.Alias, "render");
_createdby = htmltext.CreatedBy;
_createdon = htmltext.CreatedOn;
_modifiedby = htmltext.ModifiedBy;
_modifiedon = htmltext.ModifiedOn;
}
else
{
_content = string.Empty;
}
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Loading Content {Error}", ex.Message);
AddModuleMessage(Localizer["Error.Content.Load"], MessageType.Error);
}
}
private async Task LoadContent()
{
var htmltext = await HtmlTextService.GetHtmlTextAsync(ModuleState.ModuleId);
if (htmltext != null)
{
_content = htmltext.Content;
_content = Utilities.FormatContent(_content, PageState.Alias, "render");
_createdby = htmltext.CreatedBy;
_createdon = htmltext.CreatedOn;
_modifiedby = htmltext.ModifiedBy;
_modifiedon = htmltext.ModifiedOn;
}
else
{
_content = string.Empty;
}
private async Task SaveContent()
{
string content = await RichTextEditorHtml.GetHtml();
content = Utilities.FormatContent(content, PageState.Alias, "save");
_htmltexts = await HtmlTextService.GetHtmlTextsAsync(ModuleState.ModuleId);
_htmltexts = _htmltexts.OrderByDescending(item => item.CreatedOn).ToList();
try
{
var htmltext = await HtmlTextService.GetHtmlTextAsync(ModuleState.ModuleId);
if (htmltext != null)
{
htmltext.Content = content;
await HtmlTextService.UpdateHtmlTextAsync(htmltext);
}
else
{
htmltext = new HtmlText();
htmltext.ModuleId = ModuleState.ModuleId;
htmltext.Content = content;
await HtmlTextService.AddHtmlTextAsync(htmltext);
}
_view = "";
}
await logger.LogInformation("Content Saved {HtmlText}", htmltext);
NavigationManager.NavigateTo(NavigateUrl());
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Saving Content {Error}", ex.Message);
AddModuleMessage(Localizer["Error.Content.Save"], MessageType.Error);
}
}
private async Task SaveContent()
{
string content = await RichTextEditorHtml.GetHtml();
content = Utilities.FormatContent(content, PageState.Alias, "save");
try
{
var htmltext = new HtmlText();
htmltext.ModuleId = ModuleState.ModuleId;
htmltext.Content = content;
await HtmlTextService.AddHtmlTextAsync(htmltext);
await logger.LogInformation("Content Saved {HtmlText}", htmltext);
NavigationManager.NavigateTo(NavigateUrl());
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Saving Content {Error}", ex.Message);
AddModuleMessage(Localizer["Error.Content.Save"], MessageType.Error);
}
}
private async Task View(Models.HtmlText htmltext)
{
try
{
htmltext = await HtmlTextService.GetHtmlTextAsync(htmltext.HtmlTextId, htmltext.ModuleId);
if (htmltext != null)
{
_view = htmltext.Content;
_view = Utilities.FormatContent(_view, PageState.Alias, "render");
StateHasChanged();
}
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Viewing Content {Error}", ex.Message);
AddModuleMessage(Localizer["Error.Content.View"], MessageType.Error);
}
}
private async Task Restore(Models.HtmlText htmltext)
{
try
{
htmltext = await HtmlTextService.GetHtmlTextAsync(htmltext.HtmlTextId, ModuleState.ModuleId);
if (htmltext != null)
{
var content = htmltext.Content;
htmltext = new HtmlText();
htmltext.ModuleId = ModuleState.ModuleId;
htmltext.Content = content;
await HtmlTextService.AddHtmlTextAsync(htmltext);
await logger.LogInformation("Content Restored {HtmlText}", htmltext);
AddModuleMessage(Localizer["Message.Content.Restored"], MessageType.Success);
await LoadContent();
StateHasChanged();
}
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Restoring Content {Error}", ex.Message);
AddModuleMessage(Localizer["Error.Content.Restore"], MessageType.Error);
}
}
private async Task Delete(Models.HtmlText htmltext)
{
try
{
htmltext = await HtmlTextService.GetHtmlTextAsync(htmltext.HtmlTextId, ModuleState.ModuleId);
if (htmltext != null)
{
await HtmlTextService.DeleteHtmlTextAsync(htmltext.HtmlTextId, htmltext.ModuleId);
await logger.LogInformation("Content Deleted {HtmlText}", htmltext);
AddModuleMessage(Localizer["Message.Content.Deleted"], MessageType.Success);
await LoadContent();
StateHasChanged();
}
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Deleting Content {Error}", ex.Message);
AddModuleMessage(Localizer["Error.Content.Delete"], MessageType.Error);
}
}
}

View File

@ -1,3 +1,5 @@
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Oqtane.Documentation;
@ -13,24 +15,29 @@ namespace Oqtane.Modules.HtmlText.Services
private string ApiUrl => CreateApiUrl("HtmlText");
public async Task<List<Models.HtmlText>> GetHtmlTextsAsync(int moduleId)
{
return await GetJsonAsync<List<Models.HtmlText>>(CreateAuthorizationPolicyUrl($"{ApiUrl}?moduleid={moduleId}", EntityNames.Module, moduleId));
}
public async Task<Models.HtmlText> GetHtmlTextAsync(int moduleId)
{
return await GetJsonAsync<Models.HtmlText>(CreateAuthorizationPolicyUrl($"{ApiUrl}/{moduleId}", EntityNames.Module, moduleId));
}
public async Task<Models.HtmlText> GetHtmlTextAsync(int htmlTextId, int moduleId)
{
return await GetJsonAsync<Models.HtmlText>(CreateAuthorizationPolicyUrl($"{ApiUrl}/{htmlTextId}/{moduleId}", EntityNames.Module, moduleId));
}
public async Task AddHtmlTextAsync(Models.HtmlText htmlText)
{
await PostJsonAsync(CreateAuthorizationPolicyUrl($"{ApiUrl}", EntityNames.Module, htmlText.ModuleId), htmlText);
}
public async Task UpdateHtmlTextAsync(Models.HtmlText htmlText)
public async Task DeleteHtmlTextAsync(int htmlTextId, int moduleId)
{
await PutJsonAsync(CreateAuthorizationPolicyUrl($"{ApiUrl}/{htmlText.HtmlTextId}", EntityNames.Module, htmlText.ModuleId), htmlText);
}
public async Task DeleteHtmlTextAsync(int moduleId)
{
await DeleteAsync(CreateAuthorizationPolicyUrl($"{ApiUrl}/{moduleId}", EntityNames.Module, moduleId));
await DeleteAsync(CreateAuthorizationPolicyUrl($"{ApiUrl}/{htmlTextId}/{moduleId}", EntityNames.Module, moduleId));
}
}
}

View File

@ -1,19 +1,20 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Oqtane.Documentation;
using Oqtane.Modules.HtmlText.Models;
namespace Oqtane.Modules.HtmlText.Services
{
[PrivateApi("Mark HtmlText classes as private, since it's not very useful in the public docs")]
public interface IHtmlTextService
{
Task<Models.HtmlText> GetHtmlTextAsync(int ModuleId);
Task<List<Models.HtmlText>> GetHtmlTextsAsync(int moduleId);
Task<Models.HtmlText> GetHtmlTextAsync(int moduleId);
Task<Models.HtmlText> GetHtmlTextAsync(int htmlTextId, int moduleId);
Task AddHtmlTextAsync(Models.HtmlText htmltext);
Task UpdateHtmlTextAsync(Models.HtmlText htmltext);
Task DeleteHtmlTextAsync(int ModuleId);
Task DeleteHtmlTextAsync(int htmlTextId, int moduleId);
}
}

View File

@ -231,4 +231,10 @@
<data name="Message.Page.Deleted" xml:space="preserve">
<value>A page with path {0} already exists for the selected parent page in the Recycle Bin. Either recover the page or remove from the Recycle Bin and create it again.</value>
</data>
<data name="Meta.HelpText" xml:space="preserve">
<value>Optionally enter meta tags (in exactly the form you want them to be included in the page output).</value>
</data>
<data name="Meta.Text" xml:space="preserve">
<value>Meta:</value>
</data>
</root>

View File

@ -264,4 +264,10 @@
<data name="Clickable.Text" xml:space="preserve">
<value>Clickable?</value>
</data>
<data name="Meta.HelpText" xml:space="preserve">
<value>Optionally enter meta tags (in exactly the form you want them to be included in the page output).</value>
</data>
<data name="Meta.Text" xml:space="preserve">
<value>Meta:</value>
</data>
</root>

View File

@ -117,10 +117,52 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Confirm.Delete" xml:space="preserve">
<value>Are You Sure You Wish To Delete The {0} Version?</value>
</data>
<data name="Confirm.Restore" xml:space="preserve">
<value>Are You Sure You Wish To Restore The {0} Version?</value>
</data>
<data name="CreatedBy" xml:space="preserve">
<value>Created By</value>
</data>
<data name="CreatedOn" xml:space="preserve">
<value>Created On</value>
</data>
<data name="Delete.Header" xml:space="preserve">
<value>Delete Version</value>
</data>
<data name="Delete.Text" xml:space="preserve">
<value>Delete</value>
</data>
<data name="Error.Content.Delete" xml:space="preserve">
<value>Error Deleting Version</value>
</data>
<data name="Error.Content.Load" xml:space="preserve">
<value>An Error Occurred Loading Content</value>
</data>
<data name="Error.Content.Restore" xml:space="preserve">
<value>Error Restoring Version</value>
</data>
<data name="Error.Content.Save" xml:space="preserve">
<value>An Error Occurred Saving Content</value>
</data>
<data name="Error.Content.View" xml:space="preserve">
<value>Error Viewing Version</value>
</data>
<data name="Message.Content.Deleted" xml:space="preserve">
<value>Version Deleted</value>
</data>
<data name="Message.Content.Restored" xml:space="preserve">
<value>Version Restored</value>
</data>
<data name="Restore.Header" xml:space="preserve">
<value>Restore Version</value>
</data>
<data name="Restore.Text" xml:space="preserve">
<value>Restore</value>
</data>
<data name="View.Text" xml:space="preserve">
<value>View</value>
</data>
</root>

View File

@ -17,18 +17,17 @@ using Oqtane.Infrastructure;
using Oqtane.Modules;
using Oqtane.Repository;
using Oqtane.Security;
using Oqtane.Services;
using Oqtane.Shared;
namespace Microsoft.Extensions.DependencyInjection
{
public static class OqtaneServiceCollectionExtensions
{
public static IServiceCollection AddOqtane(this IServiceCollection services, Runtime runtime, string[] supportedCultures)
public static IServiceCollection AddOqtane(this IServiceCollection services, string[] supportedCultures)
{
LoadAssemblies();
LoadSatelliteAssemblies(supportedCultures);
services.AddOqtaneServices(runtime);
services.AddOqtaneServices();
return services;
}
@ -190,7 +189,7 @@ namespace Microsoft.Extensions.DependencyInjection
return services;
}
private static IServiceCollection AddOqtaneServices(this IServiceCollection services, Runtime runtime)
private static IServiceCollection AddOqtaneServices(this IServiceCollection services)
{
if (services is null)
{
@ -229,14 +228,6 @@ namespace Microsoft.Extensions.DependencyInjection
{
startup.ConfigureServices(services);
}
if (runtime == Runtime.Server)
{
// register client startup services if running on server
assembly.GetInstances<IClientStartup>()
.ToList()
.ForEach(x => x.ConfigureServices(services));
}
}
return services;
}

View File

@ -28,14 +28,14 @@ namespace Oqtane.Infrastructure
{
public class DatabaseManager : IDatabaseManager
{
private readonly IConfigurationRoot _config;
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(IConfigurationRoot config, IServiceScopeFactory serviceScopeFactory, IWebHostEnvironment environment, IMemoryCache cache, IConfigManager configManager, ILogger<DatabaseManager> filelogger)
public DatabaseManager(IConfigManager config, IServiceScopeFactory serviceScopeFactory, IWebHostEnvironment environment, IMemoryCache cache, IConfigManager configManager, ILogger<DatabaseManager> filelogger)
{
_config = config;
_serviceScopeFactory = serviceScopeFactory;

View File

@ -125,6 +125,9 @@ namespace Oqtane.Infrastructure
case "ref": // ref/net*/...
filename = ExtractFile(entry, Path.Combine(binPath, "ref"), 2);
break;
case "refs": // refs/net*/...
filename = ExtractFile(entry, Path.Combine(binPath, "refs"), 2);
break;
}
if (filename != "")

View File

@ -14,18 +14,18 @@ namespace Oqtane.Infrastructure
public class LogManager : ILogManager
{
private readonly ILogRepository _logs;
private readonly IConfigurationRoot _config;
private readonly ITenantManager _tenantManager;
private readonly IConfigManager _config;
private readonly IUserPermissions _userPermissions;
private readonly IHttpContextAccessor _accessor;
private readonly Alias _alias;
public LogManager(ILogRepository logs, ITenantManager tenantManager, IConfigurationRoot config, IUserPermissions userPermissions, IHttpContextAccessor accessor)
public LogManager(ILogRepository logs, ITenantManager tenantManager, IConfigManager config, IUserPermissions userPermissions, IHttpContextAccessor accessor)
{
_logs = logs;
_tenantManager = tenantManager;
_config = config;
_userPermissions = userPermissions;
_accessor = accessor;
_alias = tenantManager.GetAlias();
}
public void Log(LogLevel level, object @class, LogFunction function, string message, params object[] args)
@ -48,9 +48,13 @@ namespace Oqtane.Infrastructure
Log log = new Log();
log.SiteId = siteId;
if (log.SiteId == -1 && _alias != null)
if (log.SiteId == -1)
{
log.SiteId = _alias.SiteId;
var alias = _tenantManager.GetAlias();
if (alias != null)
{
log.SiteId = alias.SiteId;
}
}
if (log.SiteId == -1) return; // logs must be site specific

View File

@ -1,6 +1,5 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
namespace Oqtane.Infrastructure
{
@ -16,8 +15,8 @@ namespace Oqtane.Infrastructure
public async Task Invoke(HttpContext context)
{
// check if framework is installed
var config = context.RequestServices.GetService(typeof(IConfiguration)) as IConfiguration;
if (!string.IsNullOrEmpty(config.GetConnectionString("DefaultConnection")))
var config = context.RequestServices.GetService(typeof(IConfigManager)) as IConfigManager;
if (config.IsInstalled())
{
// get alias
var tenantManager = context.RequestServices.GetService(typeof(ITenantManager)) as ITenantManager;

View File

@ -0,0 +1,29 @@
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.03.00.03.01")]
public class AddPageMeta : MultiDatabaseMigration
{
public AddPageMeta(IDatabase database) : base(database)
{
}
protected override void Up(MigrationBuilder migrationBuilder)
{
var pageEntityBuilder = new PageEntityBuilder(migrationBuilder, ActiveDatabase);
pageEntityBuilder.AddStringColumn("Meta", 2000, true);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
var pageEntityBuilder = new PageEntityBuilder(migrationBuilder, ActiveDatabase);
pageEntityBuilder.DropColumn("Meta");
}
}
}

View File

@ -8,6 +8,8 @@ using Oqtane.Infrastructure;
using Oqtane.Controllers;
using System.Net;
using Oqtane.Documentation;
using System.Collections.Generic;
using System.Linq;
namespace Oqtane.Modules.HtmlText.Controllers
{
@ -22,18 +24,60 @@ namespace Oqtane.Modules.HtmlText.Controllers
_htmlText = htmlText;
}
// GET api/<controller>/5
[HttpGet("{id}")]
[Authorize(Policy = PolicyNames.ViewModule)]
public Models.HtmlText Get(int id)
// GET: api/<controller>?moduleid=x
[HttpGet]
[Authorize(Roles = RoleNames.Registered)]
public IEnumerable<Models.HtmlText> Get(string moduleId)
{
if (AuthEntityId(EntityNames.Module) == id)
if (int.TryParse(moduleId, out int ModuleId) && AuthEntityId(EntityNames.Module) == ModuleId)
{
return _htmlText.GetHtmlTexts(ModuleId);
}
else
{
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Html/Text Get Attempt {ModuleId}", moduleId);
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
return null;
}
}
// GET api/<controller>/5
[HttpGet("{moduleid}")]
[Authorize(Policy = PolicyNames.ViewModule)]
public Models.HtmlText Get(int moduleId)
{
if (AuthEntityId(EntityNames.Module) == moduleId)
{
var htmltexts = _htmlText.GetHtmlTexts(moduleId);
if (htmltexts != null && htmltexts.Any())
{
return htmltexts.OrderByDescending(item => item.CreatedOn).First();
}
else
{
return null;
}
}
else
{
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Html/Text Get Attempt {ModuleId}", moduleId);
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
return null;
}
}
// GET api/<controller>/5/6
[HttpGet("{id}/{moduleid}")]
[Authorize(Policy = PolicyNames.ViewModule)]
public Models.HtmlText Get(int id, int moduleId)
{
if (AuthEntityId(EntityNames.Module) == moduleId)
{
return _htmlText.GetHtmlText(id);
}
else
{
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized HtmlText Get Attempt {ModuleId}", id);
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Html/Text Get Attempt {HtmlTextId}", id);
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
return null;
}
@ -53,27 +97,7 @@ namespace Oqtane.Modules.HtmlText.Controllers
}
else
{
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized HtmlText Post Attempt {HtmlText}", htmlText);
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
return null;
}
}
// PUT api/<controller>/5
[ValidateAntiForgeryToken]
[HttpPut("{id}")]
[Authorize(Policy = PolicyNames.EditModule)]
public Models.HtmlText Put(int id, [FromBody] Models.HtmlText htmlText)
{
if (ModelState.IsValid && AuthEntityId(EntityNames.Module) == htmlText.ModuleId)
{
htmlText = _htmlText.UpdateHtmlText(htmlText);
_logger.Log(LogLevel.Information, this, LogFunction.Update, "Html/Text Updated {HtmlText}", htmlText);
return htmlText;
}
else
{
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized HtmlText Put Attempt {HtmlText}", htmlText);
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Html/Text Post Attempt {HtmlText}", htmlText);
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
return null;
}
@ -81,18 +105,18 @@ namespace Oqtane.Modules.HtmlText.Controllers
// DELETE api/<controller>/5
[ValidateAntiForgeryToken]
[HttpDelete("{id}")]
[HttpDelete("{id}/{moduleid}")]
[Authorize(Policy = PolicyNames.EditModule)]
public void Delete(int id)
public void Delete(int id, int moduleId)
{
if (AuthEntityId(EntityNames.Module) == id)
if (AuthEntityId(EntityNames.Module) == moduleId)
{
_htmlText.DeleteHtmlText(id);
_logger.Log(LogLevel.Information, this, LogFunction.Delete, "Html/Text Deleted {HtmlTextId}", id);
}
else
{
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized HtmlText Delete Attempt {ModuleId}", id);
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Html/Text Delete Attempt {HtmlTextId}", id);
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
}
}

View File

@ -43,19 +43,10 @@ namespace Oqtane.Modules.HtmlText.Manager
public void ImportModule(Module module, string content, string version)
{
content = WebUtility.HtmlDecode(content);
var htmlText = _htmlText.GetHtmlText(module.ModuleId);
if (htmlText != null)
{
htmlText.Content = content;
_htmlText.UpdateHtmlText(htmlText);
}
else
{
htmlText = new Models.HtmlText();
htmlText.ModuleId = module.ModuleId;
htmlText.Content = content;
_htmlText.AddHtmlText(htmlText);
}
var htmlText = new Models.HtmlText();
htmlText.ModuleId = module.ModuleId;
htmlText.Content = content;
_htmlText.AddHtmlText(htmlText);
}
public bool Install(Tenant tenant, string version)

View File

@ -2,6 +2,7 @@ using Microsoft.EntityFrameworkCore;
using System.Linq;
using Oqtane.Modules.HtmlText.Models;
using Oqtane.Documentation;
using System.Collections.Generic;
namespace Oqtane.Modules.HtmlText.Repository
{
@ -15,11 +16,15 @@ namespace Oqtane.Modules.HtmlText.Repository
_db = context;
}
public Models.HtmlText GetHtmlText(int moduleId)
public IEnumerable<Models.HtmlText> GetHtmlTexts(int moduleId)
{
return _db.HtmlText.FirstOrDefault(item => item.ModuleId == moduleId);
return _db.HtmlText.Where(item => item.ModuleId == moduleId);
}
public Models.HtmlText GetHtmlText(int htmlTextId)
{
return _db.HtmlText.Find(htmlTextId);
}
public Models.HtmlText AddHtmlText(Models.HtmlText htmlText)
{
@ -28,16 +33,9 @@ namespace Oqtane.Modules.HtmlText.Repository
return htmlText;
}
public Models.HtmlText UpdateHtmlText(Models.HtmlText htmlText)
public void DeleteHtmlText(int htmlTextId)
{
_db.Entry(htmlText).State = EntityState.Modified;
_db.SaveChanges();
return htmlText;
}
public void DeleteHtmlText(int moduleId)
{
Models.HtmlText htmlText = _db.HtmlText.FirstOrDefault(item => item.ModuleId == moduleId);
Models.HtmlText htmlText = _db.HtmlText.FirstOrDefault(item => item.HtmlTextId == htmlTextId);
if (htmlText != null) _db.HtmlText.Remove(htmlText);
_db.SaveChanges();
}

View File

@ -1,3 +1,4 @@
using System.Collections.Generic;
using Oqtane.Documentation;
using Oqtane.Modules.HtmlText.Models;
@ -6,9 +7,9 @@ namespace Oqtane.Modules.HtmlText.Repository
[PrivateApi("Mark HtmlText classes as private, since it's not very useful in the public docs")]
public interface IHtmlTextRepository
{
Models.HtmlText GetHtmlText(int moduleId);
IEnumerable<Models.HtmlText> GetHtmlTexts(int moduleId);
Models.HtmlText GetHtmlText(int htmlTextId);
Models.HtmlText AddHtmlText(Models.HtmlText htmlText);
Models.HtmlText UpdateHtmlText(Models.HtmlText htmlText);
void DeleteHtmlText(int moduleId);
void DeleteHtmlText(int htmlTextId);
}
}

View File

@ -8,6 +8,7 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@Model.Title</title>
@Html.Raw(@Model.Meta)
<base href="~/" />
<link id="app-favicon" rel="shortcut icon" type="image/x-icon" href="@Model.FavIcon" />
@if (!string.IsNullOrEmpty(Model.PWAScript))
@ -20,34 +21,42 @@
@Html.Raw(Model.HeadResources)
</head>
<body>
@(Html.AntiForgeryToken())
<component type="typeof(Oqtane.App)" render-mode="@Model.RenderMode" param-AntiForgeryToken="@Model.AntiForgeryToken" param-Runtime="@Model.Runtime" param-RenderMode="@Model.RenderMode.ToString()" param-VisitorId="@Model.VisitorId" param-RemoteIPAddress="@Model.RemoteIPAddress" />
<div id="blazor-error-ui">
<environment include="Staging,Production">
An error has occurred. This application may no longer respond until reloaded.
</environment>
<environment include="Development">
An unhandled exception has occurred. See browser dev tools for details.
</environment>
<a href="" class="reload">Reload</a>
<a class="dismiss">🗙</a>
</div>
<script src="js/interop.js"></script>
@if (Model.Runtime == "WebAssembly")
{
<script src="_framework/blazor.webassembly.js"></script>
}
else
{
<script src="_framework/blazor.server.js"></script>
}
@if (!string.IsNullOrEmpty(Model.PWAScript))
@if (string.IsNullOrEmpty(Model.Message))
{
@Html.Raw(Model.PWAScript)
@(Html.AntiForgeryToken())
<component type="typeof(Oqtane.App)" render-mode="@Model.RenderMode" param-AntiForgeryToken="@Model.AntiForgeryToken" param-Runtime="@Model.Runtime" param-RenderMode="@Model.RenderMode.ToString()" param-VisitorId="@Model.VisitorId" param-RemoteIPAddress="@Model.RemoteIPAddress" />
<div id="blazor-error-ui">
<environment include="Staging,Production">
An error has occurred. This application may no longer respond until reloaded.
</environment>
<environment include="Development">
An unhandled exception has occurred. See browser dev tools for details.
</environment>
<a href="" class="reload">Reload</a>
<a class="dismiss">🗙</a>
</div>
<script src="js/interop.js"></script>
@if (Model.Runtime == "WebAssembly")
{
<script src="_framework/blazor.webassembly.js"></script>
}
else
{
<script src="_framework/blazor.server.js"></script>
}
@if (!string.IsNullOrEmpty(Model.PWAScript))
{
@Html.Raw(Model.PWAScript)
}
@Html.Raw(Model.BodyResources)
}
else
{
<div class="app-alert">@Model.Message</div>
}
@Html.Raw(Model.BodyResources)
</body>
</html>

View File

@ -25,7 +25,7 @@ namespace Oqtane.Pages
{
public class HostModel : PageModel
{
private IConfiguration _configuration;
private IConfigManager _configuration;
private readonly ITenantManager _tenantManager;
private readonly ILocalizationManager _localizationManager;
private readonly ILanguageRepository _languages;
@ -38,7 +38,7 @@ namespace Oqtane.Pages
private readonly ISettingRepository _settings;
private readonly ILogManager _logger;
public HostModel(IConfiguration configuration, ITenantManager tenantManager, ILocalizationManager localizationManager, ILanguageRepository languages, IAntiforgery antiforgery, ISiteRepository sites, IPageRepository pages, IUrlMappingRepository urlMappings, IVisitorRepository visitors, IAliasRepository aliases, ISettingRepository settings, ILogManager logger)
public HostModel(IConfigManager configuration, ITenantManager tenantManager, ILocalizationManager localizationManager, ILanguageRepository languages, IAntiforgery antiforgery, ISiteRepository sites, IPageRepository pages, IUrlMappingRepository urlMappings, IVisitorRepository visitors, IAliasRepository aliases, ISettingRepository settings, ILogManager logger)
{
_configuration = configuration;
_tenantManager = tenantManager;
@ -63,9 +63,11 @@ namespace Oqtane.Pages
public string HeadResources = "";
public string BodyResources = "";
public string Title = "";
public string Meta = "";
public string FavIcon = "favicon.ico";
public string PWAScript = "";
public string ThemeType = "";
public string Message = "";
public IActionResult OnGet()
{
@ -83,7 +85,7 @@ namespace Oqtane.Pages
}
// if framework is installed
if (!string.IsNullOrEmpty(_configuration.GetConnectionString("DefaultConnection")))
if (_configuration.IsInstalled())
{
var alias = _tenantManager.GetAlias();
if (alias != null)
@ -108,7 +110,7 @@ namespace Oqtane.Pages
}
var site = _sites.GetSite(alias.SiteId);
if (site != null)
if (site != null && !site.IsDeleted)
{
Route route = new Route(url, alias.Path);
@ -148,6 +150,7 @@ namespace Oqtane.Pages
{
Title = Title + " - " + page.Name;
}
Meta = page.Meta;
// include theme resources
if (!string.IsNullOrEmpty(page.ThemeType))
@ -165,42 +168,50 @@ namespace Oqtane.Pages
return RedirectPermanent(url);
}
}
}
// include global resources
var assemblies = AppDomain.CurrentDomain.GetOqtaneAssemblies();
foreach (Assembly assembly in assemblies)
{
ProcessHostResources(assembly);
ProcessModuleControls(assembly);
ProcessThemeControls(assembly);
}
// set culture if not specified
string culture = HttpContext.Request.Cookies[CookieRequestCultureProvider.DefaultCookieName];
if (culture == null)
{
// get default language for site
var languages = _languages.GetLanguages(alias.SiteId);
if (languages.Any())
// include global resources
var assemblies = AppDomain.CurrentDomain.GetOqtaneAssemblies();
foreach (Assembly assembly in assemblies)
{
// use default language if specified otherwise use first language in collection
culture = (languages.Where(l => l.IsDefault).SingleOrDefault() ?? languages.First()).Code;
ProcessHostResources(assembly);
ProcessModuleControls(assembly);
ProcessThemeControls(assembly);
}
else
{
culture = _localizationManager.GetDefaultCulture();
}
SetLocalizationCookie(culture);
}
// set language for page
if (!string.IsNullOrEmpty(culture))
{
// localization cookie value in form of c=en|uic=en
Language = culture.Split('|')[0];
Language = Language.Replace("c=", "");
// set culture if not specified
string culture = HttpContext.Request.Cookies[CookieRequestCultureProvider.DefaultCookieName];
if (culture == null)
{
// get default language for site
var languages = _languages.GetLanguages(alias.SiteId);
if (languages.Any())
{
// use default language if specified otherwise use first language in collection
culture = (languages.Where(l => l.IsDefault).SingleOrDefault() ?? languages.First()).Code;
}
else
{
culture = _localizationManager.GetDefaultCulture();
}
SetLocalizationCookie(culture);
}
// set language for page
if (!string.IsNullOrEmpty(culture))
{
// localization cookie value in form of c=en|uic=en
Language = culture.Split('|')[0];
Language = Language.Replace("c=", "");
}
}
else
{
Message = "Site Is Either Disabled Or Not Configured Correctly";
}
}
else
{
Message = "Site Not Configured Correctly - No Matching Alias Exists For Host Name";
}
}
return Page();

View File

@ -1,19 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Migrations;
using Oqtane.Models;
using Microsoft.Extensions.Configuration;
using Oqtane.Databases.Interfaces;
using Oqtane.Extensions;
using Oqtane.Interfaces;
using Oqtane.Migrations.Framework;
using Oqtane.Repository.Databases.Interfaces;
using Oqtane.Shared;
using System.Threading.Tasks;
using System.Threading;
using Oqtane.Infrastructure;
// ReSharper disable BuiltInTypeReferenceStyleForMemberAccess
// ReSharper disable UnusedAutoPropertyAccessor.Global
@ -24,14 +21,14 @@ namespace Oqtane.Repository
public class MasterDBContext : DbContext, IMultiDatabase
{
private readonly IHttpContextAccessor _accessor;
private readonly IConfiguration _configuration;
private readonly IConfigManager _config;
private string _connectionString;
private string _databaseType;
public MasterDBContext(DbContextOptions<MasterDBContext> options, IHttpContextAccessor accessor, IConfiguration configuration) : base(options)
public MasterDBContext(DbContextOptions<MasterDBContext> options, IHttpContextAccessor accessor, IConfigManager config) : base(options)
{
_accessor = accessor;
_configuration = configuration;
_config = config;
}
public IDatabase ActiveDatabase { get; private set; }
@ -40,15 +37,15 @@ namespace Oqtane.Repository
{
optionsBuilder.ReplaceService<IMigrationsAssembly, MultiDatabaseMigrationsAssembly>();
if(_configuration != null)
if(_config != null)
{
if (!String.IsNullOrEmpty(_configuration.GetConnectionString("DefaultConnection")))
if (_config.IsInstalled())
{
_connectionString = _configuration.GetConnectionString("DefaultConnection")
_connectionString = _config.GetConnectionString("DefaultConnection")
.Replace("|DataDirectory|", AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString());
}
_databaseType = _configuration.GetSection(SettingKeys.DatabaseSection)[SettingKeys.DatabaseTypeKey];
_databaseType = _config.GetSection(SettingKeys.DatabaseSection)[SettingKeys.DatabaseTypeKey];
}
if (!String.IsNullOrEmpty(_databaseType))

View File

@ -6,7 +6,6 @@ using Oqtane.Infrastructure;
using Oqtane.Repository;
using Oqtane.Models;
using System.Collections.Generic;
using Microsoft.Extensions.Configuration;
namespace Oqtane.Security
{
@ -17,8 +16,8 @@ namespace Oqtane.Security
if (context != null && context.Principal.Identity.IsAuthenticated)
{
// check if framework is installed
var config = context.HttpContext.RequestServices.GetService(typeof(IConfiguration)) as IConfiguration;
if (!string.IsNullOrEmpty(config.GetConnectionString("DefaultConnection")))
var config = context.HttpContext.RequestServices.GetService(typeof(IConfigManager)) as IConfigManager;
if (config.IsInstalled())
{
var tenantManager = context.HttpContext.RequestServices.GetService(typeof(ITenantManager)) as ITenantManager;
var alias = tenantManager.GetAlias();

View File

@ -21,7 +21,6 @@ namespace Oqtane
{
public class Startup
{
private readonly Runtime _runtime;
private readonly bool _useSwagger;
private readonly IWebHostEnvironment _env;
private readonly string[] _supportedCultures;
@ -36,7 +35,6 @@ namespace Oqtane
Configuration = builder.Build();
_supportedCultures = localizationManager.GetSupportedCultures();
_runtime = (Configuration.GetSection("Runtime").Value == "WebAssembly") ? Runtime.WebAssembly : Runtime.Server;
//add possibility to switch off swagger on production.
_useSwagger = Configuration.GetSection("UseSwagger").Value != "false";
@ -115,7 +113,7 @@ namespace Oqtane
services.AddOqtaneTransientServices();
// load the external assemblies into the app domain, install services
services.AddOqtane(_runtime, _supportedCultures);
services.AddOqtane(_supportedCultures);
services.AddOqtaneDbContext();
services.AddMvc()

View File

@ -61,7 +61,12 @@ namespace Oqtane.Models
/// Reference to a Container which will be used for modules on this page.
/// </summary>
public string DefaultContainerType { get; set; }
/// <summary>
/// Meta tags to be included in the head of the page
/// </summary>
public string Meta { get; set; }
/// <summary>
/// Icon file for this page.
/// TODO: unclear what this is for, and what icon library is used. Probably FontAwesome?