Merge pull request #9 from oqtane/master

Sync upstream master
This commit is contained in:
Jim Spillane 2020-05-15 12:56:45 -04:00 committed by GitHub
commit f5ce00ae7d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 333 additions and 283 deletions

View File

@ -12,7 +12,7 @@
<Label For="upload" HelpText="Upload the file you want">Upload: </Label> <Label For="upload" HelpText="Upload the file you want">Upload: </Label>
</td> </td>
<td> <td>
<FileManager UploadMultiple="true" ShowFiles="false" FolderId="@_folderId.ToString()" /> <FileManager UploadMultiple="true" ShowFiles="false" FolderId="@_folderId" />
</td> </td>
</tr> </tr>
</table> </table>

View File

@ -25,7 +25,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<Label for="name" HelpText="Enter the file name">Name: </Label> <Label for="name" HelpText="Enter the folder name">Name: </Label>
</td> </td>
<td> <td>
<input id="name" class="form-control" @bind="@_name" /> <input id="name" class="form-control" @bind="@_name" />
@ -112,57 +112,63 @@
private async Task SaveFolder() private async Task SaveFolder()
{ {
if (_name == string.Empty || _parentId == -1)
{
AddModuleMessage("Folders Must Have A Parent And A Name", MessageType.Warning);
return;
}
if (!_name.IsPathOrFileValid())
{
AddModuleMessage("Folder Name Not Valid.", MessageType.Warning);
return;
}
try try
{ {
if (_name != string.Empty && _parentId != -1) Folder folder;
if (_folderId != -1)
{ {
Folder folder; folder = await FolderService.GetFolderAsync(_folderId);
if (_folderId != -1)
{
folder = await FolderService.GetFolderAsync(_folderId);
}
else
{
folder = new Folder();
}
folder.SiteId = PageState.Site.SiteId;
if (_parentId == -1)
{
folder.ParentId = null;
}
else
{
folder.ParentId = _parentId;
}
folder.Name = _name;
folder.IsSystem = _isSystem;
folder.Permissions = _permissionGrid.GetPermissions();
if (_folderId != -1)
{
folder = await FolderService.UpdateFolderAsync(folder);
}
else
{
folder = await FolderService.AddFolderAsync(folder);
}
if (folder != null)
{
await FolderService.UpdateFolderOrderAsync(folder.SiteId, folder.FolderId, folder.ParentId);
await logger.LogInformation("Folder Saved {Folder}", folder);
NavigationManager.NavigateTo(NavigateUrl());
}
else
{
AddModuleMessage("An Error Was Encountered Saving The Folder", MessageType.Error);
}
} }
else else
{ {
AddModuleMessage("Folders Must Have A Parent And A Name", MessageType.Warning); folder = new Folder();
}
folder.SiteId = PageState.Site.SiteId;
if (_parentId == -1)
{
folder.ParentId = null;
}
else
{
folder.ParentId = _parentId;
}
folder.Name = _name;
folder.IsSystem = _isSystem;
folder.Permissions = _permissionGrid.GetPermissions();
if (_folderId != -1)
{
folder = await FolderService.UpdateFolderAsync(folder);
}
else
{
folder = await FolderService.AddFolderAsync(folder);
}
if (folder != null)
{
await FolderService.UpdateFolderOrderAsync(folder.SiteId, folder.FolderId, folder.ParentId);
await logger.LogInformation("Folder Saved {Folder}", folder);
NavigationManager.NavigateTo(NavigateUrl());
}
else
{
AddModuleMessage("An Error Was Encountered Saving The Folder", MessageType.Error);
} }
} }
catch (Exception ex) catch (Exception ex)

View File

@ -61,8 +61,8 @@ else
- Repository\I[Module]Repository.cs - interface for defining repository methods<br /> - Repository\I[Module]Repository.cs - interface for defining repository methods<br />
- Repository\[Module]Respository.cs - implements repository interface methods for data access using EF Core<br /> - Repository\[Module]Respository.cs - implements repository interface methods for data access using EF Core<br />
- Repository\[Module]Context.cs - provides a DB Context for data access<br /> - Repository\[Module]Context.cs - provides a DB Context for data access<br />
- Scripts\[Owner].[Module].1.0.0.sql - database schema definition script<br /><br /> - Scripts\[Owner].[Module]s.1.0.0.sql - database schema definition script<br />
- Scripts\[Owner].[Module].Uninstall.sql - database uninstall script<br /><br /> - Scripts\[Owner].[Module]s.Uninstall.sql - database uninstall script<br /><br />
[RootPath]Shared\<br /> [RootPath]Shared\<br />
- [Owner].[Module]s.csproj - shared project<br /> - [Owner].[Module]s.csproj - shared project<br />
- Models\[Module].cs - model definition<br /><br /> - Models\[Module].cs - model definition<br /><br />

View File

@ -23,12 +23,12 @@ namespace [Owner].[Module]s.Manager
public bool Install(Tenant tenant, string version) public bool Install(Tenant tenant, string version)
{ {
return _sql.ExecuteScript(tenant, GetType().Assembly, "[Owner].[Module]." + version + ".sql"); return _sql.ExecuteScript(tenant, GetType().Assembly, "[Owner].[Module]s." + version + ".sql");
} }
public bool Uninstall(Tenant tenant) public bool Uninstall(Tenant tenant)
{ {
return _sql.ExecuteScript(tenant, GetType().Assembly, "[Owner].[Module].Uninstall.sql"); return _sql.ExecuteScript(tenant, GetType().Assembly, "[Owner].[Module]s.Uninstall.sql");
} }
public string ExportModule(Module module) public string ExportModule(Module module)

View File

@ -53,8 +53,8 @@ else
- Repository\I[Module]Repository.cs - interface for defining repository methods<br /> - Repository\I[Module]Repository.cs - interface for defining repository methods<br />
- Repository\[Module]Respository.cs - implements repository interface methods for data access using EF Core<br /> - Repository\[Module]Respository.cs - implements repository interface methods for data access using EF Core<br />
- Repository\[Module]Context.cs - provides a DB Context for data access<br /> - Repository\[Module]Context.cs - provides a DB Context for data access<br />
- Scripts\[Owner].[Module].1.0.0.sql - database schema definition script<br /><br /> - Scripts\[Owner].[Module]s.1.0.0.sql - database schema definition script<br />
- Scripts\[Owner].[Module].Uninstall.sql - database uninstall script<br /><br /> - Scripts\[Owner].[Module]s.Uninstall.sql - database uninstall script<br /><br />
[RootPath]Oqtane.Shared\Modules\[Module]\<br /> [RootPath]Oqtane.Shared\Modules\[Module]\<br />
- Models\[Module].cs - model definition<br /><br /> - Models\[Module].cs - model definition<br /><br />

View File

@ -23,12 +23,12 @@ namespace [Owner].[Module]s.Manager
public bool Install(Tenant tenant, string version) public bool Install(Tenant tenant, string version)
{ {
return _sql.ExecuteScript(tenant, GetType().Assembly, "[Owner].[Module]." + version + ".sql"); return _sql.ExecuteScript(tenant, GetType().Assembly, "[Owner].[Module]s." + version + ".sql");
} }
public bool Uninstall(Tenant tenant) public bool Uninstall(Tenant tenant)
{ {
return _sql.ExecuteScript(tenant, GetType().Assembly, "[Owner].[Module].Uninstall.sql"); return _sql.ExecuteScript(tenant, GetType().Assembly, "[Owner].[Module]s.Uninstall.sql");
} }
public string ExportModule(Module module) public string ExportModule(Module module)

View File

@ -35,7 +35,7 @@
<Label HelpText="Upload one or more module packages. Once they are uploaded click Install to complete the installation.">Module: </Label> <Label HelpText="Upload one or more module packages. Once they are uploaded click Install to complete the installation.">Module: </Label>
</td> </td>
<td> <td>
<FileManager Filter="nupkg" ShowFiles="false" Folder="Modules" UploadMultiple="True" /> <FileManager Filter="nupkg" ShowFiles="false" Folder="Modules" UploadMultiple="true" />
</td> </td>
</tr> </tr>
</table> </table>

View File

@ -24,7 +24,7 @@
</td> </td>
<td> <td>
<select id="container" class="form-control" @bind="@_containerType"> <select id="container" class="form-control" @bind="@_containerType">
<option value="">&lt;Select Container&gt;</option> <option value="-">&lt;Inherit From Page Or Site&gt;</option>
@foreach (KeyValuePair<string, string> container in _containers) @foreach (KeyValuePair<string, string> container in _containers)
{ {
<option value="@container.Key">@container.Value</option> <option value="@container.Key">@container.Value</option>
@ -107,6 +107,14 @@
_title = ModuleState.Title; _title = ModuleState.Title;
_containers = ThemeService.GetContainerTypes(await ThemeService.GetThemesAsync()); _containers = ThemeService.GetContainerTypes(await ThemeService.GetThemesAsync());
_containerType = ModuleState.ContainerType; _containerType = ModuleState.ContainerType;
if (!string.IsNullOrEmpty(PageState.Page.DefaultContainerType) && _containerType == PageState.Page.DefaultContainerType)
{
_containerType = "-";
}
if (_containerType == PageState.Site.DefaultContainerType)
{
_containerType = "-";
}
_allPages = ModuleState.AllPages.ToString(); _allPages = ModuleState.AllPages.ToString();
_permissions = ModuleState.Permissions; _permissions = ModuleState.Permissions;
_permissionNames = ModuleState.ModuleDefinition.PermissionNames; _permissionNames = ModuleState.ModuleDefinition.PermissionNames;
@ -136,7 +144,15 @@
var pagemodule = await PageModuleService.GetPageModuleAsync(ModuleState.PageModuleId); var pagemodule = await PageModuleService.GetPageModuleAsync(ModuleState.PageModuleId);
pagemodule.PageId = int.Parse(_pageId); pagemodule.PageId = int.Parse(_pageId);
pagemodule.Title = _title; pagemodule.Title = _title;
pagemodule.ContainerType = _containerType; pagemodule.ContainerType = (_containerType != "-") ? _containerType : string.Empty;
if (!string.IsNullOrEmpty(pagemodule.ContainerType) && pagemodule.ContainerType == PageState.Page.DefaultContainerType)
{
pagemodule.ContainerType = string.Empty;
}
if (!string.IsNullOrEmpty(pagemodule.ContainerType) && pagemodule.ContainerType == PageState.Site.DefaultContainerType)
{
pagemodule.ContainerType = string.Empty;
}
await PageModuleService.UpdatePageModuleAsync(pagemodule); await PageModuleService.UpdatePageModuleAsync(pagemodule);
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane); await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);

View File

@ -101,7 +101,7 @@
</td> </td>
<td> <td>
<select id="Theme" class="form-control" @onchange="(e => ThemeChanged(e))"> <select id="Theme" class="form-control" @onchange="(e => ThemeChanged(e))">
<option value="-">&lt;Select Theme&gt;</option> <option value="-">&lt;Inherit From Site&gt;</option>
@foreach (KeyValuePair<string, string> item in _themes) @foreach (KeyValuePair<string, string> item in _themes)
{ {
if (item.Key == _themetype) if (item.Key == _themetype)
@ -122,7 +122,7 @@
</td> </td>
<td> <td>
<select id="Layout" class="form-control" @bind="@_layouttype"> <select id="Layout" class="form-control" @bind="@_layouttype">
<option value="-">&lt;Select Layout&gt;</option> <option value="-">&lt;Inherit From Site&gt;</option>
@foreach (KeyValuePair<string, string> panelayout in _panelayouts) @foreach (KeyValuePair<string, string> panelayout in _panelayouts)
{ {
if (panelayout.Key == _layouttype) if (panelayout.Key == _layouttype)
@ -137,6 +137,20 @@
</select> </select>
</td> </td>
</tr> </tr>
<tr>
<td>
<Label For="defaultContainer" HelpText="Select the default container for the page">Default Container: </Label>
</td>
<td>
<select id="defaultContainer" class="form-control" @bind="@_containertype">
<option value="-">&lt;Inherit From Site&gt;</option>
@foreach (KeyValuePair<string, string> container in _containers)
{
<option value="@container.Key">@container.Value</option>
}
</select>
</td>
</tr>
<tr> <tr>
<td> <td>
<Label For="Icon" HelpText="Optionally provide an icon for this page which will be displayed in the site navigation">Icon: </Label> <Label For="Icon" HelpText="Optionally provide an icon for this page which will be displayed in the site navigation">Icon: </Label>
@ -187,6 +201,7 @@
@code { @code {
private Dictionary<string, string> _themes; private Dictionary<string, string> _themes;
private Dictionary<string, string> _panelayouts; private Dictionary<string, string> _panelayouts;
private Dictionary<string, string> _containers = new Dictionary<string, string>();
private List<Theme> _themeList; private List<Theme> _themeList;
private List<Page> _pageList; private List<Page> _pageList;
private string _name; private string _name;
@ -202,6 +217,7 @@
private string _mode = "view"; private string _mode = "view";
private string _themetype = "-"; private string _themetype = "-";
private string _layouttype = "-"; private string _layouttype = "-";
private string _containertype = "-";
private string _icon = string.Empty; private string _icon = string.Empty;
private string _permissions = string.Empty; private string _permissions = string.Empty;
private PermissionGrid _permissionGrid; private PermissionGrid _permissionGrid;
@ -216,11 +232,9 @@
_pageList = PageState.Pages; _pageList = PageState.Pages;
_children = PageState.Pages.Where(item => item.ParentId == null).ToList(); _children = PageState.Pages.Where(item => item.ParentId == null).ToList();
_themetype = PageState.Site.DefaultThemeType;
_layouttype = PageState.Site.DefaultLayoutType;
_themes = ThemeService.GetThemeTypes(_themeList); _themes = ThemeService.GetThemeTypes(_themeList);
_panelayouts = ThemeService.GetPaneLayoutTypes(_themeList, _themetype); _panelayouts = ThemeService.GetPaneLayoutTypes(_themeList, _themetype);
_containers = ThemeService.GetContainerTypes(_themeList);
_permissions = string.Empty; _permissions = string.Empty;
} }
@ -351,16 +365,20 @@
page.Url = _url; page.Url = _url;
page.EditMode = (_mode == "edit" ? true : false); page.EditMode = (_mode == "edit" ? true : false);
page.ThemeType = (_themetype != "-") ? _themetype : string.Empty; page.ThemeType = (_themetype != "-") ? _themetype : string.Empty;
page.LayoutType = (_layouttype != "-") ? _layouttype : string.Empty; if (!string.IsNullOrEmpty(page.ThemeType) && page.ThemeType == PageState.Site.DefaultThemeType)
if (page.ThemeType == PageState.Site.DefaultThemeType)
{ {
page.ThemeType = string.Empty; page.ThemeType = string.Empty;
} }
page.LayoutType = (_layouttype != "-") ? _layouttype : string.Empty;
if (page.LayoutType == PageState.Site.DefaultLayoutType) if (!string.IsNullOrEmpty(page.LayoutType) && page.LayoutType == PageState.Site.DefaultLayoutType)
{ {
page.LayoutType = string.Empty; page.LayoutType = string.Empty;
} }
page.DefaultContainerType = (_containertype != "-") ? _containertype : string.Empty;
if (!string.IsNullOrEmpty(page.DefaultContainerType) && page.DefaultContainerType == PageState.Site.DefaultContainerType)
{
page.DefaultContainerType = string.Empty;
}
page.Icon = (_icon == null ? string.Empty : _icon); page.Icon = (_icon == null ? string.Empty : _icon);
page.Permissions = _permissionGrid.GetPermissions(); page.Permissions = _permissionGrid.GetPermissions();
page.IsPersonalizable = (_ispersonalizable == null ? false : Boolean.Parse(_ispersonalizable)); page.IsPersonalizable = (_ispersonalizable == null ? false : Boolean.Parse(_ispersonalizable));

View File

@ -112,7 +112,7 @@
</td> </td>
<td> <td>
<select id="Theme" class="form-control" @onchange="(e => ThemeChanged(e))"> <select id="Theme" class="form-control" @onchange="(e => ThemeChanged(e))">
<option value="-">&lt;Select Theme&gt;</option> <option value="-">&lt;Inherit From Site&gt;</option>
@foreach (KeyValuePair<string, string> item in _themes) @foreach (KeyValuePair<string, string> item in _themes)
{ {
if (item.Key == _themetype) if (item.Key == _themetype)
@ -133,7 +133,7 @@
</td> </td>
<td> <td>
<select id="Layout" class="form-control" @bind="@_layouttype"> <select id="Layout" class="form-control" @bind="@_layouttype">
<option value="-">&lt;Select Layout&gt;</option> <option value="-">&lt;Inherit From Site&gt;</option>
@foreach (KeyValuePair<string, string> panelayout in _panelayouts) @foreach (KeyValuePair<string, string> panelayout in _panelayouts)
{ {
if (panelayout.Key == _layouttype) if (panelayout.Key == _layouttype)
@ -148,6 +148,20 @@
</select> </select>
</td> </td>
</tr> </tr>
<tr>
<td>
<Label For="defaultContainer" HelpText="Select the default container for the page">Default Container: </Label>
</td>
<td>
<select id="defaultContainer" class="form-control" @bind="@_containertype">
<option value="-">&lt;Inherit From Site&gt;</option>
@foreach (KeyValuePair<string, string> container in _containers)
{
<option value="@container.Key">@container.Value</option>
}
</select>
</td>
</tr>
<tr> <tr>
<td> <td>
<Label For="Icon" HelpText="Optionally provide an icon for this page which will be displayed in the site navigation">Icon: </Label> <Label For="Icon" HelpText="Optionally provide an icon for this page which will be displayed in the site navigation">Icon: </Label>
@ -200,6 +214,7 @@
@code { @code {
private Dictionary<string, string> _themes; private Dictionary<string, string> _themes;
private Dictionary<string, string> _panelayouts; private Dictionary<string, string> _panelayouts;
private Dictionary<string, string> _containers = new Dictionary<string, string>();
private List<Theme> _themeList; private List<Theme> _themeList;
private List<Page> _pageList; private List<Page> _pageList;
private int _pageId; private int _pageId;
@ -217,6 +232,7 @@
private string _mode; private string _mode;
private string _themetype = "-"; private string _themetype = "-";
private string _layouttype = "-"; private string _layouttype = "-";
private string _containertype = "-";
private string _icon; private string _icon;
private string _permissions; private string _permissions;
private string _createdby; private string _createdby;
@ -241,6 +257,7 @@
_children = PageState.Pages.Where(item => item.ParentId == null).ToList(); _children = PageState.Pages.Where(item => item.ParentId == null).ToList();
_themes = ThemeService.GetThemeTypes(_themeList); _themes = ThemeService.GetThemeTypes(_themeList);
_containers = ThemeService.GetContainerTypes(_themeList);
_pageId = Int32.Parse(PageState.QueryString["id"]); _pageId = Int32.Parse(PageState.QueryString["id"]);
var page = PageState.Pages.FirstOrDefault(item => item.PageId == _pageId); var page = PageState.Pages.FirstOrDefault(item => item.PageId == _pageId);
@ -270,16 +287,21 @@
_ispersonalizable = page.IsPersonalizable.ToString(); _ispersonalizable = page.IsPersonalizable.ToString();
_mode = (page.EditMode) ? "edit" : "view"; _mode = (page.EditMode) ? "edit" : "view";
_themetype = page.ThemeType; _themetype = page.ThemeType;
_panelayouts = ThemeService.GetPaneLayoutTypes(_themeList, _themetype);
_layouttype = page.LayoutType;
if (_themetype == PageState.Site.DefaultThemeType) if (_themetype == PageState.Site.DefaultThemeType)
{ {
_themetype = "-"; _themetype = "-";
} }
_panelayouts = ThemeService.GetPaneLayoutTypes(_themeList, _themetype);
_layouttype = page.LayoutType;
if (_layouttype == PageState.Site.DefaultLayoutType) if (_layouttype == PageState.Site.DefaultLayoutType)
{ {
_layouttype = "-"; _layouttype = "-";
} }
_containertype = page.DefaultContainerType;
if (string.IsNullOrEmpty(_containertype))
{
_containertype = "-";
}
_icon = page.Icon; _icon = page.Icon;
_permissions = page.Permissions; _permissions = page.Permissions;
_createdby = page.CreatedBy; _createdby = page.CreatedBy;
@ -426,15 +448,20 @@
page.Url = _url; page.Url = _url;
page.EditMode = (_mode == "edit"); page.EditMode = (_mode == "edit");
page.ThemeType = (_themetype != "-") ? _themetype : string.Empty; page.ThemeType = (_themetype != "-") ? _themetype : string.Empty;
page.LayoutType = (_layouttype != "-") ? _layouttype : string.Empty; if (!string.IsNullOrEmpty(page.ThemeType) && page.ThemeType == PageState.Site.DefaultThemeType)
if (page.ThemeType == PageState.Site.DefaultThemeType)
{ {
page.ThemeType = string.Empty; page.ThemeType = string.Empty;
} }
if (page.LayoutType == PageState.Site.DefaultLayoutType) page.LayoutType = (_layouttype != "-") ? _layouttype : string.Empty;
if (!string.IsNullOrEmpty(page.LayoutType) && page.LayoutType == PageState.Site.DefaultLayoutType)
{ {
page.LayoutType = string.Empty; page.LayoutType = string.Empty;
} }
page.DefaultContainerType = (_containertype != "-") ? _containertype : string.Empty;
if (!string.IsNullOrEmpty(page.DefaultContainerType) && page.DefaultContainerType == PageState.Site.DefaultContainerType)
{
page.DefaultContainerType = string.Empty;
}
page.Icon = _icon ?? string.Empty; page.Icon = _icon ?? string.Empty;
page.Permissions = _permissionGrid.GetPermissions(); page.Permissions = _permissionGrid.GetPermissions();
page.IsPersonalizable = (_ispersonalizable != null && Boolean.Parse(_ispersonalizable)); page.IsPersonalizable = (_ispersonalizable != null && Boolean.Parse(_ispersonalizable));

View File

@ -39,7 +39,7 @@
<Label For="logo" HelpText="Upload a logo for the site">Logo: </Label> <Label For="logo" HelpText="Upload a logo for the site">Logo: </Label>
</td> </td>
<td> <td>
<FileManager FileId="@_logofileid.ToString()" Filter="@Constants.ImageFiles" @ref="_logofilemanager" /> <FileManager FileId="@_logofileid" Filter="@Constants.ImageFiles" @ref="_logofilemanager" />
</td> </td>
</tr> </tr>
<tr> <tr>
@ -47,7 +47,7 @@
<Label For="favicon" HelpText="Select Your default icon">Favicon: </Label> <Label For="favicon" HelpText="Select Your default icon">Favicon: </Label>
</td> </td>
<td> <td>
<FileManager FileId="@_faviconfileid.ToString()" Filter="ico" @ref="_faviconfilemanager" /> <FileManager FileId="@_faviconfileid" Filter="ico" @ref="_faviconfilemanager" />
</td> </td>
</tr> </tr>
<tr> <tr>
@ -185,7 +185,7 @@
<Label For="appIcon" HelpText="Include an application icon for your PWA. It should be a PNG which is 192 X 192 pixels in dimension.">App Icon: </Label> <Label For="appIcon" HelpText="Include an application icon for your PWA. It should be a PNG which is 192 X 192 pixels in dimension.">App Icon: </Label>
</td> </td>
<td> <td>
<FileManager FileId="@_pwaappiconfileid.ToString()" Filter="png" @ref="_pwaappiconfilemanager" /> <FileManager FileId="@_pwaappiconfileid" Filter="png" @ref="_pwaappiconfilemanager" />
</td> </td>
</tr> </tr>
<tr> <tr>
@ -193,7 +193,7 @@
<Label For="splashIcon" HelpText="Include a splash icon for your PWA. It should be a PNG which is 512 X 512 pixels in dimension.">Splash Icon: </Label> <Label For="splashIcon" HelpText="Include a splash icon for your PWA. It should be a PNG which is 512 X 512 pixels in dimension.">Splash Icon: </Label>
</td> </td>
<td> <td>
<FileManager FileId="@_pwasplashiconfileid.ToString()" Filter="png" @ref="_pwasplashiconfilemanager" /> <FileManager FileId="@_pwasplashiconfileid" Filter="png" @ref="_pwasplashiconfilemanager" />
</td> </td>
</tr> </tr>
</table> </table>

View File

@ -8,7 +8,7 @@
<Label For="version" HelpText="Framework Version">Framework Version: </Label> <Label For="version" HelpText="Framework Version">Framework Version: </Label>
</td> </td>
<td> <td>
<input id="version" class="form-control" @bind="@_version" disabled /> <input id="version" class="form-control" @bind="@_version" readonly />
</td> </td>
</tr> </tr>
<tr> <tr>
@ -16,7 +16,7 @@
<Label For="runtime" HelpText="Blazor Runtime (Server or WebAssembly)">Blazor Runtime: </Label> <Label For="runtime" HelpText="Blazor Runtime (Server or WebAssembly)">Blazor Runtime: </Label>
</td> </td>
<td> <td>
<input id="runtime" class="form-control" @bind="@_runtime" disabled /> <input id="runtime" class="form-control" @bind="@_runtime" readonly />
</td> </td>
</tr> </tr>
<tr> <tr>
@ -24,7 +24,7 @@
<Label For="clrversion" HelpText="Common Language Runtime Version">CLR Version: </Label> <Label For="clrversion" HelpText="Common Language Runtime Version">CLR Version: </Label>
</td> </td>
<td> <td>
<input id="clrversion" class="form-control" @bind="@_clrversion" disabled /> <input id="clrversion" class="form-control" @bind="@_clrversion" readonly />
</td> </td>
</tr> </tr>
<tr> <tr>
@ -32,7 +32,7 @@
<Label For="osversion" HelpText="Operating System Version">OS Version: </Label> <Label For="osversion" HelpText="Operating System Version">OS Version: </Label>
</td> </td>
<td> <td>
<input id="osversion" class="form-control" @bind="@_osversion" disabled /> <input id="osversion" class="form-control" @bind="@_osversion" readonly />
</td> </td>
</tr> </tr>
<tr> <tr>
@ -40,7 +40,7 @@
<Label For="serverpath" HelpText="Server Path">Server Path: </Label> <Label For="serverpath" HelpText="Server Path">Server Path: </Label>
</td> </td>
<td> <td>
<input id="serverpath" class="form-control" @bind="@_serverpath" disabled /> <input id="serverpath" class="form-control" @bind="@_serverpath" readonly />
</td> </td>
</tr> </tr>
<tr> <tr>
@ -48,7 +48,7 @@
<Label For="servertime" HelpText="Server Time">Server Time: </Label> <Label For="servertime" HelpText="Server Time">Server Time: </Label>
</td> </td>
<td> <td>
<input id="servertime" class="form-control" @bind="@_servertime" disabled /> <input id="servertime" class="form-control" @bind="@_servertime" readonly />
</td> </td>
</tr> </tr>
</table> </table>

View File

@ -35,7 +35,7 @@
<Label HelpText="Upload one or more theme packages. Once they are uploaded click Install to complete the installation.">Theme: </Label> <Label HelpText="Upload one or more theme packages. Once they are uploaded click Install to complete the installation.">Theme: </Label>
</td> </td>
<td> <td>
<FileManager Filter="nupkg" ShowFiles="false" Folder="Themes" UploadMultiple="True" /> <FileManager Filter="nupkg" ShowFiles="false" Folder="Themes" UploadMultiple="@true" />
</td> </td>
</tr> </tr>
</table> </table>

View File

@ -64,7 +64,7 @@ else
<label for="Name" class="control-label">Photo: </label> <label for="Name" class="control-label">Photo: </label>
</td> </td>
<td> <td>
<FileManager FileId="@photofileid.ToString()" @ref="filemanager" /> <FileManager FileId="@photofileid" @ref="filemanager" />
</td> </td>
</tr> </tr>
</table> </table>

View File

@ -63,7 +63,7 @@ else
<label class="control-label">Photo: </label> <label class="control-label">Photo: </label>
</td> </td>
<td> <td>
<FileManager FileId="@photofileid.ToString()" @ref="filemanager" /> <FileManager FileId="@photofileid" @ref="filemanager" />
</td> </td>
</tr> </tr>
<tr> <tr>

View File

@ -1,5 +1,6 @@
@namespace Oqtane.Modules.Controls @namespace Oqtane.Modules.Controls
@inherits ModuleBase @inherits ModuleBase
@attribute [OqtaneIgnore] @attribute [OqtaneIgnore]
@inject IFolderService FolderService @inject IFolderService FolderService
@inject IFileService FileService @inject IFileService FileService
@ -10,33 +11,36 @@
<div id="@Id" class="container-fluid px-0"> <div id="@Id" class="container-fluid px-0">
<div class="row"> <div class="row">
<div class="col"> <div class="col">
<div> @if (ShowFolders || FolderId <= 0)
<select class="form-control" @onchange="(e => FolderChanged(e))"> {
@if (string.IsNullOrEmpty(Folder)) <div>
{ <select class="form-control" @onchange="(e => FolderChanged(e))">
<option value="-1">&lt;Select Folder&gt;</option> @if (string.IsNullOrEmpty(Folder))
}
@foreach (Folder folder in _folders)
{
if (folder.FolderId == _folderid)
{ {
<option value="@(folder.FolderId)" selected>@(new string('-', folder.Level * 2))@(folder.Name)</option> <option value="-1">&lt;Select Folder&gt;</option>
} }
else @foreach (Folder folder in _folders)
{ {
<option value="@(folder.FolderId)">@(new string('-', folder.Level * 2))@(folder.Name)</option> if (folder.FolderId == FolderId)
{
<option value="@(folder.FolderId)" selected>@(new string('-', folder.Level * 2))@(folder.Name)</option>
}
else
{
<option value="@(folder.FolderId)">@(new string('-', folder.Level * 2))@(folder.Name)</option>
}
} }
} </select>
</select> </div>
</div> }
@if (_showfiles) @if (ShowFiles)
{ {
<div> <div>
<select class="form-control" @onchange="(e => FileChanged(e))"> <select class="form-control" @onchange="(e => FileChanged(e))">
<option value="-1">&lt;Select File&gt;</option> <option value="-1">&lt;Select File&gt;</option>
@foreach (File file in _files) @foreach (File file in _files)
{ {
if (file.FileId == _fileid) if (file.FileId == FileId)
{ {
<option value="@(file.FileId)" selected>@(file.Name)</option> <option value="@(file.FileId)" selected>@(file.Name)</option>
} }
@ -48,33 +52,33 @@
</select> </select>
</div> </div>
} }
@if (_haseditpermission) @if (ShowUpload && _haseditpermission)
{ {
<div> <div>
@if (_uploadmultiple) @if (UploadMultiple)
{ {
<input type="file" id="@_fileinputid" name="file" accept="@_filter" multiple /> <input type="file" id="@_fileinputid" name="file" accept="@_filter" multiple/>
} }
else else
{ {
<input type="file" id="@_fileinputid" name="file" accept="@_filter" /> <input type="file" id="@_fileinputid" name="file" accept="@_filter"/>
} }
<span id="@_progressinfoid"></span><progress id="@_progressbarid" style="width: 150px; visibility: hidden;"></progress> <span id="@_progressinfoid"></span><progress id="@_progressbarid" style="width: 150px; visibility: hidden;"></progress>
<span class="float-right"> <span class="float-right">
<button type="button" class="btn btn-success" @onclick="UploadFile">Upload</button> <button type="button" class="btn btn-success" @onclick="UploadFile">Upload</button>
@if (_showfiles && GetFileId() != -1) @if (_showfiles && GetFileId() != -1)
{ {
<button type="button" class="btn btn-danger" @onclick="DeleteFile">Delete</button> <button type="button" class="btn btn-danger" @onclick="DeleteFile">Delete</button>
} }
</span> </span>
</div> </div>
@((MarkupString)_message)
} }
@((MarkupString) _message)
</div> </div>
@if (_image != string.Empty) @if (_image != string.Empty)
{ {
<div class="col-auto"> <div class="col-auto">
@((MarkupString)_image) @((MarkupString) _image)
</div> </div>
} }
</div> </div>
@ -84,19 +88,19 @@
@code { @code {
private string _id; private string _id;
private List<Folder> _folders; private List<Folder> _folders;
private int _folderid = -1;
private List<File> _files = new List<File>(); private List<File> _files = new List<File>();
private int _fileid = -1;
private bool _showfiles = true; private bool _showfiles = true;
private string _fileinputid = string.Empty; private string _fileinputid = string.Empty;
private string _progressinfoid = string.Empty; private string _progressinfoid = string.Empty;
private string _progressbarid = string.Empty; private string _progressbarid = string.Empty;
private string _filter = "*"; private string _filter = "*";
private bool _uploadmultiple = false;
private bool _haseditpermission = false; private bool _haseditpermission = false;
private string _message = string.Empty; private string _message = string.Empty;
private string _image = string.Empty; private string _image = string.Empty;
private string _guid; private string _guid;
private int _folderId = -1;
private bool _uploadMultiple;
private int _fileId;
[Parameter] [Parameter]
public string Id { get; set; } // optional - for setting the id of the FileManager component for accessibility public string Id { get; set; } // optional - for setting the id of the FileManager component for accessibility
@ -105,19 +109,25 @@
public string Folder { get; set; } // optional - for setting a specific folder by default public string Folder { get; set; } // optional - for setting a specific folder by default
[Parameter] [Parameter]
public string FolderId { get; set; } // optional - for setting a specific folderid by default public int FolderId { get; set; } = -1; // optional - for setting a specific folderid by default
[Parameter] [Parameter]
public string ShowFiles { get; set; } // optional - for indicating whether a list of files should be displayed - default is true public bool ShowFiles { get; set; } = true; // optional - for indicating whether a list of files should be displayed - default is true
[Parameter] [Parameter]
public string FileId { get; set; } // optional - for setting a specific file by default public bool ShowUpload { get; set; } = true; // optional - for indicating whether a Upload controls should be displayed - default is true
[Parameter]
public bool ShowFolders { get; set; } = true; // optional - for indicating whether a list of folders should be displayed - default is true
[Parameter]
public int FileId { get; set; } = -1; // optional - for setting a specific file by default
[Parameter] [Parameter]
public string Filter { get; set; } // optional - comma delimited list of file types that can be selected or uploaded ie. "jpg,gif" public string Filter { get; set; } // optional - comma delimited list of file types that can be selected or uploaded ie. "jpg,gif"
[Parameter] [Parameter]
public string UploadMultiple { get; set; } // optional - enable multiple file uploads - default false public bool UploadMultiple { get; set; } = false; // optional - enable multiple file uploads - default false
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
@ -129,56 +139,39 @@
if (!string.IsNullOrEmpty(Folder)) if (!string.IsNullOrEmpty(Folder))
{ {
_folders = new List<Folder> {new Folder {FolderId = -1, Name = Folder}}; _folders = new List<Folder> {new Folder {FolderId = -1, Name = Folder}};
_folderid = -1; FolderId = -1;
} }
else else
{ {
_folders = await FolderService.GetFoldersAsync(ModuleState.SiteId); _folders = await FolderService.GetFoldersAsync(ModuleState.SiteId);
if (!string.IsNullOrEmpty(FolderId))
{
_folderid = int.Parse(FolderId);
}
} }
if (!string.IsNullOrEmpty(FileId)) if (FileId != -1)
{ {
_fileid = int.Parse(FileId); File file = await FileService.GetFileAsync(FileId);
if (_fileid != -1) if (file != null)
{ {
File file = await FileService.GetFileAsync(int.Parse(FileId)); FolderId = file.FolderId;
if (file != null) }
{ else
_folderid = file.FolderId; {
} FileId = -1; // file does not exist
else
{
_fileid = -1; // file does not exist
}
} }
await SetImage();
}
if (!string.IsNullOrEmpty(ShowFiles))
{
_showfiles = bool.Parse(ShowFiles);
} }
await SetImage();
if (!string.IsNullOrEmpty(Filter)) if (!string.IsNullOrEmpty(Filter))
{ {
_filter = "." + Filter.Replace(",",",."); _filter = "." + Filter.Replace(",", ",.");
} }
await GetFiles(); await GetFiles();
// create unique id for component // create unique id for component
_guid = Guid.NewGuid().ToString("N"); _guid = Guid.NewGuid().ToString("N");
_fileinputid = _guid + "FileInput"; _fileinputid = _guid + "FileInput";
_progressinfoid = _guid + "ProgressInfo"; _progressinfoid = _guid + "ProgressInfo";
_progressbarid = _guid + "ProgressBar"; _progressbarid = _guid + "ProgressBar";
if (!string.IsNullOrEmpty(UploadMultiple))
{
_uploadmultiple = bool.Parse(UploadMultiple);
}
} }
private async Task GetFiles() private async Task GetFiles()
@ -191,11 +184,11 @@
} }
else else
{ {
Folder folder = _folders.FirstOrDefault(item => item.FolderId == _folderid); Folder folder = _folders.FirstOrDefault(item => item.FolderId == FolderId);
if (folder != null) if (folder != null)
{ {
_haseditpermission = UserSecurity.IsAuthorized(PageState.User,PermissionNames.Edit, folder.Permissions); _haseditpermission = UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, folder.Permissions);
_files = await FileService.GetFilesAsync(_folderid); _files = await FileService.GetFilesAsync(FolderId);
} }
else else
{ {
@ -222,9 +215,9 @@
_message = string.Empty; _message = string.Empty;
try try
{ {
_folderid = int.Parse((string)e.Value); FolderId = int.Parse((string) e.Value);
await GetFiles(); await GetFiles();
_fileid = -1; FileId = -1;
_image = string.Empty; _image = string.Empty;
StateHasChanged(); StateHasChanged();
} }
@ -238,7 +231,7 @@
private async Task FileChanged(ChangeEventArgs e) private async Task FileChanged(ChangeEventArgs e)
{ {
_message = string.Empty; _message = string.Empty;
_fileid = int.Parse((string)e.Value); FileId = int.Parse((string) e.Value);
await SetImage(); await SetImage();
StateHasChanged(); StateHasChanged();
@ -247,21 +240,21 @@
private async Task SetImage() private async Task SetImage()
{ {
_image = string.Empty; _image = string.Empty;
if (_fileid != -1) if (FileId != -1)
{ {
File file = await FileService.GetFileAsync(_fileid); File file = await FileService.GetFileAsync(FileId);
if (file != null && file.ImageHeight != 0 && file.ImageWidth != 0) if (file != null && file.ImageHeight != 0 && file.ImageWidth != 0)
{ {
var maxwidth = 200; var maxwidth = 200;
var maxheight = 200; var maxheight = 200;
var ratioX = (double)maxwidth / (double)file.ImageWidth; var ratioX = (double) maxwidth / (double) file.ImageWidth;
var ratioY = (double)maxheight / (double)file.ImageHeight; var ratioY = (double) maxheight / (double) file.ImageHeight;
var ratio = ratioX < ratioY ? ratioX : ratioY; var ratio = ratioX < ratioY ? ratioX : ratioY;
_image = "<img src=\"" + ContentUrl(_fileid) + "\" alt=\"" + file.Name + _image = "<img src=\"" + ContentUrl(FileId) + "\" alt=\"" + file.Name +
"\" width=\"" + Convert.ToInt32(file.ImageWidth * ratio).ToString() + "\" width=\"" + Convert.ToInt32(file.ImageWidth * ratio).ToString() +
"\" height=\"" + Convert.ToInt32(file.ImageHeight * ratio).ToString() + "\" />"; "\" height=\"" + Convert.ToInt32(file.ImageHeight * ratio).ToString() + "\" />";
} }
} }
} }
@ -281,7 +274,7 @@
} }
else else
{ {
result = await FileService.UploadFilesAsync(_folderid, upload, _guid); result = await FileService.UploadFilesAsync(FolderId, upload, _guid);
} }
if (result == string.Empty) if (result == string.Empty)
@ -295,7 +288,7 @@
var file = _files.Where(item => item.Name == upload[0]).FirstOrDefault(); var file = _files.Where(item => item.Name == upload[0]).FirstOrDefault();
if (file != null) if (file != null)
{ {
_fileid = file.FileId; FileId = file.FileId;
await SetImage(); await SetImage();
} }
} }
@ -325,21 +318,21 @@
try try
{ {
await FileService.DeleteFileAsync(_fileid); await FileService.DeleteFileAsync(FileId);
await logger.LogInformation("File Deleted {File}", _fileid); await logger.LogInformation("File Deleted {File}", FileId);
_message = "<br /><div class=\"alert alert-success\" role=\"alert\">File Deleted</div>"; _message = "<br /><div class=\"alert alert-success\" role=\"alert\">File Deleted</div>";
await GetFiles(); await GetFiles();
_fileid = -1; FileId = -1;
await SetImage(); await SetImage();
StateHasChanged(); StateHasChanged();
} }
catch (Exception ex) catch (Exception ex)
{ {
await logger.LogError(ex, "Error Deleting File {File} {Error}", _fileid, ex.Message); await logger.LogError(ex, "Error Deleting File {File} {Error}", FileId, ex.Message);
_message = "<br /><div class=\"alert alert-danger\" role=\"alert\">Error Deleting File</div>"; _message = "<br /><div class=\"alert alert-danger\" role=\"alert\">Error Deleting File</div>";
} }
} }
public int GetFileId() => _fileid; public int GetFileId() => FileId;
} }

View File

@ -12,7 +12,6 @@ namespace Oqtane.Services
Task UpdateModuleDefinitionAsync(ModuleDefinition moduleDefinition); Task UpdateModuleDefinitionAsync(ModuleDefinition moduleDefinition);
Task InstallModuleDefinitionsAsync(); Task InstallModuleDefinitionsAsync();
Task DeleteModuleDefinitionAsync(int moduleDefinitionId, int siteId); Task DeleteModuleDefinitionAsync(int moduleDefinitionId, int siteId);
Task LoadModuleDefinitionsAsync(int siteId, Runtime runtime);
Task CreateModuleDefinitionAsync(ModuleDefinition moduleDefinition, int moduleId); Task CreateModuleDefinitionAsync(ModuleDefinition moduleDefinition, int moduleId);
} }
} }

View File

@ -49,43 +49,6 @@ namespace Oqtane.Services
await DeleteAsync($"{Apiurl}/{moduleDefinitionId}?siteid={siteId}"); await DeleteAsync($"{Apiurl}/{moduleDefinitionId}?siteid={siteId}");
} }
public async Task LoadModuleDefinitionsAsync(int siteId, Runtime runtime)
{
// get list of modules from the server
List<ModuleDefinition> moduledefinitions = await GetModuleDefinitionsAsync(siteId);
// download assemblies to browser when running client-side Blazor
if (runtime == Runtime.WebAssembly)
{
// get list of loaded assemblies on the client ( in the client-side hosting module the browser client has its own app domain )
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (ModuleDefinition moduledefinition in moduledefinitions)
{
// if a module has dependencies, check if they are loaded
if (moduledefinition.Dependencies != "")
{
foreach (string dependency in moduledefinition.Dependencies.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
{
string assemblyname = dependency.Replace(".dll", "");
if (assemblies.Where(item => item.FullName.StartsWith(assemblyname + ",")).FirstOrDefault() == null)
{
// download assembly from server and load
var bytes = await _http.GetByteArrayAsync($"{Apiurl}/load/{assemblyname}.dll");
Assembly.Load(bytes);
}
}
}
// check if the module assembly is loaded
if (assemblies.Where(item => item.FullName.StartsWith(moduledefinition.AssemblyName + ",")).FirstOrDefault() == null)
{
// download assembly from server and load
var bytes = await _http.GetByteArrayAsync($"{Apiurl}/load/{moduledefinition.AssemblyName}.dll");
Assembly.Load(bytes);
}
}
}
}
public async Task CreateModuleDefinitionAsync(ModuleDefinition moduleDefinition, int moduleId) public async Task CreateModuleDefinitionAsync(ModuleDefinition moduleDefinition, int moduleId)
{ {
await PostJsonAsync($"{Apiurl}?moduleid={moduleId.ToString()}", moduleDefinition); await PostJsonAsync($"{Apiurl}?moduleid={moduleId.ToString()}", moduleDefinition);

View File

@ -23,33 +23,6 @@ namespace Oqtane.Services
public async Task<List<Theme>> GetThemesAsync() public async Task<List<Theme>> GetThemesAsync()
{ {
List<Theme> themes = await GetJsonAsync<List<Theme>>(Apiurl); List<Theme> themes = await GetJsonAsync<List<Theme>>(Apiurl);
// get list of loaded assemblies
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (Theme theme in themes)
{
if (theme.Dependencies != "")
{
foreach (string dependency in theme.Dependencies.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
{
string assemblyname = dependency.Replace(".dll", "");
if (assemblies.Where(item => item.FullName.StartsWith(assemblyname + ",")).FirstOrDefault() == null)
{
// download assembly from server and load
var bytes = await _http.GetByteArrayAsync($"{Apiurl}/load/{assemblyname}.dll");
Assembly.Load(bytes);
}
}
}
if (assemblies.Where(item => item.FullName.StartsWith(theme.AssemblyName + ",")).FirstOrDefault() == null)
{
// download assembly from server and load
var bytes = await _http.GetByteArrayAsync($"{Apiurl}/load/{theme.AssemblyName}.dll");
Assembly.Load(bytes);
}
}
return themes.OrderBy(item => item.Name).ToList(); return themes.OrderBy(item => item.Name).ToList();
} }

View File

@ -32,7 +32,7 @@
} }
else else
{ {
_paneadminborder = ""; _paneadminborder = "container";
_panetitle = ""; _panetitle = "";
} }

View File

@ -11,7 +11,6 @@
@inject IPageService PageService @inject IPageService PageService
@inject IUserService UserService @inject IUserService UserService
@inject IModuleService ModuleService @inject IModuleService ModuleService
@inject IModuleDefinitionService ModuleDefinitionService
@inject ILogService LogService @inject ILogService LogService
@implements IHandleAfterRender @implements IHandleAfterRender
@ -157,7 +156,6 @@
if (PageState == null || reload >= Reload.Site) if (PageState == null || reload >= Reload.Site)
{ {
await ModuleDefinitionService.LoadModuleDefinitionsAsync(site.SiteId, runtime);
pages = await PageService.GetPagesAsync(site.SiteId); pages = await PageService.GetPagesAsync(site.SiteId);
} }
else else
@ -262,7 +260,7 @@
if (PageState == null || reload >= Reload.Page) if (PageState == null || reload >= Reload.Page)
{ {
modules = await ModuleService.GetModulesAsync(site.SiteId); modules = await ModuleService.GetModulesAsync(site.SiteId);
modules = ProcessModules(modules, page.PageId, _pagestate.ModuleId, _pagestate.Action, page.Panes, site.DefaultContainerType); modules = ProcessModules(modules, page.PageId, _pagestate.ModuleId, _pagestate.Action, page.Panes, (!string.IsNullOrEmpty(page.DefaultContainerType)) ? page.DefaultContainerType : site.DefaultContainerType);
} }
else else
{ {

View File

@ -413,8 +413,11 @@ namespace Oqtane.Controllers
{ {
_logger.Log(LogLevel.Error, this, LogFunction.Read, "File Does Not Exist {FileId} {FilePath}", id, filepath); _logger.Log(LogLevel.Error, this, LogFunction.Read, "File Does Not Exist {FileId} {FilePath}", id, filepath);
HttpContext.Response.StatusCode = 404; HttpContext.Response.StatusCode = 404;
byte[] filebytes = System.IO.File.ReadAllBytes(errorpath); if (System.IO.File.Exists(errorpath))
return File(filebytes, "application/octet-stream", file.Name); {
byte[] filebytes = System.IO.File.ReadAllBytes(errorpath);
return File(filebytes, "application/octet-stream", file.Name);
}
} }
} }
else else
@ -432,6 +435,7 @@ namespace Oqtane.Controllers
byte[] filebytes = System.IO.File.ReadAllBytes(errorpath); byte[] filebytes = System.IO.File.ReadAllBytes(errorpath);
return File(filebytes, "application/octet-stream", "error.png"); return File(filebytes, "application/octet-stream", "error.png");
} }
return null;
} }
private string GetFolderPath(Folder folder) private string GetFolderPath(Folder folder)

View File

@ -105,7 +105,7 @@ namespace Oqtane.Controllers
} }
if (_userPermissions.IsAuthorized(User, PermissionNames.Edit, permissions)) if (_userPermissions.IsAuthorized(User, PermissionNames.Edit, permissions))
{ {
if (FolderPathValid(folder)) if (folder.IsPathValid())
{ {
if (string.IsNullOrEmpty(folder.Path) && folder.ParentId != null) if (string.IsNullOrEmpty(folder.Path) && folder.ParentId != null)
{ {
@ -140,7 +140,7 @@ namespace Oqtane.Controllers
{ {
if (ModelState.IsValid && _userPermissions.IsAuthorized(User, EntityNames.Folder, folder.FolderId, PermissionNames.Edit)) if (ModelState.IsValid && _userPermissions.IsAuthorized(User, EntityNames.Folder, folder.FolderId, PermissionNames.Edit))
{ {
if (FolderPathValid(folder)) if (folder.IsPathValid())
{ {
if (string.IsNullOrEmpty(folder.Path) && folder.ParentId != null) if (string.IsNullOrEmpty(folder.Path) && folder.ParentId != null)
{ {
@ -210,13 +210,5 @@ namespace Oqtane.Controllers
HttpContext.Response.StatusCode = 401; HttpContext.Response.StatusCode = 401;
} }
} }
private bool FolderPathValid(Folder folder)
{
// prevent folder path traversal and reserved devices
return (folder.Name.IndexOfAny(Constants.InvalidFileNameChars) == -1 &&
!Constants.InvalidFileNameEndingChars.Any(x => folder.Name.EndsWith(x)) &&
!Constants.ReservedDevices.Split(',').Contains(folder.Name.ToUpper().Split('.')[0]));
}
} }
} }

View File

@ -13,6 +13,9 @@ using Oqtane.Repository;
using Oqtane.Security; using Oqtane.Security;
using System; using System;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using System.Xml.Linq;
using Microsoft.AspNetCore.Mvc.Formatters;
// ReSharper disable StringIndexOfIsCultureSpecific.1 // ReSharper disable StringIndexOfIsCultureSpecific.1
namespace Oqtane.Controllers namespace Oqtane.Controllers
@ -27,10 +30,11 @@ namespace Oqtane.Controllers
private readonly IUserPermissions _userPermissions; private readonly IUserPermissions _userPermissions;
private readonly IInstallationManager _installationManager; private readonly IInstallationManager _installationManager;
private readonly IWebHostEnvironment _environment; private readonly IWebHostEnvironment _environment;
private readonly IConfigurationRoot _config;
private readonly IServiceProvider _serviceProvider; private readonly IServiceProvider _serviceProvider;
private readonly ILogManager _logger; private readonly ILogManager _logger;
public ModuleDefinitionController(IModuleDefinitionRepository moduleDefinitions, IModuleRepository modules,ITenantRepository tenants, ISqlRepository sql, IUserPermissions userPermissions, IInstallationManager installationManager, IWebHostEnvironment environment, IServiceProvider serviceProvider, ILogManager logger) public ModuleDefinitionController(IModuleDefinitionRepository moduleDefinitions, IModuleRepository modules,ITenantRepository tenants, ISqlRepository sql, IUserPermissions userPermissions, IInstallationManager installationManager, IWebHostEnvironment environment, IConfigurationRoot config, IServiceProvider serviceProvider, ILogManager logger)
{ {
_moduleDefinitions = moduleDefinitions; _moduleDefinitions = moduleDefinitions;
_modules = modules; _modules = modules;
@ -39,6 +43,7 @@ namespace Oqtane.Controllers
_userPermissions = userPermissions; _userPermissions = userPermissions;
_installationManager = installationManager; _installationManager = installationManager;
_environment = environment; _environment = environment;
_config = config;
_serviceProvider = serviceProvider; _serviceProvider = serviceProvider;
_logger = logger; _logger = logger;
} }
@ -158,11 +163,26 @@ namespace Oqtane.Controllers
} }
} }
// GET api/<controller>/load
[HttpGet("load")]
public List<string> Load()
{
List<string> list = new List<string>();
if (_config.GetSection("Runtime").Value == "WebAssembly")
{
var assemblies = AppDomain.CurrentDomain.GetOqtaneClientAssemblies();
list = AppDomain.CurrentDomain.GetOqtaneClientAssemblies().Select(a => a.GetName().Name).ToList();
var deps = assemblies.SelectMany(a => a.GetReferencedAssemblies()).Distinct();
list.AddRange(deps.Where(a => a.Name.EndsWith(".oqtane", StringComparison.OrdinalIgnoreCase)).Select(a => a.Name));
}
return list;
}
// GET api/<controller>/load/assembyname // GET api/<controller>/load/assembyname
[HttpGet("load/{assemblyname}")] [HttpGet("load/{assemblyname}")]
public IActionResult Load(string assemblyname) public IActionResult Load(string assemblyname)
{ {
if (Path.GetExtension(assemblyname).ToLower() == ".dll") if (_config.GetSection("Runtime").Value == "WebAssembly" && Path.GetExtension(assemblyname).ToLower() == ".dll")
{ {
string binfolder = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); string binfolder = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
byte[] file = System.IO.File.ReadAllBytes(Path.Combine(binfolder, assemblyname)); byte[] file = System.IO.File.ReadAllBytes(Path.Combine(binfolder, assemblyname));
@ -175,16 +195,6 @@ namespace Oqtane.Controllers
return null; return null;
} }
} }
// GET api/<controller>/load/assembyname
[HttpGet("load")]
public List<string> Load()
{
var assemblies = AppDomain.CurrentDomain.GetOqtaneClientAssemblies();
var list = AppDomain.CurrentDomain.GetOqtaneClientAssemblies().Select(a => a.GetName().Name).ToList();
var deps = assemblies.SelectMany(a => a.GetReferencedAssemblies()).Distinct();
list.AddRange(deps.Where(a=>a.Name.EndsWith(".oqtane",StringComparison.OrdinalIgnoreCase)).Select(a=>a.Name));
return list;
}
// POST api/<controller>?moduleid=x // POST api/<controller>?moduleid=x
[HttpPost] [HttpPost]
@ -200,13 +210,13 @@ namespace Oqtane.Controllers
if (moduleDefinition.Template == "internal") if (moduleDefinition.Template == "internal")
{ {
rootPath = Utilities.PathCombine(rootFolder.FullName,"\\"); rootPath = Utilities.PathCombine(rootFolder.FullName,"\\");
moduleDefinition.ModuleDefinitionName = moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Modules, Oqtane.Client"; moduleDefinition.ModuleDefinitionName = moduleDefinition.Owner + "." + moduleDefinition.Name + "s, Oqtane.Client";
moduleDefinition.ServerManagerType = moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Manager." + moduleDefinition.Name + "Manager, Oqtane.Server"; moduleDefinition.ServerManagerType = moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Manager." + moduleDefinition.Name + "Manager, Oqtane.Server";
} }
else else
{ {
rootPath = Utilities.PathCombine(rootFolder.Parent.FullName , moduleDefinition.Owner + "." + moduleDefinition.Name + "s","\\"); rootPath = Utilities.PathCombine(rootFolder.Parent.FullName , moduleDefinition.Owner + "." + moduleDefinition.Name + "s","\\");
moduleDefinition.ModuleDefinitionName = moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Modules, " + moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Client.Oqtane"; moduleDefinition.ModuleDefinitionName = moduleDefinition.Owner + "." + moduleDefinition.Name + "s, " + moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Client.Oqtane";
moduleDefinition.ServerManagerType = moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Manager." + moduleDefinition.Name + "Manager, " + moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Server.Oqtane"; moduleDefinition.ServerManagerType = moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Manager." + moduleDefinition.Name + "Manager, " + moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Server.Oqtane";
} }
@ -219,7 +229,11 @@ namespace Oqtane.Controllers
if (moduleDefinition.Template == "internal") if (moduleDefinition.Template == "internal")
{ {
// need logic to add embedded scripts to Oqtane.Server.csproj - also you need to remove them on uninstall // add embedded resources to project
List<string> resources = new List<string>();
resources.Add(Utilities.PathCombine("Modules", moduleDefinition.Name, "Scripts", moduleDefinition.Owner + "." + moduleDefinition.Name + "s.1.0.0.sql"));
resources.Add(Utilities.PathCombine("Modules", moduleDefinition.Name, "Scripts", moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Uninstall.sql"));
EmbedResourceFiles(Utilities.PathCombine(rootPath, "Oqtane.Server", "Oqtane.Server.csproj"), resources);
} }
_installationManager.RestartApplication(); _installationManager.RestartApplication();
@ -268,5 +282,19 @@ namespace Oqtane.Controllers
} }
} }
} }
private void EmbedResourceFiles(string projectfile, List<string> resources)
{
XDocument project = XDocument.Load(projectfile);
var itemGroup = project.Descendants("ItemGroup").Descendants("EmbeddedResource").FirstOrDefault().Parent;
if (itemGroup != null)
{
foreach (var resource in resources)
{
itemGroup.Add(new XElement("EmbeddedResource", new XAttribute("Include", resource)));
}
}
project.Save(projectfile);
}
} }
} }

