diff --git a/Oqtane.Client/Modules/Admin/ModuleDefinitions/Add.razor b/Oqtane.Client/Modules/Admin/ModuleDefinitions/Add.razor index 49e70702..a63784bc 100644 --- a/Oqtane.Client/Modules/Admin/ModuleDefinitions/Add.razor +++ b/Oqtane.Client/Modules/Admin/ModuleDefinitions/Add.razor @@ -5,42 +5,47 @@ @inject IModuleDefinitionService ModuleDefinitionService @inject IPackageService PackageService - - - - - -
- - - -
- @if (_packages != null) { -
-

Available Modules

+ + @if (_packages.Count > 0) + { + + + +
+ Name + Version + +
+ + @context.Name + @context.Version + + + + +
+
+ } + + + + + + +
+ + + +
+
+
- -
- Name - Version - -
- - @context.Name - @context.Version - - - - -
+ + Cancel } - -Cancel - - @code { private List _packages; @@ -52,8 +57,8 @@ { var moduledefinitions = await ModuleDefinitionService.GetModuleDefinitionsAsync(PageState.Site.SiteId); _packages = await PackageService.GetPackagesAsync("module"); - - foreach(Package package in _packages.ToArray()) + + foreach (Package package in _packages.ToArray()) { if (moduledefinitions.Exists(item => Utilities.GetTypeName(item.ModuleDefinitionName) == package.PackageId)) { @@ -81,18 +86,18 @@ } } - private async Task DownloadModule(string moduledefinitionname, string version) + private async Task DownloadModule(string packageid, string version) { try { - await PackageService.DownloadPackageAsync(moduledefinitionname, version, "Modules"); - await logger.LogInformation("Module {ModuleDefinitionName} {Version} Downloaded Successfully", moduledefinitionname, version); - AddModuleMessage("Module Downloaded Successfully. Click Install To Complete Installation.", MessageType.Success); + await PackageService.DownloadPackageAsync(packageid, version, "Modules"); + await logger.LogInformation("Module {ModuleDefinitionName} {Version} Downloaded Successfully", packageid, version); + AddModuleMessage("Modules Downloaded Successfully. Click Install To Complete Installation.", MessageType.Success); StateHasChanged(); } catch (Exception ex) { - await logger.LogError(ex, "Error Downloading Module {ModuleDefinitionName} {Version}", moduledefinitionname, version); + await logger.LogError(ex, "Error Downloading Module {ModuleDefinitionName} {Version}", packageid, version); AddModuleMessage("Error Downloading Module", MessageType.Error); } } diff --git a/Oqtane.Client/Modules/Admin/SystemInfo/Index.razor b/Oqtane.Client/Modules/Admin/SystemInfo/Index.razor index b37adc98..d4ac4947 100644 --- a/Oqtane.Client/Modules/Admin/SystemInfo/Index.razor +++ b/Oqtane.Client/Modules/Admin/SystemInfo/Index.razor @@ -1,29 +1,38 @@ @namespace Oqtane.Modules.Admin.SystemInfo @inherits ModuleBase +@inject ISystemService SystemService + + + + @@ -31,7 +40,7 @@ @@ -39,7 +48,7 @@
- + - @_version +
- + - @_runtime +
- + - @_netcore + +
+ + +
- @_serverpath +
- @_servertime +
@@ -49,16 +58,23 @@ private string _version = string.Empty; private string _runtime = string.Empty; - private string _netcore = string.Empty; + private string _clrversion = string.Empty; + private string _osversion = string.Empty; private string _serverpath = string.Empty; private string _servertime = string.Empty; - protected override void OnInitialized() + protected override async Task OnInitializedAsync() { _version = Constants.Version; _runtime = PageState.Runtime.ToString(); - _netcore = string.Empty; - _serverpath = string.Empty; - _servertime = string.Empty; + + Dictionary systeminfo = await SystemService.GetSystemInfoAsync(); + if (systeminfo != null) + { + _clrversion = systeminfo["clrversion"]; + _osversion = systeminfo["osversion"]; + _serverpath = systeminfo["serverpath"]; + _servertime = systeminfo["servertime"]; + } } } diff --git a/Oqtane.Client/Modules/Admin/Themes/Add.razor b/Oqtane.Client/Modules/Admin/Themes/Add.razor index dcf822f9..5ad4f5c6 100644 --- a/Oqtane.Client/Modules/Admin/Themes/Add.razor +++ b/Oqtane.Client/Modules/Admin/Themes/Add.razor @@ -5,70 +5,100 @@ @inject IThemeService ThemeService @inject IPackageService PackageService - - - - - -
- - - -
- -@if (packages != null) +@if (_packages != null) { -
-

Available Themes

- - -
- Name - Version - -
- - @context.Name - @context.Version - - - - -
-} + + @if (_packages.Count > 0) + { + + + +
+ Name + Version + +
+ + @context.Name + @context.Version + + + + +
+
+ } + + + + + + +
+ + + +
+
+
Cancel +} @code { - private List packages; + private List _packages; public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host; protected override async Task OnInitializedAsync() { - var themes = await ThemeService.GetThemesAsync(); - packages = await PackageService.GetPackagesAsync("theme"); - - foreach(Package package in packages.ToArray()) + try { - if (themes.Exists(item => Utilities.GetTypeName(item.ThemeName) == package.PackageId)) + var themes = await ThemeService.GetThemesAsync(); + _packages = await PackageService.GetPackagesAsync("theme"); + + foreach (Package package in _packages.ToArray()) { - packages.Remove(package); + if (themes.Exists(item => Utilities.GetTypeName(item.ThemeName) == package.PackageId)) + { + _packages.Remove(package); + } } } + catch (Exception ex) + { + await logger.LogError(ex, "Error Loading Packages {Error}", ex.Message); + AddModuleMessage("Error Loading Packages", MessageType.Error); + } } private async Task InstallThemes() { - await ThemeService.InstallThemesAsync(); - NavigationManager.NavigateTo(NavigateUrl()); + try + { + await ThemeService.InstallThemesAsync(); + NavigationManager.NavigateTo(NavigateUrl()); + } + catch (Exception ex) + { + await logger.LogError(ex, "Error Installating Theme"); + } } private async Task DownloadTheme(string packageid, string version) { - await PackageService.DownloadPackageAsync(packageid, version, "Themes"); - AddModuleMessage("Theme Downloaded Successfully. Click Install To Complete Installation.", MessageType.Success); - StateHasChanged(); + try + { + await PackageService.DownloadPackageAsync(packageid, version, "Themes"); + await logger.LogInformation("Theme {ThemeName} {Version} Downloaded Successfully", packageid, version); + AddModuleMessage("Themes Downloaded Successfully. Click Install To Complete Installation.", MessageType.Success); + StateHasChanged(); + } + catch (Exception ex) + { + await logger.LogError(ex, "Error Downloading Module {ThemeName} {Version}", packageid, version); + AddModuleMessage("Error Downloading Theme", MessageType.Error); + } + } } -} diff --git a/Oqtane.Client/Modules/Admin/Upgrade/Index.razor b/Oqtane.Client/Modules/Admin/Upgrade/Index.razor index e70ab017..2aa2ce86 100644 --- a/Oqtane.Client/Modules/Admin/Upgrade/Index.razor +++ b/Oqtane.Client/Modules/Admin/Upgrade/Index.razor @@ -5,42 +5,55 @@ @inject IPackageService PackageService @inject IInstallationService InstallationService - - - - - -
- - - -
- - -@if (upgradeavailable) +@if (_package != null) { -
-

Upgrade Available

- - + + + @if (_upgradeavailable) + { + + @("Framework") @_package.Version + } + else + { + + } + + @if (_upgradeavailable) + { + + + + + + +
+ + + +
+
+ } +
} @code { - private bool upgradeavailable = false; + private Package _package; + private bool _upgradeavailable = false; public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host; protected override async Task OnInitializedAsync() { - var packages = await PackageService.GetPackagesAsync("framework"); - var package = packages.FirstOrDefault(); - if (package != null) + List packages = await PackageService.GetPackagesAsync("framework"); + _package = packages.FirstOrDefault(); + if (_package != null) { - upgradeavailable = (Version.Parse(package.Version).CompareTo(Version.Parse(Constants.Version)) > 0); + _upgradeavailable = (Version.Parse(_package.Version).CompareTo(Version.Parse(Constants.Version)) > 0); } - if (!upgradeavailable) + else { - AddModuleMessage("Framework Is Up To Date", MessageType.Info); + _package = new Package { Name = Constants.PackageId, Version = Constants.Version }; } } diff --git a/Oqtane.Client/Program.cs b/Oqtane.Client/Program.cs index 9e4e1261..8c9b118a 100644 --- a/Oqtane.Client/Program.cs +++ b/Oqtane.Client/Program.cs @@ -52,6 +52,7 @@ namespace Oqtane.Client builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); + builder.Services.AddScoped(); // dynamically register module contexts and repository services Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); diff --git a/Oqtane.Client/Services/Interfaces/ISystemService.cs b/Oqtane.Client/Services/Interfaces/ISystemService.cs new file mode 100644 index 00000000..c450cdc7 --- /dev/null +++ b/Oqtane.Client/Services/Interfaces/ISystemService.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace Oqtane.Services +{ + public interface ISystemService + { + Task> GetSystemInfoAsync(); + } +} diff --git a/Oqtane.Client/Services/SystemService.cs b/Oqtane.Client/Services/SystemService.cs new file mode 100644 index 00000000..0823a79c --- /dev/null +++ b/Oqtane.Client/Services/SystemService.cs @@ -0,0 +1,32 @@ +using System.Net.Http; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Components; +using Oqtane.Shared; +using System.Collections.Generic; + +namespace Oqtane.Services +{ + public class SystemService : ServiceBase, ISystemService + { + + private readonly SiteState _siteState; + private readonly NavigationManager _navigationManager; + + public SystemService(HttpClient http, SiteState siteState, NavigationManager navigationManager) : base(http) + { + + _siteState = siteState; + _navigationManager = navigationManager; + } + + private string Apiurl + { + get { return CreateApiUrl(_siteState.Alias, _navigationManager.Uri, "System"); } + } + + public async Task> GetSystemInfoAsync() + { + return await GetJsonAsync>(Apiurl); + } + } +} diff --git a/Oqtane.Server/Controllers/SystemController.cs b/Oqtane.Server/Controllers/SystemController.cs new file mode 100644 index 00000000..bfd8d97a --- /dev/null +++ b/Oqtane.Server/Controllers/SystemController.cs @@ -0,0 +1,35 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Authorization; +using System.Collections.Generic; +using Oqtane.Shared; +using System; +using Microsoft.AspNetCore.Hosting; + +namespace Oqtane.Controllers +{ + [Route("{site}/api/[controller]")] + public class SystemController : Controller + { + private readonly IWebHostEnvironment _environment; + + public SystemController(IWebHostEnvironment environment) + { + _environment = environment; + } + + // GET: api/ + [HttpGet] + [Authorize(Roles = Constants.HostRole)] + public Dictionary Get() + { + Dictionary systeminfo = new Dictionary(); + systeminfo.Add("clrversion", Environment.Version.ToString()); + systeminfo.Add("osversion", Environment.OSVersion.ToString()); + systeminfo.Add("machinename", Environment.MachineName); + systeminfo.Add("serverpath", _environment.ContentRootPath); + systeminfo.Add("servertime", DateTime.Now.ToString()); + return systeminfo; + } + + } +} diff --git a/Oqtane.Server/Infrastructure/LogManager.cs b/Oqtane.Server/Infrastructure/LogManager.cs index a213cb10..b46bc8dc 100644 --- a/Oqtane.Server/Infrastructure/LogManager.cs +++ b/Oqtane.Server/Infrastructure/LogManager.cs @@ -75,7 +75,7 @@ namespace Oqtane.Infrastructure log.Url = $"{request.Scheme}://{request.Host}{request.Path}{request.QueryString}"; } - Type type = @class.GetType(); + Type type = Type.GetType(@class.ToString()); if (type != null) { log.Category = type.AssemblyQualifiedName; diff --git a/Oqtane.Server/Repository/ModuleDefinitionRepository.cs b/Oqtane.Server/Repository/ModuleDefinitionRepository.cs index bc91823a..4803ba9e 100644 --- a/Oqtane.Server/Repository/ModuleDefinitionRepository.cs +++ b/Oqtane.Server/Repository/ModuleDefinitionRepository.cs @@ -105,6 +105,10 @@ namespace Oqtane.Repository { moduledefinition.Categories = moduledef.Categories; } + if (!string.IsNullOrEmpty(moduledef.Version)) + { + moduledefinition.Version = moduledef.Version; + } if (permissions.Count == 0) { _permissions.UpdatePermissions(siteId, EntityNames.ModuleDefinition, moduledef.ModuleDefinitionId, moduledefinition.Permissions); @@ -173,23 +177,29 @@ namespace Oqtane.Repository .FirstOrDefault(item => item.GetInterfaces().Contains(typeof(IModule))); if (moduletype != null) { + // get property values from IModule var moduleobject = Activator.CreateInstance(moduletype); moduledefinition = (ModuleDefinition)moduletype.GetProperty("ModuleDefinition").GetValue(moduleobject); } else { + // set default property values moduledefinition = new ModuleDefinition { Name = moduleType.Substring(moduleType.LastIndexOf(".") + 1), Description = "Manage " + moduleType.Substring(moduleType.LastIndexOf(".") + 1), Categories = ((qualifiedModuleType.StartsWith("Oqtane.Modules.Admin.")) ? "Admin" : ""), - Version = new Version(1, 0, 0).ToString() + Version = "1.0.0" }; } // set internal properties moduledefinition.ModuleDefinitionName = qualifiedModuleType; moduledefinition.ControlTypeTemplate = moduleType + "." + Constants.ActionToken + ", " + typename[1]; moduledefinition.AssemblyName = assembly.FullName.Split(",")[0]; + if (assembly.FullName.StartsWith("Oqtane.Client")) + { + moduledefinition.Version = Constants.Version; + } if (string.IsNullOrEmpty(moduledefinition.Categories)) { moduledefinition.Categories = "Common"; diff --git a/Oqtane.Server/Repository/SiteRepository.cs b/Oqtane.Server/Repository/SiteRepository.cs index 4cba5e20..c726ccc7 100644 --- a/Oqtane.Server/Repository/SiteRepository.cs +++ b/Oqtane.Server/Repository/SiteRepository.cs @@ -388,6 +388,34 @@ namespace Oqtane.Repository } }); pageTemplates.Add(new PageTemplate + { + Name = "System Info", + Parent = "Admin", + Path = "admin/system", + Icon = "medical-cross", + IsNavigation = false, + IsPersonalizable = false, + EditMode = true, + PagePermissions = new List + { + new Permission(PermissionNames.View, Constants.AdminRole, true), + new Permission(PermissionNames.Edit, Constants.AdminRole, true) + }.EncodePermissions(), + PageTemplateModules = new List + { + new PageTemplateModule + { + ModuleDefinitionName = typeof(Oqtane.Modules.Admin.SystemInfo.Index).ToModuleDefinitionName(), Title = "System Info", Pane = "Content", + ModulePermissions = new List + { + new Permission(PermissionNames.View, Constants.AdminRole, true), + new Permission(PermissionNames.Edit, Constants.AdminRole, true) + }.EncodePermissions(), + Content = "" + } + } + }); + pageTemplates.Add(new PageTemplate { Name = "Upgrade Service", Parent = "Admin", Path = "admin/upgrade", Icon = Icons.Aperture, IsNavigation = false, IsPersonalizable = false, EditMode = true, PagePermissions = new List diff --git a/Oqtane.Server/Scripts/Master.00.00.00.sql b/Oqtane.Server/Scripts/Master.00.00.00.sql index 5dcf652e..0b10fb01 100644 --- a/Oqtane.Server/Scripts/Master.00.00.00.sql +++ b/Oqtane.Server/Scripts/Master.00.00.00.sql @@ -43,6 +43,7 @@ CREATE TABLE [dbo].[ModuleDefinition]( [Name] [nvarchar](200) NULL, [Description] [nvarchar](2000) NULL, [Categories] [nvarchar](200) NULL, + [Version] [nvarchar](50) NULL, [CreatedBy] [nvarchar](256) NOT NULL, [CreatedOn] [datetime] NOT NULL, [ModifiedBy] [nvarchar](256) NOT NULL, diff --git a/Oqtane.Server/Startup.cs b/Oqtane.Server/Startup.cs index 917632b6..52599d6e 100644 --- a/Oqtane.Server/Startup.cs +++ b/Oqtane.Server/Startup.cs @@ -102,6 +102,7 @@ namespace Oqtane services.AddScoped(); services.AddScoped(); services.AddScoped(); + services.AddScoped(); services.AddSingleton(); diff --git a/Oqtane.Shared/Models/ModuleDefinition.cs b/Oqtane.Shared/Models/ModuleDefinition.cs index 0bc66da1..82836f0c 100644 --- a/Oqtane.Shared/Models/ModuleDefinition.cs +++ b/Oqtane.Shared/Models/ModuleDefinition.cs @@ -27,6 +27,7 @@ namespace Oqtane.Models public string Name { get; set; } public string Description { get; set; } public string Categories { get; set; } + public string Version { get; set; } public string CreatedBy { get; set; } public DateTime CreatedOn { get; set; } @@ -36,8 +37,6 @@ namespace Oqtane.Models [NotMapped] public int SiteId { get; set; } [NotMapped] - public string Version { get; set; } - [NotMapped] public string Owner { get; set; } [NotMapped] public string Url { get; set; }