Merge remote-tracking branch 'oqtane/dev' into dev
This commit is contained in:
commit
e54cfa629e
|
@ -6,102 +6,109 @@
|
||||||
@inject IStringLocalizer<Add> Localizer
|
@inject IStringLocalizer<Add> Localizer
|
||||||
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
||||||
|
|
||||||
|
@if (_initialized)
|
||||||
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
|
{
|
||||||
<TabStrip Refresh="@_refresh">
|
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
|
||||||
<TabPanel Name="Settings" ResourceKey="Settings">
|
<TabStrip Refresh="@_refresh">
|
||||||
@if (PageState.Site.Themes != null)
|
<TabPanel Name="Settings" ResourceKey="Settings">
|
||||||
{
|
@if (PageState.Site.Themes != null)
|
||||||
<div class="container">
|
{
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<Label Class="col-sm-3" For="name" HelpText="Enter the page name" ResourceKey="Name">Name: </Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<input id="name" class="form-control" @bind="@_name" required />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<Label Class="col-sm-3" For="parent" HelpText="Select the parent for the page in the site hierarchy" ResourceKey="Parent">Parent: </Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<select id="parent" class="form-select" @onchange="(e => ParentChanged(e))" required>
|
|
||||||
<option value="-1"><@Localizer["SiteRoot"]></option>
|
|
||||||
@foreach (Page page in PageState.Pages)
|
|
||||||
{
|
|
||||||
<option value="@(page.PageId)">@(new string('-', page.Level * 2))@(page.Name)</option>
|
|
||||||
}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<Label Class="col-sm-3" For="insert" HelpText="Select the location where you would like the page to be inserted in relation to other pages" ResourceKey="Insert">Insert: </Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<select id="insert" class="form-select" @bind="@_insert" required>
|
|
||||||
<option value="<<">@Localizer["AtBeginning"]</option>
|
|
||||||
@if (_children != null && _children.Count > 0)
|
|
||||||
{
|
|
||||||
<option value="<">@Localizer["Before"]</option>
|
|
||||||
<option value=">">@Localizer["After"]</option>
|
|
||||||
}
|
|
||||||
<option value=">>">@Localizer["AtEnd"]</option>
|
|
||||||
</select>
|
|
||||||
@if (_children != null && _children.Count > 0 && (_insert == "<" || _insert == ">"))
|
|
||||||
{
|
|
||||||
<select class="form-select" @bind="@_childid">
|
|
||||||
<option value="-1"><@Localizer["Page.Select"]></option>
|
|
||||||
@foreach (Page page in _children)
|
|
||||||
{
|
|
||||||
<option value="@(page.PageId)">@(page.Name)</option>
|
|
||||||
}
|
|
||||||
</select>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<Label Class="col-sm-3" For="navigation" HelpText="Select whether the page is part of the site navigation or hidden" ResourceKey="Navigation">Navigation? </Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<select id="navigation" class="form-select" @bind="@_isnavigation" required>
|
|
||||||
<option value="True">@SharedLocalizer["Yes"]</option>
|
|
||||||
<option value="False">@SharedLocalizer["No"]</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<Label Class="col-sm-3" For="clickable" HelpText="Select whether the link in the site navigation is enabled or disabled" ResourceKey="Clickable">Clickable? </Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<select id="clickable" class="form-select" @bind="@_isclickable" required>
|
|
||||||
<option value="True">@SharedLocalizer["Yes"]</option>
|
|
||||||
<option value="False">@SharedLocalizer["No"]</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<Label Class="col-sm-3" For="path" HelpText="Optionally enter a url path for this page (ie. home ). If you do not provide a url path, the page name will be used. If the page is intended to be the root path specify '/'." ResourceKey="UrlPath">Url Path: </Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<input id="path" class="form-control" @bind="@_path" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<Label Class="col-sm-3" For="url" HelpText="Optionally enter a url which this page should redirect to when a user navigates to it" ResourceKey="Redirect">Redirect: </Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<input id="url" class="form-control" @bind="@_url" />
|
|
||||||
</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">
|
|
||||||
<select id="personalizable" class="form-select" @bind="@_ispersonalizable" required>
|
|
||||||
<option value="True">@SharedLocalizer["Yes"]</option>
|
|
||||||
<option value="False">@SharedLocalizer["No"]</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Section Name="Appearance" Heading="Appearance" ResourceKey="Appearance">
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="title" HelpText="Optionally enter the page title. If you do not provide a page title, the page name will be used." ResourceKey="Title">Title: </Label>
|
<Label Class="col-sm-3" For="name" HelpText="Enter the page name" ResourceKey="Name">Name: </Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<input id="title" class="form-control" @bind="@_title" />
|
<input id="name" class="form-control" @bind="@_name" required />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin))
|
||||||
|
{
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="parent" HelpText="Select the parent for the page in the site hierarchy" ResourceKey="Parent">Parent: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<select id="parent" class="form-select" @onchange="(e => ParentChanged(e))" required>
|
||||||
|
<option value="-1"><@Localizer["SiteRoot"]></option>
|
||||||
|
@foreach (Page page in PageState.Pages)
|
||||||
|
{
|
||||||
|
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, page.PermissionList))
|
||||||
|
{
|
||||||
|
<option value="@(page.PageId)">@(new string('-', page.Level * 2))@(page.Name)</option>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="insert" HelpText="Select the location where you would like the page to be inserted in relation to other pages" ResourceKey="Insert">Insert: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<select id="insert" class="form-select" @bind="@_insert" required>
|
||||||
|
<option value="<<">@Localizer["AtBeginning"]</option>
|
||||||
|
@if (_children != null && _children.Count > 0)
|
||||||
|
{
|
||||||
|
<option value="<">@Localizer["Before"]</option>
|
||||||
|
<option value=">">@Localizer["After"]</option>
|
||||||
|
}
|
||||||
|
<option value=">>">@Localizer["AtEnd"]</option>
|
||||||
|
</select>
|
||||||
|
@if (_children != null && _children.Count > 0 && (_insert == "<" || _insert == ">"))
|
||||||
|
{
|
||||||
|
<select class="form-select" @bind="@_childid">
|
||||||
|
<option value="-1"><@Localizer["Page.Select"]></option>
|
||||||
|
@foreach (Page page in _children)
|
||||||
|
{
|
||||||
|
<option value="@(page.PageId)">@(page.Name)</option>
|
||||||
|
}
|
||||||
|
</select>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="parent" HelpText="Select the parent for the page in the site hierarchy" ResourceKey="Parent">Parent: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<select id="parent" class="form-select" @onchange="(e => ParentChanged(e))" required>
|
||||||
|
<option value="@(_parent.PageId)">@(new string('-', _parent.Level * 2))@(_parent.Name)</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="insert" HelpText="Select the location where you would like the page to be inserted in relation to other pages" ResourceKey="Insert">Insert: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<select id="insert" class="form-select" @bind="@_insert" required>
|
||||||
|
<option value=">>">@Localizer["AtEnd"]</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="navigation" HelpText="Select whether the page is part of the site navigation or hidden" ResourceKey="Navigation">Navigation? </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<select id="navigation" class="form-select" @bind="@_isnavigation" required>
|
||||||
|
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||||
|
<option value="False">@SharedLocalizer["No"]</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="clickable" HelpText="Select whether the link in the site navigation is enabled or disabled" ResourceKey="Clickable">Clickable? </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<select id="clickable" class="form-select" @bind="@_isclickable" required>
|
||||||
|
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||||
|
<option value="False">@SharedLocalizer["No"]</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="path" HelpText="Optionally enter a url path for this page (ie. home ). If you do not provide a url path, the page name will be used. If the page is intended to be the root path specify '/'." ResourceKey="UrlPath">Url Path: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="path" class="form-control" @bind="@_path" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="url" HelpText="Optionally enter a url which this page should redirect to when a user navigates to it" ResourceKey="Redirect">Redirect: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="url" class="form-control" @bind="@_url" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
|
@ -111,112 +118,155 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="theme" HelpText="Select the theme for this page" ResourceKey="Theme">Theme: </Label>
|
<Label Class="col-sm-3" For="personalizable" HelpText="Select whether you would like users to be able to personalize this page with their own content" ResourceKey="Personalizable">Personalizable? </Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<select id="theme" class="form-select" value="@_themetype" @onchange="(e => ThemeChanged(e))" required>
|
<select id="personalizable" class="form-select" @bind="@_ispersonalizable" required>
|
||||||
@foreach (var theme in _themes)
|
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||||
{
|
<option value="False">@SharedLocalizer["No"]</option>
|
||||||
<option value="@theme.TypeName">@theme.Name</option>
|
|
||||||
}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<Label Class="col-sm-3" For="container" HelpText="Select the default container for the page" ResourceKey="DefaultContainer">Default Container: </Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<select id="container" class="form-select" @bind="@_containertype" required>
|
|
||||||
<option value="-"><@Localizer["Container.Select"]></option>
|
|
||||||
@foreach (var container in _containers)
|
|
||||||
{
|
|
||||||
<option value="@container.TypeName">@container.Name</option>
|
|
||||||
}
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Section>
|
|
||||||
<Section Name="PageContent" Heading="Page Content" ResourceKey="PageContent">
|
<Section Name="Appearance" Heading="Appearance" ResourceKey="Appearance">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="headcontent" HelpText="Optionally enter content to be included in the page head (ie. meta, link, or script tags)" ResourceKey="HeadContent">Head Content: </Label>
|
<Label Class="col-sm-3" For="title" HelpText="Optionally enter the page title. If you do not provide a page title, the page name will be used." ResourceKey="Title">Title: </Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<textarea id="headcontent" class="form-control" @bind="@_headcontent" rows="3"></textarea>
|
<input id="title" class="form-control" @bind="@_title" />
|
||||||
|
</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">
|
||||||
|
<select id="theme" class="form-select" value="@_themetype" @onchange="(e => ThemeChanged(e))" required>
|
||||||
|
@foreach (var theme in _themes)
|
||||||
|
{
|
||||||
|
<option value="@theme.TypeName">@theme.Name</option>
|
||||||
|
}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="container" HelpText="Select the default container for the page" ResourceKey="DefaultContainer">Default Container: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<select id="container" class="form-select" @bind="@_containertype" required>
|
||||||
|
<option value="-"><@Localizer["Container.Select"]></option>
|
||||||
|
@foreach (var container in _containers)
|
||||||
|
{
|
||||||
|
<option value="@container.TypeName">@container.Name</option>
|
||||||
|
}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-1 align-items-center">
|
</Section>
|
||||||
<Label Class="col-sm-3" For="bodycontent" HelpText="Optionally enter content to be included in the page body (ie. script tags)" ResourceKey="BodyContent">Body Content: </Label>
|
<Section Name="PageContent" Heading="Page Content" ResourceKey="PageContent">
|
||||||
<div class="col-sm-9">
|
<div class="container">
|
||||||
<textarea id="bodycontent" class="form-control" @bind="@_bodycontent" rows="3"></textarea>
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="headcontent" HelpText="Optionally enter content to be included in the page head (ie. meta, link, or script tags)" ResourceKey="HeadContent">Head Content: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<textarea id="headcontent" class="form-control" @bind="@_headcontent" rows="3"></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="bodycontent" HelpText="Optionally enter content to be included in the page body (ie. script tags)" ResourceKey="BodyContent">Body Content: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<textarea id="bodycontent" class="form-control" @bind="@_bodycontent" rows="3"></textarea>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Section>
|
||||||
</Section>
|
}
|
||||||
}
|
|
||||||
</TabPanel>
|
|
||||||
<TabPanel Name="Permissions" ResourceKey="Permissions">
|
|
||||||
<div class="container">
|
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<PermissionGrid EntityName="@EntityNames.Page" Permissions="@_permissions" @ref="_permissionGrid" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</TabPanel>
|
|
||||||
@if (_themeSettingsType != null)
|
|
||||||
{
|
|
||||||
<TabPanel Name="ThemeSettings" Heading="Theme Settings" ResourceKey="ThemeSettings">
|
|
||||||
@ThemeSettingsComponent
|
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
}
|
<TabPanel Name="Permissions" ResourceKey="Permissions">
|
||||||
</TabStrip>
|
<div class="container">
|
||||||
<br />
|
<div class="row mb-1 align-items-center">
|
||||||
<button type="button" class="btn btn-success" @onclick="SavePage">@SharedLocalizer["Save"]</button>
|
<PermissionGrid EntityName="@EntityNames.Page" Permissions="@_permissions" @ref="_permissionGrid" />
|
||||||
<button type="button" class="btn btn-secondary" @onclick="Cancel">@SharedLocalizer["Cancel"]</button>
|
</div>
|
||||||
</form>
|
</div>
|
||||||
|
</TabPanel>
|
||||||
|
@if (_themeSettingsType != null)
|
||||||
|
{
|
||||||
|
<TabPanel Name="ThemeSettings" Heading="Theme Settings" ResourceKey="ThemeSettings">
|
||||||
|
@ThemeSettingsComponent
|
||||||
|
</TabPanel>
|
||||||
|
}
|
||||||
|
</TabStrip>
|
||||||
|
<br />
|
||||||
|
<button type="button" class="btn btn-success" @onclick="SavePage">@SharedLocalizer["Save"]</button>
|
||||||
|
<button type="button" class="btn btn-secondary" @onclick="Cancel">@SharedLocalizer["Cancel"]</button>
|
||||||
|
</form>
|
||||||
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.View;
|
||||||
|
|
||||||
private List<ThemeControl> _themes = new List<ThemeControl>();
|
private bool _initialized = false;
|
||||||
private List<ThemeControl> _containers = new List<ThemeControl>();
|
private ElementReference form;
|
||||||
private string _name;
|
private bool validated = false;
|
||||||
private string _parentid = "-1";
|
private List<ThemeControl> _themes = new List<ThemeControl>();
|
||||||
private string _insert = ">>";
|
private List<ThemeControl> _containers = new List<ThemeControl>();
|
||||||
private List<Page> _children;
|
private int _pageId;
|
||||||
private int _childid = -1;
|
private string _name;
|
||||||
private string _isnavigation = "True";
|
private string _parentid = "-1";
|
||||||
private string _isclickable = "True";
|
private string _insert = ">>";
|
||||||
|
private List<Page> _children;
|
||||||
|
private int _childid = -1;
|
||||||
|
private string _isnavigation = "True";
|
||||||
|
private string _isclickable = "True";
|
||||||
private string _path = string.Empty;
|
private string _path = string.Empty;
|
||||||
private string _url;
|
private string _url;
|
||||||
private string _ispersonalizable = "False";
|
private string _ispersonalizable = "False";
|
||||||
private string _title;
|
private string _title;
|
||||||
private string _icon = string.Empty;
|
private string _icon = string.Empty;
|
||||||
private string _themetype = string.Empty;
|
private string _themetype = string.Empty;
|
||||||
private string _containertype = string.Empty;
|
private string _containertype = string.Empty;
|
||||||
private string _headcontent;
|
private string _headcontent;
|
||||||
private string _bodycontent;
|
private string _bodycontent;
|
||||||
private string _permissions = null;
|
private string _permissions = null;
|
||||||
private PermissionGrid _permissionGrid;
|
private PermissionGrid _permissionGrid;
|
||||||
private Type _themeSettingsType;
|
private Type _themeSettingsType;
|
||||||
private object _themeSettings;
|
private object _themeSettings;
|
||||||
private RenderFragment ThemeSettingsComponent { get; set; }
|
private RenderFragment ThemeSettingsComponent { get; set; }
|
||||||
private bool _refresh = false;
|
private bool _refresh = false;
|
||||||
private ElementReference form;
|
protected Page _parent = null;
|
||||||
private bool validated = false;
|
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_themes = ThemeService.GetThemeControls(PageState.Site.Themes);
|
if (PageState.QueryString.ContainsKey("id"))
|
||||||
_themetype = PageState.Site.DefaultThemeType;
|
{
|
||||||
_containers = ThemeService.GetContainerControls(PageState.Site.Themes, _themetype);
|
_pageId = Int32.Parse(PageState.QueryString["id"]);
|
||||||
_containertype = PageState.Site.DefaultContainerType;
|
_parent = await PageService.GetPageAsync(_pageId);
|
||||||
_children = PageState.Pages.Where(item => item.ParentId == null).ToList();
|
if (_parent != null)
|
||||||
ThemeSettings();
|
{
|
||||||
}
|
_parentid = _parent.PageId.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if admin or user has edit access to parent page
|
||||||
|
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin) || (_parent != null && UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, _parent.PermissionList)))
|
||||||
|
{
|
||||||
|
_themes = ThemeService.GetThemeControls(PageState.Site.Themes);
|
||||||
|
_themetype = PageState.Site.DefaultThemeType;
|
||||||
|
_containers = ThemeService.GetContainerControls(PageState.Site.Themes, _themetype);
|
||||||
|
_containertype = PageState.Site.DefaultContainerType;
|
||||||
|
_children = PageState.Pages.Where(item => item.ParentId == null).ToList();
|
||||||
|
ThemeSettings();
|
||||||
|
_initialized = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await logger.LogWarning("Error Loading Page {ParentId}", _parentid);
|
||||||
|
AddModuleMessage(Localizer["Error.Page.Load"], MessageType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await logger.LogError(ex, "Error Initializing Page {Error}", ex.Message);
|
await logger.LogError(ex, "Error Loading Page {Error}", ex.Message);
|
||||||
AddModuleMessage(Localizer["Error.Page.Initialize"], MessageType.Error);
|
AddModuleMessage(Localizer["Error.Page.Load"], MessageType.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -402,9 +452,9 @@
|
||||||
await PageService.UpdatePageOrderAsync(page.SiteId, page.PageId, page.ParentId);
|
await PageService.UpdatePageOrderAsync(page.SiteId, page.PageId, page.ParentId);
|
||||||
|
|
||||||
await logger.LogInformation("Page Added {Page}", page);
|
await logger.LogInformation("Page Added {Page}", page);
|
||||||
if (PageState.QueryString.ContainsKey("cp"))
|
if (!string.IsNullOrEmpty(PageState.ReturnUrl))
|
||||||
{
|
{
|
||||||
NavigationManager.NavigateTo(NavigateUrl(PageState.Pages.First(item => item.PageId == int.Parse(PageState.QueryString["cp"])).Path));
|
NavigationManager.NavigateTo(PageState.ReturnUrl);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -431,9 +481,9 @@
|
||||||
|
|
||||||
private void Cancel()
|
private void Cancel()
|
||||||
{
|
{
|
||||||
if (PageState.QueryString.ContainsKey("cp"))
|
if (!string.IsNullOrEmpty(PageState.ReturnUrl))
|
||||||
{
|
{
|
||||||
NavigationManager.NavigateTo(NavigateUrl(PageState.Pages.First(item => item.PageId == int.Parse(PageState.QueryString["cp"])).Path));
|
NavigationManager.NavigateTo(PageState.ReturnUrl);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -8,113 +8,238 @@
|
||||||
@inject IStringLocalizer<Edit> Localizer
|
@inject IStringLocalizer<Edit> Localizer
|
||||||
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
||||||
|
|
||||||
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
|
@if (_initialized)
|
||||||
<TabStrip Refresh="@_refresh">
|
{
|
||||||
<TabPanel Name="Settings" ResourceKey="Settings" Heading=@Localizer["Settings.Heading"]>
|
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
|
||||||
@if (PageState.Site.Themes != null)
|
@if (_page.UserId == null)
|
||||||
{
|
{
|
||||||
<div class="container">
|
<TabStrip Refresh="@_refresh">
|
||||||
<div class="row mb-1 align-items-center">
|
<TabPanel Name="Settings" ResourceKey="Settings" Heading=@Localizer["Settings.Heading"]>
|
||||||
<Label Class="col-sm-3" For="name" HelpText="Enter the page name" ResourceKey="Name">Name: </Label>
|
@if (PageState.Site.Themes != null)
|
||||||
<div class="col-sm-9">
|
{
|
||||||
<input id="name" class="form-control" @bind="@_name" maxlength="50" required />
|
<div class="container">
|
||||||
</div>
|
<div class="row mb-1 align-items-center">
|
||||||
</div>
|
<Label Class="col-sm-3" For="name" HelpText="Enter the page name" ResourceKey="Name">Name: </Label>
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="col-sm-9">
|
||||||
<Label Class="col-sm-3" For="parent" HelpText="Select the parent for the page in the site hierarchy" ResourceKey="Parent">Parent: </Label>
|
<input id="name" class="form-control" @bind="@_name" maxlength="50" required />
|
||||||
<div class="col-sm-9">
|
</div>
|
||||||
<select id="parent" class="form-select" value="@_parentid" @onchange="(e => ParentChanged(e))" required>
|
</div>
|
||||||
<option value="-1"><@Localizer["SiteRoot"]></option>
|
@if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin))
|
||||||
@foreach (Page page in PageState.Pages)
|
|
||||||
{
|
|
||||||
if (page.PageId != _pageId)
|
|
||||||
{
|
|
||||||
<option value="@(page.PageId)">@(new string('-', page.Level * 2))@(page.Name)</option>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<Label Class="col-sm-3" For="move" HelpText="Select the location where you would like the page to be moved in relation to other pages" ResourceKey="Move">Move: </Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<select id="move" class="form-select" @bind="@_insert" required>
|
|
||||||
@if (_parentid == _currentparentid)
|
|
||||||
{
|
|
||||||
<option value="="><@Localizer["ThisLocation.Keep"]></option>
|
|
||||||
}
|
|
||||||
<option value="<<">@Localizer["ToBeginning"]</option>
|
|
||||||
@if (_children != null && _children.Count > 0)
|
|
||||||
{
|
|
||||||
<option value="<">@Localizer["Before"]</option>
|
|
||||||
<option value=">">@Localizer["After"]</option>
|
|
||||||
}
|
|
||||||
<option value=">>">@Localizer["ToEnd"]</option>
|
|
||||||
</select>
|
|
||||||
@if (_children != null && _children.Count > 0 && (_insert == "<" || _insert == ">"))
|
|
||||||
{
|
{
|
||||||
<select class="form-select" @bind="@_childid">
|
<div class="row mb-1 align-items-center">
|
||||||
<option value="-1"><@Localizer["Page.Select"]></option>
|
<Label Class="col-sm-3" For="parent" HelpText="Select the parent for the page in the site hierarchy" ResourceKey="Parent">Parent: </Label>
|
||||||
@foreach (Page page in _children)
|
<div class="col-sm-9">
|
||||||
{
|
<select id="parent" class="form-select" value="@_parentid" @onchange="(e => ParentChanged(e))" required>
|
||||||
<option value="@(page.PageId)">@(page.Name)</option>
|
<option value="-1"><@Localizer["SiteRoot"]></option>
|
||||||
}
|
@foreach (Page page in PageState.Pages)
|
||||||
</select>
|
{
|
||||||
|
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, page.PermissionList) && page.PageId != _pageId)
|
||||||
|
{
|
||||||
|
<option value="@(page.PageId)">@(new string('-', page.Level * 2))@(page.Name)</option>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="move" HelpText="Select the location where you would like the page to be moved in relation to other pages" ResourceKey="Move">Move: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<select id="move" class="form-select" @bind="@_insert" required>
|
||||||
|
@if (_parentid == _currentparentid)
|
||||||
|
{
|
||||||
|
<option value="="><@Localizer["ThisLocation.Keep"]></option>
|
||||||
|
}
|
||||||
|
<option value="<<">@Localizer["ToBeginning"]</option>
|
||||||
|
@if (_children != null && _children.Count > 0)
|
||||||
|
{
|
||||||
|
<option value="<">@Localizer["Before"]</option>
|
||||||
|
<option value=">">@Localizer["After"]</option>
|
||||||
|
}
|
||||||
|
<option value=">>">@Localizer["ToEnd"]</option>
|
||||||
|
</select>
|
||||||
|
@if (_children != null && _children.Count > 0 && (_insert == "<" || _insert == ">"))
|
||||||
|
{
|
||||||
|
<select class="form-select" @bind="@_childid">
|
||||||
|
<option value="-1"><@Localizer["Page.Select"]></option>
|
||||||
|
@foreach (Page page in _children)
|
||||||
|
{
|
||||||
|
<option value="@(page.PageId)">@(page.Name)</option>
|
||||||
|
}
|
||||||
|
</select>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="parent" HelpText="Select the parent for the page in the site hierarchy" ResourceKey="Parent">Parent: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<select id="parent" class="form-select" value="@_parentid" @onchange="(e => ParentChanged(e))" disabled>
|
||||||
|
<option value="-1"><@Localizer["SiteRoot"]></option>
|
||||||
|
@if (_parent != null)
|
||||||
|
{
|
||||||
|
<option value="@(_parent.PageId)">@(new string('-', _parent.Level * 2))@(_parent.Name)</option>
|
||||||
|
}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="move" HelpText="Select the location where you would like the page to be moved in relation to other pages" ResourceKey="Move">Move: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<select id="move" class="form-select" @bind="@_insert" disabled>
|
||||||
|
<option value="="><@Localizer["ThisLocation.Keep"]></option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="navigation" HelpText="Select whether the page is part of the site navigation or hidden" ResourceKey="Navigation">Navigation? </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<select id="navigation" class="form-select" @bind="@_isnavigation" required>
|
||||||
|
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||||
|
<option value="False">@SharedLocalizer["No"]</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="clickable" HelpText="Select whether the link in the site navigation is enabled or disabled" ResourceKey="Clickable">Clickable? </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<select id="clickable" class="form-select" @bind="@_isclickable" required>
|
||||||
|
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||||
|
<option value="False">@SharedLocalizer["No"]</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="path" HelpText="Optionally enter a url path for this page (ie. home ). If you do not provide a url path, the page name will be used. If the page is intended to be the root path specify '/'." ResourceKey="UrlPath">Url Path: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="path" class="form-control" @bind="@_path" maxlength="256" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="url" HelpText="Optionally enter a url which this page should redirect to when a user navigates to it" ResourceKey="Redirect">Redirect: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="url" class="form-control" @bind="@_url" maxlength="500" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="icon" HelpText="Optionally provide an icon class name for this page which will be displayed in the site navigation" ResourceKey="Icon">Icon: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="icon" class="form-control" @bind="@_icon" maxlength="50" />
|
||||||
|
</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">
|
||||||
|
<select id="personalizable" class="form-select" @bind="@_ispersonalizable" required>
|
||||||
|
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||||
|
<option value="False">@SharedLocalizer["No"]</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<Section Name="Appearance" ResourceKey="Appearance">
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="container">
|
||||||
<Label Class="col-sm-3" For="navigation" HelpText="Select whether the page is part of the site navigation or hidden" ResourceKey="Navigation">Navigation? </Label>
|
<div class="row mb-1 align-items-center">
|
||||||
<div class="col-sm-9">
|
<Label Class="col-sm-3" For="title" HelpText="Optionally enter the page title. If you do not provide a page title, the page name will be used." ResourceKey="Title">Title: </Label>
|
||||||
<select id="navigation" class="form-select" @bind="@_isnavigation" required>
|
<div class="col-sm-9">
|
||||||
<option value="True">@SharedLocalizer["Yes"]</option>
|
<input id="title" class="form-control" @bind="@_title" maxlength="200" />
|
||||||
<option value="False">@SharedLocalizer["No"]</option>
|
</div>
|
||||||
</select>
|
</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">
|
||||||
|
<select id="theme" class="form-select" value="@_themetype" @onchange="(e => ThemeChanged(e))" required>
|
||||||
|
@foreach (var theme in _themes)
|
||||||
|
{
|
||||||
|
<option value="@theme.TypeName">@theme.Name</option>
|
||||||
|
}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="container" HelpText="Select the default container for the page" ResourceKey="DefaultContainer">Default Container: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<select id="container" class="form-select" @bind="@_containertype" required>
|
||||||
|
<option value="-"><@Localizer["Container.Select"]></option>
|
||||||
|
@foreach (var container in _containers)
|
||||||
|
{
|
||||||
|
<option value="@container.TypeName">@container.Name</option>
|
||||||
|
}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Section>
|
||||||
|
<Section Name="PageContent" Heading="Page Content" ResourceKey="PageContent">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="headcontent" HelpText="Optionally enter content to be included in the page head (ie. meta, link, or script tags)" ResourceKey="HeadContent">Head Content: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<textarea id="headcontent" class="form-control" @bind="@_headcontent" rows="3"></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="bodycontent" HelpText="Optionally enter content to be included in the page body (ie. script tags)" ResourceKey="BodyContent">Body Content: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<textarea id="bodycontent" class="form-control" @bind="@_bodycontent" rows="3"></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Section>
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<AuditInfo CreatedBy="@_createdby" CreatedOn="@_createdon" ModifiedBy="@_modifiedby" ModifiedOn="@_modifiedon" DeletedBy="@_deletedby" DeletedOn="@_deletedon"></AuditInfo>
|
||||||
|
}
|
||||||
|
</TabPanel>
|
||||||
|
<TabPanel Name="Permissions" ResourceKey="Permissions">
|
||||||
|
@if (_permissions != null)
|
||||||
|
{
|
||||||
|
<div class="container">
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<PermissionGrid EntityName="@EntityNames.Page" PermissionList="@_permissions" @ref="_permissionGrid" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
}
|
||||||
<div class="row mb-1 align-items-center">
|
</TabPanel>
|
||||||
<Label Class="col-sm-3" For="clickable" HelpText="Select whether the link in the site navigation is enabled or disabled" ResourceKey="Clickable">Clickable? </Label>
|
<TabPanel Name="PageModules" Heading="Modules" ResourceKey="PageModules">
|
||||||
<div class="col-sm-9">
|
@if (_pageModules != null)
|
||||||
<select id="clickable" class="form-select" @bind="@_isclickable" required>
|
{
|
||||||
<option value="True">@SharedLocalizer["Yes"]</option>
|
<Pager Items="_pageModules">
|
||||||
<option value="False">@SharedLocalizer["No"]</option>
|
<Header>
|
||||||
</select>
|
<th style="width: 1px;"> </th>
|
||||||
</div>
|
<th style="width: 1px;"> </th>
|
||||||
</div>
|
<th>@Localizer["ModuleTitle"]</th>
|
||||||
<div class="row mb-1 align-items-center">
|
<th>@Localizer["ModuleDefinition"]</th>
|
||||||
<Label Class="col-sm-3" For="path" HelpText="Optionally enter a url path for this page (ie. home ). If you do not provide a url path, the page name will be used. If the page is intended to be the root path specify '/'." ResourceKey="UrlPath">Url Path: </Label>
|
</Header>
|
||||||
<div class="col-sm-9">
|
<Row>
|
||||||
<input id="path" class="form-control" @bind="@_path" maxlength="256"/>
|
<td><ActionLink Action="Settings" Text="Edit" ModuleId="@context.ModuleId" Security="SecurityAccessLevel.Edit" PermissionList="@context.PermissionList" ResourceKey="ModuleSettings" /></td>
|
||||||
</div>
|
<td><ActionDialog Header="Delete Module" Message="Are You Sure You Wish To Delete This Module?" Action="Delete" Security="SecurityAccessLevel.Edit" PermissionList="@context.PermissionList" Class="btn btn-danger" OnClick="@(async () => await DeleteModule(context))" ResourceKey="DeleteModule" /></td>
|
||||||
</div>
|
<td>@context.Title</td>
|
||||||
<div class="row mb-1 align-items-center">
|
<td>@context.ModuleDefinition?.Name</td>
|
||||||
<Label Class="col-sm-3" For="url" HelpText="Optionally enter a url which this page should redirect to when a user navigates to it" ResourceKey="Redirect">Redirect: </Label>
|
</Row>
|
||||||
<div class="col-sm-9">
|
</Pager>
|
||||||
<input id="url" class="form-control" @bind="@_url" maxlength="500"/>
|
}
|
||||||
</div>
|
</TabPanel>
|
||||||
</div>
|
@if (_themeSettingsType != null)
|
||||||
<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>
|
<TabPanel Name="ThemeSettings" Heading="Theme Settings" ResourceKey="ThemeSettings">
|
||||||
<div class="col-sm-9">
|
@ThemeSettingsComponent
|
||||||
<select id="personalizable" class="form-select" @bind="@_ispersonalizable" required>
|
</TabPanel>
|
||||||
<option value="True">@SharedLocalizer["Yes"]</option>
|
<br />
|
||||||
<option value="False">@SharedLocalizer["No"]</option>
|
}
|
||||||
</select>
|
</TabStrip>
|
||||||
</div>
|
}
|
||||||
</div>
|
else
|
||||||
</div>
|
{
|
||||||
<Section Name="Appearance" ResourceKey="Appearance">
|
<TabStrip Refresh="@_refresh">
|
||||||
|
<TabPanel Name="Settings" ResourceKey="Settings" Heading=@Localizer["Settings.Heading"]>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="title" HelpText="Optionally enter the page title. If you do not provide a page title, the page name will be used." ResourceKey="Title">Title: </Label>
|
<Label Class="col-sm-3" For="title" HelpText="Optionally enter the page title. If you do not provide a page title, the page name will be used." ResourceKey="Title">Title: </Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<input id="title" class="form-control" @bind="@_title" maxlength="200"/>
|
<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="icon" HelpText="Optionally provide an icon class name for this page which will be displayed in the site navigation" ResourceKey="Icon">Icon: </Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<input id="icon" class="form-control" @bind="@_icon" maxlength="50" />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
|
@ -141,73 +266,26 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Section>
|
</TabPanel>
|
||||||
<Section Name="PageContent" Heading="Page Content" ResourceKey="PageContent">
|
@if (_themeSettingsType != null)
|
||||||
<div class="container">
|
{
|
||||||
<div class="row mb-1 align-items-center">
|
<TabPanel Name="ThemeSettings" Heading="Theme Settings" ResourceKey="ThemeSettings">
|
||||||
<Label Class="col-sm-3" For="headcontent" HelpText="Optionally enter content to be included in the page head (ie. meta, link, or script tags)" ResourceKey="HeadContent">Head Content: </Label>
|
@ThemeSettingsComponent
|
||||||
<div class="col-sm-9">
|
</TabPanel>
|
||||||
<textarea id="headcontent" class="form-control" @bind="@_headcontent" rows="3"></textarea>
|
<br />
|
||||||
</div>
|
}
|
||||||
</div>
|
</TabStrip>
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<Label Class="col-sm-3" For="bodycontent" HelpText="Optionally enter content to be included in the page body (ie. script tags)" ResourceKey="BodyContent">Body Content: </Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<textarea id="bodycontent" class="form-control" @bind="@_bodycontent" rows="3"></textarea>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Section>
|
|
||||||
<br />
|
|
||||||
<br />
|
|
||||||
<AuditInfo CreatedBy="@_createdby" CreatedOn="@_createdon" ModifiedBy="@_modifiedby" ModifiedOn="@_modifiedon" DeletedBy="@_deletedby" DeletedOn="@_deletedon"></AuditInfo>
|
|
||||||
}
|
|
||||||
</TabPanel>
|
|
||||||
<TabPanel Name="Permissions" ResourceKey="Permissions">
|
|
||||||
@if (_permissions != null)
|
|
||||||
{
|
|
||||||
<div class="container">
|
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<PermissionGrid EntityName="@EntityNames.Page" PermissionList="@_permissions" @ref="_permissionGrid" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</TabPanel>
|
|
||||||
<TabPanel Name="PageModules" Heading="Modules" ResourceKey="PageModules">
|
|
||||||
@if(_pageModules != null)
|
|
||||||
{
|
|
||||||
<Pager Items="_pageModules">
|
|
||||||
<Header>
|
|
||||||
<th style="width: 1px;"> </th>
|
|
||||||
<th style="width: 1px;"> </th>
|
|
||||||
<th>@Localizer["ModuleTitle"]</th>
|
|
||||||
<th>@Localizer["ModuleDefinition"]</th>
|
|
||||||
</Header>
|
|
||||||
<Row>
|
|
||||||
<td><ActionLink Action="Settings" Text="Edit" ModuleId="@context.ModuleId" Security="SecurityAccessLevel.Edit" PermissionList="@context.PermissionList" ResourceKey="ModuleSettings" /></td>
|
|
||||||
<td><ActionDialog Header="Delete Module" Message="Are You Sure You Wish To Delete This Module?" Action="Delete" Security="SecurityAccessLevel.Edit" PermissionList="@context.PermissionList" Class="btn btn-danger" OnClick="@(async () => await DeleteModule(context))" ResourceKey="DeleteModule" /></td>
|
|
||||||
<td>@context.Title</td>
|
|
||||||
<td>@context.ModuleDefinition?.Name</td>
|
|
||||||
</Row>
|
|
||||||
</Pager>
|
|
||||||
}
|
|
||||||
</TabPanel>
|
|
||||||
@if (_themeSettingsType != null)
|
|
||||||
{
|
|
||||||
<TabPanel Name="ThemeSettings" Heading="Theme Settings" ResourceKey="ThemeSettings">
|
|
||||||
@ThemeSettingsComponent
|
|
||||||
</TabPanel>
|
|
||||||
<br />
|
|
||||||
}
|
}
|
||||||
</TabStrip>
|
<br />
|
||||||
<br />
|
<button type="button" class="btn btn-success" @onclick="SavePage">@SharedLocalizer["Save"]</button>
|
||||||
<button type="button" class="btn btn-success" @onclick="SavePage">@SharedLocalizer["Save"]</button>
|
<button type="button" class="btn btn-secondary" @onclick="Cancel">@SharedLocalizer["Cancel"]</button>
|
||||||
<button type="button" class="btn btn-secondary" @onclick="Cancel">@SharedLocalizer["Cancel"]</button>
|
</form>
|
||||||
</form>
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.View;
|
||||||
|
|
||||||
|
private bool _initialized = false;
|
||||||
private ElementReference form;
|
private ElementReference form;
|
||||||
private bool validated = false;
|
private bool validated = false;
|
||||||
private List<ThemeControl> _themes = new List<ThemeControl>();
|
private List<ThemeControl> _themes = new List<ThemeControl>();
|
||||||
|
@ -243,7 +321,8 @@
|
||||||
private string _deletedby;
|
private string _deletedby;
|
||||||
private DateTime? _deletedon;
|
private DateTime? _deletedon;
|
||||||
private bool _refresh = false;
|
private bool _refresh = false;
|
||||||
protected Page page;
|
protected Page _page = null;
|
||||||
|
protected Page _parent = null;
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
|
@ -253,23 +332,24 @@
|
||||||
_themes = ThemeService.GetThemeControls(PageState.Site.Themes);
|
_themes = ThemeService.GetThemeControls(PageState.Site.Themes);
|
||||||
|
|
||||||
_pageId = Int32.Parse(PageState.QueryString["id"]);
|
_pageId = Int32.Parse(PageState.QueryString["id"]);
|
||||||
page = PageState.Pages.FirstOrDefault(item => item.PageId == _pageId);
|
_page = await PageService.GetPageAsync(_pageId);
|
||||||
|
|
||||||
if (page != null)
|
if (_page != null && UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, _page.PermissionList))
|
||||||
{
|
{
|
||||||
_name = page.Name;
|
_name = _page.Name;
|
||||||
if (page.ParentId == null)
|
if (_page.ParentId == null)
|
||||||
{
|
{
|
||||||
_parentid = "-1";
|
_parentid = "-1";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_parentid = page.ParentId.ToString();
|
_parentid = _page.ParentId.ToString();
|
||||||
|
_parent = PageState.Pages.FirstOrDefault(item => item.PageId == _page.ParentId);
|
||||||
}
|
}
|
||||||
_currentparentid = _parentid;
|
_currentparentid = _parentid;
|
||||||
_isnavigation = page.IsNavigation.ToString();
|
_isnavigation = _page.IsNavigation.ToString();
|
||||||
_isclickable = page.IsClickable.ToString();
|
_isclickable = _page.IsClickable.ToString();
|
||||||
_path = page.Path;
|
_path = _page.Path;
|
||||||
if (string.IsNullOrEmpty(_path))
|
if (string.IsNullOrEmpty(_path))
|
||||||
{
|
{
|
||||||
_path = "/";
|
_path = "/";
|
||||||
|
@ -281,43 +361,49 @@
|
||||||
_path = _path.Substring(_path.LastIndexOf("/") + 1);
|
_path = _path.Substring(_path.LastIndexOf("/") + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_url = page.Url;
|
_url = _page.Url;
|
||||||
_ispersonalizable = page.IsPersonalizable.ToString();
|
_icon = _page.Icon;
|
||||||
|
_ispersonalizable = _page.IsPersonalizable.ToString();
|
||||||
|
|
||||||
// appearance
|
// appearance
|
||||||
_title = page.Title;
|
_title = _page.Title;
|
||||||
_icon = page.Icon;
|
_themetype = _page.ThemeType;
|
||||||
_themetype = page.ThemeType;
|
|
||||||
if (string.IsNullOrEmpty(_themetype))
|
if (string.IsNullOrEmpty(_themetype))
|
||||||
{
|
{
|
||||||
_themetype = PageState.Site.DefaultThemeType;
|
_themetype = PageState.Site.DefaultThemeType;
|
||||||
}
|
}
|
||||||
_containers = ThemeService.GetContainerControls(PageState.Site.Themes, _themetype);
|
_containers = ThemeService.GetContainerControls(PageState.Site.Themes, _themetype);
|
||||||
_containertype = page.DefaultContainerType;
|
_containertype = _page.DefaultContainerType;
|
||||||
if (string.IsNullOrEmpty(_containertype))
|
if (string.IsNullOrEmpty(_containertype))
|
||||||
{
|
{
|
||||||
_containertype = PageState.Site.DefaultContainerType;
|
_containertype = PageState.Site.DefaultContainerType;
|
||||||
}
|
}
|
||||||
|
|
||||||
// page content
|
// page content
|
||||||
_headcontent = page.HeadContent;
|
_headcontent = _page.HeadContent;
|
||||||
_bodycontent = page.BodyContent;
|
_bodycontent = _page.BodyContent;
|
||||||
|
|
||||||
// permissions
|
// permissions
|
||||||
_permissions = page.PermissionList;
|
_permissions = _page.PermissionList;
|
||||||
|
|
||||||
// page modules
|
// page modules
|
||||||
_pageModules = PageState.Modules.Where(m => m.PageId == page.PageId).ToList();
|
_pageModules = PageState.Modules.Where(m => m.PageId == _page.PageId).ToList();
|
||||||
|
|
||||||
// audit
|
// audit
|
||||||
_createdby = page.CreatedBy;
|
_createdby = _page.CreatedBy;
|
||||||
_createdon = page.CreatedOn;
|
_createdon = _page.CreatedOn;
|
||||||
_modifiedby = page.ModifiedBy;
|
_modifiedby = _page.ModifiedBy;
|
||||||
_modifiedon = page.ModifiedOn;
|
_modifiedon = _page.ModifiedOn;
|
||||||
_deletedby = page.DeletedBy;
|
_deletedby = _page.DeletedBy;
|
||||||
_deletedon = page.DeletedOn;
|
_deletedon = _page.DeletedOn;
|
||||||
|
|
||||||
ThemeSettings();
|
ThemeSettings();
|
||||||
|
_initialized = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await logger.LogWarning("Error Loading Page {PageId}", _pageId);
|
||||||
|
AddModuleMessage(Localizer["Error.Page.Load"], MessageType.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
@ -331,7 +417,7 @@
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
PageModule pagemodule = await PageModuleService.GetPageModuleAsync(page.PageId, module.ModuleId);
|
PageModule pagemodule = await PageModuleService.GetPageModuleAsync(_page.PageId, module.ModuleId);
|
||||||
pagemodule.IsDeleted = true;
|
pagemodule.IsDeleted = true;
|
||||||
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
||||||
await logger.LogInformation(LogFunction.Update,"Module Deleted {Title}", module.Title);
|
await logger.LogInformation(LogFunction.Update,"Module Deleted {Title}", module.Title);
|
||||||
|
@ -409,23 +495,20 @@
|
||||||
private void ThemeSettings()
|
private void ThemeSettings()
|
||||||
{
|
{
|
||||||
_themeSettingsType = null;
|
_themeSettingsType = null;
|
||||||
if (PageState.QueryString.ContainsKey("cp")) // can only be displayed if invoked from Control Panel
|
var theme = PageState.Site.Themes.FirstOrDefault(item => item.Themes.Any(themecontrol => themecontrol.TypeName.Equals(_themetype)));
|
||||||
|
if (theme != null && !string.IsNullOrEmpty(theme.ThemeSettingsType))
|
||||||
{
|
{
|
||||||
var theme = PageState.Site.Themes.FirstOrDefault(item => item.Themes.Any(themecontrol => themecontrol.TypeName.Equals(_themetype)));
|
_themeSettingsType = Type.GetType(theme.ThemeSettingsType);
|
||||||
if (theme != null && !string.IsNullOrEmpty(theme.ThemeSettingsType))
|
if (_themeSettingsType != null)
|
||||||
{
|
{
|
||||||
_themeSettingsType = Type.GetType(theme.ThemeSettingsType);
|
ThemeSettingsComponent = builder =>
|
||||||
if (_themeSettingsType != null)
|
|
||||||
{
|
{
|
||||||
ThemeSettingsComponent = builder =>
|
builder.OpenComponent(0, _themeSettingsType);
|
||||||
{
|
builder.AddComponentReferenceCapture(1, inst => { _themeSettings = Convert.ChangeType(inst, _themeSettingsType); });
|
||||||
builder.OpenComponent(0, _themeSettingsType);
|
builder.CloseComponent();
|
||||||
builder.AddComponentReferenceCapture(1, inst => { _themeSettings = Convert.ChangeType(inst, _themeSettingsType); });
|
};
|
||||||
builder.CloseComponent();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
_refresh = true;
|
|
||||||
}
|
}
|
||||||
|
_refresh = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -435,15 +518,13 @@
|
||||||
var interop = new Interop(JSRuntime);
|
var interop = new Interop(JSRuntime);
|
||||||
if (await interop.FormValid(form))
|
if (await interop.FormValid(form))
|
||||||
{
|
{
|
||||||
Page page = null;
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(_themetype) && _containertype != "-")
|
if (!string.IsNullOrEmpty(_themetype) && _containertype != "-")
|
||||||
{
|
{
|
||||||
page = PageState.Pages.FirstOrDefault(item => item.PageId == _pageId);
|
string currentPath = _page.Path;
|
||||||
string currentPath = page.Path;
|
|
||||||
|
|
||||||
page.Name = _name;
|
_page.Name = _name;
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(_path))
|
if (string.IsNullOrEmpty(_path))
|
||||||
{
|
{
|
||||||
|
@ -460,33 +541,33 @@
|
||||||
|
|
||||||
if (_parentid == "-1")
|
if (_parentid == "-1")
|
||||||
{
|
{
|
||||||
page.ParentId = null;
|
_page.ParentId = null;
|
||||||
page.Path = Utilities.GetFriendlyUrl(_path);
|
_page.Path = Utilities.GetFriendlyUrl(_path);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
page.ParentId = Int32.Parse(_parentid);
|
_page.ParentId = Int32.Parse(_parentid);
|
||||||
Page parent = PageState.Pages.FirstOrDefault(item => item.PageId == page.ParentId);
|
Page parent = PageState.Pages.FirstOrDefault(item => item.PageId == _page.ParentId);
|
||||||
if (parent.Path == string.Empty)
|
if (parent.Path == string.Empty)
|
||||||
{
|
{
|
||||||
page.Path = Utilities.GetFriendlyUrl(parent.Name) + "/" + Utilities.GetFriendlyUrl(_path);
|
_page.Path = Utilities.GetFriendlyUrl(parent.Name) + "/" + Utilities.GetFriendlyUrl(_path);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
page.Path = parent.Path + "/" + Utilities.GetFriendlyUrl(_path);
|
_page.Path = parent.Path + "/" + Utilities.GetFriendlyUrl(_path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var _pages = await PageService.GetPagesAsync(PageState.Site.SiteId);
|
var _pages = await PageService.GetPagesAsync(PageState.Site.SiteId);
|
||||||
if (_pages.Any(item => item.Path == page.Path && item.PageId != page.PageId))
|
if (_pages.Any(item => item.Path == _page.Path && item.PageId != _page.PageId))
|
||||||
{
|
{
|
||||||
AddModuleMessage(string.Format(Localizer["Mesage.Page.PathExists"], _path), MessageType.Warning);
|
AddModuleMessage(string.Format(Localizer["Mesage.Page.PathExists"], _path), MessageType.Warning);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (page.ParentId == null && Constants.ReservedRoutes.Contains(page.Name.ToLower()))
|
if (_page.ParentId == null && Constants.ReservedRoutes.Contains(_page.Name.ToLower()))
|
||||||
{
|
{
|
||||||
AddModuleMessage(string.Format(Localizer["Message.Page.Reserved"], page.Name), MessageType.Warning);
|
AddModuleMessage(string.Format(Localizer["Message.Page.Reserved"], _page.Name), MessageType.Warning);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -496,57 +577,59 @@
|
||||||
switch (_insert)
|
switch (_insert)
|
||||||
{
|
{
|
||||||
case "<<":
|
case "<<":
|
||||||
page.Order = 0;
|
_page.Order = 0;
|
||||||
break;
|
break;
|
||||||
case "<":
|
case "<":
|
||||||
child = PageState.Pages.FirstOrDefault(item => item.PageId == _childid);
|
child = PageState.Pages.FirstOrDefault(item => item.PageId == _childid);
|
||||||
if (child != null) page.Order = child.Order - 1;
|
if (child != null) _page.Order = child.Order - 1;
|
||||||
break;
|
break;
|
||||||
case ">":
|
case ">":
|
||||||
child = PageState.Pages.FirstOrDefault(item => item.PageId == _childid);
|
child = PageState.Pages.FirstOrDefault(item => item.PageId == _childid);
|
||||||
if (child != null) page.Order = child.Order + 1;
|
if (child != null) _page.Order = child.Order + 1;
|
||||||
break;
|
break;
|
||||||
case ">>":
|
case ">>":
|
||||||
page.Order = int.MaxValue;
|
_page.Order = int.MaxValue;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
page.IsNavigation = (_isnavigation == null || Boolean.Parse(_isnavigation));
|
_page.IsNavigation = (_isnavigation == null || Boolean.Parse(_isnavigation));
|
||||||
page.IsClickable = (_isclickable == null ? true : Boolean.Parse(_isclickable));
|
_page.IsClickable = (_isclickable == null ? true : Boolean.Parse(_isclickable));
|
||||||
page.Url = _url;
|
_page.Url = _url;
|
||||||
page.IsPersonalizable = (_ispersonalizable != null && Boolean.Parse(_ispersonalizable));
|
_page.IsPersonalizable = (_ispersonalizable != null && Boolean.Parse(_ispersonalizable));
|
||||||
page.UserId = null;
|
|
||||||
|
|
||||||
// appearance
|
// appearance
|
||||||
page.Title = _title;
|
_page.Title = _title;
|
||||||
page.Icon = _icon ?? string.Empty;
|
_page.Icon = _icon ?? string.Empty;
|
||||||
page.ThemeType = (_themetype != "-") ? _themetype : string.Empty;
|
_page.ThemeType = (_themetype != "-") ? _themetype : string.Empty;
|
||||||
if (!string.IsNullOrEmpty(page.ThemeType) && page.ThemeType == PageState.Site.DefaultThemeType)
|
if (!string.IsNullOrEmpty(_page.ThemeType) && _page.ThemeType == PageState.Site.DefaultThemeType)
|
||||||
{
|
{
|
||||||
page.ThemeType = string.Empty;
|
_page.ThemeType = string.Empty;
|
||||||
}
|
}
|
||||||
page.DefaultContainerType = (_containertype != "-") ? _containertype : string.Empty;
|
_page.DefaultContainerType = (_containertype != "-") ? _containertype : string.Empty;
|
||||||
if (!string.IsNullOrEmpty(page.DefaultContainerType) && page.DefaultContainerType == PageState.Site.DefaultContainerType)
|
if (!string.IsNullOrEmpty(_page.DefaultContainerType) && _page.DefaultContainerType == PageState.Site.DefaultContainerType)
|
||||||
{
|
{
|
||||||
page.DefaultContainerType = string.Empty;
|
_page.DefaultContainerType = string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
// page content
|
// page content
|
||||||
page.HeadContent = _headcontent;
|
_page.HeadContent = _headcontent;
|
||||||
page.BodyContent = _bodycontent;
|
_page.BodyContent = _bodycontent;
|
||||||
|
|
||||||
// permissions
|
// permissions
|
||||||
page.PermissionList = _permissionGrid.GetPermissionList();
|
if (_page.UserId == null)
|
||||||
|
{
|
||||||
|
_page.PermissionList = _permissionGrid.GetPermissionList();
|
||||||
|
}
|
||||||
|
|
||||||
page = await PageService.UpdatePageAsync(page);
|
_page = await PageService.UpdatePageAsync(_page);
|
||||||
await PageService.UpdatePageOrderAsync(page.SiteId, page.PageId, page.ParentId);
|
await PageService.UpdatePageOrderAsync(_page.SiteId, _page.PageId, _page.ParentId);
|
||||||
if (_currentparentid == string.Empty)
|
if (_currentparentid == string.Empty)
|
||||||
{
|
{
|
||||||
await PageService.UpdatePageOrderAsync(page.SiteId, page.PageId, null);
|
await PageService.UpdatePageOrderAsync(_page.SiteId, _page.PageId, null);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await PageService.UpdatePageOrderAsync(page.SiteId, page.PageId, int.Parse(_currentparentid));
|
await PageService.UpdatePageOrderAsync(_page.SiteId, _page.PageId, int.Parse(_currentparentid));
|
||||||
}
|
}
|
||||||
|
|
||||||
// update child paths
|
// update child paths
|
||||||
|
@ -554,7 +637,7 @@
|
||||||
{
|
{
|
||||||
foreach (Page p in PageState.Pages.Where(item => item.Path.StartsWith(currentPath)))
|
foreach (Page p in PageState.Pages.Where(item => item.Path.StartsWith(currentPath)))
|
||||||
{
|
{
|
||||||
p.Path = p.Path.Replace(currentPath, page.Path);
|
p.Path = p.Path.Replace(currentPath, _page.Path);
|
||||||
await PageService.UpdatePageAsync(p);
|
await PageService.UpdatePageAsync(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -564,14 +647,14 @@
|
||||||
await themeSettingsControl.UpdateSettings();
|
await themeSettingsControl.UpdateSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
await logger.LogInformation("Page Saved {Page}", page);
|
await logger.LogInformation("Page Saved {Page}", _page);
|
||||||
if (PageState.QueryString.ContainsKey("cp"))
|
if (!string.IsNullOrEmpty(PageState.ReturnUrl))
|
||||||
{
|
{
|
||||||
NavigationManager.NavigateTo(NavigateUrl(PageState.Pages.First(item => item.PageId == int.Parse(PageState.QueryString["cp"])).Path));
|
NavigationManager.NavigateTo(PageState.ReturnUrl);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
NavigationManager.NavigateTo(NavigateUrl(page.Path));
|
NavigationManager.NavigateTo(NavigateUrl(_page.Path));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -581,7 +664,7 @@
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await logger.LogError(ex, "Error Saving Page {Page} {Error}", page, ex.Message);
|
await logger.LogError(ex, "Error Saving Page {Page} {Error}", _page, ex.Message);
|
||||||
AddModuleMessage(Localizer["Error.Page.Save"], MessageType.Error);
|
AddModuleMessage(Localizer["Error.Page.Save"], MessageType.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -593,9 +676,9 @@
|
||||||
|
|
||||||
private void Cancel()
|
private void Cancel()
|
||||||
{
|
{
|
||||||
if (PageState.QueryString.ContainsKey("cp"))
|
if (!string.IsNullOrEmpty(PageState.ReturnUrl))
|
||||||
{
|
{
|
||||||
NavigationManager.NavigateTo(NavigateUrl(PageState.Pages.First(item => item.PageId == int.Parse(PageState.QueryString["cp"])).Path));
|
NavigationManager.NavigateTo(PageState.ReturnUrl);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
@inject IStringLocalizer<Index> Localizer
|
@inject IStringLocalizer<Index> Localizer
|
||||||
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
||||||
|
|
||||||
@if (PageState.Pages != null)
|
@if (PageState.Pages != null && UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin))
|
||||||
{
|
{
|
||||||
<ActionLink Action="Add" Text="Add Page" ResourceKey="AddPage" />
|
<ActionLink Action="Add" Text="Add Page" ResourceKey="AddPage" />
|
||||||
|
|
||||||
|
|
|
@ -76,8 +76,8 @@ else
|
||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private List<Page> _pages;
|
private List<Page> _pages;
|
||||||
private List<Module> _modules;
|
private List<Module> _modules;
|
||||||
private int _pagePage = 1;
|
private int _pagePage = 1;
|
||||||
private int _pageModule = 1;
|
private int _pageModule = 1;
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
||||||
|
@ -184,13 +184,6 @@ else
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await PageModuleService.DeletePageModuleAsync(module.PageModuleId);
|
await PageModuleService.DeletePageModuleAsync(module.PageModuleId);
|
||||||
|
|
||||||
// check if there are any remaining module instances in the site
|
|
||||||
if (!_modules.Exists (item => item.ModuleId == module.ModuleId && item.PageModuleId != module.PageModuleId))
|
|
||||||
{
|
|
||||||
await ModuleService.DeleteModuleAsync(module.ModuleId);
|
|
||||||
}
|
|
||||||
|
|
||||||
await logger.LogInformation("Module Permanently Deleted {Module}", module);
|
await logger.LogInformation("Module Permanently Deleted {Module}", module);
|
||||||
await Load();
|
await Load();
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
|
@ -210,16 +203,7 @@ else
|
||||||
foreach (Module module in _modules.Where(item => item.IsDeleted).ToList())
|
foreach (Module module in _modules.Where(item => item.IsDeleted).ToList())
|
||||||
{
|
{
|
||||||
await PageModuleService.DeletePageModuleAsync(module.PageModuleId);
|
await PageModuleService.DeletePageModuleAsync(module.PageModuleId);
|
||||||
|
|
||||||
// DeletePageModuleAsync does not update _modules so remove it.
|
|
||||||
_modules.Remove(module);
|
|
||||||
// check if there are any remaining module instances in the site
|
|
||||||
if (!_modules.Exists(item => item.ModuleId == module.ModuleId && item.PageModuleId != module.PageModuleId))
|
|
||||||
{
|
|
||||||
await ModuleService.DeleteModuleAsync(module.ModuleId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await logger.LogInformation("Modules Permanently Deleted");
|
await logger.LogInformation("Modules Permanently Deleted");
|
||||||
await Load();
|
await Load();
|
||||||
ModuleInstance.HideProgressIndicator();
|
ModuleInstance.HideProgressIndicator();
|
||||||
|
|
|
@ -291,6 +291,16 @@ namespace Oqtane.Modules
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void AddScript(Resource resource)
|
||||||
|
{
|
||||||
|
resource.ResourceType = ResourceType.Script;
|
||||||
|
if (Resources == null) Resources = new List<Resource>();
|
||||||
|
if (!Resources.Any(item => (!string.IsNullOrEmpty(resource.Url) && item.Url == resource.Url) || (!string.IsNullOrEmpty(resource.Content) && item.Content == resource.Content)))
|
||||||
|
{
|
||||||
|
Resources.Add(resource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async Task ScrollToPageTop()
|
public async Task ScrollToPageTop()
|
||||||
{
|
{
|
||||||
var interop = new Interop(JSRuntime);
|
var interop = new Interop(JSRuntime);
|
||||||
|
|
|
@ -150,8 +150,8 @@
|
||||||
<data name="Container.Select" xml:space="preserve">
|
<data name="Container.Select" xml:space="preserve">
|
||||||
<value>Select Container</value>
|
<value>Select Container</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Error.Page.Initialize" xml:space="preserve">
|
<data name="Error.Page.Load" xml:space="preserve">
|
||||||
<value>Error Initializing Page</value>
|
<value>Error Loading Page</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Error.ChildPage.Load" xml:space="preserve">
|
<data name="Error.ChildPage.Load" xml:space="preserve">
|
||||||
<value>Error Loading Child Pages For Parent</value>
|
<value>Error Loading Child Pages For Parent</value>
|
||||||
|
|
|
@ -23,14 +23,6 @@ namespace Oqtane.Services
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<Page> GetPageAsync(int pageId);
|
Task<Page> GetPageAsync(int pageId);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Returns a specific page personalized for the given user
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="pageId"></param>
|
|
||||||
/// <param name="userId"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
Task<Page> GetPageAsync(int pageId, int userId);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns a specific page by its defined path
|
/// Returns a specific page by its defined path
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -25,11 +25,6 @@ namespace Oqtane.Services
|
||||||
return await GetJsonAsync<Page>($"{Apiurl}/{pageId}");
|
return await GetJsonAsync<Page>($"{Apiurl}/{pageId}");
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Page> GetPageAsync(int pageId, int userId)
|
|
||||||
{
|
|
||||||
return await GetJsonAsync<Page>($"{Apiurl}/{pageId}?userid={userId}");
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<Page> GetPageAsync(string path, int siteId)
|
public async Task<Page> GetPageAsync(string path, int siteId)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
// obtained from https://cdnjs.com/libraries
|
// obtained from https://cdnjs.com/libraries
|
||||||
new Resource { ResourceType = ResourceType.Stylesheet, Url = "https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.2.0/css/bootstrap.min.css", Integrity = "sha512-XWTTruHZEYJsxV3W/lSXG1n3Q39YIWOstqvmFsdNEEQfHoZ6vm6E9GK2OrF6DSJSpIbRbi+Nn0WDPID9O7xB2Q==", CrossOrigin = "anonymous" },
|
new Resource { ResourceType = ResourceType.Stylesheet, Url = "https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.2.0/css/bootstrap.min.css", Integrity = "sha512-XWTTruHZEYJsxV3W/lSXG1n3Q39YIWOstqvmFsdNEEQfHoZ6vm6E9GK2OrF6DSJSpIbRbi+Nn0WDPID9O7xB2Q==", CrossOrigin = "anonymous" },
|
||||||
new Resource { ResourceType = ResourceType.Stylesheet, Url = ThemePath() + "Theme.css" },
|
new Resource { ResourceType = ResourceType.Stylesheet, Url = ThemePath() + "Theme.css" },
|
||||||
new Resource { ResourceType = ResourceType.Script, Bundle = "Bootstrap", Url = "https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.2.0/js/bootstrap.bundle.min.js", Integrity = "sha512-9GacT4119eY3AcosfWtHMsT5JyZudrexyEVzTBWV3viP/YfB9e2pEy3N7WXL3SV6ASXpTU0vzzSxsbfsuUH4sQ==", CrossOrigin = "anonymous" }
|
new Resource { ResourceType = ResourceType.Script, Url = "https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.2.0/js/bootstrap.bundle.min.js", Integrity = "sha512-9GacT4119eY3AcosfWtHMsT5JyZudrexyEVzTBWV3viP/YfB9e2pEy3N7WXL3SV6ASXpTU0vzzSxsbfsuUH4sQ==", CrossOrigin = "anonymous" }
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
|
@ -2,7 +2,6 @@
|
||||||
@namespace Oqtane.Themes.Controls
|
@namespace Oqtane.Themes.Controls
|
||||||
@inherits ContainerBase
|
@inherits ContainerBase
|
||||||
@attribute [OqtaneIgnore]
|
@attribute [OqtaneIgnore]
|
||||||
@inject SiteState SiteState
|
|
||||||
|
|
||||||
<span class="app-moduletitle">
|
<span class="app-moduletitle">
|
||||||
@((MarkupString)title)
|
@((MarkupString)title)
|
||||||
|
|
|
@ -56,7 +56,7 @@
|
||||||
</div>
|
</div>
|
||||||
<hr class="app-rule" />
|
<hr class="app-rule" />
|
||||||
}
|
}
|
||||||
@if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin))
|
@if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.PermissionList))
|
||||||
{
|
{
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col text-center">
|
<div class="col text-center">
|
||||||
|
@ -65,7 +65,10 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="row d-flex mb-2">
|
<div class="row d-flex mb-2">
|
||||||
<div class="col d-flex justify-content-between">
|
<div class="col d-flex justify-content-between">
|
||||||
<button type="button" class="btn btn-secondary col me-1" data-bs-dismiss="offcanvas" @onclick=@(async () => Navigate("Add"))>@SharedLocalizer["Add"]</button>
|
@if (PageState.Page.UserId == null)
|
||||||
|
{
|
||||||
|
<button type="button" class="btn btn-secondary col me-1" data-bs-dismiss="offcanvas" @onclick=@(async () => Navigate("Add"))>@SharedLocalizer["Add"]</button>
|
||||||
|
}
|
||||||
<button type="button" class="btn btn-secondary col" data-bs-dismiss="offcanvas" @onclick=@(async () => Navigate("Edit"))>@SharedLocalizer["Edit"]</button>
|
<button type="button" class="btn btn-secondary col" data-bs-dismiss="offcanvas" @onclick=@(async () => Navigate("Edit"))>@SharedLocalizer["Edit"]</button>
|
||||||
<button type="button" class="btn btn-danger col ms-1" @onclick="ConfirmDelete">@SharedLocalizer["Delete"]</button>
|
<button type="button" class="btn btn-danger col ms-1" @onclick="ConfirmDelete">@SharedLocalizer["Delete"]</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -489,9 +492,9 @@
|
||||||
{
|
{
|
||||||
if (PageState.Page.IsPersonalizable && PageState.User != null)
|
if (PageState.Page.IsPersonalizable && PageState.User != null)
|
||||||
{
|
{
|
||||||
await PageService.AddPageAsync(PageState.Page.PageId, PageState.User.UserId);
|
var page = await PageService.AddPageAsync(PageState.Page.PageId, PageState.User.UserId);
|
||||||
PageState.EditMode = true;
|
PageState.EditMode = true;
|
||||||
NavigationManager.NavigateTo(NavigateUrl(PageState.Page.Path, "edit=" + ((PageState.EditMode) ? "true" : "false")));
|
NavigationManager.NavigateTo(NavigateUrl(page.Path, "edit=" + ((PageState.EditMode) ? "true" : "false")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -520,10 +523,10 @@
|
||||||
switch (location)
|
switch (location)
|
||||||
{
|
{
|
||||||
case "Add":
|
case "Add":
|
||||||
url = EditUrl(PageState.Page.Path, module.ModuleId, location, "cp=" + PageState.Page.PageId);
|
url = EditUrl("admin/pages", module.ModuleId, location, $"id={PageState.Page.PageId}&returnurl={WebUtility.UrlEncode(PageState.Route.PathAndQuery)}");
|
||||||
break;
|
break;
|
||||||
case "Edit":
|
case "Edit":
|
||||||
url = EditUrl(PageState.Page.Path, module.ModuleId, location, "id=" + PageState.Page.PageId.ToString() + "&cp=" + PageState.Page.PageId);
|
url = EditUrl("admin/pages", module.ModuleId, location, $"id={PageState.Page.PageId}&returnurl={WebUtility.UrlEncode(PageState.Route.PathAndQuery)}");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,6 @@ namespace Oqtane.Themes.Controls
|
||||||
[Inject] public IUserService UserService { get; set; }
|
[Inject] public IUserService UserService { get; set; }
|
||||||
[Inject] public IJSRuntime jsRuntime { get; set; }
|
[Inject] public IJSRuntime jsRuntime { get; set; }
|
||||||
[Inject] public IServiceProvider ServiceProvider { get; set; }
|
[Inject] public IServiceProvider ServiceProvider { get; set; }
|
||||||
[Inject] public SiteState SiteState { get; set; }
|
|
||||||
[Inject] public ILogService LoggingService { get; set; }
|
[Inject] public ILogService LoggingService { get; set; }
|
||||||
|
|
||||||
protected void LoginUser()
|
protected void LoginUser()
|
||||||
|
|
|
@ -52,17 +52,23 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private string resourceType = "Oqtane.Themes.OqtaneTheme.ThemeSettings, Oqtane.Client"; // for localization
|
private int pageId = -1;
|
||||||
private string _scope = "page";
|
private string resourceType = "Oqtane.Themes.OqtaneTheme.ThemeSettings, Oqtane.Client"; // for localization
|
||||||
private string _login = "-";
|
private string _scope = "page";
|
||||||
private string _register = "-";
|
private string _login = "-";
|
||||||
private string _footer = "-";
|
private string _register = "-";
|
||||||
|
private string _footer = "-";
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
try
|
if (PageState.QueryString.ContainsKey("id"))
|
||||||
{
|
{
|
||||||
await LoadSettings();
|
pageId = int.Parse(PageState.QueryString["id"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await LoadSettings();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@ -82,10 +88,11 @@
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var settings = SettingService.MergeSettings(PageState.Site.Settings, PageState.Page.Settings);
|
var settings = await SettingService.GetPageSettingsAsync(pageId);
|
||||||
|
settings = SettingService.MergeSettings(PageState.Site.Settings, settings);
|
||||||
_login = SettingService.GetSetting(settings, GetType().Namespace + ":Login", "-");
|
_login = SettingService.GetSetting(settings, GetType().Namespace + ":Login", "-");
|
||||||
_register = SettingService.GetSetting(settings, GetType().Namespace + ":Register", "-");
|
_register = SettingService.GetSetting(settings, GetType().Namespace + ":Register", "-");
|
||||||
_footer = SettingService.GetSetting(settings, GetType().Namespace + ":Footer", "-");
|
_footer = SettingService.GetSetting(settings, GetType().Namespace + ":Footer", "-");
|
||||||
}
|
}
|
||||||
await Task.Yield();
|
await Task.Yield();
|
||||||
}
|
}
|
||||||
|
@ -128,7 +135,7 @@
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var settings = await SettingService.GetPageSettingsAsync(PageState.Page.PageId);
|
var settings = await SettingService.GetPageSettingsAsync(pageId);
|
||||||
if (_login != "-")
|
if (_login != "-")
|
||||||
{
|
{
|
||||||
settings = SettingService.SetSetting(settings, GetType().Namespace + ":Login", _login);
|
settings = SettingService.SetSetting(settings, GetType().Namespace + ":Login", _login);
|
||||||
|
@ -141,7 +148,7 @@
|
||||||
{
|
{
|
||||||
settings = SettingService.SetSetting(settings, GetType().Namespace + ":Footer", _footer);
|
settings = SettingService.SetSetting(settings, GetType().Namespace + ":Footer", _footer);
|
||||||
}
|
}
|
||||||
await SettingService.UpdatePageSettingsAsync(settings, PageState.Page.PageId);
|
await SettingService.UpdatePageSettingsAsync(settings, pageId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|
|
@ -15,10 +15,13 @@ namespace Oqtane.Themes
|
||||||
[Inject]
|
[Inject]
|
||||||
protected IJSRuntime JSRuntime { get; set; }
|
protected IJSRuntime JSRuntime { get; set; }
|
||||||
|
|
||||||
// optional interface properties
|
[Inject]
|
||||||
|
protected SiteState SiteState { get; set; }
|
||||||
|
|
||||||
[CascadingParameter]
|
[CascadingParameter]
|
||||||
protected PageState PageState { get; set; }
|
protected PageState PageState { get; set; }
|
||||||
|
|
||||||
|
// optional interface properties
|
||||||
public virtual string Name { get; set; }
|
public virtual string Name { get; set; }
|
||||||
public virtual string Thumbnail { get; set; }
|
public virtual string Thumbnail { get; set; }
|
||||||
public virtual string Panes { get; set; }
|
public virtual string Panes { get; set; }
|
||||||
|
@ -139,6 +142,34 @@ namespace Oqtane.Themes
|
||||||
return Utilities.ImageUrl(PageState.Alias, fileid, width, height, mode, position, background, rotate, recreate);
|
return Utilities.ImageUrl(PageState.Alias, fileid, width, height, mode, position, background, rotate, recreate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetPageTitle(string title)
|
||||||
|
{
|
||||||
|
SiteState.Properties.PageTitle = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
// note - only supports links and meta tags - not scripts
|
||||||
|
public void AddHeadContent(string content)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(SiteState.Properties.HeadContent))
|
||||||
|
{
|
||||||
|
SiteState.Properties.HeadContent = content;
|
||||||
|
}
|
||||||
|
else if (!SiteState.Properties.HeadContent.Contains(content))
|
||||||
|
{
|
||||||
|
SiteState.Properties.HeadContent += content;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddScript(Resource resource)
|
||||||
|
{
|
||||||
|
resource.ResourceType = ResourceType.Script;
|
||||||
|
if (Resources == null) Resources = new List<Resource>();
|
||||||
|
if (!Resources.Any(item => (!string.IsNullOrEmpty(resource.Url) && item.Url == resource.Url) || (!string.IsNullOrEmpty(resource.Content) && item.Content == resource.Content)))
|
||||||
|
{
|
||||||
|
Resources.Add(resource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Obsolete("ContentUrl(int fileId) is deprecated. Use FileUrl(int fileId) instead.", false)]
|
[Obsolete("ContentUrl(int fileId) is deprecated. Use FileUrl(int fileId) instead.", false)]
|
||||||
public string ContentUrl(int fileid)
|
public string ContentUrl(int fileid)
|
||||||
{
|
{
|
||||||
|
|
|
@ -221,6 +221,23 @@
|
||||||
page = site.Pages.FirstOrDefault();
|
page = site.Pages.FirstOrDefault();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (page == null)
|
||||||
|
{
|
||||||
|
// look for personalized page
|
||||||
|
page = await PageService.GetPageAsync(route.PagePath, site.SiteId);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (user != null && page.IsPersonalizable)
|
||||||
|
{
|
||||||
|
var personalized = await PageService.GetPageAsync(route.PagePath + "/" + user.Username, site.SiteId);
|
||||||
|
if (personalized != null)
|
||||||
|
{
|
||||||
|
// redirect to the personalized page
|
||||||
|
NavigationManager.NavigateTo(Utilities.NavigateUrl(SiteState.Alias.Path, personalized.Path, ""), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (page != null)
|
if (page != null)
|
||||||
{
|
{
|
||||||
|
@ -228,7 +245,7 @@
|
||||||
if (UserSecurity.IsAuthorized(user, PermissionNames.View, page.PermissionList))
|
if (UserSecurity.IsAuthorized(user, PermissionNames.View, page.PermissionList))
|
||||||
{
|
{
|
||||||
// load additional metadata for current page
|
// load additional metadata for current page
|
||||||
page = await ProcessPage(page, site, user, SiteState.Alias);
|
page = ProcessPage(page, site, user, SiteState.Alias);
|
||||||
|
|
||||||
// load additional metadata for modules
|
// load additional metadata for modules
|
||||||
(page, site.Modules) = ProcessModules(page, site.Modules, moduleid, action, (!string.IsNullOrEmpty(page.DefaultContainerType)) ? page.DefaultContainerType : site.DefaultContainerType, SiteState.Alias);
|
(page, site.Modules) = ProcessModules(page, site.Modules, moduleid, action, (!string.IsNullOrEmpty(page.DefaultContainerType)) ? page.DefaultContainerType : site.DefaultContainerType, SiteState.Alias);
|
||||||
|
@ -297,16 +314,10 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<Page> ProcessPage(Page page, Site site, User user, Alias alias)
|
private Page ProcessPage(Page page, Site site, User user, Alias alias)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (page.IsPersonalizable && user != null)
|
|
||||||
{
|
|
||||||
// load the personalized page
|
|
||||||
page = await PageService.GetPageAsync(page.PageId, user.UserId);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(page.ThemeType))
|
if (string.IsNullOrEmpty(page.ThemeType))
|
||||||
{
|
{
|
||||||
page.ThemeType = site.DefaultThemeType;
|
page.ThemeType = site.DefaultThemeType;
|
||||||
|
|
|
@ -96,30 +96,30 @@
|
||||||
{
|
{
|
||||||
await InjectScripts(PageState.Page.BodyContent, ResourceLocation.Body);
|
await InjectScripts(PageState.Page.BodyContent, ResourceLocation.Body);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (PageState.Page.Resources != null && PageState.Page.Resources.Exists(item => item.ResourceType == ResourceType.Script))
|
if (PageState.Page.Resources != null && PageState.Page.Resources.Exists(item => item.ResourceType == ResourceType.Script))
|
||||||
|
{
|
||||||
|
var interop = new Interop(JSRuntime);
|
||||||
|
var scripts = new List<object>();
|
||||||
|
var inline = 0;
|
||||||
|
foreach (Resource resource in PageState.Page.Resources.Where(item => item.ResourceType == ResourceType.Script && item.Level != ResourceLevel.Site))
|
||||||
{
|
{
|
||||||
var interop = new Interop(JSRuntime);
|
if (!string.IsNullOrEmpty(resource.Url))
|
||||||
var scripts = new List<object>();
|
|
||||||
var inline = 0;
|
|
||||||
foreach (Resource resource in PageState.Page.Resources.Where(item => item.ResourceType == ResourceType.Script && item.Level != ResourceLevel.Site))
|
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(resource.Url))
|
var url = (resource.Url.Contains("://")) ? resource.Url : PageState.Alias.BaseUrl + resource.Url;
|
||||||
{
|
scripts.Add(new { href = url, bundle = resource.Bundle ?? "", integrity = resource.Integrity ?? "", crossorigin = resource.CrossOrigin ?? "", es6module = resource.ES6Module, location = resource.Location.ToString().ToLower() });
|
||||||
var url = (resource.Url.Contains("://")) ? resource.Url : PageState.Alias.BaseUrl + resource.Url;
|
|
||||||
scripts.Add(new { href = url, bundle = resource.Bundle ?? "", integrity = resource.Integrity ?? "", crossorigin = resource.CrossOrigin ?? "", es6module = resource.ES6Module, location = resource.Location.ToString().ToLower() });
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
inline += 1;
|
|
||||||
await interop.IncludeScript(GetType().Namespace.ToLower() + inline.ToString(), "", "", "", resource.Content, resource.Location.ToString().ToLower());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (scripts.Any())
|
else
|
||||||
{
|
{
|
||||||
await interop.IncludeScripts(scripts.ToArray());
|
inline += 1;
|
||||||
|
await interop.IncludeScript(GetType().Namespace.ToLower() + inline.ToString(), "", "", "", resource.Content, resource.Location.ToString().ToLower());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (scripts.Any())
|
||||||
|
{
|
||||||
|
await interop.IncludeScripts(scripts.ToArray());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
6
Oqtane.Maui/Head.razor
Normal file
6
Oqtane.Maui/Head.razor
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<DynamicComponent Type="@ComponentType"></DynamicComponent>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
Type ComponentType = Type.GetType("Oqtane.Head, Oqtane.Client");
|
||||||
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
<BlazorWebView HostPage="wwwroot/index.html">
|
<BlazorWebView HostPage="wwwroot/index.html">
|
||||||
<BlazorWebView.RootComponents>
|
<BlazorWebView.RootComponents>
|
||||||
|
<RootComponent Selector="head::after" ComponentType="{x:Type local:Head}" />
|
||||||
<RootComponent Selector="#app" ComponentType="{x:Type local:Main}" />
|
<RootComponent Selector="#app" ComponentType="{x:Type local:Main}" />
|
||||||
</BlazorWebView.RootComponents>
|
</BlazorWebView.RootComponents>
|
||||||
</BlazorWebView>
|
</BlazorWebView>
|
||||||
|
|
|
@ -10,6 +10,8 @@ using Oqtane.Enums;
|
||||||
using Oqtane.Extensions;
|
using Oqtane.Extensions;
|
||||||
using Oqtane.Infrastructure;
|
using Oqtane.Infrastructure;
|
||||||
using Oqtane.Repository;
|
using Oqtane.Repository;
|
||||||
|
using Oqtane.Modules.Admin.Users;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
namespace Oqtane.Controllers
|
namespace Oqtane.Controllers
|
||||||
{
|
{
|
||||||
|
@ -73,19 +75,11 @@ namespace Oqtane.Controllers
|
||||||
return pages;
|
return pages;
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET api/<controller>/5?userid=x
|
// GET api/<controller>/5
|
||||||
[HttpGet("{id}")]
|
[HttpGet("{id}")]
|
||||||
public Page Get(int id, string userid)
|
public Page Get(int id)
|
||||||
{
|
{
|
||||||
Page page = null;
|
var page = _pages.GetPage(id);
|
||||||
if (string.IsNullOrEmpty(userid))
|
|
||||||
{
|
|
||||||
page = _pages.GetPage(id);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
page = _pages.GetPage(id, int.Parse(userid));
|
|
||||||
}
|
|
||||||
if (page != null && page.SiteId == _alias.SiteId && _userPermissions.IsAuthorized(User, PermissionNames.View, page.PermissionList))
|
if (page != null && page.SiteId == _alias.SiteId && _userPermissions.IsAuthorized(User, PermissionNames.View, page.PermissionList))
|
||||||
{
|
{
|
||||||
page.Settings = _settings.GetSettings(EntityNames.Page, page.PageId)
|
page.Settings = _settings.GetSettings(EntityNames.Page, page.PageId)
|
||||||
|
@ -95,7 +89,7 @@ namespace Oqtane.Controllers
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Page Get Attempt {PageId} {UserId}", id, userid);
|
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Page Get Attempt {PageId}", id);
|
||||||
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -180,29 +174,30 @@ namespace Oqtane.Controllers
|
||||||
{
|
{
|
||||||
Page page = null;
|
Page page = null;
|
||||||
Page parent = _pages.GetPage(id);
|
Page parent = _pages.GetPage(id);
|
||||||
if (parent != null && parent.SiteId == _alias.SiteId && parent.IsPersonalizable && _userPermissions.GetUser(User).UserId == int.Parse(userid))
|
User user = _userPermissions.GetUser(User);
|
||||||
|
if (parent != null && parent.SiteId == _alias.SiteId && parent.IsPersonalizable && user.UserId == int.Parse(userid))
|
||||||
{
|
{
|
||||||
page = new Page();
|
page = new Page();
|
||||||
page.SiteId = parent.SiteId;
|
page.SiteId = parent.SiteId;
|
||||||
page.Name = parent.Name;
|
|
||||||
page.Title = parent.Title;
|
|
||||||
page.Path = parent.Path;
|
|
||||||
page.ParentId = parent.PageId;
|
page.ParentId = parent.PageId;
|
||||||
|
page.Name = user.Username;
|
||||||
|
page.Path = parent.Path + "/" + page.Name;
|
||||||
|
page.Title = parent.Name + " - " + page.Name;
|
||||||
page.Order = 0;
|
page.Order = 0;
|
||||||
page.IsNavigation = false;
|
page.IsNavigation = false;
|
||||||
page.Url = "";
|
page.Url = "";
|
||||||
page.ThemeType = parent.ThemeType;
|
page.ThemeType = parent.ThemeType;
|
||||||
page.DefaultContainerType = parent.DefaultContainerType;
|
page.DefaultContainerType = parent.DefaultContainerType;
|
||||||
page.Icon = parent.Icon;
|
page.Icon = parent.Icon;
|
||||||
page.PermissionList = new List<Permission> {
|
page.PermissionList = new List<Permission>()
|
||||||
|
{
|
||||||
new Permission(PermissionNames.View, int.Parse(userid), true),
|
new Permission(PermissionNames.View, int.Parse(userid), true),
|
||||||
|
new Permission(PermissionNames.View, RoleNames.Everyone, true),
|
||||||
new Permission(PermissionNames.Edit, int.Parse(userid), true)
|
new Permission(PermissionNames.Edit, int.Parse(userid), true)
|
||||||
};
|
};
|
||||||
page.IsPersonalizable = false;
|
page.IsPersonalizable = false;
|
||||||
page.UserId = int.Parse(userid);
|
page.UserId = int.Parse(userid);
|
||||||
page = _pages.AddPage(page);
|
page = _pages.AddPage(page);
|
||||||
_syncManager.AddSyncEvent(_alias.TenantId, EntityNames.Page, page.PageId, SyncEventActions.Create);
|
|
||||||
_syncManager.AddSyncEvent(_alias.TenantId, EntityNames.Site, page.SiteId, SyncEventActions.Refresh);
|
|
||||||
|
|
||||||
// copy modules
|
// copy modules
|
||||||
List<PageModule> pagemodules = _pageModules.GetPageModules(page.SiteId).ToList();
|
List<PageModule> pagemodules = _pageModules.GetPageModules(page.SiteId).ToList();
|
||||||
|
@ -213,8 +208,10 @@ namespace Oqtane.Controllers
|
||||||
module.PageId = page.PageId;
|
module.PageId = page.PageId;
|
||||||
module.ModuleDefinitionName = pm.Module.ModuleDefinitionName;
|
module.ModuleDefinitionName = pm.Module.ModuleDefinitionName;
|
||||||
module.AllPages = false;
|
module.AllPages = false;
|
||||||
module.PermissionList = new List<Permission> {
|
module.PermissionList = new List<Permission>()
|
||||||
|
{
|
||||||
new Permission(PermissionNames.View, int.Parse(userid), true),
|
new Permission(PermissionNames.View, int.Parse(userid), true),
|
||||||
|
new Permission(PermissionNames.View, RoleNames.Everyone, true),
|
||||||
new Permission(PermissionNames.Edit, int.Parse(userid), true)
|
new Permission(PermissionNames.Edit, int.Parse(userid), true)
|
||||||
};
|
};
|
||||||
module = _modules.AddModule(module);
|
module = _modules.AddModule(module);
|
||||||
|
@ -235,6 +232,9 @@ namespace Oqtane.Controllers
|
||||||
|
|
||||||
_pageModules.AddPageModule(pagemodule);
|
_pageModules.AddPageModule(pagemodule);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_syncManager.AddSyncEvent(_alias.TenantId, EntityNames.Page, page.PageId, SyncEventActions.Create);
|
||||||
|
_syncManager.AddSyncEvent(_alias.TenantId, EntityNames.Site, page.SiteId, SyncEventActions.Refresh);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -141,7 +141,7 @@ namespace Oqtane.SiteTemplates
|
||||||
Path = "develop",
|
Path = "develop",
|
||||||
Icon = "oi oi-wrench",
|
Icon = "oi oi-wrench",
|
||||||
IsNavigation = true,
|
IsNavigation = true,
|
||||||
IsPersonalizable = true,
|
IsPersonalizable = false,
|
||||||
PermissionList = new List<Permission> {
|
PermissionList = new List<Permission> {
|
||||||
new Permission(PermissionNames.View, RoleNames.Host, true),
|
new Permission(PermissionNames.View, RoleNames.Host, true),
|
||||||
new Permission(PermissionNames.Edit, RoleNames.Host, true)
|
new Permission(PermissionNames.Edit, RoleNames.Host, true)
|
||||||
|
|
|
@ -10,7 +10,6 @@ namespace Oqtane.Repository
|
||||||
Page UpdatePage(Page page);
|
Page UpdatePage(Page page);
|
||||||
Page GetPage(int pageId);
|
Page GetPage(int pageId);
|
||||||
Page GetPage(int pageId, bool tracking);
|
Page GetPage(int pageId, bool tracking);
|
||||||
Page GetPage(int pageId, int userId);
|
|
||||||
Page GetPage(string path, int siteId);
|
Page GetPage(string path, int siteId);
|
||||||
void DeletePage(int pageId);
|
void DeletePage(int pageId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Oqtane.Extensions;
|
using Oqtane.Extensions;
|
||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
|
@ -11,16 +12,20 @@ namespace Oqtane.Repository
|
||||||
{
|
{
|
||||||
private TenantDBContext _db;
|
private TenantDBContext _db;
|
||||||
private readonly IModuleDefinitionRepository _moduleDefinitions;
|
private readonly IModuleDefinitionRepository _moduleDefinitions;
|
||||||
|
private readonly IModuleRepository _modules;
|
||||||
private readonly IPermissionRepository _permissions;
|
private readonly IPermissionRepository _permissions;
|
||||||
|
private readonly ISettingRepository _settings;
|
||||||
|
|
||||||
public PageModuleRepository(TenantDBContext context, IModuleDefinitionRepository moduleDefinitions, IPermissionRepository permissions)
|
public PageModuleRepository(TenantDBContext context, IModuleDefinitionRepository moduleDefinitions, IModuleRepository modules, IPermissionRepository permissions, ISettingRepository settings)
|
||||||
{
|
{
|
||||||
_db = context;
|
_db = context;
|
||||||
_moduleDefinitions = moduleDefinitions;
|
_moduleDefinitions = moduleDefinitions;
|
||||||
|
_modules = modules;
|
||||||
_permissions = permissions;
|
_permissions = permissions;
|
||||||
}
|
_settings = settings;
|
||||||
|
}
|
||||||
|
|
||||||
public IEnumerable<PageModule> GetPageModules(int siteId)
|
public IEnumerable<PageModule> GetPageModules(int siteId)
|
||||||
{
|
{
|
||||||
var pagemodules = _db.PageModule
|
var pagemodules = _db.PageModule
|
||||||
.Include(item => item.Module) // eager load modules
|
.Include(item => item.Module) // eager load modules
|
||||||
|
@ -93,9 +98,18 @@ namespace Oqtane.Repository
|
||||||
|
|
||||||
public void DeletePageModule(int pageModuleId)
|
public void DeletePageModule(int pageModuleId)
|
||||||
{
|
{
|
||||||
PageModule pageModule = _db.PageModule.Find(pageModuleId);
|
PageModule pageModule = _db.PageModule.Include(item => item.Module) // eager load modules
|
||||||
|
.SingleOrDefault(item => item.PageModuleId == pageModuleId);
|
||||||
|
_settings.DeleteSettings(EntityNames.PageModule, pageModuleId);
|
||||||
_db.PageModule.Remove(pageModule);
|
_db.PageModule.Remove(pageModule);
|
||||||
_db.SaveChanges();
|
_db.SaveChanges();
|
||||||
|
|
||||||
|
// check if there are any remaining module instances in the site
|
||||||
|
var pageModules = GetPageModules(pageModule.Module.SiteId);
|
||||||
|
if (!pageModules.Any(item => item.ModuleId == pageModule.ModuleId))
|
||||||
|
{
|
||||||
|
_modules.DeleteModule(pageModule.ModuleId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private PageModule GetPageModule(PageModule pageModule, List<ModuleDefinition> moduleDefinitions, List<Permission> modulePermissions)
|
private PageModule GetPageModule(PageModule pageModule, List<ModuleDefinition> moduleDefinitions, List<Permission> modulePermissions)
|
||||||
|
|
|
@ -10,14 +10,16 @@ namespace Oqtane.Repository
|
||||||
public class PageRepository : IPageRepository
|
public class PageRepository : IPageRepository
|
||||||
{
|
{
|
||||||
private TenantDBContext _db;
|
private TenantDBContext _db;
|
||||||
private readonly IPermissionRepository _permissions;
|
|
||||||
private readonly IPageModuleRepository _pageModules;
|
private readonly IPageModuleRepository _pageModules;
|
||||||
|
private readonly IPermissionRepository _permissions;
|
||||||
|
private readonly ISettingRepository _settings;
|
||||||
|
|
||||||
public PageRepository(TenantDBContext context, IPermissionRepository permissions, IPageModuleRepository pageModules)
|
public PageRepository(TenantDBContext context, IPageModuleRepository pageModules, IPermissionRepository permissions, ISettingRepository settings)
|
||||||
{
|
{
|
||||||
_db = context;
|
_db = context;
|
||||||
_permissions = permissions;
|
|
||||||
_pageModules = pageModules;
|
_pageModules = pageModules;
|
||||||
|
_permissions = permissions;
|
||||||
|
_settings = settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<Page> GetPages(int siteId)
|
public IEnumerable<Page> GetPages(int siteId)
|
||||||
|
@ -71,21 +73,6 @@ namespace Oqtane.Repository
|
||||||
return page;
|
return page;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Page GetPage(int pageId, int userId)
|
|
||||||
{
|
|
||||||
Page page = _db.Page.Find(pageId);
|
|
||||||
if (page != null)
|
|
||||||
{
|
|
||||||
Page personalized = _db.Page.FirstOrDefault(item => item.SiteId == page.SiteId && item.Path == page.Path && item.UserId == userId);
|
|
||||||
if (personalized != null)
|
|
||||||
{
|
|
||||||
page = personalized;
|
|
||||||
}
|
|
||||||
page.PermissionList = _permissions.GetPermissions(page.SiteId, EntityNames.Page, page.PageId)?.ToList();
|
|
||||||
}
|
|
||||||
return page;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Page GetPage(string path, int siteId)
|
public Page GetPage(string path, int siteId)
|
||||||
{
|
{
|
||||||
Page page = _db.Page.FirstOrDefault(item => item.Path == path && item.SiteId == siteId);
|
Page page = _db.Page.FirstOrDefault(item => item.Path == path && item.SiteId == siteId);
|
||||||
|
@ -100,11 +87,14 @@ namespace Oqtane.Repository
|
||||||
{
|
{
|
||||||
Page page = _db.Page.Find(pageId);
|
Page page = _db.Page.Find(pageId);
|
||||||
_permissions.DeletePermissions(page.SiteId, EntityNames.Page, pageId);
|
_permissions.DeletePermissions(page.SiteId, EntityNames.Page, pageId);
|
||||||
IEnumerable<PageModule> pageModules = _db.PageModule.Where(item => item.PageId == pageId).ToList();
|
_settings.DeleteSettings(EntityNames.Page, pageId);
|
||||||
|
// remove page modules for page
|
||||||
|
var pageModules = _db.PageModule.Where(item => item.PageId == pageId).ToList();
|
||||||
foreach (var pageModule in pageModules)
|
foreach (var pageModule in pageModules)
|
||||||
{
|
{
|
||||||
_pageModules.DeletePageModule(pageModule.PageModuleId);
|
_pageModules.DeletePageModule(pageModule.PageModuleId);
|
||||||
}
|
}
|
||||||
|
// must occur after page modules are deleted because of cascading delete relationship
|
||||||
_db.Page.Remove(page);
|
_db.Page.Remove(page);
|
||||||
_db.SaveChanges();
|
_db.SaveChanges();
|
||||||
}
|
}
|
||||||
|
|
|
@ -694,6 +694,7 @@ namespace Oqtane.Repository
|
||||||
PermissionList = new List<Permission>
|
PermissionList = new List<Permission>
|
||||||
{
|
{
|
||||||
new Permission(PermissionNames.View, RoleNames.Admin, true),
|
new Permission(PermissionNames.View, RoleNames.Admin, true),
|
||||||
|
new Permission(PermissionNames.View, RoleNames.Registered, true),
|
||||||
new Permission(PermissionNames.Edit, RoleNames.Admin, true)
|
new Permission(PermissionNames.Edit, RoleNames.Admin, true)
|
||||||
},
|
},
|
||||||
PageTemplateModules = new List<PageTemplateModule>
|
PageTemplateModules = new List<PageTemplateModule>
|
||||||
|
|
|
@ -87,6 +87,8 @@ namespace Oqtane.Repository
|
||||||
Theme.Resources = theme.Resources;
|
Theme.Resources = theme.Resources;
|
||||||
Theme.Themes = theme.Themes;
|
Theme.Themes = theme.Themes;
|
||||||
Theme.Containers = theme.Containers;
|
Theme.Containers = theme.Containers;
|
||||||
|
Theme.ThemeSettingsType = theme.ThemeSettingsType;
|
||||||
|
Theme.ContainerSettingsType = theme.ContainerSettingsType;
|
||||||
Themes.Add(Theme);
|
Themes.Add(Theme);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ namespace [Owner].[Module]
|
||||||
public ModuleDefinition ModuleDefinition => new ModuleDefinition
|
public ModuleDefinition ModuleDefinition => new ModuleDefinition
|
||||||
{
|
{
|
||||||
Name = "[Module]",
|
Name = "[Module]",
|
||||||
Description = "[Module]",
|
Description = "[Description]",
|
||||||
Version = "1.0.0",
|
Version = "1.0.0",
|
||||||
ServerManagerType = "[ServerManagerType]",
|
ServerManagerType = "[ServerManagerType]",
|
||||||
ReleaseVersions = "1.0.0",
|
ReleaseVersions = "1.0.0",
|
||||||
|
|
Loading…
Reference in New Issue
Block a user