View File

@ -166,6 +166,7 @@ namespace Oqtane.Controllers
page.EditMode = false; page.EditMode = false;
page.ThemeType = parent.ThemeType; page.ThemeType = parent.ThemeType;
page.LayoutType = parent.LayoutType; page.LayoutType = parent.LayoutType;
page.DefaultContainerType = parent.DefaultContainerType;
page.Icon = parent.Icon; page.Icon = parent.Icon;
page.Permissions = new List<Permission> { page.Permissions = new List<Permission> {
new Permission(PermissionNames.View, userid, true), new Permission(PermissionNames.View, userid, true),

View File

@ -1,5 +1,5 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework> <TargetFramework>netcoreapp3.1</TargetFramework>
<LangVersion>7.3</LangVersion> <LangVersion>7.3</LangVersion>
@ -16,19 +16,14 @@
<PackageReleaseNotes>Not for production use.</PackageReleaseNotes> <PackageReleaseNotes>Not for production use.</PackageReleaseNotes>
<RootNamespace>Oqtane</RootNamespace> <RootNamespace>Oqtane</RootNamespace>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<None Remove="Scripts\Tenant.0.9.1.sql" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="Scripts\Master.0.9.0.sql" />
<EmbeddedResource Include="Scripts\Tenant.0.9.0.sql" />
<EmbeddedResource Include="Scripts\Tenant.0.9.1.sql" />
<EmbeddedResource Include="Scripts\Tenant.0.9.2.sql" />
<EmbeddedResource Include="Modules\HtmlText\Scripts\HtmlText.1.0.0.sql" /> <EmbeddedResource Include="Modules\HtmlText\Scripts\HtmlText.1.0.0.sql" />
<EmbeddedResource Include="Modules\HtmlText\Scripts\HtmlText.Uninstall.sql" /> <EmbeddedResource Include="Modules\HtmlText\Scripts\HtmlText.Uninstall.sql" />
<EmbeddedResource Include="Scripts\Master.0.9.0.sql" />
<EmbeddedResource Include="Scripts\Tenant.0.9.1.sql" />
<EmbeddedResource Include="Scripts\Tenant.0.9.0.sql" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="dbup" Version="4.3.0" /> <PackageReference Include="dbup" Version="4.3.0" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="3.2.0-rc1.20223.4" /> <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="3.2.0-rc1.20223.4" />
@ -39,10 +34,8 @@
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.1.0" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="5.1.0" />
<PackageReference Include="System.Drawing.Common" Version="4.7.0" /> <PackageReference Include="System.Drawing.Common" Version="4.7.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Oqtane.Client\Oqtane.Client.csproj" /> <ProjectReference Include="..\Oqtane.Client\Oqtane.Client.csproj" />
<ProjectReference Include="..\Oqtane.Shared\Oqtane.Shared.csproj" /> <ProjectReference Include="..\Oqtane.Shared\Oqtane.Shared.csproj" />
</ItemGroup> </ItemGroup>
</Project>
</Project>

View File

@ -757,6 +757,7 @@ namespace Oqtane.Repository
EditMode = pagetemplate.EditMode, EditMode = pagetemplate.EditMode,
ThemeType = "", ThemeType = "",
LayoutType = "", LayoutType = "",
DefaultContainerType = "",
Icon = pagetemplate.Icon, Icon = pagetemplate.Icon,
Permissions = pagetemplate.PagePermissions, Permissions = pagetemplate.PagePermissions,
IsPersonalizable = pagetemplate.IsPersonalizable, IsPersonalizable = pagetemplate.IsPersonalizable,

View File

@ -1,6 +1,6 @@
/* /*
migration script Version 0.9.1 migration script
*/ */

View File

@ -0,0 +1,18 @@
/*
Version 0.9.2 migration script
*/
ALTER TABLE [dbo].[Role]
ALTER COLUMN [Description] VARCHAR (256) NOT NULL
GO
ALTER TABLE [dbo].[Page] ADD
[DefaultContainerType] [nvarchar](200) NULL
GO
UPDATE [dbo].[Page]
SET [DefaultContainerType] = ''
GO

View File

@ -15,6 +15,7 @@ namespace Oqtane.Models
public string Url { get; set; } public string Url { get; set; }
public string ThemeType { get; set; } public string ThemeType { get; set; }
public string LayoutType { get; set; } public string LayoutType { get; set; }
public string DefaultContainerType { get; set; }
public string Icon { get; set; } public string Icon { get; set; }
public bool IsNavigation { get; set; } public bool IsNavigation { get; set; }
public bool EditMode { get; set; } public bool EditMode { get; set; }

View File

@ -2,8 +2,10 @@
using System; using System;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Linq;
using System.Text; using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using File = Oqtane.Models.File;
namespace Oqtane.Shared namespace Oqtane.Shared
{ {
@ -254,5 +256,22 @@ namespace Oqtane.Shared
return Path.Combine(segments).TrimEnd(); return Path.Combine(segments).TrimEnd();
} }
public static bool IsPathValid(this Folder folder)
{
return IsPathOrFileValid(folder.Name);
}
public static bool IsFileValid(this File file)
{
return IsPathOrFileValid(file.Name);
}
public static bool IsPathOrFileValid(this string name)
{
return (name.IndexOfAny(Constants.InvalidFileNameChars) == -1 &&
!Constants.InvalidFileNameEndingChars.Any(name.EndsWith) &&
!Constants.ReservedDevices.Split(',').Contains(name.ToUpper().Split('.')[0]));
}
} }
} }