improved file upload, enhanced module installation from Nuget to support upgrades, added ability to upgrade the framework from Nuget, completed isolated multitenancy and site alias management, created IPortable interface for importing data into modules, added default content to initial installation
This commit is contained in:
@ -11,7 +11,7 @@
|
||||
<label for="Name" class="control-label">Module: </label>
|
||||
</td>
|
||||
<td>
|
||||
<FileUpload Filter=".nupkg"></FileUpload>
|
||||
<FileUpload Filter=".nupkg" @ref="fileupload"></FileUpload>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
@ -50,18 +50,55 @@
|
||||
|
||||
bool uploaded = false;
|
||||
List<Package> packages;
|
||||
FileUpload fileupload;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
List<ModuleDefinition> moduledefinitions = await ModuleDefinitionService.GetModuleDefinitionsAsync(PageState.Site.SiteId);
|
||||
packages = await PackageService.GetPackagesAsync("module");
|
||||
foreach(Package package in packages.ToArray())
|
||||
{
|
||||
if (moduledefinitions.Exists(item => Utilities.GetTypeName(item.ModuleDefinitionName) == package.PackageId))
|
||||
{
|
||||
packages.Remove(package);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task UploadFile()
|
||||
{
|
||||
await FileService.UploadFilesAsync("Modules");
|
||||
ModuleInstance.AddModuleMessage("Module Uploaded Successfully. Click Install To Complete Installation.", MessageType.Success);
|
||||
uploaded = true;
|
||||
StateHasChanged();
|
||||
string[] files = await fileupload.GetFiles();
|
||||
if (files.Length > 0)
|
||||
{
|
||||
if (files[0].Contains(".Module."))
|
||||
{
|
||||
try
|
||||
{
|
||||
if (await FileService.UploadFilesAsync("Modules", files, ""))
|
||||
{
|
||||
ModuleInstance.AddModuleMessage("Module Uploaded Successfully. Click Install To Complete Installation.", MessageType.Success);
|
||||
uploaded = true;
|
||||
StateHasChanged();
|
||||
}
|
||||
else
|
||||
{
|
||||
ModuleInstance.AddModuleMessage("Module Upload Failed.", MessageType.Error);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ModuleInstance.AddModuleMessage("Module Upload Failed. " + ex.Message, MessageType.Error);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ModuleInstance.AddModuleMessage("Invalid Module Package", MessageType.Error);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ModuleInstance.AddModuleMessage("You Must Select A Module To Upload", MessageType.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task InstallModules()
|
||||
|
@ -1,6 +1,8 @@
|
||||
@namespace Oqtane.Modules.Admin.ModuleDefinitions
|
||||
@inherits ModuleBase
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject IModuleDefinitionService ModuleDefinitionService
|
||||
@inject IPackageService PackageService
|
||||
|
||||
@if (moduledefinitions == null)
|
||||
{
|
||||
@ -16,12 +18,19 @@ else
|
||||
<th>Version</th>
|
||||
<th> </th>
|
||||
<th> </th>
|
||||
<th> </th>
|
||||
</Header>
|
||||
<Row>
|
||||
<td>@context.Name</td>
|
||||
<td>@context.Version</td>
|
||||
<td><ActionLink Action="Edit" Parameters="@($"id=" + context.ModuleDefinitionId.ToString())" /></td>
|
||||
<td><ActionLink Action="Delete" Parameters="@($"id=" + context.ModuleDefinitionId.ToString())" Class="btn btn-danger" /></td>
|
||||
<td>
|
||||
@if (UpgradeAvailable(context.ModuleDefinitionName, context.Version))
|
||||
{
|
||||
<button type="button" class="btn btn-success" @onclick=@(async () => await DownloadModule(context.ModuleDefinitionName, context.Version))>Upgrade</button>
|
||||
}
|
||||
</td>
|
||||
</Row>
|
||||
</Pager>
|
||||
}
|
||||
@ -30,9 +39,29 @@ else
|
||||
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Host; } }
|
||||
|
||||
List<ModuleDefinition> moduledefinitions;
|
||||
List<Package> packages;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
moduledefinitions = await ModuleDefinitionService.GetModuleDefinitionsAsync(PageState.Site.SiteId);
|
||||
packages = await PackageService.GetPackagesAsync("module");
|
||||
}
|
||||
|
||||
private bool UpgradeAvailable(string moduledefinitionname, string version)
|
||||
{
|
||||
bool upgradeavailable = false;
|
||||
Package package = packages.Where(item => item.PackageId == Utilities.GetTypeName(moduledefinitionname)).FirstOrDefault();
|
||||
if (package != null)
|
||||
{
|
||||
upgradeavailable = (Version.Parse(package.Version).CompareTo(Version.Parse(version)) > 0);
|
||||
}
|
||||
return upgradeavailable;
|
||||
}
|
||||
|
||||
private async Task DownloadModule(string moduledefinitionname, string version)
|
||||
{
|
||||
await PackageService.DownloadPackageAsync(moduledefinitionname, version, "Modules");
|
||||
await ModuleDefinitionService.InstallModulesAsync();
|
||||
NavigationManager.NavigateTo(NavigateUrl(Reload.Application));
|
||||
}
|
||||
}
|
32
Oqtane.Client/Modules/Admin/Modules/Export.razor
Normal file
32
Oqtane.Client/Modules/Admin/Modules/Export.razor
Normal file
@ -0,0 +1,32 @@
|
||||
@namespace Oqtane.Modules.Admin.Modules
|
||||
@inherits ModuleBase
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject IModuleService ModuleService
|
||||
|
||||
<table class="table table-borderless">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Title" class="control-label">Content: </label>
|
||||
</td>
|
||||
<td>
|
||||
<textarea class="form-control" @bind="@content" rows="5" />
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<button type="button" class="btn btn-success" @onclick="ExportModule">Export</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
|
||||
|
||||
|
||||
@code {
|
||||
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Admin; } }
|
||||
public override string Title { get { return "Export Module"; } }
|
||||
|
||||
string content = "";
|
||||
|
||||
private async Task ExportModule()
|
||||
{
|
||||
content = await ModuleService.ExportModuleAsync(ModuleState.ModuleId);
|
||||
}
|
||||
}
|
41
Oqtane.Client/Modules/Admin/Modules/Import.razor
Normal file
41
Oqtane.Client/Modules/Admin/Modules/Import.razor
Normal file
@ -0,0 +1,41 @@
|
||||
@namespace Oqtane.Modules.Admin.Modules
|
||||
@inherits ModuleBase
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject IModuleService ModuleService
|
||||
|
||||
<table class="table table-borderless">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Title" class="control-label">Content: </label>
|
||||
</td>
|
||||
<td>
|
||||
<textarea class="form-control" @bind="@content" rows="5" />
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<button type="button" class="btn btn-success" @onclick="ImportModule">Import</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
|
||||
|
||||
|
||||
@code {
|
||||
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Admin; } }
|
||||
public override string Title { get { return "Import Module"; } }
|
||||
|
||||
string content = "";
|
||||
|
||||
|
||||
private async Task ImportModule()
|
||||
{
|
||||
if (content != "")
|
||||
{
|
||||
await ModuleService.ImportModuleAsync(ModuleState.ModuleId, content);
|
||||
NavigationManager.NavigateTo(NavigateUrl(Reload.Page));
|
||||
}
|
||||
else
|
||||
{
|
||||
ModuleInstance.AddModuleMessage("You Must Enter Some Content To Import", MessageType.Warning);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
@namespace Oqtane.Modules.Admin.ModuleSettings
|
||||
@namespace Oqtane.Modules.Admin.Modules
|
||||
@inherits ModuleBase
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject IThemeService ThemeService
|
||||
@ -6,7 +6,7 @@
|
||||
@inject IPageModuleService PageModuleService
|
||||
|
||||
<table class="table table-borderless">
|
||||
<thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Title" class="control-label">Title: </label>
|
||||
@ -15,8 +15,6 @@
|
||||
<input type="text" name="Title" class="form-control" @bind="@title" />
|
||||
</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Container" class="control-label">Container: </label>
|
@ -19,7 +19,7 @@ else
|
||||
</td>
|
||||
<td>
|
||||
<select class="form-control" @bind="@tenantid">
|
||||
<option value=""><Select Tenant></option>
|
||||
<option value="-1"><Select Tenant></option>
|
||||
@foreach (Tenant tenant in tenants)
|
||||
{
|
||||
<option value="@tenant.TenantId">@tenant.Name</option>
|
||||
@ -37,10 +37,10 @@ else
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Alias: </label>
|
||||
<label for="Name" class="control-label">Aliases: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@url" />
|
||||
<textarea class="form-control" @bind="@urls" rows="3" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@ -91,9 +91,9 @@ else
|
||||
Dictionary<string, string> panelayouts = new Dictionary<string, string>();
|
||||
|
||||
List<Tenant> tenants;
|
||||
string tenantid = "";
|
||||
string tenantid = "-1";
|
||||
string name = "";
|
||||
string url = "";
|
||||
string urls = "";
|
||||
string logo = "";
|
||||
string themetype;
|
||||
string layouttype;
|
||||
@ -101,7 +101,7 @@ else
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
tenants = await TenantService.GetTenantsAsync();
|
||||
url = PageState.Alias.Name;
|
||||
urls = PageState.Alias.Name;
|
||||
themes = ThemeService.GetThemeTypes(PageState.Themes);
|
||||
panelayouts = ThemeService.GetPaneLayoutTypes(PageState.Themes);
|
||||
}
|
||||
@ -115,12 +115,16 @@ else
|
||||
site.DefaultLayoutType = (layouttype == null ? "" : layouttype);
|
||||
site = await SiteService.AddSiteAsync(site);
|
||||
|
||||
Alias alias = new Alias();
|
||||
alias.Name = url;
|
||||
alias.TenantId = int.Parse(tenantid);
|
||||
alias.SiteId = site.SiteId;
|
||||
await AliasService.AddAliasAsync(alias);
|
||||
urls = urls.Replace("\n", ",");
|
||||
foreach(string name in urls.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
|
||||
{
|
||||
Alias alias = new Alias();
|
||||
alias.Name = name;
|
||||
alias.TenantId = int.Parse(tenantid);
|
||||
alias.SiteId = site.SiteId;
|
||||
await AliasService.AddAliasAsync(alias);
|
||||
}
|
||||
|
||||
NavigationManager.NavigateTo("http://" + url, true);
|
||||
NavigationManager.NavigateTo("http://" + urls[0], true);
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
@inherits ModuleBase
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject ISiteService SiteService
|
||||
@inject IAliasService AliasService
|
||||
@inject IThemeService ThemeService
|
||||
|
||||
@if (themes == null)
|
||||
@ -19,6 +20,14 @@ else
|
||||
<input class="form-control" @bind="@name" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Aliases: </label>
|
||||
</td>
|
||||
<td>
|
||||
<textarea class="form-control" @bind="@urls" rows="3" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Logo: </label>
|
||||
@ -80,7 +89,9 @@ else
|
||||
Dictionary<string, string> themes = new Dictionary<string, string>();
|
||||
Dictionary<string, string> panelayouts = new Dictionary<string, string>();
|
||||
|
||||
List<Alias> aliases;
|
||||
string name = "";
|
||||
string urls = "";
|
||||
string logo = "";
|
||||
string themetype;
|
||||
string layouttype;
|
||||
@ -95,9 +106,14 @@ else
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
aliases = PageState.Aliases.Where(item => item.TenantId == PageState.Alias.TenantId && item.SiteId == PageState.Site.SiteId).ToList();
|
||||
themes = ThemeService.GetThemeTypes(PageState.Themes);
|
||||
panelayouts = ThemeService.GetPaneLayoutTypes(PageState.Themes);
|
||||
name = PageState.Site.Name;
|
||||
foreach (Alias alias in aliases)
|
||||
{
|
||||
urls += alias.Name + "\n";
|
||||
}
|
||||
logo = PageState.Site.Logo;
|
||||
themetype = PageState.Site.DefaultThemeType;
|
||||
layouttype = PageState.Site.DefaultLayoutType;
|
||||
@ -122,6 +138,27 @@ else
|
||||
|
||||
site = await SiteService.UpdateSiteAsync(site);
|
||||
|
||||
urls = urls.Replace("\n", ",");
|
||||
string[] names = urls.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
foreach (Alias alias in aliases)
|
||||
{
|
||||
if (!names.Contains(alias.Name))
|
||||
{
|
||||
await AliasService.DeleteAliasAsync(alias.AliasId);
|
||||
}
|
||||
}
|
||||
foreach (string name in names)
|
||||
{
|
||||
if (!aliases.Exists(item => item.Name == name))
|
||||
{
|
||||
Alias alias = new Alias();
|
||||
alias.Name = name;
|
||||
alias.TenantId = PageState.Alias.TenantId;
|
||||
alias.SiteId = site.SiteId;
|
||||
await AliasService.AddAliasAsync(alias);
|
||||
}
|
||||
}
|
||||
|
||||
NavigationManager.NavigateTo(NavigateUrl());
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
@inherits ModuleBase
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject ITenantService TenantService
|
||||
@inject IInstallationService InstallationService
|
||||
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
@ -41,12 +42,20 @@
|
||||
|
||||
private async Task SaveTenant()
|
||||
{
|
||||
Tenant tenant = new Tenant();
|
||||
tenant.Name = name;
|
||||
tenant.DBConnectionString = connectionstring;
|
||||
tenant.DBSchema = schema;
|
||||
await TenantService.AddTenantAsync(tenant);
|
||||
GenericResponse response = await InstallationService.Install(connectionstring);
|
||||
if (response.Success)
|
||||
{
|
||||
Tenant tenant = new Tenant();
|
||||
tenant.Name = name;
|
||||
tenant.DBConnectionString = connectionstring;
|
||||
tenant.DBSchema = schema;
|
||||
await TenantService.AddTenantAsync(tenant);
|
||||
|
||||
NavigationManager.NavigateTo(NavigateUrl());
|
||||
NavigationManager.NavigateTo(NavigateUrl());
|
||||
}
|
||||
else
|
||||
{
|
||||
ModuleInstance.AddModuleMessage(response.Message, MessageType.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
||||
<label for="Name" class="control-label">Theme: </label>
|
||||
</td>
|
||||
<td>
|
||||
<FileUpload Filter=".nupkg"></FileUpload>
|
||||
<FileUpload Filter=".nupkg" @ref="fileupload"></FileUpload>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
@ -49,18 +49,55 @@
|
||||
|
||||
bool uploaded = false;
|
||||
List<Package> packages;
|
||||
FileUpload fileupload;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
List<Theme> themes = await ThemeService.GetThemesAsync();
|
||||
packages = await PackageService.GetPackagesAsync("theme");
|
||||
foreach(Package package in packages.ToArray())
|
||||
{
|
||||
if (themes.Exists(item => Utilities.GetTypeName(item.ThemeName) == package.PackageId))
|
||||
{
|
||||
packages.Remove(package);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task UploadTheme()
|
||||
{
|
||||
await FileService.UploadFilesAsync("Themes");
|
||||
ModuleInstance.AddModuleMessage("Theme Uploaded Successfully. Click Install To Complete Installation.", MessageType.Success);
|
||||
uploaded = true;
|
||||
StateHasChanged();
|
||||
string[] files = await fileupload.GetFiles();
|
||||
if (files.Length > 0)
|
||||
{
|
||||
if (files[0].Contains(".Theme."))
|
||||
{
|
||||
try
|
||||
{
|
||||
if (await FileService.UploadFilesAsync("Themes", files, ""))
|
||||
{
|
||||
ModuleInstance.AddModuleMessage("Theme Uploaded Successfully. Click Install To Complete Installation.", MessageType.Success);
|
||||
uploaded = true;
|
||||
StateHasChanged();
|
||||
}
|
||||
else
|
||||
{
|
||||
ModuleInstance.AddModuleMessage("Theme Upload Failed.", MessageType.Error);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ModuleInstance.AddModuleMessage("Theme Upload Failed. " + ex.Message, MessageType.Error);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ModuleInstance.AddModuleMessage("Invalid Theme Package", MessageType.Error);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ModuleInstance.AddModuleMessage("You Must Select A Theme To Upload", MessageType.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task InstallThemes()
|
||||
|
@ -1,6 +1,8 @@
|
||||
@namespace Oqtane.Modules.Admin.Themes
|
||||
@inherits ModuleBase
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject IThemeService ThemeService
|
||||
@inject IPackageService PackageService
|
||||
|
||||
@if (themes == null)
|
||||
{
|
||||
@ -14,10 +16,19 @@ else
|
||||
<Header>
|
||||
<th>Name</th>
|
||||
<th>Version</th>
|
||||
<th> </th>
|
||||
<th> </th>
|
||||
</Header>
|
||||
<Row>
|
||||
<td>@context.Name</td>
|
||||
<td>@context.Version</td>
|
||||
<td><ActionLink Action="Delete" Parameters="@($"id=" + context.ThemeName)" Class="btn btn-danger" /></td>
|
||||
<td>
|
||||
@if (UpgradeAvailable(context.ThemeName, context.Version))
|
||||
{
|
||||
<button type="button" class="btn btn-success" @onclick=@(async () => await DownloadTheme(context.ThemeName, context.Version))>Upgrade</button>
|
||||
}
|
||||
</td>
|
||||
</Row>
|
||||
</Pager>
|
||||
}
|
||||
@ -26,9 +37,29 @@ else
|
||||
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Host; } }
|
||||
|
||||
List<Theme> themes;
|
||||
List<Package> packages;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
themes = await ThemeService.GetThemesAsync();
|
||||
packages = await PackageService.GetPackagesAsync("module");
|
||||
}
|
||||
|
||||
private bool UpgradeAvailable(string themename, string version)
|
||||
{
|
||||
bool upgradeavailable = false;
|
||||
Package package = packages.Where(item => item.PackageId == Utilities.GetTypeName(themename)).FirstOrDefault();
|
||||
if (package != null)
|
||||
{
|
||||
upgradeavailable = (Version.Parse(package.Version).CompareTo(Version.Parse(version)) > 0);
|
||||
}
|
||||
return upgradeavailable;
|
||||
}
|
||||
|
||||
private async Task DownloadTheme(string themename, string version)
|
||||
{
|
||||
await PackageService.DownloadPackageAsync(themename, version, "Themes");
|
||||
await ThemeService.InstallThemesAsync();
|
||||
NavigationManager.NavigateTo(NavigateUrl(Reload.Application));
|
||||
}
|
||||
}
|
104
Oqtane.Client/Modules/Admin/Upgrade/Index.razor
Normal file
104
Oqtane.Client/Modules/Admin/Upgrade/Index.razor
Normal file
@ -0,0 +1,104 @@
|
||||
@namespace Oqtane.Modules.Admin.Upgrade
|
||||
@inherits ModuleBase
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject IFileService FileService
|
||||
@inject IPackageService PackageService
|
||||
@inject IInstallationService InstallationService
|
||||
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Framework: </label>
|
||||
</td>
|
||||
<td>
|
||||
<FileUpload Filter=".nupkg" @ref="fileupload"></FileUpload>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
@if (uploaded)
|
||||
{
|
||||
<button type="button" class="btn btn-success" @onclick="Upgrade">Upgrade</button>
|
||||
}
|
||||
else
|
||||
{
|
||||
<button type="button" class="btn btn-primary" @onclick="UploadFile">Upload</button>
|
||||
}
|
||||
|
||||
@if (upgradeavailable)
|
||||
{
|
||||
<hr />
|
||||
<div class="mx-auto text-center"><h2>Upgrade Available</h2></div>
|
||||
|
||||
<button type="button" class="btn btn-success" @onclick=@(async () => await Download(Constants.PackageId, Constants.Version))>Upgrade Framework</button>
|
||||
}
|
||||
|
||||
@code {
|
||||
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Host; } }
|
||||
|
||||
bool uploaded = false;
|
||||
bool upgradeavailable = false;
|
||||
FileUpload fileupload;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
List<Package> packages = await PackageService.GetPackagesAsync("framework");
|
||||
Package package = packages.FirstOrDefault();
|
||||
if (package != null)
|
||||
{
|
||||
upgradeavailable = (Version.Parse(package.Version).CompareTo(Version.Parse(Constants.Version)) > 0);
|
||||
}
|
||||
if (!upgradeavailable)
|
||||
{
|
||||
ModuleInstance.AddModuleMessage("Framework Up To Date", MessageType.Info);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task UploadFile()
|
||||
{
|
||||
string[] files = await fileupload.GetFiles();
|
||||
if (files.Length > 0)
|
||||
{
|
||||
if (files[0].Contains(".Framework."))
|
||||
{
|
||||
try
|
||||
{
|
||||
if (await FileService.UploadFilesAsync("Framework", files, ""))
|
||||
{
|
||||
ModuleInstance.AddModuleMessage("Framework Uploaded Successfully. Click Upgrade To Complete Installation.", MessageType.Success);
|
||||
uploaded = true;
|
||||
StateHasChanged();
|
||||
}
|
||||
else
|
||||
{
|
||||
ModuleInstance.AddModuleMessage("Framework Upload Failed.", MessageType.Error);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ModuleInstance.AddModuleMessage("Framework Upload Failed. " + ex.Message, MessageType.Error);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ModuleInstance.AddModuleMessage("Invalid Framework Package", MessageType.Error);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ModuleInstance.AddModuleMessage("You Must Select A Framework Package To Upload", MessageType.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task Upgrade()
|
||||
{
|
||||
await InstallationService.Upgrade();
|
||||
NavigationManager.NavigateTo(NavigateUrl(Reload.Application));
|
||||
}
|
||||
|
||||
private async Task Download(string packageid, string version)
|
||||
{
|
||||
await PackageService.DownloadPackageAsync(packageid, version, "Framework");
|
||||
await InstallationService.Upgrade();
|
||||
NavigationManager.NavigateTo(NavigateUrl(Reload.Application));
|
||||
}
|
||||
}
|
@ -1,12 +1,13 @@
|
||||
@namespace Oqtane.Modules.Controls
|
||||
@inject IJSRuntime jsRuntime
|
||||
|
||||
@if (multiple)
|
||||
{
|
||||
<input type="file" id="@fileid" name="file" accept="@filter" multiple />
|
||||
<input type="file" id="@fileid" name="file" accept="@filter" value="@files" multiple />
|
||||
}
|
||||
else
|
||||
{
|
||||
<input type="file" id="@fileid" name="file" accept="@filter" />
|
||||
<input type="file" id="@fileid" name="file" accept="@filter" value="@files" />
|
||||
}
|
||||
<span id="@progressinfoid"></span> <progress id="@progressbarid" style="visibility: hidden;"></progress>
|
||||
|
||||
@ -24,6 +25,7 @@ else
|
||||
string progressinfoid = "";
|
||||
string progressbarid = "";
|
||||
string filter = "*";
|
||||
string files = "";
|
||||
bool multiple = false;
|
||||
|
||||
protected override void OnInitialized()
|
||||
@ -42,4 +44,11 @@ else
|
||||
multiple = bool.Parse(Multiple);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<string[]> GetFiles()
|
||||
{
|
||||
var interop = new Interop(jsRuntime);
|
||||
string[] files = await interop.GetFiles(fileid);
|
||||
return files;
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
namespace Oqtane.Modules.HtmlText
|
||||
{
|
||||
public class Module : IModule
|
||||
public class ModuleInfo : IModule
|
||||
{
|
||||
public Dictionary<string, string> Properties
|
||||
{
|
||||
@ -12,7 +12,8 @@ namespace Oqtane.Modules.HtmlText
|
||||
{
|
||||
{ "Name", "HtmlText" },
|
||||
{ "Description", "Renders HTML or Text" },
|
||||
{ "Version", "1.0.0" }
|
||||
{ "Version", "1.0.0" },
|
||||
{ "ServerAssemblyName", "Oqtane.Server" }
|
||||
};
|
||||
return properties;
|
||||
}
|
@ -1,12 +1,10 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Net.Http;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Oqtane.Services;
|
||||
using Oqtane.Modules.HtmlText.Models;
|
||||
using Oqtane.Shared;
|
||||
using System.Text.Json;
|
||||
using Oqtane.Models;
|
||||
|
||||
namespace Oqtane.Modules.HtmlText.Services
|
||||
{
|
||||
@ -57,5 +55,6 @@ namespace Oqtane.Modules.HtmlText.Services
|
||||
{
|
||||
await http.DeleteAsync(apiurl + "/" + ModuleId.ToString() + "?entityid=" + ModuleId.ToString());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ using Microsoft.JSInterop;
|
||||
using Oqtane.Shared;
|
||||
using Oqtane.Models;
|
||||
using System.Threading.Tasks;
|
||||
using System.Linq;
|
||||
|
||||
namespace Oqtane.Modules
|
||||
{
|
||||
@ -20,6 +21,14 @@ namespace Oqtane.Modules
|
||||
[CascadingParameter]
|
||||
protected ModuleInstance ModuleInstance { get; set; }
|
||||
|
||||
protected ModuleDefinition ModuleDefinition
|
||||
{
|
||||
get
|
||||
{
|
||||
return PageState.ModuleDefinitions.Where(item => item.ModuleDefinitionName == ModuleState.ModuleDefinitionName).FirstOrDefault();
|
||||
}
|
||||
}
|
||||
|
||||
public virtual SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.View; } set { } } // default security
|
||||
|
||||
public virtual string Title { get { return ""; } }
|
||||
|
@ -1,4 +1,6 @@
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.JSInterop;
|
||||
using Oqtane.Shared;
|
||||
@ -7,12 +9,14 @@ namespace Oqtane.Services
|
||||
{
|
||||
public class FileService : ServiceBase, IFileService
|
||||
{
|
||||
private readonly HttpClient http;
|
||||
private readonly SiteState sitestate;
|
||||
private readonly NavigationManager NavigationManager;
|
||||
private readonly IJSRuntime jsRuntime;
|
||||
|
||||
public FileService(SiteState sitestate, NavigationManager NavigationManager, IJSRuntime jsRuntime)
|
||||
public FileService(HttpClient http, SiteState sitestate, NavigationManager NavigationManager, IJSRuntime jsRuntime)
|
||||
{
|
||||
this.http = http;
|
||||
this.sitestate = sitestate;
|
||||
this.NavigationManager = NavigationManager;
|
||||
this.jsRuntime = jsRuntime;
|
||||
@ -23,15 +27,29 @@ namespace Oqtane.Services
|
||||
get { return CreateApiUrl(sitestate.Alias, NavigationManager.Uri, "File"); }
|
||||
}
|
||||
|
||||
public async Task UploadFilesAsync(string Folder)
|
||||
public async Task<List<string>> GetFilesAsync(string Folder)
|
||||
{
|
||||
await UploadFilesAsync(Folder, "");
|
||||
return await http.GetJsonAsync<List<string>>(apiurl + "?folder=" + Folder);
|
||||
}
|
||||
|
||||
public async Task UploadFilesAsync(string Folder, string FileUploadName)
|
||||
public async Task<bool> UploadFilesAsync(string Folder, string[] Files, string FileUploadName)
|
||||
{
|
||||
bool success = false;
|
||||
var interop = new Interop(jsRuntime);
|
||||
await interop.UploadFiles(apiurl + "/upload", Folder, FileUploadName);
|
||||
List<string> files = await GetFilesAsync(Folder);
|
||||
if (files.Count > 0)
|
||||
{
|
||||
success = true;
|
||||
foreach (string file in Files)
|
||||
{
|
||||
if (!files.Contains(file))
|
||||
{
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -35,5 +35,10 @@ namespace Oqtane.Services
|
||||
{
|
||||
return await http.PostJsonAsync<GenericResponse>(apiurl, connectionstring);
|
||||
}
|
||||
|
||||
public async Task<GenericResponse> Upgrade()
|
||||
{
|
||||
return await http.GetJsonAsync<GenericResponse>(apiurl + "/upgrade");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ namespace Oqtane.Services
|
||||
{
|
||||
public interface IFileService
|
||||
{
|
||||
Task UploadFilesAsync(string Folder);
|
||||
Task UploadFilesAsync(string Folder, string FileUploadName);
|
||||
Task<List<string>> GetFilesAsync(string Folder);
|
||||
Task<bool> UploadFilesAsync(string Folder, string[] Files, string FileUploadName);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
using Oqtane.Models;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Oqtane.Services
|
||||
@ -8,5 +7,6 @@ namespace Oqtane.Services
|
||||
{
|
||||
Task<GenericResponse> IsInstalled();
|
||||
Task<GenericResponse> Install(string connectionstring);
|
||||
Task<GenericResponse> Upgrade();
|
||||
}
|
||||
}
|
||||
|
@ -12,5 +12,7 @@ namespace Oqtane.Services
|
||||
Task<Module> AddModuleAsync(Module Module);
|
||||
Task<Module> UpdateModuleAsync(Module Module);
|
||||
Task DeleteModuleAsync(int ModuleId);
|
||||
Task<bool> ImportModuleAsync(int ModuleId, string Content);
|
||||
Task<string> ExportModuleAsync(int ModuleId);
|
||||
}
|
||||
}
|
||||
|
@ -60,5 +60,15 @@ namespace Oqtane.Services
|
||||
{
|
||||
await http.DeleteAsync(apiurl + "/" + ModuleId.ToString());
|
||||
}
|
||||
|
||||
public async Task<bool> ImportModuleAsync(int ModuleId, string Content)
|
||||
{
|
||||
return await http.PostJsonAsync<bool>(apiurl + "/import?moduleid=" + ModuleId, Content);
|
||||
}
|
||||
|
||||
public async Task<string> ExportModuleAsync(int ModuleId)
|
||||
{
|
||||
return await http.GetStringAsync(apiurl + "/export?moduleid=" + ModuleId.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -122,7 +122,7 @@
|
||||
private string DatabaseType = "LocalDB";
|
||||
private string ServerName = "(LocalDb)\\MSSQLLocalDB";
|
||||
private string DatabaseName = "Oqtane-" + DateTime.Now.ToString("yyyyMMddHHmm");
|
||||
private string Username = "";
|
||||
private string Username = "host";
|
||||
private string Password = "";
|
||||
private string HostUsername = "";
|
||||
private string HostPassword = "";
|
||||
@ -146,7 +146,7 @@
|
||||
|
||||
private async Task Install()
|
||||
{
|
||||
if (HostPassword.Length >= 6)
|
||||
if (HostUsername != "" & HostPassword.Length >= 6 & HostEmail != "")
|
||||
{
|
||||
LoadingDisplay = "";
|
||||
StateHasChanged();
|
||||
@ -197,7 +197,7 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
Message = "<div class=\"alert alert-danger\" role=\"alert\">Password Must Be 6 Characters Or Greater</div>";
|
||||
Message = "<div class=\"alert alert-danger\" role=\"alert\">Username And Email Must Be Provided And Password Must Be Greater Than 5 Characters</div>";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -100,6 +100,20 @@ namespace Oqtane.Shared
|
||||
}
|
||||
}
|
||||
|
||||
public ValueTask<string[]> GetFiles(string name)
|
||||
{
|
||||
try
|
||||
{
|
||||
return jsRuntime.InvokeAsync<string[]>(
|
||||
"interop.getFiles",
|
||||
name);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return new ValueTask<string[]>(Task.FromResult(new string[0]));
|
||||
}
|
||||
}
|
||||
|
||||
public Task UploadFiles(string posturl, string folder, string name)
|
||||
{
|
||||
try
|
||||
|
@ -21,10 +21,12 @@
|
||||
DynamicComponent = builder =>
|
||||
{
|
||||
string typename = ModuleState.ModuleType;
|
||||
if (PageState.Control == "Settings") // module settings are a core component
|
||||
{
|
||||
typename = Constants.DefaultSettingsControl;
|
||||
// check for core module actions component
|
||||
if (Constants.DefaultModuleActions.Contains(PageState.Control))
|
||||
{
|
||||
typename = Constants.DefaultModuleActionsTemplate.Replace("{Control}", PageState.Control);
|
||||
}
|
||||
|
||||
Type moduleType = null;
|
||||
if (typename != null)
|
||||
{
|
||||
|
@ -40,21 +40,22 @@
|
||||
{
|
||||
if (PageState.ModuleId != -1 && PageState.Control != "")
|
||||
{
|
||||
if (Name == Constants.AdminPane)
|
||||
if (Name.ToLower() == Constants.AdminPane.ToLower())
|
||||
{
|
||||
Module module = PageState.Modules.Where(item => item.ModuleId == PageState.ModuleId).FirstOrDefault();
|
||||
if (module != null)
|
||||
{
|
||||
string typename = module.ModuleType;
|
||||
if (PageState.Control == "Settings")
|
||||
// check for core module actions component
|
||||
if (Constants.DefaultModuleActions.Contains(PageState.Control))
|
||||
{
|
||||
typename = Constants.DefaultSettingsControl;
|
||||
typename = Constants.DefaultModuleActionsTemplate.Replace("{Control}", PageState.Control);
|
||||
}
|
||||
Type moduleType = Type.GetType(typename);
|
||||
if (moduleType != null)
|
||||
{
|
||||
bool authorized = false;
|
||||
if (PageState.Control == "Settings")
|
||||
if (Constants.DefaultModuleActions.Contains(PageState.Control))
|
||||
{
|
||||
authorized = UserSecurity.IsAuthorized(PageState.User, "Edit", PageState.Page.Permissions);
|
||||
}
|
||||
@ -82,7 +83,7 @@
|
||||
}
|
||||
if (authorized)
|
||||
{
|
||||
if (PageState.Control != "Settings" && module.ControlTitle != "")
|
||||
if (!Constants.DefaultModuleActions.Contains(PageState.Control) && module.ControlTitle != "")
|
||||
{
|
||||
module.Title = module.ControlTitle;
|
||||
}
|
||||
@ -93,8 +94,8 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
// module control does not exist with name specified
|
||||
}
|
||||
// module control does not exist with name specified
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -103,10 +104,10 @@
|
||||
if (PageState.ModuleId != -1)
|
||||
{
|
||||
Module module = PageState.Modules.Where(item => item.ModuleId == PageState.ModuleId).FirstOrDefault();
|
||||
if (module != null && module.Pane == Name)
|
||||
if (module != null && module.Pane.ToLower() == Name.ToLower())
|
||||
{
|
||||
// check if user is authorized to view module
|
||||
if (UserSecurity.IsAuthorized(PageState.User, "View", module.Permissions))
|
||||
// check if user is authorized to view module
|
||||
if (UserSecurity.IsAuthorized(PageState.User, "View", module.Permissions))
|
||||
{
|
||||
builder.OpenComponent(0, Type.GetType(Constants.DefaultContainer));
|
||||
builder.AddAttribute(1, "Module", module);
|
||||
@ -116,10 +117,10 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (Module module in PageState.Modules.Where(item => item.Pane == Name).OrderBy(x => x.Order).ToArray())
|
||||
foreach (Module module in PageState.Modules.Where(item => item.Pane.ToLower() == Name.ToLower()).OrderBy(x => x.Order).ToArray())
|
||||
{
|
||||
// check if user is authorized to view module
|
||||
if (UserSecurity.IsAuthorized(PageState.User, "View", module.Permissions))
|
||||
// check if user is authorized to view module
|
||||
if (UserSecurity.IsAuthorized(PageState.User, "View", module.Permissions))
|
||||
{
|
||||
builder.OpenComponent(0, Type.GetType(Constants.DefaultContainer));
|
||||
builder.AddAttribute(1, "Module", module);
|
||||
|
@ -342,9 +342,10 @@
|
||||
|
||||
// get IModuleControl properties
|
||||
typename = module.ModuleType;
|
||||
if (control == "Settings")
|
||||
// check for core module actions component
|
||||
if (Constants.DefaultModuleActions.Contains(control))
|
||||
{
|
||||
typename = Constants.DefaultSettingsControl;
|
||||
typename = Constants.DefaultModuleActionsTemplate.Replace("{Control}", control);
|
||||
}
|
||||
Type moduletype = Type.GetType(typename);
|
||||
if (moduletype != null)
|
||||
@ -358,7 +359,7 @@
|
||||
}
|
||||
|
||||
// ensure module's pane exists in current page and if not, assign it to the Admin pane
|
||||
if (!panes.Contains(module.Pane))
|
||||
if (!panes.ToLower().Contains(module.Pane.ToLower()))
|
||||
{
|
||||
module.Pane = Constants.AdminPane;
|
||||
}
|
||||
|
@ -59,6 +59,18 @@ namespace Oqtane.Shared
|
||||
return url;
|
||||
}
|
||||
|
||||
public static string GetTypeName(string fullyqualifiedtypename)
|
||||
{
|
||||
if (fullyqualifiedtypename.Contains(","))
|
||||
{
|
||||
return fullyqualifiedtypename.Substring(0, fullyqualifiedtypename.IndexOf(","));
|
||||
}
|
||||
else
|
||||
{
|
||||
return fullyqualifiedtypename;
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetTypeNameClass(string typename)
|
||||
{
|
||||
if (typename.Contains(","))
|
||||
|
@ -3,6 +3,7 @@ using Microsoft.JSInterop;
|
||||
using Oqtane.Shared;
|
||||
using Oqtane.Models;
|
||||
using System.Threading.Tasks;
|
||||
using System.Linq;
|
||||
|
||||
namespace Oqtane.Themes
|
||||
{
|
||||
@ -17,6 +18,14 @@ namespace Oqtane.Themes
|
||||
[CascadingParameter]
|
||||
protected Module ModuleState { get; set; }
|
||||
|
||||
protected ModuleDefinition ModuleDefinition
|
||||
{
|
||||
get
|
||||
{
|
||||
return PageState.ModuleDefinitions.Where(item => item.ModuleDefinitionName == ModuleState.ModuleDefinitionName).FirstOrDefault();
|
||||
}
|
||||
}
|
||||
|
||||
public virtual string Name { get; set; }
|
||||
|
||||
public string ThemePath()
|
||||
|
@ -48,8 +48,13 @@
|
||||
actions.Add(new ActionViewModel { Action = pane, Name = "Move To " + pane + " Pane" });
|
||||
}
|
||||
}
|
||||
actions.Add(new ActionViewModel { Action = "settings", Name = "Settings" });
|
||||
actions.Add(new ActionViewModel { Action = "delete", Name = "Delete" });
|
||||
actions.Add(new ActionViewModel { Action = "settings", Name = "Manage Settings" });
|
||||
if (ModuleDefinition.ServerAssemblyName != "")
|
||||
{
|
||||
actions.Add(new ActionViewModel { Action = "import", Name = "Import Content" });
|
||||
actions.Add(new ActionViewModel { Action = "export", Name = "Export Content" });
|
||||
}
|
||||
actions.Add(new ActionViewModel { Action = "delete", Name = "Delete Module" });
|
||||
}
|
||||
}
|
||||
|
||||
@ -85,6 +90,12 @@
|
||||
case "settings":
|
||||
url = EditUrl(pagemodule.ModuleId, "Settings");
|
||||
break;
|
||||
case "import":
|
||||
url = EditUrl(pagemodule.ModuleId, "Import");
|
||||
break;
|
||||
case "export":
|
||||
url = EditUrl(pagemodule.ModuleId, "Export");
|
||||
break;
|
||||
case "delete":
|
||||
await PageModuleService.DeletePageModuleAsync(pagemodule.PageModuleId);
|
||||
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
||||
|
@ -9,7 +9,8 @@
|
||||
protected override Task OnParametersSetAsync()
|
||||
{
|
||||
title = ModuleState.Title;
|
||||
if (PageState.Control == "Settings")
|
||||
// check for core module actions component
|
||||
if (Constants.DefaultModuleActions.Contains(PageState.Control))
|
||||
{
|
||||
title = PageState.Control;
|
||||
}
|
||||
|
@ -64,6 +64,16 @@ window.interop = {
|
||||
document.body.appendChild(form);
|
||||
form.submit();
|
||||
},
|
||||
getFiles: function (name) {
|
||||
var files = [];
|
||||
var fileinput = document.getElementById(name);
|
||||
if (fileinput !== null) {
|
||||
for (var i = 0; i < fileinput.files.length; i++) {
|
||||
files.push(fileinput.files[i].name);
|
||||
}
|
||||
}
|
||||
return files;
|
||||
},
|
||||
uploadFiles: function (posturl, folder, name) {
|
||||
var files = document.getElementById(name + 'FileInput').files;
|
||||
var progressinfo = document.getElementById(name + 'ProgressInfo');
|
||||
|
Reference in New Issue
Block a user