improve support for module content editors

This commit is contained in:
Shaun Walker 2022-08-16 17:25:46 -04:00
parent 3659422165
commit c7edc28bd9
10 changed files with 125 additions and 107 deletions

View File

@ -19,7 +19,7 @@
@code { @code {
private string _content = string.Empty; private string _content = string.Empty;
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin; public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
public override string Title => "Export Content"; public override string Title => "Export Content";
@ -27,7 +27,7 @@
{ {
try try
{ {
_content = await ModuleService.ExportModuleAsync(ModuleState.ModuleId); _content = await ModuleService.ExportModuleAsync(ModuleState.ModuleId, PageState.Page.PageId);
AddModuleMessage(Localizer["Success.Content.Export"], MessageType.Success); AddModuleMessage(Localizer["Success.Content.Export"], MessageType.Success);
} }
catch (Exception ex) catch (Exception ex)

View File

@ -25,7 +25,7 @@
private ElementReference form; private ElementReference form;
private bool validated = false; private bool validated = false;
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin; public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
public override string Title => "Import Content"; public override string Title => "Import Content";
private async Task ImportModule() private async Task ImportModule()
@ -38,7 +38,7 @@
{ {
try try
{ {
bool success = await ModuleService.ImportModuleAsync(ModuleState.ModuleId, _content); bool success = await ModuleService.ImportModuleAsync(ModuleState.ModuleId, PageState.Page.PageId, _content);
if (success) if (success)
{ {
AddModuleMessage(Localizer["Success.Content.Import"], MessageType.Success); AddModuleMessage(Localizer["Success.Content.Import"], MessageType.Success);

View File

@ -153,6 +153,22 @@ namespace Oqtane.Modules
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 string AddUrlParameters(params string[] parameters)
{
return AddUrlParameters(PageState.Page.Path, parameters);
}
public string AddUrlParameters(string path, params string[] parameters)
{
var url = path + "/" + Constants.UrlParametersDelimiter;
for (var i = 0; i < parameters.Length; i++)
{
url += "/" + parameters[i];
}
return url;
}
// parameters template is in the form of a standard route template ie. "{id}/{name}"
public virtual Dictionary<string, string> GetUrlParameters(string parametersTemplate = "") public virtual Dictionary<string, string> GetUrlParameters(string parametersTemplate = "")
{ {
var urlParameters = new Dictionary<string, string>(); var urlParameters = new Dictionary<string, string>();

View File

@ -50,13 +50,13 @@ namespace Oqtane.Services
/// <param name="moduleId"></param> /// <param name="moduleId"></param>
/// <param name="content">module in JSON format</param> /// <param name="content">module in JSON format</param>
/// <returns></returns> /// <returns></returns>
Task<bool> ImportModuleAsync(int moduleId, string content); Task<bool> ImportModuleAsync(int moduleId, int pageId, string content);
/// <summary> /// <summary>
/// Exports a given module /// Exports a given module
/// </summary> /// </summary>
/// <param name="moduleId"></param> /// <param name="moduleId"></param>
/// <returns>module in JSON</returns> /// <returns>module in JSON</returns>
Task<string> ExportModuleAsync(int moduleId); Task<string> ExportModuleAsync(int moduleId, int pageId);
} }
} }

View File

@ -5,6 +5,7 @@ using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
using Oqtane.Documentation; using Oqtane.Documentation;
using Oqtane.Shared; using Oqtane.Shared;
using Oqtane.Modules.Controls;
namespace Oqtane.Services namespace Oqtane.Services
{ {
@ -44,14 +45,14 @@ namespace Oqtane.Services
await DeleteAsync($"{Apiurl}/{moduleId.ToString()}"); await DeleteAsync($"{Apiurl}/{moduleId.ToString()}");
} }
public async Task<bool> ImportModuleAsync(int moduleId, string content) public async Task<bool> ImportModuleAsync(int moduleId, int pageId, string content)
{ {
return await PostJsonAsync<string,bool>($"{Apiurl}/import?moduleid={moduleId}", content); return await PostJsonAsync<string,bool>($"{Apiurl}/import?moduleid={moduleId}&pageid={pageId}", content);
} }
public async Task<string> ExportModuleAsync(int moduleId) public async Task<string> ExportModuleAsync(int moduleId, int pageId)
{ {
return await GetStringAsync($"{Apiurl}/export?moduleid={moduleId}"); return await GetStringAsync($"{Apiurl}/export?moduleid={moduleId}&pageid={pageId}");
} }
} }
} }

View File

@ -2,44 +2,44 @@
@inherits ModuleActionsBase @inherits ModuleActionsBase
@attribute [OqtaneIgnore] @attribute [OqtaneIgnore]
@if (PageState.EditMode && UserSecurity.IsAuthorized(PageState.User,PermissionNames.Edit, ModuleState.Permissions) && PageState.Action == Constants.DefaultAction) @if (PageState.EditMode && UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.Permissions) && PageState.Action == Constants.DefaultAction)
{ {
<div class="app-moduleactions py-2 px-3"> <div class="app-moduleactions py-2 px-3">
<a class="nav-link dropdown-toggle" data-bs-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"></a> <a class="nav-link dropdown-toggle" data-bs-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"></a>
<ul class="dropdown-menu" x-placement="bottom-start" style="position: absolute; will-change: transform; top: 0px; left: 0px; transform: translate3d(0px, 37px, 0px);"> <ul class="dropdown-menu" x-placement="bottom-start" style="position: absolute; will-change: transform; top: 0px; left: 0px; transform: translate3d(0px, 37px, 0px);">
@foreach (var action in Actions.Where(item => !item.Name.Contains("Pane"))) @foreach (var action in Actions.Where(item => !item.Name.Contains("Pane")))
{ {
if (string.IsNullOrEmpty(action.Name)) if (string.IsNullOrEmpty(action.Name))
{ {
<li class="dropdown-divider"></li> <li class="dropdown-divider"></li>
} }
else else
{ {
<li> <li>
<a class="dropdown-item" @onclick="(async () => await ModuleAction(action))"> <a class="dropdown-item" @onclick="(async () => await ModuleAction(action))">
<span class="@action.Icon" aria-hidden="true"></span>&nbsp;@action.Name <span class="@action.Icon" aria-hidden="true"></span>&nbsp;@action.Name
</a> </a>
</li> </li>
} }
} }
@if (Actions.Where(item => item.Name.Contains("Pane")).Any()) @if (Actions.Where(item => item.Name.Contains("Pane")).Any())
{ {
<li class="dropdown-submenu"> <li class="dropdown-submenu">
<a class="dropdown-item" onclick="return subMenu(this)"> <a class="dropdown-item" onclick="return subMenu(this)">
<span class="@Icons.AccountLogin" aria-hidden="true"></span>&nbsp;Move To &gt; <span class="@Icons.AccountLogin" aria-hidden="true"></span>&nbsp;Move To &gt;
</a> </a>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
@foreach (var action in Actions.Where(item => item.Name.Contains("Pane"))) @foreach (var action in Actions.Where(item => item.Name.Contains("Pane")))
{ {
<li> <li>
<a class="dropdown-item" @onclick="(async () => await ModuleAction(action))"> <a class="dropdown-item" @onclick="(async () => await ModuleAction(action))">
<span class="@action.Icon" aria-hidden="true"></span>&nbsp;@action.Name <span class="@action.Icon" aria-hidden="true"></span>&nbsp;@action.Name
</a> </a>
</li> </li>
} }
</ul> </ul>
</li> </li>
} }
</ul> </ul>
</div> </div>
} }

View File

@ -29,54 +29,55 @@ namespace Oqtane.Themes.Controls
protected virtual List<ActionViewModel> GetActions() protected virtual List<ActionViewModel> GetActions()
{ {
var actionList = new List<ActionViewModel>(); var actionList = new List<ActionViewModel>();
if (PageState.EditMode && UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, ModuleState.Permissions))
if (PageState.EditMode && UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.Permissions))
{ {
actionList.Add(new ActionViewModel {Icon = Icons.Cog, Name = "Manage Settings", Action = async (u, m) => await Settings(u, m)}); actionList.Add(new ActionViewModel { Icon = Icons.Cog, Name = "Manage Settings", Action = async (u, m) => await Settings(u, m) });
if (UserSecurity.ContainsRole(ModuleState.Permissions, PermissionNames.View, RoleNames.Everyone)) if (UserSecurity.ContainsRole(ModuleState.Permissions, PermissionNames.View, RoleNames.Everyone))
{ {
actionList.Add(new ActionViewModel {Icon=Icons.CircleX, Name = "Unpublish Module", Action = async (s, m) => await Unpublish(s, m) }); actionList.Add(new ActionViewModel { Icon = Icons.CircleX, Name = "Unpublish Module", Action = async (s, m) => await Unpublish(s, m) });
} }
else else
{ {
actionList.Add(new ActionViewModel {Icon=Icons.CircleCheck, Name = "Publish Module", Action = async (s, m) => await Publish(s, m) }); actionList.Add(new ActionViewModel { Icon = Icons.CircleCheck, Name = "Publish Module", Action = async (s, m) => await Publish(s, m) });
} }
actionList.Add(new ActionViewModel {Icon=Icons.Trash, Name = "Delete Module", Action = async (u, m) => await DeleteModule(u, m) }); actionList.Add(new ActionViewModel { Icon = Icons.Trash, Name = "Delete Module", Action = async (u, m) => await DeleteModule(u, m) });
if (ModuleState.ModuleDefinition != null && ModuleState.ModuleDefinition.ServerManagerType != "") if (ModuleState.ModuleDefinition != null && ModuleState.ModuleDefinition.ServerManagerType != "")
{ {
actionList.Add(new ActionViewModel { Name = "" }); actionList.Add(new ActionViewModel { Name = "" });
actionList.Add(new ActionViewModel {Icon=Icons.CloudUpload, Name = "Import Content", Action = async (u, m) => await EditUrlAsync(u, m.ModuleId, "Import")}); actionList.Add(new ActionViewModel { Icon = Icons.CloudUpload, Name = "Import Content", Action = async (u, m) => await EditUrlAsync(u, m.ModuleId, "Import") });
actionList.Add(new ActionViewModel {Icon = Icons.CloudDownload, Name = "Export Content", Action = async (u, m) => await EditUrlAsync(u, m.ModuleId, "Export")}); actionList.Add(new ActionViewModel { Icon = Icons.CloudDownload, Name = "Export Content", Action = async (u, m) => await EditUrlAsync(u, m.ModuleId, "Export") });
} }
actionList.Add(new ActionViewModel {Name = ""}); actionList.Add(new ActionViewModel { Name = "" });
if (ModuleState.PaneModuleIndex > 0) if (ModuleState.PaneModuleIndex > 0)
{ {
actionList.Add(new ActionViewModel {Icon = Icons.DataTransferUpload ,Name = "Move To Top", Action = async (s, m) => await MoveTop(s, m)}); actionList.Add(new ActionViewModel { Icon = Icons.DataTransferUpload, Name = "Move To Top", Action = async (s, m) => await MoveTop(s, m) });
} }
if (ModuleState.PaneModuleIndex > 0) if (ModuleState.PaneModuleIndex > 0)
{ {
actionList.Add(new ActionViewModel {Icon = Icons.ArrowThickTop, Name = "Move Up", Action = async (s, m) => await MoveUp(s, m)}); actionList.Add(new ActionViewModel { Icon = Icons.ArrowThickTop, Name = "Move Up", Action = async (s, m) => await MoveUp(s, m) });
} }
if (ModuleState.PaneModuleIndex < (ModuleState.PaneModuleCount - 1)) if (ModuleState.PaneModuleIndex < (ModuleState.PaneModuleCount - 1))
{ {
actionList.Add(new ActionViewModel {Icon = Icons.ArrowThickBottom, Name = "Move Down", Action = async (s, m) => await MoveDown(s, m)}); actionList.Add(new ActionViewModel { Icon = Icons.ArrowThickBottom, Name = "Move Down", Action = async (s, m) => await MoveDown(s, m) });
} }
if (ModuleState.PaneModuleIndex < (ModuleState.PaneModuleCount - 1)) if (ModuleState.PaneModuleIndex < (ModuleState.PaneModuleCount - 1))
{ {
actionList.Add(new ActionViewModel {Icon = Icons.DataTransferDownload, Name = "Move To Bottom", Action = async (s, m) => await MoveBottom(s, m)}); actionList.Add(new ActionViewModel { Icon = Icons.DataTransferDownload, Name = "Move To Bottom", Action = async (s, m) => await MoveBottom(s, m) });
} }
foreach (string pane in PageState.Page.Panes) foreach (string pane in PageState.Page.Panes)
{ {
if (pane != ModuleState.Pane) if (pane != ModuleState.Pane)
{ {
actionList.Add(new ActionViewModel {Icon = Icons.AccountLogin, Name = pane + " Pane", Action = async (s, m) => await MoveToPane(s, pane, m)}); actionList.Add(new ActionViewModel { Icon = Icons.AccountLogin, Name = pane + " Pane", Action = async (s, m) => await MoveToPane(s, pane, m) });
} }
} }
} }

View File

@ -17,46 +17,46 @@ else
} }
@code { @code {
private bool _useadminborder = false; private bool _useadminborder = false;
private string _panetitle = ""; private string _panetitle = "";
[CascadingParameter] [CascadingParameter]
protected PageState PageState { get; set; } protected PageState PageState { get; set; }
[Parameter] [Parameter]
public string Name { get; set; } public string Name { get; set; }
RenderFragment DynamicComponent { get; set; } RenderFragment DynamicComponent { get; set; }
protected override void OnParametersSet() protected override void OnParametersSet()
{ {
if (PageState.EditMode && UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.Permissions) && PageState.Action == Constants.DefaultAction) if (PageState.EditMode && UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.Permissions) && PageState.Action == Constants.DefaultAction)
{ {
_useadminborder = true; _useadminborder = true;
_panetitle = "<div class=\"app-pane-admin-title\">" + Name + " Pane</div>"; _panetitle = "<div class=\"app-pane-admin-title\">" + Name + " Pane</div>";
} }
else else
{ {
_useadminborder = false; _useadminborder = false;
_panetitle = ""; _panetitle = "";
} }
DynamicComponent = builder => DynamicComponent = builder =>
{ {
if (PageState.ModuleId != -1 && PageState.Action != Constants.DefaultAction) if (PageState.ModuleId != -1 && PageState.Action != Constants.DefaultAction)
{ {
if (Name.ToLower() == PaneNames.Admin.ToLower()) if (Name.ToLower() == PaneNames.Admin.ToLower())
{ {
Module module = PageState.Modules.FirstOrDefault(item => item.ModuleId == PageState.ModuleId); Module module = PageState.Modules.FirstOrDefault(item => item.ModuleId == PageState.ModuleId);
if (module != null) if (module != null)
{ {
var moduleType = Type.GetType(module.ModuleType); var moduleType = Type.GetType(module.ModuleType);
if (moduleType != null) if (moduleType != null)
{ {
bool authorized = false; bool authorized = false;
if (Constants.DefaultModuleActions.Contains(PageState.Action)) if (Constants.DefaultModuleActions.Contains(PageState.Action))
{ {
authorized = UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.Permissions); authorized = UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.Permissions);
} }
else else
{ {

View File

@ -205,14 +205,14 @@ namespace Oqtane.Controllers
} }
} }
// GET api/<controller>/export?moduleid=x // GET api/<controller>/export?moduleid=x&pageid=y
[HttpGet("export")] [HttpGet("export")]
[Authorize(Roles = RoleNames.Registered)] [Authorize(Roles = RoleNames.Registered)]
public string Export(int moduleid) public string Export(int moduleid, int pageid)
{ {
string content = ""; string content = "";
var module = _modules.GetModule(moduleid); var module = _modules.GetModule(moduleid);
if (module != null && module.SiteId == _alias.SiteId && _userPermissions.IsAuthorized(User, EntityNames.Module, module.ModuleId, PermissionNames.Edit)) if (module != null && module.SiteId == _alias.SiteId && _userPermissions.IsAuthorized(User, EntityNames.Page, pageid, PermissionNames.Edit))
{ {
content = _modules.ExportModule(moduleid); content = _modules.ExportModule(moduleid);
if (!string.IsNullOrEmpty(content)) if (!string.IsNullOrEmpty(content))
@ -232,14 +232,14 @@ namespace Oqtane.Controllers
return content; return content;
} }
// POST api/<controller>/import?moduleid=x // POST api/<controller>/import?moduleid=x&pageid=y
[HttpPost("import")] [HttpPost("import")]
[Authorize(Roles = RoleNames.Registered)] [Authorize(Roles = RoleNames.Registered)]
public bool Import(int moduleid, [FromBody] string content) public bool Import(int moduleid, int pageid, [FromBody] string content)
{ {
bool success = false; bool success = false;
var module = _modules.GetModule(moduleid); var module = _modules.GetModule(moduleid);
if (ModelState.IsValid && module != null && module.SiteId == _alias.SiteId && _userPermissions.IsAuthorized(User, EntityNames.Module, module.ModuleId, PermissionNames.Edit)) if (ModelState.IsValid && module != null && module.SiteId == _alias.SiteId && _userPermissions.IsAuthorized(User, EntityNames.Page, pageid, PermissionNames.Edit))
{ {
success = _modules.ImportModule(moduleid, content); success = _modules.ImportModule(moduleid, content);
if (success) if (success)

View File

@ -54,7 +54,7 @@ namespace Oqtane.Controllers
public PageModule Get(int pageid, int moduleid) public PageModule Get(int pageid, int moduleid)
{ {
PageModule pagemodule = _pageModules.GetPageModule(pageid, moduleid); PageModule pagemodule = _pageModules.GetPageModule(pageid, moduleid);
if (pagemodule != null && pagemodule.Module.SiteId == _alias.SiteId && _userPermissions.IsAuthorized(User,PermissionNames.View, pagemodule.Module.Permissions)) if (pagemodule != null && pagemodule.Module.SiteId == _alias.SiteId && _userPermissions.IsAuthorized(User, PermissionNames.View, pagemodule.Module.Permissions))
{ {
return pagemodule; return pagemodule;
} }
@ -93,7 +93,7 @@ namespace Oqtane.Controllers
public PageModule Put(int id, [FromBody] PageModule pageModule) public PageModule Put(int id, [FromBody] PageModule pageModule)
{ {
var page = _pages.GetPage(pageModule.PageId); var page = _pages.GetPage(pageModule.PageId);
if (ModelState.IsValid && page != null && page.SiteId == _alias.SiteId && _pageModules.GetPageModule(pageModule.PageModuleId, false) != null && _userPermissions.IsAuthorized(User, EntityNames.Module, pageModule.ModuleId, PermissionNames.Edit)) if (ModelState.IsValid && page != null && page.SiteId == _alias.SiteId && _pageModules.GetPageModule(pageModule.PageModuleId, false) != null && _userPermissions.IsAuthorized(User, EntityNames.Page, pageModule.PageId, PermissionNames.Edit))
{ {
pageModule = _pageModules.UpdatePageModule(pageModule); pageModule = _pageModules.UpdatePageModule(pageModule);
_syncManager.AddSyncEvent(_alias.TenantId, EntityNames.Site, _alias.SiteId); _syncManager.AddSyncEvent(_alias.TenantId, EntityNames.Site, _alias.SiteId);